init
This commit is contained in:
2025-06-27 17:42:38 +08:00
commit bd6402478b
5317 changed files with 785994 additions and 0 deletions
@@ -0,0 +1,71 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm } = useMessage();
enum Api {
list = '/health-emergency/emergency/orderSendRecord/list',
save = '/health-emergency/emergency/orderSendRecord/add',
edit = '/health-emergency/emergency/orderSendRecord/edit',
deleteOne = '/health-emergency/emergency/orderSendRecord/delete',
deleteBatch = '/health-emergency/emergency/orderSendRecord/deleteBatch',
importExcel = '/health-emergency/emergency/orderSendRecord/importExcel',
exportXls = '/health-emergency/emergency/orderSendRecord/exportXls',
queryById = '/emergency/orderSendRecord/queryById',
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
export const queryByIdUrl = Api.queryById;
/**
* 导入api
*/
export const getImportUrl = Api.importExcel;
/**
* 列表接口
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
* 删除单个
*/
export const deleteOne = (params, handleSuccess) => {
return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
};
/**
* 批量删除
* @param params
*/
export const batchDelete = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
},
});
};
/**
* 保存或者更新
* @param params
*/
export const saveOrUpdate = (params, isUpdate) => {
const url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params });
};
@@ -0,0 +1,184 @@
import { BasicColumn, FormSchema } from '/@/components/Table';
import { render } from '/@/utils/common/renderUtils';
// 列表数据
export const columns: BasicColumn[] = [
{
title: '驻场人员',
align: 'center',
dataIndex: 'stationUserName',
},
// {
// title: '驻场人员部门',
// align: 'center',
// dataIndex: 'stationUserDepart',
// },
{
title: '是否接单',
align: 'center',
dataIndex: 'accept',
customRender: ({ text }) => {
return render.renderDict(text, 'emergency_order_send_accept');
},
},
{
title: '派单医院',
align: 'center',
dataIndex: 'sendOrderHospital',
},
{
title: '驻场人员派单业务',
align: 'center',
dataIndex: 'stationBusiness_dictText',
// 字典:emergency_send_order_type
},
{
title: '处理时间',
align: 'center',
dataIndex: 'transferOrderTime',
customRender: ({ text }) => {
return !text ? '' : text.length > 10 ? text.substr(0, 10) : text;
},
},
// {
// title: '状态(1-正常,2-冻结)',
// align:"center",
// dataIndex: 'status'
// },
// {
// title: '删除状态(0-正常,1-已删除)',
// align:"center",
// dataIndex: 'delFlag'
// },
// {
// title: '备注',
// align:"center",
// dataIndex: 'memo'
// },
];
// 查询数据
export const searchFormSchema: FormSchema[] = [
{
label: '驻场人员',
field: 'stationUserName',
component: 'Input',
},
{
label: '是否接单',
field: 'accept',
component: 'Select',
componentProps: {
options: [
{
value: null,
label: '请选择...',
},
{
value: 0,
label: '否',
},
{
value: 1,
label: '是',
},
],
},
},
];
// 表单数据
export const formSchema: FormSchema[] = [
{
label: '驻场人员',
field: 'stationUserName',
component: 'Input',
},
// {
// field: 'stationUserSex',
// component: 'JDictSelectTag',
// label: '性别',
// componentProps: {
// dictCode: 'sex',
// type: 'radioButton',
// },
// },
{
// label: '驻场人员部门:二级-三级(使用,隔开)',
label: '驻场人员部门',
field: 'stationUserDepart',
component: 'Input',
},
{
label: '是否接单',
field: 'accept',
component: 'RadioGroup',
componentProps: {
options: [
{
value: '0',
label: '否',
},
{
value: '1',
label: '是',
},
],
},
},
{
label: '派单医院',
field: 'sendOrderHospital',
component: 'Input',
},
{
label: '驻场人员派单业务',
field: 'stationBusiness_dictText',
component: 'Input',
},
{
label: '转单时间',
field: 'transferOrderTime',
component: 'DatePicker',
},
// {
// label: '状态(1-正常,2-冻结)',
// field: 'status',
// component: 'InputNumber',
// dynamicRules: ({model,schema}) => {
// return [
// { required: true, message: '请输入状态(1-正常,2-冻结)!'},
// ];
// },
// },
// {
// label: '删除状态(0-正常,1-已删除)',
// field: 'delFlag',
// component: 'InputNumber',
// dynamicRules: ({model,schema}) => {
// return [
// { required: true, message: '请输入删除状态(0-正常,1-已删除)!'},
// ];
// },
// },
// {
// label: '备注',
// field: 'memo',
// component: 'Input',
// },
// TODO 主键隐藏字段,目前写死为ID
{
label: '',
field: 'id',
component: 'Input',
show: false,
},
];
/**
* 流程表单调用这个方法获取formSchema
* @param _formData
*/
export function getBpmFormSchema(_formData): FormSchema[] {
// 默认和原始表单保持一致 如果流程中配置了权限数据,这里需要单独处理formSchema
return formSchema;
}
@@ -0,0 +1,111 @@
<template>
<div>
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="null">
<!--插槽:table标题-->
<template #tableTitle></template>
<!--操作栏-->
<!-- <template #action="{ record }">-->
<!-- <TableAction :actions="getTableAction(record)" />-->
<!-- </template>-->
</BasicTable>
<!-- 表单区域 -->
<OrderSendRecordModal @register="registerModal" @success="handleSuccess" />
</div>
</template>
<script lang="ts" name="emergency-orderSendRecord" setup>
import { BasicTable, TableAction } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
import { useListPage } from '/@/hooks/system/useListPage';
import OrderSendRecordModal from './components/OrderSendRecordModal.vue';
import { columns, searchFormSchema } from './OrderSendRecord.data';
import { list } from './OrderSendRecord.api';
const props = defineProps({
orderId: String,
});
//注册model
const [registerModal, { openModal }] = useModal();
//注册table数据
const { tableContext } = useListPage({
tableProps: {
title: 'emergency_order_send_record',
api: list,
columns,
canResize: false,
formConfig: {
//labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter: true,
showAdvancedButton: false,
fieldMapToNumber: [],
fieldMapToTime: [],
baseColProps: {
xs: 8, // <576px
sm: 8, // ≥576px
md: 8, // ≥768px
lg: 8, // ≥992px
xl: 8, // ≥1200px
xxl: 8, // ≥1600px
},
actionColOptions: {
offset: 0,
span: 8,
xs: 8,
sm: 8,
md: 8,
lg: 8,
xl: 8,
xxl: 8,
},
},
beforeFetch: (info) => {
info['stationUserName'] = info['stationUserName'] && `*${info['stationUserName']}*`;
info['orderId'] = props.orderId;
delete info['order'];
return info;
},
actionColumn: {
ifShow: false,
width: 120,
fixed: 'right',
},
},
});
const [registerTable, { reload }] = tableContext;
/**
* 详情
*/
function handleDetail(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: false,
});
}
/**
* 成功回调
*/
function handleSuccess() {
reload();
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
},
];
}
</script>
<style scoped></style>
@@ -0,0 +1,66 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="800" @ok="handleSubmit">
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, computed, unref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { formSchema } from '../OrderSendRecord.data';
import { saveOrUpdate } from '../OrderSendRecord.api';
// Emits声明
const emit = defineEmits(['register', 'success']);
const isUpdate = ref(true);
//表单配置
const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({
//labelWidth: 150,
schemas: formSchema,
showActionButtonGroup: false,
baseColProps: { span: 24 },
});
//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
//重置表单
await resetFields();
setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, showOkBtn: !!data?.showFooter });
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
//表单赋值
await setFieldsValue({
...data.record,
});
}
// 隐藏底部时禁用整个表单
await setProps({ disabled: !data?.showFooter });
});
//设置标题
const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
//表单提交事件
async function handleSubmit() {
try {
let values = await validate();
setModalProps({ confirmLoading: true });
//提交表单
await saveOrUpdate(values, isUpdate.value);
//关闭弹窗
closeModal();
//刷新列表
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>
<style lang="less" scoped>
/** 时间和数字输入框样式 */
:deep(.ant-input-number) {
width: 100%;
}
:deep(.ant-calendar-picker) {
width: 100%;
}
</style>
@@ -0,0 +1,136 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm } = useMessage();
enum Api {
list = '/health-emergency/emergency/scheduleCustom/list',
save = '/health-emergency/emergency/scheduleCustom/add',
edit = '/health-emergency/emergency/scheduleCustom/edit',
deleteOne = '/health-emergency/emergency/scheduleCustom/delete',
deleteBatch = '/health-emergency/emergency/scheduleCustom/deleteBatch',
importExcel = '/health-emergency/emergency/scheduleCustom/importExcel',
exportXls = '/health-emergency/emergency/scheduleCustom/exportXls',
queryById = '/emergency/scheduleCustom/queryById',
delCustom = '/health-emergency/emergency/scheduleCustom/delCustom',
updateScheduleCustom = '/health-emergency/emergency/scheduleCustom/updateScheduleCustom',
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
export const queryByIdUrl = Api.queryById;
/**
* 导入api
*/
export const getImportUrl = Api.importExcel;
/**
* 列表接口
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
* 删除单个
*/
export const deleteOne = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () =>
defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
}),
});
};
/**
* 批量删除
* @param params
*/
export const batchDelete = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
},
});
};
export const customDeleteOne = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除该数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.post({ url: Api.delCustom, data: params }).then(() => {
console.log('查询');
handleSuccess();
});
},
});
};
/**
* 保存或者更新
* @param params
*/
export const saveOrUpdate = (params, isUpdate) => {
const url = isUpdate ? Api.edit : Api.updateScheduleCustom;
return defHttp.post({ url: url, params });
};
/**
* 专业人员列表
* */
export const professional = () => {
const arr = [
{
label: '张1',
value: '张1111',
},
{
label: '张2',
value: '张2222',
},
{
label: '张3',
value: '张3333',
},
];
return new Promise((resolve) => resolve(arr));
};
/**
* 专业人员列表
* */
export const operator = () => {
const arr = [
{
label: '李1',
value: '李1111',
},
{
label: '李2',
value: '李2222',
},
{
label: '李3',
value: '李3333',
},
];
return new Promise((resolve) => resolve(arr));
};
@@ -0,0 +1,150 @@
import { BasicColumn } from '/@/components/Table';
import { FormSchema } from '/@/components/Table';
import { personType2 } from '/@/views/emergency/outburst/ScheduleCustom/ScheduleDefault.api';
import { getPhysicalHospitalsList } from '/@/views/system/user/user.api';
//列表数据
export const columns: BasicColumn[] = [
{
title: '排班时间',
align: 'center',
dataIndex: 'scheduleTime',
},
{
title: '姓名',
align: 'center',
dataIndex: 'userName',
},
{
title: '类型',
align: 'center',
dataIndex: 'userType',
customRender: ({ text }) => {
return text == '0' ? '操作人员' : text == '1' ? '专业人员' : '';
},
},
{
title: '时间',
align: 'center',
dataIndex: 'type',
customRender: ({ text }) => {
return text == '0' ? '上午' : text == '1' ? '下午' : '';
},
},
];
//查询数据
export const searchFormSchema: FormSchema[] = [
{
label: '姓名',
field: 'userName',
component: 'Input',
},
];
//表单数据
export const formSchema: FormSchema[] = [
{
label: '排班时间',
field: 'time',
component: 'DatePicker',
dynamicRules: () => {
return [{ required: true, message: '请输入排班时间!' }];
},
componentProps: {
getPopupContainer: () => document.body,
valueFormat: 'YYYY-MM-DD',
},
},
{
label: '班次',
field: 'type',
component: 'RadioGroup',
componentProps: {
options: [
{
value: '2',
label: '全天',
},
{
value: '0',
label: '上午',
},
{
value: '1',
label: '下午',
},
],
},
dynamicRules: () => {
return [{ required: true, message: '请选择班次' }];
},
},
{
label: '操作人员',
field: 'operators',
component: 'ApiSelect',
componentProps: (res) => {
return {
api: personType2,
params: { personType: 5 },
resultField: 'list',
labelField: 'realname',
valueField: 'id',
mode: 'multiple',
getPopupContainer: () => document.body,
showSearch: true,
filterOption: (input: string, option: any): boolean => {
const str: string = input.toLowerCase();
return option.label.toLowerCase().indexOf(str) >= 0;
},
};
},
required: true,
},
{
label: '专业人员',
field: 'majors',
component: 'ApiSelect',
componentProps: {
api: personType2,
params: { personType: 6 },
resultField: 'list',
labelField: 'realname',
valueField: 'id',
mode: 'multiple',
getPopupContainer: () => document.body,
showSearch: true,
filterOption: (input: string, option: any): boolean => {
const str: string = input.toLowerCase();
return option.label.toLowerCase().indexOf(str) >= 0;
},
},
required: true,
},
// {
// label: '性别',
// field: 'userSex',
// component: 'JDictSelectTag',
// componentProps: {
// dictCode: 'sex',
// type: 'radioButton',
// },
// },
// TODO 主键隐藏字段,目前写死为ID
{
label: '',
field: 'id',
component: 'Input',
show: false,
},
];
// };
/**
* 流程表单调用这个方法获取formSchema
* @param _formData
*/
export function getBpmFormSchema(_formData): FormSchema[] {
// 默认和原始表单保持一致 如果流程中配置了权限数据,这里需要单独处理formSchema
return formSchema;
}
@@ -0,0 +1,168 @@
<template>
<div>
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
<!-- <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button> -->
<!-- <j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button> -->
<a-dropdown v-if="selectedRowKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined" />
删除
</a-menu-item>
</a-menu>
</template>
<a-button
>批量操作
<Icon icon="mdi:chevron-down" />
</a-button>
</a-dropdown>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
</template>
<!--字段回显插槽-->
<template #htmlSlot="{ text }">
<div v-html="text"></div>
</template>
<!--省市区字段回显插槽-->
<template #pcaSlot="{ text }">
{{ getAreaTextByCode(text) }}
</template>
<template #fileSlot="{ text }">
<span v-if="!text" style="font-size: 12px; font-style: italic">无文件</span>
<a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)"
>下载</a-button
>
</template>
</BasicTable>
<!-- 表单区域 -->
<ScheduleCustomModal @register="registerModal" @success="handleSuccess" />
</div>
</template>
<script lang="ts" name="emergency-scheduleCustom" setup>
import { ref, computed, unref } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
import { useListPage } from '/@/hooks/system/useListPage';
import ScheduleCustomModal from './components/ScheduleCustomModal.vue';
import { columns, searchFormSchema } from './ScheduleCustom.data';
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './ScheduleCustom.api';
import { downloadFile } from '/@/utils/common/renderUtils';
const checkedKeys = ref<Array<string | number>>([]);
//注册model
const [registerModal, { openModal }] = useModal();
//注册table数据
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: 'emergency_schedule_custom',
api: list,
columns,
canResize: false,
formConfig: {
//labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter: true,
showAdvancedButton: true,
fieldMapToNumber: [],
fieldMapToTime: [],
},
actionColumn: {
width: 120,
fixed: 'right',
},
},
exportConfig: {
name: 'emergency_schedule_custom',
url: getExportUrl,
},
importConfig: {
url: getImportUrl,
success: handleSuccess,
},
});
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
/**
* 新增事件
*/
function handleAdd() {
openModal(true, {
isUpdate: false,
showFooter: true,
});
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: true,
});
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: false,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteOne({ id: record.id }, handleSuccess);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
await batchDelete({ ids: selectedRowKeys.value }, handleSuccess);
}
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
},
];
}
/**
* 下拉操作栏
*/
function getDropDownAction(record) {
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
},
{
label: '删除',
onClick: handleDelete.bind(null, record),
},
];
}
</script>
<style scoped></style>
@@ -0,0 +1,117 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
import { resolve } from 'path';
const { createConfirm } = useMessage();
enum Api {
list = '/health-emergency/emergency/scheduleDefault/list',
save = '/health-emergency/emergency/scheduleDefault/add',
edit = '/health-emergency/emergency/scheduleDefault/edit',
deleteOne = '/health-emergency/emergency/scheduleDefault/delete',
deleteBatch = '/health-emergency/emergency/scheduleDefault/deleteBatch',
importExcel = '/health-emergency/emergency/scheduleDefault/importExcel',
exportXls = '/health-emergency/emergency/scheduleDefault/exportXls',
queryById = '/emergency/scheduleDefault/queryById',
personType = '/sys/api/listUserByPersonType',
updateScheduleDefault = '/health-emergency/emergency/scheduleDefault/updateScheduleDefault', //修改排班人员
// customList = '/health-emergency/emergency/scheduleCustom/list',
customList = '/health-emergency/emergency/scheduleCustom/listCustom',
updateScheduleCustom = '/health-emergency/emergency/scheduleCustom/updateScheduleCustom',
scheduleRecord = '/health-emergency/emergency/scheduleRecord/listCustom',
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
export const queryByIdUrl = Api.queryById;
/**
* 导入api
*/
export const getImportUrl = Api.importExcel;
/**
* 列表接口
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
* @desc 操作 专业人员列表
* 5: 操作人员 6:专业人员
* */
export const personType = (params) => {
return new Promise((resolve) => {
defHttp.get({ url: Api.personType, params }).then((res) => {
resolve(res);
});
});
};
export const personType2 = async (params) => {
return await defHttp.get({ url: Api.personType, params });
};
export const updateScheduleDefault = (params) =>
defHttp.post({
url: Api.updateScheduleDefault,
params,
});
export const updateScheduleCustom = (params) =>
defHttp.post({
url: Api.updateScheduleCustom,
params,
});
/**
* 删除单个
*/
export const deleteOne = (params, handleSuccess) => {
return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
};
/**
* 批量删除
* @param params
*/
export const batchDelete = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp
.delete(
{
url: Api.deleteBatch,
data: params,
},
{ joinParamsToUrl: true }
)
.then(() => {
handleSuccess();
});
},
});
};
/**
* 保存或者更新
* @param params
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params });
};
//自定义排班
//1.获取列表
export const customList = (params) => defHttp.get({ url: Api.customList, params });
// 排班记录
export const scheduleRecord = (params) => defHttp.get({ url: Api.scheduleRecord, params });
@@ -0,0 +1,535 @@
import { BasicColumn } from '/@/components/Table';
import { FormSchema } from '/@/components/Table';
import { render } from '/@/utils/common/renderUtils';
import dayjs from 'dayjs';
function getWeek(text) {
return render.renderDict(text, 'week');
}
function getTime(text) {
return render.renderDict(text, 'am_pm');
}
function getUserType(text) {
return text == '0' ? '操作人员' : text == '1' ? '专业人员' : '';
}
/**
* @time1
* @time2
* @desc 第二个时间是否更大,
* */
export function compareDate(time1, time2) {
const time = dayjs(time1).valueOf();
const today = dayjs(time2).format('YYYY-MM-DD');
return time < dayjs(`${today}`).valueOf();
}
export const day = {
today: () => new Date(),
nextDay: () => {
const day = new Date();
return day.getTime() + 24 * 60 * 60 * 1000;
},
};
//列表数据
export const columns: BasicColumn[] = [
{
title: '姓名',
align: 'center',
dataIndex: 'userName',
},
{
title: '星期',
align: 'center',
dataIndex: 'week',
customRender: ({ text }) => {
return getWeek(text);
},
},
{
title: '时间',
align: 'center',
dataIndex: 'type',
customRender: ({ text }) => {
return getTime(text);
},
},
{
title: '人员类型',
align: 'center',
dataIndex: 'userType',
customRender: ({ text }) => {
return getUserType(text);
},
},
];
//查询数据
export const searchFormSchema: FormSchema[] = [
{
label: '星期',
field: 'week',
component: 'JDictSelectTag',
componentProps: {
dictCode: 'week',
},
},
];
//排班表格列表项
export const defaultColumns = [
{
title: '星期',
dataIndex: 'week_dictText',
key: 'week_dictText',
width: 80,
customCell: (_, index) => {
if (index % 2 === 0) {
return {
rowSpan: 2,
};
} else {
return {
rowSpan: 0,
};
}
},
},
{
title: '班次',
width: 80,
// dataIndex: 'type',
dataIndex: 'type_dictText',
// type_dictText
// customRender: ({ index }) => {
// return index % 2 == 0 ? '上午' : '下午';
// },
},
{
title: '值班人员',
children: [
{
title: '操作人员',
dataIndex: 'operations',
key: 'operations',
},
{
title: '专业人员',
dataIndex: 'majors',
key: 'majors',
},
],
},
{
title: '操作',
dataIndex: 'action',
key: 'action',
width: 80,
},
];
export const defaultColumnData = [
{
time: null,
week: 1,
week_dictText: '星期一',
detail: [
{
type: '0',
type_dictText: '上午',
operations: [],
majors: [],
},
{
type: '1',
type_dictText: '下午',
operations: [],
majors: [],
},
],
},
{
time: null,
week: 2,
week_dictText: '星期二',
detail: [
{
type: '0',
type_dictText: '上午',
operations: [],
majors: [],
},
{
type: '1',
type_dictText: '下午',
operations: [],
majors: [],
},
],
},
{
time: null,
week: 3,
week_dictText: '星期三',
detail: [
{
type: '0',
type_dictText: '上午',
operations: [],
majors: [],
},
{
type: '1',
type_dictText: '下午',
operations: [],
majors: [],
},
],
},
{
time: null,
week: 4,
week_dictText: '星期四',
detail: [
{
type: '0',
type_dictText: '上午',
operations: [],
majors: [],
},
{
type: '1',
type_dictText: '下午',
operations: [],
majors: [],
},
],
},
{
time: null,
week: 5,
week_dictText: '星期五',
detail: [
{
type: '0',
type_dictText: '上午',
operations: [],
majors: [],
},
{
type: '1',
type_dictText: '下午',
operations: [],
majors: [],
},
],
},
{
time: null,
week: 6,
week_dictText: '星期六',
detail: [
{
type: '0',
type_dictText: '上午',
operations: [],
majors: [],
},
{
type: '1',
type_dictText: '下午',
operations: [],
majors: [],
},
],
},
{
time: null,
week: 7,
week_dictText: '星期日',
detail: [
{
type: '0',
type_dictText: '上午',
operations: [],
majors: [],
},
{
type: '1',
type_dictText: '下午',
operations: [],
majors: [],
},
],
},
];
// 1.处理默认排班格式
export function dealObj(obj, index) {
return {
week: obj.week,
week_dictText: render.renderDict(obj.week, 'week').children,
operations: obj.detail[index]['operations'].map((val) => val.userName).join('、'),
majors: obj.detail[index]['majors'].map((val) => val.userName).join('、'),
type_dictText: obj.detail[index].type_dictText,
type: obj.detail[index].type,
};
}
// 2.处理自定义排班格式
export function dealCustomObj(obj, index) {
return {
time: obj.time,
operations: obj.detail[index]['operations'].map((val) => val.userName).join('、'),
majors: obj.detail[index]['majors'].map((val) => val.userName).join('、'),
type_dictText: obj.detail[index].type_dictText,
type: obj.detail[index].type,
majorsId: obj.detail[index]['majors'].map((val) => val.userId),
operationsId: obj.detail[index]['operations'].map((val) => val.userId),
};
}
/**
* @defaultData 接口数据
* @dealObj 返回格式
* @desc 处理排班返回数据格式
* */
export function dealResData(defaultData, dealObj) {
const res = [];
defaultData &&
defaultData.map((item) => {
const obj1 = dealObj(item, 0);
const obj2 = dealObj(item, 1);
res.push(obj1);
res.push(obj2);
});
return res;
}
// 自定义排班表单配置
export const customSearchForm: FormSchema[] = [
{
field: 'date',
component: 'DatePicker',
label: '排班时间',
colProps: {
span: 6,
},
componentProps: {
placeholder: '请选择排班时间',
valueFormat: 'YYYY-MM-DD',
},
},
{
field: 'amOrPm',
component: 'Select',
label: '排班班次',
colProps: {
span: 6,
},
componentProps: {
options: [
{
label: '上午',
value: '0',
},
{
label: '下午',
value: '1',
},
],
placeholder: '请选择班次',
},
},
];
//排班记录表格列表项
export const recordColumns = [
{
title: '排班时间',
dataIndex: 'time',
key: 'time',
width: 120,
customCell: (_, index) => {
if (index % 2 === 0) {
return {
rowSpan: 2,
};
} else {
return {
rowSpan: 0,
};
}
},
},
{
title: '班次',
width: 80,
dataIndex: 'type',
customRender: ({ text }) => text && render.renderDict(text, 'am_pm'),
},
{
title: '值班人员',
children: [
{
title: '操作人员',
dataIndex: 'operations',
key: 'operations',
},
{
title: '专业人员',
dataIndex: 'majors',
key: 'majors',
},
],
},
];
export const customColumns = [
{
title: '排班时间',
dataIndex: 'time',
key: 'time',
width: 120,
customCell: (_, index) => {
if (index % 2 === 0) {
return {
rowSpan: 2,
};
} else {
return {
rowSpan: 0,
};
}
},
},
{
title: '班次',
width: 80,
dataIndex: 'type',
customRender: ({ text }) => text && render.renderDict(text, 'am_pm'),
},
{
title: '值班人员',
children: [
{
title: '操作人员',
dataIndex: 'operations',
key: 'operations',
},
{
title: '专业人员',
dataIndex: 'majors',
key: 'majors',
},
],
},
{
title: '操作',
dataIndex: 'action',
key: 'action',
width: 80,
},
];
// 处理自定义排班数据
export function dealData(customData) {
const arr = {};
for (const jsonElement of customData) {
if (!arr.hasOwnProperty(jsonElement.scheduleTime)) {
arr[jsonElement.scheduleTime] = {
'0': { ...jsonElement, '0': [], '1': [] },
'1': { ...jsonElement, '0': [], '1': [] },
};
}
if (jsonElement.type && jsonElement.userType) {
arr[jsonElement.scheduleTime][jsonElement.type][jsonElement.userType].push(jsonElement);
}
}
const result = [];
for (const j in arr) {
for (const k in arr[j]) {
result.push(arr[j][k]);
}
}
return result;
}
// 处理数据返回格式
export function renderType(type) {
return render.renderDict(type, 'am_pm').children;
}
//自定义表单新增
export const formSchema: FormSchema[] = [
{
label: '姓名',
field: 'userName',
component: 'Input',
dynamicRules: () => {
return [{ required: true, message: '请输入${label}!' }];
},
},
{
label: '星期',
field: 'week',
component: 'JDictSelectTag',
componentProps: {
dictCode: 'week',
stringToNumber: true,
},
},
{
label: '类型',
field: 'type',
component: 'RadioGroup',
componentProps: {
options: [
{
value: '0',
label: '上午',
},
{
value: '1',
label: '下午',
},
],
},
},
{
label: '人员类型',
field: 'userType',
component: 'RadioGroup',
componentProps: {
options: [
{
value: '0',
label: '操作人员',
},
{
value: '1',
label: '专业人员',
},
],
},
},
{
label: '性别',
field: 'userSex',
component: 'JDictSelectTag',
componentProps: {
dictCode: 'sex',
type: 'radioButton',
},
},
// TODO 主键隐藏字段,目前写死为ID
{
label: '',
field: 'id',
component: 'Input',
show: false,
},
];
/**
* 流程表单调用这个方法获取formSchema
* @param _formData
*/
export function getBpmFormSchema(_formData): FormSchema[] {
// 默认和原始表单保持一致 如果流程中配置了权限数据,这里需要单独处理formSchema
return formSchema;
}
@@ -0,0 +1,327 @@
<template>
<div class="schedule-default-list">
<div class="schedule-def-content">
<a-tabs v-model:activeKey="activeKey" :destroyInactiveTabPane="true">
<template #rightExtra>
<a-button v-show="activeKey === '2'" type="primary" preIcon="ant-design:plus-outlined" @click="customDataAdd">新增 </a-button>
</template>
<a-tab-pane key="1" tab="默认排班">
<a-table :columns="defaultColumns" :data-source="defaultState.columnData" bordered size="small" :pagination="false">
<template #bodyCell="{ column, record, index }">
<template v-if="column.key === 'action'">
<a @click="defaultEdit(record, index)">编辑</a>
</template>
</template>
</a-table>
</a-tab-pane>
<a-tab-pane key="2" tab="自定义排班">
<BasicForm
:labelWidth="80"
:schemas="customSearchForm"
:actionColOptions="{ span: 8 }"
@submit="handleSubmit"
@reset="resetFields"
/>
<a-table
:columns="customColumns"
:data-source="customState.customData"
@change="changeTable"
border
size="small"
:pagination="paginationState"
>
<template #bodyCell="{ column, record, index }">
<template v-if="column.key === 'action'">
<table-action :actions="getTableAction(record, index)" />
</template>
</template>
</a-table>
</a-tab-pane>
<a-tab-pane key="3" tab="值班记录">
<schedule-tab v-if="activeKey === '3'" />
</a-tab-pane>
</a-tabs>
</div>
<ScheduleCustomModal v-if="activeKey === '2'" @register="registerModal" @success="handleSuccess" />
<default-drawer-edit ref="defaultEditRef" :edit-data="defaultEditData" :visible="visible" @submit="defaultSubmit" />
<custom-drawer-edit ref="customEditRef" :edit-data="customEditData" :visibleCustom="visibleCustom" @on-submit="customSubmit" />
</div>
</template>
<script setup lang="ts">
import { nextTick, onMounted, reactive, ref, watch } from 'vue';
import {
compareDate,
customColumns,
customSearchForm,
dealCustomObj,
dealObj,
dealResData,
defaultColumnData,
defaultColumns,
day,
} from './ScheduleDefault.data';
import { BasicForm } from '/@/components/Form';
import { useModal } from '/@/components/Modal';
import { TableAction } from '/@/components/Table';
import ScheduleCustomModal from './components/ScheduleCustomModal.vue';
import DefaultDrawerEdit from '/@/views/emergency/outburst/ScheduleCustom/components/DefaultDrawerEdit.vue';
import CustomDrawerEdit from '/@/views/emergency/outburst/ScheduleCustom/components/CustomDrawerEdit.vue';
import ScheduleTab from '/@/views/emergency/outburst/ScheduleCustom/components/ScheduleTab.vue';
import {
customList,
list,
personType,
updateScheduleCustom,
updateScheduleDefault,
} from '/@/views/emergency/outburst/ScheduleCustom/ScheduleDefault.api';
import { customDeleteOne } from '/@/views/emergency/outburst/ScheduleCustom/ScheduleCustom.api';
const activeKey = ref('1');
let visible = ref(false);
let visibleCustom = ref(false);
const defaultEditRef = ref(null);
const customEditRef = ref(null);
let defaultState = reactive({
columnData: dealResData(defaultColumnData, dealObj),
apiData: [],
});
let paginationState = ref({
current: 1,
pageSize: 10,
pageSizeOptions: ['5', '10', '50', '80', '100'],
total: 0,
showQuickJumper: true,
size: 'small',
showTotal: (total) => ' 共 ' + total / 2 + ' 条数据',
});
// 当前排班
onMounted(() => {
getDefaultList();
});
function getDefaultList() {
list('').then((res) => {
let params = res.length > 0 ? res : defaultColumnData;
defaultState.apiData = params;
defaultState.columnData = dealResData(params, dealObj);
});
}
const defaultEditData = reactive({});
/**
* @Description:默认排班编辑
* @date 2023/6/26
*/
async function defaultEdit(row, index) {
let i = Math.floor(index / 2);
const rowData = defaultState.apiData[i]?.detail[row.type] || {};
const operationOptions = await personType({ personType: 5 });
const majorOptions = await personType({ personType: 6 });
Object.assign(defaultEditData, {
...row,
majors: rowData?.majors?.map((item) => item.userId) || [],
operations: rowData?.operations?.map((item) => item.userId) || [],
renderType: () => row.week_dictText + row.type_dictText,
majorOptions,
operationOptions,
});
defaultEditRef?.value?.openDrawer(defaultEditData);
}
function defaultSubmit(data) {
updateScheduleDefault(data).then(() => {
getDefaultList();
});
}
watch(activeKey, (val) => {
const fun = {
'1': getDefaultList,
'2': getCustomList,
'3': () => 1,
};
return fun[val]();
});
//自定义排班
const customState = reactive({
form: {
date: '',
type: '',
},
customData: [],
apiData: [],
});
/**
* @Description:自定义表单查询
* @date 2023/6/26
*/
function handleSubmit(val) {
customState.form = val;
getCustomList(1);
}
/**
* @Description:自定义排版表单重置
* @date 2023/6/26
*/
function resetFields() {
let form = customState.form;
for (const key in form) {
customState.form[key] = '';
}
nextTick(() => {
customState.form = form;
getCustomList(1);
});
}
/**
* @Description: 获取自定义页码
* @date 2023/6/20
*/
function getCustomList(pageNo?: number) {
const params = {
...customState.form,
pageNo: pageNo ?? paginationState.value.current,
pageSize: 5,
};
return customList(params).then((res) => {
nextTick(() => {
customState.customData = dealResData(res.records, dealCustomObj);
customState.apiData = res.records;
const { current, total } = res;
paginationState.value = {
...paginationState.value,
current,
total: total * 2,
};
});
});
}
/**
* @Description:页码改变事件
* @date 2023/6/20
* @param pagination
*/
const changeTable = (pagination) => {
paginationState.value.current = pagination.current;
paginationState.value.pageSize = 10;
getCustomList();
};
//注册model
const [registerModal, { openModal }] = useModal();
/**
* @Description:自定义排班操作列
* @date 2023/6/26
*/
function getTableAction(record, index) {
return [
{
label: '编辑',
disabled: compareDate(record.time, day.nextDay()),
onClick: customEdit.bind(null, record, index),
},
{
label: '删除',
disabled: compareDate(record.time, day.nextDay()),
onClick: customDelete.bind(null, record),
},
];
}
/**
* @Description:自定义排班新增
* @date 2023/6/26
*/
function customDataAdd() {
openModal(true, {
isUpdate: false,
showFooter: true,
});
}
const customEditData = reactive({
scheduleTime: '',
type: '',
opeVal: [],
opeOptions: [],
proVal: [],
proOptions: [],
});
/**
* @Description:自定义排班编辑
* @date 2023/6/26
* @param:
*/
async function customEdit(row) {
const operationOptions = await personType({ personType: 5 });
const majorOptions = await personType({ personType: 6 });
Object.assign(customEditData, {
...row,
majors: row.majorsId,
operations: row.operationsId,
majorOptions,
operationOptions,
});
customEditRef?.value?.openDrawer(customEditData);
}
/**
* @Description:自定义排班编辑成功后更新列表
* @date 2023/6/26
* @param:
*/
function customSubmit(data) {
updateScheduleCustom(data).then(() => {
getCustomList();
});
}
/**
* @Description:自定义排版删除
* @date 2023/6/26
* @param:{row}
*/
function customDelete(row) {
const params = {
time: row.time,
amOrPm: row.type,
};
customDeleteOne(params, getCustomList);
}
function handleSuccess() {
getCustomList();
}
</script>
<style lang="less" scoped>
.schedule-default-list {
padding: 10px 10px 0 10px;
height: 100%;
overflow: hidden;
}
.schedule-def-content {
box-sizing: border-box;
padding: 12px;
height: 100%;
overflow: auto;
background-color: #fff;
}
.edit-content {
.form-item {
margin: 16px 0;
}
.form-label {
}
}
:deep(table tr, table th, table td) {
border-right: 1px solid #f0f0f0 !important;
border-bottom: 1px solid #f0f0f0 !important;
}
</style>
@@ -0,0 +1,127 @@
<template>
<a-drawer forceRender v-model:visible="drawerData.visibleCustom" width="420" :title="title" placement="right" @close="onClose">
<template #extra>
<a-button style="margin-right: 8px" @click="onClose">取消</a-button>
<a-button type="primary" @click="onSubmit">确认</a-button>
</template>
<div class="edit-content">
<div class="form-item">
<span class="form-label">排班时间</span>
<span>{{ drawerData.time }}</span>
</div>
<div class="form-item">
<span class="form-label">排班班次</span>
<span>{{ renderType(drawerData.type) }}</span>
</div>
<div class="form-item">
<span class="form-label">操作人员</span>
<a-select
v-model:value="drawerData.operations"
:options="drawerData.operationOptions"
:fieldNames="{ label: 'realname', value: 'id' }"
mode="tags"
size="middle"
placeholder="请选择"
style="width: 220px"
/>
</div>
<div class="form-item">
<span class="form-label">专业人员</span>
<a-select
v-model:value="drawerData.majors"
:options="drawerData.majorOptions"
:fieldNames="{ label: 'realname', value: 'id' }"
mode="tags"
size="middle"
placeholder="请选择"
style="width: 220px"
/>
</div>
</div>
</a-drawer>
</template>
<script setup lang="ts">
import { reactive } from 'vue';
import { renderType } from '/@/views/emergency/outburst/ScheduleCustom/ScheduleDefault.data';
const props = defineProps({
visibleCustom: {
type: Boolean,
default: () => false,
},
title: {
type: String,
default: () => '编辑',
},
editData: {
type: Object,
},
});
const $emits = defineEmits(['onSubmit']);
const drawerData = reactive({
visibleCustom: props.visibleCustom,
majors: [],
operations: [],
majorOptions: [],
operationOptions: [],
time: '',
type: '',
...props.editData,
});
// 打开事件
function openDrawer(data) {
Object.assign(drawerData, { ...data });
drawerData.visibleCustom = true;
}
// 关闭事件
function onClose() {
drawerData.visibleCustom = false;
}
function filterData(data, filterData) {
let arr = [];
data.map((val) => {
let row = {};
filterData.map((item) => {
if (val.id === item) {
row = { userName: val.realname, userSex: val.sex, userId: val.id };
arr.push(row);
}
});
});
return arr;
}
function getSubmitData() {
return {
time: drawerData.time,
amOrPm: drawerData.type,
operators: filterData(drawerData.operationOptions, drawerData.operations),
majors: filterData(drawerData.majorOptions, drawerData.majors),
};
}
function onSubmit() {
const data = {
time: drawerData.time,
amOrPm: drawerData.type,
operators: filterData(drawerData.operationOptions, drawerData.operations),
majors: filterData(drawerData.majorOptions, drawerData.majors),
};
$emits('onSubmit', data);
onClose();
}
defineExpose({
openDrawer,
getSubmitData,
});
</script>
<style scoped lang="less">
.edit-content {
.form-item {
margin: 16px 0;
}
.form-label {
}
}
</style>
@@ -0,0 +1,129 @@
<template>
<a-drawer v-model:visible="drawerData.visible" width="420" title="编辑" placement="right" @close="onClose">
<template #extra>
<a-button style="margin-right: 8px" @click="onClose">取消</a-button>
<a-button type="primary" @click="submit">确认</a-button>
</template>
<div class="edit-content">
<div class="form-item">
<span class="form-label">排班班次</span>
<span>{{ drawerData.renderType() }}</span>
</div>
<div class="form-item">
<span class="form-label">操作人员</span>
<a-select
v-model:value="drawerData.operations"
:options="drawerData.operationOptions"
:fieldNames="{ label: 'realname', value: 'id' }"
showSearch
:filterOption="optionFilter"
mode="multiple"
size="middle"
placeholder="请选择"
style="width: 220px"
/>
</div>
<div class="form-item">
<span class="form-label">专业人员</span>
<a-select
v-model:value="drawerData.majors"
:options="drawerData.majorOptions"
:fieldNames="{ label: 'realname', value: 'id' }"
showSearch
:filter-option="optionFilter"
mode="multiple"
size="middle"
placeholder="请选择"
style="width: 220px"
/>
</div>
</div>
</a-drawer>
</template>
<script setup lang="ts">
import { reactive } from 'vue';
import { message } from 'ant-design-vue';
const props = defineProps({
visible: {
type: Boolean,
default: () => false,
},
title: {
type: String,
default: () => '编辑',
},
editData: {
type: Object,
},
});
const $emits = defineEmits(['submit']);
const drawerData = reactive({
visible: props.visible,
majors: [],
operations: [],
majorOptions: [],
operationOptions: [],
week: '',
type: '',
...props.editData,
});
function openDrawer(data) {
Object.assign(drawerData, { ...data });
drawerData.visible = true;
}
/**
* @Description:根据输入项进行筛选
* @date 2023/6/25
*/
function optionFilter(input: string, option: any): boolean {
const str: string = input.toLowerCase();
return option.realname.toLowerCase().indexOf(str) >= 0;
}
// 关闭事件
function onClose() {
drawerData.visible = false;
}
function filterData(data, filterData) {
let arr = [];
data.map((val) => {
let row = {};
filterData.map((item) => {
if (val.id === item) {
row = { userName: val.realname, userSex: val.sex, userId: val.id };
arr.push(row);
}
});
});
return arr;
}
function submit() {
const data = {
week: drawerData.week,
amOrPm: drawerData.type,
operators: filterData(drawerData.operationOptions, drawerData.operations),
majors: filterData(drawerData.majorOptions, drawerData.majors),
};
if (data.operators.length < 1) {
return message.warn('操作人员不能为空');
}
if (data.majors.length < 1) {
return message.warn('专业人员不能为空');
}
$emits('submit', data);
onClose();
}
defineExpose({
openDrawer,
});
</script>
<style scoped lang="less">
.edit-content {
.form-item {
margin: 16px 0;
}
.form-label {
}
}
</style>
@@ -0,0 +1,104 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="800" @ok="handleSubmit">
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, computed, unref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { formSchema } from '../ScheduleCustom.data';
import { saveOrUpdate } from '../ScheduleCustom.api';
import { personType } from '/@/views/emergency/outburst/ScheduleCustom/ScheduleDefault.api';
import { message } from 'ant-design-vue';
// Emits声明
const emit = defineEmits(['register', 'success']);
const isUpdate = ref(true);
//表单配置
const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({
//labelWidth: 150,
schemas: formSchema,
showActionButtonGroup: false,
baseColProps: { span: 24 },
});
//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
//重置表单
await resetFields();
setModalProps({
confirmLoading: false,
showCancelBtn: !!data?.showFooter,
showOkBtn: !!data?.showFooter,
});
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
//表单赋值
await setFieldsValue({
...data.record,
});
}
// 隐藏底部时禁用整个表单
setProps({ disabled: !data?.showFooter });
});
//设置标题
const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
function filterData(data, filterData) {
let arr = [];
data.map((val) => {
let row = {};
filterData.map((item) => {
if (val.id === item) {
row = { userName: val.realname, userSex: val.sex, userId: val.id };
arr.push(row);
}
});
});
return arr;
}
//表单提交事件
async function handleSubmit() {
try {
let values = await validate();
const operationOptions = await personType({ personType: 5 });
const majorOptions = await personType({ personType: 6 });
const params = {
time: values.time,
amOrPm: values.type,
operators: filterData(operationOptions, values.operators?.split(',') || []),
majors: filterData(majorOptions, values.majors?.split(',') || []),
};
setModalProps({ confirmLoading: true });
if (!params.operators.length && !params.majors.length) {
return message.warn('操作人员或专业人员至少填写一条数据');
}
// 选择全天
if (values.type === '2') {
await saveOrUpdate({ ...params, amOrPm: '0' }, isUpdate.value);
await saveOrUpdate({ ...params, amOrPm: '1' }, isUpdate.value);
} else {
await saveOrUpdate(params, isUpdate.value);
}
//提交表单
//关闭弹窗
closeModal();
//刷新列表
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>
<style lang="less" scoped>
/** 时间和数字输入框样式 */
:deep(.ant-input-number) {
width: 100%;
}
:deep(.ant-calendar-picker) {
width: 100%;
}
</style>
@@ -0,0 +1,66 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="800" @ok="handleSubmit">
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, computed, unref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { formSchema } from '../ScheduleDefault.data';
import { saveOrUpdate } from '../ScheduleDefault.api';
// Emits声明
const emit = defineEmits(['register', 'success']);
const isUpdate = ref(true);
//表单配置
const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({
//labelWidth: 150,
schemas: formSchema,
showActionButtonGroup: false,
baseColProps: { span: 24 },
});
//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
//重置表单
await resetFields();
setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, showOkBtn: !!data?.showFooter });
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
//表单赋值
await setFieldsValue({
...data.record,
});
}
// 隐藏底部时禁用整个表单
await setProps({ disabled: !data?.showFooter });
});
//设置标题
const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
//表单提交事件
async function handleSubmit() {
try {
let values = await validate();
setModalProps({ confirmLoading: true });
//提交表单
await saveOrUpdate(values, isUpdate.value);
//关闭弹窗
closeModal();
//刷新列表
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>
<style lang="less" scoped>
/** 时间和数字输入框样式 */
:deep(.ant-input-number) {
width: 100%;
}
:deep(.ant-calendar-picker) {
width: 100%;
}
</style>
@@ -0,0 +1,75 @@
<template>
<BasicForm :labelWidth="80" :schemas="customSearchForm" :actionColOptions="{ span: 6 }" @submit="handleSubmit" @reset="resetFields" />
<a-table :columns="recordColumns" :pagination="paginationState" @change="changeTable" :data-source="customState.customData" border size="small" />
</template>
<script setup lang="ts">
import { recordColumns, customSearchForm, dealCustomObj, dealResData } from '/@/views/emergency/outburst/ScheduleCustom/ScheduleDefault.data';
import { BasicForm } from '/@/components/Form';
import { nextTick, reactive, ref, onMounted } from 'vue';
import { scheduleRecord } from '/@/views/emergency/outburst/ScheduleCustom/ScheduleDefault.api';
const customState = reactive({
form: {
date: '',
type: '',
},
customData: [],
apiData: [],
});
let paginationState = ref({
current: 1,
pageSize: 10,
showSizeChanger: false,
// pageSizeOptions: ['10', '50', '80', '100'],
total: 0,
showQuickJumper: true,
size: 'small',
showTotal: (total) => ' 共 ' + total / 2 + ' 条数据',
});
onMounted(() => {
getCustomList();
});
function getCustomList(pageNo?: number) {
const pageSize = paginationState.value.pageSize === 10 ? 5 : paginationState.value.pageSize / 2;
const params = {
...customState.form,
pageNo: pageNo ?? paginationState.value.current,
pageSize: pageSize,
};
scheduleRecord(params).then((res) => {
customState.customData = dealResData(res.records, dealCustomObj);
customState.apiData = res.records;
const { current, total } = res;
paginationState.value = {
...paginationState.value,
current,
total: total * 2,
};
});
}
/**
* @Description:页码改变事件
* @date 2023/6/20
* @param pagination
*/
const changeTable = (pagination: { current: number; pageSize: number }) => {
paginationState.value.current = pagination.current;
paginationState.value.pageSize = pagination.pageSize;
getCustomList();
};
function resetFields() {
let form = customState.form;
for (const key in form) {
customState.form[key] = '';
}
nextTick(() => {
customState.form = form;
getCustomList(1);
});
}
function handleSubmit(val) {
customState.form = val;
getCustomList(1);
}
</script>
@@ -0,0 +1,95 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm } = useMessage();
enum Api {
list = '/health-emergency/emergency/order/list',
newList = '/health-emergency/emergency/order/listOrderMajor',
save = '/health-emergency/emergency/order/add',
edit = '/health-emergency/emergency/order/edit',
deleteOne = '/health-emergency/emergency/order/delete',
deleteBatch = '/health-emergency/emergency/order/deleteBatch',
importExcel = '/health-emergency/emergency/order/importExcel',
exportXls = '/health-emergency/emergency/order/exportXls',
queryById = '/health-emergency/emergency/order/queryById',
employeeUnit = '/sys/sysDepart/allSecondaryDeparts', //员工单位
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
export const queryByIdUrl = Api.queryById;
/**
* 请求编辑数据
*/
export const resEditData = async (params) => {
return await defHttp.get({ url: Api.queryById, params });
};
/**
* 导入api
*/
export const getImportUrl = Api.importExcel;
/**
* 列表接口
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
export const newList = (params) => defHttp.get({ url: Api.newList, params });
/**
* 删除单个
*/
export const deleteOne = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () =>
defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
}),
});
};
/**
* 批量删除
* @param params
*/
export const batchDelete = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
},
});
};
/**
* 保存或者更新
* @param params
*/
export const saveOrUpdate = (params, isUpdate) => {
const url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params });
};
/**
* 获取员工单位
* */
export const employeeUnit = (params) => {
return defHttp.get({ url: Api.employeeUnit, params });
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,79 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm } = useMessage();
enum Api {
list = '/health-emergency/emergency/orderDetail/list',
save = '/health-emergency/emergency/orderDetail/add',
edit = '/health-emergency/emergency/orderDetail/edit',
deleteOne = '/health-emergency/emergency/orderDetail/delete',
deleteBatch = '/health-emergency/emergency/orderDetail/deleteBatch',
importExcel = '/health-emergency/emergency/orderDetail/importExcel',
exportXls = '/health-emergency/emergency/orderDetail/exportXls',
queryById = '/emergency/orderDetail/queryById',
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
export const queryByIdUrl = Api.queryById;
/**
* 导入api
*/
export const getImportUrl = Api.importExcel;
/**
* 列表接口
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
* 删除单个
*/
export const deleteOne = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () =>
defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
}),
});
};
/**
* 批量删除
* @param params
*/
export const batchDelete = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
},
});
};
/**
* 保存或者更新
* @param params
*/
export const saveOrUpdate = (params, isUpdate) => {
const url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params });
};
@@ -0,0 +1,96 @@
import { BasicColumn } from '/@/components/Table';
import { FormSchema } from '/@/components/Table';
//列表数据
export const columns: BasicColumn[] = [
{
title: '评价',
align: 'center',
dataIndex: 'orderEvaluation',
},
{
title: '事件经过',
align: 'center',
dataIndex: 'orderThrough',
},
{
title: '事件结果',
align: 'center',
dataIndex: 'orderResult',
},
// {
// title: '状态(1-正常,2-冻结)',
// align:"center",
// dataIndex: 'status'
// },
// {
// title: '删除状态(0-正常,1-已删除)',
// align:"center",
// dataIndex: 'delFlag'
// },
// {
// title: '备注',
// align:"center",
// dataIndex: 'memo'
// },
];
//查询数据
export const searchFormSchema: FormSchema[] = [];
//表单数据
export const formSchema: FormSchema[] = [
{
label: '评价',
field: 'orderEvaluation',
component: 'Input',
},
{
label: '事件经过',
field: 'orderThrough',
component: 'InputTextArea',
},
{
label: '事件结果',
field: 'orderResult',
component: 'InputTextArea',
},
// {
// label: '状态(1-正常,2-冻结)',
// field: 'status',
// component: 'InputNumber',
// dynamicRules: ({model,schema}) => {
// return [
// { required: true, message: '请输入状态(1-正常,2-冻结)!'},
// ];
// },
// },
// {
// label: '删除状态(0-正常,1-已删除)',
// field: 'delFlag',
// component: 'InputNumber',
// dynamicRules: ({model,schema}) => {
// return [
// { required: true, message: '请输入删除状态(0-正常,1-已删除)!'},
// ];
// },
// },
// {
// label: '备注',
// field: 'memo',
// component: 'Input',
// },
// TODO 主键隐藏字段,目前写死为ID
{
label: '',
field: 'id',
component: 'Input',
show: false,
},
];
/**
* 流程表单调用这个方法获取formSchema
* @param _formData
*/
export function getBpmFormSchema(_formData): FormSchema[] {
// 默认和原始表单保持一致 如果流程中配置了权限数据,这里需要单独处理formSchema
return formSchema;
}
@@ -0,0 +1,164 @@
<template>
<div>
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
<a-dropdown v-if="selectedRowKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined" />
删除
</a-menu-item>
</a-menu>
</template>
<a-button
>批量操作
<Icon icon="mdi:chevron-down" />
</a-button>
</a-dropdown>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
</template>
<!--字段回显插槽-->
<template #htmlSlot="{ text }">
<div v-html="text"></div>
</template>
<!--省市区字段回显插槽-->
<template #pcaSlot="{ text }">
{{ getAreaTextByCode(text) }}
</template>
<template #fileSlot="{ text }">
<span v-if="!text" style="font-size: 12px; font-style: italic">无文件</span>
<a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)"
>下载</a-button
>
</template>
</BasicTable>
<!-- 表单区域 -->
<OrderDetailModal @register="registerModal" @success="handleSuccess" />
</div>
</template>
<script lang="ts" name="emergency-orderDetail" setup>
import { BasicTable, TableAction } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
import { useListPage } from '/@/hooks/system/useListPage';
import OrderDetailModal from './components/OrderDetailModal.vue';
import { columns, searchFormSchema } from './OrderDetail.data';
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './OrderDetail.api';
import { downloadFile } from '/@/utils/common/renderUtils';
//注册model
const [registerModal, { openModal }] = useModal();
//注册table数据
const { tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: 'emergency_order_detail',
api: list,
columns,
canResize: false,
formConfig: {
//labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter: true,
showAdvancedButton: true,
fieldMapToNumber: [],
fieldMapToTime: [],
},
actionColumn: {
width: 120,
fixed: 'right',
},
},
exportConfig: {
name: 'emergency_order_detail',
url: getExportUrl,
},
importConfig: {
url: getImportUrl,
success: handleSuccess,
},
});
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
/**
* 新增事件
*/
function handleAdd() {
openModal(true, {
isUpdate: false,
showFooter: true,
});
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: true,
});
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: false,
});
}
/**
* 删除事件
*/
function handleDelete(record: Recordable) {
deleteOne({ id: record.id }, handleSuccess);
}
/**
* 批量删除事件
*/
function batchHandleDelete() {
batchDelete({ ids: selectedRowKeys.value }, handleSuccess);
}
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 操作栏
*/
function getTableAction(record: Recordable) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
},
];
}
/**
* 下拉操作栏
*/
function getDropDownAction(record: Recordable) {
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
},
{
label: '删除',
onClick: handleDelete.bind(null, record),
},
];
}
</script>
@@ -0,0 +1,180 @@
<template>
<div>
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
</BasicTable>
<!-- 表单区域 -->
<!--详情弹窗-->
<OrderDrawer ref="RefOrderDrawer" />
<detail ref="detailRef" />
<OrderRecord @register="registerModal" />
</div>
</template>
<script lang="ts" name="emergency-order" setup>
import { ref, nextTick } from 'vue';
import { BasicColumn, BasicTable, TableAction } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
import { useListPage } from '/@/hooks/system/useListPage';
import OrderDrawer from './components/OrderDrawer.vue';
import { columns, searchFormSchema, columnsPersonF, columnsPersonS, searchFormSchemaS } from './Order.data';
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl, resEditData, newList } from './Order.api';
import { message } from 'ant-design-vue';
import { useUserStore } from '/@/store/modules/user';
import detail from '/@/views/emergency/communication/components/detail.vue';
import { router } from '/@/router';
import OrderRecord from '/@/views/emergency/outburst/order/components/OrderRecord.vue';
//注册model
const [registerModal, { openModal }] = useModal();
const userStore = useUserStore();
const useColumns: BasicColumn[] =
userStore.getUserInfo.personType === '5' ? columnsPersonF : userStore.getUserInfo.personType === '6' ? columnsPersonS : columns;
//注册table数据
const { tableContext } = useListPage({
tableProps: {
title: 'emergency_order',
api: userStore.getUserInfo.personType === '6' ? newList : list,
columns: useColumns,
canResize: false,
rowSelection: false,
formConfig: {
//labelWidth: 120,
schemas: userStore.getUserInfo.personType === '6' ? searchFormSchemaS : searchFormSchema,
autoSubmitOnEnter: true,
showAdvancedButton: false,
fieldMapToNumber: [],
fieldMapToTime: [],
},
showActionColumn: userStore.getUserInfo?.personType !== '6',
actionColumn: {
width: 200,
fixed: 'right',
},
beforeFetch: (info) => {
// 对日期选择器的处理
const createTimeRange = info?.createTimeRange?.split(',');
if (createTimeRange) {
return { ...info, createTimeStart: createTimeRange[0], createTimeEnd: createTimeRange[1] };
}
},
},
exportConfig: {
name: 'emergency_order',
url: getExportUrl,
},
importConfig: {
url: getImportUrl,
success: handleSuccess,
},
});
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
/**
* 详情
*/
const RefOrderDrawer = ref();
function handleDetail(record: Recordable) {
resEditData({ id: record.id }).then((res) => {
nextTick(() => {
RefOrderDrawer.value.showDrawer(res);
});
});
}
/**
* 删除事件
*/
function handleDelete(record: Recordable) {
deleteOne({ id: record.id }, handleSuccess);
}
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/*
* 咨询详情
* */
function handleZDetail(record: Recordable) {
router.push({ path: `/emergency/communication`, query: { sessionId: record.sessionId } });
}
const detailRef = ref();
/*
* 应急详情
* */
function handleYDetail(res) {
detailRef.value.showDrawer(res.id);
}
/**
* @Description:派单记录
* @date 2023/6/29
* @param record 列表数据
*/
function orderRecord(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: false,
});
}
/**
* 操作栏
*/
function getTableAction(record: Recordable) {
let result = [
{
label: '应急工单',
onClick: handleDetail.bind(null, record),
auth: 'emergency:emergency_order:edit',
},
{
label: '派单记录',
onClick: orderRecord.bind(null, record),
},
{
label: '删除',
onClick: handleDelete.bind(null, record),
},
];
switch (userStore.getUserInfo?.personType) {
case '5':
result = [
{
label: '应急详情',
onClick: handleYDetail.bind(null, record),
auth: '',
},
];
break;
case '6':
result = [
{
label: '咨询详情',
onClick: handleZDetail.bind(null, record),
auth: '',
},
];
break;
}
return result;
}
</script>
<style lang="less" scoped>
:deep(.ant-popover-buttons) {
display: flex !important;
}
</style>
@@ -0,0 +1,66 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="800" @ok="handleSubmit">
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, computed, unref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { formSchema } from '../OrderDetail.data';
import { saveOrUpdate } from '../OrderDetail.api';
// Emits声明
const emit = defineEmits(['register', 'success']);
const isUpdate = ref(true);
//表单配置
const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({
//labelWidth: 150,
schemas: formSchema,
showActionButtonGroup: false,
baseColProps: { span: 24 },
});
//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
//重置表单
await resetFields();
setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, showOkBtn: !!data?.showFooter });
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
//表单赋值
await setFieldsValue({
...data.record,
});
}
// 隐藏底部时禁用整个表单
await setProps({ disabled: !data?.showFooter });
});
//设置标题
const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
//表单提交事件
async function handleSubmit(v) {
try {
let values = await validate();
setModalProps({ confirmLoading: true });
//提交表单
await saveOrUpdate(values, isUpdate.value);
//关闭弹窗
closeModal();
//刷新列表
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>
<style lang="less" scoped>
/** 时间和数字输入框样式 */
:deep(.ant-input-number) {
width: 100%;
}
:deep(.ant-calendar-picker) {
width: 100%;
}
</style>
@@ -0,0 +1,136 @@
<template>
<a-drawer
:title="title"
:headerStyle="{ textAlign: 'left' }"
width="80%"
placement="right"
:closable="true"
v-model:visible="open"
@close="onClose"
>
<div>
<div>
<CommonDesc title="应急员工信息" :descList="descList1" :descRes="descRes">
<template #salvageUserName="{ row }">
{{ row.val }}
<!-- <span class="span-action" @click="btn(row)">更改被救助人</span>-->
</template>
</CommonDesc>
</div>
<div class="desc-item">
<CommonDesc title="工单信息" :descList="descList2" :descRes="descRes" />
</div>
<div class="desc-item">
<CommonDesc title="应急小结" :column="1" :descList="descList3" :descRes="descRes" />
<!-- <a-descriptions title="应急小结" :column="1" bordered :label-style="{ width: '110px', padding: '12px 12px' }">-->
<!-- <a-descriptions-item label="应急经过" :column="{ xxl: 4, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 }">-->
<!-- <a-textarea v-model:value="descRes.orderThrough" />-->
<!-- </a-descriptions-item>-->
<!-- <a-descriptions-item label="应急结果" :column="{ xxl: 4, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 }">-->
<!-- <a-textarea v-model:value="descRes.orderResult" />-->
<!-- </a-descriptions-item>-->
<!-- </a-descriptions>-->
</div>
<div class="desc-item">
<!-- <a-descriptions title="应急过程" />-->
<!-- <div>-->
<!-- <span class="span-action">视频</span>-->
<!-- <span class="span-action">聊天记录</span>-->
<!-- </div>-->
<CommonDesc class="desc-item-process" title="救护车" :descList="descList4" :descRes="descRes" />
<CommonDesc class="desc-item-process" title="单位车辆" :descList="descList5" :descRes="descRes" />
<CommonDesc class="desc-item-process" title="救助信息" :descList="descList6" :descRes="descRes" />
</div>
<div class="scene-photo desc-item">
<div class="scene-photo-label"> 现场照片</div>
<div class="photo-list">
<ImagePreview :imageList="imgList" />
</div>
</div>
<div class="desc-item">
<CommonDesc title="" :column="1" :descList="descList7" :descRes="descRes" />
</div>
</div>
</a-drawer>
</template>
<script setup lang="ts">
import { ref, nextTick } from 'vue';
import CommonDesc from '/@/views/emergency/outburst/order/components/commonDesc.vue';
import { descList1, descList2, descList3, descList4, descList5, descList6, descList7 } from '/@/views/emergency/outburst/order/Order.data';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import { ImagePreview } from '/@/components/Preview/index';
let title = '应急工单';
let open = ref(false);
const descRes = ref({});
const imgList = ref([]);
const showDrawer = (data) => {
nextTick(() => {
open.value = true;
descRes.value = {
...data,
...data.orderDetail,
};
imgList.value = data.orderDetail?.imgs?.split(',').map((item) => ({
width: 150,
height: 150,
src: getFileAccessHttpUrl(item),
}));
});
};
const onClose = () => {
open.value = false;
};
function btn(scope) {
console.log('--->scope', scope);
}
// 暴露给父组件
defineExpose({
showDrawer,
});
</script>
<style scoped lang="less">
.scene-photo {
display: flex;
flex-direction: column;
.scene-photo-label {
font-weight: bold;
}
.photo-list {
flex: 1;
display: flex;
.photo-style {
display: flex;
}
}
}
.span-action {
color: #1890ff;
cursor: pointer;
margin-left: 5px;
}
.desc-item {
margin-top: 16px;
}
.desc-item-process {
margin-top: 12px;
}
@prefix-cls: ~'@{namespace}-image-preview';
.@{prefix-cls} {
display: flex;
.ant-image {
margin-right: 10px;
border-radius: 8px;
}
}
</style>
@@ -0,0 +1,66 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="800" @ok="handleSubmit">
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, computed, unref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { formSchema } from '../Order.data';
import { saveOrUpdate } from '../Order.api';
// Emits声明
const emit = defineEmits(['register', 'success']);
const isUpdate = ref(true);
//表单配置
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
//labelWidth: 150,
schemas: formSchema,
showActionButtonGroup: false,
baseColProps: { span: 24 },
});
//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
//重置表单
await resetFields();
setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, showOkBtn: !!data?.showFooter });
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
//表单赋值
await setFieldsValue({
...data.record,
});
}
// 隐藏底部时禁用整个表单
setProps({ disabled: !data?.showFooter });
});
//设置标题
const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
//表单提交事件
async function handleSubmit(v) {
try {
let values = await validate();
setModalProps({ confirmLoading: true });
//提交表单
await saveOrUpdate(values, isUpdate.value);
//关闭弹窗
closeModal();
//刷新列表
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>
<style lang="less" scoped>
/** 时间和数字输入框样式 */
:deep(.ant-input-number) {
width: 100%;
}
:deep(.ant-calendar-picker) {
width: 100%;
}
</style>
@@ -0,0 +1,28 @@
<template>
<div>
<BasicModal v-bind="$attrs" :title="title" :width="1200" @register="registerModal" destroyOnClose>
<div style="max-height: 70vh; overflow: auto">
<OrderSendRecordList :orderId="orderId" />
</div>
</BasicModal>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import OrderSendRecordList from '/@/views/emergency/outburst/OrderSendRecord/OrderSendRecordList.vue';
const title = '派单记录';
const orderId = ref('');
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
console.log('orderId', data.record.id);
orderId.value = data.record.id;
setModalProps({
confirmLoading: false,
showCancelBtn: !!data?.showFooter,
showOkBtn: !!data?.showFooter,
});
});
</script>
<style scoped lang="less"></style>
@@ -0,0 +1,47 @@
<template>
<a-descriptions :title="title" :column="column" bordered :label-style="labelStyle">
<a-descriptions-item
v-for="(item, i) in descList"
:key="i"
:label="item.label"
:span="item.spanNumber || 1"
:column="{ xxl: 4, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 }"
>
<slot v-if="item.hasOwnProperty('slot')" :name="item.slot" :row="{ item, val: descRes?.[item.key] }"></slot>
<div v-else-if="item.hasOwnProperty('render')">
{{ item.render(descRes[item.key]) || '' }}
</div>
<div v-else-if="item.type === 'richText'" v-html="descRes?.[item.key]"></div>
<div v-else>
{{ (item.key && descRes[item.key]) || '' }}
</div>
</a-descriptions-item>
</a-descriptions>
</template>
<script setup lang="ts">
/**
* @column 一行排列几个
* @descList 数据描述列表
* @descRes 结果数据
* */
const props = defineProps({
title: String,
descList: {
type: Array,
default: () => [],
},
descRes: {
type: Object,
default: () => {},
},
column: {
type: Number,
default: () => 3,
},
labelStyle: {
type: Object,
default: () => ({ width: '110px', padding: '12px 12px' }),
},
});
</script>
<style scoped lang="less"></style>
@@ -0,0 +1,79 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm } = useMessage();
enum Api {
list = '/health-emergency/emergency/resource/list',
save = '/health-emergency/emergency/resource/add',
edit = '/health-emergency/emergency/resource/edit',
deleteOne = '/health-emergency/emergency/resource/delete',
deleteBatch = '/health-emergency/emergency/resource/deleteBatch',
importExcel = '/health-emergency/emergency/resource/importExcel',
exportXls = '/health-emergency/emergency/resource/exportXls',
queryById = '/emergency/resource/queryById',
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
export const queryByIdUrl = Api.queryById;
/**
* 导入api
*/
export const getImportUrl = Api.importExcel;
/**
* 列表接口
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
* 删除单个
*/
export const deleteOne = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () =>
defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
}),
});
};
/**
* 批量删除
* @param params
*/
export const batchDelete = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
},
});
};
/**
* 保存或者更新
* @param params
*/
export const saveOrUpdate = (params, isUpdate) => {
const url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params });
};
@@ -0,0 +1,194 @@
import { BasicColumn } from '/@/components/Table';
import { FormSchema } from '/@/components/Table';
import { render } from '/@/utils/common/renderUtils';
//列表数据
export const columns: BasicColumn[] = [
{
title: '资源名称',
align: 'center',
dataIndex: 'name',
},
{
title: '资源类型',
align: 'center',
dataIndex: 'type',
customRender: ({ text }) => {
return render.renderDict(text, 'resource_type');
},
},
{
title: '医院等级',
align: 'center',
dataIndex: 'level',
customRender: ({ text }) => {
return render.renderDict(text, 'hospital_level');
},
},
{
title: '详细地址',
align: 'center',
dataIndex: 'address',
},
{
title: '联系电话',
align: 'center',
dataIndex: 'mobile',
},
{
title: '介绍/简介',
align: 'center',
dataIndex: 'aidrange',
},
];
//查询数据
export const searchFormSchema: FormSchema[] = [
{
label: '资源名称',
field: 'name',
component: 'Input',
},
{
label: '资源类型',
field: 'type',
component: 'JDictSelectTag',
componentProps: {
dictCode: 'resource_type',
},
},
{
label: '医院等级',
field: 'level',
component: 'JDictSelectTag',
componentProps: {
dictCode: 'hospital_level',
},
},
{
label: '介绍/简介',
field: 'aidrange',
component: 'Input',
},
];
//表单数据
export const formSchema: FormSchema[] = [
{
label: '资源类型',
field: 'type',
component: 'JDictSelectTag',
componentProps: {
dictCode: 'resource_type',
},
required: true,
},
{
label: '资源名称',
field: 'name',
component: 'Input',
componentProps: ({ schema, formModel }) => {
// 急救员
if (formModel?.type == '6') {
schema.label = '医生姓名';
} else {
schema.label = '资源名称';
}
},
dynamicRules: () => {
return [{ required: true, message: '请输入资源名称!' }];
},
},
{
label: '医院等级',
field: 'level',
component: 'JDictSelectTag',
componentProps: {
dictCode: 'hospital_level',
},
// 处理特殊类型不展示医院等级
ifShow: (params) => !['4', '5', '6'].includes(params.values?.type),
required: true,
},
// {
// field: 'province',
// component: 'JAreaSelect',
// label: '省市区',
// // defaultValue: ['610101'],
// defaultValue: ['140000', '140300', '140302']
// },
{
label: '介绍/简介',
field: 'aidrange',
component: 'InputTextArea',
},
{
label: '网址',
field: 'url',
component: 'Input',
rules: [
{ required: false, pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '网址格式有误' },
],
ifShow: (params) => !['5', '6'].includes(params.values?.type),
},
{
label: '图片',
field: 'img',
component: 'JImageUpload',
},
{
label: '地址',
field: 'customAddress',
component: 'Input',
slot: 'customAddress',
rules: [{ required: true }],
ifShow: false,
},
{
label: '详细地址',
field: 'address',
component: 'Input',
slot: 'address',
required: true,
},
{
label: '联系电话',
field: 'mobile',
component: 'Input',
rules: [{ required: true, pattern: /^1[3456789]\d{9}$/, message: '手机号码格式有误' }],
},
{
label: '经度',
field: 'longitude',
component: 'InputNumber',
// required: true,
ifShow: false,
},
{
label: '纬度',
field: 'latitude',
component: 'InputNumber',
// required: true,
ifShow: false,
},
// {
// label: '高德地图数据',
// field: 'gdId',
// component: 'Input',
// },
// TODO 主键隐藏字段,目前写死为ID
{
label: '',
field: 'id',
component: 'Input',
show: false,
},
];
/**
* 流程表单调用这个方法获取formSchema
* @param param
*/
export function getBpmFormSchema(_formData): FormSchema[] {
// 默认和原始表单保持一致 如果流程中配置了权限数据,这里需要单独处理formSchema
return formSchema;
}
@@ -0,0 +1,172 @@
<template>
<div>
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined" v-auth="'emergency:emergency_resource:add'">
新增
</a-button>
<a-button
type="primary"
@click="batchHandleDelete"
preIcon="ant-design:delete-outlined"
v-auth="'emergency:emergency_resource:delete'"
>
批量删除
</a-button>
<!-- <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button> -->
<!-- <j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button> -->
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
<!--字段回显插槽-->
<template #htmlSlot="{ text }">
<div v-html="text"></div>
</template>
</BasicTable>
<!-- 表单区域 -->
<ResourceModal @register="registerDrawer" @success="handleSuccess" />
</div>
</template>
<script lang="ts" name="emergency-resource" setup>
import { ref } from 'vue';
import { BasicTable, TableAction } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
import { useListPage } from '/@/hooks/system/useListPage';
import ResourceModal from './components/ResourceModal.vue';
import { columns, searchFormSchema } from './Resource.data';
import { batchDelete, deleteOne, getExportUrl, getImportUrl, list } from './Resource.api';
import { message } from 'ant-design-vue';
import { useDrawer } from '/@/components/Drawer';
const checkedKeys = ref<Array<string | number>>([]);
//注册model
const [registerDrawer, { openDrawer }] = useDrawer();
//注册table数据
const { prefixCls, tableContext } = useListPage({
tableProps: {
title: '应急资源',
api: list,
columns,
canResize: false,
formConfig: {
//labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter: true,
showAdvancedButton: false,
fieldMapToNumber: [],
fieldMapToTime: [],
},
actionColumn: {
width: 160,
fixed: 'right',
},
beforeFetch: (info) => {
info['name'] = info?.name && `*${info.name}*`;
info['aidrange'] = info?.aidrange && `*${info.aidrange}*`;
return info;
},
},
exportConfig: {
name: '应急资源',
url: getExportUrl,
},
importConfig: {
url: getImportUrl,
success: handleSuccess,
},
});
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
/**
* 新增事件
*/
function handleAdd() {
openDrawer(true, {
isUpdate: false,
showFooter: true,
title: '新增',
});
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
openDrawer(true, {
record,
isUpdate: true,
showFooter: true,
title: '编辑',
});
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
openDrawer(true, {
record,
isUpdate: true,
showFooter: false,
title: '详情',
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteOne({ id: record.id }, handleSuccess);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
if (selectedRowKeys.value.length === 0) {
return message.warning('未选中任何数据');
}
await batchDelete({ ids: selectedRowKeys.value }, handleSuccess);
}
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
auth: 'emergency:emergency_resource:edit',
},
{
label: '详情',
onClick: handleDetail.bind(null, record),
},
{
label: '删除',
onClick: handleDelete.bind(null, record),
auth: 'emergency:emergency_resource:delete',
},
];
}
</script>
<style lang="less" scoped>
:deep(.ant-popover-buttons) {
display: flex !important;
}
</style>
@@ -0,0 +1,117 @@
<template>
<BasicDrawer v-bind="$attrs" :showFooter="showFooter" @register="registerModal" destroyOnClose :title="title" :width="800" @ok="handleSubmit">
<BasicForm @register="registerForm">
<template #address="{ model }">
<a-input style="width: 82%" v-model:value="model['address']" :disabled="true" />
<a-button style="margin-left: 10px" @click="viewMap" :disabled="!showFooter">查看地图</a-button>
</template>
</BasicForm>
<Map @register="registerMap" :state="state" ref="map" @get-position="getPosition" />
</BasicDrawer>
</template>
<script lang="ts" setup>
import { ref, unref } from 'vue';
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
import { BasicForm, useForm } from '/@/components/Form/index';
import { formSchema } from '../Resource.data';
import { saveOrUpdate } from '../Resource.api';
import Map from '/@/views/consult/resource/components/Map.vue';
import { useModal } from '/@/components/Modal';
// Emits声明
const emit = defineEmits(['register', 'success']);
const isUpdate = ref(true);
const showFooter = ref<boolean>(true);
const state = ref();
//设置标题
const title = ref<string>('');
//表单配置
const [registerForm, { setProps, resetFields, setFieldsValue, validate, getFieldsValue, clearValidate }] = useForm({
//labelWidth: 150,
schemas: formSchema,
showActionButtonGroup: false,
baseColProps: { span: 24 },
});
const [registerMap, { openModal }] = useModal();
//表单赋值
const [registerModal, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
//重置表单
await resetFields();
setDrawerProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, showOkBtn: !!data?.showFooter });
isUpdate.value = !!data?.isUpdate;
showFooter.value = data.showFooter;
title.value = data.title;
let customAddress = '';
if (unref(isUpdate)) {
customAddress = `${data.record?.longitude}${data.record?.latitude}`;
//表单赋值
await setFieldsValue({
...data.record,
customAddress,
});
state.value = data.record;
} else {
state.value = {};
}
await clearValidate();
// 隐藏底部时禁用整个表单
await setProps({ disabled: !data?.showFooter });
});
function viewMap() {
openModal(true, {
record: { ...getFieldsValue() },
});
}
async function getPosition(val) {
let { pname, cityname, adname, address, name } = val.handleItem || '';
let nameList = [pname, cityname, adname, address, name];
let str = '';
nameList.map((item) => {
if (item !== undefined) {
str += item;
}
});
await setFieldsValue({
latitude: val.lat,
longitude: val.lng,
customAddress: `${val.lng}${val.lat}`,
address: str,
});
state.value = {
...state.value,
latitude: val.lat,
longitude: val.lng,
};
}
//表单提交事件
async function handleSubmit() {
try {
let values = await validate();
setDrawerProps({ confirmLoading: true });
const params = {
...state.value,
...values,
};
//提交表单
await saveOrUpdate(params, isUpdate.value);
//关闭弹窗
closeDrawer();
//刷新列表
emit('success');
} finally {
setDrawerProps({ confirmLoading: false });
}
}
</script>
<style lang="less" scoped>
/** 时间和数字输入框样式 */
:deep(.ant-input-number) {
width: 100%;
}
:deep(.ant-calendar-picker) {
width: 100%;
}
</style>