CreateDialog.vue 117 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984
  1. <template>
  2. <div>
  3. <el-dialog v-el-drag-dialog :title="titleStr" :visible.sync="data.bSwitch" width="1200px" top="5vh">
  4. <el-form ref="ruleForm" :disabled="titleStr === '详情'" :model="ruleForm" :rules="rules" label-width="80px" class="demo-ruleForm">
  5. <el-row :gutter="16">
  6. <el-col :span="8">
  7. <el-form-item label="病历类型" prop="case_type">
  8. <el-select v-model="ruleForm.case_type" placeholder="请选择" style="width: 100%;">
  9. <el-option
  10. v-for="item in caseTypeOptions"
  11. :key="item.value"
  12. :label="item.label"
  13. :value="item.value"
  14. />
  15. </el-select>
  16. </el-form-item>
  17. </el-col>
  18. <el-col :span="8">
  19. <el-form-item label="质控项目" prop="object">
  20. <el-cascader
  21. v-model="ruleForm.object"
  22. :options="objects"
  23. :props="{
  24. expandTrigger: 'hover',
  25. value: 'field_name',
  26. label: 'field_name',
  27. children: 'child',
  28. checkStrictly: true // 添加此属性允许选择任意一级
  29. }"
  30. clearable
  31. filterable
  32. :show-all-levels="false"
  33. placeholder="请选择"
  34. style="width: 100%;"
  35. />
  36. </el-form-item>
  37. </el-col>
  38. <el-col :span="8">
  39. <el-form-item label="质控科室">
  40. <el-select
  41. v-model="ruleForm.department"
  42. multiple
  43. collapse-tags
  44. placeholder="请选择"
  45. style="width: 100%;"
  46. >
  47. <el-option
  48. v-for="item in departments"
  49. :key="item.id"
  50. :label="item.dep_name"
  51. :value="item.dep_id"
  52. />
  53. </el-select>
  54. </el-form-item>
  55. </el-col>
  56. <el-col :span="8">
  57. <el-form-item label="单项否决">
  58. <el-select v-model="ruleForm.is_not" filterable clearable placeholder="请选择" style="width: 100%;">
  59. <el-option label="是" :value="1" />
  60. <el-option label="否" :value="0" />
  61. </el-select>
  62. </el-form-item>
  63. </el-col>
  64. <el-col :span="8">
  65. <el-form-item label="质控状态" prop="status">
  66. <el-select v-model="ruleForm.status" filterable clearable placeholder="请选择" style="width: 100%;">
  67. <el-option label="开启" :value="1" />
  68. <el-option label="禁用" :value="2" />
  69. </el-select>
  70. </el-form-item>
  71. </el-col>
  72. <el-col :span="8">
  73. <el-form-item label="质控类型" prop="type">
  74. <el-select v-model="ruleForm.type" placeholder="请选择" style="width: 100%;">
  75. <el-option
  76. v-for="item in qualityTypeOptions"
  77. :key="item.value"
  78. :label="item.label"
  79. :value="item.value"
  80. />
  81. </el-select>
  82. </el-form-item>
  83. </el-col>
  84. <el-col :span="8">
  85. <el-form-item label="质控场景" prop="changjing">
  86. <el-select
  87. v-model="ruleForm.changjing"
  88. multiple
  89. collapse-tags
  90. placeholder="请选择"
  91. style="width: 100%;"
  92. >
  93. <el-option
  94. v-for="item in sceneOptions"
  95. :key="item.value"
  96. :label="item.label"
  97. :value="item.value"
  98. />
  99. </el-select>
  100. </el-form-item>
  101. </el-col>
  102. <el-col :span="8">
  103. <el-form-item label="风险等级" prop="error_level">
  104. <el-select v-model="ruleForm.error_level" filterable clearable placeholder="请选择" style="width: 100%;">
  105. <el-option label="必改" :value="1" />
  106. <el-option label="建议" :value="2" />
  107. </el-select>
  108. </el-form-item>
  109. </el-col>
  110. <el-col :span="8">
  111. <el-form-item label="扣分分值" prop="score">
  112. <el-input-number
  113. v-model="ruleForm.score"
  114. :precision="1"
  115. :step="0.5"
  116. step-strictly
  117. :max="100"
  118. :min="0"
  119. controls-position="right"
  120. placeholder="请输入"
  121. style="width: 100%;"
  122. />
  123. </el-form-item>
  124. </el-col>
  125. <el-col :span="24">
  126. <el-form-item label="规则描述" prop="description">
  127. <el-input v-model="ruleForm.description" type="textarea" :autosize="{ minRows: 3 }" placeholder="请输入" />
  128. </el-form-item>
  129. </el-col>
  130. </el-row>
  131. <el-row :gutter="16">
  132. <el-col :span="24">
  133. <el-form-item label="质控规则">
  134. <el-col :span="5">
  135. <el-form-item label="规则模板" prop="rule_type">
  136. <el-select v-model="ruleForm.rule_type" filterable placeholder="请选择" style="width: 100%;">
  137. <el-option label="普通规则" value="普通规则" />
  138. <!-- <el-option label="时效性规则" value="时效性规则" />
  139. <el-option label="完整性规则" value="完整性规则" />
  140. <el-option label="知识库规则" value="知识库规则" />
  141. <el-option label="大模型规则" value="大模型规则" /> -->
  142. </el-select>
  143. </el-form-item>
  144. </el-col>
  145. <el-col :span="24" style="margin-bottom: 20px;">
  146. <el-button type="primary" plain icon="el-icon-plus" @click="onAddQZTJ">前置条件</el-button>
  147. <el-button type="primary" plain icon="el-icon-plus" @click="onAddZKLJ">质控逻辑</el-button>
  148. <el-button type="primary" plain icon="el-icon-plus" @click="onAddZKYJ">质控依据</el-button>
  149. <el-button type="primary" plain icon="el-icon-plus" @click="onAddZKyujing">质控预警</el-button>
  150. </el-col>
  151. <!-- 前置条件 -->
  152. <el-col v-if="ruleForm.qztj.length" :span="24">
  153. <el-card v-for="(item, index) of ruleForm.qztj" :key="'qztj' + index" class="box-card" shadow="never">
  154. <div slot="header" class="clearfix box-card_header span">
  155. <span class="text">前置条件{{ index + 1 }}</span>
  156. <span class="ml40">
  157. <el-radio v-model="item.condition_type" :label="1">过滤</el-radio>
  158. <el-radio v-model="item.condition_type" :label="2">免审</el-radio>
  159. </span>
  160. <i
  161. class="el-icon-delete"
  162. style="float: right; margin-top: 13px; cursor: pointer;"
  163. @click="onDeleteQZTJ(index)"
  164. />
  165. </div>
  166. <div>
  167. <el-row
  168. v-for="(sItem, sIndex) of item.condition_content"
  169. :key="'tj' + sIndex"
  170. :gutter="12"
  171. class="mb12"
  172. >
  173. <el-col :span="2">
  174. <div class="text-right">条件{{ sIndex + 1 }}</div>
  175. </el-col>
  176. <el-col :span="6">
  177. <div class="rule-condition" @click="openCategoryDialog(index, sIndex, 'qztj')">
  178. <el-input
  179. :value="getDisplayName(sItem.param1)"
  180. placeholder="请选择"
  181. size="small"
  182. readonly
  183. style="width: 100%"
  184. />
  185. </div>
  186. </el-col>
  187. <el-col :span="3">
  188. <el-select
  189. v-model="sItem.condition"
  190. filterable
  191. clearable
  192. placeholder="请选择"
  193. style="width: 100%;"
  194. >
  195. <el-option
  196. v-for="(items, bindex) in selectFormula"
  197. :key="bindex"
  198. :label="items.formula"
  199. :value="items.formula"
  200. />
  201. </el-select>
  202. </el-col>
  203. <el-col v-if="sItem.condition === '时效'" :span="9">
  204. <el-row :gutter="8">
  205. <el-col :span="6">
  206. <div class="rule-condition">
  207. <el-input
  208. :value="getDisplayName(sItem.sx_1)"
  209. placeholder="请选择"
  210. size="small"
  211. readonly
  212. style="width: 100%;"
  213. />
  214. <el-button
  215. size="small"
  216. style="width: 70px; position: absolute; right: 0; top: 0; opacity: 0;"
  217. @click="openCategoryDialog(index, sIndex, 'sx_1')"
  218. />
  219. </div>
  220. </el-col>
  221. <el-col :span="2">
  222. <div class="text-right">至</div>
  223. </el-col>
  224. <el-col :span="6">
  225. <div class="rule-condition">
  226. <el-input
  227. :value="getDisplayName(sItem.sx_2)"
  228. placeholder="请选择"
  229. size="small"
  230. readonly
  231. style="width: 100%;"
  232. />
  233. <el-button
  234. size="small"
  235. style="width: 70px; position: absolute; right: 0; top: 0; opacity: 0;"
  236. @click="openCategoryDialog(index, sIndex, 'sx_2')"
  237. />
  238. </div>
  239. </el-col>
  240. <el-col v-if="sItem.sx_2" :span="0.5">
  241. <div class="text-right">+</div>
  242. </el-col>
  243. <el-col v-if="sItem.sx_2" :span="5">
  244. <el-input v-model="sItem.sx_3" clearable placeholder="请输入" style="width: 100%;" />
  245. </el-col>
  246. <el-col :span="3" style="margin-left: 5px;">
  247. <div class="text-right">小时</div>
  248. </el-col>
  249. </el-row>
  250. </el-col>
  251. <el-col v-else-if="sItem.condition === '范围'" :span="6">
  252. <el-row :gutter="8">
  253. <el-col :span="10">
  254. <el-input v-model="sItem.fanwei_1" clearable placeholder="请输入" />
  255. </el-col>
  256. <el-col :span="2">
  257. <div class="text-right">至</div>
  258. </el-col>
  259. <el-col :span="10">
  260. <el-input v-model="sItem.fanwei_2" clearable placeholder="请输入" />
  261. </el-col>
  262. </el-row>
  263. </el-col>
  264. <el-col v-else-if="['等于', '不等于', '包含', '不包含', '大于', '小于', '大于等于', '小于等于'].includes(sItem.condition)" :span="6">
  265. <div class="input-with-category">
  266. <template v-if="sItem.hasChildOptions">
  267. <!-- 当有三级数据时显示只读输入框和选择按钮 -->
  268. <el-input
  269. v-if="sItem.hasThirdLevel"
  270. :value="sItem.param2"
  271. placeholder="请选择"
  272. size="small"
  273. readonly
  274. style="width: calc(100% - 90px)"
  275. />
  276. <!-- 当没有三级数据时显示多选下拉框 -->
  277. <el-select
  278. v-else
  279. v-model="sItem.param2"
  280. multiple
  281. collapse-tags
  282. filterable
  283. clearable
  284. placeholder="请选择"
  285. size="small"
  286. style="width: calc(100% - 90px)"
  287. @change="(value) => handleInput(value, index, sIndex, 'qztj')"
  288. >
  289. <el-option
  290. v-for="option in sItem.childOptions"
  291. :key="option.field"
  292. :label="option.field_name"
  293. :value="option.field_name"
  294. />
  295. </el-select>
  296. </template>
  297. <template v-else>
  298. <el-input
  299. v-model="sItem.param2"
  300. placeholder="请输入"
  301. size="small"
  302. style="width: calc(100% - 90px)"
  303. @input="(value) => handleInput(value, index, sIndex, 'qztj')"
  304. />
  305. </template>
  306. <!-- 当有三级数据时显示选择按钮 -->
  307. <el-button
  308. v-if="sItem.hasThirdLevel"
  309. size="small"
  310. style="width: 90px"
  311. class="category-select"
  312. @click="openChildOptionsDialog(index, sIndex)"
  313. >
  314. <i class="el-icon-s-operation" style="margin-right: 5px" />
  315. 选择
  316. </el-button>
  317. <!-- 当没有三级数据时显示类型选择 -->
  318. <el-select
  319. v-else
  320. v-model="sItem.categoryType"
  321. size="small"
  322. placeholder="文本"
  323. style="width: 90px"
  324. class="category-select"
  325. :disabled="sItem.categoryTypeDisabled"
  326. >
  327. <i slot="prefix" class="el-icon-s-operation" />
  328. <el-option
  329. v-for="sitem in categories"
  330. :key="sitem.value"
  331. :label="sitem.label"
  332. :value="sitem.value"
  333. />
  334. </el-select>
  335. </div>
  336. </el-col>
  337. <el-col v-if="sItem.condition === '减'" :span="4">
  338. <div class="rule-condition">
  339. <el-input
  340. :value="getDisplayName(sItem.subtract_param)"
  341. placeholder="请选择"
  342. size="small"
  343. style="width: calc(100% - 70px)"
  344. readonly
  345. @click="openCategoryDialog(index, sIndex, 'subtract')"
  346. />
  347. <el-button
  348. size="small"
  349. style="width: 70px"
  350. class="category-select"
  351. @click="openCategoryDialog(index, sIndex, 'subtract')"
  352. >
  353. <i class="el-icon-s-operation" style="margin-right: 5px" />
  354. 选择
  355. </el-button>
  356. </div>
  357. </el-col>
  358. <el-col v-if="sItem.condition === '减'" :span="3">
  359. <el-select
  360. v-model="sItem.subtract_condition"
  361. filterable
  362. clearable
  363. placeholder="请选择"
  364. style="width: 100%;"
  365. >
  366. <el-option label="大于" value="gt" />
  367. <el-option label="小于" value="lt" />
  368. <el-option label="等于" value="eq" />
  369. </el-select>
  370. </el-col>
  371. <el-col v-if="sItem.condition === '减'" :span="3">
  372. <div class="input-with-category">
  373. <el-input
  374. v-model="sItem.subtract_value"
  375. placeholder="请输入"
  376. size="small"
  377. style="width: calc(100% - 70px)"
  378. />
  379. <el-select
  380. v-model="sItem.subtract_value_type"
  381. size="small"
  382. placeholder="类型"
  383. style="width: 70px"
  384. class="category-select"
  385. >
  386. <el-option label="小时" value="hour" />
  387. <el-option label="分钟" value="minute" />
  388. <el-option label="数值" value="number" />
  389. </el-select>
  390. </div>
  391. </el-col>
  392. <el-col v-else-if="sItem.condition === '重复率'" :span="9">
  393. <el-row :gutter="8">
  394. <el-col :span="10">
  395. <!-- 第二参数选择 -->
  396. <div class="rule-condition">
  397. <el-input
  398. :value="getDisplayName(sItem.param2_object)"
  399. placeholder="请选择比较对象"
  400. size="small"
  401. readonly
  402. style="width: 100%;"
  403. />
  404. <el-button
  405. size="small"
  406. style="width: 90px; position: absolute; right: 0; top: 0; opacity: 0;"
  407. @click="openCategoryDialog(index, sIndex, 'param2_object')"
  408. />
  409. </div>
  410. </el-col>
  411. <el-col :span="2">
  412. <div class="text-center" style="line-height: 36px;">≥</div>
  413. </el-col>
  414. <el-col :span="8">
  415. <!-- 重复率值输入 -->
  416. <el-input-number
  417. v-model="sItem.subtract_value"
  418. :precision="1"
  419. :step="0.1"
  420. :max="100"
  421. :min="0"
  422. controls-position="right"
  423. placeholder="重复率"
  424. style="width: 100%;"
  425. />
  426. </el-col>
  427. <el-col :span="2">
  428. <div class="text-left" style="line-height: 36px; padding-left: 5px;">%</div>
  429. </el-col>
  430. </el-row>
  431. </el-col>
  432. <el-col :span="2">
  433. <div class="button-group">
  434. <el-button
  435. type="primary"
  436. plain
  437. icon="el-icon-plus"
  438. size="mini"
  439. @click="onAddTJ(index, sIndex)"
  440. />
  441. <el-button
  442. v-if="item.condition_content.length !== 1"
  443. size="mini"
  444. type="primary"
  445. plain
  446. icon="el-icon-minus"
  447. @click="onDeleteTJ(index, sIndex)"
  448. />
  449. </div>
  450. </el-col>
  451. </el-row>
  452. </div>
  453. </el-card>
  454. </el-col>
  455. <!-- 质控逻辑 -->
  456. <el-col :span="24">
  457. <el-divider />
  458. <el-card v-for="(item, index) of ruleForm.rule" :key="'rule' + index" class="box-card" shadow="never">
  459. <div slot="header" class="clearfix box-card_header span">
  460. <span class="text">质控逻辑</span>
  461. <span class="ml40">
  462. <span>流向</span>
  463. <el-radio v-model="item.detail_status" :label="1" class="ml40">正确</el-radio>
  464. <el-radio v-model="item.detail_status" :label="2">错误</el-radio>
  465. </span>
  466. </div>
  467. <div>
  468. <el-row
  469. v-for="(sItem, sIndex) of item.condition_content"
  470. :key="'tj' + sIndex"
  471. :gutter="12"
  472. class="mb12"
  473. >
  474. <el-col :span="2">
  475. <div class="text-right">逻辑{{ sIndex + 1 }}</div>
  476. </el-col>
  477. <el-col v-if="!(sItem.condition === '病程记录关联' || sItem.condition === '时效')" :span="5">
  478. <div class="rule-condition" @click="openCategoryDialog(index, sIndex, 'rule')">
  479. <el-input
  480. :value="getDisplayName(sItem.param1)"
  481. placeholder="请选择"
  482. size="small"
  483. readonly
  484. style="width: 100%"
  485. />
  486. </div>
  487. </el-col>
  488. <el-col v-if="!(sItem.condition === '病程记录关联' || sItem.condition === '时效')" :span="4">
  489. <el-select
  490. v-model="sItem.condition"
  491. filterable
  492. clearable
  493. placeholder="请选择"
  494. style="width: 100%;"
  495. >
  496. <el-option
  497. v-for="(items, bindex) in selectFormula"
  498. :key="bindex"
  499. :label="items.formula"
  500. :value="items.formula"
  501. />
  502. </el-select>
  503. </el-col>
  504. <el-col v-if="sItem.condition === '时效'" :span="22" class="progress-note">
  505. <el-row :gutter="24">
  506. <el-col v-if="sItem.condition === '时效'" :span="5">
  507. <el-select
  508. v-model="sItem.condition"
  509. filterable
  510. clearable
  511. placeholder="请选择"
  512. style="width: 100%;"
  513. >
  514. <el-option
  515. v-for="(items, bindex) in selectFormula"
  516. :key="bindex"
  517. :label="items.formula"
  518. :value="items.formula"
  519. />
  520. </el-select>
  521. </el-col>
  522. <el-col :span="5">
  523. <div class="rule-condition" @click="openCategoryDialog(index, sIndex, 'sx_param1')">
  524. <el-input
  525. :value="getDisplayName(sItem.sx_param1)"
  526. placeholder="请选择"
  527. size="small"
  528. readonly
  529. style="width: 100%"
  530. />
  531. </div>
  532. </el-col>
  533. <el-col :span="2">
  534. <div class="text-center">等于</div>
  535. </el-col>
  536. <el-col :span="5">
  537. <div class="rule-condition">
  538. <el-input
  539. v-model="sItem.sx_param2"
  540. placeholder="请输入"
  541. size="small"
  542. style="width: 100%;"
  543. @input="(value) => handleInput(value, index, sIndex, 'rule_other', 'sx_param2')"
  544. />
  545. </div>
  546. </el-col>
  547. <el-col :span="5">
  548. <div class="rule-condition" @click="openCategoryDialog(index, sIndex, 'sx_param3')">
  549. <el-input
  550. :value="getDisplayName(sItem.sx_param3)"
  551. placeholder="请选择"
  552. size="small"
  553. readonly
  554. style="width: 100%"
  555. />
  556. </div>
  557. </el-col>
  558. <el-col :span="2">
  559. <div class="text-center">在</div>
  560. </el-col>
  561. <el-col :span="5">
  562. <div class="rule-condition" @click="openCategoryDialog(index, sIndex, 'sx_param4_index')">
  563. <el-input
  564. :value="getDisplayName(sItem.sx_param4_index)"
  565. placeholder="请选择"
  566. size="small"
  567. readonly
  568. style="width: 100%"
  569. />
  570. </div>
  571. </el-col>
  572. <el-col :span="2">
  573. <div class="text-center">包含</div>
  574. </el-col>
  575. <el-col :span="4">
  576. <div class="rule-condition">
  577. <el-input
  578. v-model="sItem.sx_param4_condition1"
  579. placeholder="请输入"
  580. size="small"
  581. style="width: 100%;"
  582. @input="(value) => handleInput(value, index, sIndex, 'rule_other', 'sx_param4_condition1')"
  583. />
  584. </div>
  585. </el-col>
  586. <el-col :span="2">
  587. <div class="text-center">不包含</div>
  588. </el-col>
  589. <el-col :span="4">
  590. <div class="rule-condition">
  591. <el-input
  592. v-model="sItem.sx_param4_condition2"
  593. placeholder="请输入"
  594. size="small"
  595. style="width: 100%;"
  596. @input="(value) => handleInput(value, index, sIndex, 'rule_other', 'sx_param4_condition2')"
  597. />
  598. </div>
  599. </el-col>
  600. <el-col :span="5">
  601. <div class="rule-condition" @click="openCategoryDialog(index, sIndex, 'sx_param4_kssj')">
  602. <el-input
  603. :value="getDisplayName(sItem.sx_param4_kssj)"
  604. placeholder="请选择"
  605. size="small"
  606. readonly
  607. style="width: 100%"
  608. />
  609. </div>
  610. </el-col>
  611. <el-col :span="2">
  612. <div class="text-center">至</div>
  613. </el-col>
  614. <el-col :span="5">
  615. <div class="rule-condition" @click="openCategoryDialog(index, sIndex, 'sx_param4_jssj')">
  616. <el-input
  617. :value="getDisplayName(sItem.sx_param4_jssj)"
  618. placeholder="请选择"
  619. size="small"
  620. readonly
  621. style="width: 100%"
  622. />
  623. </div>
  624. </el-col>
  625. <el-col :span="1">
  626. <div class="text-center">+</div>
  627. </el-col>
  628. <el-col :span="4">
  629. <div class="rule-condition">
  630. <el-input
  631. v-model="sItem.sx_param4_sjjg"
  632. placeholder="请输入"
  633. size="small"
  634. style="width: 100%;"
  635. />
  636. </div>
  637. </el-col>
  638. <el-col :span="2">
  639. <div class="text-center">小时内</div>
  640. </el-col>
  641. <el-col v-if="sItem.condition === '时效'" :span="2">
  642. <div class="button-group">
  643. <el-button
  644. type="primary"
  645. plain
  646. icon="el-icon-plus"
  647. size="mini"
  648. @click="onAddGZ(index, sIndex)"
  649. />
  650. <el-button
  651. v-if="item.condition_content.length !== 1"
  652. size="mini"
  653. type="primary"
  654. plain
  655. icon="el-icon-minus"
  656. @click="onDeleteGZ(index, sIndex)"
  657. />
  658. </div>
  659. </el-col>
  660. <!-- <el-col :span="6">
  661. <div class="rule-condition">
  662. <el-input
  663. :value="getDisplayName(sItem.sx_2)"
  664. placeholder="请选择"
  665. size="small"
  666. readonly
  667. style="width: 100%;"
  668. />
  669. <el-button
  670. size="small"
  671. style="width: 90px; position: absolute; right: 0; top: 0; opacity: 0;"
  672. @click="openCategoryDialog(index, sIndex, 'sx_2')"
  673. />
  674. </div>
  675. </el-col>
  676. <el-col v-if="sItem.sx_2" :span="0.5">
  677. <div class="text-right">+</div>
  678. </el-col>
  679. <el-col v-if="sItem.sx_2" :span="5">
  680. <el-input v-model="sItem.sx_3" clearable placeholder="请输入" style="width: 100%;" />
  681. </el-col>
  682. <el-col :span="3">
  683. <div class="text-right">小时</div>
  684. </el-col> -->
  685. </el-row>
  686. </el-col>
  687. <el-col v-else-if="sItem.condition === '范围'" :span="6">
  688. <el-row :gutter="8">
  689. <el-col :span="10">
  690. <el-input v-model="sItem.fanwei_1" clearable placeholder="请输入" />
  691. </el-col>
  692. <el-col :span="2">
  693. <div class="text-right">至</div>
  694. </el-col>
  695. <el-col :span="10">
  696. <el-input v-model="sItem.fanwei_2" clearable placeholder="请输入" />
  697. </el-col>
  698. </el-row>
  699. </el-col>
  700. <el-col v-else-if="['等于', '不等于', '包含', '不包含', '大于', '小于', '大于等于', '小于等于'].includes(sItem.condition)" :span="6">
  701. <div class="input-with-category">
  702. <template v-if="sItem.hasChildOptions">
  703. <!-- 当有三级数据时显示只读输入框和选择按钮 -->
  704. <el-input
  705. v-if="sItem.hasThirdLevel"
  706. :value="sItem.param2"
  707. placeholder="请选择"
  708. size="small"
  709. readonly
  710. style="width: calc(100% - 90px)"
  711. />
  712. <!-- 当没有三级数据时显示多选下拉框 -->
  713. <el-select
  714. v-else
  715. v-model="sItem.param2"
  716. multiple
  717. collapse-tags
  718. filterable
  719. clearable
  720. placeholder="请选择"
  721. size="small"
  722. style="width: calc(100% - 90px)"
  723. @change="(value) => handleInput(value, index, sIndex, 'rule')"
  724. >
  725. <el-option
  726. v-for="option in sItem.childOptions"
  727. :key="option.field"
  728. :label="option.field_name"
  729. :value="option.field_name"
  730. />
  731. </el-select>
  732. </template>
  733. <template v-else>
  734. <el-input
  735. v-model="sItem.param2"
  736. placeholder="请输入"
  737. size="small"
  738. style="width: calc(100% - 90px)"
  739. @input="(value) => sItem.categoryType === '字典' && handleInput(value, index, sIndex, 'rule')"
  740. />
  741. </template>
  742. <!-- 当有三级数据时显示选择按钮 -->
  743. <el-button
  744. v-if="sItem.hasThirdLevel"
  745. size="small"
  746. style="width: 90px"
  747. class="category-select"
  748. @click="openChildOptionsDialog(index, sIndex)"
  749. >
  750. <i class="el-icon-s-operation" style="margin-right: 5px" />
  751. 选择
  752. </el-button>
  753. <!-- 当没有三级数据时显示类型选择 -->
  754. <el-select
  755. v-else
  756. v-model="sItem.categoryType"
  757. size="small"
  758. placeholder="文本"
  759. style="width: 90px"
  760. class="category-select"
  761. :disabled="sItem.categoryTypeDisabled"
  762. >
  763. <i slot="prefix" class="el-icon-s-operation" />
  764. <el-option
  765. v-for="sitem in categories"
  766. :key="sitem.value"
  767. :label="sitem.label"
  768. :value="sitem.value"
  769. />
  770. </el-select>
  771. </div>
  772. </el-col>
  773. <el-col v-if="['包含', '不包含'].includes(sItem.condition)" :span="1">
  774. <div class="text-center" style="line-height: 36px;">删除</div>
  775. </el-col>
  776. <el-col v-if="['包含', '不包含'].includes(sItem.condition)" :span="4">
  777. <!-- 第二参数选择 -->
  778. <div class="rule-condition">
  779. <el-input
  780. v-model="sItem.delete_field"
  781. placeholder="请输入"
  782. size="small"
  783. style="width: 100%;"
  784. />
  785. </div>
  786. </el-col>
  787. <el-col v-if="sItem.condition === '减'" :span="4">
  788. <div class="rule-condition">
  789. <el-input
  790. :value="getDisplayName(sItem.subtract_param)"
  791. placeholder="请选择"
  792. size="small"
  793. style="width: calc(100% - 90px)"
  794. readonly
  795. @click="openCategoryDialog(index, sIndex, 'subtract')"
  796. />
  797. <el-button
  798. size="small"
  799. style="width: 90px"
  800. class="category-select"
  801. @click="openCategoryDialog(index, sIndex, 'subtract')"
  802. >
  803. <i class="el-icon-s-operation" style="margin-right: 5px" />
  804. 选择
  805. </el-button>
  806. </div>
  807. </el-col>
  808. <el-col v-if="sItem.condition === '减'" :span="3">
  809. <el-select
  810. v-model="sItem.subtract_condition"
  811. filterable
  812. clearable
  813. placeholder="请选择"
  814. style="width: 100%;"
  815. >
  816. <el-option label="大于" value="gt" />
  817. <el-option label="小于" value="lt" />
  818. <el-option label="等于" value="eq" />
  819. </el-select>
  820. </el-col>
  821. <el-col v-if="sItem.condition === '减'" :span="3">
  822. <div class="input-with-category">
  823. <el-input
  824. v-model="sItem.subtract_value"
  825. placeholder="请输入"
  826. size="small"
  827. style="width: calc(100% - 70px)"
  828. />
  829. <el-select
  830. v-model="sItem.subtract_value_type"
  831. size="small"
  832. placeholder="类型"
  833. style="width: 70px"
  834. class="category-select"
  835. >
  836. <el-option label="小时" value="hour" />
  837. <el-option label="分钟" value="minute" />
  838. <el-option label="数值" value="number" />
  839. </el-select>
  840. </div>
  841. </el-col>
  842. <el-col v-else-if="sItem.condition === '重复率'" :span="9">
  843. <el-row :gutter="8">
  844. <el-col :span="10">
  845. <!-- 第二参数选择 -->
  846. <div class="rule-condition">
  847. <el-input
  848. :value="getDisplayName(sItem.param2_object)"
  849. placeholder="请选择比较对象"
  850. size="small"
  851. readonly
  852. style="width: 100%;"
  853. />
  854. <el-button
  855. size="small"
  856. style="width: 90px; position: absolute; right: 0; top: 0; opacity: 0;"
  857. @click="openCategoryDialog(index, sIndex, 'param2_object')"
  858. />
  859. </div>
  860. </el-col>
  861. <el-col :span="2">
  862. <div class="text-center" style="line-height: 36px;">≥</div>
  863. </el-col>
  864. <el-col :span="8">
  865. <!-- 重复率值输入 -->
  866. <el-input-number
  867. v-model="sItem.subtract_value"
  868. :precision="1"
  869. :step="0.1"
  870. :max="100"
  871. :min="0"
  872. controls-position="right"
  873. placeholder="重复率"
  874. style="width: 100%;"
  875. />
  876. </el-col>
  877. <el-col :span="2">
  878. <div class="text-left" style="line-height: 36px; padding-left: 5px;">%</div>
  879. </el-col>
  880. </el-row>
  881. </el-col>
  882. <el-col v-else-if="sItem.condition === '病程记录关联'" :span="22" class="progress-note">
  883. <el-row :gutter="24">
  884. <!-- 参数1 -->
  885. <el-col v-if="sItem.condition === '病程记录关联'" :span="5">
  886. <el-select
  887. v-model="sItem.condition"
  888. filterable
  889. clearable
  890. placeholder="请选择"
  891. style="width: 100%;"
  892. >
  893. <el-option
  894. v-for="(items, bindex) in selectFormula"
  895. :key="bindex"
  896. :label="items.formula"
  897. :value="items.formula"
  898. />
  899. </el-select>
  900. </el-col>
  901. <!-- 参数2 -->
  902. <el-col :span="4">
  903. <div class="rule-condition">
  904. <el-input
  905. v-model="sItem.pn_param1_BLBH"
  906. placeholder="请输入"
  907. size="small"
  908. style="width: 100%;"
  909. @input="(value) => handleInput(value, index, sIndex, 'rule_other', 'pn_param1_BLBH')"
  910. />
  911. </div>
  912. </el-col>
  913. <!-- 参数3 -->
  914. <el-col :span="5">
  915. <div class="rule-condition" @click="openCategoryDialog(index, sIndex, 'pn_param1')">
  916. <el-input
  917. :value="getDisplayName(sItem.pn_param1)"
  918. placeholder="请选择"
  919. size="small"
  920. readonly
  921. style="width: 100%"
  922. />
  923. </div>
  924. </el-col>
  925. <!-- 参数4 -->
  926. <el-col :span="4">
  927. <div class="rule-condition">
  928. <el-input
  929. v-model="sItem.pn_param2"
  930. placeholder="请输入"
  931. size="small"
  932. style="width: 100%;"
  933. @input="(value) => handleInput(value, index, sIndex, 'rule_other', 'pn_param2')"
  934. />
  935. </div>
  936. </el-col>
  937. <!-- 参数5 -->
  938. <el-col :span="5">
  939. <div class="rule-condition" @click="openCategoryDialog(index, sIndex, 'pn_param3')">
  940. <el-input
  941. :value="getDisplayName(sItem.pn_param3)"
  942. placeholder="请选择"
  943. size="small"
  944. readonly
  945. style="width: 100%"
  946. />
  947. </div>
  948. </el-col>
  949. <el-col :span="1">
  950. <div class="text-center" style="line-height: 36px;">在</div>
  951. </el-col>
  952. <!-- 参数6 -->
  953. <el-col :span="5">
  954. <div class="rule-condition" @click="openCategoryDialog(index, sIndex, 'pn_param4_index')">
  955. <el-input
  956. :value="getDisplayName(sItem.pn_param4_index)"
  957. placeholder="请选择"
  958. size="small"
  959. readonly
  960. style="width: 100%"
  961. />
  962. </div>
  963. </el-col>
  964. <el-col :span="2">
  965. <div class="text-center" style="line-height: 36px;">包含</div>
  966. </el-col>
  967. <!-- 参数7 -->
  968. <el-col :span="4">
  969. <div class="rule-condition">
  970. <el-input
  971. v-model="sItem.pn_param4_condition1"
  972. placeholder="请输入"
  973. size="small"
  974. style="width: 100%;"
  975. @input="(value) => handleInput(value, index, sIndex, 'rule_other', 'pn_param4_condition1')"
  976. />
  977. </div>
  978. </el-col>
  979. <el-col :span="2">
  980. <div class="text-center" style="line-height: 36px;">不包含</div>
  981. </el-col>
  982. <!-- 参数8 -->
  983. <el-col :span="4">
  984. <div class="rule-condition">
  985. <el-input
  986. v-model="sItem.pn_param4_condition2"
  987. placeholder="请输入"
  988. size="small"
  989. style="width: 100%;"
  990. @input="(value) => handleInput(value, index, sIndex, 'rule_other', 'pn_param4_condition2')"
  991. />
  992. </div>
  993. </el-col>
  994. <!-- 参数9 -->
  995. <el-col :span="5">
  996. <div class="rule-condition" @click="openCategoryDialog(index, sIndex, 'pn_param4_kssj')">
  997. <el-input
  998. :value="getDisplayName(sItem.pn_param4_kssj)"
  999. placeholder="请选择"
  1000. size="small"
  1001. readonly
  1002. style="width: 100%"
  1003. />
  1004. </div>
  1005. </el-col>
  1006. <el-col :span="1">
  1007. <div class="text-center" style="line-height: 36px;">至</div>
  1008. </el-col>
  1009. <!-- 参数10 -->
  1010. <el-col :span="5">
  1011. <div class="rule-condition" @click="openCategoryDialog(index, sIndex, 'pn_param4_jssj')">
  1012. <el-input
  1013. :value="getDisplayName(sItem.pn_param4_jssj)"
  1014. placeholder="请选择"
  1015. size="small"
  1016. readonly
  1017. style="width: 100%"
  1018. />
  1019. </div>
  1020. </el-col>
  1021. <el-col :span="1">
  1022. <div class="text-center" style="line-height: 36px;">+</div>
  1023. </el-col>
  1024. <!-- 参数11 -->
  1025. <el-col :span="4">
  1026. <div class="rule-condition">
  1027. <el-input
  1028. v-model="sItem.pn_param4_sjjg"
  1029. placeholder="请输入"
  1030. size="small"
  1031. style="width: 100%;"
  1032. />
  1033. </div>
  1034. </el-col>
  1035. <el-col :span="2">
  1036. <div class="text-center" style="line-height: 36px;">小时内</div>
  1037. </el-col>
  1038. </el-row>
  1039. <el-row :gutter="24">
  1040. <!-- 参数12 -->
  1041. <el-col :span="5">
  1042. <el-select
  1043. v-model="sItem.pn_param5"
  1044. filterable
  1045. clearable
  1046. placeholder="请选择"
  1047. style="width: 100%;"
  1048. >
  1049. <el-option label="关联" value="gl" />
  1050. <el-option label="不关联" value="bgl" />
  1051. </el-select>
  1052. </el-col>
  1053. <!-- 参数13 -->
  1054. <el-col :span="4">
  1055. <div class="rule-condition" @click="openCategoryDialog(index, sIndex, 'pn_param6')">
  1056. <el-input
  1057. :value="getDisplayName(sItem.pn_param6)"
  1058. placeholder="请选择"
  1059. size="small"
  1060. readonly
  1061. style="width: 100%"
  1062. />
  1063. </div>
  1064. </el-col>
  1065. <el-col :span="2">
  1066. <div class="text-center" style="line-height: 36px;">包含</div>
  1067. </el-col>
  1068. <!-- 参数14 -->
  1069. <el-col :span="4">
  1070. <div class="rule-condition">
  1071. <el-input
  1072. v-model="sItem.pn_param6_ct"
  1073. placeholder="请输入"
  1074. size="small"
  1075. style="width: 100%;"
  1076. @input="(value) => handleInput(value, index, sIndex, 'rule_other', 'pn_param6_ct')"
  1077. />
  1078. </div>
  1079. </el-col>
  1080. <el-col :span="2">
  1081. <div class="text-center" style="line-height: 36px;">不含</div>
  1082. </el-col>
  1083. <!-- 参数15 -->
  1084. <el-col :span="4">
  1085. <div class="rule-condition">
  1086. <el-input
  1087. v-model="sItem.pn_param6_oct"
  1088. placeholder="请输入"
  1089. size="small"
  1090. style="width: 100%;"
  1091. @input="(value) => handleInput(value, index, sIndex, 'rule_other', 'pn_param6_oct')"
  1092. />
  1093. </div>
  1094. </el-col>
  1095. <el-col v-if="sItem.condition === '病程记录关联'" :span="2">
  1096. <div class="button-group">
  1097. <el-button
  1098. type="primary"
  1099. plain
  1100. icon="el-icon-plus"
  1101. size="mini"
  1102. @click="onAddGZ(index, sIndex)"
  1103. />
  1104. <el-button
  1105. v-if="item.condition_content.length !== 1"
  1106. size="mini"
  1107. type="primary"
  1108. plain
  1109. icon="el-icon-minus"
  1110. @click="onDeleteGZ(index, sIndex)"
  1111. />
  1112. </div>
  1113. </el-col>
  1114. </el-row>
  1115. </el-col>
  1116. <el-col v-if="!(sItem.condition === '病程记录关联' || sItem.condition === '时效')" :span="2">
  1117. <div class="button-group">
  1118. <el-button
  1119. type="primary"
  1120. plain
  1121. icon="el-icon-plus"
  1122. size="mini"
  1123. @click="onAddGZ(index, sIndex)"
  1124. />
  1125. <el-button
  1126. v-if="item.condition_content.length !== 1"
  1127. size="mini"
  1128. type="primary"
  1129. plain
  1130. icon="el-icon-minus"
  1131. @click="onDeleteGZ(index, sIndex)"
  1132. />
  1133. </div>
  1134. </el-col>
  1135. </el-row>
  1136. <div class="span">
  1137. <span>规则之间的逻辑</span>
  1138. <el-radio v-model="item.condition_relation" :label="1" class="ml40">且(满足所有条件)</el-radio>
  1139. <el-radio v-model="item.condition_relation" :label="2">或(满足任意一条件)</el-radio>
  1140. </div>
  1141. </div>
  1142. </el-card>
  1143. </el-col>
  1144. <!-- 质控依据 -->
  1145. <el-col v-if="ruleForm.rule[0].custom_basis.length" :span="24">
  1146. <el-card v-for="(item, index) of ruleForm.rule" :key="'rule' + index" class="box-card" shadow="never">
  1147. <div slot="header" class="clearfix box-card_header span">
  1148. <span class="text">质控依据</span>
  1149. <i
  1150. class="el-icon-delete"
  1151. style="float: right; margin-top: 13px; cursor: pointer;"
  1152. @click="onDeleteZKYJ(index)"
  1153. />
  1154. </div>
  1155. <div>
  1156. <el-row v-for="(sItem, sIndex) of item.custom_basis" :key="'tj' + sIndex" :gutter="12" class="mb12">
  1157. <el-col :span="2">
  1158. <div class="text-right">条件{{ sIndex + 1 }}</div>
  1159. </el-col>
  1160. <el-col :span="6">
  1161. <div class="rule-condition">
  1162. <el-input
  1163. v-model="sItem.input1"
  1164. placeholder="请输入"
  1165. size="small"
  1166. style="width: 100%"
  1167. />
  1168. </div>
  1169. </el-col>
  1170. <el-col :span="6">
  1171. <div class="rule-condition">
  1172. <el-input
  1173. :value="getDisplayName(sItem.param1)"
  1174. placeholder="请选择"
  1175. size="small"
  1176. style="width: calc(100% - 90px)"
  1177. readonly
  1178. @click="openCategoryDialog(index, sIndex, 'custom_basis')"
  1179. />
  1180. <el-button
  1181. size="small"
  1182. style="width: 90px"
  1183. class="category-select"
  1184. @click="openCategoryDialog(index, sIndex, 'custom_basis')"
  1185. >
  1186. <i class="el-icon-s-operation" style="margin-right: 5px" />
  1187. 选择
  1188. </el-button>
  1189. </div>
  1190. </el-col>
  1191. <el-col :span="6">
  1192. <el-input v-model="sItem.input2" clearable placeholder="请输入" style="width: 100%;" />
  1193. </el-col>
  1194. <el-col :span="4">
  1195. <el-button
  1196. type="primary"
  1197. plain
  1198. icon="el-icon-plus"
  1199. size="mini"
  1200. @click="onAddTJZKYJ(index, sIndex)"
  1201. />
  1202. <el-button
  1203. v-if="item.custom_basis.length !== 1"
  1204. size="mini"
  1205. type="primary"
  1206. plain
  1207. icon="el-icon-minus"
  1208. @click="onDeleteTJZKYJ(index, sIndex)"
  1209. />
  1210. </el-col>
  1211. </el-row>
  1212. </div>
  1213. </el-card>
  1214. </el-col>
  1215. <!-- 质控预警 -->
  1216. <el-col v-if="Object.keys(ruleForm.rule[0].custom_msg).length != 0" :span="24">
  1217. <el-card v-for="(item, index) of ruleForm.rule" :key="'rule' + index" class="box-card" shadow="never">
  1218. <div slot="header" class="clearfix box-card_header span">
  1219. <span class="text">质控预警</span>
  1220. <i
  1221. class="el-icon-delete"
  1222. style="float: right; margin-top: 13px; cursor: pointer;"
  1223. @click="onDeleteZKyujing(index)"
  1224. />
  1225. </div>
  1226. <div>
  1227. <el-row :gutter="12" class="mb12">
  1228. <el-col :span="2">
  1229. <div class="text-right">事件</div>
  1230. </el-col>
  1231. <el-col :span="7">
  1232. <div class="rule-condition" @click="openCategoryDialog(index, 0, 'custom_msg')">
  1233. <el-input
  1234. :value="getDisplayName(item.custom_msg.param1)"
  1235. placeholder="请选择"
  1236. size="small"
  1237. readonly
  1238. style="width: 100%"
  1239. />
  1240. </div>
  1241. </el-col>
  1242. <el-col :span="1"> + </el-col>
  1243. <el-col :span="2"><el-input
  1244. v-model="item.custom_msg.aftertime"
  1245. clearable
  1246. placeholder="请输入"
  1247. style="width: 100%;"
  1248. /></el-col>
  1249. <el-col :span="1">分</el-col>
  1250. <el-col :span="1">前</el-col>
  1251. <el-col :span="2"><el-input
  1252. v-model="item.pre_warning_time"
  1253. clearable
  1254. placeholder="请输入"
  1255. style="width: 100%;"
  1256. /></el-col>
  1257. <el-col :span="2">分提醒</el-col>
  1258. </el-row>
  1259. <el-row :gutter="12" class="mb12">
  1260. <el-col :span="2">
  1261. <div class="text-right">预警提示</div>
  1262. </el-col>
  1263. <el-col :span="6">
  1264. <el-input v-model="item.custom_msg.input1" clearable placeholder="请输入" style="width: 100%;" />
  1265. </el-col>
  1266. <el-col :span="4">
  1267. <el-input
  1268. v-model="item.custom_msg.input3"
  1269. clearable
  1270. disabled
  1271. placeholder="请输入"
  1272. style="width: 100%;"
  1273. />
  1274. </el-col>
  1275. <el-col :span="6">
  1276. <el-input v-model="item.custom_msg.input2" clearable placeholder="请输入" style="width: 100%;" />
  1277. </el-col>
  1278. <el-col :span="4" />
  1279. </el-row>
  1280. </div>
  1281. </el-card>
  1282. </el-col>
  1283. </el-form-item>
  1284. </el-col>
  1285. </el-row>
  1286. </el-form>
  1287. <span v-if="titleStr !== '详情'" slot="footer" class="dialog-footer">
  1288. <el-button type="primary" @click="submitForm('ruleForm')">提 交</el-button>
  1289. <el-button @click="onTest">测试规则</el-button>
  1290. </span>
  1291. </el-dialog>
  1292. <!-- 新增选择弹窗 -->
  1293. <el-dialog title="选择类目" :visible.sync="categoryDialogVisible" width="600px" append-to-body>
  1294. <el-tabs
  1295. v-model="activeCategory"
  1296. type="border-card"
  1297. class="tab"
  1298. :tab-position="'left'"
  1299. style="height:max-content"
  1300. @tab-click="handleCategoryClick"
  1301. >
  1302. <el-tab-pane
  1303. v-for="(item) in (objects)"
  1304. :key="item.field_name"
  1305. :label="item.field_name"
  1306. :name="item.field_name"
  1307. >
  1308. <el-row slot="label" type="flex" align="middle">{{ item.field_name }}</el-row>
  1309. <div class="grid-container">
  1310. <el-tag
  1311. v-for="(tag) in item.child"
  1312. :key="tag.field"
  1313. size="large"
  1314. type="info"
  1315. @click="handleSubCategorySelect(tag)"
  1316. >
  1317. {{ tag.field_name }}
  1318. </el-tag>
  1319. </div>
  1320. </el-tab-pane>
  1321. </el-tabs>
  1322. </el-dialog>
  1323. <!-- 修改知识库弹窗 -->
  1324. <el-dialog title="知识库" :visible.sync="knowledgeDialogVisible" width="800px" append-to-body>
  1325. <div class="knowledge-content">
  1326. <!-- 搜索框 -->
  1327. <el-input
  1328. v-model="searchKeyword"
  1329. placeholder="请输入内容"
  1330. prefix-icon="el-icon-search"
  1331. style="margin-bottom: 15px;"
  1332. />
  1333. <!-- 知识库列表 -->
  1334. <el-table
  1335. :data="knowledgeList.filter(data => !searchKeyword || data.name.toLowerCase().includes(searchKeyword.toLowerCase()))"
  1336. style="width: 100%"
  1337. >
  1338. <el-table-column prop="id" label="序号" width="80" />
  1339. <el-table-column prop="name" label="知识库名称" />
  1340. <el-table-column label="操作" width="180">
  1341. <template slot-scope="scope">
  1342. <el-button type="text" @click="handleKnowledgeView(scope.row)">
  1343. 查看
  1344. </el-button>
  1345. <el-button type="text" @click="handleKnowledgeSelect(scope.row)">
  1346. 引用
  1347. </el-button>
  1348. </template>
  1349. </el-table-column>
  1350. </el-table>
  1351. </div>
  1352. </el-dialog>
  1353. <!-- 添加知识库详情弹窗 -->
  1354. <el-dialog title="知识库详情" :visible.sync="knowledgeDetailVisible" width="600px" append-to-body>
  1355. <div class="knowledge-detail">
  1356. <div class="detail-item">
  1357. <span class="label">名称:</span>
  1358. <el-input v-model="editKnowledge.name" placeholder="请输入名称" />
  1359. </div>
  1360. <div class="detail-item">
  1361. <span class="label">ID:</span>
  1362. <span class="id-value">{{ currentKnowledge.id }}</span>
  1363. </div>
  1364. <div class="detail-item">
  1365. <span class="label">用途:</span>
  1366. <div class="tags-input">
  1367. <el-button
  1368. v-for="(item, index) in bzmcArray"
  1369. :key="'bzmc_' + index"
  1370. type="primary"
  1371. plain
  1372. class="tag-button"
  1373. >
  1374. {{ item }}
  1375. <i class="el-icon-close" @click.stop="handleBzmcClose(index)" />
  1376. </el-button>
  1377. <el-input
  1378. v-if="inputVisible.bzmc"
  1379. ref="bzmcInput"
  1380. v-model="editKnowledge.bzmc"
  1381. class="tag-input"
  1382. @keyup.enter.native="handleInputConfirm('bzmc')"
  1383. @blur="handleInputConfirm('bzmc')"
  1384. />
  1385. <el-button v-else type="primary" plain @click="showInput('bzmc')">+ 添加</el-button>
  1386. </div>
  1387. </div>
  1388. <div class="detail-item">
  1389. <span class="label">关键词:</span>
  1390. <div class="tags-input">
  1391. <el-button
  1392. v-for="(keyword, index) in keywordsArray"
  1393. :key="'keyword_' + index"
  1394. type="primary"
  1395. plain
  1396. class="tag-button"
  1397. >
  1398. {{ keyword }}
  1399. <i class="el-icon-close" @click.stop="handleKeywordClose(index)" />
  1400. </el-button>
  1401. <el-input
  1402. v-if="inputVisible.keyword"
  1403. ref="keywordInput"
  1404. v-model="editKnowledge.keyword"
  1405. class="tag-input"
  1406. @keyup.enter.native="handleInputConfirm('keyword')"
  1407. @blur="handleInputConfirm('keyword')"
  1408. />
  1409. <el-button v-else type="primary" plain @click="showInput('keyword')">+ 添加</el-button>
  1410. </div>
  1411. </div>
  1412. </div>
  1413. <span slot="footer" class="dialog-footer">
  1414. <el-button @click="knowledgeDetailVisible = false">取 消</el-button>
  1415. <el-button type="primary" @click="saveKnowledge">保 存</el-button>
  1416. </span>
  1417. </el-dialog>
  1418. <!-- 添加新的对话框 -->
  1419. <el-dialog
  1420. title="选择子选项"
  1421. :visible.sync="childOptionsDialogVisible"
  1422. width="30%"
  1423. >
  1424. <div class="child-options-list">
  1425. <el-button
  1426. v-for="option in currentChildOptions"
  1427. :key="option.field"
  1428. size="small"
  1429. @click="handleChildOptionSelect(option)"
  1430. >
  1431. {{ option.field_name }}
  1432. </el-button>
  1433. </div>
  1434. </el-dialog>
  1435. </div>
  1436. </template>
  1437. <script>
  1438. import { add_rule } from '@/api/rule/config'
  1439. import { get_all_word_map } from '@/api/dict'
  1440. import { get_rule_detail, getSelectFormula } from '@/api/rule/config'
  1441. import { edit_word_map } from '@/api/dict'
  1442. import { get_rule_setting_other } from '@/api/rule/config'
  1443. import { get_dict_by_type } from '@/api/rule/config'
  1444. export default {
  1445. props: {
  1446. data: {
  1447. type: Object,
  1448. default() {
  1449. return {
  1450. bSwitch: false,
  1451. row: {}
  1452. }
  1453. }
  1454. },
  1455. objects: {
  1456. type: Array,
  1457. default() {
  1458. return []
  1459. }
  1460. },
  1461. departments: {
  1462. type: Array,
  1463. default() {
  1464. return []
  1465. }
  1466. }
  1467. },
  1468. data() {
  1469. return {
  1470. qcData: [],
  1471. ruleForm: {
  1472. case_type: '',
  1473. changjing: [],
  1474. department: [],
  1475. object: [],
  1476. type: '',
  1477. is_not: '',
  1478. description: '',
  1479. score: undefined,
  1480. error_level: '',
  1481. status: '',
  1482. rule_type: '普通规则',
  1483. selectFormula: [],
  1484. compareFormula: [],
  1485. rule: [
  1486. // 质控逻辑只有一条
  1487. {
  1488. is_pre_condition: 0,
  1489. condition_type: 1,
  1490. condition_relation: 2,
  1491. detail_status: 1,
  1492. condition_content: [
  1493. {
  1494. param1: '',
  1495. param2: '',
  1496. delete_field: '',
  1497. condition: '包含',
  1498. categoryType: '文本',
  1499. sx_1: '',
  1500. sx_2: '',
  1501. sx_3: '',
  1502. subtract_param: '',
  1503. subtract_condition: '',
  1504. subtract_value: '',
  1505. subtract_value_type: 'number',
  1506. hasChildOptions: false,
  1507. childOptions: [],
  1508. // 病程记录关联
  1509. pn_param1_BLBH: '',
  1510. pn_param1: [],
  1511. pn_param2: '',
  1512. pn_param3: [],
  1513. pn_param4_index: [],
  1514. pn_param4_condition1: '',
  1515. pn_param4_condition2: '',
  1516. pn_param4_kssj: [],
  1517. pn_param4_jssj: [],
  1518. pn_param4_sjjg: '',
  1519. pn_param5: '',
  1520. pn_param6: [],
  1521. pn_param6_ct: '',
  1522. pn_param6_oct: '',
  1523. // 时效
  1524. sx_param1: [],
  1525. sx_param2: '',
  1526. sx_param3: [],
  1527. sx_param4_index: [],
  1528. sx_param4_kssj: [],
  1529. sx_param4_jssj: [],
  1530. sx_param4_condition1: '',
  1531. sx_param4_condition2: '',
  1532. sx_param4_sjjg: ''
  1533. }
  1534. ],
  1535. custom_basis: [], // 质控依据
  1536. pre_warning_time: '',
  1537. custom_msg: {}
  1538. }
  1539. ],
  1540. qztj: []
  1541. },
  1542. rules: {
  1543. description: [
  1544. { required: true, message: '请输入', trigger: 'blur' }
  1545. ],
  1546. score: [
  1547. { required: true, message: '请输入', trigger: 'blur' }
  1548. ],
  1549. case_type: [
  1550. { required: true, message: '请选择', trigger: 'blur' }
  1551. ],
  1552. changjing: [
  1553. { required: true, message: '请选择', trigger: 'blur' }
  1554. ],
  1555. department: [
  1556. { required: true, message: '请选择', trigger: 'blur' }
  1557. ],
  1558. object: [
  1559. { required: true, message: '请选择', trigger: 'blur' }
  1560. ],
  1561. type: [
  1562. { required: true, message: '请选择', trigger: 'blur' }
  1563. ],
  1564. is_not: [
  1565. { required: true, message: '请选择', trigger: 'blur' }
  1566. ],
  1567. error_level: [
  1568. { required: true, message: '请选择', trigger: 'blur' }
  1569. ],
  1570. status: [
  1571. { required: true, message: '请选择', trigger: 'blur' }
  1572. ],
  1573. rule_type: [
  1574. { required: true, message: '请选择', trigger: 'blur' }
  1575. ]
  1576. },
  1577. categoryDialogVisible: false,
  1578. searchKeyword: '',
  1579. selectedCategoryValue: '',
  1580. currentRuleIndex: null,
  1581. currentConditionIndex: null,
  1582. categories: [],
  1583. categoryType: 'text', // 默认选中文本类型
  1584. activeCategory: '',
  1585. currentSubCategories: [],
  1586. selectedCategory: null,
  1587. currentSource: '',
  1588. currentInputSource: '', // 添加输入来源标识
  1589. currentFieldsName: '',
  1590. knowledgeDialogVisible: false,
  1591. knowledgeList: [],
  1592. currentInputIndex: null,
  1593. currentRuleIndexForKnowledge: null,
  1594. knowledgeDetailVisible: false,
  1595. currentKnowledge: {
  1596. id: '',
  1597. name: '',
  1598. BZMC: '', // 改为字符串类型
  1599. keywords: []
  1600. },
  1601. editKnowledge: {
  1602. name: '',
  1603. bzmc: '',
  1604. keyword: ''
  1605. },
  1606. inputVisible: {
  1607. bzmc: false,
  1608. keyword: false
  1609. },
  1610. caseTypeOptions: [], // 病历类型选项
  1611. qualityTypeOptions: [], // 质控类型选项
  1612. sceneOptions: [], // 质控场景选项
  1613. childOptionsDialogVisible: false,
  1614. currentChildOptions: []
  1615. }
  1616. },
  1617. computed: {
  1618. titleStr() {
  1619. return this.data.row.id ? this.data.actionType === 'DETAIL' ? '详情' : '编辑' : '新增'
  1620. },
  1621. filteredCategories() {
  1622. if (!this.searchKeyword) return this.categories
  1623. return this.categories.filter(item =>
  1624. item.label.toLowerCase().includes(this.searchKeyword.toLowerCase())
  1625. )
  1626. },
  1627. bzmcArray() {
  1628. return this.currentKnowledge.BZMC ? this.currentKnowledge.BZMC.split(',') : []
  1629. },
  1630. // 获取格式化后的关键词字符串
  1631. formattedKeywords() {
  1632. return Array.isArray(this.currentKnowledge.keywords)
  1633. ? this.currentKnowledge.keywords.join(',')
  1634. : this.currentKnowledge.keywords || ''
  1635. },
  1636. // 处理关键词数组
  1637. keywordsArray() {
  1638. return this.currentKnowledge.keywords
  1639. ? (typeof this.currentKnowledge.keywords === 'string'
  1640. ? this.currentKnowledge.keywords.split(',')
  1641. : this.currentKnowledge.keywords)
  1642. : []
  1643. }
  1644. },
  1645. created() {
  1646. this.getQcData()
  1647. this.getSelectFormula()
  1648. this.getCategories()
  1649. if (this.data.row.id) {
  1650. this.getDetail(this.data.row.id)
  1651. }
  1652. this.getDropdownData()
  1653. },
  1654. methods: {
  1655. onTest() {
  1656. this.$message.info('功能待开放...')
  1657. },
  1658. // 获取详情
  1659. getDetail(id) {
  1660. get_rule_detail({ id }).then(res => {
  1661. const { p } = res
  1662. const {
  1663. case_type,
  1664. changjing,
  1665. department,
  1666. object,
  1667. type,
  1668. is_not,
  1669. description,
  1670. score,
  1671. error_level,
  1672. status
  1673. } = p.rule
  1674. // 直接使用字符串数组,不需要转换为数字
  1675. this.ruleForm.department = department || []
  1676. this.ruleForm.case_type = case_type
  1677. this.ruleForm.changjing = changjing.split(',')
  1678. this.ruleForm.is_not = is_not
  1679. this.ruleForm.status = status
  1680. this.ruleForm.type = type
  1681. this.ruleForm.error_level = error_level
  1682. this.ruleForm.score = score
  1683. this.ruleForm.description = description
  1684. this.ruleForm.object = object.split(',')
  1685. // 获取规则列表并处理 param2
  1686. const ruleList = this.getQcRule(p.rule_list)
  1687. ruleList.forEach(rule => {
  1688. rule.condition_content.forEach(item => {
  1689. if (item.condition === '病程记录关联') {
  1690. // 病程记录关联
  1691. item.pn_param1_BLBH = item.param1[2]
  1692. item.pn_param1 = [item.param1[0], item.param1[1]]
  1693. item.pn_param2 = item.param2
  1694. item.pn_param3 = item.param3
  1695. item.pn_param4_index = item.param4[0].index && (item.param4[0].index).split('.') || []
  1696. item.pn_param4_condition1 = item.param4[0].condition1
  1697. item.pn_param4_condition2 = item.param4[0].condition2
  1698. item.pn_param4_kssj = item.param4[0].kssj && (item.param4[0].kssj).split('.') || []
  1699. item.pn_param4_jssj = item.param4[0].jssj && (item.param4[0].jssj).split('.') || []
  1700. item.pn_param4_sjjg = item.param4[0].sjjg
  1701. item.pn_param5 = item.param5
  1702. item.pn_param6 = item.param6[0] && (item.param6[0]).split('.') || []
  1703. item.pn_param6_ct = item.param6[1]
  1704. item.pn_param6_oct = item.param6[2]
  1705. }
  1706. if (item.condition === '时效') {
  1707. // 时效
  1708. item.sx_param1 = [item.param1[0], item.param1[1]]
  1709. item.sx_param2 = item.param2
  1710. item.sx_param3 = [item.param3[0], item.param3[1]]
  1711. item.sx_param4_index = item.param4[0].index && (item.param4[0].index).split('.') || []
  1712. item.sx_param4_condition1 = item.param4[0].condition1
  1713. item.sx_param4_condition2 = item.param4[0].condition2
  1714. item.sx_param4_kssj = item.param4[0].kssj && (item.param4[0].kssj).split('.') || []
  1715. item.sx_param4_jssj = item.param4[0].jssj && (item.param4[0].jssj).split('.') || []
  1716. item.sx_param4_sjjg = item.param4[0].sjjg
  1717. }
  1718. // 如果是字典类型且 param2 是字符串,转换为数组
  1719. if (item.hasChildOptions && typeof item.param2 === 'string' && item.param2) {
  1720. item.param2 = item.param2.split(',')
  1721. }
  1722. // 处理重复率条件的param2
  1723. if (item.condition === '重复率' && item.param2) {
  1724. // 将形如 "bllb294_295_2023.BLTD" 的字符串解析为对象数组
  1725. const parts = item.param2.split('.')
  1726. if (parts.length === 2) {
  1727. item.param2_object = [parts[0], parts[1]]
  1728. }
  1729. }
  1730. })
  1731. })
  1732. this.ruleForm.rule = ruleList
  1733. // 获取前置条件并处理 param2
  1734. const preRuleList = this.getPreRule(p.rule_list)
  1735. preRuleList.forEach(rule => {
  1736. rule.condition_content.forEach(item => {
  1737. // 如果是字典类型且 param2 是字符串,转换为数组
  1738. if (item.hasChildOptions && typeof item.param2 === 'string' && item.param2) {
  1739. item.param2 = item.param2.split(',')
  1740. }
  1741. // 处理重复率条件的param2
  1742. if (item.condition === '重复率' && item.param2) {
  1743. // 将形如 "bllb294_295_2023.BLTD" 的字符串解析为对象数组
  1744. const parts = item.param2.split('.')
  1745. if (parts.length === 2) {
  1746. item.param2_object = [parts[0], parts[1]]
  1747. }
  1748. }
  1749. })
  1750. })
  1751. this.ruleForm.qztj = preRuleList
  1752. })
  1753. },
  1754. // 找到前置条件
  1755. getPreRule(list) {
  1756. return list.filter(item => item.is_pre_condition)
  1757. },
  1758. // 找到质控逻辑
  1759. getQcRule(list) {
  1760. const rule = list.filter(item => !item.is_pre_condition)
  1761. return rule
  1762. },
  1763. getSelectFormula() {
  1764. getSelectFormula({ lx: 0 }).then(res => {
  1765. const { p } = res
  1766. console.log('select formula:', p)
  1767. this.selectFormula = p
  1768. })
  1769. },
  1770. // 搜索质控字典
  1771. getQcData() {
  1772. get_all_word_map({ status: 1 }).then(res => {
  1773. const { p } = res
  1774. this.qcData = Array.isArray(p) ? p : []
  1775. })
  1776. },
  1777. querySearch(queryString, cb) {
  1778. var qcData = this.qcData
  1779. var results = queryString ? qcData.filter(this.createFilter(queryString)) : qcData
  1780. // 调用 callback 返回建议列表的数据
  1781. cb(results)
  1782. },
  1783. createFilter(queryString) {
  1784. return (restaurant) => {
  1785. return (restaurant.name.toLowerCase().indexOf(queryString.toLowerCase()) === 0)
  1786. }
  1787. },
  1788. handleSelect(item) {
  1789. console.log(item)
  1790. },
  1791. // 添加前置条件大框
  1792. onAddQZTJ() {
  1793. this.ruleForm.qztj.push({
  1794. is_pre_condition: 1,
  1795. condition_type: 1,
  1796. condition_relation: 2,
  1797. detail_status: 1,
  1798. condition_content: [
  1799. {
  1800. param1: '',
  1801. param2: '',
  1802. param2_object: null, // 添加这个字段存储对象选择
  1803. condition: '包含',
  1804. categoryType: '文本',
  1805. sx_1: '',
  1806. sx_2: '',
  1807. sx_3: '',
  1808. subtract_param: '',
  1809. subtract_condition: '',
  1810. subtract_value: '',
  1811. subtract_value_type: 'number',
  1812. hasChildOptions: false,
  1813. childOptions: []
  1814. }
  1815. ]
  1816. })
  1817. },
  1818. // 删除前置条件大框
  1819. onDeleteQZTJ(index) {
  1820. this.ruleForm.qztj.splice(index, 1)
  1821. },
  1822. // 新增前置条件大框中_条件
  1823. onAddTJ(index, sIndex) {
  1824. this.ruleForm.qztj[index].condition_content.push({
  1825. param1: '',
  1826. param2: '',
  1827. param2_object: null, // 添加这个字段存储对象选择
  1828. condition: '包含',
  1829. categoryType: 'text',
  1830. sx_1: '',
  1831. sx_2: '',
  1832. sx_3: '',
  1833. subtract_param: '',
  1834. subtract_condition: '',
  1835. subtract_value: '',
  1836. subtract_value_type: 'number',
  1837. hasChildOptions: false,
  1838. childOptions: []
  1839. })
  1840. },
  1841. // 删除前置条件大框中_条件
  1842. onDeleteTJ(index, sIndex) {
  1843. this.ruleForm.qztj[index].condition_content.splice(sIndex, 1)
  1844. },
  1845. // 新增质控逻辑大框中_逻辑
  1846. onAddGZ(index, sIndex) {
  1847. this.ruleForm.rule[index].condition_content.push({
  1848. param1: '',
  1849. param2: '',
  1850. delete_field: '',
  1851. param2_object: null, // 添加这个字段存储对象选择
  1852. condition: '包含',
  1853. subtract_param: '',
  1854. subtract_condition: '',
  1855. subtract_value: '',
  1856. subtract_value_type: 'number',
  1857. hasChildOptions: false,
  1858. childOptions: [],
  1859. // 病程记录关联
  1860. pn_param1_BLBH: '',
  1861. pn_param1: [],
  1862. pn_param2: '',
  1863. pn_param3: [],
  1864. pn_param4_index: [],
  1865. pn_param4_condition1: '',
  1866. pn_param4_condition2: '',
  1867. pn_param4_kssj: [],
  1868. pn_param4_jssj: [],
  1869. pn_param4_sjjg: '',
  1870. pn_param5: '',
  1871. pn_param6: [],
  1872. pn_param6_ct: '',
  1873. pn_param6_oct: '',
  1874. // 时效
  1875. sx_param1: [],
  1876. sx_param2: '',
  1877. sx_param3: [],
  1878. sx_param4_index: [],
  1879. sx_param4_kssj: [],
  1880. sx_param4_jssj: [],
  1881. sx_param4_condition1: '',
  1882. sx_param4_condition2: '',
  1883. sx_param4_sjjg: ''
  1884. })
  1885. },
  1886. // 删除质控逻辑大框中_逻辑
  1887. onDeleteGZ(index, sIndex) {
  1888. this.ruleForm.rule[index].condition_content.splice(sIndex, 1)
  1889. },
  1890. // 添加质控依据
  1891. onAddZKYJ() {
  1892. this.ruleForm.rule[0].custom_basis = this.ruleForm.rule[0].custom_basis ? this.ruleForm.rule[0].custom_basis : []
  1893. this.ruleForm.rule[0].custom_basis.push({
  1894. param1: '',
  1895. input1: '',
  1896. input2: ''
  1897. })
  1898. },
  1899. // 删除质控依据大框
  1900. onDeleteZKYJ(index) {
  1901. this.ruleForm.rule[0].custom_basis = []
  1902. },
  1903. // 新增质控依据大框中_条件
  1904. onAddTJZKYJ(index, sIndex) {
  1905. this.ruleForm.rule[index].custom_basis.push({
  1906. param1: '',
  1907. input1: '',
  1908. input2: ''
  1909. })
  1910. },
  1911. // 删除质控依据大框中_条件
  1912. onDeleteTJZKYJ(index, sIndex) {
  1913. this.ruleForm.rule[index].custom_basis.splice(sIndex, 1)
  1914. },
  1915. // 添加质控预警
  1916. onAddZKyujing() {
  1917. this.ruleForm.rule[0].custom_msg = {
  1918. aftertime: '',
  1919. param1: '',
  1920. input1: '',
  1921. input2: ''
  1922. }
  1923. },
  1924. // 删除质控预警大框
  1925. onDeleteZKyujing(index) {
  1926. this.ruleForm.rule[0].custom_msg = {}
  1927. },
  1928. hasEmptyValues(obj) {
  1929. return Object.entries(obj).some(([key, value]) => {
  1930. // 如果是数组(多选的情况),检查数组长度
  1931. if (Array.isArray(value)) {
  1932. return value.length === 0
  1933. }
  1934. // 其他情况保持原有的空值判断
  1935. return !value
  1936. })
  1937. },
  1938. // 验证前置条件
  1939. judgeQZTJ() {
  1940. const { qztj } = this.ruleForm
  1941. let result = true
  1942. const e_index = []
  1943. console.log('>>>>>>>>>>', qztj)
  1944. if (qztj.length) {
  1945. for (let i = 0; i < qztj.length; i++) {
  1946. qztj[i].condition_content.forEach(item => {
  1947. // 检查必填项
  1948. // const isEmpty = !item.param1 ||
  1949. // (Array.isArray(item.param2) ? item.param2.length === 0 : !item.param2) ||
  1950. // !item.condition
  1951. // 检查必填项
  1952. const isEmpty = !item.param1 || !item.condition
  1953. if (isEmpty) {
  1954. e_index.push(i + 1)
  1955. }
  1956. })
  1957. }
  1958. if (e_index.length) {
  1959. this.$message.error(`请完善前置条件${e_index.join()}`)
  1960. result = false
  1961. }
  1962. }
  1963. return result
  1964. },
  1965. // 验证质控逻辑
  1966. judgeRule() {
  1967. const { rule } = this.ruleForm
  1968. let result = true
  1969. // 质控逻辑只有一条
  1970. rule[0].condition_content.map(item => {
  1971. console.log(item)
  1972. if (this.hasEmptyValues(item)) {
  1973. this.$message.error(`请完善质控逻辑`)
  1974. result = false
  1975. }
  1976. })
  1977. return result
  1978. },
  1979. submitForm(formName) {
  1980. this.$refs[formName].validate(async(valid) => {
  1981. if (valid) {
  1982. if (this.judgeQZTJ()) {
  1983. const processConditionContent = (content) => {
  1984. const contentArr = []
  1985. content.forEach(item => {
  1986. const element = { ...item }
  1987. if (element.condition === '病程记录关联') {
  1988. const elementParams = {
  1989. param1: [
  1990. Array.isArray(element.pn_param1) && !!(element.pn_param1.length) ? element.pn_param1[0] : '',
  1991. Array.isArray(element.pn_param1) && !!(element.pn_param1.length) ? element.pn_param1[1] : '',
  1992. element.pn_param1_BLBH
  1993. ],
  1994. param2: element.pn_param2,
  1995. condition: element.condition,
  1996. param3: [
  1997. Array.isArray(element.pn_param3) && !!(element.pn_param3.length) ? element.pn_param3[0] : '',
  1998. Array.isArray(element.pn_param3) && !!(element.pn_param3.length) ? element.pn_param3[1] : ''
  1999. ],
  2000. param4: [
  2001. {
  2002. kssj: element.pn_param4_kssj.join('.'),
  2003. jssj: element.pn_param4_jssj.join('.'),
  2004. sjjg: element.pn_param4_sjjg,
  2005. index: element.pn_param4_index.join('.'),
  2006. condition1: element.pn_param4_condition1,
  2007. condition2: element.pn_param4_condition2
  2008. }
  2009. ],
  2010. param5: element.pn_param5,
  2011. param6: [
  2012. element.pn_param6.join('.'),
  2013. element.pn_param6_ct,
  2014. element.pn_param6_oct
  2015. ]
  2016. }
  2017. contentArr.push(elementParams)
  2018. } else if (element.condition === '时效') {
  2019. const elementParams = {
  2020. param1: [
  2021. Array.isArray(element.sx_param1) && !!(element.sx_param1.length) ? element.sx_param1[0] : '',
  2022. Array.isArray(element.sx_param1) && !!(element.sx_param1.length) ? element.sx_param1[1] : ''
  2023. ],
  2024. param2: element.sx_param2,
  2025. condition: element.condition,
  2026. param3: [
  2027. Array.isArray(element.sx_param3) && !!(element.sx_param3.length) ? element.sx_param3[0] : '',
  2028. Array.isArray(element.sx_param3) && !!(element.sx_param3.length) ? element.sx_param3[1] : ''
  2029. ],
  2030. param4: [
  2031. {
  2032. kssj: element.sx_param4_kssj.join('.'),
  2033. jssj: element.sx_param4_jssj.join('.'),
  2034. sjjg: element.sx_param4_sjjg,
  2035. index: element.sx_param4_index.join('.'),
  2036. condition1: element.sx_param4_condition1,
  2037. condition2: element.sx_param4_condition2
  2038. }
  2039. ]
  2040. }
  2041. contentArr.push(elementParams)
  2042. } else {
  2043. // 处理多选值
  2044. if (Array.isArray(element.param2)) {
  2045. element.param2 = element.param2.join(',')
  2046. }
  2047. if (element.condition === '减' && element.subtract_param) {
  2048. // 组合减法条件的完整表达式
  2049. const subtractValue = this.getDisplayName(element.subtract_param)
  2050. if (subtractValue) {
  2051. // 获取父级字段名
  2052. const [parentField] = element.subtract_param
  2053. // 构造 param2 格式: parentField.field
  2054. element.param2 = `${parentField}.${element.subtract_param[1]}`
  2055. }
  2056. }
  2057. // 对重复率条件的特殊处理
  2058. if (element.condition === '重复率') {
  2059. // 确保param2格式正确
  2060. if (element.param2_object && Array.isArray(element.param2_object)) {
  2061. const [field1, field2] = element.param2_object
  2062. element.param2 = `${field1}.${field2}`
  2063. }
  2064. // 确保subtract_value是数字格式
  2065. if (element.subtract_value !== undefined) {
  2066. element.subtract_value = Number(element.subtract_value)
  2067. }
  2068. }
  2069. contentArr.push(element)
  2070. }
  2071. })
  2072. return contentArr
  2073. }
  2074. // 处理前置条件和质控逻辑中的减法条件
  2075. this.ruleForm.qztj.forEach(item => {
  2076. processConditionContent(item.condition_content)
  2077. })
  2078. console.log('=============this.ruleForm', this.ruleForm.rule)
  2079. const rules = []
  2080. this.ruleForm.rule.forEach(item => {
  2081. rules.push({
  2082. ...item,
  2083. condition_content: processConditionContent(item.condition_content)
  2084. })
  2085. })
  2086. // 继续原有的提交逻辑
  2087. const params = {
  2088. case_type: this.ruleForm.case_type,
  2089. changjing: this.ruleForm.changjing,
  2090. department: this.ruleForm.department,
  2091. object: this.ruleForm.object,
  2092. type: this.ruleForm.type,
  2093. is_not: this.ruleForm.is_not,
  2094. description: this.ruleForm.description,
  2095. score: this.ruleForm.score,
  2096. error_level: this.ruleForm.error_level,
  2097. status: this.ruleForm.status,
  2098. rule_type: this.ruleForm.rule_type,
  2099. rule: [...rules, ...this.ruleForm.qztj]
  2100. }
  2101. console.log('>>>>>>>>>>>>>>>>>>>>', params)
  2102. if (this.data.row.id) {
  2103. params.id = this.data.row.id
  2104. }
  2105. add_rule(params).then(res => {
  2106. this.data.bSwitch = false
  2107. this.$emit('refresh')
  2108. this.$message.success(res.m || '操作成功')
  2109. })
  2110. }
  2111. } else {
  2112. return false
  2113. }
  2114. })
  2115. },
  2116. openCategoryDialog(index, sIndex, source) {
  2117. this.currentRuleIndex = index
  2118. this.currentConditionIndex = sIndex
  2119. this.currentSource = source
  2120. // 判断来源类型
  2121. if (source === 'qztj') {
  2122. this.currentInputSource = 'qztj'
  2123. } else if (source === 'rule') {
  2124. this.currentInputSource = 'rule'
  2125. } else if (source === 'sx_1' || source === 'sx_2') {
  2126. // 需要判断是在前置条件还是质控逻辑中调用的
  2127. const parentElement = document.activeElement.closest('.box-card')
  2128. if (parentElement && parentElement.querySelector('.box-card_header span')?.textContent.includes('前置条件')) {
  2129. this.currentInputSource = 'qztj'
  2130. } else {
  2131. this.currentInputSource = 'rule'
  2132. }
  2133. this.currentSource = source // 保持原有的 source 值
  2134. }
  2135. // 设置默认显示
  2136. if (this.objects.length > 0) {
  2137. this.activeCategory = this.objects[0].field_name
  2138. this.currentSubCategories = this.objects[0].child || []
  2139. }
  2140. this.categoryDialogVisible = true
  2141. this.selectedCategory = null
  2142. },
  2143. handleSearch(value) {
  2144. // 搜索功能已通过 computed 属性实现
  2145. },
  2146. confirmCategory() {
  2147. if (this.selectedCategory) {
  2148. // 更新对应条件的类目
  2149. this.ruleForm.rule[this.currentRuleIndex].condition_content[this.currentConditionIndex].category = this.selectedCategory
  2150. // 可能还需要更新显示的文本
  2151. const selectedItem = this.categories.find(item => item.value === this.selectedCategory)
  2152. this.ruleForm.rule[this.currentRuleIndex].condition_content[this.currentConditionIndex].param2 =
  2153. selectedItem ? selectedItem.label : ''
  2154. }
  2155. this.categoryDialogVisible = false
  2156. },
  2157. // 点击左侧类目
  2158. handleCategoryClick(item) {
  2159. console.log('>>>>>>>>>>>>>>>>>>>>>', item)
  2160. this.activeCategory = item.name
  2161. this.currentSubCategories = item.child || []
  2162. },
  2163. // 选择右侧子类目
  2164. handleSubCategorySelect(subItem) {
  2165. if (this.currentRuleIndex !== null && this.currentConditionIndex !== null) {
  2166. const parentObj = this.objects.find(obj => obj.field_name === this.activeCategory)
  2167. const parentField = parentObj ? parentObj.field : ''
  2168. if (this.currentSource === 'qztj') {
  2169. const condition = this.ruleForm.qztj[this.currentRuleIndex].condition_content[this.currentConditionIndex]
  2170. if (condition) {
  2171. condition.param1 = [parentField, subItem.field]
  2172. condition.field_name = subItem.field_name
  2173. condition.categoryTypeDisabled = false
  2174. // 检查子数据类型
  2175. if (subItem.type === 2 && subItem.child && subItem.child.length > 0) {
  2176. const dictData = subItem.child.find(item => item.type === 4)
  2177. if (dictData) {
  2178. condition.hasChildOptions = true
  2179. condition.categoryType = '选择'
  2180. condition.categoryTypeDisabled = true // 重置禁用标志
  2181. // type=4 的情况,获取字典数据
  2182. get_dict_by_type({
  2183. table: dictData.field,
  2184. field: dictData.field_name
  2185. }).then(res => {
  2186. if (res?.p) {
  2187. // 转换数据格式
  2188. condition.childOptions = res.p.map(item => ({
  2189. field: item.dep_name,
  2190. field_name: item.dep_name
  2191. }))
  2192. }
  2193. })
  2194. } else if (subItem.child.some(item => item.type === 3)) {
  2195. // type=3 的情况,直接使用 child 数据
  2196. condition.hasChildOptions = true
  2197. condition.childOptions = subItem.child
  2198. condition.categoryType = '选择' // 设置为选择类型
  2199. condition.categoryTypeDisabled = true // 添加禁用标志
  2200. } else {
  2201. // 没有子数据时重置标志
  2202. condition.categoryTypeDisabled = false
  2203. condition.hasChildOptions = false
  2204. }
  2205. }
  2206. }
  2207. } else if (this.currentSource === 'rule') {
  2208. const condition = this.ruleForm.rule[this.currentRuleIndex].condition_content[this.currentConditionIndex]
  2209. if (condition) {
  2210. condition.param1 = [parentField, subItem.field]
  2211. condition.field_name = subItem.field_name
  2212. condition.categoryTypeDisabled = false
  2213. if (subItem.type === 2 && subItem.child && subItem.child.length > 0) {
  2214. const dictData = subItem.child.find(item => item.type === 4)
  2215. if (dictData) {
  2216. condition.hasChildOptions = true
  2217. condition.categoryType = '选择'
  2218. condition.categoryTypeDisabled = true // 重置禁用标志
  2219. get_dict_by_type({
  2220. table: dictData.field,
  2221. field: dictData.field_name
  2222. }).then(res => {
  2223. if (res?.p) {
  2224. condition.childOptions = res.p.map(item => ({
  2225. field: item.dep_name,
  2226. field_name: item.dep_name
  2227. }))
  2228. }
  2229. })
  2230. } else if (subItem.child.some(item => item.type === 3)) {
  2231. // type=3 的情况,直接使用 child 数据
  2232. condition.hasChildOptions = true
  2233. condition.childOptions = subItem.child
  2234. condition.categoryType = '选择' // 设置为选择类型
  2235. condition.categoryTypeDisabled = true // 添加禁用标志
  2236. } else {
  2237. // 没有子数据时重置标志
  2238. condition.categoryTypeDisabled = false
  2239. condition.hasChildOptions = false
  2240. }
  2241. }
  2242. }
  2243. } else if (this.currentSource === 'sx_1') {
  2244. if (this.currentInputSource === 'qztj') {
  2245. // 前置条件的时效
  2246. const condition = this.ruleForm.qztj[this.currentRuleIndex].condition_content[this.currentConditionIndex]
  2247. if (condition) {
  2248. condition.sx_1 = [parentField, subItem.field]
  2249. condition.field_name = subItem.field_name
  2250. }
  2251. } else {
  2252. // 质控逻辑的时效
  2253. const condition = this.ruleForm.rule[this.currentRuleIndex].condition_content[this.currentConditionIndex]
  2254. if (condition) {
  2255. condition.sx_1 = [parentField, subItem.field]
  2256. condition.field_name = subItem.field_name
  2257. }
  2258. }
  2259. } else if (this.currentSource === 'sx_2') {
  2260. if (this.currentInputSource === 'qztj') {
  2261. // 前置条件的时效
  2262. const condition = this.ruleForm.qztj[this.currentRuleIndex].condition_content[this.currentConditionIndex]
  2263. if (condition) {
  2264. condition.sx_2 = [parentField, subItem.field]
  2265. condition.field_name = subItem.field_name
  2266. this.$set(condition, 'sx_3', '') // 确保 sx_3 是响应式的
  2267. }
  2268. } else {
  2269. // 质控逻辑的时效
  2270. const condition = this.ruleForm.rule[this.currentRuleIndex].condition_content[this.currentConditionIndex]
  2271. if (condition) {
  2272. condition.sx_2 = [parentField, subItem.field]
  2273. condition.field_name = subItem.field_name
  2274. this.$set(condition, 'sx_3', '') // 确保 sx_3 是响应式的
  2275. }
  2276. }
  2277. } else if (this.currentSource === 'rule') {
  2278. // 质控逻辑
  2279. const condition = this.ruleForm.rule[this.currentRuleIndex].condition_content[this.currentConditionIndex]
  2280. if (condition) {
  2281. condition.param1 = [parentField, subItem.field]
  2282. condition.field_name = subItem.field_name
  2283. // 检查是否有 type=4 的子数据
  2284. if (subItem.type === 2 && subItem.child && subItem.child.length > 0) {
  2285. const dictData = subItem.child.find(item => item.type === 4)
  2286. if (dictData) {
  2287. condition.hasChildOptions = true
  2288. // type=4 的情况,获取字典数据
  2289. get_dict_by_type({
  2290. table: dictData.field,
  2291. field: dictData.field_name
  2292. }).then(res => {
  2293. if (res?.p) {
  2294. // 转换数据格式
  2295. condition.childOptions = res.p.map(item => ({
  2296. field: item.dep_name,
  2297. field_name: item.dep_name
  2298. }))
  2299. }
  2300. })
  2301. } else if (subItem.child.some(item => item.type === 3)) {
  2302. // type=3 的情况,直接使用 child 数据
  2303. condition.hasChildOptions = true
  2304. condition.childOptions = subItem.child
  2305. }
  2306. }
  2307. }
  2308. } else if (this.currentSource === 'custom_basis') {
  2309. // 质控依据
  2310. const basis = this.ruleForm.rule[this.currentRuleIndex].custom_basis[this.currentConditionIndex]
  2311. if (basis) {
  2312. basis.param1 = [parentField, subItem.field]
  2313. basis.field_name = subItem.field_name
  2314. }
  2315. } else if (this.currentSource === 'custom_msg') {
  2316. // 预警
  2317. const msg = this.ruleForm.rule[this.currentRuleIndex].custom_msg
  2318. if (msg) {
  2319. msg.param1 = [parentField, subItem.field]
  2320. msg.field_name = subItem.field_name
  2321. }
  2322. } else if (this.currentSource === 'subtract') {
  2323. // 处理减法时的第二个类目选择
  2324. if (this.currentInputSource === 'qztj') {
  2325. const condition = this.ruleForm.qztj[this.currentRuleIndex].condition_content[this.currentConditionIndex]
  2326. if (condition) {
  2327. condition.subtract_param = [parentField, subItem.field]
  2328. }
  2329. } else if (this.currentInputSource === 'rule') {
  2330. const condition = this.ruleForm.rule[this.currentRuleIndex].condition_content[this.currentConditionIndex]
  2331. if (condition) {
  2332. condition.subtract_param = [parentField, subItem.field]
  2333. }
  2334. }
  2335. } else if (this.currentSource === 'param2_object') {
  2336. // 判断是在前置条件还是质控逻辑中
  2337. if (this.currentInputSource === 'qztj') {
  2338. const condition = this.ruleForm.qztj[this.currentRuleIndex].condition_content[this.currentConditionIndex]
  2339. if (condition) {
  2340. // 存储完整的对象选择,而不只是字段名
  2341. condition.param2_object = [parentField, subItem.field]
  2342. // 同时更新param2为字符串表示形式,用于提交
  2343. condition.param2 = `${parentField}.${subItem.field}`
  2344. }
  2345. } else {
  2346. const condition = this.ruleForm.rule[this.currentRuleIndex].condition_content[this.currentConditionIndex]
  2347. if (condition) {
  2348. condition.param2_object = [parentField, subItem.field]
  2349. condition.param2 = `${parentField}.${subItem.field}`
  2350. }
  2351. }
  2352. } else if (this.currentSource === 'pn_param1' || this.currentSource === 'pn_param3' || this.currentSource === 'pn_param6' || this.currentSource === 'pn_param4_index' || this.currentSource === 'pn_param4_kssj' || this.currentSource === 'pn_param4_jssj') {
  2353. // 判断是在前置条件还是质控逻辑中
  2354. if (this.currentInputSource === 'qztj') {
  2355. const condition = this.ruleForm.qztj[this.currentRuleIndex].condition_content[this.currentConditionIndex]
  2356. if (condition) {
  2357. // 存储完整的对象选择,而不只是字段名
  2358. condition.param2_object = [parentField, subItem.field]
  2359. // 同时更新param2为字符串表示形式,用于提交
  2360. condition.param2 = `${parentField}.${subItem.field}`
  2361. }
  2362. } else {
  2363. const condition = this.ruleForm.rule[this.currentRuleIndex].condition_content[this.currentConditionIndex]
  2364. if (condition) {
  2365. condition[this.currentSource] = [parentField, subItem.field]
  2366. }
  2367. }
  2368. } else if (this.currentSource === 'sx_param1' || this.currentSource === 'sx_param3' || this.currentSource === 'sx_param4_index' || this.currentSource === 'sx_param4_kssj' || this.currentSource === 'sx_param4_jssj') {
  2369. // 判断是在前置条件还是质控逻辑中
  2370. if (this.currentInputSource === 'qztj') {
  2371. const condition = this.ruleForm.qztj[this.currentRuleIndex].condition_content[this.currentConditionIndex]
  2372. if (condition) {
  2373. // 存储完整的对象选择,而不只是字段名
  2374. condition.param2_object = [parentField, subItem.field]
  2375. // 同时更新param2为字符串表示形式,用于提交
  2376. condition.param2 = `${parentField}.${subItem.field}`
  2377. }
  2378. } else {
  2379. const condition = this.ruleForm.rule[this.currentRuleIndex].condition_content[this.currentConditionIndex]
  2380. if (condition) {
  2381. condition[this.currentSource] = [parentField, subItem.field]
  2382. }
  2383. }
  2384. }
  2385. }
  2386. this.categoryDialogVisible = false
  2387. },
  2388. getDisplayName(param1) {
  2389. if (!Array.isArray(param1)) return ''
  2390. const [parentField, childField] = param1
  2391. const parentObj = this.objects.find(obj => obj.field === parentField)
  2392. if (!parentObj) return ''
  2393. const childObj = parentObj.child.find(child => child.field === childField)
  2394. return childObj ? childObj.field_name : ''
  2395. },
  2396. handleInput(value, ruleIndex, index, source = 'custom_basis', fieldsName) {
  2397. if (value && value.endsWith('@')) {
  2398. this.currentInputIndex = index
  2399. this.currentRuleIndexForKnowledge = ruleIndex
  2400. this.currentInputSource = source
  2401. this.knowledgeDialogVisible = true
  2402. this.currentFieldsName = fieldsName
  2403. this.getKnowledgeList()
  2404. }
  2405. },
  2406. handleKnowledgeSelect(item) {
  2407. if (this.currentInputIndex !== null && this.currentRuleIndexForKnowledge !== null) {
  2408. if (this.currentInputSource === 'rule') {
  2409. // 质控逻辑
  2410. const condition = this.ruleForm.rule[this.currentRuleIndexForKnowledge].condition_content[this.currentInputIndex]
  2411. if (condition) {
  2412. // 直接替换整个值,不保留@
  2413. condition.param2 = condition.param2.replace(/@.*$/, item.name)
  2414. }
  2415. } else if (this.currentInputSource === 'qztj') {
  2416. const condition = this.ruleForm.qztj[this.currentRuleIndexForKnowledge].condition_content[this.currentInputIndex]
  2417. if (condition) {
  2418. condition.param2 = condition.param2.replace(/@.*$/, item.name)
  2419. }
  2420. } else if (this.currentInputSource === 'rule_other') {
  2421. const condition = this.ruleForm.rule[this.currentRuleIndexForKnowledge].condition_content[this.currentInputIndex]
  2422. if (condition) {
  2423. // condition[this.currentFieldsName] = condition[this.currentFieldsName].replace(/@.*$/, item.name)
  2424. condition[this.currentFieldsName] = `@${item.name}`
  2425. }
  2426. } else {
  2427. const basis = this.ruleForm.rule[this.currentRuleIndexForKnowledge].custom_basis[this.currentInputIndex]
  2428. if (basis) {
  2429. // 直接替换整个值,不保留@
  2430. basis.input2 = basis.input2.replace(/@.*$/, item.name)
  2431. }
  2432. }
  2433. }
  2434. this.knowledgeDialogVisible = false
  2435. },
  2436. // 获取知识库列表
  2437. async getKnowledgeList() {
  2438. try {
  2439. const res = await get_all_word_map({ status: 1 })
  2440. if (res && res.p) {
  2441. this.knowledgeList = Array.isArray(res.p) ? res.p : []
  2442. }
  2443. } catch (error) {
  2444. console.error('获取知识库列表失败:', error)
  2445. this.$message.error('获取知识库列表失败')
  2446. }
  2447. },
  2448. // 添加质控逻辑
  2449. onAddZKLJ() {
  2450. // 检查是否已存在质控逻辑
  2451. if (this.ruleForm.rule && this.ruleForm.rule.length > 0) {
  2452. this.$message.warning('质控逻辑已存在')
  2453. return
  2454. }
  2455. this.ruleForm.rule = [{
  2456. is_pre_condition: 0,
  2457. condition_type: 1,
  2458. condition_relation: 2,
  2459. detail_status: 1,
  2460. condition_content: [
  2461. {
  2462. param1: '',
  2463. param2: '',
  2464. param2_object: null, // 添加这个字段存储对象选择
  2465. condition: '包含',
  2466. categoryType: 'text',
  2467. sx_1: '',
  2468. sx_2: '',
  2469. sx_3: '',
  2470. subtract_param: '',
  2471. subtract_condition: '',
  2472. subtract_value: '',
  2473. subtract_value_type: 'number',
  2474. hasChildOptions: false,
  2475. childOptions: []
  2476. }
  2477. ],
  2478. custom_basis: [],
  2479. pre_warning_time: '',
  2480. custom_msg: {}
  2481. }]
  2482. },
  2483. // 查看知识库详情
  2484. handleKnowledgeView(row) {
  2485. this.currentKnowledge = {
  2486. ...row,
  2487. keywords: row.keywords || '',
  2488. BZMC: row.BZMC || ''
  2489. }
  2490. this.editKnowledge.name = row.name
  2491. this.knowledgeDetailVisible = true
  2492. },
  2493. // 获取比较公式数据
  2494. getCompareFormula() {
  2495. getSelectFormula({ lx: 1 }).then(res => {
  2496. const { p } = res
  2497. console.log('compare formula:', p)
  2498. this.compareFormula = p
  2499. })
  2500. },
  2501. // 获取类型数据
  2502. getCategories() {
  2503. getSelectFormula({ lx: 1 }).then(res => {
  2504. const { p } = res
  2505. console.log('categories:', p)
  2506. // 转换数据格式
  2507. this.categories = p.map(item => ({
  2508. label: item.formula,
  2509. value: item.formula // 或者使用 id,取决于后端需要的格式
  2510. }))
  2511. })
  2512. },
  2513. // 获取完整的请求参数
  2514. getFullParams(extraParams = {}) {
  2515. return {
  2516. id: this.currentKnowledge.id,
  2517. name: this.currentKnowledge.name,
  2518. BZMC: this.currentKnowledge.BZMC || '',
  2519. keywords: this.formattedKeywords,
  2520. ...extraParams
  2521. }
  2522. },
  2523. // 显示输入框
  2524. showInput(type) {
  2525. this.inputVisible[type] = true
  2526. this.$nextTick(() => {
  2527. this.$refs[`${type}Input`].focus()
  2528. })
  2529. },
  2530. // 处理输入确认
  2531. handleInputConfirm(type) {
  2532. if (type === 'bzmc') {
  2533. if (this.editKnowledge.bzmc) {
  2534. this.addBzmc()
  2535. }
  2536. } else if (type === 'keyword') {
  2537. if (this.editKnowledge.keyword) {
  2538. this.addKeyword()
  2539. }
  2540. }
  2541. this.inputVisible[type] = false
  2542. },
  2543. // 添加用途
  2544. addBzmc() {
  2545. if (!this.editKnowledge.bzmc) return
  2546. const newBzmc = this.currentKnowledge.BZMC
  2547. ? `${this.currentKnowledge.BZMC},${this.editKnowledge.bzmc}`
  2548. : this.editKnowledge.bzmc
  2549. const params = this.getFullParams({ BZMC: newBzmc })
  2550. edit_word_map(params).then(res => {
  2551. this.$message.success('添加成功')
  2552. this.editKnowledge.bzmc = ''
  2553. this.getKnowledgeDetail(this.currentKnowledge.id)
  2554. })
  2555. },
  2556. // 添加关键词
  2557. addKeyword() {
  2558. if (!this.editKnowledge.keyword) return
  2559. const newKeywords = this.formattedKeywords
  2560. ? `${this.formattedKeywords},${this.editKnowledge.keyword}`
  2561. : this.editKnowledge.keyword
  2562. const params = this.getFullParams({ keywords: newKeywords })
  2563. edit_word_map(params).then(res => {
  2564. this.$message.success('添加成功')
  2565. this.editKnowledge.keyword = ''
  2566. this.getKnowledgeDetail(this.currentKnowledge.id)
  2567. })
  2568. },
  2569. // 处理用途的删除
  2570. handleBzmcClose(index) {
  2571. const bzmc = this.bzmcArray
  2572. bzmc.splice(index, 1)
  2573. const params = this.getFullParams({ BZMC: bzmc.join(',') })
  2574. edit_word_map(params).then(res => {
  2575. this.$message.success('删除成功')
  2576. this.getKnowledgeDetail(this.currentKnowledge.id)
  2577. })
  2578. },
  2579. // 处理关键词的删除
  2580. handleKeywordClose(index) {
  2581. const keywords = this.formattedKeywords.split(',')
  2582. keywords.splice(index, 1)
  2583. const params = this.getFullParams({ keywords: keywords.join(',') })
  2584. edit_word_map(params).then(res => {
  2585. this.$message.success('删除成功')
  2586. this.getKnowledgeDetail(this.currentKnowledge.id)
  2587. })
  2588. },
  2589. // 保存名称
  2590. saveKnowledge() {
  2591. const params = this.getFullParams({ name: this.editKnowledge.name })
  2592. edit_word_map(params).then(res => {
  2593. this.$message.success('保存成功')
  2594. this.knowledgeDetailVisible = false
  2595. // 刷新知识库列表
  2596. this.getKnowledgeList()
  2597. })
  2598. },
  2599. // 获取知识库详情
  2600. getKnowledgeDetail(id) {
  2601. get_all_word_map({ id }).then(res => {
  2602. const { p } = res
  2603. if (Array.isArray(p) && p.length > 0) {
  2604. // 找到对应 id 的数据
  2605. const detail = p.find(item => item.id === id)
  2606. if (detail) {
  2607. this.currentKnowledge = {
  2608. ...detail,
  2609. // 确保 keywords 和 BZMC 有值
  2610. keywords: detail.keywords || '',
  2611. BZMC: detail.BZMC || ''
  2612. }
  2613. // 同步更新编辑框的名称
  2614. this.editKnowledge.name = detail.name
  2615. }
  2616. }
  2617. })
  2618. },
  2619. // 获取下拉数据
  2620. async getDropdownData() {
  2621. try {
  2622. // 获取病历类型
  2623. const caseTypeRes = await get_rule_setting_other({ type: 1 })
  2624. if (caseTypeRes?.p) {
  2625. this.caseTypeOptions = caseTypeRes.p.map(item => ({
  2626. value: item.name, // 使用 name 作为 value
  2627. label: item.name // 使用 name 作为 label
  2628. }))
  2629. }
  2630. // 获取质控类型
  2631. const qualityTypeRes = await get_rule_setting_other({ type: 2 })
  2632. if (qualityTypeRes?.p) {
  2633. this.qualityTypeOptions = qualityTypeRes.p.map(item => ({
  2634. value: item.name,
  2635. label: item.name
  2636. }))
  2637. }
  2638. // 获取质控场景
  2639. const sceneRes = await get_rule_setting_other({ type: 3 })
  2640. if (sceneRes?.p) {
  2641. this.sceneOptions = sceneRes.p.map(item => ({
  2642. value: item.name,
  2643. label: item.name
  2644. }))
  2645. }
  2646. } catch (error) {
  2647. console.error('获取下拉数据失败:', error)
  2648. this.$message.error('获取下拉数据失败')
  2649. }
  2650. },
  2651. openChildOptionsDialog(index, sIndex) {
  2652. const currentItem = this.ruleForm[this.currentInputSource][index].condition_content[sIndex]
  2653. if (currentItem.param1 && Array.isArray(currentItem.param1)) {
  2654. const [parentField, field] = currentItem.param1
  2655. const category = this.objects.find(item => item.field === parentField)
  2656. const subCategory = category?.child?.find(item => item.field === field)
  2657. if (subCategory?.child && subCategory.child.length > 0) {
  2658. this.currentChildOptions = subCategory.child
  2659. this.currentRuleIndex = index
  2660. this.currentConditionIndex = sIndex
  2661. // this.currentInputSource = source
  2662. this.childOptionsDialogVisible = true
  2663. }
  2664. }
  2665. },
  2666. handleChildOptionSelect(option) {
  2667. const condition = this.ruleForm[this.currentInputSource][this.currentRuleIndex].condition_content[this.currentConditionIndex]
  2668. condition.param2 = option.field_name
  2669. this.childOptionsDialogVisible = false
  2670. }
  2671. }
  2672. }
  2673. </script>
  2674. <style lang="scss" scoped>
  2675. ::v-deep .el-col-15 {
  2676. .el-form-item__label {
  2677. width: 160px !important;
  2678. }
  2679. }
  2680. .box-card {
  2681. margin-bottom: 16px;
  2682. }
  2683. ::v-deep .el-card__header {
  2684. padding: 0;
  2685. .box-card_header {
  2686. background: #F7F7F8;
  2687. padding: 0 20px;
  2688. line-height: 40px;
  2689. }
  2690. }
  2691. ::v-deep .el-card__body {
  2692. padding: 20px 12px;
  2693. }
  2694. .text-right {
  2695. text-align: right;
  2696. }
  2697. .ml40 {
  2698. margin-left: 40px;
  2699. }
  2700. .mb12 {
  2701. margin-bottom: 12px;
  2702. }
  2703. .span {
  2704. padding-top: 40px;
  2705. .text {
  2706. color: #909399;
  2707. }
  2708. }
  2709. .input-with-category {
  2710. display: flex;
  2711. align-items: stretch;
  2712. gap: 0;
  2713. ::v-deep .el-input__inner {
  2714. border-top-right-radius: 0;
  2715. border-bottom-right-radius: 0;
  2716. }
  2717. .category-select {
  2718. ::v-deep .el-input__inner {
  2719. border-top-left-radius: 0;
  2720. border-bottom-left-radius: 0;
  2721. margin-left: -1px;
  2722. padding-left: 25px;
  2723. /* 为图标留出空间 */
  2724. }
  2725. ::v-deep .el-input__prefix {
  2726. left: 5px;
  2727. color: #909399;
  2728. }
  2729. }
  2730. }
  2731. .category-content {
  2732. height: 400px;
  2733. .category-menu {
  2734. height: 100%;
  2735. border-right: 1px solid #e6e6e6;
  2736. }
  2737. .sub-category-list {
  2738. padding: 10px;
  2739. display: flex;
  2740. flex-wrap: wrap;
  2741. gap: 10px;
  2742. .el-button {
  2743. margin: 5px;
  2744. }
  2745. }
  2746. }
  2747. .rule-condition {
  2748. position: relative;
  2749. display: flex;
  2750. align-items: center;
  2751. cursor: pointer; // 添加手型光标
  2752. .el-input {
  2753. cursor: pointer;
  2754. ::v-deep .el-input__inner {
  2755. cursor: pointer;
  2756. }
  2757. }
  2758. }
  2759. .knowledge-content {
  2760. max-height: 500px;
  2761. overflow-y: auto;
  2762. }
  2763. .knowledge-detail {
  2764. padding: 20px;
  2765. .detail-item {
  2766. margin-bottom: 20px;
  2767. display: flex;
  2768. align-items: center;
  2769. .label {
  2770. width: 70px;
  2771. line-height: 32px;
  2772. }
  2773. .id-value {
  2774. line-height: 32px;
  2775. padding: 0 15px;
  2776. }
  2777. .el-input {
  2778. flex: 1;
  2779. }
  2780. }
  2781. .tags-input {
  2782. flex: 1;
  2783. display: flex;
  2784. flex-wrap: wrap;
  2785. align-items: center;
  2786. gap: 8px;
  2787. .tag-button {
  2788. margin: 0 8px 8px 0;
  2789. padding: 5px 10px;
  2790. height: 28px;
  2791. line-height: 1;
  2792. font-weight: normal;
  2793. position: relative;
  2794. .el-icon-close {
  2795. margin-left: 5px;
  2796. &:hover {
  2797. color: #409eff;
  2798. }
  2799. }
  2800. }
  2801. .tag-input {
  2802. width: 120px;
  2803. margin-right: 8px;
  2804. }
  2805. .el-button {
  2806. margin: 0 8px 8px 0;
  2807. padding: 5px 10px;
  2808. height: 28px;
  2809. line-height: 1;
  2810. font-weight: normal;
  2811. &.is-plain {
  2812. background: #ecf5ff;
  2813. border-color: #d9ecff;
  2814. color: #409eff;
  2815. &:hover {
  2816. background: #ecf5ff;
  2817. border-color: #409eff;
  2818. color: #409eff;
  2819. }
  2820. }
  2821. }
  2822. }
  2823. }
  2824. .button-group {
  2825. display: flex;
  2826. gap: 5px;
  2827. .el-button {
  2828. padding: 7px 8px;
  2829. }
  2830. }
  2831. .knowledge-detail .detail-item {
  2832. margin-bottom: 20px;
  2833. }
  2834. .knowledge-detail .label {
  2835. display: inline-block;
  2836. width: 80px;
  2837. vertical-align: top;
  2838. }
  2839. .input-with-tags {
  2840. display: flex;
  2841. flex-direction: column;
  2842. width: calc(100% - 80px);
  2843. margin-left: 80px;
  2844. margin-top: -20px;
  2845. }
  2846. .tags-container {
  2847. margin-bottom: 10px;
  2848. }
  2849. .tags-container .el-tag {
  2850. margin-right: 10px;
  2851. margin-bottom: 10px;
  2852. }
  2853. .input-container {
  2854. width: 100%;
  2855. }
  2856. .rule-condition {
  2857. .category-select {
  2858. position: absolute;
  2859. right: 0;
  2860. top: 0;
  2861. }
  2862. }
  2863. .child-options-list {
  2864. display: flex;
  2865. flex-wrap: wrap;
  2866. gap: 10px;
  2867. padding: 10px;
  2868. }
  2869. .progress-note {
  2870. .el-row {
  2871. display: flex;
  2872. flex-wrap: wrap;
  2873. justify-content: flex-start;
  2874. }
  2875. .el-col {
  2876. margin-bottom: 10px;
  2877. }
  2878. }
  2879. .grid-container {
  2880. display: grid;
  2881. grid-template-columns: repeat(3, 1fr);
  2882. gap: 10px;
  2883. .el-tag {
  2884. text-align: center;
  2885. }
  2886. }
  2887. ::v-deep .el-tabs--left .el-tabs__nav-wrap.is-left.is-scrollable {
  2888. padding: 0;
  2889. .el-tabs__nav-prev {
  2890. display: none;
  2891. height: 0px;
  2892. }
  2893. .el-tabs__nav-next {
  2894. display: none;
  2895. height: 0;
  2896. }
  2897. }
  2898. </style>