|
@@ -10,16 +10,29 @@ import request from '@/config/axios'
|
|
|
|
|
|
|
|
// ==================== 枚举 ====================
|
|
// ==================== 枚举 ====================
|
|
|
|
|
|
|
|
-/** 出院原因 */
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * 出院原因
|
|
|
|
|
+ * 与「退住原因」字典 back_cause_arr 合并(全部项),键值与字典一致:
|
|
|
|
|
+ * 1 正常退住 2 死亡退住 3 转院退住 4 试住结束
|
|
|
|
|
+ * 5 居家照护 6 医院就诊 7 死亡退住(院内) 8 死亡退住(院外) 9 其他
|
|
|
|
|
+ */
|
|
|
export const DISCHARGE_REASON = {
|
|
export const DISCHARGE_REASON = {
|
|
|
- HOME_CARE: 1, // 居家照护
|
|
|
|
|
- HOSPITAL: 2, // 医院就诊
|
|
|
|
|
- DEATH_IN: 3, // 死亡退住(院内)
|
|
|
|
|
- DEATH_OUT: 4, // 死亡退住(院外)
|
|
|
|
|
- OTHER: 5 // 其他
|
|
|
|
|
|
|
+ NORMAL: 1, // 正常退住
|
|
|
|
|
+ DEATH: 2, // 死亡退住(仅有该大类,无院内/院外细分)
|
|
|
|
|
+ TRANSFER: 3, // 转院退住
|
|
|
|
|
+ TRIAL_END: 4, // 试住结束
|
|
|
|
|
+ HOME_CARE: 5, // 居家照护
|
|
|
|
|
+ HOSPITAL: 6, // 医院就诊
|
|
|
|
|
+ DEATH_IN: 7, // 死亡退住(院内)
|
|
|
|
|
+ DEATH_OUT: 8, // 死亡退住(院外)
|
|
|
|
|
+ OTHER: 9 // 其他
|
|
|
} as const
|
|
} as const
|
|
|
|
|
|
|
|
export const DISCHARGE_REASON_OPTIONS = [
|
|
export const DISCHARGE_REASON_OPTIONS = [
|
|
|
|
|
+ { value: DISCHARGE_REASON.NORMAL, label: '正常退住' },
|
|
|
|
|
+ { value: DISCHARGE_REASON.DEATH, label: '死亡退住' },
|
|
|
|
|
+ { value: DISCHARGE_REASON.TRANSFER, label: '转院退住' },
|
|
|
|
|
+ { value: DISCHARGE_REASON.TRIAL_END, label: '试住结束' },
|
|
|
{ value: DISCHARGE_REASON.HOME_CARE, label: '居家照护' },
|
|
{ value: DISCHARGE_REASON.HOME_CARE, label: '居家照护' },
|
|
|
{ value: DISCHARGE_REASON.HOSPITAL, label: '医院就诊' },
|
|
{ value: DISCHARGE_REASON.HOSPITAL, label: '医院就诊' },
|
|
|
{ value: DISCHARGE_REASON.DEATH_IN, label: '死亡退住(院内)' },
|
|
{ value: DISCHARGE_REASON.DEATH_IN, label: '死亡退住(院内)' },
|
|
@@ -27,7 +40,7 @@ export const DISCHARGE_REASON_OPTIONS = [
|
|
|
{ value: DISCHARGE_REASON.OTHER, label: '其他' }
|
|
{ value: DISCHARGE_REASON.OTHER, label: '其他' }
|
|
|
]
|
|
]
|
|
|
|
|
|
|
|
-/** 死亡出院(用药情况 / 出院指导 不需填写) */
|
|
|
|
|
|
|
+/** 死亡出院(用药情况 / 出院指导 不需填写):命中「死亡退住(院内/院外)」即触发 */
|
|
|
export const isDeathDischarge = (reason: any): boolean =>
|
|
export const isDeathDischarge = (reason: any): boolean =>
|
|
|
Number(reason) === DISCHARGE_REASON.DEATH_IN || Number(reason) === DISCHARGE_REASON.DEATH_OUT
|
|
Number(reason) === DISCHARGE_REASON.DEATH_IN || Number(reason) === DISCHARGE_REASON.DEATH_OUT
|
|
|
|
|
|
|
@@ -126,29 +139,229 @@ export interface DischargeSummaryVO {
|
|
|
/** 提交表单结构(与 VO 一致,medications 为子表) */
|
|
/** 提交表单结构(与 VO 一致,medications 为子表) */
|
|
|
export type DischargeSummaryForm = DischargeSummaryVO
|
|
export type DischargeSummaryForm = DischargeSummaryVO
|
|
|
|
|
|
|
|
|
|
+// ==================== 字段转换(后端 dischargeAbstract <-> 前端表单) ====================
|
|
|
|
|
+// 后端接口与前端表单字段命名不一致,统一在此做对称转换,Form / Print / columns 无需感知后端字段名。
|
|
|
|
|
+// 后端字段一览:
|
|
|
|
|
+// elderId/elderName/elderSex/elderSexName/elderAge/region/checkInDate/dischargeDate/reasonDischarge
|
|
|
|
|
+// /doctorSign/anamnesis/recentHealthIssues/physicalActivityAbility/cognitionMentalState
|
|
|
|
|
+// /diseaseTreatmentControl/recentMedicalTreatmentSituation/vitalSigns/physicalFunctions
|
|
|
|
|
+// /keyIssues/safetyProtection/dietMedicalTreatment/signDate/medicines(medicineName/dose/usage/frequency)
|
|
|
|
|
+
|
|
|
|
|
+/** 生命体征:前端四段(P/R/收缩压/舒张压) -> 后端单个字符串 vitalSigns */
|
|
|
|
|
+const vitalSignsToStr = (form: any): string => {
|
|
|
|
|
+ const parts: string[] = []
|
|
|
|
|
+ if (form.pulse) parts.push(`P:${form.pulse}`)
|
|
|
|
|
+ if (form.respiration) parts.push(`R:${form.respiration}`)
|
|
|
|
|
+ const bp = [form.systolicPressure, form.diastolicPressure].filter((v) => v !== '' && v != null)
|
|
|
|
|
+ if (bp.length) parts.push(`HP:${bp.join('/')}`)
|
|
|
|
|
+ return parts.join(';')
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 生命体征:后端字符串 vitalSigns -> 前端四段 */
|
|
|
|
|
+const vitalSignsFromStr = (vitalSigns?: string) => {
|
|
|
|
|
+ const res = { pulse: '', respiration: '', systolicPressure: '', diastolicPressure: '' }
|
|
|
|
|
+ if (!vitalSigns) return res
|
|
|
|
|
+ String(vitalSigns)
|
|
|
|
|
+ .split(/[;;]/)
|
|
|
|
|
+ .forEach((s) => {
|
|
|
|
|
+ s = s.trim()
|
|
|
|
|
+ if (s.startsWith('P')) {
|
|
|
|
|
+ res.pulse = s.replace(/^P[::]?\s*/, '')
|
|
|
|
|
+ } else if (s.startsWith('R')) {
|
|
|
|
|
+ res.respiration = s.replace(/^R[::]?\s*/, '')
|
|
|
|
|
+ } else if (s.startsWith('HP')) {
|
|
|
|
|
+ const [sys = '', dia = ''] = s.replace(/^HP[::]?\s*/, '').split('/')
|
|
|
|
|
+ res.systolicPressure = sys.trim()
|
|
|
|
|
+ res.diastolicPressure = dia.trim()
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ return res
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 出院原因:前端枚举(+其他补充) -> 后端字符串 reasonDischarge("其他"时拼补充说明) */
|
|
|
|
|
+const reasonToStr = (dischargeReason: any, dischargeReasonOther?: string): string => {
|
|
|
|
|
+ const label = getDischargeReasonText(dischargeReason)
|
|
|
|
|
+ if (!label) return dischargeReasonOther || ''
|
|
|
|
|
+ if (Number(dischargeReason) === DISCHARGE_REASON.OTHER) {
|
|
|
|
|
+ return dischargeReasonOther ? `${label}:${dischargeReasonOther}` : label
|
|
|
|
|
+ }
|
|
|
|
|
+ return label
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 出院原因:后端字符串 reasonDischarge -> 前端枚举(+其他补充) */
|
|
|
|
|
+const reasonFromStr = (text?: string) => {
|
|
|
|
|
+ if (!text) return { dischargeReason: undefined as number | undefined, dischargeReasonOther: '' }
|
|
|
|
|
+ const otherLabel = getDischargeReasonText(DISCHARGE_REASON.OTHER)
|
|
|
|
|
+ if (String(text).startsWith(otherLabel)) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ dischargeReason: DISCHARGE_REASON.OTHER,
|
|
|
|
|
+ dischargeReasonOther: String(text).slice(otherLabel.length).replace(/^[::]/, '')
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ const matched = DISCHARGE_REASON_OPTIONS.find((o) => o.label === String(text))
|
|
|
|
|
+ return { dischargeReason: matched ? (matched.value as number) : undefined, dischargeReasonOther: '' }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 用药子表:前端 drugName/dosage/usageMethod/frequency -> 后端 medicineName/dose/usage/frequency */
|
|
|
|
|
+const toBackendMedicine = (m: DischargeMedication): any => ({
|
|
|
|
|
+ id: m.id,
|
|
|
|
|
+ medicineName: m.drugName,
|
|
|
|
|
+ dose: m.dosage,
|
|
|
|
|
+ usage: m.usageMethod,
|
|
|
|
|
+ frequency: m.frequency
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+/** 用药子表:后端 -> 前端 */
|
|
|
|
|
+const fromBackendMedicine = (m: any): DischargeMedication => ({
|
|
|
|
|
+ id: m?.id,
|
|
|
|
|
+ drugName: m?.medicineName,
|
|
|
|
|
+ dosage: m?.dose,
|
|
|
|
|
+ usageMethod: m?.usage,
|
|
|
|
|
+ frequency: m?.frequency
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 枚举字段存库:前端 value(数字) -> 后端字符串 label。
|
|
|
|
|
+ * 后端 physicalActivityAbility / cognitionMentalState 均为 string 字段,
|
|
|
|
|
+ * 与 reasonDischarge 一致,实际存的是中文 label,故提交时传 label 文本。
|
|
|
|
|
+ */
|
|
|
|
|
+const optionValueToStored = (options: { value: number; label: string }[], value: any): string => {
|
|
|
|
|
+ const found = options.find((o) => Number(o.value) === Number(value))
|
|
|
|
|
+ return found ? found.label : value ?? ''
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 枚举字段回显:后端 string(label 或 value) -> 前端 value(数字) */
|
|
|
|
|
+const optionStoredToValue = (
|
|
|
|
|
+ options: { value: number; label: string }[],
|
|
|
|
|
+ stored: any
|
|
|
|
|
+): number | undefined => {
|
|
|
|
|
+ if (stored === '' || stored === null || stored === undefined) return undefined
|
|
|
|
|
+ // 后端若直接存数字值,原样返回
|
|
|
|
|
+ if (options.some((o) => Number(o.value) === Number(stored))) return Number(stored)
|
|
|
|
|
+ // 否则按 label 反查 value
|
|
|
|
|
+ const found = options.find((o) => o.label === String(stored))
|
|
|
|
|
+ return found ? found.value : undefined
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 提交:前端表单 -> 后端 SaveReqVO */
|
|
|
|
|
+const buildSavePayload = (form: DischargeSummaryForm): any => ({
|
|
|
|
|
+ id: form.id,
|
|
|
|
|
+ elderId: form.elderId,
|
|
|
|
|
+ dischargeDate: form.dischargeDate,
|
|
|
|
|
+ anamnesis: form.pastMedicalHistory,
|
|
|
|
|
+ recentHealthIssues: form.recentHealthProblems,
|
|
|
|
|
+ physicalActivityAbility: optionValueToStored(PHYSICAL_ABILITY_OPTIONS, form.physicalAbility),
|
|
|
|
|
+ cognitionMentalState: optionValueToStored(COGNITIVE_STATUS_OPTIONS, form.cognitiveStatus),
|
|
|
|
|
+ diseaseTreatmentControl: form.diseaseTreatment,
|
|
|
|
|
+ recentMedicalTreatmentSituation: form.recentMedicalVisit,
|
|
|
|
|
+ reasonDischarge: reasonToStr(form.dischargeReason, form.dischargeReasonOther),
|
|
|
|
|
+ vitalSigns: vitalSignsToStr(form),
|
|
|
|
|
+ physicalFunctions: form.bodyFunction,
|
|
|
|
|
+ keyIssues: form.focusProblems,
|
|
|
|
|
+ safetyProtection: form.safetyProtection,
|
|
|
|
|
+ dietMedicalTreatment: form.dietAndMedical,
|
|
|
|
|
+ doctorSign: form.doctorSign,
|
|
|
|
|
+ signDate: form.signDate,
|
|
|
|
|
+ tenantId: form.tenantId,
|
|
|
|
|
+ medicines: (form.medications || [])
|
|
|
|
|
+ .filter((m) => m.drugName)
|
|
|
|
|
+ .map((m) => toBackendMedicine(m))
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+/** 详情/列表项:后端 VO -> 前端表单结构 */
|
|
|
|
|
+const fromBackendVO = (data: any): any => {
|
|
|
|
|
+ const vitals = vitalSignsFromStr(data.vitalSigns)
|
|
|
|
|
+ const reason = reasonFromStr(data.reasonDischarge)
|
|
|
|
|
+ return {
|
|
|
|
|
+ id: data.id,
|
|
|
|
|
+ elderId: data.elderId,
|
|
|
|
|
+ elderName: data.elderName,
|
|
|
|
|
+ gender: data.elderSex,
|
|
|
|
|
+ genderName: data.elderSexName,
|
|
|
|
|
+ elderAge: data.elderAge,
|
|
|
|
|
+ bedName: data.region, // 居住区域:后端返回 region
|
|
|
|
|
+ checkInDate: data.checkInDate,
|
|
|
|
|
+ dischargeDate: data.dischargeDate,
|
|
|
|
|
+ pastMedicalHistory: data.anamnesis,
|
|
|
|
|
+ recentHealthProblems: data.recentHealthIssues,
|
|
|
|
|
+ physicalAbility: optionStoredToValue(PHYSICAL_ABILITY_OPTIONS, data.physicalActivityAbility),
|
|
|
|
|
+ cognitiveStatus: optionStoredToValue(COGNITIVE_STATUS_OPTIONS, data.cognitionMentalState),
|
|
|
|
|
+ diseaseTreatment: data.diseaseTreatmentControl,
|
|
|
|
|
+ recentMedicalVisit: data.recentMedicalTreatmentSituation,
|
|
|
|
|
+ dischargeReason: reason.dischargeReason,
|
|
|
|
|
+ dischargeReasonOther: reason.dischargeReasonOther,
|
|
|
|
|
+ dischargeReasonText: data.reasonDischarge || '', // 列表/打印直接展示后端文本
|
|
|
|
|
+ pulse: vitals.pulse,
|
|
|
|
|
+ respiration: vitals.respiration,
|
|
|
|
|
+ systolicPressure: vitals.systolicPressure,
|
|
|
|
|
+ diastolicPressure: vitals.diastolicPressure,
|
|
|
|
|
+ bodyFunction: data.physicalFunctions,
|
|
|
|
|
+ medications: (data.medicines || []).map((m: any) => fromBackendMedicine(m)),
|
|
|
|
|
+ focusProblems: data.keyIssues,
|
|
|
|
|
+ safetyProtection: data.safetyProtection,
|
|
|
|
|
+ dietAndMedical: data.dietMedicalTreatment,
|
|
|
|
|
+ doctorSign: data.doctorSign,
|
|
|
|
|
+ signDate: data.signDate,
|
|
|
|
|
+ tenantId: data.tenantId,
|
|
|
|
|
+ creator: data.creator,
|
|
|
|
|
+ createTime: data.createTime
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 列表项:仅保留列表展示字段,并预计算展示辅助字段 */
|
|
|
|
|
+const fromBackendListItem = (item: any): any => {
|
|
|
|
|
+ const vo = fromBackendVO(item)
|
|
|
|
|
+ return {
|
|
|
|
|
+ id: vo.id,
|
|
|
|
|
+ elderId: vo.elderId,
|
|
|
|
|
+ elderName: vo.elderName,
|
|
|
|
|
+ gender: vo.gender,
|
|
|
|
|
+ genderName: vo.genderName,
|
|
|
|
|
+ elderAge: vo.elderAge,
|
|
|
|
|
+ elderAgeText:
|
|
|
|
|
+ vo.elderAge === undefined || vo.elderAge === null || vo.elderAge === ''
|
|
|
|
|
+ ? ''
|
|
|
|
|
+ : `${vo.elderAge} 岁`,
|
|
|
|
|
+ bedName: vo.bedName,
|
|
|
|
|
+ checkInDate: vo.checkInDate,
|
|
|
|
|
+ dischargeDate: vo.dischargeDate,
|
|
|
|
|
+ dischargeReason: vo.dischargeReason,
|
|
|
|
|
+ dischargeReasonOther: vo.dischargeReasonOther,
|
|
|
|
|
+ dischargeReasonText: vo.dischargeReasonText,
|
|
|
|
|
+ doctorSign: vo.doctorSign,
|
|
|
|
|
+ tenantId: vo.tenantId,
|
|
|
|
|
+ createTime: vo.createTime
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// ==================== 接口 ====================
|
|
// ==================== 接口 ====================
|
|
|
|
|
|
|
|
/** 分页查询 */
|
|
/** 分页查询 */
|
|
|
-export const getDischargeSummaryPage = (params: any) => {
|
|
|
|
|
- return request.get({ url: 'elderly/dischargeSummary/page', params })
|
|
|
|
|
|
|
+export const getDischargeSummaryPage = async (params: any) => {
|
|
|
|
|
+ const data = await request.get({ url: 'elderly/dischargeAbstract/page', params })
|
|
|
|
|
+ return {
|
|
|
|
|
+ list: (data?.list || []).map((item: any) => fromBackendListItem(item)),
|
|
|
|
|
+ total: data?.total || 0
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 详情 */
|
|
/** 详情 */
|
|
|
-export const getDischargeSummary = (id: number) => {
|
|
|
|
|
- return request.get({ url: `elderly/dischargeSummary/get?id=${id}` })
|
|
|
|
|
|
|
+export const getDischargeSummary = async (id: number) => {
|
|
|
|
|
+ const data = await request.get({ url: `elderly/dischargeAbstract/get?id=${id}` })
|
|
|
|
|
+ return fromBackendVO(data)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 新增 */
|
|
/** 新增 */
|
|
|
export const createDischargeSummary = (data: DischargeSummaryForm) => {
|
|
export const createDischargeSummary = (data: DischargeSummaryForm) => {
|
|
|
- return request.post({ url: 'elderly/dischargeSummary/create', data })
|
|
|
|
|
|
|
+ return request.post({ url: 'elderly/dischargeAbstract/create', data: buildSavePayload(data) })
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 更新 */
|
|
/** 更新 */
|
|
|
export const updateDischargeSummary = (data: DischargeSummaryForm) => {
|
|
export const updateDischargeSummary = (data: DischargeSummaryForm) => {
|
|
|
- return request.put({ url: 'elderly/dischargeSummary/update', data })
|
|
|
|
|
|
|
+ return request.put({ url: 'elderly/dischargeAbstract/update', data: buildSavePayload(data) })
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 删除 */
|
|
/** 删除 */
|
|
|
export const deleteDischargeSummary = (id: number) => {
|
|
export const deleteDischargeSummary = (id: number) => {
|
|
|
- return request.delete({ url: `elderly/dischargeSummary/delete?id=${id}` })
|
|
|
|
|
|
|
+ return request.delete({ url: `elderly/dischargeAbstract/delete?id=${id}` })
|
|
|
}
|
|
}
|