diff --git a/src/api/doctor/disease.js b/src/api/doctor/disease.js index d71b8be8165f93a2616f8520650dd1d5e378e754..cf14aeb280f17532c6071e5e1eacda527412051a 100644 --- a/src/api/doctor/disease.js +++ b/src/api/doctor/disease.js @@ -8,4 +8,9 @@ export function fetchDiseaseTypeList(params, loading) { // 查询随访列表 export function getVisitManageList(params, loading) { return fetchBase({ url: `/chronic-admin/v1/chronic-visit-record/page`, body: params, loading }) +} + +// 获取检验项目对码表 +export function getInspectCode(configType) { + return fetchBase({ url: `/chronic-admin/v1/chronic-inspect-item/query-list/${configType}`, loading: true }) } \ No newline at end of file diff --git a/src/doctor/diagnose/common/InputSelect.vue b/src/doctor/diagnose/common/InputSelect.vue new file mode 100644 index 0000000000000000000000000000000000000000..45df0a59e899eba80d34385763129907e734d41f --- /dev/null +++ b/src/doctor/diagnose/common/InputSelect.vue @@ -0,0 +1,83 @@ +<template> + <van-popup :show="show" position="bottom" + :teleport="teleport" + class="input-select"> + <van-picker + title="请选择" + :columns="array" + :columns-field-names="fieldNames" + v-model="innerValue" + @confirm="onConfirm" + @cancel="onCancel" + > + <template #columns-top> + <van-field v-model="customValue" placeholder="请输入" clearable/> + </template> + </van-picker> + </van-popup> +</template> + +<script> +export default { + props: { + show: Boolean, + value: [String, Number], + fieldNames: { + type: Object, + default: () => { + return {text: 'name', value: 'value'} + } + }, + // 字典 + dict: { + type: Array, + required: true + }, + teleport: [String, Element] + }, + emits: ['update:show', 'update:value', 'change'], + data() { + return { + innerValue: undefined, + customValue: '' + } + }, + computed: { + array() { + const array = this.dict || [] + const result = array.filter(e => e.value.startsWith(this.customValue)) + if (result.length) { + return [...result] + } + return [{ + [this.fieldNames.text]: this.customValue, + [this.fieldNames.value]: this.customValue + }] + } + }, + methods: { + onConfirm({ selectedValues, selectedOptions }) { + this.$emit('update:value', selectedValues[0] || {}) + this.$emit('change', selectedOptions[0] || {}) + this.$emit('update:show', false) + this.customValue = '' + }, + onCancel() { + this.$emit('update:show', false) + } + }, + watch: { + value: { + handler(value) { + if (value == null) return + this.innerValue = [value] + }, + immediate: true + }, + } +} +</script> + +<style lang="less" scoped> + +</style> diff --git a/src/doctor/diagnose/common/Instpect.vue b/src/doctor/diagnose/common/Instpect.vue new file mode 100644 index 0000000000000000000000000000000000000000..efe2f44a73cfa6a6a6c8e6fcc19e367cf84b5cba --- /dev/null +++ b/src/doctor/diagnose/common/Instpect.vue @@ -0,0 +1,186 @@ +<template> + <div class="instpect-common"> + <div class='doc-form-label' required>检验项目</div> + <van-field is-link + :modelValue='inspectName' + readonly + placeholder='请选择' + name="inspect" + @click="showInspect = true" + :rules="[{ required: true, message: '请选择' }]" + /> + <van-popup v-model:show="showInspect" position="bottom" style="height: 60%"> + <div class="pt-4 h-full flex flex-col popup-checkbox"> + <div class="flex justify-between shrink-0 pb-2"> + <button class="van-picker__cancel van-haptics-feedback" @click="showInspect = false" >取消</button> + <span class="text-16" >请选择(可多选)</span> + <button class="van-picker__confirm van-haptics-feedback" @click="inspectConfirm" >确认</button> + </div> + <div class="bottom-small-line"></div> + <van-checkbox-group v-model="inspect" class="px-4 pb-4 pt-2 grow overflow-y-auto" > + <van-checkbox v-for="(item, index) in store.getDict('CP00100')" :key="index" + :name="item.value" + class="mb-3"> + <span :class="{'text-primary': adviseInspect.includes(item.value)}">{{ item.name }}</span> + </van-checkbox> + </van-checkbox-group> + </div> + </van-popup> + + <div class="flex flex-col mt-3 instpect-list"> + <div v-for="(row, index1) in viewData" :key="row.insType" + class="pt-3 px-2 mb-2" + :style="`order: ${row.insType}`"> + <div class="required-mark mb-3">{{ row.insName }}</div> + <template v-for="(item, index2) in row.items" :key="item.itemCode"> + <van-field :label="getItemName(item)" + v-model="item.itemValue" + placeholder="请输入" + :maxLength="100" + :rules="getRule(item)" + :name="['viewData', index1, 'items', index2, 'itemValue'].join('.')" + label-align="top" + class="no-back mb-2" + style="border-radius: .08rem;" + v-destory:itemValue="item" + v-if="item.itemType === 1" + > + <template #extra v-if="item.unit"> + <span class="ml-1">{{ item.unit }}</span> + </template> + </van-field> + </template> + + </div> + </div> + </div> +</template> + +<script> +import { inspectDefault } from './config.js' +import { getInspectCode } from '@/api/doctor/disease.js' +import { useStore } from '@/doctor/store/index.js' + +export default { + name: 'InstpectCommon', + components: {}, + props: { + // 初始化数据 + info: { default: () => { return {} } }, + // 慢病 + disease: { + type: [String, Number], + required: true + }, + // 是否显示图片上传表单 + imageVisible: { + type: Boolean, + default: false + } + }, + data() { + return { + store: useStore(), + inspect: [], + inspectName: '', + viewData: [], + image: '', + // 可显示的检验项 + codeTable: [], + // 图片上传回显 + imageData: [], + showInspect: false + } + }, + computed: { + // 推荐选中的项目 + adviseInspect() { + return inspectDefault(this.disease) + } + }, + created() { + this.init() + }, + methods: { + init() { + if (this.info.inspect) { + let inspect = this.info.inspect + this.inspect = typeof inspect === 'string' ? inspect.split(',') : inspect + } + this.image = this.info.image + this.imageData = this.info.imageData || [] + getInspectCode(1).then(res => { + console.log(res) + const inspect = this.inspect + const data = this.info.items || [] + this.codeTable = res.data || [] + this.codeTable.forEach(e => { + const item = data.find(i => e.itemCode === i.itemCode) || {} + e.itemValue = item.itemValue + }) + this.viewData = inspect.map(val => { + const items = this.codeTable.filter(e => e.insType === val) + if (!items.length) return {} + return { + insName: items[0].insName, + insType: val, + items: [...items] + } + }) + console.log(this.viewData) + }) + }, + inspectConfirm() { + this.inspectName = this.store.getDict('CP00100').map(e => { + return this.inspect.includes(e.value) ? e.name : '' + }).filter(e => e).join('、') + this.showInspect = false + this.inspectChange(this.inspect) + }, + inspectChange(val) { + const viewData = this.viewData + const addValue = val.filter(e => !viewData.find(i => i.insType === e)) + const delValue = viewData.filter(i => !val.includes(i.insType)).map(e => e.insType) + if (delValue.length) { + this.viewData = this.viewData.filter(e => !delValue.includes(e.insType)) + } + if (addValue.length) { + addValue.forEach(val => { + const items = this.codeTable.filter(e => e.insType === val) + if (!items.length) return {} + this.viewData.push({ + insName: items[0].insName, + insType: val, + items: [...items] + }) + }) + } + console.log('inspectChange', this.viewData) + }, + getItemName(item) { + if (item.itemCode) { + return `${item.itemName}(${item.itemCode})` + } + return item.itemName + }, + getRule(item) { + if (!item.pattern) { + return [{ required: true, message: '请录入' }] + } + return [ + { required: true, message: '请录入' }, + { pattern: new RegExp(item.pattern), message: item.message } + ] + }, + } +} +</script> + +<style lang="less" scoped> +.instpect-list { + >div { + background-color: #F5F5F5; + border-radius: 8px; + } +} +</style> diff --git a/src/doctor/diagnose/common/config.js b/src/doctor/diagnose/common/config.js new file mode 100644 index 0000000000000000000000000000000000000000..00bd2e86920d463f9969548f31d73d07d45ae65a --- /dev/null +++ b/src/doctor/diagnose/common/config.js @@ -0,0 +1,60 @@ +/** + * itemType 表单类型 input || select || inputSelect + * pattern 校验正则 + */ +// export const inspectConfig = [ +// { id: 1, insType: 1, insName: '血常规', itemCode: 'wbc', itemName: '白细胞计数(WBC)', unit: '10^9/L', sort: 1, itemType: 'input', +// pattern: /^(?:0(?:\.\d{1,3})?|[1-9]\d{0,1}(?:\.\d{1,3})?|100)$/, message: '请输入0-100之间的数字,最多3位小数' }, +// { id: 2, insType: 1, insName: '血常规', itemCode: 'hgb', itemName: '血红蛋白(HGB)', unit: 'g/L', sort: 2, itemType: 'input', +// pattern: /^(?:0(?:\.\d{1,3})?|[1-4]\d{0,2}(?:\.\d{1,3})?|500)$/, message: '请输入0-500之间的数字,最多3位小数' }, +// { id: 3, insType: 1, insName: '血常规', itemCode: 'plt', itemName: '血小板计数(PLT)', unit: '10^9/L', sort: 3, itemType: 'input', +// pattern: /^(?:0(?:\.\d{1,3})?|[1-9]\d{0,2}(?:\.\d{1,3})?|1000)$/, message: '请输入0-1000之间的数字,最多3位小数' }, +// { id: 4, insType: 2, insName: '尿常规', itemCode: 'pro', itemName: '尿蛋白(PRO)', unit: '', sort: 4, itemType: 'inputSelect', dict: 'MY001' }, +// { id: 5, insType: 2, insName: '尿常规', itemCode: 'GLU-nt', itemName: '尿糖(GLU-nt)', unit: '', sort: 5, itemType: 'inputSelect', dict: 'MY001' }, +// { id: 6, insType: 2, insName: '尿常规', itemCode: 'KET', itemName: '尿酮体(KET)', unit: '', sort: 6, itemType: 'inputSelect', dict: 'MY001' }, +// { id: 6, insType: 2, insName: '尿常规', itemCode: 'BLD', itemName: '尿潜血(BLD)', unit: '', sort: 7, itemType: 'inputSelect', dict: 'MY001' }, +// { id: 6, insType: 2, insName: '尿常规', itemCode: 'mAlb', itemName: '尿微量白蛋白测定(mAlb)', unit: 'mg/dl', sort: 7, itemType: 'input', +// pattern: /^(?:0(?:\.\d{1,3})?|[1-9]\d{0,1}(?:\.\d{1,3})?|100)$/, message: '请输入0-100之间的数字,最多3位小数' } +// ] + +// 不同慢病对应的检验 +export const inspectDefault = (disease) => { + const config = { + // 高血压 + 1: [1, 2, 3, 4, 5, 6, 12, 14], + // 糖尿病 + 2: [8, 9, 10, 11, 12], + // 冠心病 + 3: [1, 3, 7, 32], + // 脑卒中 + 4: [], + // 慢性阻塞性肺疾病 + 5: [3, 4, 5, 6, 13, 15, 16], + // 慢性肾病 + 6: [2, 3, 4, 5, 6, 12, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31], + // 血脂异常 + 7: [5], + } + return config[disease] || [] +} + +// 不同慢病对应的检验 +export const checkDefault = (disease) => { + const config = { + // 高血压 + 1: [1, 5, 6, 7, 8, 9], + // 糖尿病 + 2: [9, 10, 11], + // 冠心病 + 3: [5, 12, 13], + // 脑卒中 + 4: [4, 14], + // 慢性阻塞性肺疾病 + 5: [1, 2, 5, 16, 17], + // 慢性肾病 + 6: [3, 19], + // 血脂异常 + 7: [], + } + return config[disease] || [] +} diff --git a/src/doctor/diagnose/form/DiagnoseForm.vue b/src/doctor/diagnose/form/DiagnoseForm.vue index e465fa01020bb25059e83d8019ad730257d5645e..78eaac994cf1a3e258e787507ae874509d679763 100644 --- a/src/doctor/diagnose/form/DiagnoseForm.vue +++ b/src/doctor/diagnose/form/DiagnoseForm.vue @@ -3,9 +3,9 @@ <DocNavBar :title="`${id ? '修改' : '新增'}慢病诊断`" class="shrink-0" :backFunc="onBack"></DocNavBar> <div class="p-4 overflow-y-auto grow" ref="all"> - <DiseaseSelect v-if="step == 1" ref="DiseaseSelect"/> + <DiseaseSelect v-if="step == 1" :excludeType="excludeType" ref="DiseaseSelect"/> <archiveCommon :info="baseInfo" v-else-if="step == 2"></archiveCommon> - <FormCont v-else-if="step == 3"/> + <FormCont :diseaseType="innerDiseaseType" v-else-if="step == 3"/> </div> <div class="shrink-0"> <div class='bottom-small-line'></div> @@ -50,7 +50,8 @@ export default { return { step: 1, // 患者基础信息 - baseInfo: {} + baseInfo: {}, + innerDiseaseType: null } }, computed: { @@ -62,6 +63,10 @@ export default { }, residentInfoId() { return this.$route.query.residentInfoId + }, + excludeType() { + const excludeType = this.$route.query.excludeType + return excludeType && excludeType.split(',').map(e => Number(e)) } }, created() { @@ -93,12 +98,12 @@ export default { if (this.step == 1) { const diseaseType = await this.$refs.DiseaseSelect.submit() console.log(diseaseType) + this.innerDiseaseType = diseaseType } this.onStep(this.step + 1) } catch (e) { console.warn(e) } - }, onStep(val) { this.$refs.all.scrollTo(0, 0) diff --git a/src/doctor/diagnose/form/DiseaseSelect.vue b/src/doctor/diagnose/form/DiseaseSelect.vue index 7bce3cb70a6084f628eb349a367846958e9c0983..d35650e3df0af9a66a0689f70d53985b86d21b0f 100644 --- a/src/doctor/diagnose/form/DiseaseSelect.vue +++ b/src/doctor/diagnose/form/DiseaseSelect.vue @@ -20,11 +20,13 @@ import { useStore } from '@/doctor/store/index.js' import { showToast } from 'vant' export default { + props: { + // 排除已选择的疾病 + excludeType: { default: () => [] } + }, data() { return { store: useStore(), - // 排除已选择的疾病 - excludeType: [1], // 选中的疾病类型 diseaseType: null } diff --git a/src/doctor/diagnose/form/FormCont.vue b/src/doctor/diagnose/form/FormCont.vue index f17295df5dc781601ccc66ecbf70c1c332af0b3e..239d9924b90e7c6e138552e2771e4dd8c0a59efe 100644 --- a/src/doctor/diagnose/form/FormCont.vue +++ b/src/doctor/diagnose/form/FormCont.vue @@ -1,12 +1,20 @@ <template> <div class="diagnose-form-cont"> - form + <van-form ref='form' class="doc-form" > + <InstpectCommon :disease="diseaseType"/> + </van-form> </div> </template> <script> +import InstpectCommon from '../common/Instpect.vue' export default { - + components: { + InstpectCommon + }, + props: { + diseaseType: [Number, String] + } } </script> diff --git a/src/doctor/patientDetail/PatientDetail.vue b/src/doctor/patientDetail/PatientDetail.vue index 9c0c8a29c2754d563dfe8c665c09bb838c14f466..95c5b56cd7b3bb826317c9b213190909a8427b09 100644 --- a/src/doctor/patientDetail/PatientDetail.vue +++ b/src/doctor/patientDetail/PatientDetail.vue @@ -81,7 +81,7 @@ <span class="right" style="width: .32rem;"></span> </div> <div class="p-4"> - <CheckBtn :options="addOptions" activeStyleNone + <CheckBtn :options="addOptions" activeStyleNone :clearable="false" @change="onAddChange" column-1 /> <div class="pb-5"></div> </div> @@ -154,18 +154,9 @@ export default { return this.residentInfo.chronicStatus }, tabList() { - const diseaseList = [ - { name: '高血压', value: 1, code: '512', id: 'HYPERTENSION' }, - { name: '糖尿病', value: 2, code: '1024', id: 'DIABETE' }, - { name: '冠心病', value: 3, code: '2048', id: 'COPD' }, - { name: '脑卒中', value: 4, code: '4096', id: 'STROKE' }, - { name: '慢性阻塞性疾病', value: 5, code: '8192', id: 'NEPHROPATHY' }, - { name: '慢性肾脏病', value: 6, code: '16384', id: 'KIDNEY' }, - { name: '血脂异常', value: 7, code: '32768', id: 'DYSLIPEMIA' } - ] const result = [ { name: '筛查管理', id: 'SCREENING' }, - ...diseaseList.filter(e => this.groupsArrays.includes(e.code)), + ...this.diagnoseList, { name: '通用随访', id: 'CURRENCY' }, // { name: '转诊记录', id: 'REFERRAL' }, // { name: '会诊记录', id: 'CONSULTATION' } @@ -175,6 +166,18 @@ export default { activeTabItem() { return this.tabList[this.activeTab] || {} }, + diagnoseList() { + const diseaseList = [ + { name: '高血压', value: 1, code: '512', id: 'HYPERTENSION' }, + { name: '糖尿病', value: 2, code: '1024', id: 'DIABETE' }, + { name: '冠心病', value: 3, code: '2048', id: 'COPD' }, + { name: '脑卒中', value: 4, code: '4096', id: 'STROKE' }, + { name: '慢性阻塞性疾病', value: 5, code: '8192', id: 'NEPHROPATHY' }, + { name: '慢性肾脏病', value: 6, code: '16384', id: 'KIDNEY' }, + { name: '血脂异常', value: 7, code: '32768', id: 'DYSLIPEMIA' } + ] + return diseaseList.filter(e => this.groupsArrays.includes(e.code)) + } }, activated() { this.residentInfoId = this.$route.query.residentInfoId @@ -196,9 +199,14 @@ export default { return } this.addVisible = false + const query = { residentInfoId: this.residentInfoId } + if (val == 3 && this.diagnoseList.length) { + // 诊断 + query.excludeType = this.diagnoseList.map(e => e.value).join(',') + } this.$router.push({ path: option.path, - query: { residentInfoId: this.residentInfoId } + query }) }, toArchivesEdit() { diff --git a/src/doctor/screening/first/FormCont.vue b/src/doctor/screening/first/FormCont.vue index a7bdda58f5e084b4ec3bf0129a7f8112bafe3770..b659583ac00f7f8b2cccdbeb9d8f5170742c0a47 100644 --- a/src/doctor/screening/first/FormCont.vue +++ b/src/doctor/screening/first/FormCont.vue @@ -13,11 +13,12 @@ /> <van-popup v-model:show="showMedical" position="bottom"> <div class="pt-4 popup-checkbox"> - <div class="flex justify-between"> + <div class="flex justify-between pb-2"> <button class="van-picker__cancel van-haptics-feedback" @click="showMedical = false">取消</button> <button class="van-picker__confirm van-haptics-feedback" @click="medicalConfirm">确认</button> </div> - <van-checkbox-group v-model="form.medicalHistory" class="p-4"> + <div class="bottom-small-line"></div> + <van-checkbox-group v-model="form.medicalHistory" class="px-4 pb-4 pt-2"> <van-checkbox v-for="(item, index) in store.getDict('CP00118')" :key="index" @click="medicalChange" :name="item.value" diff --git a/src/register.js b/src/register.js index cc34dfda9e23e7b12d2fe54db79f07c696ddec15..974d559bd7ddbc5988dd820276a972e1334a4dd8 100644 --- a/src/register.js +++ b/src/register.js @@ -27,6 +27,9 @@ export function registe(app) { const now = dayjs() return [now.year(), now.month() + 1, now.date()] } + + // 注册指令 + setDirective(app) } // idCard 脱敏 @@ -50,3 +53,18 @@ function addrJoin(str1 = '', str2 = '') { if (!str1 && !str2) return '-' return (str1 ?? '') + (str2 ?? '') } + +function setDirective(app) { + // dom 取消挂载 将指定字段值设为 undefined + app.directive('destory', { + beforeUnmount(el, binding, vnode, prevVnod) { + const field = binding.arg + const form = binding.value + const modifiers = binding.modifiers + if (form && field && form[field] != null) { + form[field] = modifiers.string ? '' : undefined + } + // console.log(el, binding, vnode, prevVnod) + } + }) +} \ No newline at end of file diff --git a/src/test/Index.vue b/src/test/Index.vue index 47fe5ba0cfd6ee3273ce011e652e6ca592d64dec..df5834ef1804dea4c4bfff4e3ec9e266edab256c 100644 --- a/src/test/Index.vue +++ b/src/test/Index.vue @@ -39,6 +39,17 @@ <h4 @click="mp3Show">MP3</h4> <Mp3 v-for="item in mp3Data" :file="item" :key="item.annexId" remove/> + + <h4>InputSelect</h4> + <van-field is-link + v-model='value' + readonly + placeholder='请选择' + @click="showInputSelect = true" + /> + <InputSelect v-model:show="showInputSelect" + v-model:value="value" + :dict="[{ name: '+', value: '+' }, { name: '-', value: '-' }]"/> </div> </template> @@ -48,6 +59,7 @@ import CheckBtn from '@/doctor/components/checkBtn/CheckBtn.vue' import DocImageUpload from '@/doctor/components/docImageUpload/DocImageUpload.vue' import Mp4 from '@/doctor/components/mediaPlay/Mp4.vue' import Mp3 from '@/doctor/components/mediaPlay/Mp3.vue' +import InputSelect from '@/doctor/diagnose/common/InputSelect.vue' export default { components:{ @@ -55,7 +67,8 @@ export default { CheckBtn, DocImageUpload, Mp4, - Mp3 + Mp3, + InputSelect }, data(){ return { @@ -72,7 +85,9 @@ export default { { name: '电解质', value: 5 } ], mp4Data: [{ annexId: 1, annexUrl: 'https://beta-tumour.zmnyjk.com/chronic-admin/file-proxy/tumour/20241025/1729847263522306995.mp4?e=1733300684&token=yrkyCAltqk1WVrw1ZNWUl5F5gLxE0O8LJ0Vq4hzi:xukYHUsfX6OuAXIagBuHMCJ8XNg=', annexFileName: 'kanna.mp4' }], - mp3Data: [] + mp3Data: [], + showInputSelect: false, + value: '' } }, created() {