1.消息通知
2.健康银行:积分管理、员工打卡监测、积分兑换记录
This commit is contained in:
2026-02-06 18:03:53 +08:00
parent ae3a3bcab6
commit a416e9d7df
16 changed files with 1413 additions and 6 deletions
@@ -18,14 +18,14 @@
/>
</template>
<script setup lang="ts">
import { nextTick, onMounted, ref, watch } from 'vue';
import { onMounted, ref, watch } from 'vue';
import { isFunction } from '/@/utils/is';
import { queryDepartTreeSync } from '/@/views/system/depart/depart.api';
const props = defineProps({
api: {
type: Function as PropType<(args?: any) => Promise<any>>,
default: null,
default: queryDepartTreeSync,
},
apiParams: {
type: Object,
@@ -37,7 +37,7 @@
},
loadApi: {
type: Function as PropType<(args?: any) => Promise<any>>,
default: null,
default: queryDepartTreeSync,
},
loadApiParams: {
type: Object,
@@ -99,12 +99,16 @@
type: String,
default: () => '',
},
isHaveFLevel: {
type: Boolean,
default: () => false,
},
});
const emit = defineEmits(['change', 'update:change']);
const value = ref();
const treeData = ref([]);
const treeData = ref<any[]>([]);
onMounted(() => {
if (props.apiParams) {
@@ -145,7 +149,31 @@
result = props.afterApi(result) || result;
}
treeData.value = result;
if (props.isHaveFLevel) {
treeData.value = fResult.map((item: any) => {
item['preTitle'] = item['title'];
item['resultItem'] = JSON.stringify({
record: item.title,
scopeId: item.orgCode,
type: 1,
});
item['key'] = item[props.fieldNamesInfo.key];
return item;
});
console.log(treeData.value);
treeData.value[0]['children'] = result.map((item: any) => {
item['resultItem'] = JSON.stringify({
record: item.title,
scopeId: item.orgCode,
type: 1,
});
item['key'] = item[props.fieldNamesInfo.key];
return item;
});
} else {
treeData.value = result;
}
if (props.selectedKeys.length > 0) {
try {
await getChildren(treeData.value, props.selectedKeys);
@@ -163,7 +191,15 @@
result = props.afterApi(result) || result;
}
treeData.value = result;
treeData.value = result.map((item: any) => {
item['resultItem'] = JSON.stringify({
record: item.title,
scopeId: item.orgCode,
type: 1,
});
item['key'] = item[props.fieldNamesInfo.key];
return item;
});
if (props.selectedKeys.length > 0) {
try {
await getChildren(treeData.value, props.selectedKeys);
@@ -0,0 +1,170 @@
import { BasicColumn, FormSchema } from '/@/components/Table';
import { orgSearchInfo } from '/@/utils/orgSearchInfo';
export const columns: BasicColumn[] = [
{
title: '健康分类',
dataIndex: 'a',
},
{
title: '健康行为',
dataIndex: 'b',
},
{
title: '行为周期',
dataIndex: 'c',
},
{
title: '奖励积分',
dataIndex: 'd',
},
{
title: '状态',
dataIndex: 'd',
},
];
export const searchFormSchema: FormSchema[] = [
{
label: '员工姓名',
field: 'a',
component: 'Input',
},
{
label: '员工编号',
field: 'b',
component: 'Select',
componentProps: () => ({
options: [
{
label: '日常健康行为',
value: '日常健康行为',
},
{
label: '进阶健康行为',
value: '进阶健康行为',
},
{
label: '健康监测达标',
value: '健康监测达标',
},
],
}),
},
...orgSearchInfo({ orgName: '所属单位', deptName: '所属部门' }),
{
label: '健康行为',
field: 'f',
component: 'Input',
},
{
label: '打卡日期',
field: 'date',
component: 'RangeDate',
componentProps: () => ({
valueFormat: 'YYYY-MM-DD',
format: 'YYYY-MM-DD',
}),
},
];
export const schemas: FormSchema[] = [
{
label: '健康图标',
field: 'a',
component: 'JImageUpload',
},
{
label: '健康分类',
field: 'b',
component: 'Select',
componentProps: () => ({
options: [
{
label: '日常健康行为',
value: '日常健康行为',
},
{
label: '进阶健康行为',
value: '进阶健康行为',
},
{
label: '健康监测达标',
value: '健康监测达标',
},
],
}),
required: true,
},
{
label: '健康行为描述',
field: 'f',
component: 'Input',
required: true,
},
{
label: '行为周期',
field: 'c',
component: 'RadioGroup',
defaultValue: '日',
componentProps: () => ({
options: [
{
label: '次',
value: '次',
},
{
label: '日',
value: '日',
},
{
label: '周',
value: '周',
},
{
label: '月',
value: '月',
},
{
label: '季',
value: '季',
},
{
label: '年',
value: '年',
},
],
}),
required: true,
},
{
label: '奖励积分',
field: 'd',
component: 'InputNumber',
componentProps: () => ({
style: {
width: '100%',
},
}),
required: true,
},
{
label: '状态',
field: 'e',
component: 'RadioGroup',
defaultValue: '启用',
componentProps: () => ({
options: [
{
label: '启用',
value: '启用',
},
{
label: '停用',
value: '停用',
},
],
}),
required: true,
},
];
@@ -0,0 +1,73 @@
<template>
<BasicTable @register="registerTable" :row-selection="selectedRows">
<template #tableTitle>
<div>
<div style="font-size: 16px; font-weight: bold"> 打卡监测 </div>
<div class="button-d">
<a-button type="primary">导出</a-button>
<a-button type="primary">导出记录</a-button>
</div>
</div>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
</BasicTable>
</template>
<script setup lang="ts">
import { BasicTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { listApi } from '/@/views/emergency/aed/devices/deviceList.api';
import { columns, searchFormSchema } from '/@/views/banner/empMonitor/empMonitor.data';
//注册table数据
const { tableContext } = useListPage({
tableProps: {
api: listApi,
columns,
canResize: false,
formConfig: {
schemas: searchFormSchema,
autoSubmitOnEnter: true,
showAdvancedButton: false,
fieldMapToNumber: [],
fieldMapToTime: [['date', ['startDate', 'endDate']]],
},
actionColumn: {
width: 120,
fixed: 'right',
},
},
});
const [registerTable, {}, { selectedRows }] = tableContext;
function getTableAction(record: Recordable) {
return [
{
label: '打卡明细',
onclick: detail.bind(null, record),
},
{
label: '调整积分',
onclick: adjust.bind(null, record),
},
];
}
function detail(record: Recordable) {
console.log(record);
}
function adjust(record: Recordable) {
console.log(record);
}
</script>
<style scoped lang="less">
.button-d {
button {
margin: 5px 10px 0 0;
}
}
</style>
@@ -0,0 +1,7 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
pageList = '/health-bank/bank/userPoints/pageList',
}
export const listApi = (params: any) => defHttp.post({ url: Api.pageList, params });
@@ -0,0 +1,73 @@
import { BasicColumn, FormSchema } from '/@/components/Table';
import { orgSearchInfo } from '/@/utils/orgSearchInfo';
export const columns: BasicColumn[] = [
{
title: '所属单位',
dataIndex: 'deptName',
},
{
title: '所属部门',
dataIndex: 'orgName',
},
{
title: '员工姓名',
dataIndex: 'realName',
width: 130,
},
{
title: '员工编号',
dataIndex: 'workNo',
width: 120,
},
{
title: '性别',
dataIndex: 'sexName',
width: 70,
},
{
title: '年龄',
dataIndex: 'age',
width: 70,
},
{
title: '当前可用积分',
dataIndex: 'points',
width: 130,
sorter: true,
},
{
title: '累计获得积分',
dataIndex: 'addPointsSum',
width: 130,
sorter: true,
},
{
title: '累计兑换积分',
dataIndex: 'exchangePointsSum',
width: 130,
sorter: true,
customRender: ({ text }) => {
return text || 0;
},
},
{
title: '最后一次打卡时间',
dataIndex: 'lastAddDate',
width: 160,
},
];
export const searchFormSchema: FormSchema[] = [
{
label: '员工姓名',
field: 'realName',
component: 'Input',
},
{
label: '员工编号',
field: 'workNo',
component: 'Input',
},
...orgSearchInfo({ orgName: '所属单位', deptName: '所属部门' }),
];
@@ -0,0 +1,108 @@
<template>
<BasicTable @register="registerTable" :row-selection="selectedRows" @change="changeTables">
<template #tableTitle>
<div>
<div class="button-d">
<a-button type="primary">导出</a-button>
<a-button type="primary">导出记录</a-button>
</div>
</div>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
</BasicTable>
</template>
<script setup lang="ts">
import { BasicTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { columns, searchFormSchema } from '/@/views/banner/empPoints/empPoints.data';
import { listApi } from '/@/views/banner/empPoints/empPoints.api';
import { ref } from 'vue';
const orders = ref({
column: '',
order: '',
});
//注册table数据
const { tableContext } = useListPage({
tableProps: {
api: listApi,
columns,
canResize: false,
beforeFetch: (params) => {
params = { ...params, ...orders.value };
return params;
},
formConfig: {
schemas: searchFormSchema,
autoSubmitOnEnter: true,
showAdvancedButton: false,
fieldMapToNumber: [],
fieldMapToTime: [],
},
actionColumn: {
width: 150,
fixed: 'right',
},
},
});
const [registerTable, { getForm, reload }, { selectedRows }] = tableContext;
function getTableAction(record: Recordable) {
return [
{
label: '打卡明细',
onclick: detail.bind(null, record),
},
{
label: '调整积分',
onclick: adjust.bind(null, record),
},
];
}
function detail(record: Recordable) {
console.log(record);
}
function adjust(record: Recordable) {
console.log(record);
}
function changeTables(pagination, filters, sorter, {}) {
console.log(pagination);
const label = sorter.columnKey;
let column = '';
let asc = '';
switch (label) {
case 'points':
column = sorter.order ? 'points' : '';
asc = sorter.order ? (sorter.order == 'ascend' ? 'asc' : 'desc') : '';
break;
case 'addPointsSum':
column = sorter.order ? 'addPointsSum' : '';
asc = sorter.order ? (sorter.order == 'ascend' ? 'asc' : 'desc') : '';
break;
case 'exchangePointsSum':
column = sorter.order ? 'exchangePointsSum' : '';
asc = sorter.order ? (sorter.order == 'ascend' ? 'asc' : 'desc') : '';
break;
}
orders.value = {
column,
asc,
};
reload();
}
</script>
<style scoped lang="less">
.button-d {
button {
margin: 5px 10px 0 0;
}
}
</style>
@@ -0,0 +1,55 @@
<template>
<BasicModal @register="registerModal" title="发布通知" width="50%" @ok="handleSubmit">
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script setup lang="ts">
import BasicModal from '/@/components/Modal/src/BasicModal.vue';
import { useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form';
import { schemas } from '/@/views/banner/points/pointsList.data';
import { ref } from 'vue';
import { editApi, addApi } from '/@/views/banner/points/pointsList.api';
const isUpdate = ref(false);
const emit = defineEmits(['ok']);
const [registerForm, { setFieldsValue, getFieldsValue, updateSchema, resetFields, clearValidate, validate }] = useForm({
schemas,
showActionButtonGroup: false,
labelWidth: 120,
});
const [registerModal, { setModalProps, closeModal }] = useModalInner((data) => {
setModalProps({ confirmLoading: false });
updateSchema({
field: 'status',
show: !data?.isUpdate,
});
isUpdate.value = data?.isUpdate;
resetFields();
if (data?.isUpdate) {
setFieldsValue(data);
clearValidate();
}
});
async function handleSubmit() {
try {
const values = await validate();
setModalProps({ confirmLoading: true });
if (isUpdate.value) {
await editApi(values);
} else {
await addApi(values);
}
setModalProps({ confirmLoading: false });
emit('ok');
closeModal();
} catch (error) {
console.error(error);
setModalProps({ confirmLoading: false });
}
}
</script>
<style scoped lang="less"></style>
+47
View File
@@ -0,0 +1,47 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm } = useMessage();
enum Api {
pageList = '/health-bank/bank/pointsRule/pageList',
add = '/health-bank/bank/pointsRule/add',
edit = '/health-bank/bank/pointsRule/edit',
editStatus = '/health-bank/bank/pointsRule/editStatus',
delete = '/health-bank/bank/pointsRule/delete',
deleteBatch = '/health-bank/bank/pointsRule/deleteBatch',
}
export const listApi = (params: any) => defHttp.post({ url: Api.pageList, params });
export const addApi = (params: any) => defHttp.post({ url: Api.add, params });
export const editApi = (params: any) => defHttp.post({ url: Api.edit, params });
export const editStatusApi = (params: any) => defHttp.get({ url: Api.editStatus, params });
export const deleteApi = (params: any, callBack: any) => {
createConfirm({
iconType: 'warning',
title: '删除',
content: '确定要删除吗?',
onOk: async () => {
try {
await defHttp.get({ url: Api.delete, params });
callBack();
} catch (error) {
console.log(error);
}
},
});
};
export const deleteBatchApi = (params: any, callBack: any) => {
createConfirm({
iconType: 'warning',
title: '删除',
content: '确定要删除吗?',
onOk: async () => {
try {
await defHttp.get({ url: Api.deleteBatch, params });
callBack();
} catch (error) {
console.log(error);
}
},
});
};
+159
View File
@@ -0,0 +1,159 @@
import { BasicColumn, FormSchema } from '/@/components/Table';
const options: any[] = [
{
label: '次',
value: 1,
},
{
label: '日',
value: 2,
},
{
label: '周',
value: 3,
},
{
label: '月',
value: 4,
},
{
label: '季',
value: 5,
},
{
label: '年',
value: 6,
},
];
export const columns: BasicColumn[] = [
{
title: '健康分类',
dataIndex: 'ruleCategory_dictText',
},
{
title: '健康行为',
dataIndex: 'ruleDesc',
},
{
title: '行为周期',
dataIndex: 'frequency',
customRender: ({ text }) => {
return options.find((item) => item.value === text)?.label || '';
},
width: 120,
},
{
title: '奖励积分',
dataIndex: 'points',
width: 120,
},
{
title: '状态',
dataIndex: 'status',
width: 120,
},
];
export const searchFormSchema: FormSchema[] = [
{
label: '健康图标',
field: 'a',
component: 'Input',
},
{
label: '健康分类',
field: 'ruleCategory',
component: 'Select',
componentProps: () => ({
options: [
{
label: '日常健康行为',
value: '日常健康行为',
},
{
label: '进阶健康行为',
value: '进阶健康行为',
},
{
label: '健康监测达标',
value: '健康监测达标',
},
],
}),
},
{
label: '发布日期',
field: 'c',
component: 'RangeDate',
componentProps: () => ({
valueFormat: 'YYYY-MM-DD',
format: 'YYYY-MM-DD',
}),
},
];
export const schemas: FormSchema[] = [
{
label: '健康图标',
field: 'icon',
component: 'JImageUpload',
},
{
label: '健康分类',
field: 'ruleCategory',
component: 'JDictSelectTag',
componentProps: () => ({
dictCode: 'points_rule_category',
}),
required: true,
},
{
label: '健康行为描述',
field: 'ruleDesc',
component: 'Input',
required: true,
},
{
label: '行为周期',
field: 'frequency',
component: 'RadioGroup',
defaultValue: 2,
componentProps: () => ({
options,
}),
required: true,
},
{
label: '奖励积分',
field: 'points',
component: 'InputNumber',
componentProps: () => ({
style: {
width: '100%',
},
}),
required: true,
},
{
label: '状态',
field: 'status',
component: 'RadioGroup',
defaultValue: 1,
componentProps: () => ({
options: [
{
label: '启用',
value: 1,
},
{
label: '停用',
value: 2,
},
],
}),
required: true,
show: true,
},
];
+126
View File
@@ -0,0 +1,126 @@
<template>
<BasicTable @register="registerTable" :row-selection="rowSelection">
<template #tableTitle>
<div>
<div class="button-d">
<a-button type="primary" @click="() => openModal(true, { isUpdate: false })">新增</a-button>
<a-button type="primary">导出</a-button>
<a-button type="primary">导出记录</a-button>
<a-button type="danger" @click="deleteBatch">批量删除</a-button>
</div>
</div>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'status'">
<a-switch
v-model:checked="record!.status"
:checked-value="1"
:un-checked-value="2"
@change="changeSwitch(record)"
:loading="record!.switchLoading"
></a-switch>
</template>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
</BasicTable>
<points-modal @register="registerModal" @ok="reload" />
</template>
<script setup lang="ts">
import { BasicTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { columns, searchFormSchema } from '/@/views/banner/points/pointsList.data';
import { useModal } from '/@/components/Modal';
import PointsModal from '/@/views/banner/points/components/pointsModal.vue';
import { deleteApi, deleteBatchApi, editStatusApi, listApi } from '/@/views/banner/points/pointsList.api';
import { message } from 'ant-design-vue';
const [registerModal, { openModal }] = useModal();
//注册table数据
const { tableContext } = useListPage({
tableProps: {
api: listApi,
columns,
canResize: false,
afterFetch: (data: any) => {
return data.map((item) => {
item['switchLoading'] = false;
return item;
});
},
formConfig: {
schemas: searchFormSchema,
autoSubmitOnEnter: true,
showAdvancedButton: true,
fieldMapToNumber: [],
fieldMapToTime: [],
},
actionColumn: {
width: 120,
fixed: 'right',
},
},
});
const [registerTable, { reload }, { selectedRowKeys, rowSelection }] = tableContext;
function getTableAction(record: Recordable) {
return [
{
label: '编辑',
onclick: edit.bind(null, record),
},
{
label: '删除',
onclick: del.bind(null, record),
},
];
}
function edit(record: Recordable) {
openModal(true, {
isUpdate: true,
...record,
});
}
function del(record: Recordable) {
deleteApi({ id: record.id }, clearKey);
}
function deleteBatch() {
if (selectedRowKeys.value.length === 0) return message.warning('未选中任何数据');
deleteBatchApi({ ids: selectedRowKeys.value.join(',') }, clearKey);
}
function clearKey() {
selectedRowKeys.value = [];
reload();
}
async function changeSwitch(record: Recordable) {
record.status = record.status === 1 ? 2 : 1;
record.switchLoading = true;
try {
await editStatusApi({ id: record.id, status: record.status === 1 ? 2 : 1 });
record.status = record.status === 1 ? 2 : 1;
record.switchLoading = false;
} catch (error) {
console.error(error);
record.switchLoading = false;
}
}
</script>
<style scoped lang="less">
.button-d {
button {
margin: 5px 10px 0 0;
}
}
:deep(.ant-switch-checked) {
background: #00e166 !important;
}
</style>
@@ -0,0 +1,50 @@
<template>
<BasicModal @register="registerModal" title="通知详情" width="50%" :footer="null">
<div class="modal-d">
<div style="font-size: 16px; font-weight: bold">{{ dataInfo?.title }}</div>
<div style="display: flex; padding: 8px 0; font-weight: 500">
<div style="flex: 1">发布人{{ dataInfo?.createBy }}</div>
<div style="flex: 1">时间{{ dataInfo?.createTime }}</div>
</div>
<div style="border-bottom: 1px dashed; margin-bottom: 10px; padding: 0 0 10px; font-weight: 500; display: flex">
<div>通知范围</div>
<div style="flex: 1">
{{
dataInfo?.scopeType === 1
? dataInfo?.departScopeList && dataInfo?.departScopeList[0]?.record
: dataInfo?.userScopeList && dataInfo?.userScopeList.map((item: any) => item.record).join(',')
}}
</div>
</div>
<div class="information">
<div v-html="dataInfo.content"></div>
</div>
</div>
</BasicModal>
</template>
<script setup lang="ts">
import BasicModal from '/@/components/Modal/src/BasicModal.vue';
import { useModalInner } from '/@/components/Modal';
import { ref } from 'vue';
const dataInfo = ref({
information: '',
});
const [registerModal, {}] = useModalInner((data: any) => {
dataInfo.value = data;
});
</script>
<style scoped lang="less">
.modal-d {
max-height: 65vh;
display: flex;
flex-direction: column;
padding-left: 6px;
.information {
flex: 1;
overflow: auto;
}
}
</style>
@@ -0,0 +1,189 @@
<template>
<BasicModal @register="registerModal" title="发布通知" width="50%" @ok="handleSubmit">
<BasicForm @register="registerForm">
<template #scopeTypeSlot="{ model, field }">
<div style="margin-top: 5px">
<a-form-item-rest>
<a-radio-group v-model:value="model[field]">
<a-radio :value="1">指定机构</a-radio>
<a-radio :value="2">指定员工</a-radio>
</a-radio-group>
</a-form-item-rest>
</div>
<div class="input-d">
<template v-if="model[field] === 1">
<div>选择机构</div>
<jlazy-tree-select
:isHaveFLevel="true"
:multiple="false"
:fieldNamesInfo="{ key: 'resultItem', label: 'title', value: 'resultItem' }"
treeNodeFilterProp="title"
:api-params="{ primaryKey: 'orgCode', ids: userInfo.orgCode }"
v-model:value="scopeDept"
/>
</template>
<template v-else>
<div>指定员工</div>
<a-input v-model:value="model['userScopeListRecord']" readonly placeholder="请选择员工" @click="openPeople" />
</template>
</div>
</template>
</BasicForm>
<choose-some
ref="chooseSomeRef"
:width="800"
@register="registerUserDrawer"
@select-some="onSelectUserOk"
selection-type="checkbox"
title="选择用户"
:tableprops="auditorTableProps"
/>
</BasicModal>
</template>
<script setup lang="ts">
import BasicModal from '/@/components/Modal/src/BasicModal.vue';
import { useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form';
import { schemas, auditorColumns, auditorSchema } from '/@/views/system/noticeList/noticeList.data';
import JlazyTreeSelect from '/@/components/Form/src/jeecg/components/JlazyTreeSelect.vue';
import ChooseSome from '/@/views/compoents/chooseSome/index.vue';
import { useDrawer } from '/@/components/Drawer';
import { ref } from 'vue';
import { addApi, scopeUserListApi } from '/@/views/system/noticeList/noticeList.api';
import { useUserStore } from '/@/store/modules/user';
import { message } from 'ant-design-vue';
const userInfo = useUserStore().getUserInfo;
const [registerUserDrawer, { openDrawer }] = useDrawer();
const chooseSomeRef = ref();
const emit = defineEmits(['ok']);
const scopeDept = ref<any>();
const expandedRowKeys = ref<any[]>([]);
const auditorTableProps = ref<object>({
tableProps: {
// title: '一线医疗点医药管理',
api: scopeUserListApi,
columns: auditorColumns,
canResize: false,
clearSelectOnPageChange: false,
beforeFetch: (params: any) => {
params['permissions'] = false;
return params;
},
rowKey: (record: Recordable) => {
return JSON.stringify({
realName: record.realName,
userId: record.userId,
});
},
formConfig: {
labelWidth: 100,
schemas: auditorSchema,
autoSubmitOnEnter: true,
showAdvancedButton: false,
fieldMapToNumber: [],
fieldMapToTime: [],
submitFunc: () => {
chooseSomeRef.value.reL();
},
resetFunc: () => {
chooseSomeRef.value.reL();
},
baseColProps: {
xs: 8,
sm: 8,
md: 8,
lg: 8,
xl: 12,
xxl: 12,
},
actionColOptions: {
span: 24,
offset: 0,
style: {
paddingLeft: '104px',
},
xs: 8,
sm: 8,
md: 8,
lg: 8,
xl: 12,
xxl: 12,
},
},
showActionColumn: false,
},
});
const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({
schemas,
showActionButtonGroup: false,
labelWidth: 120,
});
const [registerModal, { setModalProps, closeModal }] = useModalInner(() => {
setModalProps({ confirmLoading: false });
resetFields();
});
function onSelectUserOk(e: any) {
expandedRowKeys.value = e;
setFieldsValue({
userScopeListRecord: expandedRowKeys.value
.map((item) => {
return JSON.parse(item)['realName'];
})
.join(','),
});
}
function openPeople() {
openDrawer(true, {
selectedRowKeys: expandedRowKeys.value,
});
}
async function handleSubmit() {
try {
const values = await validate();
if (!scopeDept.value && values.scopeType === 1) return message.error('请选择机构');
if (expandedRowKeys.value.length === 0 && values.scopeType === 2) return message.error('请指定员工');
if (values.scopeType === 1) {
values['departScopeList'] = [JSON.parse(scopeDept.value)];
} else {
values['userScopeList'] = expandedRowKeys.value.map((item) => {
return {
id: JSON.parse(item).userId,
record: JSON.parse(item).realName,
};
});
}
setModalProps({ confirmLoading: true });
await addApi(values);
emit('ok');
closeModal();
setModalProps({ confirmLoading: false });
} catch (error) {
console.log(error);
setModalProps({ confirmLoading: false });
}
}
</script>
<style scoped lang="less">
.input-d {
display: flex;
align-items: center;
margin: 10px 0 -5px;
> div {
&:nth-child(1) {
width: 80px;
}
}
}
</style>
@@ -0,0 +1,49 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
import qs from 'qs';
const { createConfirm } = useMessage();
enum Api {
list = '/health-system/sys/message/notice/list',
scopeUserList = '/health-system/sys/user/scopeUserList',
add = '/health-system/sys/message/notice/add',
delete = '/health-system/sys/message/notice/delete',
deleteBatch = '/health-system/sys/message/notice/deleteBatch',
}
export const listApi = (params: any) => defHttp.get({ url: Api.list, params });
export const scopeUserListApi = (params: any) => defHttp.get({ url: Api.scopeUserList, params });
export const addApi = (params: any) => defHttp.post({ url: Api.add, params });
export const deleteApi = (params: any, callBack: any) => {
createConfirm({
iconType: 'warning',
title: '删除',
content: '确定要删除吗?',
onOk: async () => {
try {
await defHttp.delete({ url: Api.delete + '?' + qs.stringify(params), params });
callBack();
} catch (error) {
console.log(error);
}
},
});
};
export const deleteBatchApi = (params: any, callBack: any) => {
createConfirm({
iconType: 'warning',
title: '删除',
content: '确定要删除吗?',
onOk: async () => {
try {
await defHttp.delete({ url: Api.deleteBatch + '?' + qs.stringify(params), params });
callBack();
} catch (error) {
console.log(error);
}
},
});
};
@@ -0,0 +1,172 @@
import { BasicColumn, FormSchema } from '/@/components/Table';
export const columns: BasicColumn[] = [
{
title: '通知标题',
dataIndex: 'title',
},
{
title: '通知范围',
dataIndex: 'scopeType',
customRender: ({ text }) => {
switch (text) {
case 1:
return '指定部门';
case 2:
return '指定员工';
case 3:
return '即指定部门又指定员工';
default:
return '-';
}
},
width: 120,
},
{
title: '发布时间',
dataIndex: 'createTime',
width: 150,
},
{
title: '操作人',
dataIndex: 'createBy',
width: 150,
},
];
export const searchFormSchema: FormSchema[] = [
{
label: '通知标题',
field: 'title',
component: 'Input',
},
{
label: '通知范围',
field: 'scopeType',
component: 'Select',
componentProps: () => ({
options: [
{
label: '指定机构',
value: 1,
},
{
label: '指定员工',
value: 2,
},
],
}),
},
{
label: '发布日期',
field: 'date',
component: 'RangeDate',
componentProps: () => ({
valueFormat: 'YYYY-MM-DD',
format: 'YYYY-MM-DD',
}),
},
];
export const schemas: FormSchema[] = [
{
label: '通知标题',
field: 'title',
component: 'Input',
required: true,
},
{
label: '通知范围',
field: 'scopeType',
component: 'RadioGroup',
defaultValue: 1,
componentProps: () => ({
options: [
{
label: '指定机构',
value: 1,
},
{
label: '指定员工',
value: 2,
},
],
}),
slot: 'scopeTypeSlot',
required: true,
},
{
label: '机构',
field: 'departScopeList',
component: 'Input',
show: false,
},
{
label: '员工',
field: 'userScopeList',
component: 'Input',
show: false,
},
{
label: '员工',
field: 'userScopeListRecord',
component: 'Input',
show: false,
},
{
label: '通知内容',
field: 'content',
component: 'JEditor',
required: true,
},
{
label: '',
field: 'id',
component: 'Input',
show: false,
},
];
export const auditorColumns: BasicColumn[] = [
{
title: '单位名称',
align: 'center',
dataIndex: 'orgName',
},
{
title: '部门名称',
align: 'center',
dataIndex: 'departName',
},
{
title: '员工姓名',
align: 'center',
dataIndex: 'realName',
},
{
title: '员工工号',
align: 'center',
dataIndex: 'workNo',
},
];
export const auditorSchema: FormSchema[] = [
{
label: '单位',
field: 'orgCode',
component: 'JlazyTreeSelect',
componentProps: () => ({
isHaveFLevel: true,
multiple: false,
}),
},
{
label: '员工姓名',
field: 'realName',
component: 'Input',
},
{
label: '员工工号',
field: 'workNo',
component: 'Input',
},
];
@@ -0,0 +1,93 @@
<template>
<BasicTable @register="registerTable" :row-selection="rowSelection">
<template #tableTitle>
<div>
<div style="font-size: 16px; font-weight: bold"> 公告通知列表 </div>
<div class="button-d">
<a-button type="primary" @click="() => openModal(true, {})">新增</a-button>
<a-button type="primary">导出</a-button>
<a-button type="primary">导出记录</a-button>
<a-button type="danger" @click="deleteBatch">批量删除</a-button>
</div>
</div>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
</BasicTable>
<notice-modal @register="registerModal" @ok="reload" />
<notice-detail-modal @register="registerDetailModal" />
</template>
<script setup lang="ts">
import { BasicTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { deleteApi, listApi, deleteBatchApi } from '/@/views/system/noticeList/noticeList.api';
import { columns, searchFormSchema } from '/@/views/system/noticeList/noticeList.data';
import NoticeModal from '/@/views/system/noticeList/components/noticeModal.vue';
import { useModal } from '/@/components/Modal';
import NoticeDetailModal from '/@/views/system/noticeList/components/noticeDetailModal.vue';
import { message } from 'ant-design-vue';
const [registerModal, { openModal }] = useModal();
const [registerDetailModal, { openModal: openDetailModal }] = useModal();
//注册table数据
const { tableContext } = useListPage({
tableProps: {
api: listApi,
columns,
canResize: false,
formConfig: {
schemas: searchFormSchema,
autoSubmitOnEnter: true,
showAdvancedButton: true,
fieldMapToNumber: [],
fieldMapToTime: [['date', ['startDate', 'endDate']]],
},
actionColumn: {
width: 120,
fixed: 'right',
},
},
});
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
function getTableAction(record: Recordable) {
return [
{
label: '详情',
onclick: detail.bind(null, record),
},
{
label: '删除',
onclick: del.bind(null, record),
},
];
}
function detail(record: Recordable) {
openDetailModal(true, record);
}
function del(record: Recordable) {
deleteApi({ id: record.id }, clearKeys);
}
function deleteBatch() {
if (selectedRowKeys.value.length === 0) return message.warning('未选中任何数据');
deleteBatchApi({ ids: selectedRowKeys.value.join(',') }, clearKeys);
}
function clearKeys() {
selectedRowKeys.value = [];
reload();
}
</script>
<style scoped lang="less">
.button-d {
button {
margin: 5px 10px 0 0;
}
}
</style>