add.vue 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762
  1. <template>
  2. <div class="p-2">
  3. <!-- 新增顶部操作栏 -->
  4. <el-row type="flex" align="middle" justify="space-between" style="margin-bottom: 16px;">
  5. <el-col :span="4">
  6. <el-button type="primary" plain @click="close" style="margin-right: 20px;margin-left: 30px;">返回</el-button>
  7. <span style="font-size: 14px; vertical-align: middle;">新增量表</span>
  8. </el-col>
  9. <el-col :span="4" style="text-align: right;">
  10. <!-- <el-button type="primary" plain @click="handlePreview" style="margin-right: 8px;">预览</el-button> -->
  11. <el-button type="primary" @click="submitForm" style="margin-right: 30px;">保存</el-button>
  12. </el-col>
  13. </el-row>
  14. <el-container class="layout-container-demo" style="height: 100vh; min-height: 100vh;">
  15. <el-aside id="leftPanel"
  16. style="background:transparent; width: 450px; min-width: 300px; max-width: 500px; flex: 0 0 auto; border-right: 2px solid #e4e7ed;">
  17. <div style="background:#f6f9fc; border-radius:4px; margin-bottom: 16px; padding: 16px 0;">
  18. <div style="font-weight:bold; font-size:16px; padding:0 24px 8px 24px; cursor:pointer;"
  19. @click="showSystemParam = !showSystemParam">
  20. 系统参数
  21. <i class="el-icon-arrow-down" :style="{
  22. float: 'right',
  23. transition: 'transform 0.2s',
  24. transform: showSystemParam ? 'rotate(0deg)' : 'rotate(-90deg)'
  25. }"></i>
  26. </div>
  27. <div v-show="showSystemParam" style="padding: 16px 16px 0 16px;">
  28. <div style="font-weight: bold; margin-bottom: 8px;">基本信息</div>
  29. <el-row :gutter="20" style="margin-bottom: 24px;">
  30. <el-col :span="8">
  31. <el-button class="param-btn" plain @click="handleBaseBtnClick('gender', '性别')">性别</el-button>
  32. </el-col>
  33. <el-col :span="8">
  34. <el-button class="param-btn" plain @click="handleBaseBtnClick('birthDate', '出生日期')">出生日期</el-button>
  35. </el-col>
  36. <el-col :span="8">
  37. <el-button class="param-btn" plain @click="handleBaseBtnClick('height', '身高')">身高</el-button>
  38. </el-col>
  39. <el-col :span="8">
  40. <el-button class="param-btn" plain @click="handleBaseBtnClick('weight', '体重')">体重</el-button>
  41. </el-col>
  42. <el-col :span="8">
  43. <el-button class="param-btn" plain @click="handleBaseBtnClick('BMI', 'BMI')">BMI</el-button>
  44. </el-col>
  45. <el-col :span="8">
  46. <el-button class="param-btn" plain
  47. @click="handleBaseBtnClick('nutritionalDiagnosis', '营养诊断')">营养诊断</el-button>
  48. </el-col>
  49. <el-col :span="8">
  50. <el-button class="param-btn" plain @click="handleBaseBtnClick('admissionDate', '入院日期')">入院日期</el-button>
  51. </el-col>
  52. </el-row>
  53. <div style="font-weight: bold; margin-bottom: 8px;">其他</div>
  54. <el-row :gutter="20">
  55. <el-col :span="8">
  56. <el-button class="param-btn" plain
  57. @click="handleOtherBtnClick('otherInfo', 'anthropometry', '人体测量')">人体测量</el-button>
  58. </el-col>
  59. <el-col :span="8">
  60. <el-button class="param-btn" plain
  61. @click="handleOtherBtnClick('otherInfo', 'dietaryStatus', '膳食状况')">膳食状况</el-button>
  62. </el-col>
  63. <el-col :span="8">
  64. <el-button class="param-btn" plain
  65. @click="handleOtherBtnClick('otherInfo', 'nutritionalBiochemical', '营养生化检查')">营养生化检查</el-button>
  66. </el-col>
  67. </el-row>
  68. </div>
  69. </div>
  70. <div style="background:#f6f9fc; border-radius:4px; margin-bottom: 16px; padding: 16px 0;">
  71. <div style="font-weight:bold; font-size:16px; padding:0 24px 8px 24px; cursor:pointer;"
  72. @click="showQuestionType = !showQuestionType">
  73. 题型选择
  74. <i class="el-icon-arrow-down" :style="{
  75. float: 'right',
  76. transition: 'transform 0.2s',
  77. transform: showQuestionType ? 'rotate(0deg)' : 'rotate(-90deg)'
  78. }"></i>
  79. </div>
  80. <div v-show="showQuestionType" style="min-height:40px; padding:0 24px 16px 24px;">
  81. <el-row :gutter="12">
  82. <el-col :span="8"><el-button class="param-btn" plain
  83. @click="handleOtherBtnClick('questionTypeSelection', 'singleChoice', '单选题')">单选题</el-button></el-col>
  84. <el-col :span="8"><el-button class="param-btn" plain
  85. @click="handleOtherBtnClick('questionTypeSelection', 'multipleChoice', '多选题')">多选题</el-button></el-col>
  86. <el-col :span="8"><el-button class="param-btn" plain
  87. @click="handleOtherBtnClick('questionTypeSelection', 'fillBlanks', '填空题')">填空题</el-button></el-col>
  88. <el-col :span="8"><el-button class="param-btn" plain
  89. @click="handleOtherBtnClick('questionTypeSelection', 'scaleQuestions', '量表题')">量表题</el-button></el-col>
  90. <el-col :span="8"><el-button class="param-btn" plain
  91. @click="handleOtherBtnClick('questionTypeSelection', 'matrixScale', '矩阵量表')">矩阵量表</el-button></el-col>
  92. </el-row>
  93. </div>
  94. </div>
  95. </el-aside>
  96. <el-container>
  97. <el-main style="padding-left: 20px;">
  98. <el-scrollbar>
  99. <div style="width: 50%;">
  100. <el-form label-width="100px" label-position="left" :model="form" ref="screeningAssessmentConfigFormRef">
  101. <el-form-item label="量表类型:" required>
  102. <el-radio-group v-model="form.type">
  103. <el-radio :label="item.label" :value="item.value" v-for="item in scale_type" :key="item.value"/>
  104. </el-radio-group>
  105. </el-form-item>
  106. <el-form-item label="适用条件:" required>
  107. <!-- 可留空或加说明 -->
  108. </el-form-item>
  109. <el-form-item label="性别:" style="margin-left: 20px;">
  110. <el-radio-group v-model="form.gender" style="margin-left: -50px;">
  111. <el-radio label="不限" value="-1">不限</el-radio>
  112. </el-radio-group>
  113. </el-form-item>
  114. <el-form-item label="年龄:" style="margin-left: 20px;">
  115. <el-radio-group v-model="form.age" style="margin-left: -50px;">
  116. <el-radio label="不限" style="width: 50%" value="-1">不限</el-radio>
  117. </el-radio-group>
  118. </el-form-item>
  119. <el-form-item label="量表名称:" required>
  120. <el-input v-model="form.name" maxlength="50" show-word-limit placeholder="请输入" />
  121. </el-form-item>
  122. <el-form-item label="量表说明:">
  123. <el-input v-model="form.description" maxlength="50" show-word-limit placeholder="请输入" />
  124. </el-form-item>
  125. <el-form-item label="备注:">
  126. <el-input type="textarea" v-model="form.remark" maxlength="500" show-word-limit placeholder="请输入"
  127. :rows="3" />
  128. </el-form-item>
  129. </el-form>
  130. </div>
  131. <div v-if="baseInfo.questionType" @click="selectBaseInfo" :class="{ selectedDiv: baseInfo.selected }">
  132. <span>&nbsp;</span>
  133. <div style="width: 50%;margin-top: 32px;">
  134. <el-form label-width="100px" label-position="left">
  135. <el-form-item label="1. 标题:" required>
  136. <el-input :value="baseInfo.title" readonly size="large" />
  137. </el-form-item>
  138. <div style="margin-left: 60px;">
  139. <template v-for="ctl in baseInfo.contentList">
  140. <el-form-item label="填空:">
  141. <el-input v-model="ctl.label" readonly style="margin-left: -50px;" size="large">
  142. <template #append><el-button @click="handleBaseBtnDelete(ctl.nameEn)">-</el-button></template>
  143. </el-input>
  144. </el-form-item>
  145. </template>
  146. </div>
  147. </el-form>
  148. </div>
  149. <div style="display: flex; align-items: right;justify-content: right;padding-right: 50px;"
  150. v-show="baseInfo.selected">
  151. <el-button type="primary" icon="Delete" plain @click="deleteBaseInfo">删除</el-button>
  152. </div>
  153. <span>&nbsp;</span>
  154. </div>
  155. <template v-for="other, index in otherInfo">
  156. <div style="overflow-x: scroll;" v-if="other.questionChildType == 'scaleQuestions'">
  157. <div class="custom-radio-grid">
  158. <div v-for="n in other.contentList.length" :key="n"
  159. :class="['custom-radio-cell', { 'is-checked': other.contentList.length === n, 'is-last': n > 1 }]">
  160. {{ n }}
  161. </div>
  162. </div>
  163. <div class="custom-radio-grid">
  164. <div v-for="ctl, n in other.contentList" :key="ctl.nameEn" style="border: none;"
  165. :class="['custom-radio-cell']">
  166. {{ ctl.label }}
  167. </div>
  168. </div>
  169. </div>
  170. <div style="border-bottom: 1px solid #e5e7eb;width: 98%;" v-if="other.questionChildType == 'matrixScale'">
  171. <el-row :gutter="10" class="mb8">
  172. <el-col :span="3" style="margin-top: 30px;">
  173. </el-col>
  174. <template v-for="clt in other.contentList">
  175. <template v-if="clt.optionFlag">
  176. <el-col :span="1" align="center" style="margin-top: 30px;margin-left: 30px;">
  177. {{ clt.optionContent }}
  178. </el-col>
  179. </template>
  180. </template>
  181. </el-row>
  182. <template v-for="clt, idx in other.contentList">
  183. <el-row :gutter="10" class="mb8">
  184. <el-col :span="3" style="margin-top: 10px;">
  185. <template v-if="clt.labelFlag">
  186. 标题{{ idx + 1 }}:{{ clt.label }}
  187. </template>
  188. </el-col>
  189. <template v-for="clt2, idx in other.contentList">
  190. <el-col :span="1" align="center" style="margin-left: 30px;">
  191. <template v-if="clt2.optionFlag && clt.labelFlag">
  192. <el-radio-group>
  193. <el-radio value="1" size="large" />
  194. </el-radio-group>
  195. </template>
  196. </el-col>
  197. </template>
  198. </el-row>
  199. </template>
  200. </div>
  201. <div style="border-bottom: 1px solid #e5e7eb;width: 98%;" :class="{ selectedDiv: other.selected }"
  202. @click="selectOtherInfo(index)">
  203. <span>&nbsp;</span>
  204. <template v-if="other.questionType != 'questionTypeSelection'">
  205. <el-row :gutter="10" class="mb8">
  206. <el-col :span="12">
  207. <el-form-item :label="(index + 1 + baseInfo.contentList.length) + '. 标题:'" required>
  208. <el-input readonly style="width: 100%;" v-model="other.title" size="large" />
  209. </el-form-item>
  210. </el-col>
  211. <el-col :span="2" align="center">
  212. </el-col>
  213. <el-col :span="3">
  214. </el-col>
  215. <el-col :span="3">
  216. </el-col>
  217. <el-col :span="4">
  218. </el-col>
  219. </el-row>
  220. </template>
  221. <template v-if="other.questionType == 'questionTypeSelection'">
  222. <el-row :gutter="10" class="mb8">
  223. <el-col :span="12">
  224. <el-form-item :label="(index + 1 + baseInfo.contentList.length) + '. 标题:'" required>
  225. <el-input style="width: 100%;" v-model="other.title" placeholder="请输入标题" size="large"
  226. show-word-limit maxlength="150" />
  227. </el-form-item>
  228. </el-col>
  229. <el-col :span="2" align="center">
  230. <el-checkbox label="是否必填" v-model="other.required" />
  231. </el-col>
  232. <el-col :span="3">
  233. <el-select v-model="other.arrangement" placeholder="请选择" clearable
  234. v-if="other.questionChildType == 'multipleChoice' || other.questionChildType == 'singleChoice' || other.questionChildType == 'fillBlanks'">
  235. <el-option v-for="dict in arrangement_method" :key="dict.value" :label="dict.label"
  236. :value="dict.value"></el-option>
  237. </el-select>
  238. </el-col>
  239. <el-col :span="5">
  240. <div v-if="other.questionChildType == 'multipleChoice'">
  241. <el-form-item label="计分方式" id="jffs">
  242. <el-select v-model="other.scoreMethod" placeholder="请选择" clearable>
  243. <el-option v-for="dict in score_method" :key="dict.value" :label="dict.label"
  244. :value="dict.value"></el-option>
  245. </el-select>
  246. </el-form-item>
  247. </div>
  248. </el-col>
  249. <el-col :span="2">
  250. </el-col>
  251. </el-row>
  252. </template>
  253. <el-row :gutter="10" class="mb8" v-if="other.questionChildType == 'singleChoice'"
  254. style="background-color: #e5e7eb;height: 40px;line-height: 40px;width: 98%;">
  255. <el-col :span="12">
  256. <div style="text-align: center;">选项(单选)</div>
  257. </el-col>
  258. <el-col :span="2">
  259. <div style="text-align: center;">添加图片</div>
  260. </el-col>
  261. <el-col :span="3">
  262. <div style="text-align: center;">分值设置</div>
  263. </el-col>
  264. <el-col :span="3">
  265. <div style="text-align: left;">允许填空</div>
  266. </el-col>
  267. <el-col :span="4">
  268. </el-col>
  269. </el-row>
  270. <el-row :gutter="10" class="mb8" v-if="other.questionChildType == 'multipleChoice'"
  271. style="background-color: #e5e7eb;height: 40px;line-height: 40px;width: 98%;">
  272. <el-col :span="12">
  273. <div style="text-align: center;"> 选项(多选)</div>
  274. </el-col>
  275. <el-col :span="2">
  276. <div style="text-align: center;">添加图片</div>
  277. </el-col>
  278. <el-col :span="3">
  279. <div style="text-align: center;">分值设置</div>
  280. </el-col>
  281. <el-col :span="3">
  282. <div style="text-align: left;">允许填空</div>
  283. </el-col>
  284. <el-col :span="4">
  285. </el-col>
  286. </el-row>
  287. <el-row :gutter="10" class="mb8" v-if="other.questionChildType == 'matrixScale'"
  288. style="background-color: #e5e7eb;height: 40px;line-height: 40px;width: 98%;">
  289. <el-col :span="10">
  290. <div style="text-align: center;"> 选项题目(矩阵量表)</div>
  291. </el-col>
  292. <el-col :span="4">
  293. <div style="text-align: center;">选项内容</div>
  294. </el-col>
  295. <el-col :span="3">
  296. <div style="text-align: center;">分值设置</div>
  297. </el-col>
  298. <el-col :span="3">
  299. <div style="text-align: left;">允许填空</div>
  300. </el-col>
  301. <el-col :span="4">
  302. </el-col>
  303. </el-row>
  304. <el-row :gutter="10" class="mb8"
  305. v-if="other.questionChildType == 'anthropometry' && other.lastType == '2'"
  306. style="background-color: #e5e7eb;height: 40px;line-height: 40px;width: 98%;">
  307. <el-col :span="12">
  308. <div style="text-align: center;">选项(单选)</div>
  309. </el-col>
  310. <el-col :span="2">
  311. </el-col>
  312. <el-col :span="3">
  313. </el-col>
  314. <el-col :span="3">
  315. </el-col>
  316. <el-col :span="4">
  317. </el-col>
  318. </el-row>
  319. <el-row :gutter="10" class="mb8" v-if="(other.questionChildType == 'anthropometry' && other.lastType == '4')
  320. || (other.questionChildType == 'dietaryStatus' && other.lastType == '2')"
  321. style="background-color: #e5e7eb;height: 40px;line-height: 40px;width: 98%;">
  322. <el-col :span="12">
  323. <div style="text-align: center;">选项(单选)</div>
  324. </el-col>
  325. <el-col :span="2">
  326. <div style="text-align: center;">分值设置</div>
  327. </el-col>
  328. <el-col :span="3">
  329. </el-col>
  330. <el-col :span="3">
  331. </el-col>
  332. <el-col :span="4">
  333. </el-col>
  334. </el-row>
  335. <el-row :gutter="10" class="mb8" v-if="other.questionChildType == 'scaleQuestions'"
  336. style="background-color: #e5e7eb;height: 40px;line-height: 40px;width: 98%;">
  337. <el-col :span="12">
  338. <div style="text-align: center;">选项(量表)</div>
  339. </el-col>
  340. <el-col :span="2">
  341. <div style="text-align: center;">分值设置</div>
  342. </el-col>
  343. <el-col :span="3">
  344. </el-col>
  345. <el-col :span="3">
  346. </el-col>
  347. <el-col :span="4">
  348. </el-col>
  349. </el-row>
  350. <el-row :gutter="10" class="mb8" v-if="other.questionChildType == 'fillBlanks'"
  351. style="background-color: #e5e7eb;height: 40px;line-height: 40px;width: 98%;">
  352. <el-col :span="12">
  353. <div style="text-align: center;">选项(填空)</div>
  354. </el-col>
  355. <el-col :span="2">
  356. <div style="text-align: center;">添加图片</div>
  357. </el-col>
  358. <el-col :span="3">
  359. <div style="text-align: center;">分值设置</div>
  360. </el-col>
  361. <el-col :span="3">
  362. <div style="text-align: left;">单位</div>
  363. </el-col>
  364. <el-col :span="4">
  365. </el-col>
  366. </el-row>
  367. <template v-if="other.questionChildType == 'singleChoice' || other.questionChildType == 'fillBlanks'
  368. || other.questionChildType == 'multipleChoice'">
  369. <template v-for="ctl, idx in other.contentList">
  370. <el-row :gutter="10" class="mb8" style="margin-top: 20px;width: 98%;">
  371. <el-col :span="12">
  372. <el-form-item required style="margin-left: 40px;">
  373. <el-radio-group>
  374. <el-radio :disabled="true">
  375. 选项{{ idx + 1 }}:
  376. <el-input size="large" style="width: 430px;" v-model="ctl.label" show-word-limit
  377. maxlength="150">
  378. <template #prepend><el-button
  379. @click="handleOtherBtnAdd(index, other.questionChildType)">+</el-button></template>
  380. <template #append><el-button
  381. @click="handleOtherBtnDelete(index, idx)">-</el-button></template>
  382. </el-input>
  383. </el-radio>
  384. </el-radio-group>
  385. </el-form-item>
  386. </el-col>
  387. <el-col :span="2" align="center" style="margin-top: -5px;">
  388. <miniImageUpload :limit="1" v-model="ctl.img" />
  389. </el-col>
  390. <el-col :span="3" align="center" style="margin-top: -5px;">
  391. <el-input style="width: 60px;" size="large" v-model="ctl.score" />
  392. </el-col>
  393. <el-col :span="3" align="left" style="margin-top: -5px;">
  394. <template v-if="other.questionChildType == 'fillBlanks'">
  395. <el-input style="width: 40px;" size="large" v-model="ctl.unit" />
  396. </template>
  397. <template v-if="other.questionChildType != 'fillBlanks'">
  398. <el-checkbox v-model="ctl.allowFillBlank" />
  399. </template>
  400. </el-col>
  401. <el-col :span="4" align="center">
  402. </el-col>
  403. </el-row>
  404. </template>
  405. </template>
  406. <template v-if="other.questionChildType == 'matrixScale'">
  407. <template v-for="ctl, idx in other.contentList">
  408. <el-row :gutter="10" class="mb8" style="margin-top: 20px;width: 98%;">
  409. <el-col :span="10" style="margin-top: -5px;">
  410. <template v-if="ctl.labelFlag">
  411. <el-form-item required style="margin-left: 40px;">
  412. 行标题{{ idx + 1 }}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  413. <el-input size="large" style="width: 330px;" v-model="ctl.label" show-word-limit
  414. maxlength="150">
  415. <template #prepend><el-button
  416. @click="handleMatrixScaleAdd(index, idx, true)">+</el-button></template>
  417. <template #append><el-button
  418. @click="handleMatrixScaleDelete(index, idx, true)">-</el-button></template>
  419. </el-input>
  420. </el-form-item>
  421. </template>
  422. </el-col>
  423. <el-col :span="4" align="center" style="margin-top: -5px;">
  424. <template v-if="ctl.optionFlag">
  425. <el-input size="large" v-model="ctl.optionContent" show-word-limit maxlength="150">
  426. <template #prepend><el-button
  427. @click="handleMatrixScaleAdd(index, idx, false)">+</el-button></template>
  428. <template #append><el-button
  429. @click="handleMatrixScaleDelete(index, idx, false)">-</el-button></template>
  430. </el-input>
  431. </template>
  432. </el-col>
  433. <el-col :span="3" align="center" style="margin-top: -5px;">
  434. <el-input style="width: 60px;" size="large" v-model="ctl.score" />
  435. </el-col>
  436. <el-col :span="3" align="left" style="margin-top: -5px;">
  437. <el-checkbox v-model="ctl.allowFillBlank" />
  438. </el-col>
  439. <el-col :span="4" align="center">
  440. </el-col>
  441. </el-row>
  442. </template>
  443. </template>
  444. <template v-if="(other.questionChildType == 'anthropometry' && (other.lastType == '1' || other.lastType == '3')
  445. || (other.questionChildType == 'dietaryStatus' && other.lastType != '2'))">
  446. <template v-for="ctl, idx in other.contentList">
  447. <el-row :gutter="10" class="mb8" :style="{ marginTop: idx == 0 ? '20px' : '0px' }"
  448. style="width: 98%;">
  449. <el-col :span="12">
  450. <div style="margin-left: 60px;margin-top: -15px;">
  451. <el-form-item label="填空:">
  452. <el-input readonly size="large" v-model="ctl.label">
  453. <template #append><el-button
  454. @click="handleOtherBtnDelete(index, idx)">-</el-button></template>
  455. </el-input>
  456. </el-form-item>
  457. </div>
  458. </el-col>
  459. <el-col :span="2" align="center" style="margin-top: -5px;">
  460. </el-col>
  461. <el-col :span="3" align="center">
  462. </el-col>
  463. <el-col :span="3" align="center">
  464. </el-col>
  465. <el-col :span="4" align="center">
  466. </el-col>
  467. </el-row>
  468. </template>
  469. </template>
  470. <template v-if="((other.questionChildType == 'anthropometry' && other.lastType == '4')
  471. || (other.questionChildType == 'dietaryStatus' && other.lastType == '2'))">
  472. <template v-for="ctl, idx in other.contentList">
  473. <el-row :gutter="10" class="mb8" :style="{ marginTop: idx == 0 ? '20px' : '0px' }"
  474. style="width: 98%;">
  475. <el-col :span="12">
  476. <el-form-item required style="margin-left: 40px;"
  477. :style="{ marginTop: idx == 0 ? '0px' : '-5px' }">
  478. <el-radio-group>
  479. <el-radio :disabled="true">
  480. 选项{{ idx + 1 }}:
  481. <el-input readonly size="large" style="width: 430px;" v-model="ctl.label">
  482. <template #append><el-button
  483. @click="handleOtherBtnDelete(index, idx)">-</el-button></template>
  484. </el-input>
  485. </el-radio>
  486. </el-radio-group>
  487. </el-form-item>
  488. </el-col>
  489. <el-col :span="2" align="center" style="margin-top: -5px;">
  490. <el-input style="width: 60px;" v-model="ctl.score" size="large" />
  491. </el-col>
  492. <el-col :span="3" align="center">
  493. </el-col>
  494. <el-col :span="3" align="center">
  495. </el-col>
  496. <el-col :span="4" align="center">
  497. </el-col>
  498. </el-row>
  499. </template>
  500. </template>
  501. <template v-if="other.questionChildType == 'scaleQuestions'">
  502. <template v-for="ctl, idx in other.contentList">
  503. <el-row :gutter="10" class="mb8" :style="{ marginTop: idx == 0 ? '20px' : '0px' }"
  504. style="width: 98%;">
  505. <el-col :span="12">
  506. <el-form-item required style="margin-left: 40px;"
  507. :style="{ marginTop: idx == 0 ? '0px' : '-5px' }">
  508. {{ idx + 1 }}:
  509. <el-input size="large" style="width: 430px;" v-model="ctl.label" show-word-limit
  510. maxlength="150">
  511. <template #prepend><el-button
  512. @click="handleOtherBtnAdd(index, other.questionChildType)">+</el-button></template>
  513. <template #append><el-button
  514. @click="handleOtherBtnDelete(index, idx)">-</el-button></template>
  515. </el-input>
  516. </el-form-item>
  517. </el-col>
  518. <el-col :span="2" align="center" style="margin-top: -5px;">
  519. <el-input style="width: 60px;" v-model="ctl.score" size="large" />
  520. </el-col>
  521. <el-col :span="3" align="center">
  522. </el-col>
  523. <el-col :span="3" align="center">
  524. </el-col>
  525. <el-col :span="4" align="center">
  526. </el-col>
  527. </el-row>
  528. </template>
  529. </template>
  530. <template v-if="(other.questionChildType == 'anthropometry' && other.lastType == '2'
  531. || (other.questionChildType == 'dietaryStatus' && other.lastType == '12'))">
  532. <template v-for="ctl, idx in other.contentList">
  533. <el-row :gutter="10" class="mb8" :style="{ marginTop: idx == 0 ? '20px' : '0px' }"
  534. style="width: 98%;">
  535. <el-col :span="12">
  536. <el-form-item required style="margin-left: 40px;"
  537. :style="{ marginTop: idx == 0 ? '0px' : '-5px' }">
  538. <el-radio-group>
  539. <el-radio :disabled="true">
  540. 选项{{ idx + 1 }}:
  541. <el-input readonly size="large" style="width: 430px;" v-model="ctl.label">
  542. <template #append><el-button
  543. @click="handleOtherBtnDelete(index, idx)">-</el-button></template>
  544. </el-input>
  545. </el-radio>
  546. </el-radio-group>
  547. </el-form-item>
  548. </el-col>
  549. <el-col :span="2" align="center" style="margin-top: -5px;">
  550. </el-col>
  551. <el-col :span="3" align="center">
  552. </el-col>
  553. <el-col :span="3" align="center">
  554. </el-col>
  555. <el-col :span="4" align="center">
  556. </el-col>
  557. </el-row>
  558. </template>
  559. </template>
  560. <div style="display: flex; align-items: right;justify-content: right;padding-right: 50px;"
  561. v-show="other.selected">
  562. <el-button type="primary" icon="Top" plain :disabled="index == 0"
  563. @click="moveUp(index)">上移</el-button>
  564. <el-button type="primary" icon="Bottom" plain :disabled="index + 1 == otherInfo.length"
  565. @click="moveDown(index)">下移</el-button>
  566. <el-button type="primary" icon="Upload" plain :disabled="index == 0"
  567. @click="topUp(index)">置顶</el-button>
  568. <el-button type="primary" icon="Download" plain :disabled="index + 1 == otherInfo.length"
  569. @click="bottomUp(index)">置底</el-button>
  570. <el-button type="primary" icon="Delete" plain @click="deleteOtherInfo(index)">删除</el-button>
  571. </div>
  572. <span>&nbsp;</span>
  573. </div>
  574. </template>
  575. </el-scrollbar>
  576. </el-main>
  577. </el-container>
  578. </el-container>
  579. </div>
  580. </template>
  581. <script setup name="ScreeningAssessmentConfig" lang="ts">
  582. import { ref, onMounted, onUnmounted } from 'vue';
  583. import { listScreeningAssessmentConfig, getScreeningAssessmentConfig, delScreeningAssessmentConfig, addScreeningAssessmentConfig, updateScreeningAssessmentConfig } from '@/api/system/screeningAssessmentConfig';
  584. import { ScreeningAssessmentConfigVO, ScreeningAssessmentConfigQuery, ScreeningAssessmentConfigForm, QuestionAttrVO, QuestionVO } from '@/api/system/screeningAssessmentConfig/types';
  585. const route = useRoute();
  586. const showSystemParam = ref(true);
  587. const showQuestionType = ref(true);
  588. const { proxy } = getCurrentInstance() as ComponentInternalInstance;
  589. const { arrangement_method, score_method ,scale_type} = toRefs<any>(proxy?.useDict('scale_type','arrangement_method', 'score_method'));
  590. const screeningAssessmentConfigList = ref<ScreeningAssessmentConfigVO[]>([]);
  591. const buttonLoading = ref(false);
  592. const loading = ref(true);
  593. const ids = ref<Array<string | number>>([]);
  594. const single = ref(true);
  595. const multiple = ref(true);
  596. const total = ref(0);
  597. const baseInfo = ref<QuestionVO>({
  598. questionId: '',
  599. title: '',
  600. questionType: '',
  601. content: '',
  602. selected: false,
  603. contentList: [],
  604. });
  605. const otherInfo = ref<QuestionVO[]>([]);
  606. const queryFormRef = ref<ElFormInstance>();
  607. const screeningAssessmentConfigFormRef = ref<ElFormInstance>();
  608. const dialog = reactive<DialogOption>({
  609. visible: false,
  610. title: ''
  611. });
  612. const initFormData: ScreeningAssessmentConfigForm = {
  613. configId: undefined,
  614. type: '1',
  615. gender: '-1',
  616. age: '-1',
  617. name: undefined,
  618. description: undefined,
  619. remark: undefined,
  620. status: undefined,
  621. baseInfo: undefined,
  622. otherInfo: undefined
  623. }
  624. const data = reactive<PageData<ScreeningAssessmentConfigForm, ScreeningAssessmentConfigQuery>>({
  625. form: { ...initFormData },
  626. queryParams: {
  627. pageNum: 1,
  628. pageSize: 10,
  629. type: undefined,
  630. gender: undefined,
  631. age: undefined,
  632. name: undefined,
  633. description: undefined,
  634. status: undefined,
  635. params: {
  636. }
  637. },
  638. rules: {
  639. age: [
  640. { required: true, message: "年龄不能为空", trigger: "blur" }
  641. ],
  642. gender: [
  643. { required: true, message: "性别不能为空", trigger: "blur" }
  644. ],
  645. type: [
  646. { required: true, message: "量表类型不能为空", trigger: "change" }
  647. ],
  648. name: [
  649. { required: true, message: "量表名称不能为空", trigger: "blur" }
  650. ],
  651. }
  652. });
  653. const { queryParams, form, rules } = toRefs(data);
  654. /** 查询筛查/评估配置列表 */
  655. const getList = async () => {
  656. const eId = route.params && route.params.id;
  657. const vId = route.params && route.params.vid;
  658. let id=undefined;
  659. if(vId){
  660. id=vId;
  661. }else{
  662. id=eId;
  663. }
  664. if (id&&id!='0') {
  665. loading.value = true;
  666. const res = await getScreeningAssessmentConfig(id as string);
  667. Object.assign(form.value, res.data);
  668. if(res.data.baseInfo){
  669. baseInfo.value = res.data.baseInfo;
  670. }
  671. if(res.data.otherInfo){
  672. otherInfo.value = res.data.otherInfo;
  673. }
  674. loading.value = false;
  675. }
  676. }
  677. /** 取消按钮 */
  678. const cancel = () => {
  679. reset();
  680. dialog.visible = false;
  681. }
  682. /** 表单重置 */
  683. const reset = () => {
  684. form.value = { ...initFormData };
  685. screeningAssessmentConfigFormRef.value?.resetFields();
  686. }
  687. /** 搜索按钮操作 */
  688. const handleQuery = () => {
  689. queryParams.value.pageNum = 1;
  690. getList();
  691. }
  692. /** 重置按钮操作 */
  693. const resetQuery = () => {
  694. queryFormRef.value?.resetFields();
  695. handleQuery();
  696. }
  697. /** 多选框选中数据 */
  698. const handleSelectionChange = (selection: ScreeningAssessmentConfigVO[]) => {
  699. ids.value = selection.map(item => item.configId);
  700. single.value = selection.length != 1;
  701. multiple.value = !selection.length;
  702. }
  703. /** 新增按钮操作 */
  704. const handleAdd = () => {
  705. reset();
  706. dialog.visible = true;
  707. dialog.title = "添加筛查/评估配置";
  708. }
  709. /** 修改按钮操作 */
  710. const handleUpdate = async (row?: ScreeningAssessmentConfigVO) => {
  711. reset();
  712. const _configId = row?.configId || ids.value[0]
  713. const res = await getScreeningAssessmentConfig(_configId);
  714. Object.assign(form.value, res.data);
  715. dialog.visible = true;
  716. dialog.title = "修改筛查/评估配置";
  717. }
  718. /** 提交按钮 */
  719. const submitForm = () => {
  720. screeningAssessmentConfigFormRef.value?.validate(async (valid: boolean) => {
  721. if (valid) {
  722. if (!baseInfo.value.questionType && otherInfo.value.length == 0) {
  723. proxy?.$modal.msgError("请选择题型");
  724. return;
  725. }
  726. let baseNum=!baseInfo.value.questionType?0:1;
  727. let lineNum=0;
  728. for (let item of otherInfo.value) {
  729. lineNum++;
  730. if (!item.title || item.title.trim().length < 1) {
  731. proxy?.$modal.msgError("第"+(baseNum+lineNum)+"行标题为空");
  732. return;
  733. }
  734. for (let ch of item.contentList) {
  735. if (!ch.label || ch.label.trim().length < 1) {
  736. proxy?.$modal.msgError("第"+(baseNum+lineNum)+"行标题的选项有空值");
  737. return;
  738. }
  739. if (item.questionChildType=='matrixScale'&&(!ch.optionContent || ch.optionContent.trim().length < 1)) {
  740. proxy?.$modal.msgError("第"+(baseNum+lineNum)+"行标题的选项内容为空");
  741. return;
  742. }
  743. }
  744. }
  745. if(baseInfo.value.questionType&&baseInfo.value.questionType.length>0){
  746. form.value.baseInfo = baseInfo.value;
  747. }
  748. if(otherInfo.value&&otherInfo.value.length>0){
  749. form.value.otherInfo = otherInfo.value;
  750. }
  751. buttonLoading.value = true;
  752. if (form.value.configId) {
  753. await updateScreeningAssessmentConfig(form.value).finally(() => buttonLoading.value = false);
  754. } else {
  755. await addScreeningAssessmentConfig(form.value).finally(() => buttonLoading.value = false);
  756. }
  757. proxy?.$modal.msgSuccess("操作成功");
  758. close();
  759. }
  760. });
  761. }
  762. /** 删除按钮操作 */
  763. const handleDelete = async (row?: ScreeningAssessmentConfigVO) => {
  764. const _configIds = row?.configId || ids.value;
  765. await proxy?.$modal.confirm('是否确认删除筛查/评估配置编号为"' + _configIds + '"的数据项?').finally(() => loading.value = false);
  766. await delScreeningAssessmentConfig(_configIds);
  767. proxy?.$modal.msgSuccess("删除成功");
  768. await getList();
  769. }
  770. /** 导出按钮操作 */
  771. const handleExport = () => {
  772. proxy?.download('system/screeningAssessmentConfig/export', {
  773. ...queryParams.value
  774. }, `screeningAssessmentConfig_${new Date().getTime()}.xlsx`)
  775. }
  776. /** 预览按钮操作 */
  777. const handlePreview = () => {
  778. // Implementation of handlePreview function
  779. }
  780. /** 关闭按钮操作 */
  781. const close = () => {
  782. const obj: RouteLocationNormalized = {
  783. fullPath: '',
  784. hash: '',
  785. matched: [],
  786. meta: undefined,
  787. name: undefined,
  788. params: undefined,
  789. query: undefined,
  790. redirectedFrom: undefined,
  791. path: '/argManage/screeningAssessmentConfig'
  792. };
  793. proxy?.$tab.closeOpenPage(obj);
  794. }
  795. function handleOtherBtnClick(questionType: string, nameEn: string, nameCn: string) {
  796. if (otherInfo.value.length > 0 && questionType == 'otherInfo') {
  797. let newList = []
  798. for (let i = 0, len = otherInfo.value.length; i < len; i++) {
  799. let other = otherInfo.value[i];
  800. if (other.questionType == 'otherInfo' && other.questionChildType == nameEn) {
  801. continue;
  802. }
  803. newList.push(other);
  804. }
  805. if (newList.length != otherInfo.value.length) {
  806. otherInfo.value = newList;
  807. }
  808. }
  809. let question: QuestionVO = {
  810. questionId: '',
  811. title: nameCn,
  812. questionType: questionType,
  813. questionChildType: nameEn,
  814. lastType: '1',
  815. selected: false,
  816. required: false,
  817. scoreMethod: '1',
  818. arrangement: '1',
  819. content: '',
  820. contentList: [],
  821. };
  822. otherInfo.value.push(question);
  823. if ('anthropometry' == nameEn) {
  824. question.contentList.push({
  825. label: '身高',
  826. value: undefined,
  827. nameEn: 'height',
  828. });
  829. question.contentList.push({
  830. label: '当前体重',
  831. value: undefined,
  832. nameEn: 'currentWeight',
  833. });
  834. question.contentList.push({
  835. label: '出生体重',
  836. value: undefined,
  837. nameEn: 'birthWeight',
  838. });
  839. question.contentList.push({
  840. label: '理想体重',
  841. value: undefined,
  842. nameEn: 'idealWeight',
  843. });
  844. question.contentList.push({
  845. label: 'BMI',
  846. value: undefined,
  847. nameEn: 'BMI',
  848. });
  849. question.contentList.push({
  850. label: '握力',
  851. value: undefined,
  852. nameEn: 'gripStrength',
  853. });
  854. question.contentList.push({
  855. label: '皮褶厚度',
  856. value: undefined,
  857. nameEn: 'leatherFoldThickness',
  858. });
  859. question.contentList.push({
  860. label: '腰围',
  861. value: undefined,
  862. nameEn: 'waistCircumference',
  863. });
  864. question.contentList.push({
  865. label: '上臂围',
  866. value: undefined,
  867. nameEn: 'upperArmCircumference',
  868. });
  869. question.contentList.push({
  870. label: '小腿围',
  871. value: undefined,
  872. nameEn: 'calfCircumference',
  873. });
  874. question.contentList.push({
  875. label: '其他测量指标',
  876. value: undefined,
  877. nameEn: 'otherMeasurementIndicators',
  878. });
  879. question = {
  880. questionId: '',
  881. title: '请选择调查时间',
  882. questionType: questionType,
  883. questionChildType: nameEn,
  884. content: '',
  885. lastType: '2',
  886. contentList: [],
  887. };
  888. otherInfo.value.push(question);
  889. question.contentList.push({
  890. label: '三个月前',
  891. formType: 'radio',
  892. value: undefined,
  893. nameEn: 'threeMonthsAgo',
  894. });
  895. question.contentList.push({
  896. label: '两个月前',
  897. value: undefined,
  898. formType: 'radio',
  899. nameEn: 'twoMonthsAgo',
  900. });
  901. question.contentList.push({
  902. label: '一个月前',
  903. formType: 'radio',
  904. value: undefined,
  905. nameEn: 'oneMonthsAgo',
  906. });
  907. question = {
  908. questionId: '',
  909. title: '请填入已选调查时间体重',
  910. questionType: questionType,
  911. questionChildType: nameEn,
  912. lastType: '3',
  913. content: '',
  914. contentList: [],
  915. };
  916. otherInfo.value.push(question);
  917. question.contentList.push({
  918. label: '过去体重',
  919. value: undefined,
  920. nameEn: 'pastWeight',
  921. });
  922. question = {
  923. questionId: '',
  924. title: '1-3个月内体重变化情况',
  925. questionType: questionType,
  926. questionChildType: nameEn,
  927. lastType: '4',
  928. content: '',
  929. contentList: [],
  930. };
  931. otherInfo.value.push(question);
  932. question.contentList.push({
  933. label: '近3个月体重无显著变化',
  934. formType: 'radioScore',
  935. value: undefined,
  936. nameEn: 'noChangeWeight',
  937. });
  938. question.contentList.push({
  939. label: '近3个月体重丢失>5%',
  940. formType: 'radioScore',
  941. value: undefined,
  942. nameEn: 'weightLoss5In3Months',
  943. });
  944. question.contentList.push({
  945. label: '近2个月体重丢失>5%',
  946. formType: 'radioScore',
  947. value: undefined,
  948. nameEn: 'weightLoss5In2Months',
  949. });
  950. question.contentList.push({
  951. label: '近1个月体重丢失>5%',
  952. formType: 'radioScore',
  953. value: undefined,
  954. nameEn: 'weightLoss5In1Months',
  955. });
  956. for (let i = 0, len = question.contentList.length; i < len; i++) {
  957. question.contentList[i].score = i.toString();
  958. }
  959. return;
  960. }
  961. if ('dietaryStatus' == nameEn) {
  962. question.contentList.push({
  963. label: '平素膳食餐次',
  964. value: undefined,
  965. nameEn: 'regularMealSchedule',
  966. });
  967. question = {
  968. questionId: '',
  969. title: '近1周食物摄入量是否减少',
  970. questionType: questionType,
  971. questionChildType: nameEn,
  972. lastType: '2',
  973. content: '',
  974. contentList: [],
  975. };
  976. otherInfo.value.push(question);
  977. question.contentList.push({
  978. label: '无变化',
  979. formType: 'radioScore',
  980. value: undefined,
  981. nameEn: 'noChange',
  982. });
  983. question.contentList.push({
  984. label: '较从前减少25%~50%',
  985. formType: 'radioScore',
  986. value: undefined,
  987. nameEn: 'decreasedBy25To50',
  988. });
  989. question.contentList.push({
  990. label: '较从前减少51%~75%',
  991. formType: 'radioScore',
  992. value: undefined,
  993. nameEn: 'decreasedBy51To75',
  994. });
  995. question.contentList.push({
  996. label: '较从前减少76%~100%',
  997. formType: 'radioScore',
  998. value: undefined,
  999. nameEn: 'decreasedBy76To100',
  1000. });
  1001. for (let i = 0, len = question.contentList.length; i < len; i++) {
  1002. question.contentList[i].score = i.toString();
  1003. }
  1004. question = {
  1005. questionId: '',
  1006. title: '近1周食物摄入种类(/日)',
  1007. questionType: questionType,
  1008. questionChildType: nameEn,
  1009. lastType: '3',
  1010. content: '',
  1011. contentList: [],
  1012. };
  1013. otherInfo.value.push(question);
  1014. question.contentList.push({
  1015. label: '奶及奶制品',
  1016. value: undefined,
  1017. nameEn: 'milkAndDairyProducts',
  1018. });
  1019. question.contentList.push({
  1020. label: '坚果类',
  1021. value: undefined,
  1022. nameEn: 'nutCategory',
  1023. });
  1024. question.contentList.push({
  1025. label: '大豆类',
  1026. value: undefined,
  1027. nameEn: 'largeBeans',
  1028. });
  1029. question.contentList.push({
  1030. label: '肉蛋水产类',
  1031. value: undefined,
  1032. nameEn: 'meatEggAndAquaticProducts',
  1033. });
  1034. question.contentList.push({
  1035. label: '蔬菜类',
  1036. value: undefined,
  1037. nameEn: 'vegetables',
  1038. });
  1039. question.contentList.push({
  1040. label: '水果类',
  1041. value: undefined,
  1042. nameEn: 'fruitCategory',
  1043. });
  1044. question.contentList.push({
  1045. label: '谷薯杂豆类',
  1046. value: undefined,
  1047. nameEn: 'grainPotatoAndMixedBeans',
  1048. });
  1049. question.contentList.push({
  1050. label: '调料类',
  1051. value: undefined,
  1052. nameEn: 'seasoning',
  1053. });
  1054. question.contentList.push({
  1055. label: '水',
  1056. value: undefined,
  1057. nameEn: 'water',
  1058. });
  1059. question = {
  1060. questionId: '',
  1061. title: '近1周能量-营养素摄入分析(/日)',
  1062. questionType: questionType,
  1063. questionChildType: nameEn,
  1064. lastType: '4',
  1065. content: '',
  1066. contentList: [],
  1067. };
  1068. otherInfo.value.push(question);
  1069. question.contentList.push({
  1070. label: '总能量',
  1071. value: undefined,
  1072. nameEn: 'totalEnergy',
  1073. });
  1074. question.contentList.push({
  1075. label: '总氮量',
  1076. value: undefined,
  1077. nameEn: 'totalNitrogenContent',
  1078. });
  1079. question.contentList.push({
  1080. label: '氮/能量比值:1',
  1081. value: undefined,
  1082. nameEn: 'nitrogenEnergyRatio1',
  1083. });
  1084. question.contentList.push({
  1085. label: '蛋白质含量',
  1086. value: undefined,
  1087. nameEn: 'proteinContent',
  1088. });
  1089. question.contentList.push({
  1090. label: '脂肪含量',
  1091. value: undefined,
  1092. nameEn: 'fatContent',
  1093. });
  1094. question.contentList.push({
  1095. label: '碳水化合物含量',
  1096. value: undefined,
  1097. nameEn: 'carbohydrateContent',
  1098. });
  1099. question.contentList.push({
  1100. label: '蛋白质热比',
  1101. value: undefined,
  1102. nameEn: 'proteinHeatRatio',
  1103. });
  1104. question.contentList.push({
  1105. label: '脂肪热比',
  1106. value: undefined,
  1107. nameEn: 'protefatToHeatRatioinHeatRatio',
  1108. });
  1109. question.contentList.push({
  1110. label: '碳水化合物热比',
  1111. value: undefined,
  1112. nameEn: 'carbohydrateHeatRatio',
  1113. });
  1114. question.contentList.push({
  1115. label: '盐',
  1116. value: undefined,
  1117. nameEn: 'salt',
  1118. });
  1119. question.contentList.push({
  1120. label: '钠',
  1121. value: undefined,
  1122. nameEn: 'sodium',
  1123. });
  1124. return;
  1125. }
  1126. if ('singleChoice' == nameEn) {
  1127. question.title = undefined;
  1128. question.required = false;
  1129. question.arrangement = '1';
  1130. question.increment = 0;
  1131. question.contentList.push({
  1132. label: undefined,
  1133. value: undefined,
  1134. nameEn: 'single' + question.increment.toString(),
  1135. allowFillBlank: false,
  1136. img: undefined,
  1137. score: '0.0',
  1138. });
  1139. return;
  1140. }
  1141. if ('multipleChoice' == nameEn) {
  1142. question.title = undefined;
  1143. question.required = false;
  1144. question.arrangement = '1';
  1145. question.scoreMethod = '1';
  1146. question.increment = 0;
  1147. question.contentList.push({
  1148. label: undefined,
  1149. value: undefined,
  1150. nameEn: 'multiple' + question.increment.toString(),
  1151. allowFillBlank: false,
  1152. img: undefined,
  1153. score: '0.0',
  1154. });
  1155. return;
  1156. }
  1157. if ('fillBlanks' == nameEn) {
  1158. question.title = undefined;
  1159. question.required = false;
  1160. question.arrangement = '1';
  1161. question.increment = 0;
  1162. question.contentList.push({
  1163. label: undefined,
  1164. value: undefined,
  1165. nameEn: 'fill' + question.increment.toString(),
  1166. img: undefined,
  1167. score: '0.0',
  1168. unit: '',
  1169. });
  1170. return;
  1171. }
  1172. if ('scaleQuestions' == nameEn) {
  1173. question.title = undefined;
  1174. question.required = false;
  1175. question.increment = 0;
  1176. question.contentList.push({
  1177. label: undefined,
  1178. value: undefined,
  1179. nameEn: 'scale' + question.increment.toString(),
  1180. score: '0.0',
  1181. });
  1182. return;
  1183. }
  1184. if ('matrixScale' == nameEn) {
  1185. question.title = undefined;
  1186. question.required = false;
  1187. question.increment = 0;
  1188. question.contentList.push({
  1189. labelFlag: true,
  1190. label: undefined,
  1191. value: undefined,
  1192. nameEn: 'matrix' + question.increment.toString(),
  1193. score: '0.0',
  1194. optionContent: '',
  1195. optionFlag: true,
  1196. });
  1197. return;
  1198. }
  1199. }
  1200. function handleBaseBtnClick(nameEn: string, nameCn: string) {
  1201. if (baseInfo.value.contentList.length < 1) {
  1202. baseInfo.value.title = '基本信息';
  1203. baseInfo.value.questionType = 'baseInfo';
  1204. baseInfo.value.contentList = [];
  1205. }
  1206. let questionAttr: QuestionAttrVO = {
  1207. label: nameCn,
  1208. value: undefined,
  1209. nameEn: nameEn,
  1210. };
  1211. if (baseInfo.value.contentList.length < 1) {
  1212. baseInfo.value.contentList.push(questionAttr);
  1213. } else {
  1214. let existed = false;
  1215. for (let item of baseInfo.value.contentList) {
  1216. if (item.nameEn == nameEn) {
  1217. existed = true;
  1218. break;
  1219. }
  1220. }
  1221. if (!existed) {
  1222. baseInfo.value.contentList.push(questionAttr);
  1223. }
  1224. }
  1225. }
  1226. function handleBaseBtnDelete(nameEn: string) {
  1227. let contentList = [];
  1228. for (let item of baseInfo.value.contentList) {
  1229. if (item.nameEn != nameEn) {
  1230. contentList.push(item);
  1231. }
  1232. }
  1233. if (contentList.length < 1) {
  1234. baseInfo.value.questionType = undefined;
  1235. baseInfo.value.contentList = [];
  1236. } else {
  1237. baseInfo.value.contentList = contentList;
  1238. }
  1239. }
  1240. function deleteBaseInfo() {
  1241. baseInfo.value.contentList = [];
  1242. baseInfo.value.questionType = undefined;
  1243. }
  1244. function deleteOtherInfo(index: number) {
  1245. let newList = []
  1246. for (let i = 0, len = otherInfo.value.length; i < len; i++) {
  1247. if (i == index) {
  1248. continue;
  1249. }
  1250. newList.push(otherInfo.value[i]);
  1251. }
  1252. otherInfo.value = newList;
  1253. }
  1254. function handleOtherBtnDelete(index: number, childIndex: number) {
  1255. let other = otherInfo.value[index]
  1256. let newList = [];
  1257. for (let i = 0, len = other.contentList.length; i < len; i++) {
  1258. if (i == childIndex) {
  1259. continue;
  1260. }
  1261. newList.push(other.contentList[i]);
  1262. }
  1263. other.contentList = newList;
  1264. if (newList.length == 0) {
  1265. newList = [];
  1266. for (let i = 0, len = otherInfo.value.length; i < len; i++) {
  1267. if (i == index) {
  1268. continue;
  1269. }
  1270. newList.push(otherInfo.value[i]);
  1271. }
  1272. otherInfo.value = newList
  1273. }
  1274. }
  1275. function handleMatrixScaleAdd(index: number, childIndex: number, isLeft: boolean) {
  1276. let other = otherInfo.value[index];
  1277. if (other.contentList.length == childIndex + 1) {
  1278. other.contentList.push({
  1279. labelFlag: isLeft,
  1280. label: undefined,
  1281. value: undefined,
  1282. nameEn: 'matrix' + other.increment.toString(),
  1283. score: '0.0',
  1284. optionContent: undefined,
  1285. optionFlag: !isLeft ,
  1286. });
  1287. return;
  1288. }
  1289. let effectiveNum = 0;
  1290. for (let item of other.contentList) {
  1291. if (isLeft) {
  1292. effectiveNum += (item.labelFlag ? 1 : 0);
  1293. } else {
  1294. effectiveNum += (item.optionFlag ? 1 : 0);
  1295. }
  1296. }
  1297. if (effectiveNum == other.contentList.length) {
  1298. other.contentList.push({
  1299. labelFlag: isLeft ,
  1300. label: undefined,
  1301. value: undefined,
  1302. nameEn: 'matrix' + other.increment.toString(),
  1303. score: '0.0',
  1304. optionContent: undefined,
  1305. optionFlag: !isLeft ,
  1306. });
  1307. } else {
  1308. let o = other.contentList[effectiveNum];
  1309. if (isLeft) {
  1310. o.labelFlag = true;
  1311. } else {
  1312. o.optionFlag = true;
  1313. }
  1314. }
  1315. for (let i = effectiveNum; i > 0; i--) {
  1316. let child = other.contentList[i]
  1317. if (i == childIndex + 1) {
  1318. if (isLeft) {
  1319. child.value = undefined;
  1320. } else {
  1321. child.optionContent = undefined;
  1322. }
  1323. break
  1324. }
  1325. let childPre = other.contentList[i - 1];
  1326. if (isLeft) {
  1327. child.value = childPre.value;
  1328. } else {
  1329. child.optionContent = childPre.optionContent;
  1330. }
  1331. }
  1332. }
  1333. function handleMatrixScaleDelete(index: number, childIndex: number, isLeft: boolean) {
  1334. let other = otherInfo.value[index];
  1335. let child = other.contentList[childIndex];
  1336. if (other.contentList.length == 0) {
  1337. if (isLeft) {
  1338. if (!child.optionFlag) {
  1339. other.contentList = [];
  1340. } else {
  1341. child.label = undefined;
  1342. }
  1343. } else {
  1344. if (!child.labelFlag) {
  1345. other.contentList = [];
  1346. } else {
  1347. child.optionFlag = false;
  1348. }
  1349. }
  1350. return;
  1351. }
  1352. for (let i = childIndex + 1, len = other.contentList.length; i < len; i++) {
  1353. let childPre = other.contentList[i - 1];
  1354. child = other.contentList[i];
  1355. if (isLeft) {
  1356. childPre.labelFlag = child.labelFlag;
  1357. childPre.value = child.value;
  1358. } else {
  1359. childPre.optionFlag = child.optionFlag;
  1360. childPre.optionContent = child.optionContent;
  1361. }
  1362. }
  1363. other.contentList.pop();
  1364. }
  1365. function handleOtherBtnAdd(index: number, questionType: string) {
  1366. let other = otherInfo.value[index]
  1367. let contentList = other.contentList;
  1368. other.increment += 1;
  1369. if ('singleChoice' == questionType) {
  1370. contentList.push({
  1371. label: undefined,
  1372. value: undefined,
  1373. nameEn: 'single' + other.increment.toString(),
  1374. allowFillBlank: false,
  1375. img: undefined,
  1376. score: '0.0',
  1377. });
  1378. return;
  1379. }
  1380. if ('multipleChoice' == questionType) {
  1381. contentList.push({
  1382. label: undefined,
  1383. value: undefined,
  1384. nameEn: 'multiple' + other.increment.toString(),
  1385. allowFillBlank: false,
  1386. img: undefined,
  1387. score: '0.0',
  1388. });
  1389. return;
  1390. }
  1391. if ('fillBlanks' == questionType) {
  1392. contentList.push({
  1393. label: undefined,
  1394. value: undefined,
  1395. nameEn: 'fill' + other.increment.toString(),
  1396. img: undefined,
  1397. score: '0.0',
  1398. unit: '',
  1399. });
  1400. return;
  1401. }
  1402. if ('scaleQuestions' == questionType) {
  1403. contentList.push({
  1404. label: undefined,
  1405. value: undefined,
  1406. nameEn: 'scale' + other.increment.toString(),
  1407. score: '0.0',
  1408. });
  1409. return;
  1410. }
  1411. if ('matrixScale' == questionType) {
  1412. contentList.push({
  1413. labelFlag: true,
  1414. label: undefined,
  1415. value: undefined,
  1416. nameEn: 'matrix' + other.increment.toString(),
  1417. score: '0.0',
  1418. optionContent: undefined,
  1419. optionFlag: true,
  1420. });
  1421. return;
  1422. }
  1423. }
  1424. function selectBaseInfo() {
  1425. baseInfo.value.selected = true;
  1426. otherInfo.value.forEach(item => {
  1427. item.selected = false;
  1428. });
  1429. }
  1430. function selectOtherInfo(index: number) {
  1431. baseInfo.value.selected = false;
  1432. otherInfo.value.forEach(item => {
  1433. item.selected = false;
  1434. });
  1435. let other = otherInfo.value[index]
  1436. other.selected = true;
  1437. }
  1438. function topUp(index: number) {
  1439. let other = otherInfo.value[index];
  1440. let newList = [other];
  1441. for (let i = 0, len = otherInfo.value.length; i < len; i++) {
  1442. if (i == index) {
  1443. continue;
  1444. }
  1445. newList.push(otherInfo.value[i]);
  1446. }
  1447. otherInfo.value = newList;
  1448. }
  1449. function bottomUp(index: number) {
  1450. let other = otherInfo.value[index];
  1451. let newList = [];
  1452. for (let i = 0, len = otherInfo.value.length; i < len; i++) {
  1453. if (i == index) {
  1454. continue;
  1455. }
  1456. newList.push(otherInfo.value[i]);
  1457. }
  1458. newList.push(other);
  1459. otherInfo.value = newList;
  1460. }
  1461. function moveUp(index: number) {
  1462. let other = otherInfo.value[index];
  1463. let newList = [];
  1464. for (let i = 0, len = otherInfo.value.length; i < len; i++) {
  1465. if (i == index - 1) {
  1466. newList.push(other);
  1467. }
  1468. if (i == index) {
  1469. continue;
  1470. }
  1471. newList.push(otherInfo.value[i]);
  1472. }
  1473. otherInfo.value = newList;
  1474. }
  1475. function moveDown(index: number) {
  1476. let other = otherInfo.value[index];
  1477. let newList = [];
  1478. for (let i = 0, len = otherInfo.value.length; i < len; i++) {
  1479. if (i == index) {
  1480. continue;
  1481. }
  1482. newList.push(otherInfo.value[i]);
  1483. if (i == index + 1) {
  1484. newList.push(other);
  1485. }
  1486. }
  1487. otherInfo.value = newList;
  1488. }
  1489. const bodyWidth = ref((window.document.body.clientWidth - 500) * 0.8);
  1490. function updateBodyWidth() {
  1491. let leftPanel = window.document.querySelector('#leftPanel').clientWidth;
  1492. bodyWidth.value = (window.document.body.clientWidth - leftPanel) * 0.93;
  1493. }
  1494. onMounted(() => {
  1495. window.addEventListener('resize', updateBodyWidth);
  1496. updateBodyWidth();
  1497. getList();
  1498. });
  1499. onUnmounted(() => {
  1500. window.removeEventListener('resize', updateBodyWidth);
  1501. });
  1502. </script>
  1503. <style scoped>
  1504. .layout-container-demo .el-header {
  1505. position: relative;
  1506. background-color: var(--el-color-primary-light-7);
  1507. color: var(--el-text-color-primary);
  1508. }
  1509. .layout-container-demo .el-aside {
  1510. color: var(--el-text-color-primary);
  1511. background: var(--el-color-primary-light-8);
  1512. }
  1513. .layout-container-demo .el-menu {
  1514. border-right: none;
  1515. }
  1516. .layout-container-demo .el-main {
  1517. padding: 0;
  1518. }
  1519. .layout-container-demo .toolbar {
  1520. display: inline-flex;
  1521. align-items: center;
  1522. justify-content: center;
  1523. height: 100%;
  1524. right: 20px;
  1525. }
  1526. .param-btn {
  1527. width: 100%;
  1528. height: 48px;
  1529. font-size: 13px;
  1530. font-weight: normal;
  1531. border: 1.5px solid #bfcbd9;
  1532. border-radius: 4px;
  1533. margin-bottom: 16px;
  1534. background: #fff;
  1535. color: #222;
  1536. letter-spacing: 1px;
  1537. display: flex;
  1538. align-items: center;
  1539. justify-content: center;
  1540. text-align: center;
  1541. white-space: nowrap;
  1542. overflow: hidden;
  1543. text-overflow: ellipsis;
  1544. padding: 0 2px;
  1545. }
  1546. @media (max-width: 1200px) {
  1547. .param-btn {
  1548. font-size: 13px;
  1549. }
  1550. }
  1551. @media (max-width: 800px) {
  1552. .param-btn {
  1553. font-size: 12px;
  1554. }
  1555. }
  1556. .selectedDiv {
  1557. background-color: #e8f4ff;
  1558. }
  1559. ul .el-upload--picture-card {
  1560. --el-upload-picture-card-size: 500px
  1561. }
  1562. .custom-radio-grid {
  1563. display: flex;
  1564. /* border: 1px solid #bfc4cc; */
  1565. border-radius: 4px;
  1566. background: #fff;
  1567. margin-bottom: 16px;
  1568. }
  1569. .custom-radio-cell {
  1570. width: 100px;
  1571. flex: none;
  1572. text-align: center;
  1573. border: 1px solid #bfc4cc;
  1574. margin: 0 !important;
  1575. height: 40px;
  1576. line-height: 20px;
  1577. font-size: 18px;
  1578. font-weight: normal;
  1579. background: #fff;
  1580. border-radius: 0 !important;
  1581. cursor: pointer;
  1582. user-select: none;
  1583. transition: background 0.2s;
  1584. word-break: break-all;
  1585. white-space: normal;
  1586. overflow-wrap: break-word;
  1587. display: flex;
  1588. align-items: center;
  1589. justify-content: center;
  1590. padding: 0 5px;
  1591. }
  1592. .custom-radio-cell:last-child {
  1593. border-right: none;
  1594. }
  1595. .custom-radio-cell .el-radio__input {
  1596. display: none !important;
  1597. }
  1598. .custom-radio-cell .el-radio__label {
  1599. padding: 0;
  1600. width: 100%;
  1601. display: block;
  1602. text-align: center;
  1603. cursor: pointer;
  1604. }
  1605. .custom-radio-cell.is-checked {
  1606. border-right: 1px solid #bfc4cc;
  1607. }
  1608. .custom-radio-cell.is-last {
  1609. border-right: 1px solid #bfc4cc;
  1610. border-left: none;
  1611. }
  1612. :deep(#jffs label) {
  1613. font-weight: normal;
  1614. }
  1615. </style>