import * as api from './api';
import { dict, UserPageQuery, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, EditReq, AddReq } from '@fast-crud/fast-crud';
import { errorMessage, successMessage } from '/@/utils';
import { ElMessageBox } from 'element-plus';
import { CommonResult, EnumInquiryFormTplStatus, LabelValue, PageResult, Questionnaire, QuestionnaireQuery } from '/@/models';
import { debounce } from 'lodash-es';
import { SciencePopularization, SciencePopularizationQuery } from '/@/views/basic/education/types';
import { ref } from 'vue';
import {
EnumContentType,
EnumPeriodicType,
EnumRemindScene,
EnumRemindTimeType,
EnumWeekDay,
SchemeReminder,
SchemeReminderQuery,
SchemeReminderUpdate,
} from '../type';
import { computed } from '@vue/reactivity';
import { useRoute } from 'vue-router';
export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const route = useRoute();
/** 添加的lock */
const addLock = ref<boolean>(false);
const pageRequest = async (query: UserPageQuery) => {
if (!query.disease_process) return;
return await api.GetList(query);
};
const editRequest = async ({ form, row }: EditReq) => {
form.uuid = row.uuid;
form.science = form.science && typeof form.science === 'object' ? form.science.value : form.science;
form.inquiry_template = form.inquiry_template && typeof form.inquiry_template === 'object' ? form.inquiry_template.value : form.inquiry_template;
return await api.UpdateObj(form);
};
const delRequest = async ({ row }: EditReq) => {
row.is_deleted = true;
row.science = row.science && typeof row.science === 'object' ? row.science.value : row.science;
row.inquiry_template = row.inquiry_template && typeof row.inquiry_template === 'object' ? row.inquiry_template.value : row.inquiry_template;
return await api.UpdateObj(row);
};
const addRequest = async ({ form }: AddReq) => {
if (addLock.value) return;
addLock.value = true;
form.disease_process = route.query.diseaseProcess ?? '';
if (!form.disease_process) {
errorMessage('新建任务失败');
addLock.value = false;
return;
}
try {
const res = await api.AddObj(form);
return res;
} catch (error) {
addLock.value = false;
}
};
function useSearchRemote() {
let lastFetchId = 0;
const state = {
data: ref<LabelValue<string>[]>([]),
loading: ref(false),
};
// type 1:患教科普 2:随访问卷
const fetchUser = debounce(async (value: string, type: number) => {
lastFetchId += 1;
const fetchId = lastFetchId;
state.data.value = [];
state.loading.value = true;
let url: string = '';
switch (type) {
case 1:
url = '/api/knowledge/science-popularization-library/manage/';
break;
case 2:
url = '/api/questionnaire/management/inquiry-templates/';
break;
default:
break;
}
const params: Partial<SciencePopularizationQuery | QuestionnaireQuery> = {
title: value.trim(),
limit: 50,
};
if (type == 1) params.is_active = true;
if (type == 2) params.status = EnumInquiryFormTplStatus.PUBLISHED;
const res = await api.fetchEducationQuestionnaire(url, params as SciencePopularizationQuery | QuestionnaireQuery);
if (fetchId !== lastFetchId) {
return;
}
state.data.value = res.map((item: SciencePopularization | Questionnaire) => ({
label: item.title,
value: item.uuid,
}));
state.loading.value = false;
}, 800);
return {
state,
fetchUser,
};
}
// 使用远程搜索函数
const { state: educationState, fetchUser: fetchEducation } = useSearchRemote();
const { state: questionnaireState, fetchUser: fetchQuestionnaire } = useSearchRemote();
/** 处理具体时间时分显示 */
const handleHHMM = computed(() => (form: SchemeReminderUpdate, trueData: string | number, falseData: string | number) => {
return form.remind_time_type == EnumRemindTimeType.periodic && form.periodic_type == EnumPeriodicType.daily ? trueData : falseData;
});
return {
crudOptions: {
request: {
pageRequest,
addRequest,
editRequest,
delRequest,
// pageRequest请求参数转换
transformQuery: ({ page, form }) => {
const limit = page?.pageSize || 10;
const currentPage = page?.currentPage || 1;
form.name_or_mobile = form.mobile;
// 删除框架产生的字段
delete form.mobile;
delete form.dispatch_time;
const query: SchemeReminderQuery = {
offset: (currentPage - 1) * limit,
limit,
...form,
disease_process: route.query.diseaseProcess ?? '',
};
return query;
},
// pageRequest请求结果转换
transformRes: ({ res, query }) => {
//将后端返回的结果,改造成fs所需要的结构
const resData = res as CommonResult<PageResult<SchemeReminder[]>>;
if (resData.success) {
return {
records: resData.data.results.map((item) => ({
...item,
science: item.science
? {
value: item.science,
label: item.science_title,
}
: '',
inquiry_template: item.inquiry_template
? {
value: item.inquiry_template,
label: item.inquiry_template_title,
}
: '',
})),
currentPage: query.offset / query.limit + 1,
pageSize: query.limit,
total: resData.data.count,
};
} else {
return {
records: [],
currentPage: query.offset / query.limit + 1,
pageSize: query.limit,
total: 0,
};
}
},
},
search: {
autoSearch: false,
show: false,
},
actionbar: {
buttons: {
add: {
show: true,
},
},
},
toolbar: {
buttons: {
export: {
show: false,
},
search: {
show: false,
},
},
},
rowHandle: {
//固定右侧
fixed: 'right',
width: 200,
buttons: {
view: {
link: true,
type: 'primary',
show: false,
},
edit: {
link: true,
type: 'primary',
show: true,
order: 1,
},
copyData: {
show: true,
link: true,
text: '复制',
type: 'primary',
order: 2,
click: ({ row }) => {
ElMessageBox.confirm('确认要复制此任务?', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}).then(async () => {
const res = await api.copyData(row.uuid);
if (res) {
successMessage('复制成功');
crudExpose.doRefresh();
} else {
errorMessage('复制失败');
}
});
},
},
remove: {
link: true,
type: 'primary',
show: true,
style: { color: '#F56C6C' },
order: 3,
},
},
},
table: {
rowKey: 'uuid',
remove: {
async confirmFn(context) {
await ElMessageBox.confirm(`删除后不可撤销,请谨慎操作!`, '确认要删除此任务?', {
distinguishCancelAndClose: true,
confirmButtonText: '确定',
cancelButtonText: '取消',
closeOnClickModal: false,
});
},
},
},
columns: {
_index: {
title: '序号',
form: { show: false },
column: {
// type: 'index',
align: 'left',
width: '70px',
columnSetDisabled: true, //禁止在列设置中选择
formatter: (context) => {
//计算序号,你可以自定义计算规则,此处为翻页累加
let index = context.index ?? 1;
let pagination = crudExpose!.crudBinding.value.pagination;
// @ts-ignore
return ((pagination.currentPage ?? 1) - 1) * pagination.pageSize + index + 1;
},
},
},
task_name: {
title: '任务名称',
type: ['text', 'colspan'],
search: {
show: false,
},
column: {
minWidth: 120,
align: 'left',
},
form: {
rules: [{ required: true, message: '请输入任务名称' }],
component: {
placeholder: '请输入任务名称',
minlength: 1,
maxlength: 20,
},
},
},
remind_scene: {
title: '提醒时机',
type: ['dict-select', 'colspan'],
search: {
show: false,
},
form: {
show: true,
title: '提醒时机',
value: EnumRemindScene.qcjh,
rules: [{ required: true, message: '请选择提醒时机' }],
},
column: {
minWidth: 100,
align: 'left',
formatter: ({ row }) => {
let label: string = '';
switch (row.remind_scene) {
case EnumRemindScene.qcjh:
label = '群创建后';
break;
case EnumRemindScene.sq:
label = '术前';
break;
case EnumRemindScene.zy:
label = '住院';
break;
case EnumRemindScene.ly:
label = `离院`;
break;
case EnumRemindScene.zczy:
label = `再次住院`;
break;
case EnumRemindScene.jtrq:
label = `具体日期`;
break;
default:
break;
}
return label;
},
},
dict: dict({
data: [
{ label: '群创建后', value: EnumRemindScene.qcjh },
{ label: '术前', value: EnumRemindScene.sq },
{ label: '住院', value: EnumRemindScene.zy },
{ label: '离院', value: EnumRemindScene.ly },
{ label: '再次住院', value: EnumRemindScene.zczy },
{ label: '具体日期', value: EnumRemindScene.jtrq },
],
}),
},
remind_time_type: {
title: '提醒时间',
type: ['dict-radio', 'colspan'],
search: {
show: false,
},
column: {
align: 'left',
minWidth: 180,
formatter: ({ row }) => {
if (row.remind_scene == EnumRemindScene.jtrq) return row.remind_time;
let label = '';
switch (row.remind_time_type) {
case EnumRemindTimeType.immediate:
label = '立即';
break;
case EnumRemindTimeType.periodic:
let periodicTypeStr: string = '';
switch (row.periodic_type) {
case EnumPeriodicType.daily:
periodicTypeStr = `每天`;
break;
case EnumPeriodicType.weekly:
let weekdayStr: string = '';
switch (row.weekday) {
case EnumWeekDay.monday:
weekdayStr = '周一';
break;
case EnumWeekDay.tuesday:
weekdayStr = '周二';
break;
case EnumWeekDay.wednesday:
weekdayStr = '周三';
break;
case EnumWeekDay.thursday:
weekdayStr = '周四';
break;
case EnumWeekDay.friday:
weekdayStr = '周五';
break;
case EnumWeekDay.saturday:
weekdayStr = '周六';
break;
case EnumWeekDay.sunday:
weekdayStr = '周日';
break;
}
periodicTypeStr = `每${weekdayStr}`;
break;
case EnumPeriodicType.monthly:
periodicTypeStr = `每月${row.day ?? ''}号`;
break;
}
label = `${periodicTypeStr} ${row.hh_mm ?? ''}(${row.expire_time?.slice(0, 11) ?? ''}截止)`;
break;
case EnumRemindTimeType.interval:
label = `${row.interval_days ?? ''}天后 ${row.hh_mm ?? ''}`;
break;
}
return label;
},
},
form: {
show: compute(({ form }) => {
if (form.remind_scene == EnumRemindScene.jtrq) form.remind_time_type = EnumRemindTimeType.immediate;
return form.remind_scene != EnumRemindScene.jtrq;
}),
title: '提醒时间',
value: EnumRemindTimeType.immediate,
rules: [{ required: true, message: '请选择提醒时间' }],
},
dict: dict({
data: [
{ label: '立即', value: EnumRemindTimeType.immediate },
{ label: '周期提醒', value: EnumRemindTimeType.periodic },
{ label: '间隔X天', value: EnumRemindTimeType.interval },
],
}),
},
remind_time: {
title: '提醒时间',
type: ['datetime', 'colspan'],
column: {
show: false,
},
form: {
show: compute(({ form }) => {
if (form.remind_scene != EnumRemindScene.jtrq) form.remind_time = null;
return form.remind_scene == EnumRemindScene.jtrq;
}),
rules: [{ required: true, message: '请选择提醒时间' }],
component: {
name: 'el-date-picker',
props: {
type: 'datetime',
placeholder: '请选择提醒时间',
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
},
},
},
},
periodic_type: {
title: '重复',
type: ['dict-radio', 'colspan'],
search: {
show: false,
},
column: {
show: false,
},
form: {
show: compute(({ form }) => {
if (form.remind_time_type != EnumRemindTimeType.periodic) form.periodic_type = EnumPeriodicType.daily;
return form.remind_time_type == EnumRemindTimeType.periodic;
}),
title: '重复',
value: EnumPeriodicType.daily,
rules: [{ required: true, message: '请选择重复' }],
},
dict: dict({
data: [
{ label: '每天', value: EnumPeriodicType.daily },
{ label: '每周', value: EnumPeriodicType.weekly },
{ label: '每月', value: EnumPeriodicType.monthly },
],
}),
},
weekday: {
title: '周几',
type: 'dict-select',
search: {
show: false,
},
column: {
show: false,
},
form: {
show: compute(({ form }) => {
if (form.periodic_type != EnumPeriodicType.weekly) form.weekday = null;
return form.periodic_type == EnumPeriodicType.weekly;
}),
title: '具体时间',
col: { span: 14 },
rules: [{ required: true, message: '请选择周几' }],
component: {
placeholder: '请选择周几',
},
},
dict: dict({
data: [
{ label: '周一', value: EnumWeekDay.monday },
{ label: '周二', value: EnumWeekDay.tuesday },
{ label: '周三', value: EnumWeekDay.wednesday },
{ label: '周四', value: EnumWeekDay.thursday },
{ label: '周五', value: EnumWeekDay.friday },
{ label: '周六', value: EnumWeekDay.saturday },
{ label: '周日', value: EnumWeekDay.sunday },
],
}),
},
day: {
title: '几号',
search: {
show: false,
},
type: 'number',
column: {
show: false,
},
form: {
show: compute(({ form }) => {
if (form.periodic_type != EnumPeriodicType.monthly) form.day = null;
return form.periodic_type == EnumPeriodicType.monthly;
}),
title: '具体时间',
col: { span: 14 },
rules: [{ required: true, message: '请输入几号' }],
component: {
name: 'el-input-number',
props: {
placeholder: '请输入几号',
min: 1,
max: 31,
step: 1,
precision: 0,
controls: false,
},
slots: {
suffix: () => '号',
},
},
},
},
interval_days: {
title: '几天后',
search: {
show: false,
},
type: 'number',
column: {
show: false,
},
form: {
show: compute(({ form }) => {
if (form.remind_time_type != EnumRemindTimeType.interval) form.interval_days = null;
return form.remind_time_type == EnumRemindTimeType.interval;
}),
title: '间隔',
col: { span: 14 },
rules: [{ required: true, message: '请输入几天后' }],
component: {
name: 'el-input-number',
props: {
placeholder: '请输入几天后',
min: 1,
max: 365,
step: 1,
precision: 0,
controls: false,
},
slots: {
suffix: () => '天后',
},
},
},
},
hh_mm: {
title: '具体时间',
type: 'time',
column: {
show: false,
},
form: {
show: compute(({ form }) => {
if (form.remind_time_type == EnumRemindTimeType.immediate) form.hh_mm = null;
return form.remind_time_type != EnumRemindTimeType.immediate;
}),
title: compute(({ form }) => {
return handleHHMM.value(form, '具体时间', '');
}),
labelWidth: compute(({ form }) => {
return handleHHMM.value(form, '120px', '0px');
}),
col: {
span: compute(({ form }) => {
return handleHHMM.value(form, 24, 10) as number;
}),
},
rules: [{ required: true, message: '请选择具体时间' }],
component: {
name: 'el-time-picker',
props: {
placeholder: '请选择具体时间',
format: 'HH:mm',
valueFormat: 'HH:mm',
},
},
class: compute(({ form }) => {
return handleHHMM.value(form, '', 'mdd-hide-required-asterisk');
}),
},
},
expire_time: {
title: '截止日期',
type: ['date', 'colspan'],
column: {
show: false,
},
form: {
show: compute(({ form }) => {
if (form.remind_time_type != EnumRemindTimeType.periodic) form.expire_time = null;
return form.remind_time_type == EnumRemindTimeType.periodic;
}),
rules: [{ required: true, message: '请选择截止日期' }],
component: {
name: 'el-date-picker',
props: {
type: 'date',
placeholder: '请选择截止日期',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
},
},
valueChange({ form }) {
// 传给后端时加上 23:59:59
if (form.expire_time && form.expire_time?.length == 10) form.expire_time += ' 23:59:59';
},
},
},
content_type: {
title: '发送内容',
type: ['dict-radio', 'colspan'],
search: {
show: false,
},
column: {
align: 'left',
minWidth: 180,
formatter: ({ row }) => {
let label: string = '';
switch (row.content_type) {
case EnumContentType.science:
return '患教:' + (row.science_title ? `《${row.science_title}》` : '');
case EnumContentType.ques_paper:
return '问卷:' + (row.inquiry_template_title ? `《${row.inquiry_template_title}》` : '');
case EnumContentType.txt:
label = `文字:${row.content_txt ?? ''}`;
break;
case EnumContentType.sms:
label = `短信:您有一条病程管理提醒,请注意:${row.content_sms ?? ''}`;
break;
default:
break;
}
const slots = {
content: () => <>{label}</>,
};
return (
<el-tooltip placement="top" popper-class="mdd-tooltip" v-slots={slots}>
<div class="mdd-line-clamp-1">{label}</div>;
</el-tooltip>
);
},
},
form: {
show: true,
title: '发送内容',
value: EnumContentType.science,
rules: [{ required: true, message: '请选择发送内容' }],
},
dict: dict({
data: [
{ label: '患教', value: EnumContentType.science },
{ label: '问卷', value: EnumContentType.ques_paper },
{ label: '文字', value: EnumContentType.txt },
{ label: '短信', value: EnumContentType.sms },
],
}),
},
science: {
title: '患教科普',
search: {
show: false,
},
type: ['dict-select', 'colspan'],
column: {
show: false,
},
form: {
show: compute(({ form }) => {
if (form.content_type != EnumContentType.science) form.science = null;
return form.content_type == EnumContentType.science;
}),
title: '',
rules: [{ required: true, message: '搜索并选择患教' }],
component: {
name: 'fs-dict-select',
placeholder: '搜索并选择患教',
filterable: true,
remote: true,
'reserve-keyword': false,
remoteMethod: (query: string) => {
if (query !== '') {
fetchEducation(query, 1);
} else {
educationState.data.value = [];
}
},
loading: educationState.loading,
options: educationState.data,
},
class: 'mdd-hide-required-asterisk',
helper: '任务触发时,以群主身份发送患教科普的卡片',
},
},
inquiry_template: {
title: '随访问卷',
search: {
show: false,
},
type: ['dict-select', 'colspan'],
column: {
show: false,
},
form: {
show: compute(({ form }) => {
if (form.content_type != EnumContentType.ques_paper) form.inquiry_template = null;
return form.content_type == EnumContentType.ques_paper;
}),
title: '',
rules: [{ required: true, message: '搜索并选择随访问卷' }],
component: {
name: 'fs-dict-select',
placeholder: '搜索并选择随访问卷',
filterable: true,
remote: true,
'reserve-keyword': false,
remoteMethod: (query: string) => {
if (query !== '') {
fetchQuestionnaire(query, 2);
} else {
questionnaireState.data.value = [];
}
},
loading: questionnaireState.loading,
options: questionnaireState.data,
},
class: 'mdd-hide-required-asterisk',
helper: '任务触发时,以群主身份发送随访问卷的卡片',
},
},
content_txt: {
title: '文字',
type: ['textarea', 'colspan'],
search: {
show: false,
},
column: {
show: false,
},
form: {
show: compute(({ form }) => {
if (form.content_type != EnumContentType.txt) form.content_txt = null;
return form.content_type == EnumContentType.txt;
}),
title: '',
rules: [{ required: true, message: '输入提醒的文字' }],
component: {
placeholder: '输入提醒的文字',
minlength: 1,
maxlength: 200,
},
class: 'mdd-hide-required-asterisk',
helper: '任务触发时,以群主身份发送文字消息',
},
},
content_sms: {
title: '短信',
type: ['text', 'colspan'],
search: {
show: false,
},
column: {
show: false,
},
form: {
show: compute(({ form }) => {
if (form.content_type != EnumContentType.sms) form.content_sms = null;
return form.content_type == EnumContentType.sms;
}),
title: '',
rules: [
{ required: true, message: '输入提醒的文本' },
{
validator: (_, value, callback) => {
if (!value) {
callback(new Error('输入提醒的文本'));
return;
}
// 计算字符长度
let charCount: number = 0;
for (let i: number = 0; i < value.length; i++) {
const charCode = value.charCodeAt(i);
// 判断是否为全角字符(汉字、全角标点等)
if (
(charCode >= 0x4e00 && charCode <= 0x9fa5) || // 中文汉字
(charCode >= 0xff00 && charCode <= 0xffef) || // 全角标点符号
(charCode >= 0x3000 && charCode <= 0x303f) // 中文标点符号
) {
charCount += 2; // 全角字符算2个字符
} else {
charCount += 1; // 半角字符算1个字符
}
}
// 校验字符长度
if (charCount < 1 || charCount > 35) {
callback(new Error(`短信内容长度必须在1到35个字符之间,当前${charCount}个字符`));
} else {
callback();
}
},
},
],
component: {
placeholder: '输入提醒的文本',
minlength: 1,
maxlength: 35,
},
class: 'mdd-hide-required-asterisk',
helper: ' 注:字数不超过35个字符(约17个汉字)。 任务触发时,发送短信。',
},
},
is_active: {
title: '状态',
search: {
show: false,
},
type: 'dict-radio',
column: {
minWidth: 90,
align: 'left',
component: {
name: 'fs-dict-switch',
activeText: '',
inactiveText: '',
style: '--el-switch-on-color: var(--el-color-primary); --el-switch-off-color: #dcdfe6',
onChange: compute((context) => {
return () => {
const form = JSON.parse(JSON.stringify(context.row));
form.science = form.science && typeof form.science === 'object' ? form.science.value : form.science;
form.inquiry_template =
form.inquiry_template && typeof form.inquiry_template === 'object' ? form.inquiry_template.value : form.inquiry_template;
api.UpdateObj(form).then((res: APIResponseData) => {
successMessage(res.msg as string);
});
};
}),
},
},
form: {
show: false,
},
dict: dict({
data: [
{ label: '启用', value: true },
{ label: '禁用', value: false },
],
}),
},
},
form: {
wrapper: {
width: '560px',
},
},
editForm: {
wrapper: {
title: '编辑任务',
},
},
addForm: {
wrapper: {
title: '新建任务',
buttons: {
ok: {
loading: addLock,
},
},
onOpened: () => {
addLock.value = false;
},
onClosed: () => {
addLock.value = false;
},
},
},
},
};
};
05-06
444

03-25
392

02-06
374

04-22
212
