import request from '@/utils/request'
|
|
/**
|
* 妇幼档案接口(妇科 / 儿科)
|
* 文档:《妇保接口文档》2026-10-11(共 8 个接口)
|
* 库表:
|
* 妇科主表 pat_maternity_archive /smartor/maternityArchive
|
* 妇科详情 pat_maternity_archive_detail /smartor/maternityArchiveDetail
|
* 儿科主表 pat_child_archive /smartor/childArchive
|
* 儿科详情 pat_child_archive_detail /smartor/childArchiveDetail
|
*
|
* 与旧版的差异(重点):
|
* 1. 新增 / 修改合并为一个接口 insertOrUpdateXxx,请求体是「主表字段 + 详情表字段」扁平混合,
|
* 一次调用同时维护两张表,返回 data 为主表 ID(旧版 add 不返回主键,需要反查)。
|
* 2. 删除改为 POST batchDelete,按主表 ID 批量删,详情表在同一事务里逻辑删除。
|
* 3. 详情查询 GET /xxxDetail/getInfo/{archiveid},路径参数是【主表 ID】,
|
* 返回的那条详情记录里:data.id 是【详情表主键】,data.archiveid 是【主表 ID】。
|
*
|
* ⚠️ id 与 archiveid 是两个独立字段,任何时候都不能互相赋值:
|
* insertOrUpdate 请求体里 id = 详情表主键,archiveid = 主表 ID;
|
* 主表行只有 id(列表接口不返回 archiveid),详情行 id 与 archiveid 同时存在。
|
* 判断一行是主表行还是详情行,必须由调用方显式声明,不能靠「有没有 archiveid」猜。
|
*
|
* 通用约定:
|
* 1. 请求体 Content-Type: application/json。
|
* 2. 日期字段统一 yyyy-MM-dd HH:mm:ss。
|
* 3. 建档时间范围用 params.beginTime / params.endTime(yyyy-MM-dd)。
|
* 4. orgid / campusid 由后端按登录用户自动注入,前端不用传。
|
* 5. 量表 / 可编辑表格数据存详情表 TEXT 字段(JSON 字符串)。
|
*/
|
|
/* ==================== 模块路径 ==================== */
|
const BASE = {
|
maternity: '/smartor/maternityArchive',
|
maternityDetail: '/smartor/maternityArchiveDetail',
|
child: '/smartor/childArchive',
|
childDetail: '/smartor/childArchiveDetail'
|
}
|
|
/* ==================== 档案类型编码 ====================
|
* 注意:妇科与儿科各自从 1 开始编号,不能跨科混用。
|
* 妇科:1-早孕关爱 2-围绝经期MHI
|
* 儿科:1-营养性疾病 2-学习困难 3-高危儿专案
|
* key 与 views/patient/archives/types.js 的 ARCHIVE_TYPES[].key 保持一致
|
*/
|
export const ARCHIVE_TYPE_CODE = {
|
pregnancy: { module: 'maternity', archiveType: '1', label: '早孕关爱' },
|
menopause: { module: 'maternity', archiveType: '2', label: '围绝经期MHI' },
|
nutrition: { module: 'child', archiveType: '1', label: '营养性疾病' },
|
learning: { module: 'child', archiveType: '2', label: '学习困难' },
|
highrisk: { module: 'child', archiveType: '3', label: '高危儿专案' }
|
}
|
|
// 主表模块 -> 详情表模块
|
const DETAIL_MODULE = { maternity: 'maternityDetail', child: 'childDetail' }
|
|
/**
|
* 由专案 key 解析出所属模块、档案类型编码与接口前缀
|
* @param {String} typeKey pregnancy|menopause|nutrition|learning|highrisk
|
*/
|
export function resolveTarget(typeKey) {
|
const t = ARCHIVE_TYPE_CODE[typeKey]
|
if (!t) return null
|
const detailModule = DETAIL_MODULE[t.module]
|
return {
|
...t,
|
detailModule,
|
base: BASE[t.module],
|
detailBase: BASE[detailModule]
|
}
|
}
|
|
/**
|
* 反查:模块 + 档案类型编码 -> 专案 key
|
* @param {String} module maternity|child
|
* @param {String|Number} archiveType 1|2|3
|
*/
|
export function resolveKey(module, archiveType) {
|
const keys = Object.keys(ARCHIVE_TYPE_CODE)
|
for (let i = 0; i < keys.length; i++) {
|
const t = ARCHIVE_TYPE_CODE[keys[i]]
|
if (t.module === module && String(t.archiveType) === String(archiveType)) return keys[i]
|
}
|
return ''
|
}
|
|
/* ==================== 日期工具 ==================== */
|
|
/** 当前时间 yyyy-MM-dd HH:mm:ss */
|
export function nowDateTime() {
|
const d = new Date()
|
const p = (n) => String(n).padStart(2, '0')
|
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`
|
}
|
|
/** 今天 yyyy-MM-dd */
|
export function today() {
|
const d = new Date()
|
const p = (n) => String(n).padStart(2, '0')
|
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`
|
}
|
|
/** 日期补成 yyyy-MM-dd HH:mm:ss(后端 DATETIME 列要求完整时间格式) */
|
export function toDateTime(val) {
|
if (!val) return ''
|
// 兼容 2026/08/25 这类斜杠格式
|
const s = String(val).trim().replace('T', ' ').replace(/\//g, '-')
|
// 只有日期:2026-08-25 -> 2026-08-25 00:00:00
|
if (/^\d{4}-\d{2}-\d{2}$/.test(s)) return s + ' 00:00:00'
|
// 缺秒:2026-08-25 09:30 -> 2026-08-25 09:30:00
|
if (/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/.test(s)) return s + ':00'
|
return s.substring(0, 19)
|
}
|
|
/** 需要补全时分秒的日期字段 */
|
export const DATE_FIELDS = [
|
'birthdate',
|
'diagTime',
|
'archiveTime',
|
'plannedFollowTime',
|
'dueDate',
|
'lastMenstrualTime'
|
]
|
|
/** 把 payload 里的日期字段统一补成 yyyy-MM-dd HH:mm:ss */
|
export function normalizeDates(payload = {}) {
|
DATE_FIELDS.forEach((k) => {
|
if (payload[k]) payload[k] = toDateTime(payload[k])
|
})
|
return payload
|
}
|
|
/** 由出生日期算年龄 */
|
export function calcAge(birth) {
|
if (!birth) return ''
|
const b = new Date(String(birth).substring(0, 10).replace(/-/g, '/'))
|
if (isNaN(b.getTime())) return ''
|
const now = new Date()
|
let age = now.getFullYear() - b.getFullYear()
|
const m = now.getMonth() - b.getMonth()
|
if (m < 0 || (m === 0 && now.getDate() < b.getDate())) age--
|
return age < 0 ? '' : age
|
}
|
|
/* ==================== 详情表 TEXT 字段(存 JSON) ====================
|
* 前端页面按「专案 + tab/区块」把对象或数组塞进对应字段
|
*/
|
export const FORM_FIELD_BY_TAB = {
|
// 早孕关爱
|
pregnancy: {
|
followupCycle: 'followupPeriod', // 随访周期(EditableTable 数组)
|
followup: 'epEarlyPregnancyFollowupForm' // 早孕随访表
|
},
|
// 围绝经期MHI
|
menopause: {
|
sysQ: 'mhiMenopauseFollowupSystemIssuesForm', // 更年期随访系统问题表
|
mhtFirst: 'mhiMhtInitialVisitMedicalRecordForm', // MHT首诊病历表
|
mhtFollow: 'mhiMhtFollowUpMedicalRecordForm', // MHT复诊病历表
|
kupperman: 'mhiModifiedKuppermanScoringScaleForm', // 改良Kupperman评分标准表
|
mrs: 'mhiMenopauseRatingScaleForm', // 更年期评定量表(MRS)
|
psqi: 'mhiPittsburghSleepQualityIndexForm' // 匹兹堡睡眠质量指数量表(PSQI)
|
},
|
// 高危儿专案
|
highrisk: {
|
growth: 'hrcGrowthDevelopmentMonitoring', // 生长发育监测
|
neuro: 'hrcNeurologicalEvaluation', // 神经系统评估
|
intervention: 'hrcInterventionRecords' // 干预记录
|
},
|
// 营养性疾病
|
nutrition: {
|
measure: 'ndPhysicalMeasurements', // 体格测量
|
diet: 'ndDietaryAssessment', // 膳食评估
|
plan: 'ndInterventionProgram' // 干预方案
|
},
|
// 学习困难(页面上是一整个 form,落库需拆成 4 个 TEXT 字段)
|
learning: {
|
appointment: 'appointmentSituation', // 预约情况(archive.appointmentStatus)
|
ability: 'ldLearningAbilityAssessment', // 学习能力评估
|
behavior: 'ldBehavioralAssessment', // 行为评估
|
train: 'ldInterventionTrainingRecord' // 干预训练记录
|
}
|
}
|
|
/* ==================== 字段对照(前端 -> 后端) ====================
|
* 前端现有档案对象沿用 views/patient/archives/types.js 的命名,
|
* 与后端 VO 驼峰命名不一致,提交/回显时用 toApiFields / fromApiFields 转换。
|
* 注意:前端 age 字段后端无对应列(由 birthdate 推算),不参与提交。
|
*/
|
export const FIELD_MAP = {
|
// 患者 / 档案通用
|
patid: 'patid',
|
patname: 'patname',
|
sex: 'sex',
|
telcode: 'phone',
|
idcardno: 'idcardno',
|
birthday: 'birthdate',
|
diagnosisDate: 'diagTime',
|
createTime: 'archiveTime',
|
outhospno: 'outhospno',
|
inhospno: 'inhospno',
|
serialnum: 'serialnum',
|
deptcode: 'deptcode',
|
deptname: 'deptname',
|
wardcode: 'wardcode',
|
wardname: 'wardname',
|
icd10code: 'icd10code',
|
diagname: 'diagname',
|
// 医生与登记
|
attendingDoctor: 'doctorName',
|
managingDoctor: 'managementDoctorName',
|
registrant: 'registerUser',
|
closeStatus: 'closeStatus',
|
// 妇科
|
pregnancyStatus: 'pregnancySituation',
|
followupCycles: 'followupCycleTimes',
|
lmp: 'lastMenstrualTime',
|
// 儿科
|
birthWeight: 'birthWeight',
|
gestationalWeek: 'gestationalWeek',
|
highriskCategory: 'highRiskChildType',
|
highriskName: 'highRiskChildName',
|
nutritionCode: 'nutritionIcd10Code',
|
nutritionName: 'nutritionDiagName',
|
appointmentStatus: 'appointmentSituation',
|
followupDate: 'plannedFollowTime'
|
}
|
|
// 家长 / 监护人(前端 parentInfo 子对象 -> 详情表字段)
|
export const PARENT_FIELD_MAP = {
|
parentName: 'parentname',
|
relation: 'parentRelation',
|
parentPhone: 'parentPhone',
|
parentIdCard: 'parentIdcardno',
|
address: 'parentAddress'
|
}
|
|
/** 按 FIELD_MAP 把前端对象转成后端字段(只转换有值的键) */
|
export function toApiFields(obj = {}) {
|
const out = {}
|
Object.keys(FIELD_MAP).forEach((k) => {
|
const v = obj[k]
|
if (v !== undefined && v !== null && v !== '') out[FIELD_MAP[k]] = v
|
})
|
return out
|
}
|
|
/** 按 FIELD_MAP 反向把后端行数据转成前端字段(保留未映射字段) */
|
export function fromApiFields(row = {}) {
|
const reverse = {}
|
Object.keys(FIELD_MAP).forEach((k) => {
|
reverse[FIELD_MAP[k]] = k
|
})
|
const out = { ...row }
|
Object.keys(row).forEach((k) => {
|
if (reverse[k] && reverse[k] !== k) {
|
out[reverse[k]] = row[k]
|
}
|
})
|
return out
|
}
|
|
/** 家长信息转换 */
|
export function toApiParent(parentInfo = {}) {
|
const out = {}
|
Object.keys(PARENT_FIELD_MAP).forEach((k) => {
|
const v = parentInfo[k]
|
if (v !== undefined && v !== null && v !== '') out[PARENT_FIELD_MAP[k]] = v
|
})
|
return out
|
}
|
|
/* ==================== JSON 打包 / 解包 ====================
|
* 后端 TEXT 字段存 JSON 字符串,前端统一用这两个方法出入
|
*/
|
export function packJson(value) {
|
if (value === null || value === undefined) return ''
|
if (typeof value === 'string') return value
|
try {
|
return JSON.stringify(value)
|
} catch (e) {
|
return ''
|
}
|
}
|
|
export function unpackJson(text, fallback) {
|
const def = fallback === undefined ? {} : fallback
|
if (!text) return def
|
if (typeof text !== 'string') return text
|
try {
|
return JSON.parse(text)
|
} catch (e) {
|
return def
|
}
|
}
|
|
/**
|
* 学习困难:页面上一整个 form 拆成后端 4 个 TEXT 字段
|
* @param {Object} form 页面 form(学习能力评估 / 行为评估 / 干预训练记录 混在一起)
|
* @param {String} appointmentStatus 预约情况
|
*/
|
export function splitLearningForm(form = {}, appointmentStatus = '') {
|
const f = FORM_FIELD_BY_TAB.learning
|
return {
|
[f.appointment]: packJson({ appointmentStatus: appointmentStatus }),
|
[f.ability]: packJson({
|
assessDate: form.assessDate,
|
testName: form.testName,
|
iq: form.iq,
|
reading: form.reading,
|
writing: form.writing,
|
math: form.math,
|
result: form.result
|
}),
|
[f.behavior]: packJson({
|
behaviorDate: form.behaviorDate,
|
attention: form.attention,
|
hyperactivity: form.hyperactivity,
|
impulsivity: form.impulsivity,
|
emotional: form.emotional,
|
totalScore: form.totalScore,
|
evaluation: form.evaluation
|
}),
|
[f.train]: packJson({
|
trainDate: form.trainDate,
|
trainingType: form.trainingType,
|
duration: form.duration,
|
trainContent: form.trainContent,
|
trainer: form.trainer,
|
progress: form.progress
|
})
|
}
|
}
|
|
/**
|
* 列表查询:自动补上档案类型编码
|
* @param {String} typeKey 专案 key
|
* @param {Object} params 其它查询条件
|
*/
|
export function buildListQuery(typeKey, params = {}) {
|
const t = resolveTarget(typeKey)
|
const q = { ...params }
|
if (t && q.archiveType == null) q.archiveType = t.archiveType
|
return q
|
}
|
|
/* ==================== 一、妇科档案 ==================== */
|
|
/** 查询妇科档案列表 POST /selectPatMaternityArchiveList */
|
export function listMaternityArchive(params) {
|
return request({
|
url: BASE.maternity + '/selectPatMaternityArchiveList',
|
method: 'post',
|
data: params
|
})
|
}
|
|
/**
|
* 新增或修改妇科档案 POST /insertOrUpdateMaternityArchive
|
* 请求体为主表 + 详情表字段扁平混合;返回 data 为妇科档案主表 ID
|
*/
|
export function saveMaternityArchive(data) {
|
return request({
|
url: BASE.maternity + '/insertOrUpdateMaternityArchive',
|
method: 'post',
|
data: data
|
})
|
}
|
|
/** 批量删除妇科档案(含详情)POST /batchDelete,body 为主表 ID 数组 */
|
export function batchDeleteMaternityArchive(ids) {
|
return request({
|
url: BASE.maternity + '/batchDelete',
|
method: 'post',
|
data: Array.isArray(ids) ? ids : String(ids).split(',')
|
})
|
}
|
|
/** 获取妇科档案详情 GET /maternityArchiveDetail/getInfo/{archiveid}(archiveid 为主表 ID) */
|
export function getMaternityArchiveDetail(archiveId) {
|
return request({
|
url: BASE.maternityDetail + '/getInfo/' + archiveId,
|
method: 'get'
|
})
|
}
|
|
/* ==================== 二、儿科档案 ==================== */
|
|
/** 查询儿科档案列表 POST /selectPatChildArchiveList */
|
export function listChildArchive(params) {
|
return request({
|
url: BASE.child + '/selectPatChildArchiveList',
|
method: 'post',
|
data: params
|
})
|
}
|
|
/**
|
* 新增或修改儿科档案 POST /insertOrUpdateChildArchive
|
* 请求体为主表 + 详情表字段扁平混合;返回 data 为儿科档案主表 ID
|
*/
|
export function saveChildArchive(data) {
|
return request({
|
url: BASE.child + '/insertOrUpdateChildArchive',
|
method: 'post',
|
data: data
|
})
|
}
|
|
/** 批量删除儿科档案(含详情)POST /batchDelete,body 为主表 ID 数组 */
|
export function batchDeleteChildArchive(ids) {
|
return request({
|
url: BASE.child + '/batchDelete',
|
method: 'post',
|
data: Array.isArray(ids) ? ids : String(ids).split(',')
|
})
|
}
|
|
/** 获取儿科档案详情 GET /childArchiveDetail/getInfo/{archiveid}(archiveid 为主表 ID) */
|
export function getChildArchiveDetail(archiveId) {
|
return request({
|
url: BASE.childDetail + '/getInfo/' + archiveId,
|
method: 'get'
|
})
|
}
|
|
/* ==================== 按专案聚合的调用入口 ====================
|
* 页面不想判断妇科 / 儿科时,直接用这一组
|
* 例:archiveApi('pregnancy').list({ pageNum: 1, pageSize: 10 })
|
* archiveApi('pregnancy').save(payload) // 新增或更新,返回主表 ID
|
*/
|
export function archiveApi(typeKey) {
|
const t = resolveTarget(typeKey)
|
if (!t) throw new Error('未知的档案专案类型:' + typeKey)
|
const isChild = t.module === 'child'
|
return {
|
target: t,
|
list: isChild ? listChildArchive : listMaternityArchive,
|
save: isChild ? saveChildArchive : saveMaternityArchive,
|
batchDelete: isChild ? batchDeleteChildArchive : batchDeleteMaternityArchive,
|
getDetail: isChild ? getChildArchiveDetail : getMaternityArchiveDetail
|
}
|
}
|