| @@ -0,0 +1,5 @@ | |||||
| -- 患者表增加监护人信息字段 | |||||
| ALTER TABLE `patient` | |||||
| ADD COLUMN `guardian_name` varchar(50) NOT NULL DEFAULT '' COMMENT '监护人姓名' AFTER `sign_privacy_jhr`, | |||||
| ADD COLUMN `guardian_id_card` varchar(18) NOT NULL DEFAULT '' COMMENT '监护人身份证号' AFTER `guardian_name`, | |||||
| ADD COLUMN `guardian_relation` varchar(20) NOT NULL DEFAULT '' COMMENT '与患者关系' AFTER `guardian_id_card`; | |||||
| @@ -1,4 +1,5 @@ | |||||
| const Base = require('../base.js'); | const Base = require('../base.js'); | ||||
| const dayjs = require('dayjs'); | |||||
| module.exports = class extends Base { | module.exports = class extends Base { | ||||
| // 患者列表页面 | // 患者列表页面 | ||||
| @@ -122,7 +123,7 @@ module.exports = class extends Base { | |||||
| // 新增患者 | // 新增患者 | ||||
| async addAction() { | async addAction() { | ||||
| const data = this.post(); | const data = this.post(); | ||||
| const { name, phone, id_card, gender, birth_date, province_code, city_code, district_code, address, emergency_contact, emergency_phone, tag, documents, sign_income, sign_privacy, sign_promise } = data; | |||||
| const { name, phone, id_card, gender, birth_date, province_code, city_code, district_code, address, emergency_contact, emergency_phone, tag, documents, sign_income, sign_privacy, sign_promise, sign_privacy_jhr, income_amount, guardian_name, guardian_id_card, guardian_relation } = data; | |||||
| if (!name || !phone || !id_card || !gender || !birth_date) { | if (!name || !phone || !id_card || !gender || !birth_date) { | ||||
| return this.fail('请填写完整信息'); | return this.fail('请填写完整信息'); | ||||
| @@ -165,14 +166,19 @@ module.exports = class extends Base { | |||||
| sign_income: sign_income || '', | sign_income: sign_income || '', | ||||
| sign_privacy: sign_privacy || '', | sign_privacy: sign_privacy || '', | ||||
| sign_promise: sign_promise || '', | sign_promise: sign_promise || '', | ||||
| status: 0, | |||||
| sign_privacy_jhr: sign_privacy_jhr || '', | |||||
| income_amount: income_amount || '', | |||||
| guardian_name: guardian_name || '', | |||||
| guardian_id_card: guardian_id_card || '', | |||||
| guardian_relation: guardian_relation || '', | |||||
| status: 1, | |||||
| create_by: this.adminUser?.id || 0 | create_by: this.adminUser?.id || 0 | ||||
| }); | }); | ||||
| // 记录审核日志 | |||||
| // 记录审核日志(后台新增直接审核通过) | |||||
| await this.model('patient_audit').add({ | await this.model('patient_audit').add({ | ||||
| patient_id: id, | patient_id: id, | ||||
| action: 'submit', | |||||
| action: 'approve', | |||||
| operator_id: this.adminUser?.id || 0, | operator_id: this.adminUser?.id || 0, | ||||
| operator_name: this.adminUser?.nickname || this.adminUser?.username || '' | operator_name: this.adminUser?.nickname || this.adminUser?.username || '' | ||||
| }); | }); | ||||
| @@ -272,7 +278,7 @@ module.exports = class extends Base { | |||||
| // 编辑患者 | // 编辑患者 | ||||
| async editAction() { | async editAction() { | ||||
| const data = this.post(); | const data = this.post(); | ||||
| const { id, name, phone, id_card, gender, birth_date, province_code, city_code, district_code, address, emergency_contact, emergency_phone, tag, documents, sign_income, sign_privacy, sign_promise } = data; | |||||
| const { id, name, phone, id_card, gender, birth_date, province_code, city_code, district_code, address, emergency_contact, emergency_phone, tag, documents, sign_income, sign_privacy, sign_promise, sign_privacy_jhr, income_amount, guardian_name, guardian_id_card, guardian_relation } = data; | |||||
| if (!id) return this.fail('参数错误'); | if (!id) return this.fail('参数错误'); | ||||
| if (!name || !phone || !id_card || !gender || !birth_date) return this.fail('请填写完整信息'); | if (!name || !phone || !id_card || !gender || !birth_date) return this.fail('请填写完整信息'); | ||||
| @@ -295,6 +301,11 @@ module.exports = class extends Base { | |||||
| sign_income: sign_income || '', | sign_income: sign_income || '', | ||||
| sign_privacy: sign_privacy || '', | sign_privacy: sign_privacy || '', | ||||
| sign_promise: sign_promise || '', | sign_promise: sign_promise || '', | ||||
| sign_privacy_jhr: sign_privacy_jhr || '', | |||||
| income_amount: income_amount || '', | |||||
| guardian_name: guardian_name || '', | |||||
| guardian_id_card: guardian_id_card || '', | |||||
| guardian_relation: guardian_relation || '', | |||||
| update_by: this.adminUser?.id || 0 | update_by: this.adminUser?.id || 0 | ||||
| }); | }); | ||||
| @@ -337,7 +348,7 @@ module.exports = class extends Base { | |||||
| } | } | ||||
| const statusMap = { '-1': '待提交', 0: '待审核', 1: '审核通过', 2: '已驳回' }; | const statusMap = { '-1': '待提交', 0: '待审核', 1: '审核通过', 2: '已驳回' }; | ||||
| const header = ['ID', '姓名', '性别', '身份证', '手机号', '省份', '城市', '审核状态', '审核日期', '审核驳回原因', '瘤种']; | |||||
| const header = ['ID', '姓名', '性别', '身份证', '手机号', '省份', '城市', '提交时间', '审核状态', '审核日期', '审核驳回原因', '瘤种']; | |||||
| const ExcelJS = require('exceljs'); | const ExcelJS = require('exceljs'); | ||||
| const workbook = new ExcelJS.Workbook(); | const workbook = new ExcelJS.Workbook(); | ||||
| @@ -379,6 +390,7 @@ module.exports = class extends Base { | |||||
| item.phone, | item.phone, | ||||
| regionMap[item.province_code] || '', | regionMap[item.province_code] || '', | ||||
| regionMap[item.city_code] || '', | regionMap[item.city_code] || '', | ||||
| item.create_time || '', | |||||
| statusMap[item.status] || '', | statusMap[item.status] || '', | ||||
| audit ? (audit.create_time || '') : '', | audit ? (audit.create_time || '') : '', | ||||
| (audit && audit.action === 'reject') ? (audit.reason || '') : '', | (audit && audit.action === 'reject') ? (audit.reason || '') : '', | ||||
| @@ -401,7 +413,8 @@ module.exports = class extends Base { | |||||
| }); | }); | ||||
| const buffer = await workbook.xlsx.writeBuffer(); | const buffer = await workbook.xlsx.writeBuffer(); | ||||
| const fileName = encodeURIComponent(`患者信息_${Date.now()}.xlsx`); | |||||
| const ts = dayjs().format('YYYYMMDDHHmmss'); | |||||
| const fileName = encodeURIComponent(`患者信息_${ts}.xlsx`); | |||||
| this.ctx.set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); | this.ctx.set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); | ||||
| this.ctx.set('Content-Disposition', `attachment; filename*=UTF-8''${fileName}`); | this.ctx.set('Content-Disposition', `attachment; filename*=UTF-8''${fileName}`); | ||||
| @@ -306,6 +306,9 @@ module.exports = class extends Base { | |||||
| sign_privacy_jhr: patient.sign_privacy_jhr || '', | sign_privacy_jhr: patient.sign_privacy_jhr || '', | ||||
| sign_promise: patient.sign_promise || '', | sign_promise: patient.sign_promise || '', | ||||
| income_amount: patient.income_amount || '', | income_amount: patient.income_amount || '', | ||||
| guardian_name: patient.guardian_name || '', | |||||
| guardian_id_card: patient.guardian_id_card || '', | |||||
| guardian_relation: patient.guardian_relation || '', | |||||
| status: patient.status, auth_status: patient.auth_status || 0, | status: patient.status, auth_status: patient.auth_status || 0, | ||||
| reject_reason: rejectReason | reject_reason: rejectReason | ||||
| }}); | }}); | ||||
| @@ -319,7 +322,7 @@ module.exports = class extends Base { | |||||
| async saveMyInfoAction() { | async saveMyInfoAction() { | ||||
| const mpUser = this.mpUser; | const mpUser = this.mpUser; | ||||
| if (!mpUser) return this.json({ code: 1009, msg: '请先登录' }); | if (!mpUser) return this.json({ code: 1009, msg: '请先登录' }); | ||||
| const { gender, province_code, city_code, district_code, address, emergency_contact, emergency_phone, documents, sign_income, sign_privacy, sign_privacy_jhr, sign_promise, income_amount, mp_env_version } = this.post(); | |||||
| const { gender, province_code, city_code, district_code, address, emergency_contact, emergency_phone, documents, sign_income, sign_privacy, sign_privacy_jhr, sign_promise, income_amount, guardian_name, guardian_id_card, guardian_relation, mp_env_version } = this.post(); | |||||
| const user = await this.model('wechat_user').where({ id: mpUser.id, status: 1 }).find(); | const user = await this.model('wechat_user').where({ id: mpUser.id, status: 1 }).find(); | ||||
| if (think.isEmpty(user) || !user.patient_id) return this.json({ code: 1, msg: '请先完成实名认证' }); | if (think.isEmpty(user) || !user.patient_id) return this.json({ code: 1, msg: '请先完成实名认证' }); | ||||
| if (!province_code || !city_code || !district_code) return this.json({ code: 1, msg: '请选择省市区' }); | if (!province_code || !city_code || !district_code) return this.json({ code: 1, msg: '请选择省市区' }); | ||||
| @@ -341,6 +344,9 @@ module.exports = class extends Base { | |||||
| sign_privacy_jhr: sign_privacy_jhr || '', | sign_privacy_jhr: sign_privacy_jhr || '', | ||||
| sign_promise: sign_promise || '', | sign_promise: sign_promise || '', | ||||
| income_amount: income_amount || null, | income_amount: income_amount || null, | ||||
| guardian_name: guardian_name || '', | |||||
| guardian_id_card: guardian_id_card || '', | |||||
| guardian_relation: guardian_relation || '', | |||||
| status: 0, | status: 0, | ||||
| update_time: now | update_time: now | ||||
| }); | }); | ||||
| @@ -3,9 +3,15 @@ const dayjs = require('dayjs'); | |||||
| module.exports = () => { | module.exports = () => { | ||||
| return async (ctx, next) => { | return async (ctx, next) => { | ||||
| // 跳过静态资源和source map | // 跳过静态资源和source map | ||||
| if (ctx.path.startsWith('/static/') || ctx.path === '/favicon.ico' || ctx.path.endsWith('.map')) { | |||||
| if (ctx.path.startsWith('/static/') || ctx.path === '/favicon.ico') { | |||||
| return next(); | return next(); | ||||
| } | } | ||||
| // source map / json 静态请求直接返回 404,避免 think-trace 报错 | |||||
| if (ctx.path.endsWith('.map') || ctx.path.endsWith('.json')) { | |||||
| ctx.status = 404; | |||||
| ctx.body = ''; | |||||
| return; | |||||
| } | |||||
| const start = Date.now(); | const start = Date.now(); | ||||
| const params = { ...ctx.query, ...(ctx.request.body || {}) }; | const params = { ...ctx.query, ...(ctx.request.body || {}) }; | ||||
| @@ -63,6 +63,36 @@ | |||||
| <div class="info-item"><span class="label">提交时间:</span><span class="value">${ patient.create_time }</span></div> | <div class="info-item"><span class="label">提交时间:</span><span class="value">${ patient.create_time }</span></div> | ||||
| <div class="info-item"><span class="label">紧急联系人:</span><span class="value">${ patient.emergency_contact || '—' }</span></div> | <div class="info-item"><span class="label">紧急联系人:</span><span class="value">${ patient.emergency_contact || '—' }</span></div> | ||||
| <div class="info-item"><span class="label">紧急联系电话:</span><span class="value">${ patient.emergency_phone || '—' }</span></div> | <div class="info-item"><span class="label">紧急联系电话:</span><span class="value">${ patient.emergency_phone || '—' }</span></div> | ||||
| <div class="info-item" v-if="patient.income_amount"><span class="label">年可支配收入:</span><span class="value">${ patient.income_amount } 元</span></div> | |||||
| <div class="info-item" v-if="patient.guardian_name"><span class="label">监护人姓名:</span><span class="value">${ patient.guardian_name }</span></div> | |||||
| <div class="info-item" v-if="patient.guardian_id_card"><span class="label">监护人身份证:</span><span class="value">${ patient.guardian_id_card }</span></div> | |||||
| <div class="info-item" v-if="patient.guardian_relation"><span class="label">与患者关系:</span><span class="value">${ patient.guardian_relation }</span></div> | |||||
| </div> | |||||
| </div> | |||||
| <!-- 实名认证照片 --> | |||||
| <div class="detail-panel" v-if="patient.id_card_front || patient.id_card_back || patient.photo"> | |||||
| <h3>实名认证照片</h3> | |||||
| <p style="font-size:13px;color:#909399;margin-bottom:12px;"> | |||||
| <template v-if="patient.id_card_type === 2">无证件儿童免冠照片</template> | |||||
| <template v-else>身份证人像面 / 国徽面照片</template> | |||||
| </p> | |||||
| <div class="doc-images"> | |||||
| <div v-if="patient.id_card_front"> | |||||
| <el-image :src="patient.id_card_front" fit="cover" :preview-src-list="authImageList" | |||||
| :initial-index="0" style="width:260px;height:170px;border-radius:8px;border:1px solid #EBEEF5;" /> | |||||
| <div style="font-size:12px;color:#909399;text-align:center;margin-top:6px;">人像面</div> | |||||
| </div> | |||||
| <div v-if="patient.id_card_back"> | |||||
| <el-image :src="patient.id_card_back" fit="cover" :preview-src-list="authImageList" | |||||
| :initial-index="patient.id_card_front ? 1 : 0" style="width:260px;height:170px;border-radius:8px;border:1px solid #EBEEF5;" /> | |||||
| <div style="font-size:12px;color:#909399;text-align:center;margin-top:6px;">国徽面</div> | |||||
| </div> | |||||
| <div v-if="patient.photo"> | |||||
| <el-image :src="patient.photo" fit="cover" :preview-src-list="[patient.photo]" | |||||
| :initial-index="0" style="width:170px;height:170px;border-radius:8px;border:1px solid #EBEEF5;" /> | |||||
| <div style="font-size:12px;color:#909399;text-align:center;margin-top:6px;">免冠照片</div> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -212,15 +242,23 @@ var app = createApp({ | |||||
| } | } | ||||
| var signDocs = Vue.computed(function() { | var signDocs = Vue.computed(function() { | ||||
| return [ | |||||
| var docs = [ | |||||
| { key: 'income', label: '个人可支配收入声明', url: patient.sign_income }, | { key: 'income', label: '个人可支配收入声明', url: patient.sign_income }, | ||||
| { key: 'privacy', label: '个人信息处理同意书', url: patient.sign_privacy }, | { key: 'privacy', label: '个人信息处理同意书', url: patient.sign_privacy }, | ||||
| { key: 'promise', label: '声明与承诺', url: patient.sign_promise } | { key: 'promise', label: '声明与承诺', url: patient.sign_promise } | ||||
| ]; | ]; | ||||
| if (patient.sign_privacy_jhr) { | |||||
| docs.push({ key: 'privacy_jhr', label: '监护人个人信息处理同意书', url: patient.sign_privacy_jhr }); | |||||
| } | |||||
| return docs; | |||||
| }); | }); | ||||
| var signImageList = Vue.computed(function() { | var signImageList = Vue.computed(function() { | ||||
| return [patient.sign_income, patient.sign_privacy, patient.sign_promise].filter(function(u) { return u && isImageUrl(u); }); | |||||
| return [patient.sign_income, patient.sign_privacy, patient.sign_promise, patient.sign_privacy_jhr].filter(function(u) { return u && isImageUrl(u); }); | |||||
| }); | |||||
| var authImageList = Vue.computed(function() { | |||||
| return [patient.id_card_front, patient.id_card_back, patient.photo].filter(Boolean); | |||||
| }); | }); | ||||
| async function handleApprove() { | async function handleApprove() { | ||||
| @@ -283,7 +321,7 @@ var app = createApp({ | |||||
| return { | return { | ||||
| loading, patient, audits, canAudit, | loading, patient, audits, canAudit, | ||||
| rejectVisible, rejectSaving, rejectReason, selectedReasons, commonReasons, | rejectVisible, rejectSaving, rejectReason, selectedReasons, commonReasons, | ||||
| goBack, downloadSign, isImageUrl, signDocs, signImageList, handleApprove, showRejectDialog, toggleReason, doReject | |||||
| goBack, downloadSign, isImageUrl, signDocs, signImageList, authImageList, handleApprove, showRejectDialog, toggleReason, doReject | |||||
| }; | }; | ||||
| } | } | ||||
| }); | }); | ||||
| @@ -170,14 +170,38 @@ | |||||
| <el-input v-model="addForm.emergency_phone" placeholder="联系人电话" maxlength="11" /> | <el-input v-model="addForm.emergency_phone" placeholder="联系人电话" maxlength="11" /> | ||||
| </el-form-item> | </el-form-item> | ||||
| </el-col> | </el-col> | ||||
| <el-col :span="12"> | |||||
| <el-form-item label="年可支配收入(元)"> | |||||
| <el-input v-model="addForm.income_amount" placeholder="请输入年可支配收入" /> | |||||
| </el-form-item> | |||||
| </el-col> | |||||
| <el-col :span="12" v-if="isMinorComputed"> | |||||
| <el-form-item label="监护人姓名"> | |||||
| <el-input v-model="addForm.guardian_name" placeholder="请输入监护人姓名" /> | |||||
| </el-form-item> | |||||
| </el-col> | |||||
| <el-col :span="12" v-if="isMinorComputed"> | |||||
| <el-form-item label="监护人身份证"> | |||||
| <el-input v-model="addForm.guardian_id_card" placeholder="请输入监护人身份证号" maxlength="18" /> | |||||
| </el-form-item> | |||||
| </el-col> | |||||
| <el-col :span="12" v-if="isMinorComputed"> | |||||
| <el-form-item label="与患者关系"> | |||||
| <el-select v-model="addForm.guardian_relation" placeholder="请选择" style="width:100%;"> | |||||
| <el-option label="父亲" value="父亲"></el-option> | |||||
| <el-option label="母亲" value="母亲"></el-option> | |||||
| <el-option label="其他" value="其他"></el-option> | |||||
| </el-select> | |||||
| </el-form-item> | |||||
| </el-col> | |||||
| <el-col :span="24"> | <el-col :span="24"> | ||||
| <el-form-item label="上传资料"> | <el-form-item label="上传资料"> | ||||
| <div class="flex flex-wrap gap-2"> | <div class="flex flex-wrap gap-2"> | ||||
| <div v-for="(doc, idx) in addForm.documents" :key="idx" | <div v-for="(doc, idx) in addForm.documents" :key="idx" | ||||
| class="relative" style="width:80px;height:80px;"> | |||||
| <el-image :src="doc" fit="cover" style="width:80px;height:80px;border-radius:6px;border:1px solid #eee;" /> | |||||
| <span @click="addForm.documents.splice(idx, 1)" | |||||
| class="absolute top-0 right-0 cursor-pointer bg-black/50 text-white rounded-full w-5 h-5 flex items-center justify-center text-xs">×</span> | |||||
| style="position:relative;width:80px;height:80px;"> | |||||
| <el-image :src="doc" fit="cover" style="width:80px;height:80px;border-radius:6px;border:1px solid #eee;"></el-image> | |||||
| <div @click="addForm.documents.splice(idx, 1)" | |||||
| style="position:absolute;top:-6px;right:-6px;cursor:pointer;background:rgba(0,0,0,0.6);color:#fff;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;font-size:12px;z-index:10;line-height:1;">×</div> | |||||
| </div> | </div> | ||||
| <el-upload action="/admin/upload" :show-file-list="false" accept="image/*" | <el-upload action="/admin/upload" :show-file-list="false" accept="image/*" | ||||
| :on-success="onDocUpload" :headers="uploadHeaders" style="width:80px;height:80px;"> | :on-success="onDocUpload" :headers="uploadHeaders" style="width:80px;height:80px;"> | ||||
| @@ -208,6 +232,12 @@ | |||||
| ${ addForm.sign_promise ? '✅' : '📄' } 声明与承诺 | ${ addForm.sign_promise ? '✅' : '📄' } 声明与承诺 | ||||
| </el-button> | </el-button> | ||||
| </el-upload> | </el-upload> | ||||
| <el-upload v-if="isMinorComputed" action="/admin/upload" :show-file-list="false" accept=".pdf,.png,.jpg,.jpeg" | |||||
| :on-success="(res) => onSignUpload(res, 'sign_privacy_jhr')" :headers="uploadHeaders"> | |||||
| <el-button :type="addForm.sign_privacy_jhr ? 'success' : 'default'" plain> | |||||
| ${ addForm.sign_privacy_jhr ? '✅' : '📄' } 监护人个人信息处理同意书 | |||||
| </el-button> | |||||
| </el-upload> | |||||
| </div> | </div> | ||||
| </el-form-item> | </el-form-item> | ||||
| </el-col> | </el-col> | ||||
| @@ -223,7 +253,7 @@ | |||||
| {% block js %} | {% block js %} | ||||
| <script> | <script> | ||||
| const { createApp, ref, reactive, onMounted } = Vue; | |||||
| const { createApp, ref, reactive, onMounted, computed } = Vue; | |||||
| const { Plus, Download } = ElementPlusIconsVue; | const { Plus, Download } = ElementPlusIconsVue; | ||||
| const perms = { | const perms = { | ||||
| @@ -254,7 +284,8 @@ const app = createApp({ | |||||
| const addForm = reactive({ | const addForm = reactive({ | ||||
| name: '', phone: '', id_card: '', gender: '', birth_date: '', | name: '', phone: '', id_card: '', gender: '', birth_date: '', | ||||
| regionCodes: [], address: '', emergency_contact: '', emergency_phone: '', | regionCodes: [], address: '', emergency_contact: '', emergency_phone: '', | ||||
| tag: '', documents: [], sign_income: '', sign_privacy: '', sign_promise: '' | |||||
| tag: '', documents: [], sign_income: '', sign_privacy: '', sign_promise: '', | |||||
| sign_privacy_jhr: '', income_amount: '', guardian_name: '', guardian_id_card: '', guardian_relation: '' | |||||
| }); | }); | ||||
| // 省市区树形数据 | // 省市区树形数据 | ||||
| @@ -263,6 +294,20 @@ const app = createApp({ | |||||
| // 瘤种选项(从接口加载) | // 瘤种选项(从接口加载) | ||||
| const tagOptions = ref([]); | const tagOptions = ref([]); | ||||
| // 判断是否未成年(根据身份证号计算年龄) | |||||
| const isMinorComputed = computed(function() { | |||||
| var idCard = addForm.id_card; | |||||
| if (!idCard || idCard.length !== 18) return false; | |||||
| var birthStr = idCard.substring(6, 10) + '-' + idCard.substring(10, 12) + '-' + idCard.substring(12, 14); | |||||
| var birth = new Date(birthStr); | |||||
| if (isNaN(birth.getTime())) return false; | |||||
| var now = new Date(); | |||||
| var age = now.getFullYear() - birth.getFullYear(); | |||||
| var m = now.getMonth() - birth.getMonth(); | |||||
| if (m < 0 || (m === 0 && now.getDate() < birth.getDate())) age--; | |||||
| return age < 18; | |||||
| }); | |||||
| const regionFilter = ref([]); | const regionFilter = ref([]); | ||||
| const exporting = ref(false); | const exporting = ref(false); | ||||
| @@ -345,7 +390,8 @@ const app = createApp({ | |||||
| Object.assign(addForm, { | Object.assign(addForm, { | ||||
| name: '', phone: '', id_card: '', gender: '', birth_date: '', | name: '', phone: '', id_card: '', gender: '', birth_date: '', | ||||
| regionCodes: [], address: '', emergency_contact: '', emergency_phone: '', | regionCodes: [], address: '', emergency_contact: '', emergency_phone: '', | ||||
| tag: '', documents: [], sign_income: '', sign_privacy: '', sign_promise: '' | |||||
| tag: '', documents: [], sign_income: '', sign_privacy: '', sign_promise: '', | |||||
| sign_privacy_jhr: '', income_amount: '', guardian_name: '', guardian_id_card: '', guardian_relation: '' | |||||
| }); | }); | ||||
| addVisible.value = true; | addVisible.value = true; | ||||
| } | } | ||||
| @@ -380,7 +426,8 @@ const app = createApp({ | |||||
| Object.assign(addForm, { | Object.assign(addForm, { | ||||
| name: '', phone: '', id_card: '', gender: '', birth_date: '', | name: '', phone: '', id_card: '', gender: '', birth_date: '', | ||||
| regionCodes: [], address: '', emergency_contact: '', emergency_phone: '', | regionCodes: [], address: '', emergency_contact: '', emergency_phone: '', | ||||
| tag: '', documents: [], sign_income: '', sign_privacy: '', sign_promise: '' | |||||
| tag: '', documents: [], sign_income: '', sign_privacy: '', sign_promise: '', | |||||
| sign_privacy_jhr: '', income_amount: '', guardian_name: '', guardian_id_card: '', guardian_relation: '' | |||||
| }); | }); | ||||
| try { | try { | ||||
| var res = await fetch('/admin/patient/info?id=' + row.id).then(function(r) { return r.json(); }); | var res = await fetch('/admin/patient/info?id=' + row.id).then(function(r) { return r.json(); }); | ||||
| @@ -400,6 +447,11 @@ const app = createApp({ | |||||
| sign_income: p.sign_income || '', | sign_income: p.sign_income || '', | ||||
| sign_privacy: p.sign_privacy || '', | sign_privacy: p.sign_privacy || '', | ||||
| sign_promise: p.sign_promise || '', | sign_promise: p.sign_promise || '', | ||||
| sign_privacy_jhr: p.sign_privacy_jhr || '', | |||||
| income_amount: p.income_amount || '', | |||||
| guardian_name: p.guardian_name || '', | |||||
| guardian_id_card: p.guardian_id_card || '', | |||||
| guardian_relation: p.guardian_relation || '', | |||||
| regionCodes: [p.province_code, p.city_code, p.district_code].filter(Boolean) | regionCodes: [p.province_code, p.city_code, p.district_code].filter(Boolean) | ||||
| }); | }); | ||||
| addVisible.value = true; | addVisible.value = true; | ||||
| @@ -439,7 +491,12 @@ const app = createApp({ | |||||
| documents: addForm.documents, | documents: addForm.documents, | ||||
| sign_income: addForm.sign_income, | sign_income: addForm.sign_income, | ||||
| sign_privacy: addForm.sign_privacy, | sign_privacy: addForm.sign_privacy, | ||||
| sign_promise: addForm.sign_promise | |||||
| sign_promise: addForm.sign_promise, | |||||
| sign_privacy_jhr: addForm.sign_privacy_jhr || '', | |||||
| income_amount: addForm.income_amount || '', | |||||
| guardian_name: addForm.guardian_name || '', | |||||
| guardian_id_card: addForm.guardian_id_card || '', | |||||
| guardian_relation: addForm.guardian_relation || '' | |||||
| }; | }; | ||||
| if (editingId.value) body.id = editingId.value; | if (editingId.value) body.id = editingId.value; | ||||
| @@ -486,7 +543,7 @@ const app = createApp({ | |||||
| return { | return { | ||||
| keyword, dateRange, tagFilter, regionFilter, activeTab, loading, tableData, pagination, counts, | keyword, dateRange, tagFilter, regionFilter, activeTab, loading, tableData, pagination, counts, | ||||
| uploadHeaders, addVisible, addSaving, addForm, exporting, editingId, perms, | uploadHeaders, addVisible, addSaving, addForm, exporting, editingId, perms, | ||||
| regionTree, tagOptions, Plus, Download, | |||||
| regionTree, tagOptions, isMinorComputed, Plus, Download, | |||||
| loadList, resetFilter, onTabChange, onSizeChange, viewDetail, showAddDialog, showEditDialog, handleExport, | loadList, resetFilter, onTabChange, onSizeChange, viewDetail, showAddDialog, showEditDialog, handleExport, | ||||
| onIdCardInput, onDocUpload, onSignUpload, submitAdd | onIdCardInput, onDocUpload, onSignUpload, submitAdd | ||||
| }; | }; | ||||