Commit 54e2aca2 authored by songrui's avatar songrui

筛查修改

parent bb9e40c3
......@@ -12,7 +12,7 @@
"core-js": "^3.8.3",
"dayjs": "^1.11.11",
"pinia": "^2.1.7",
"vant": "^4.9.1",
"vant": "^4.9.8",
"vue": "^3.2.13",
"vue-router": "^4.0.3"
},
......@@ -12765,18 +12765,23 @@
}
},
"node_modules/vant": {
"version": "4.9.1",
"resolved": "https://registry.npmmirror.com/vant/-/vant-4.9.1.tgz",
"integrity": "sha512-p7iAKJyACYVwrmrkf3COmbuvzjHrFJ+FAmlyOWbxTS2ovkRs+tNKYjX2iibAl4XnHXBQD+qpX0ogUqE3jE7Isg==",
"version": "4.9.8",
"resolved": "https://registry.npmmirror.com/vant/-/vant-4.9.8.tgz",
"integrity": "sha512-iP+jNzwxkCeEdTrlUjro3WoXgY32+1CldOtLSc2K8acY7hR7t1zCkjzXSR9zWjtWT7zgNL1LEXofL8O7mtkYdQ==",
"dependencies": {
"@vant/popperjs": "^1.3.0",
"@vant/use": "^1.6.0",
"@vue/shared": "^3.4.27"
"@vue/shared": "^3.5.11"
},
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/vant/node_modules/@vue/shared": {
"version": "3.5.12",
"resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.12.tgz",
"integrity": "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg=="
},
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz",
......@@ -23029,13 +23034,20 @@
}
},
"vant": {
"version": "4.9.1",
"resolved": "https://registry.npmmirror.com/vant/-/vant-4.9.1.tgz",
"integrity": "sha512-p7iAKJyACYVwrmrkf3COmbuvzjHrFJ+FAmlyOWbxTS2ovkRs+tNKYjX2iibAl4XnHXBQD+qpX0ogUqE3jE7Isg==",
"version": "4.9.8",
"resolved": "https://registry.npmmirror.com/vant/-/vant-4.9.8.tgz",
"integrity": "sha512-iP+jNzwxkCeEdTrlUjro3WoXgY32+1CldOtLSc2K8acY7hR7t1zCkjzXSR9zWjtWT7zgNL1LEXofL8O7mtkYdQ==",
"requires": {
"@vant/popperjs": "^1.3.0",
"@vant/use": "^1.6.0",
"@vue/shared": "^3.4.27"
"@vue/shared": "^3.5.11"
},
"dependencies": {
"@vue/shared": {
"version": "3.5.12",
"resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.12.tgz",
"integrity": "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg=="
}
}
},
"vary": {
......
......@@ -11,7 +11,7 @@
"core-js": "^3.8.3",
"dayjs": "^1.11.11",
"pinia": "^2.1.7",
"vant": "^4.9.1",
"vant": "^4.9.8",
"vue": "^3.2.13",
"vue-router": "^4.0.3"
},
......
......@@ -9,7 +9,7 @@ const routes = [
{
path: 'screening/simple/form',
name: 'tumour-screening-simple-form',
component: () => import(/* webpackChunkName: "page-tumour" */ '@/tumour/screening/simple/form/Index.vue')
component: () => import(/* webpackChunkName: "page-tumour" */ '@/tumour/screening/simpleV2/form/Index.vue')
}
]
}
......
import { getDict } from '@/tumour/utils/dictionaries.js'
/**
*
* @param {String} key 需要生成的问卷
* @param {Object} userInfo 患者信息
* @param {Object} detail 问卷选中的值
* @returns
*/
export function getQuestion(key, userInfo, detail) {
/**
* 设置问题title
* @param {String} text title文字
* @param {String} linkKey 关联的表单key
* @returns
*/
const setTitle = (text, linkKey) => {
return {
text,
linkKey
}
}
const questions = {
q1: {
title: '肺癌筛查量表',
issue: [{
key: 'question1',
title: setTitle('1、年龄介于45~74岁之间'),
answer: {
// radio单选 checkbox多选
type: 'radio',
// 选项中 其他选项 的value
other: null,
// 答案的选项 DC00001是否
cont: getDict('DC00001'),
// 禁用
disabled: true,
},
// 赋初始值
init: () => {
return userInfo.age >= 45 && userInfo.age <= 74 ? 1 : 2
}
}, {
title: setTitle('2、吸烟包年数≥20包年,包括曾经吸烟≥20包年,但戒烟不足15年'),
key: 'question2',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('3、与条件2共同生活或同室工作被动吸烟>20年'),
key: 'question3',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('4、患有慢性阻塞性肺疾病'),
key: 'question4',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('5、有职业暴露史≥1年,包括暴露于石棉、氡、铍、铬、镉、硅、煤烟和煤烟灰'),
key: 'question5',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('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平扫检查。如发现肺部结节,建议到胸外科、呼吸内科、肿瘤科等专科进行就诊。',
sub: '肺癌高风险人群介于45~74岁,且2-6至少满足一项'
},
q2: {
title: '乳腺癌筛查量表',
issue: [{
title: setTitle('1、既往乳腺3类及以上结节病史'),
key: 'question4',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('2、既往有乳腺导管或小叶中重度不典型增生或小叶原位癌患者'),
key: 'question2',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('3、既往有胸部放疗史的患者'),
key: 'question3',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('4、一级亲属或本人携带有 BRCA1/BRCA2 基因突变'),
key: 'question5',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('5、有2个或2个以上≤50岁二级亲属诊断为乳腺癌或卵巢癌或原发性腹膜癌'),
key: 'question6',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}],
check() {
return this.issue.filter(e => e.value === 1).length >= 1
},
remark: `一般风险人群建议: \n一、20~39岁:(1)每月1次乳腺自我检查;(2)每1—3年1次临床检查。\n 二、40~69岁:(1)每1~2年1次乳腺彩超或乳腺钼靶检查;(2)每月1次乳腺自我检查; (3)每年1次临床检查。\n三、70岁以上:(1)有症状或可疑体征时进行影像学检查;(2)每月1次乳腺自我检查;(3)每年1次临床检查。\n乳腺癌高危人群建议:临床体检、B 超、乳腺钼靶检查、乳腺MRI、肿瘤标志物。`,
sub: '满足任意一项乳腺癌高危人群'
},
q3: {
title: '结直肠癌筛查量表',
issue: [{
title: setTitle('1、大便潜血阳性'),
key: 'question1',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('2、一级亲属有结直肠癌病史'),
key: 'question2',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('3、以往有肠道腺瘤史'),
key: 'question3',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('4、本人有癌症史'),
key: 'question4',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('5、有大便习惯的改变'),
key: 'question5',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('6、符合以下任意2项者:', 'question7'),
key: 'question6',
answer: {
type: 'radio',
cont: getDict('DC00001'),
// 禁用
disabled: true,
},
// 赋初始值
init: () => {
return 2
}
}, {
key: 'question7',
index: 7,
answer: {
type: 'checkbox',
cont: getDict('DC00096')
},
change: (that) => {
if (!that) return
console.log('that', that)
const item1 = that.getIssue('question7') || {}
const item2 = that.getIssue('question6') || {}
if (!item1 || !item2) return
const val = item1.value || []
item2.value = val.length >= 2 ? 1 : 2
}
}],
check() {
return this.issue.filter(e => e.value === 1 && e.title).length >= 1
},
remark: '一般风险人群建议:随访观察。\n结直肠癌高危人群建议:进一步进行生化全套、结直肠镜检查、腹部 CT、肿瘤标志物。',
sub: '有任意一条者视为结直肠癌高危人群',
},
q4: {
title: '肝癌筛查量表',
issue: [{
title: setTitle('1、年龄大于40岁'),
key: 'question1',
answer: {
type: 'radio',
cont: getDict('DC00001'),
// 禁用
disabled: true,
},
// 赋初始值
init: () => {
return userInfo.age > 40 ? 1 : 2
}
}, {
title: setTitle('2、慢性乙型肝炎或者慢性丙型肝炎史'),
key: 'question2',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('3、肝硬化病史'),
key: 'question3',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('4、长期酗酒史(每日饮酒大于2两,饮酒史超过1年)'),
key: 'question4',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('5、出血史:(出血倾向:鼻出血、牙龈及皮下瘀斑)'),
key: 'question5',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('6、直系属亲属(父母、兄弟姐妹、子女)有肝癌病史'),
key: 'question6',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('7、长期进食霉变食物或进食烟熏或盐腌的肉制品'),
key: 'question7',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('8、有肝区疼痛史:(肝区疼痛:右上腹或中上腹持续性或间歇性钝痛、刺痛或胀痛,夜间或劳累后加重)'),
key: 'question8',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('9、符合以下任意2项者:', 'question10'),
key: 'question9',
answer: {
type: 'radio',
cont: getDict('DC00001'),
// 禁用
disabled: true,
},
// 赋初始值
init: () => {
return 2
}
}, {
key: 'question10',
index: 10,
answer: {
type: 'checkbox',
cont: getDict('DC00095')
},
change: (that) => {
if (!that) return
const item1 = that.getIssue('question10')
const item2 = that.getIssue('question9')
if (!item1 || !item2) return
const val = item1.value || []
item2.value = val.length >= 2 ? 1 : 2
}
}],
check() {
return this.issue[0].value === 1 &&
this.issue.filter(e => e.value === 1 && e.title).length >= 2
},
remark: '一般风险人群建议:随访观察。\n肝癌高危人群建议:进一步检查彩色多普勒腹部超声、甲胎蛋白测定。',
sub: '肝癌高风险人群年龄40岁以上,且2-9至少满足一项'
},
q5: {
title: '宫颈癌筛查量表',
issue: [{
title: setTitle('1、已婚或有性生活史3年及以上的女性'),
key: 'question1',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('2、家族中有人患有宫颈癌或其他妇科癌症'),
key: 'question2',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('3、曾经被诊断为宫颈炎症、宫颈糜烂或宫颈息肉'),
key: 'question3',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('4、有阴异常道分泌物增多,非经期流血'),
key: 'question4',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('5、感染过人类乳头瘤病毒(HPV)'),
key: 'question5',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('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检查。',
sub: '已婚或有性生活史3年及以上的女性,且至少符合条件之一'
},
q6: {
title: '甲状腺癌筛查量表',
issue: [{
title: setTitle('1、年龄40岁以上'),
key: 'question1',
answer: {
type: 'radio',
cont: getDict('DC00001'),
// 禁用
disabled: true
},
// 赋初始值
init: () => {
return userInfo.age > 40 ? 1 : 2
}
}, {
title: setTitle('2、有甲状腺疾病:甲状腺炎、甲状腺结节'),
key: 'question2',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('3、有甲状腺癌家族史'),
key: 'question3',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('4、长期接触辐射或化学物质'),
key: 'question4',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('5、颈部放疗史'),
key: 'question5',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('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: '甲状腺高风险人群:建议行甲状腺超声、甲状腺功能',
sub: '40岁以上的人群,且至少符合条件之一'
},
q7: {
title: '胃癌筛查量表',
issue: [{
title: setTitle('1、年龄40岁以上,男女不限'),
key: 'question1',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('2、胃癌高发地区人群'),
key: 'question2',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('3、幽门螺杆菌(H.pylori)感染者'),
key: 'question3',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('4、既往患有慢性萎缩性胃炎、胃溃疡、胃息肉、手术后残胃、肥厚性胃炎、恶性贫血等胃癌前疾病'),
key: 'question4',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('5、胃癌患者一级亲属'),
key: 'question5',
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
title: setTitle('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: '一般风险人群建议:随访观察。\n胃癌筛查高危人群建议:进一步进行胃十二指肠镜检查、肿瘤标志物、腹部CT。',
sub: '胃癌高风险人群年龄40岁以上,且2-6至少满足一项'
},
q8: {
title: '食管癌筛查量表',
issue: [{
key: 'question1',
title: setTitle('1、年龄40岁以上'),
answer: {
type: 'radio',
cont: getDict('DC00001'),
// 禁用
disabled: true
},
// 赋初始值
init: () => {
return userInfo.age > 40 ? 1 : 2
}
}, {
key: 'question2',
title: setTitle('2、经常食用过烫、粗硬或腌制的食物,吃饭吞食快、暴饮暴食或经常吸烟 与饮酒等不良生活习惯'),
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
key: 'question3',
title: setTitle('3、被HIV、HPV、单纯疱疹等病毒感染'),
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
key: 'question4',
title: setTitle('4、生活在食管癌高发地区的人群:如河北、山西、河南等地'),
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
key: 'question5',
title: setTitle('5、近期有吞咽困难、胸背部疼痛、食管异物感等症状'),
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
key: 'question6',
title: setTitle('6、食管癌家族史'),
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}, {
key: 'question7',
title: setTitle('7、行胃镜检查诊断为肠上皮化生的Barrett食管的患者'),
answer: {
type: 'radio',
cont: getDict('DC00001')
}
}],
check() {
return this.issue[0].value === 1 &&
this.issue.filter(e => e.value === 1).length >= 2
},
remark: '一般人群建议:随访观察。\n食管癌高危人群建议:进一步行胃镜、食管内镜超声、肿瘤标记物或食管CT扫描、胸部增强CT检查。',
sub: '40岁以上的人群,且至少符合2项'
},
q9: {
title: '前列腺癌筛查量表',
issue: [{
title: setTitle(`1、尿频或排尿困难`),
key: 'question10',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
title: setTitle(`2、尿流变小或中断`),
key: 'question11',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
title: setTitle(`3、尿液中出现血丝`),
key: 'question12',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
title: setTitle(`4、尿液浑浊或有异味`),
key: 'question13',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
title: setTitle(`5、阴茎勃起困难或全`),
key: 'question14',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
title: setTitle(`6、疼痛或不适感`),
key: 'question15',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
title: setTitle('7、您是否有家族中有人患有前列腺癌'),
key: 'question2',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
title: setTitle('8、你是否曾经被诊断为前列腺疾病'),
key: 'question3',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
title: setTitle('9、你是否常食用高脂食品?(如肥肉、蛋黄、猪脑,蟹黄等高脂食品)'),
key: 'question5',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
title: setTitle('10、您是否长期坐着工作或生活'),
key: 'question8',
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}],
check() {
let score = 0
this.issue.forEach(e => {
score = score + (e.answer.score[e.value] || 0)
})
this.score = score
return score > 4
},
remark: '一般人群建议:随访观察\n高危人群建议:进一步检查前列腺特异性抗原、前列腺B超、盆腔磁共振成像(MRI)',
sub: '计分方式:每个条目1分,结果以总分计算,也就是以十个条目的分值相加,总分范围是0—10分。0-4分属于一般人群,5-10分属于高危人群'
},
q10: {
title: '肾癌筛查量表',
issue: [{
key: 'question1',
title: setTitle('1、近期出现血尿,肾区疼痛等症状(5分)'),
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 5 }
}
}, {
key: 'question2',
title: setTitle('2、长期吸烟、酗酒及长期熬夜(1分)'),
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
key: 'question3',
title: setTitle('3、家族有肾癌患者(2分)'),
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 2 }
}
}, {
key: 'question4',
title: setTitle('4、患有高血压、糖尿病、肥胖症等慢性病(1分)'),
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}, {
key: 'question5',
title: setTitle('5、职业因素:长期接触石油、金属等产品(1分)'),
answer: {
type: 'radio',
cont: getDict('DC00001'),
score: { 1: 1 }
}
}],
check() {
let score = 0
this.issue.forEach(e => {
score = score + (e.answer.score[e.value] || 0)
})
this.score = score
return score > 2
},
remark: '0-2分一般人群建议:随访观察。\n3-10分高危群建议:进一步行尿常规、肝功能、肾功能、肿瘤标记物、泌尿系彩超、CT等检查。',
sub: '计分方式:总分范围是0—10分。 0-2分一般人群,3-10分高危群'
}
}
const result = questions['q' + key]
return result ? new Question(result, detail) : {}
}
class Question {
issue = []
check = null
result = null
remark = null
sub = null
highRisk = null
highRiskTrans = null
score = null
constructor({
title = '',
remark = '',
sub = '',
issue = [],
check = () => {}
} = {}, detail = {}) {
console.log('class Question', detail)
this.issue = issue.map(e => {
let value = detail[e.key] || (e.init && e.init())
if (!e.title && value) {
value = value.split(',').map(i => +i)
}
return {
...e,
value,
valueTrans: detail[e.key + 'Trans'],
valueOther: null,
}
})
// 处理title中有选项的
console.log('this.issue', this.issue)
const arr = this.issue.filter(e => e.title && e.title.linkKey)
arr.forEach(e => {
const linkKey = e.title.linkKey
e.titleExtend = this.getIssue(linkKey)
})
this.title = title
this.remark = remark
this.sub = sub
this.check = check
this.highRisk = detail?.highRisk
this.highRiskTrans = detail?.highRiskTrans
this.score = detail?.score
}
getIssue(key) {
return this.issue.find(e => e.key === key)
}
}
\ 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.filter(e => e.title)" :key="i"
:label="q.title.text"
:rules="[{ required: !q.title.linkKey, message: '请选择' }]">
<template #input>
<van-checkbox-group v-model="q.titleExtend.value" class="pl-2"
@change="q.titleExtend.change(item)"
v-if="q.title.linkKey">
<van-checkbox v-for="(item, index) in q.titleExtend.answer.cont" :key="index"
:name="item.value" shape="square" class="mt-3"
>{{ item.name }}</van-checkbox>
</van-checkbox-group>
<van-radio-group v-model="q.value" @change="onChange($event, item)" class="pl-2"
:disabled="q.answer.disabled"
v-else>
<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="[9, 10].includes(item.cancer)">
总分 {{ item.score || 0 }} 分
</div>
<div class="remark" v-if="item.remark">
{{ item.remark }}
</div>
</template>
</van-form>
</div>
</template>
<script>
import { getQuestion } from '../config.js'
import { useStore } from '@/tumour/store/index.js'
import { showToast } from 'vant'
export default {
props: {
// 筛查癌种 获取对应的问卷
species: Array
},
data() {
return {
store: useStore(),
formData: [],
}
},
created() {
this.init()
},
mounted() {
const dom = this.$refs['top']
if (!dom) return
dom.scrollIntoView()
},
methods: {
init() {
if (!this.species) return
this.species.forEach(e => {
const temp = getQuestion(e, this.$parent.baseInfo)
temp.cancer = e
this.formData.push(temp)
})
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('submit', res, this.formData)
const result = {}
this.formData.forEach(e => {
const temp = { highRisk: e.highRisk }
e.issue.forEach(q => {
const value = q.value
temp[q.key] = Array.isArray(value) ? value.join(',') : value
})
if (e.score) {
temp.score = e.score
}
result[e.cancer] = temp
})
resolve(result)
}).catch(err => {
console.warn(err)
showToast('还有表单未填写')
if (Array.isArray(err)) {
this.$refs.form.scrollToField(err[0].name)
}
})
})
}
}
}
</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;
white-space: pre-wrap;
}
</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;white-space: pre-wrap;">
{{ item.remark }}
</div>
</div>
</div>
</template>
<script>
import { getDictValue } from '@/tumour/utils/dictionaries.js'
import { getQuestion } from '../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 { showToast } from 'vant'
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 = [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)
showToast('还有表单未填写')
if (Array.isArray(err)) {
this.$refs.form.scrollToField(err[0].name)
}
})
})
},
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>
......@@ -22,8 +22,8 @@ module.exports = defineConfig({
// 设置代理
proxy: {
'/tumour-admin': {
// target: 'http://192.168.1.7:8081',
target: 'https://beta-tumour.zmnyjk.com',
target: 'http://192.168.1.118:8081',
// target: 'https://beta-tumour.zmnyjk.com',
changOrigin: true,
pathRewrite: {
'^/tumour-admin': '/tumour-admin'
......
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