import dayjs from 'dayjs'; const DB_KEY = 'ykt_case_archive_detail_mockdb_v1'; export const VISIT_RECORD_TEMPLATES = [ { templateType: 'outpatient', templateName: '门诊记录', templateList: [ { title: 'visitTime', name: '就诊日期', type: 'date', required: true, format: 'YYYY-MM-DD' }, { title: 'corpName', name: '就诊机构', type: 'input', required: false, wordLimit: 30, inputType: 'text' }, { title: 'deptName', name: '科室', type: 'input', required: false, wordLimit: 30, inputType: 'text' }, { title: 'doctor', name: '医生', type: 'input', required: false, wordLimit: 30, inputType: 'text' }, { title: 'diagnosisName', name: '诊断', type: 'textarea', required: false, wordLimit: 200 }, { title: 'summary', name: '摘要', type: 'textarea', required: false, wordLimit: 200 }, ], }, { templateType: 'inhospital', templateName: '住院记录', templateList: [ { title: 'inhospitalDate', name: '入院日期', type: 'date', required: true, format: 'YYYY-MM-DD' }, { title: 'corpName', name: '住院机构', type: 'input', required: false, wordLimit: 30, inputType: 'text' }, { title: 'diagnosisName', name: '诊断', type: 'textarea', required: false, wordLimit: 200 }, { title: 'summary', name: '摘要', type: 'textarea', required: false, wordLimit: 200 }, ], }, { templateType: 'physicalExaminationTemplate', templateName: '体检记录', templateList: [ { title: 'inspectDate', name: '体检日期', type: 'date', required: true, format: 'YYYY-MM-DD' }, { title: 'corpName', name: '体检机构', type: 'input', required: false, wordLimit: 30, inputType: 'text' }, { title: 'inspectPakageName', name: '体检套餐', type: 'input', required: false, wordLimit: 50, inputType: 'text' }, { title: 'positiveFind', name: '阳性发现', type: 'textarea', required: false, wordLimit: 300 }, { title: 'summary', name: '摘要', type: 'textarea', required: false, wordLimit: 200 }, ], }, ]; 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', sortTime: now - 1000 * 60 * 60 * 24 * 2, visitTime: dayjs(now - 1000 * 60 * 60 * 24 * 2).format('YYYY-MM-DD'), corpName: '某某医院', deptName: '口腔科', doctor: '李医生', diagnosisName: '牙列不齐(mock)', summary: '初诊:拍片、取模,制定治疗方案。', createTime: now - 1000 * 60 * 60 * 24 * 2, creatorName: '李医生', }, { _id: uid('mr'), medicalType: 'inhospital', tempName: '住院记录', templateType: 'inhospital', sortTime: now - 1000 * 60 * 60 * 24 * 15, inhospitalDate: dayjs(now - 1000 * 60 * 60 * 24 * 15).format('YYYY-MM-DD'), corpName: '某某医院', diagnosisName: '术后复查(mock)', summary: '复诊:术后复查,恢复良好。', createTime: now - 1000 * 60 * 60 * 24 * 15, creatorName: '王护士', }, ]; } 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); } export function queryVisitRecords({ archiveId, medicalType = 'ALL', date = '' }) { const db = getDb(); const list = Array.isArray(db.visitRecordsByArchiveId[archiveId]) ? db.visitRecordsByArchiveId[archiveId] : []; const withDate = list.map((i) => ({ ...i, dateStr: i.sortTime ? dayjs(i.sortTime).format('YYYY-MM-DD') : '', })); const matchType = medicalType === 'ALL' ? withDate : withDate.filter((i) => i.medicalType === medicalType); const matchDate = date ? matchType.filter((i) => i.dateStr === date) : matchType; return matchDate.sort((a, b) => (b.sortTime || 0) - (a.sortTime || 0)); } 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); }