411 lines
18 KiB
JavaScript
Raw Normal View History

2026-01-22 15:54:15 +08:00
import dayjs from 'dayjs';
const DB_KEY = 'ykt_case_archive_detail_mockdb_v1';
export const VISIT_RECORD_TEMPLATES = [
{
templateType: 'outpatient',
templateName: '门诊记录',
templateList: [
2026-01-22 17:39:23 +08:00
{ title: 'visitTime', name: '就诊日期', type: 'date', operateType: 'formCell', required: true, format: 'YYYY-MM-DD' },
{ title: 'corpName', name: '就诊机构', type: 'input', operateType: 'formCell', required: false, wordLimit: 30, inputType: 'text' },
{ title: 'deptName', name: '科室', type: 'input', operateType: 'formCell', required: false, wordLimit: 30, inputType: 'text' },
{ title: 'doctor', name: '医生', type: 'input', operateType: 'formCell', required: false, wordLimit: 30, inputType: 'text' },
{ title: 'diagnosisName', name: '门诊诊断', type: 'textarea', operateType: 'formCell', required: false, wordLimit: 200 },
{ title: 'treatmentPlan', name: '治疗方案', type: 'textarea', operateType: 'formCell', required: false, wordLimit: 1000 },
{ title: 'disposePlan', name: '处置计划', type: 'textarea', operateType: 'formCell', required: false, wordLimit: 1000 },
{ title: 'summary', name: '备注/摘要', type: 'textarea', operateType: 'formCell', required: false, wordLimit: 200 },
{ title: 'files', name: '文件上传', type: 'files', required: false },
2026-01-22 15:54:15 +08:00
],
},
{
templateType: 'inhospital',
templateName: '住院记录',
templateList: [
2026-01-22 17:39:23 +08:00
{ title: 'inhosDate', name: '入院日期', type: 'date', operateType: 'formCell', required: true, format: 'YYYY-MM-DD' },
{ title: 'corpName', name: '住院机构', type: 'input', operateType: 'formCell', required: false, wordLimit: 30, inputType: 'text' },
{ title: 'diagnosisName', name: '入院诊断', type: 'textarea', operateType: 'formCell', required: false, wordLimit: 200 },
{ title: 'surgeryName', name: '手术名称', type: 'input', operateType: 'formCell', required: false, wordLimit: 50, inputType: 'text' },
{ title: 'summary', name: '摘要', type: 'textarea', operateType: 'formCell', required: false, wordLimit: 200 },
{ title: 'files', name: '文件上传', type: 'files', required: false },
],
},
{
templateType: 'preConsultation',
templateName: '预问诊记录',
templateList: [
{ title: 'consultDate', name: '问诊日期', type: 'date', operateType: 'formCell', required: true, format: 'YYYY-MM-DD' },
{ title: 'chiefComplaint', name: '主诉', type: 'textarea', operateType: 'formCell', required: false, wordLimit: 300 },
{ title: 'presentIllness', name: '现病史', type: 'textarea', operateType: 'formCell', required: false, wordLimit: 800 },
{ title: 'pastHistory', name: '既往史', type: 'textarea', operateType: 'formCell', required: false, wordLimit: 800 },
{ title: 'allergyHistory', name: '过敏史', type: 'textarea', operateType: 'formCell', required: false, wordLimit: 300 },
{ title: 'summary', name: '摘要', type: 'textarea', operateType: 'formCell', required: false, wordLimit: 200 },
{ title: 'files', name: '文件上传', type: 'files', required: false },
2026-01-22 15:54:15 +08:00
],
},
{
templateType: 'physicalExaminationTemplate',
templateName: '体检记录',
templateList: [
2026-01-22 17:39:23 +08:00
{ title: 'inspectDate', name: '体检日期', type: 'date', operateType: 'formCell', required: true, format: 'YYYY-MM-DD' },
{ title: 'corpName', name: '体检机构', type: 'input', operateType: 'formCell', required: false, wordLimit: 30, inputType: 'text' },
{ title: 'inspectPakageName', name: '体检套餐', type: 'input', operateType: 'formCell', required: false, wordLimit: 50, inputType: 'text' },
{ title: 'positiveFind', name: '阳性发现', type: 'textarea', operateType: 'formCell', required: false, wordLimit: 300 },
{ title: 'summary', name: '摘要', type: 'textarea', operateType: 'formCell', required: false, wordLimit: 200 },
{ title: 'files', name: '文件上传', type: 'files', required: false },
2026-01-22 15:54:15 +08:00
],
},
];
export function getVisitRecordTemplates() {
return VISIT_RECORD_TEMPLATES.map((i) => ({ templateType: i.templateType, name: i.templateName, templateList: i.templateList }));
}
export function getVisitRecordTemplate(templateType) {
return VISIT_RECORD_TEMPLATES.find((i) => i.templateType === templateType) || null;
}
function safeParse(json) {
try {
return JSON.parse(json);
} catch {
return null;
}
}
function getDb() {
const raw = uni.getStorageSync(DB_KEY);
const db = raw && typeof raw === 'string' ? safeParse(raw) : raw;
const next = db && typeof db === 'object' ? db : {};
next.visitRecordsByArchiveId = next.visitRecordsByArchiveId || {};
next.serviceRecordsByArchiveId = next.serviceRecordsByArchiveId || {};
next.followupsByArchiveId = next.followupsByArchiveId || {};
return next;
}
function setDb(db) {
uni.setStorageSync(DB_KEY, JSON.stringify(db));
}
function uid(prefix) {
return `${prefix}_${Date.now()}_${Math.random().toString(16).slice(2)}`;
}
export function ensureSeed(archiveId, archive) {
if (!archiveId) return;
const db = getDb();
if (!Array.isArray(db.visitRecordsByArchiveId[archiveId]) || db.visitRecordsByArchiveId[archiveId].length === 0) {
const now = Date.now();
db.visitRecordsByArchiveId[archiveId] = [
{
_id: uid('mr'),
medicalType: 'outpatient',
tempName: '门诊记录',
templateType: 'outpatient',
2026-01-22 17:39:23 +08:00
teamId: 'team_1',
2026-01-22 15:54:15 +08:00
sortTime: now - 1000 * 60 * 60 * 24 * 2,
visitTime: dayjs(now - 1000 * 60 * 60 * 24 * 2).format('YYYY-MM-DD'),
corpName: '某某医院',
2026-01-22 17:39:23 +08:00
deptName: '呼吸内科',
2026-01-22 15:54:15 +08:00
doctor: '李医生',
2026-01-22 17:39:23 +08:00
diagnosisName: '急性上呼吸道感染mock',
treatmentPlan: '建议1对症处理退热2多饮水休息3如出现呼吸困难及时就医。',
disposePlan: '建议1继续对症治疗2监测体温与血压3如3天无缓解或加重立即复诊。',
summary: '初诊:对症处理并随访。',
files: [{ url: '/static/tabbar/home.png', name: '示例图片1' }],
2026-01-22 15:54:15 +08:00
createTime: now - 1000 * 60 * 60 * 24 * 2,
2026-01-22 17:39:23 +08:00
creatorName: '李珊珊',
2026-01-22 15:54:15 +08:00
},
{
_id: uid('mr'),
medicalType: 'inhospital',
tempName: '住院记录',
templateType: 'inhospital',
2026-01-22 17:39:23 +08:00
teamId: 'team_2',
2026-01-22 15:54:15 +08:00
sortTime: now - 1000 * 60 * 60 * 24 * 15,
2026-01-22 17:39:23 +08:00
inhosDate: dayjs(now - 1000 * 60 * 60 * 24 * 15).format('YYYY-MM-DD'),
2026-01-22 15:54:15 +08:00
corpName: '某某医院',
diagnosisName: '术后复查mock',
2026-01-22 17:39:23 +08:00
surgeryName: '阑尾切除术',
2026-01-22 15:54:15 +08:00
summary: '复诊:术后复查,恢复良好。',
2026-01-22 17:39:23 +08:00
files: [],
2026-01-22 15:54:15 +08:00
createTime: now - 1000 * 60 * 60 * 24 * 15,
creatorName: '王护士',
},
2026-01-22 17:39:23 +08:00
{
_id: uid('mr'),
medicalType: 'preConsultation',
tempName: '预问诊记录',
templateType: 'preConsultation',
teamId: 'team_1',
sortTime: now - 1000 * 60 * 60 * 6,
consultDate: dayjs(now - 1000 * 60 * 60 * 6).format('YYYY-MM-DD'),
chiefComplaint: '咽痛、流涕 2 天mock',
presentIllness: '近2天受凉后出现咽痛、流涕体温最高 38.2℃。',
pastHistory: '既往体健。',
allergyHistory: '无明确过敏史。',
summary: '建议对症处理,必要时线下就医。',
files: [],
createTime: now - 1000 * 60 * 60 * 6,
creatorName: '李珊珊',
},
2026-01-22 15:54:15 +08:00
];
}
if (!Array.isArray(db.serviceRecordsByArchiveId[archiveId]) || db.serviceRecordsByArchiveId[archiveId].length === 0) {
const now = Date.now();
db.serviceRecordsByArchiveId[archiveId] = Array.from({ length: 18 }).map((_, idx) => {
const eventType =
idx % 5 === 0 ? 'questionnaire' : idx % 4 === 0 ? 'article' : idx % 3 === 0 ? 'sms' : 'phone';
const executionTime = now - 1000 * 60 * 60 * (idx * 6 + 3);
const executeTeamId = idx % 2 === 0 ? 'team_1' : 'team_2';
const executeTeamName = executeTeamId === 'team_1' ? '口腔一科(示例)' : '正畸团队(示例)';
return {
_id: uid('sr'),
eventType,
taskContent: `服务内容示例 #${idx + 1}:这里是任务描述,支持长文本展开收起。`,
result: idx % 7 === 0 ? '已联系患者,已确认到院时间。' : '',
executorName: idx % 2 === 0 ? '李医生' : '王护士',
executeTeamId,
executeTeamName,
executionTime,
pannedEventSendFile:
eventType === 'article'
? { type: 'article', url: 'https://example.com/article/1' }
: eventType === 'questionnaire'
? { type: 'questionnaire', surveryId: 'q_1' }
: null,
archiveName: archive?.name || '',
};
});
}
if (!Array.isArray(db.followupsByArchiveId[archiveId]) || db.followupsByArchiveId[archiveId].length === 0) {
const now = Date.now();
db.followupsByArchiveId[archiveId] = Array.from({ length: 22 }).map((_, idx) => {
const plannedExecutionTime = now + 1000 * 60 * 60 * 24 * ((idx % 9) - 2);
const createTime = now - 1000 * 60 * 60 * (idx * 5 + 2);
const statusPool = ['processing', 'notStart', 'treated', 'cancelled', 'expired'];
const status = statusPool[idx % statusPool.length];
const eventTypePool = ['followup', 'revisit', 'questionnaire', 'other'];
const eventType = eventTypePool[idx % eventTypePool.length];
const executeTeamId = idx % 2 === 0 ? 'team_1' : 'team_2';
const executeTeamName = executeTeamId === 'team_1' ? '口腔一科(示例)' : '正畸团队(示例)';
return {
_id: uid('td'),
plannedExecutionTime,
planDate: dayjs(plannedExecutionTime).format('YYYY-MM-DD'),
createTime,
createTimeStr: dayjs(createTime).format('YYYY-MM-DD HH:mm'),
executorName: idx % 2 === 0 ? '李医生' : '王护士',
executeTeamId,
executeTeamName,
creatorName: idx % 3 === 0 ? '系统' : '管理员A',
status,
eventType,
eventTypeLabel:
eventType === 'followup' ? '回访' : eventType === 'revisit' ? '复诊提醒' : eventType === 'questionnaire' ? '问卷' : '其他',
eventStatusLabel:
status === 'processing'
? '待处理'
: status === 'notStart'
? '未开始'
: status === 'treated'
? '已完成'
: status === 'cancelled'
? '已取消'
: '已过期',
taskContent: `回访任务示例 #${idx + 1}:电话回访/提醒到院等。`,
result: status === 'treated' ? '已完成回访,患者反馈良好。' : '',
archiveName: archive?.name || '',
};
});
}
setDb(db);
}
2026-01-22 17:39:23 +08:00
export function getCurrentTeamId() {
const v = uni.getStorageSync('ykt_mock_current_team_id');
return v ? String(v) : 'team_1';
}
function getSortTimeTitle(templateType) {
if (templateType === 'outpatient') return 'visitTime';
if (templateType === 'inhospital') return 'inhosDate';
if (templateType === 'preConsultation') return 'consultDate';
if (templateType === 'physicalExaminationTemplate') return 'inspectDate';
return '';
}
export function queryVisitRecords({ archiveId, medicalType = 'ALL', timeRange = 'ALL', teamId = '', shareAllTeams = false }) {
2026-01-22 15:54:15 +08:00
const db = getDb();
const list = Array.isArray(db.visitRecordsByArchiveId[archiveId]) ? db.visitRecordsByArchiveId[archiveId] : [];
2026-01-22 17:39:23 +08:00
const withDate = list.map((i) => {
const type = i.templateType || i.medicalType || '';
const timeTitle = getSortTimeTitle(type);
const rawDate = timeTitle ? i[timeTitle] : '';
const fallback = i.sortTime ? dayjs(i.sortTime).format('YYYY-MM-DD') : '';
const date = rawDate || fallback;
return {
...i,
dateStr: date ? String(date) : '',
date: date ? String(date) : '',
createDateStr: i.createTime ? dayjs(i.createTime).format('YYYY-MM-DD') : '',
};
});
let filtered = [...withDate];
if (medicalType !== 'ALL') filtered = filtered.filter((i) => (i.medicalType || i.templateType) === medicalType);
if (!shareAllTeams && teamId) filtered = filtered.filter((i) => !i.teamId || i.teamId === teamId);
if (timeRange && timeRange !== 'ALL') {
const days = timeRange === 'today' ? 0 : timeRange === '7d' ? 7 : timeRange === '30d' ? 30 : null;
if (days !== null) {
const start = days === 0 ? dayjs().startOf('day') : dayjs().subtract(days, 'day').startOf('day');
const startMs = start.valueOf();
filtered = filtered.filter((i) => (i.sortTime || 0) >= startMs);
}
}
2026-01-22 15:54:15 +08:00
2026-01-22 17:39:23 +08:00
filtered.sort((a, b) => (b.sortTime || 0) - (a.sortTime || 0));
return filtered;
2026-01-22 15:54:15 +08:00
}
export function getVisitRecord({ archiveId, id }) {
const db = getDb();
const list = Array.isArray(db.visitRecordsByArchiveId[archiveId]) ? db.visitRecordsByArchiveId[archiveId] : [];
return list.find((i) => i._id === id) || null;
}
export function upsertVisitRecord({ archiveId, record }) {
const db = getDb();
const list = Array.isArray(db.visitRecordsByArchiveId[archiveId]) ? db.visitRecordsByArchiveId[archiveId] : [];
const next = { ...record };
if (!next._id) next._id = uid('mr');
if (!next.sortTime) next.sortTime = Date.now();
if (!next.createTime) next.createTime = Date.now();
const idx = list.findIndex((i) => i._id === next._id);
if (idx >= 0) list[idx] = { ...list[idx], ...next };
else list.unshift(next);
db.visitRecordsByArchiveId[archiveId] = list;
setDb(db);
return next;
}
export function removeVisitRecord({ archiveId, id }) {
const db = getDb();
const list = Array.isArray(db.visitRecordsByArchiveId[archiveId]) ? db.visitRecordsByArchiveId[archiveId] : [];
db.visitRecordsByArchiveId[archiveId] = list.filter((i) => i._id !== id);
setDb(db);
}
export function queryServiceRecords({ archiveId, page = 1, pageSize = 10, eventType = 'ALL', teamId = 'ALL', dateRange = [] }) {
const db = getDb();
const list = Array.isArray(db.serviceRecordsByArchiveId[archiveId]) ? db.serviceRecordsByArchiveId[archiveId] : [];
let filtered = [...list];
if (eventType !== 'ALL') filtered = filtered.filter((i) => i.eventType === eventType);
if (teamId !== 'ALL') filtered = filtered.filter((i) => i.executeTeamId === teamId);
if (Array.isArray(dateRange) && dateRange.length === 2 && dateRange[0] && dateRange[1]) {
filtered = filtered.filter((i) => {
const d = i.executionTime ? dayjs(i.executionTime).format('YYYY-MM-DD') : '';
return d >= dateRange[0] && d <= dateRange[1];
});
}
filtered.sort((a, b) => (b.executionTime || 0) - (a.executionTime || 0));
const total = filtered.length;
const pages = Math.ceil(total / pageSize) || 1;
const start = (page - 1) * pageSize;
const slice = filtered.slice(start, start + pageSize);
return { list: slice, total, pages };
}
export function getServiceRecord({ archiveId, id }) {
const db = getDb();
const list = Array.isArray(db.serviceRecordsByArchiveId[archiveId]) ? db.serviceRecordsByArchiveId[archiveId] : [];
return list.find((i) => i._id === id) || null;
}
export function upsertServiceRecord({ archiveId, record }) {
const db = getDb();
const list = Array.isArray(db.serviceRecordsByArchiveId[archiveId]) ? db.serviceRecordsByArchiveId[archiveId] : [];
const next = { ...record };
if (!next._id) next._id = uid('sr');
if (!next.executionTime) next.executionTime = Date.now();
const idx = list.findIndex((i) => i._id === next._id);
if (idx >= 0) list[idx] = { ...list[idx], ...next };
else list.unshift(next);
db.serviceRecordsByArchiveId[archiveId] = list;
setDb(db);
return next;
}
export function removeServiceRecord({ archiveId, id }) {
const db = getDb();
const list = Array.isArray(db.serviceRecordsByArchiveId[archiveId]) ? db.serviceRecordsByArchiveId[archiveId] : [];
db.serviceRecordsByArchiveId[archiveId] = list.filter((i) => i._id !== id);
setDb(db);
}
export function queryFollowups({ archiveId, page = 1, pageSize = 10, status = 'all', isMy = false, eventTypes = [], teamId = 'ALL', planRange = ['', ''] }) {
const db = getDb();
const list = Array.isArray(db.followupsByArchiveId[archiveId]) ? db.followupsByArchiveId[archiveId] : [];
let filtered = [...list];
if (status !== 'all') filtered = filtered.filter((i) => i.status === status);
if (isMy) filtered = filtered.filter((i) => i.executorName === '李医生');
if (Array.isArray(eventTypes) && eventTypes.length) filtered = filtered.filter((i) => eventTypes.includes(i.eventType));
if (teamId !== 'ALL') filtered = filtered.filter((i) => i.executeTeamId === teamId);
if (planRange && (planRange[0] || planRange[1])) {
if (planRange[0]) filtered = filtered.filter((i) => i.planDate >= planRange[0]);
if (planRange[1]) filtered = filtered.filter((i) => i.planDate <= planRange[1]);
}
filtered.sort((a, b) => (b.plannedExecutionTime || 0) - (a.plannedExecutionTime || 0));
const total = filtered.length;
const pages = Math.ceil(total / pageSize) || 1;
const start = (page - 1) * pageSize;
const slice = filtered.slice(start, start + pageSize);
return { list: slice, total, pages };
}
export function getFollowup({ archiveId, id }) {
const db = getDb();
const list = Array.isArray(db.followupsByArchiveId[archiveId]) ? db.followupsByArchiveId[archiveId] : [];
return list.find((i) => i._id === id) || null;
}
export function upsertFollowup({ archiveId, followup }) {
const db = getDb();
const list = Array.isArray(db.followupsByArchiveId[archiveId]) ? db.followupsByArchiveId[archiveId] : [];
const next = { ...followup };
if (!next._id) next._id = uid('td');
if (!next.plannedExecutionTime) next.plannedExecutionTime = Date.now();
next.planDate = dayjs(next.plannedExecutionTime).format('YYYY-MM-DD');
if (!next.createTime) next.createTime = Date.now();
next.createTimeStr = dayjs(next.createTime).format('YYYY-MM-DD HH:mm');
const idx = list.findIndex((i) => i._id === next._id);
if (idx >= 0) list[idx] = { ...list[idx], ...next };
else list.unshift(next);
db.followupsByArchiveId[archiveId] = list;
setDb(db);
return next;
}
export function removeFollowup({ archiveId, id }) {
const db = getDb();
const list = Array.isArray(db.followupsByArchiveId[archiveId]) ? db.followupsByArchiveId[archiveId] : [];
db.followupsByArchiveId[archiveId] = list.filter((i) => i._id !== id);
setDb(db);
}