AddQualityControlTemp.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. <template>
  2. <div @click="closeSearch">
  3. <crumbs :title="title" :param="$route.params" linkTo="QualityControlTemp">
  4. </crumbs>
  5. <div class="contentWrapper">
  6. <div class="content">
  7. <el-form :model="form" :rules="rules" ref="form" class="selectHospital">
  8. <el-form-item label="所属医院:" prop="hospital" class="formItem">
  9. <el-select v-model="form.hospital" placeholder="请选择医院" :disabled="isEdit||isCopy" class="selectHospital" @change="changeHsopital">
  10. <el-option v-for="item in hospitalList" :key="item.id" :label="item.name" :value="item.val"></el-option>
  11. </el-select>
  12. </el-form-item>
  13. <el-form-item label="所属模块:" prop="moduleName" class="formItem">
  14. <el-select v-model="form.moduleName" placeholder="请选择所属模块" :disabled="isEdit||isCopy" class="selectModule" @change="changeModule">
  15. <el-option v-for="item in moduleList" :key="item.id" :label="item.name" :value="item.val"></el-option>
  16. </el-select>
  17. </el-form-item>
  18. <el-form-item label="模板名称:" prop="tempName" class="formItem widthLarge">
  19. <el-input v-model.trim="form.tempName" placeholder="请输入模板名称"></el-input>
  20. </el-form-item>
  21. <el-form-item label="模块类型:" prop="moduleTypes" class="formItem widthLarge">
  22. </el-form-item>
  23. <QCTypePour :hospital="form.hospital"
  24. :moduleName="form.moduleName"
  25. @changeActionData="moduleTypeChange" :selectedTag="form.recordAnalyzeList"></QCTypePour>
  26. <el-form-item label="模块内容:" prop="moduleInfo" class="formItem addCon">
  27. <div class="moduleInfoItem" v-for="(item,index) in moduleInfoList">
  28. <div class="orderBox">
  29. <span class="el-icon-arrow-up order" @click="upUnit(index)"></span>
  30. <span class="el-icon-arrow-down order" @click="downUnit(index)"></span>
  31. </div>
  32. <div class="searchBox">
  33. <el-input v-model.trim="item.searchName" placeholder="搜索字段单元" @click="stopClick" @input="searchFiled(index)">
  34. </el-input>
  35. <ul v-if="searchIndex == index && item.searchResult.length > 0" class="searchResultBox">
  36. <li class="searchItem"
  37. v-for="searchItem in item.searchResult"
  38. :title="searchItem.tagName"
  39. @click="selectSearchFiled(searchItem,index)"
  40. >
  41. {{searchItem.tagName}}
  42. </li>
  43. </ul>
  44. </div>
  45. <div>
  46. <p>已选择字段:</p>
  47. <div class="selectFiledBox">
  48. <div class="orderBox">
  49. <span class="el-icon-arrow-up order" @click="upFiled(index)"></span>
  50. <span class="el-icon-arrow-down order" @click="downFiled(index)"></span>
  51. </div>
  52. <div class="selectFiled" v-for="(it,ii) in item.selectFiled">
  53. <span class="filedName" :class="{activeFiledName: item.activeIndex == ii}" @click="setActiveIndex(index,ii)">{{it.tagName}}
  54. <span class="el-icon-circle-close delFiled" @click="delSelected(ii,index)"></span>
  55. </span>
  56. </div>
  57. </div>
  58. </div>
  59. <span class="el-icon-circle-close delUnit" @click="delUnit(index)"></span>
  60. </div>
  61. <span class="addUnit" >
  62. <el-button size="small" type="primary" @click="addUnit">+单元组</el-button>
  63. </span>
  64. </el-form-item>
  65. </el-form>
  66. <el-button class="disclButn" size="small" type="primary" :disabled = 'saveDisable' @click="confirm('form')">确定</el-button>
  67. </div>
  68. </div>
  69. </div>
  70. </template>
  71. <script>
  72. import api from '@api/qualityControl.js';
  73. import QCTypePour from './QCTypePour.vue';
  74. export default {
  75. name:"AddQualityControlTemp",
  76. data: function(){
  77. return {
  78. title: "模板维护-添加",
  79. isEdit:false,
  80. isCopy: false,
  81. saveDisable: false,
  82. form:{
  83. tempName: "",
  84. hospital:"",
  85. moduleName:"",
  86. moduleTypes:[],
  87. recordAnalyzeList:[],
  88. nameType:""
  89. },
  90. rules:{
  91. tempName:{ required: true, message: '请输入模块名称', trigger: ['blur', 'change']},
  92. hospital:{ required: true, message: '请选择医院', trigger: ['blur', 'change']},
  93. moduleName:{ required: true, message: '请选择所属模块', trigger: ['blur', 'change']},
  94. moduleTypes:{ required: true, message: '请选择模块类型 ', trigger: ['blur', 'change']},
  95. /*name:[{ required: true, message: '请输入显示名称',trigger: ['blur', 'change'] }],*/
  96. },
  97. searchIndex: -1,
  98. hospitalList:[],
  99. moduleList:[ ],
  100. moduleInfoList:[]
  101. }
  102. },
  103. created(){
  104. this.getAllTypes();
  105. const {isCopy, isEdit, data } = this.$route.params;
  106. if(isEdit || isCopy) {
  107. this.form.hospital = ''+data.hospitalId
  108. this.form.moduleName = ''+data.modeId
  109. if(isEdit){
  110. this.isEdit = isEdit;
  111. this.id = data.id
  112. this.title ="模板维护-修改"
  113. this.form.tempName = data.name;
  114. this.form.recordAnalyzeList = data.recordAnalyzeList;
  115. }
  116. if(isCopy){
  117. this.isEdit = isEdit;
  118. this.isCopy = isCopy
  119. this.id = ""
  120. this.title ="模板维护-复制"
  121. this.form.tempName = ""
  122. this.form.moduleTypes=[];
  123. //this.form.example=""
  124. }
  125. const moduleDetail = data.moduleDetail
  126. const keysList = Object.keys(moduleDetail)
  127. for(let i = 0; i < keysList.length; i++){
  128. let selectFiled = []
  129. for(let j = 0; j < moduleDetail[keysList[i]].length; j++){
  130. const item = moduleDetail[keysList[i]][j]
  131. selectFiled.push(item.questionDTO)
  132. }
  133. this.moduleInfoList.push({
  134. searchName:"",
  135. activeIndex: -1,
  136. searchResult:[
  137. ],
  138. selectFiled:selectFiled
  139. })
  140. }
  141. }
  142. },
  143. methods:{
  144. moduleTypeChange(list){
  145. this.form.moduleTypes=[...list];
  146. },
  147. closeSearch(){
  148. if(this.searchIndex > -1){
  149. this.moduleInfoList[this.searchIndex].searchName = ""
  150. this.moduleInfoList[this.searchIndex].searchResult=[]
  151. this.searchIndex = -1
  152. }
  153. },
  154. getAllTypes(){
  155. if(localStorage.getItem("qcModuleTypes")){
  156. this.hospitalList = JSON.parse(localStorage.getItem("qcHospitalTypes"));
  157. this.moduleList = JSON.parse(localStorage.getItem("qcModuleTypes"));
  158. return new Promise(function(resolve, reject){
  159. resolve()
  160. });
  161. }
  162. //获取枚举信息
  163. return api.getQcTypes().then((res)=>{
  164. if(res.data.code==="0"){
  165. const data = res.data.data;
  166. localStorage.setItem("qcFieldTypes",JSON.stringify(data[11]));
  167. localStorage.setItem("qcModuleTypes",JSON.stringify(data[12]));
  168. localStorage.setItem("qcHospitalTypes",JSON.stringify(data[13]));
  169. this.hospitalList = JSON.parse(localStorage.getItem("qcHospitalTypes"));
  170. this.moduleList = JSON.parse(localStorage.getItem("qcModuleTypes"));
  171. }else{
  172. this.warning("获取枚举信息失败");
  173. }
  174. });
  175. },
  176. stopClick(e){
  177. console.log('11111')
  178. // e.stopPropagation()
  179. },
  180. changeHsopital(){
  181. this.form.moduleTypes = []
  182. },
  183. changeModule(){
  184. this.form.moduleTypes = []
  185. },
  186. addUnit(){
  187. const {hospital,moduleName,tempName,moduleTypes}=this.form;
  188. if(!hospital){
  189. this.warning("请先选择所属医院")
  190. return
  191. }
  192. if(!moduleName){
  193. this.warning("请选择所属模块");
  194. return
  195. }
  196. if(!tempName.trim()){
  197. this.warning("请输入模块名称");
  198. return
  199. }
  200. if(!moduleTypes.length){
  201. this.warning("请先选择模块类型");
  202. return
  203. }
  204. this.moduleInfoList.push({
  205. searchName:"",
  206. activeIndex: -1,
  207. searchResult:[
  208. ],
  209. selectFiled:[
  210. ]
  211. })
  212. },
  213. searchFiled(index){
  214. this.searchIndex = index
  215. const searchName = this.moduleInfoList[index].searchName
  216. if(!searchName){
  217. return
  218. }
  219. const param = {
  220. tagName: searchName,
  221. hospitalId: this.form.hospital,
  222. modeId: [this.form.moduleName],
  223. }
  224. api.getQCName(param).then(res =>{
  225. if(res.data.code == '0'){
  226. this.moduleInfoList[index].searchResult = []
  227. this.moduleInfoList[index].searchResult.push(...res.data.data)
  228. }
  229. }).catch(e =>{
  230. console.log(e)
  231. })
  232. },
  233. selectSearchFiled(searchItem,index){
  234. this.moduleInfoList[index].selectFiled.push(searchItem)
  235. this.searchIndex = -1
  236. this.moduleInfoList[index].searchName=""
  237. this.moduleInfoList[index].searchResult = []
  238. },
  239. setActiveIndex(index, ii){
  240. let activeIndex = this.moduleInfoList[index].activeIndex
  241. if( ii === activeIndex) {
  242. this.moduleInfoList[index].activeIndex = -1
  243. } else {
  244. this.moduleInfoList[index].activeIndex = ii
  245. }
  246. },
  247. upUnit(index){
  248. if(index == 0){
  249. return
  250. }
  251. const current = this.moduleInfoList[index]
  252. const currentPre = this.moduleInfoList[index-1]
  253. this.moduleInfoList.splice(index-1,2,current,currentPre)
  254. },
  255. downUnit(index){
  256. if(index == this.moduleInfoList.length -1){
  257. return
  258. }
  259. const current = this.moduleInfoList[index]
  260. const currentNext = this.moduleInfoList[index+1]
  261. this.moduleInfoList.splice(index,2,currentNext,current)
  262. },
  263. upFiled(index){
  264. let activeIndex = this.moduleInfoList[index].activeIndex
  265. if(activeIndex == 0 || activeIndex == -1){
  266. return
  267. }
  268. const current = this.moduleInfoList[index].selectFiled[activeIndex]
  269. const currentPre = this.moduleInfoList[index].selectFiled[activeIndex-1]
  270. this.moduleInfoList[index].selectFiled.splice(activeIndex-1,2,current,currentPre)
  271. this.moduleInfoList[index].activeIndex--
  272. },
  273. downFiled(index){
  274. let activeIndex = this.moduleInfoList[index].activeIndex
  275. if(activeIndex == this.moduleInfoList[index].selectFiled.length -1 || activeIndex == -1){
  276. return
  277. }
  278. const current = this.moduleInfoList[index].selectFiled[activeIndex]
  279. const currentNext = this.moduleInfoList[index].selectFiled[activeIndex+1]
  280. this.moduleInfoList[index].selectFiled.splice(activeIndex,2,currentNext,current)
  281. this.moduleInfoList[index].activeIndex++
  282. },
  283. delSelected(ii,index){
  284. this.moduleInfoList[index].selectFiled.splice(ii,1)
  285. },
  286. delUnit(index){
  287. this.moduleInfoList.splice(index,1)
  288. },
  289. confirm(form){
  290. // this.$refs[form].validate((valid) => {
  291. // if (valid) {
  292. const {tempName,hospital,moduleName,moduleTypes} = this.form;
  293. let moduleDetail = [], moduleInfoList = this.moduleInfoList;
  294. for(let i = 0; i < moduleInfoList.length; i++){
  295. for(let j = 0; j < moduleInfoList[i].selectFiled.length; j++){
  296. let item ={
  297. groupId: i,
  298. questionId: moduleInfoList[i].selectFiled[j].id
  299. }
  300. moduleDetail.push(item)
  301. }
  302. }
  303. if(!hospital){
  304. this.warning("请选择所属医院");
  305. return
  306. }
  307. if(!moduleName){
  308. this.warning("请选择所属模块");
  309. return
  310. }
  311. if(!tempName){
  312. this.warning("请输入模块名称");
  313. return
  314. }
  315. if(!moduleTypes.length){
  316. this.warning("请选择模块类型");
  317. return
  318. }
  319. if(moduleDetail.length === 0){
  320. this.warning('请添加模块内容')
  321. return
  322. }
  323. let param = {
  324. name: tempName,
  325. modeId: moduleName,
  326. hospitalId: hospital,
  327. moduleDetail: moduleDetail,
  328. remark:'',
  329. recordIdList:moduleTypes
  330. };
  331. if(this.isEdit){
  332. param = Object.assign({}, param, {id: this.id})
  333. }
  334. if(this.id && !this.isCopy){//修改
  335. this.saveDisable = true //提交保存按钮不可点击,返回结果时才可点击,防止频繁发送请求
  336. api.saveOrUpdateQCTemp(param).then((res)=>{
  337. if(res.data.code==0){
  338. this.$message({
  339. message:"修改成功",
  340. type:'success'
  341. });
  342. //返回带搜索条件的首页
  343. this.$router.push({
  344. name: 'QualityControlTemp',
  345. params: Object.assign({}, this.$route.params, {currentPage: 1})
  346. });
  347. }else{
  348. this.$message({
  349. message:res.data.msg,
  350. type:'warning'
  351. });
  352. }
  353. this.saveDisable = false
  354. })
  355. }else{//添加
  356. this.saveDisable = true; //提交保存按钮不可点击,返回结果时才可点击,防止频繁发送请求
  357. api.saveOrUpdateQCTemp(param).then((res)=>{
  358. if(res.data.code==0){
  359. this.$message({
  360. message:"添加成功",
  361. type:'success'
  362. })
  363. this.$router.push({name: 'QualityControlTemp'});
  364. }else{
  365. this.$message({
  366. message:res.data.msg,
  367. type:'warning'
  368. });
  369. }
  370. this.saveDisable = false
  371. })
  372. }
  373. // } else {
  374. // return false;
  375. // }
  376. // });
  377. },
  378. warning(msg, type,time) {
  379. this.$message({
  380. showClose: true,
  381. message: msg,
  382. type: type || 'warning',
  383. duration:time || '3000'
  384. })
  385. },
  386. },
  387. components:{
  388. QCTypePour
  389. }
  390. }
  391. </script>
  392. <style lang="less" scoped>
  393. .contentWrapper{
  394. padding: 50px 20px 0;
  395. }
  396. .content{
  397. background: #fff;
  398. }
  399. .formItem{
  400. /deep/.el-form-item__label{
  401. width: 150px;
  402. }
  403. }
  404. /deep/.el-form-item__content{
  405. display: inline-block;
  406. }
  407. /deep/.el-input__inner {
  408. height: 30px;
  409. line-height: 30px;
  410. // width: 200px;
  411. }
  412. /deep/.widthLarge .el-input__inner {
  413. width: 350px;
  414. }
  415. /deep/.addCon .el-form-item__label:before {
  416. content: '*';
  417. color: #f56c6c;
  418. margin-right: 4px;
  419. }
  420. .formExam{
  421. /deep/.el-form-item__content{
  422. width: calc(100% - 185px);
  423. }
  424. }
  425. .exampleTxt{
  426. display: inline-block;
  427. position: relative;
  428. width: 100%;
  429. max-height: 200px;
  430. padding: 0 20px 0 0;
  431. height: 100%;
  432. word-break: break-all;
  433. overflow-y: auto;
  434. }
  435. .moduleInfoItem{
  436. width: 500px;
  437. min-height: 200px;
  438. padding: 0 50px 0 50px;
  439. border: 1px solid #dcdfe6;
  440. border-radius: 5px;
  441. margin-bottom: 20px;
  442. position: relative;
  443. }
  444. .addUnit{
  445. display: inline-block;
  446. border: 1px solid #dcdfe6;
  447. border-radius: 5px;
  448. width: 80px;
  449. text-align: center;
  450. height: 20px;
  451. line-height: 20px;
  452. cursor: pointer;
  453. }
  454. .searchBox{
  455. width: 500px;
  456. position: relative;
  457. }
  458. .searchResultBox{
  459. position: absolute;
  460. width: 500px;
  461. box-sizing: border-box;
  462. max-height: 200px;
  463. overflow-y: auto;
  464. background: #fff;
  465. z-index: 2;
  466. border: 1px solid #48c5d7;
  467. }
  468. .searchItem{
  469. height: 40px;
  470. line-height: 40px;
  471. padding: 0 20px;
  472. cursor: pointer;
  473. overflow: hidden;
  474. white-space: nowrap;
  475. text-overflow: ellipsis;
  476. }
  477. .searchItem:hover{
  478. background-color: #F5F7FA;
  479. }
  480. .selectFiled{
  481. position: relative;
  482. }
  483. .orderBox{
  484. position: absolute;
  485. left: -50px;
  486. top: 50%;
  487. width: 50px;
  488. height: 84px;
  489. margin-top: -42px;
  490. }
  491. .selectFiledBox{
  492. position: relative;
  493. min-height: 120px;
  494. }
  495. .order{
  496. display: inline-block;
  497. width: 30px;
  498. height: 30px;
  499. font-size: 30px;
  500. margin-left: 5px;
  501. border: 1px solid #dcdfe6;
  502. cursor: pointer;
  503. }
  504. .firstItem{
  505. margin-left: 28px;
  506. }
  507. .delUnit,.delFiled{
  508. position: absolute;
  509. top: -8px;
  510. right: -6px;
  511. cursor: pointer;
  512. }
  513. .delFiled{
  514. top: -7px;
  515. right: -9px;
  516. }
  517. .filedName{
  518. position: relative;
  519. border: 1px solid #dcdfe6;
  520. border-radius: 4px;
  521. padding: 5px 10px;
  522. display: inline-block;
  523. line-height: 20px;
  524. }
  525. .activeFiledName{
  526. border: 1px solid #48C5D7;
  527. }
  528. </style>