Commit 062c2498 authored by songrui's avatar songrui

包名称修改

parent 123fdba7
<template> <template>
<div class="h-full chronic-home"> <div class="h-full resident-home">
<router-view v-slot="{ Component }"> <router-view v-slot="{ Component }">
<Transition name="route" mode="out-in"> <Transition name="route" mode="out-in">
<component :is="Component" v-if="visible"/> <component :is="Component" v-if="visible"/>
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
</template> </template>
<script> <script>
import { useStore } from '@/chronic/store/index.js' import { useStore } from '@/resident/store/index.js'
import { idCardRule } from '@/utils/commonReg.js' import { idCardRule } from '@/utils/commonReg.js'
export default { export default {
......
...@@ -2,26 +2,14 @@ import { createRouter, createWebHashHistory } from 'vue-router' ...@@ -2,26 +2,14 @@ import { createRouter, createWebHashHistory } from 'vue-router'
const routes = [ const routes = [
{ {
path: '/tumour', path: '/resident',
name: 'tumour', name: 'resident',
component: () => import(/* webpackChunkName: "page-tumour" */ '@/tumour/Tumour.vue'), component: () => import(/* webpackChunkName: "page-resident" */ '@/resident/Resident.vue'),
children: [
{
path: 'screening/simple/form',
name: 'tumour-screening-simple-form',
component: () => import(/* webpackChunkName: "page-tumour" */ '@/tumour/screening/simple/form/Index.vue')
}
]
},
{
path: '/chronic',
name: 'chronic',
component: () => import(/* webpackChunkName: "page-chronic" */ '@/chronic/Chronic.vue'),
children: [ children: [
{ {
path: 'screening/first/form', path: 'screening/first/form',
name: 'chronic-screening-first-form', name: 'resident-screening-first-form',
component: () => import(/* webpackChunkName: "page-chronic" */ '@/chronic/screening/first/form/Index.vue') component: () => import(/* webpackChunkName: "page-resident" */ '@/resident/screening/first/form/Index.vue')
} }
] ]
}, },
......
<template>
<div class="h-full tumour-home">
<router-view v-slot="{ Component }">
<Transition name="route" mode="out-in">
<component :is="Component"/>
</Transition>
</router-view>
</div>
</template>
<script>
import { getDict } from './api/base.js'
import { useStore } from './store/index.js'
export default {
created() {
this.init()
},
setup() {
const store = useStore()
return { store }
},
methods: {
init() {
getDict().then(res => {
this.store.$patch({ dict: res.data })
})
}
}
}
</script>
<style lang="less" scoped>
</style>
import { fetchBase } from '@/utils/fetch.js'
import { setSessionStorage, getSessionStorage } from '@/utils/common.js'
// 获取字典
export function getDict() {
return fetchBase({ url: `/tumour-admin/v1/h5-app/dict`, loading: true })
}
// 区划编码查询下级
export function getAreaChild(parentCode, loading = true) {
const key = 'tumour-area-cache'
return new Promise((resolve, reject) => {
const result = getSessionStorage(key) || {}
if (result[parentCode]) {
resolve(result[parentCode])
return
}
fetchBase({ url: `/tumour-admin/v1/h5-app/child-area/${parentCode}`, loading }).then(res => {
result[parentCode] = res.data
setSessionStorage(key, result)
resolve(res.data)
}).catch(err => {
reject(err)
})
})
}
// 居民基本信息查询
export function getResidentInfo(idCard) {
return fetchBase({ url: `/tumour-admin/v1/h5-app/residents/${idCard}`, loading: true })
}
import { fetchBase } from '@/utils/fetch.js'
// 简易筛查 新增
export function addSimpleScreen(params, loading = true) {
return fetchBase({ url: `/tumour-admin/v1/h5-app/add-simple-screen`, body: params, loading })
}
import { getDict } from '@/tumour/utils/dictionaries.js'
/**
* 1肺癌 2乳腺癌 3结直肠癌 4肝癌 5宫颈癌 6甲状腺癌 7胃癌 8食管癌 9前列腺癌 10肾癌 11黑色素癌
*/
export function getQuestion(key, info) {
const questions = {
q1: {
title: '肺癌筛查量表',
issue: [{
title: '1、年龄介于45~74岁之间',
key: 'question1',
answer: {
// radio单选 checkbox多选
type: 'radio',
// 选项中 其他选项 的value
other: null,
// 答案的选项 DC00001是否
cont: getDict('DC00001')
}
}, {
title: '2、吸烟包年数≥20包年,包括曾经吸烟≥20包年,但戒烟不足15年',
key: 'question2',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '3、与条件2共同生活或同室工作被动吸烟>20年',
key: 'question3',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '4、患有慢性阻塞性肺疾病',
key: 'question4',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '5、有职业暴露史≥1年,包括暴露于石棉、氡、铍、铬、镉、硅、煤烟和煤烟灰',
key: 'question5',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '6、有一、二级亲属确诊肺癌',
key: 'question6',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}],
// 高危判断条件
check() {
// console.log('question check', this.issue)
return this.issue[0].value === 1 &&
this.issue.filter(e => e.value === 1).length >= 2
},
remark: '建议每年进行胸部低剂量CT平扫检查。如发现肺部结节,建议到胸外科、呼吸内科等专科进行就诊。'
},
q2: {
title: '乳腺癌筛查量表',
issue: [{
title: '1、有明显的乳腺癌遗传倾向者',
key: 'question1',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '2、既往有乳腺导管或小叶中重度不典型增生或小叶原位癌患者',
key: 'question2',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '3、既往有胸部放疗史的患者',
key: 'question3',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}],
check() {
return this.issue.filter(e => e.value === 1).length >= 1
},
remark: '建议对乳腺癌高危人群提前进行筛查(40岁前),筛查间期推荐每半年1次,筛查手段:临床体检、B超、乳腺钼靶检查、乳腺MRI。'
},
q3: {
title: '结直肠筛查量表',
issue: [{
title: '1、大便潜血阳性',
key: 'question1',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '2、一级亲属有结直肠癌病史',
key: 'question2',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '3、以往有肠道腺瘤史',
key: 'question3',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '4、本人有癌症史',
key: 'question4',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '5、有大便习惯的改变',
key: 'question5',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '6、符合以下任意2项者:慢性腹泻、慢性便秘、黏液血便、慢性阑尾炎或阑尾切除史、慢性胆囊炎或胆囊切除史、长期精神压抑,有报警信号',
key: 'question6',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}],
check() {
return this.issue.filter(e => e.value === 1).length >= 1
},
remark: '建议进一步进行结直肠镜检查。对于家族史不详者于40岁开始考虑进行结直肠癌筛查,而一般风险者则于50岁开始,筛查终止于75岁。'
},
q4: {
title: '肝癌筛查量表',
issue: [{
title: '1、年龄大于40岁',
key: 'question1',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '2、慢性乙型肝炎或者慢性丙型肝炎史',
key: 'question2',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '3、肝硬化病史',
key: 'question3',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '4、长期酗酒史(每日饮酒大于2两,饮酒史超过1年)',
key: 'question4',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '5、出血史:(出血倾向:鼻出血、牙龈及皮下瘀斑)',
key: 'question5',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '6、直系属亲属(父母、兄弟姐妹、子女)有肝癌病史',
key: 'question6',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '7、长期进食霉变食物或进食烟熏或盐腌的肉制品',
key: 'question7',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '8、有肝区疼痛史:(肝区疼痛:右上腹或中上腹持续性或间歇性钝痛、刺痛或胀痛,夜间或劳累后加重)',
key: 'question8',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '9、符合以下任意2项者:黄疸、腹水、上消化道出血、下肢水肿、红细胞增多症、皮肤嘌呤症、食欲明显减退恶心',
key: 'question9',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}],
check() {
return this.issue[0].value === 1 &&
this.issue.filter(e => e.value === 1).length >= 2
},
remark: '建议进一步检查彩色多普勒腹部超声、甲胎蛋白测定,对于家族史不详者于40岁开始考虑进行肝癌筛查,而一般风险者则于50岁开始,筛查终止于75岁。'
},
q5: {
title: '宫颈癌筛查量表',
issue: [{
title: '1、已婚或有性生活史3年及以上的女性',
key: 'question1',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '2、家族中有人患有宫颈癌或其他妇科癌症',
key: 'question2',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '3、曾经被诊断为宫颈炎症、宫颈糜烂或宫颈息肉',
key: 'question3',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '4、有阴异常道分泌物增多,非经期流血',
key: 'question4',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '5、感染过人类乳头瘤病毒(HPV)',
key: 'question5',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '6、同房后阴道出血或非经期流血',
key: 'question6',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}],
check() {
return this.issue[0].value === 1 &&
this.issue.filter(e => e.value === 1).length >= 2
},
remark: '建议行阴道超声、宫颈图片、HPV检查。'
},
q6: {
title: '甲状腺癌筛查量表',
issue: [{
title: '1、年龄40岁以上',
key: 'question1',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '2、有甲状腺疾病:甲状腺炎、甲状腺结节',
key: 'question2',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '3、有甲状腺癌家族史',
key: 'question3',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '4、长期接触辐射或化学物质',
key: 'question4',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '5、颈部放疗史',
key: 'question5',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '6、有其他身体不适或异常表现,如体重变化、颈部增粗',
key: 'question6',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}],
check() {
return this.issue[0].value === 1 &&
this.issue.filter(e => e.value === 1).length >= 2
},
remark: '建议行甲状腺超声、甲状腺功能检查'
},
q7: {
title: '胃癌筛查量表',
issue: [{
title: '1、年龄40岁以上,男女不限',
key: 'question1',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '2、胃癌高发地区人群',
key: 'question2',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '3、H.pylori感染者',
key: 'question3',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '4、既往患有慢性萎缩性胃炎、胃溃疡、胃息肉、手术后残胃、肥厚性胃炎、恶性贫血等胃癌前疾病',
key: 'question4',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '5、胃癌患者一级亲属',
key: 'question5',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: '6、存在胃癌其他高危因素(高盐、腌制饮食、吸烟、过度饮酒等)',
key: 'question6',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}],
check() {
return this.issue[0].value === 1 &&
this.issue.filter(e => e.value === 1).length >= 2
},
remark: '建议进一步进行胃十二指肠镜检查。'
},
q9: {
title: '前列腺癌筛查量表',
issue: [{
title: `1、您是否有过以下任何一种情况?
①尿频或排尿困难;②尿流变小或中断;③尿液中出现血丝;
④尿液浑浊或有异味;⑤阴茎勃起困难或不全;⑥疼痛或不适感。`,
key: 'question1',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
title: '2、您是否有家族中有人患有前列腺癌',
key: 'question2',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
title: '3、你是否曾经被诊断为前列腺疾病',
key: 'question3',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
title: '4、您是否曾经接受过前列腺癌的检查',
key: 'question4',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 2: 1 }
}
}, {
title: '5、你是否常食用高脂食品?(如肥肉、蛋黄、猪脑,蟹黄等高脂食品)',
key: 'question5',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
title: '6、您是否吸烟',
key: 'question6',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
title: '7、您是否经常饮酒超量?(每日白酒超过2两或啤酒超过500毫升或葡萄酒超过200毫升)',
key: 'question7',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
title: '8、您是否长期坐着工作或生活',
key: 'question8',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
title: '9、您是否经常进行体育锻炼',
key: 'question9',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 2: 1 }
}
}],
check() {
let score = 0
this.issue.forEach(e => {
score = score + (e.answer.score[e.value] || 0)
})
this.score = score
return score > 4
},
remark: '建议进一步检查前列腺特异性抗原、前列腺特异性抗原正常—定期复查、前列腺特异性抗原升—高前列腺磁共振及穿刺活检'
}
}
const q = questions['q' + key]
const result = q ? new Question(q, info) : {}
return { ...result, key }
}
class Question {
issue = []
check = null
result = null
remark = null
highRisk = null
highRiskTrans = null
score = null
constructor({
title = '',
remark = '',
issue = [],
check = () => {}
} = {}, info = {}) {
console.log('class Question', info)
this.issue = issue.map(e => {
return {
...e,
value: info[e.key],
valueTrans: info[e.key + 'Trans'],
valueOther: null,
}
})
this.title = title
this.remark = remark
this.check = check
this.highRisk = info?.highRisk
this.highRiskTrans = info?.highRiskTrans
}
}
\ No newline at end of file
<template>
<div class="h-full flex flex-col ">
<div class="p-3 text-16 text-black text-center shrink-0 top-bar">
<span class="back-bt" @click="onBack" v-if="setp === 2">
<doc-icon type="doc-left" />
</span>
<span>肿瘤风险评估</span>
</div>
<div class="grow overflow-y-auto pb-5">
<BaseForm ref="base" v-show="setp === 1"/>
<QuestionForm ref="question" v-if="setp === 2"
:species="species"/>
<Result v-if="setp === 3" :info="resultInfo"/>
<div class="bt-group">
<van-button type="primary" block v-if="setp === 1"
@click="onNext">下一步</van-button>
<van-button type="primary" block v-else-if="setp === 2"
@click="submit">提交</van-button>
</div>
</div>
<div class="pb-5"></div>
</div>
</template>
<script>
import BaseForm from './base.vue'
import QuestionForm from './Question.vue'
import Result from './Result.vue'
import { showNotify } from 'vant'
import { addSimpleScreen } from '@/tumour/api/screening.js'
import { fetchDataHandle } from '@/utils/common.js'
export default {
components: {
BaseForm,
QuestionForm,
Result
},
data() {
return {
// 操作步骤
setp: 1,
// 步骤1中选中的癌种
species: [],
// 基础用户信息
baseInfo: {},
// 提交结果信息
resultInfo: {}
}
},
computed: {
routeQuery() {
return this.$route.query
},
doctorId() {
return this.routeQuery.doctorId
}
},
created() {
if (!this.doctorId) {
showNotify({ type: 'warning', message: '未获取到医生信息', duration: 0 })
}
},
methods: {
init() {
},
onBack() {
this.setp = 1
},
onNext() {
if (!this.doctorId) return
this.$refs.base.submit().then(res => {
console.log(res)
this.baseInfo = res
this.species = res.species || []
this.setp = 2
})
},
submit() {
this.$refs.question.submit().then(res => {
const result = {
...this.baseInfo,
details: res,
createdUserId: this.doctorId
}
const query = fetchDataHandle(result, {
species: 'arrToStr'
})
console.log(query)
addSimpleScreen(query).then(res => {
this.resultInfo = {
species: result.species,
details: result.details,
unitName: res.data
}
this.setp = 3
})
})
}
}
}
</script>
<style lang="less" scoped>
.top-bar {
position: relative;
border-bottom: 1px solid #0000001A;
.back-bt {
position: absolute;
left: .16rem;
}
}
.bt-group {
padding: 0 10%;
}
</style>
<template>
<div class="question-form">
<span ref="top"></span>
<van-form label-width="100%" ref="form">
<template v-for="(item, index) in formData" :key="index">
<div class="px-4 py-2 title">{{item.title}}</div>
<van-field :name="q.key" v-for="(q, i) in item.issue" :key="i"
:label="q.title"
:rules="[{ required: true, message: '请选择' }]">
<template #input>
<van-radio-group v-model="q.value" @change="onChange($event, item)" class="pl-2">
<van-radio v-for="a in q.answer.cont" shape="dot" class="mt-2"
:name="a.value" :key="a.value">{{a.name}}</van-radio>
</van-radio-group>
</template>
</van-field>
<van-field name="highRisk" label="筛查结论" label-width="4.5em">
<template #input>
<van-radio-group v-model="item.highRisk" direction="horizontal">
<van-radio v-for="r in store.getDict('DC00071')" shape="dot"
:name="r.value" :key="r.value">{{r.name}}</van-radio>
</van-radio-group>
</template>
</van-field>
<div class="remark" v-if="item.remark && item.highRisk === 1">
{{ item.remark }}
</div>
</template>
</van-form>
</div>
</template>
<script>
import { getQuestion } from '../config.js'
import { useStore } from '@/tumour/store/index.js'
export default {
props: {
// 筛查癌种 获取对应的问卷
species: Array
},
data() {
return {
formData: [],
}
},
setup() {
const store = useStore()
return { store }
},
created() {
this.init()
},
mounted() {
const dom = this.$refs['top']
if (!dom) return
dom.scrollIntoView()
},
methods: {
init() {
if (!this.species) return
this.species.forEach(e => {
this.formData.push(getQuestion(e))
})
console.log(this.formData)
},
onChange(val, item) {
// console.log(val, item)
// console.log('高危判断', item.check())
item.highRisk = item.check() ? 1 : 2
},
submit() {
return new Promise((resolve) => {
this.$refs.form.validate().then(res => {
console.log(res, this.formData)
const result = {}
this.formData.forEach(e => {
const issue = {}
e.issue.forEach(i => {
issue[i.key] = i.value
})
result[e.key] = {
highRisk: e.highRisk,
...issue
}
})
resolve(result)
}).catch(err => {
console.warn(err)
})
})
}
}
}
</script>
<style lang="less" scoped>
@import '@/tumour/utils/common.less';
.remark {
border: 1px solid #F0F0F0;
padding: 10px;
color: #595959;
background-color: #FAFAFA;
margin: 10px 16px;
line-height: 1.5;
}
</style>
<template>
<div class="p-4 form-result">
<div v-for="item in list" :key="item.key" class="p-3 mb-4 list-item">
<div class="mb-2">
<span class="mr-2 font-semibold">{{ item.title }}</span>
<span v-if="item.status == 1" class="tag-red">高风险</span>
<span v-else class="tag-green">无高风险</span>
</div>
<div style="color: #8C8C8C;" class="mb-2">{{ item.date }}</div>
<div class="mb-2 flex items-center tip" v-if="item.status == 1">
<doc-icon type="doc-exclamation-circle" class="text-16"/>
<span class="ml-2">建议到 {{ item.unitName }} 进行检查</span>
</div>
<div style="line-height: 1.5" v-if="item.status == 1">
备注:{{ item.remark }}
</div>
</div>
</div>
</template>
<script>
import { getDictValue } from '@/tumour/utils/dictionaries.js'
import { getQuestion } from '@/tumour//screening/simple/config.js'
import dayjs from 'dayjs'
export default {
props: {
info: { default: () => ({}) }
},
data() {
return {
list: []
}
},
created() {
const { species = [], details = {}, unitName = '本单位' } = this.info
// console.log(species, details, unitName)
species.forEach(e => {
const q = getQuestion(e)
this.list.push({
key: e,
title: getDictValue('DC00032', e) + '筛查结果',
status: details[e].highRisk,
remark: q.remark,
date: dayjs().format('YYYY.MM.DD'),
unitName
})
})
}
}
</script>
<style lang="less" scoped>
.list-item {
border: 1px solid #F0F0F0;
}
.font-12 {
font-size: 12px;
}
.tip {
background-color: #F8FAFC;
color: #768092;
padding: 4px 12px;
}
.tag-red {
color: #F5222D;
background-color: #FFF1F0;
padding: 4px 6px;
border-radius: 2px;
}
.tag-green {
color: #52C41A;
background-color: #D9F7BE;
padding: 4px 6px;
border-radius: 2px;
}
</style>
<template>
<div class="pt-2 base-form">
<div class="px-4 py-2 title">基本信息</div>
<van-form label-width="5em" ref="form">
<van-field v-model="form.idCard"
required
center
clearable
name="idCard"
label="身份证号"
placeholder="请输入身份证号"
:rules="rules.idCard"
>
<template #button>
<van-button size="small" plain type="primary"
@click="getInfo">搜索</van-button>
</template>
</van-field>
<van-field v-model="form.residentName"
name="residentName" required
label="姓名"
placeholder="请输入姓名"
maxlength="50"
:rules="rules.residentName"
/>
<van-field required
v-model="form.genderTrans"
is-link
readonly
name="gender"
label="性别"
placeholder="请选择"
:rules="rules.gender"
@click="showGender = true"/>
<van-popup v-model:show="showGender" position="bottom">
<van-picker
:columns-field-names="{ text: 'name', value: 'value' }"
:columns="store.getDict('DC00005')"
@confirm="genderConfirm"
@cancel="showGender = false"
/>
</van-popup>
<van-field v-model="form.age"
name="age" required
label="年龄"
type="digit"
placeholder="请输入年龄"
maxlength="10"
:rules="rules.age"
/>
<van-field required
v-model="form.dataBirth"
is-link
readonly
name="dataBirth"
label="出生日期"
placeholder="请选择"
:rules="rules.dataBirth"
@click="showPicker = true"
/>
<van-popup v-model:show="showPicker" position="bottom">
<van-date-picker @confirm="dataBirthConfirm" @cancel="showPicker = false" />
</van-popup>
<van-field required
v-model="form.nationalTrans"
is-link
readonly
name="national"
label="民族"
placeholder="请选择"
:rules="rules.national"
@click="showNational = true"/>
<van-popup v-model:show="showNational" position="bottom">
<van-picker
:columns-field-names="{ text: 'name', value: 'value' }"
:columns="store.getDict('DC00006')"
@confirm="nationalConfirm"
@cancel="showNational = false"
/>
</van-popup>
<van-field v-model="form.educationTrans"
is-link
readonly
name="education"
label="学历"
placeholder="请选择"
@click="showEducation = true"/>
<van-popup v-model:show="showEducation" position="bottom">
<van-picker
:columns-field-names="{ text: 'name', value: 'value' }"
:columns="store.getDict('DC00007')"
@confirm="educationConfirm"
@cancel="showEducation = false"
/>
</van-popup>
<van-field required
v-model="form.maritalStatusTrans"
is-link
readonly
name="marital"
label="婚姻状况"
placeholder="请选择"
:rules="rules.marital"
@click="showEarital = true"/>
<van-popup v-model:show="showEarital" position="bottom">
<van-picker
:columns-field-names="{ text: 'name', value: 'value' }"
:columns="store.getDict('DC00008')"
@confirm="maritalConfirm"
@cancel="showEarital = false"
/>
</van-popup>
<van-field v-model="form.telephone"
name="telephone" required
type="tel"
label="联系电话"
placeholder="请输入"
maxlength="11"
:rules="rules.telephone"
/>
<van-field required
v-model="form.registeredCodeTrans"
name="registeredCode"
is-link
readonly
label="户口地址"
placeholder="请选择所在地区"
:rules="rules.registeredCode"
@click="showRegistered = true"
/>
<van-popup v-model:show="showRegistered" :close-on-click-overlay="false" round position="bottom">
<DocAddress v-model:value="form.registeredCode" @close="showRegistered = false"
@change="registeredChange"/>
</van-popup>
<van-field v-model="form.permanentAddress"
name="permanentAddress"
label="详细地址"
placeholder="请输入"
@blur="permanentBlur"
maxlength="50"
/>
<van-field required
v-model="form.presentCodeTrans"
name="presentCode"
is-link
readonly
label="常住地址"
placeholder="请选择所在地区"
@click="showPresent = true"
/>
<van-popup v-model:show="showPresent" :close-on-click-overlay="false" round position="bottom">
<DocAddress v-model:value="form.presentCode" @close="showPresent = false"
@change="presentChange"/>
</van-popup>
<van-field v-model="form.nowAddress"
name="nowAddress"
label="详细地址"
placeholder="请输入"
maxlength="50"
/>
<div class="px-4 py-2 title">筛查癌种</div>
<van-field name="species" label="请选择要筛查的癌种"
required
readonly
label-width="100%"
:rules="rules.species">
<template #input>
<van-checkbox-group v-model="form.species" class="pt-2 pl-2">
<van-checkbox v-for="(item, index) in cancerArray" :key="index"
:name="item.value" shape="square"
class="mb-3">{{ item.name }}</van-checkbox>
</van-checkbox-group>
</template>
</van-field>
</van-form>
<!-- {{ form }} -->
</div>
</template>
<script>
import { fetchDataHandle, getInfoByIdCard } from '@/utils/common.js'
import { idCardRule, mobileValidator } from '@/utils/commonReg.js'
import { useStore } from '@/tumour/store/index.js'
import { getResidentInfo } from '@/tumour/api/base.js'
import { getDictValue } from '@/tumour/utils/dictionaries.js'
import DocAddress from '@/tumour/utils/docAddress/DocAddress.vue'
const defaultForm = (info = {}) => {
const form = {
id: undefined,
// 年龄
age: undefined,
// 证件类型,[DC00004]
certificateType: 1,
// 创建单位id
createdUnitId: undefined,
createdUnitName: undefined,
// 创建医生
createdUserName: undefined,
// 出生日期
dataBirth: undefined,
// 职业,[DC00010]
duty: undefined,
// 文化程度(学历),[DC00007]
education: undefined,
educationTrans: undefined,
// 性别,[DC00005]
gender: undefined,
genderTrans: undefined,
// 身份证号
idCard: '',
// 婚姻状况,[DC00008]
maritalStatus: undefined,
maritalStatusTrans: undefined,
// 民族,[DC00006]
national: undefined,
nationalTrans: undefined,
// 现住址
nowAddress: undefined,
// 户籍地址
permanentAddress: undefined,
// 现住址编码
presentCode: undefined,
presentCodeTrans: undefined,
// 户籍地编码
registeredCode: undefined,
registeredCodeTrans: undefined,
// 居民档案id
residentId: undefined,
// 姓名
residentName: undefined,
// 本人电话
telephone: undefined,
// 工作单位
workUnit: undefined,
// 筛查癌种
species: undefined
}
Reflect.ownKeys(form).forEach(key => {
if (info[key] != undefined) {
form[key] = info[key]
}
})
return form
}
export default {
components: {
DocAddress
},
data() {
return {
form: defaultForm(),
// 性别选择
showGender: false,
// 日期选择
showPicker: false,
// 民族
showNational: false,
// 学历
showEducation: false,
// 婚姻情况
showEarital: false,
// 户口地址
showRegistered: false,
// 常住
showPresent: false,
rules: {
idCard: [{ required: true, message: '请输入' }, idCardRule],
residentName: [{ required: true, message: '请输入' }],
age: [{ required: true, message: '请输入' }],
gender: [{ required: true, message: '请选择' }],
national: [{ required: true, message: '请选择' }],
maritalStatus: [{ required: true, message: '请选择' }],
telephone: [{ required: true, message: '请输入' }, mobileValidator],
registeredCode: [{ required: true, message: '请输入' }],
presentCode: [{ required: true, message: '请输入' }],
species: [{ required: true, message: '请选择' }]
}
}
},
setup() {
const store = useStore()
return { store }
},
computed: {
cancerArray() {
const exclude = [8, 10, 11, 99]
return this.store.getDict('DC00032').filter(e => !exclude.includes(e.value))
},
},
mounted() {},
methods: {
getInfo() {
const idCard = this.form.idCard
if (!idCard) return
getResidentInfo(idCard).then(res => {
const result = res.data || {}
if (result.id) {
this.form = defaultForm({
...result,
id: null,
species: []
})
return
}
const info = getInfoByIdCard(idCard)
this.form = defaultForm({
gender: info.gender,
genderTrans: getDictValue('DC00005', info.gender),
dataBirth: info.dataBirth,
age: info.age,
species: []
})
console.log(info)
})
},
submit() {
return new Promise((resolve) => {
this.$refs.form.validate().then(res => {
console.log(res, this.form)
resolve(this.form)
}).catch(err => {
console.warn(err)
})
})
},
genderConfirm({ selectedValues, selectedOptions }) {
this.form.gender = selectedValues[0]
this.form.genderTrans = selectedOptions[0].name
this.showGender = false
},
// 民族
nationalConfirm({ selectedValues, selectedOptions }) {
this.form.national = selectedValues[0]
this.form.nationalTrans = selectedOptions[0].name
this.showNational = false
},
// 学历
educationConfirm({ selectedValues, selectedOptions }) {
this.form.education = selectedValues[0]
this.form.educationTrans = selectedOptions[0].name
this.showEducation = false
},
// 婚姻
maritalConfirm({ selectedValues, selectedOptions }) {
this.form.maritalStatus = selectedValues[0]
this.form.maritalStatusTrans = selectedOptions[0].name
this.showEarital = false
},
dataBirthConfirm({ selectedValues }) {
this.form.dataBirth = selectedValues.join('-')
this.showPicker = false
},
// 户口地址
registeredChange(val) {
console.log(val)
const selectedOptions = val.selectedOptions
this.form.registeredCodeTrans = selectedOptions.map(e => e.text).join('/')
if (!this.form.presentCode && selectedOptions.length >= 5) {
this.form.presentCode = val.value
this.form.presentCodeTrans = this.form.registeredCodeTrans
}
},
// 常住地址
presentChange(val) {
const selectedOptions = val.selectedOptions
this.form.presentCodeTrans = selectedOptions.map(e => e.text).join('/')
},
permanentBlur(val) {
if (!this.form.nowAddress) {
this.form.nowAddress = this.form.permanentAddress
}
}
}
}
</script>
<style lang="less" scoped>
@import '@/tumour/utils/common.less';
.van-cell {
// padding-left: 0;
// padding-right: 0;
:deep(.van-cell__title) {
&>label {
display: inline-block;
min-width: 56px;
text-align: justify;
text-align-last: justify;
}
&:not(.van-field__label--required) {
&>label {
margin-left: 7px;
}
}
}
}
// .form-label {
// color: #595959;
// >span {
// display: inline-block;
// min-width: .56rem;
// text-align: justify;
// text-align-last: justify;
// }
// &[required] {
// &::before {
// content: '*';
// color: #F5222D;
// margin-right: 0.04rem;
// }
// }
// }
</style>
import { defineStore } from 'pinia'
export const useStore = defineStore('tumour', {
state: () => {
return {
// 字典
dict: []
}
},
getters: {},
actions: {
getDict(val) {
if (!val) return []
return this.dict[val] || []
}
}
})
.title {
font-weight: 600;
display: flex;
align-items: center;
&::before {
content: '';
display: inline-block;
background: #1890FF;
height: 16px;
width: 4px;
margin-right: 4px;
}
}
\ No newline at end of file
import { useStore } from '@/tumour/store/index.js'
/**
* 获取字典值
* @param {String | Array} dict
* @param {String} value
* @returns
*/
export function getDictValue(dict, value) {
const store = useStore()
let array = []
if (typeof dict === 'string') {
array = store.getDict(dict)
} else {
array = dict
}
if (!array || !array.length) {
return ''
}
let temp = array.find(e => e.value == value) || {}
return temp.name || ''
}
/**
* 获取字典数组
* @param {String} dict
*/
export function getDict(dict) {
const store = useStore()
return store.getDict(dict) || myDict()[dict] || []
}
// 自定义字典
function myDict() {
return {
MY001: [
{ name: '-', value: '-' },
{ name: '±', value: '±' },
{ name: '+', value: '+' },
{ name: '++', value: '++' },
{ name: '+++', value: '+++' },
{ name: '++++', value: '++++' }
]
}
}
<template>
<van-cascader class="address-select"
:closeable="false"
v-model="innerValue"
title="请选择所在地区"
:options="areaData"
@change="onChange"
@close="() => $emit('close')"
/>
</template>
<script>
import { getAreaChild } from '@/tumour/api/base.js'
import { fetchDataHandle } from '@/utils/common.js'
export default {
name: 'DocAddress',
props: {
value: [String, Number],
viewData: Array,
},
emits: ['update:value', 'change', 'close'],
data() {
return {
innerValue: '',
areaData: []
}
},
created() {
this.init()
},
methods: {
async init() {
if (!this.areaData.length) {
const res = await getAreaChild('0')
this.areaData = this.dataField(res || [])
}
if (this.value) {
const temp = fetchDataHandle({ value: this.value }, {
value: 'addToArr'
})
await this.viewHandle(temp.value)
}
// console.log(this.areaData)
},
loadData(options) {
const targetOption = options[options.length - 1]
targetOption.loading = true
getAreaChild(targetOption.value).then(res => {
targetOption.children = this.dataField(res || [], options.length === 4)
this.areaData = [...this.areaData]
}).finally(() => {
targetOption.loading = false
})
},
dataField(data, last = false) {
return data.map(e => {
return {
text: e.areaName,
value: e.areaCode,
id: e.id,
isLeaf: last
}
})
},
// 回显处理
async viewHandle(val = []) {
try {
const length = val.length
let current = this.areaData.find(e => e.value === val[0])
let index = 1
while (index < length) {
const res = await getAreaChild(current.value)
const result = res || []
if (!result.length) break
current.children = this.dataField(result, index === 4)
current = current.children.find(e => e.value === val[index])
this.areaData = [...this.areaData]
if (!current) break
index++
}
} catch(err) {
console.warn(err)
}
},
onChange(val) {
// console.log(val, this.areaData)
const tabIndex = val.tabIndex
const options = val.selectedOptions
const targetOption = options[options.length - 1]
if (tabIndex < 4 ) {
getAreaChild(val.value).then(res => {
targetOption.children = this.dataField(res || [], options.length === 4)
this.areaData = [...this.areaData]
})
}
this.$emit('update:value', val.value)
this.$emit('change', val)
if (tabIndex === 4 ) {
this.$emit('close')
}
}
},
watch: {
value: {
handler(val) {
this.innerValue = val
},
immediate: true
},
// 地址同步使用
viewData(val) {
this.viewHandle(val)
}
}
}
</script>
<style lang="less" scoped>
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment