AddPlan.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. <template>
  2. <el-scrollbar style="height: 100%" ref="elscrollbar">
  3. <div class="AddPlanWrapper clearfix" @click="close">
  4. <crumbs
  5. :title="isEdit ? '电子病历方案配置-修改方案' : '电子病历方案配置-添加方案'"
  6. class="topBack"
  7. :param="$route.params"
  8. linkTo="Plan"
  9. ></crumbs>
  10. <div class="AddPlanBox">
  11. <el-row :gutter="20">
  12. <el-col :span="16">
  13. <el-form ref="form" :model="form" label-width="80px" :rules="rules">
  14. <!-- <el-form-item label="医院名称" prop="hoipitalName">
  15. <el-input v-model="form.planName" placeholder="2-30位,可输入汉字、字母、数字和下划线"></el-input>
  16. </el-form-item>-->
  17. <el-form-item label="医院名称" class="selectMedicine" prop="hospitalId">
  18. <el-select
  19. v-model="form.hospitalId"
  20. placeholder="请选择"
  21. clearable
  22. style="width: 100%"
  23. >
  24. <el-option
  25. v-for="item in HospitalInfoList"
  26. :label="item.name"
  27. :value="item.id"
  28. :key="item.id"
  29. ></el-option>
  30. </el-select>
  31. </el-form-item>
  32. <el-form-item label="方案名称" prop="planName">
  33. <el-input v-model="form.planName" placeholder="2-30位,可输入汉字、字母、数字和下划线"></el-input>
  34. </el-form-item>
  35. <el-form-item label="方案编码" prop="planCode">
  36. <el-input v-model="form.planCode" placeholder="可输入字母、数字和下划线"></el-input>
  37. </el-form-item>
  38. <el-form-item label="方案配置">
  39. <ul>
  40. <li>
  41. <div class="title">
  42. <div class="handleIcon" @click="openPlanItems">
  43. <img
  44. src="../../../images/multi.png"
  45. alt="辅助信息"
  46. :class="{'open' : isOpenCloseItems}"
  47. />
  48. </div>
  49. <h4>辅助信息</h4>
  50. <div class="titlwSwitch">
  51. <el-switch
  52. v-model="switchSubStatus"
  53. :active-value="1"
  54. :inactive-value="0"
  55. active-color="#4BC4D7"
  56. inactive-color="#BBBBBB"
  57. ></el-switch>
  58. <span class="titlwSwitchStatus">{{switchSubStatus === 1 ? '启用中' : '未启用'}}</span>
  59. </div>
  60. </div>
  61. <transition name="plus-icon">
  62. <div v-if="isOpenCloseItems">
  63. <ul class="sub" v-for="(item,index) in planDefaultList" :key="item.id">
  64. <li class="planItem">
  65. <div class="sort">
  66. <div class="top">
  67. <img
  68. :src="isTopLight !== index ? require('../../../images/icon_default_top.png') : require('../../../images/icon_hover_top.png')"
  69. alt="上升"
  70. v-if="index !== 0"
  71. @click="sortPlan(item,index,'top')"
  72. @mouseover="handleMouseEnter1(index)"
  73. @mouseleave="handleMouseLeave1(index)"
  74. />
  75. </div>
  76. <div class="down">
  77. <img
  78. :src="isDownLight !== index ? require('../../../images/icon_default_down.png') : require('../../../images/icon_hover_down.png')"
  79. alt="下降"
  80. v-if="index !== planDefaultList.length - 1"
  81. @click="sortPlan(item,index,'down')"
  82. @mouseover="handleMouseEnter(index)"
  83. @mouseleave="handleMouseLeave(index)"
  84. />
  85. </div>
  86. </div>
  87. <div class="openOrClose">
  88. <span class="planInfo">{{item.name}}</span>
  89. <div class="switch">
  90. <el-switch
  91. v-model="item.status"
  92. :active-value="1"
  93. :inactive-value="0"
  94. active-color="#4BC4D7"
  95. inactive-color="#BBBBBB"
  96. ></el-switch>
  97. </div>
  98. <span class="planStatus">{{item.status === 1 ? '启用中' : '未启用'}}</span>
  99. </div>
  100. <div class="showNum" v-if="item.number">
  101. <span style="marginRight:8px;">默认显示个数</span>
  102. <el-select
  103. v-model="item.number"
  104. placeholder="请选择"
  105. size="small"
  106. :disabled="item.status !== 1 ? true: false"
  107. >
  108. <el-option label="1" value="1"></el-option>
  109. <el-option label="2" value="2"></el-option>
  110. <el-option label="3" value="3"></el-option>
  111. <el-option label="4" value="4"></el-option>
  112. <el-option label="5" value="5"></el-option>
  113. <el-option label="6" value="6"></el-option>
  114. </el-select>
  115. </div>
  116. </li>
  117. </ul>
  118. </div>
  119. </transition>
  120. </li>
  121. <li>
  122. <div class="title">
  123. <div class="handleIcon">
  124. <img src="../../../images/multi.png" alt="医学知识" />
  125. </div>
  126. <h4>医学知识</h4>
  127. <div class="titlwSwitch">
  128. <el-switch
  129. v-model="switchMedStatus"
  130. :active-value="1"
  131. :inactive-value="0"
  132. active-color="#4BC4D7"
  133. inactive-color="#BBBBBB"
  134. ></el-switch>
  135. <span class="titlwSwitchStatus">{{switchMedStatus === 1 ? '启用中' : '未启用'}}</span>
  136. </div>
  137. </div>
  138. </li>
  139. <li>
  140. <div class="title">
  141. <div class="handleIcon">
  142. <img src="../../../images/multi.png" alt="医学知识" />
  143. </div>
  144. <h4>随访计划</h4>
  145. <div class="titlwSwitch">
  146. <el-switch
  147. v-model="switchFollowStatus"
  148. :active-value="1"
  149. :inactive-value="0"
  150. active-color="#4BC4D7"
  151. inactive-color="#BBBBBB"
  152. ></el-switch>
  153. <span class="titlwSwitchStatus">{{switchFollowStatus === 1 ? '启用中' : '未启用'}}</span>
  154. </div>
  155. </div>
  156. </li>
  157. </ul>
  158. </el-form-item>
  159. <el-form-item>
  160. <el-button type="primary" @click="onSubmit" :disabled="saveDisable">确定</el-button>
  161. </el-form-item>
  162. </el-form>
  163. </el-col>
  164. </el-row>
  165. </div>
  166. </div>
  167. </el-scrollbar>
  168. </template>
  169. <script>
  170. import api from '@api/cdss.js';
  171. export default {
  172. name: 'AddPlan',
  173. data() {
  174. var numreg = /^[a-zA-Z0-9_\u4e00-\u9fa5]+$/;
  175. var numreg1 = /^[0-9a-zA-Z_]{1,}$/;
  176. var validatePass = (rule, value, callback) => {
  177. if (!numreg.test(value)) {
  178. callback(new Error('汉字、字母、数字和下划线'));
  179. } else {
  180. callback();
  181. }
  182. };
  183. var validatePass1 = (rule, value, callback) => {
  184. if (!numreg1.test(value)) {
  185. callback(new Error('字母、数字和下划线'));
  186. } else {
  187. callback();
  188. }
  189. };
  190. return {
  191. form: {
  192. hospitalId: '',
  193. planName: '',
  194. planCode: ''
  195. },
  196. saveDisable: false, //保存按钮禁止点击
  197. rules: {
  198. planName: [
  199. { required: true, message: '方案名称不能为空', trigger: 'change' },
  200. { min: 2, max: 30, message: '长度2-30位', trigger: 'blur' },
  201. { required: true, validator: validatePass, trigger: 'blur' }
  202. ],
  203. hospitalId: [
  204. { required: true, message: '医院名称不能为空', trigger: 'change' }
  205. // { min: 2, max: 30, message: '长度2-30位', trigger: 'blur' },
  206. // { required: true, validator: validatePass, trigger: 'blur' }
  207. ],
  208. planCode: [
  209. { required: true, message: '方案编码不能为空', trigger: 'change' },
  210. { required: true, validator: validatePass1, trigger: 'blur' }
  211. ]
  212. },
  213. planDefaultList: [],
  214. // hospitalId: '',
  215. isEdit: false, // 是否处于编辑页面 false--新增 true--编辑
  216. switchSubStatus: 0, // 辅助信息
  217. switchMedStatus: 0, // 医学知识
  218. switchFollowStatus: 0, //随访计划
  219. isOpenCloseItems: true, // 是否展开方案配置项
  220. isDownLight: -1,
  221. isTopLight: -1,
  222. flag: 1,
  223. editCount: -1, // 页面会否被编辑 >0被编辑 =0 未编辑
  224. isSaveSuccess: false, // 是否保存成功
  225. HospitalInfoList: []
  226. };
  227. },
  228. beforeRouteLeave(to, from, next) {
  229. console.log(this.editCount,'this.editCount');
  230. if (
  231. (this.editCount > 3 && !this.isSaveSuccess && this.isEdit) ||
  232. (this.editCount > 1 && !this.isSaveSuccess && !this.isEdit)
  233. ) {
  234. // console.log('页面被编辑了');
  235. this.$alert('还有未保存的内容,确定要退出当前页面吗?', '提示', {
  236. confirmButtonText: '确定',
  237. // cancelButtonText: '取消',
  238. // cancelButtonClass: 'leaveBtn',
  239. // customClass: 'leaveBox',
  240. type: 'warning'
  241. })
  242. .then(() => {
  243. next();
  244. })
  245. .catch(() => {});
  246. } else {
  247. next();
  248. }
  249. },
  250. watch: {
  251. form: {
  252. handler(newName, oldName) {
  253. this.editCount++;
  254. },
  255. deep: true
  256. // immediate: true
  257. },
  258. planDefaultList: {
  259. handler(newName, oldName) {
  260. // console.log(newName,'newName');
  261. // console.log(oldName,'oldName');
  262. this.editCount++;
  263. },
  264. deep: true,
  265. immediate: true
  266. }
  267. },
  268. async created() {
  269. const { isEdit, data } = this.$route.params;
  270. console.log(data, '编辑页传递的data');
  271. this._getHospitalInfo(); // 获取医院下拉列表
  272. // let res = await api.getHospitalInfo(); // 同步获取医院信息
  273. // this.hospitalId = res.data.data.id;
  274. if (isEdit) {
  275. // 编辑页面
  276. this.isEdit = true;
  277. this.form.hospitalId = data.hospitalId
  278. let params = {
  279. hospitalId: data.hospitalId,
  280. id: data.id
  281. };
  282. this._getPlanInfoIds(params);
  283. } else {
  284. // 新增页面
  285. this._getDefaultPlans(); // 获取默认配置信息
  286. }
  287. },
  288. methods: {
  289. close() {},
  290. // 获取医院下拉列表
  291. _getHospitalInfo() {
  292. api.getHospitalInfo().then(res => {
  293. if (res.data.code === '0') {
  294. this.HospitalInfoList = res.data.data;
  295. }
  296. });
  297. },
  298. // 方案配置排序
  299. sortPlan(item, index, type) {
  300. // console.log('排序', item, index, type);
  301. let tempList = [...this.planDefaultList];
  302. if (type === 'down') {
  303. // 降序
  304. let plan = tempList.find(item => {
  305. return item.orderNo === index + 1;
  306. });
  307. let tempPlan = { ...plan };
  308. let planNext = tempList.find(item => {
  309. return item.orderNo === index + 2;
  310. });
  311. let tempPlanNext = { ...planNext };
  312. plan = tempPlanNext;
  313. plan.orderNo -= 1;
  314. planNext = tempPlan;
  315. planNext.orderNo += 1;
  316. let arr = tempList.map((i, idx) => {
  317. if (idx === index) {
  318. return { ...plan };
  319. } else if (idx === index + 1) {
  320. return { ...planNext };
  321. } else {
  322. return i;
  323. }
  324. });
  325. this.planDefaultList = [...arr];
  326. } else {
  327. // 升序
  328. let plan = tempList.find(item => {
  329. return item.orderNo === index + 1;
  330. });
  331. let tempPlan = { ...plan };
  332. let planPre = tempList.find(item => {
  333. return item.orderNo === index;
  334. });
  335. let tempPlanPre = { ...planPre };
  336. plan = tempPlanPre;
  337. plan.orderNo += 1;
  338. planPre = tempPlan;
  339. planPre.orderNo -= 1;
  340. let arr = tempList.map((i, idx) => {
  341. if (idx === index) {
  342. return { ...plan };
  343. } else if (idx === index - 1) {
  344. return { ...planPre };
  345. } else {
  346. return i;
  347. }
  348. });
  349. this.planDefaultList = [...arr];
  350. }
  351. },
  352. // 展开列表项
  353. openPlanItems() {
  354. this.isOpenCloseItems = !this.isOpenCloseItems;
  355. },
  356. // 鼠标移入
  357. handleMouseEnter(index) {
  358. this.isDownLight = index;
  359. },
  360. // 鼠标移除
  361. handleMouseLeave(index) {
  362. this.isDownLight = -1;
  363. },
  364. // 鼠标移入
  365. handleMouseEnter1(index) {
  366. this.isTopLight = index;
  367. },
  368. // 鼠标移除
  369. handleMouseLeave1(index) {
  370. this.isTopLight = -1;
  371. },
  372. // 获取默认方案配置
  373. _getDefaultPlans() {
  374. api.getDefaultPlans().then(res => {
  375. console.log(res, '获取默认的方案配置');
  376. if (res.data.code === '0') {
  377. this.planDefaultList =
  378. res.data.data &&
  379. res.data.data.planDetailDefault.length !== 0 &&
  380. res.data.data.planDetailDefault[0].planDetails;
  381. this.switchSubStatus =
  382. res.data.data &&
  383. res.data.data.planDetailDefault.length !== 0 &&
  384. res.data.data.planDetailDefault[0].status;
  385. this.switchMedStatus =
  386. res.data.data &&
  387. res.data.data.planDetailDefault.length !== 0 &&
  388. res.data.data.planDetailDefault[1].status;
  389. this.switchFollowStatus =
  390. res.data.data &&
  391. res.data.data.planDetailDefault.length !== 0 &&
  392. res.data.data.planDetailDefault[2].status;
  393. }
  394. });
  395. },
  396. // 编辑页面 根据id获取方案配置
  397. async _getPlanInfoIds(params) {
  398. // 先获取默认的所有方案
  399. let tempArr = [];
  400. let newPlan = [];
  401. let res = await api.getDefaultPlans();
  402. if (res.data.code === '0') {
  403. tempArr =
  404. res.data.data &&
  405. res.data.data.planDetailDefault.length !== 0 &&
  406. res.data.data.planDetailDefault[0].planDetails;
  407. }
  408. let res1 = await api.getPlanInfoIds(params);
  409. console.log(res1, '==================');
  410. if (res1.data.code === '0') {
  411. newPlan = res1.data.data[0].sysSetInfo[0].planDetails;
  412. this.form.planName = res1.data.data[0].planName;
  413. this.form.planCode = res1.data.data[0].planCode;
  414. this.switchSubStatus = res1.data.data[0].sysSetInfo[0].status;
  415. this.switchMedStatus = res1.data.data[0].sysSetInfo[1].status;
  416. this.switchFollowStatus = res1.data.data[0].sysSetInfo[2].status;
  417. // this.planDefaultList = res1.data.data[0].sysSetInfo[0].planDetails;
  418. }
  419. let arr = [];
  420. let arrTemp = [];
  421. let arrTemp1 = []; // 不同index
  422. for (var i = 0; i < tempArr.length; i++) {
  423. arrTemp.push(i);
  424. }
  425. for (var i = 0; i < tempArr.length; i++) {
  426. for (var j = 0; j < newPlan.length; j++) {
  427. if (tempArr[i].code === newPlan[j].code) {
  428. arr.push(i);
  429. }
  430. }
  431. }
  432. arrTemp1 = arr
  433. .filter(x => arrTemp.indexOf(x) == -1)
  434. .concat(arrTemp.filter(x => arr.indexOf(x) == -1));
  435. let endArr = [...newPlan];
  436. for (var j = 0; j < arrTemp1.length; j++) {
  437. let temp = tempArr[arrTemp1[j]];
  438. temp.orderNo = arr.length + j + 1;
  439. temp.status = 0;
  440. endArr.push(temp);
  441. }
  442. // console.log(endArr,'-=-=-=-=-=');
  443. this.planDefaultList = endArr;
  444. },
  445. // format处理细项数据
  446. handleSendData() {
  447. let TempPlanDetail = [];
  448. TempPlanDetail = this.planDefaultList.map((item, index) => {
  449. return {
  450. code: item.code,
  451. hospitalId: this.form.hospitalId,
  452. // hospitalId: this.hospitalId,
  453. name: item.name,
  454. number: item.number,
  455. orderNo: item.orderNo,
  456. planId: item.planId,
  457. remark: item.remark,
  458. status: item.status,
  459. value: item.value
  460. };
  461. });
  462. return TempPlanDetail;
  463. // console.log(TempPlanDetail, 'TempPlanDetail');
  464. },
  465. // 处理保存活动信息参数
  466. _getParams() {
  467. let params = {
  468. hospitalId: this.form.hospitalId,
  469. planCode: this.form.planCode,
  470. planDetailParent: [
  471. {
  472. code: 'auxiliary',
  473. hospitalId: this.form.hospitalId,
  474. name: '辅助信息',
  475. number: 0,
  476. orderNo: 1,
  477. planDetailSub: this.handleSendData(),
  478. status: this.switchSubStatus
  479. },
  480. {
  481. code: 'medical',
  482. hospitalId: this.form.hospitalId,
  483. name: '医学知识',
  484. orderNo: 3,
  485. planDetailSub: [{}],
  486. status: this.switchMedStatus
  487. },
  488. {
  489. code: 'followup',
  490. hospitalId: this.form.hospitalId,
  491. name: '随访计划',
  492. orderNo: 4,
  493. planDetailSub: [{}],
  494. status: this.switchFollowStatus
  495. }
  496. ], // 方案配置信息
  497. planName: this.form.planName,
  498. planStatus: 1 // 1 启用 默认启用
  499. };
  500. if (this.isEdit) {
  501. // 编辑状态,需要额外添加ID
  502. const { data } = this.$route.params;
  503. params = { ...params, id: data.id };
  504. }
  505. return params;
  506. },
  507. onSubmit() {
  508. this.$refs.form.validate(valid => {
  509. if (valid) {
  510. this.saveDisable = true;
  511. let params = this._getParams();
  512. // console.log(params, 'params');
  513. // return;
  514. api.savePlanInfoDatas(params).then(res => {
  515. if (res.data.code === '0') {
  516. this.$message({
  517. showClose: true,
  518. message: '保存成功',
  519. type: 'success',
  520. duration: 1000
  521. });
  522. this.isSaveSuccess = true; // 保存成功,可正常退出
  523. this.$router.push({
  524. name: 'Plan',
  525. params: Object.assign({}, this.$route.params, {
  526. currentPage: 1
  527. })
  528. });
  529. } else if (res.data.code === '00020007') {
  530. // 方案名/方案编码已存在
  531. this.$message({
  532. showClose: true,
  533. message: res.data.msg,
  534. type: 'error',
  535. duration: 1000
  536. });
  537. }
  538. this.saveDisable = false;
  539. });
  540. } else {
  541. this.saveDisable = false;
  542. var div = this.$refs['elscrollbar'].$refs['wrap'];
  543. this.$nextTick(() => {
  544. div.scrollTop = 0;
  545. });
  546. return false;
  547. }
  548. });
  549. }
  550. }
  551. };
  552. </script>
  553. <style lang="less" scoped>
  554. .AddPlanWrapper {
  555. min-width: 940px;
  556. .AddPlanBox {
  557. padding: 20px 60px 120px 60px;
  558. margin: 70px 20px 0 20px;
  559. background: #fff;
  560. }
  561. color: #606266;
  562. .topBack {
  563. top: 0;
  564. }
  565. .title {
  566. background-color: #f2f2f2;
  567. display: flex;
  568. .handleIcon {
  569. width: 30px;
  570. cursor: pointer;
  571. height: 40px;
  572. display: flex;
  573. justify-content: center;
  574. align-items: center;
  575. img {
  576. width: 20px;
  577. height: 20px;
  578. }
  579. .open {
  580. transform: rotate(180deg);
  581. }
  582. .close {
  583. transform: rotate(0deg);
  584. }
  585. }
  586. .titlwSwitch {
  587. width: 120px;
  588. }
  589. h4 {
  590. flex: 1;
  591. }
  592. .titlwSwitchStatus {
  593. margin-left: 16px;
  594. }
  595. }
  596. .sub {
  597. .planItem {
  598. display: flex;
  599. .sort {
  600. width: 60px;
  601. display: flex;
  602. .top {
  603. display: flex;
  604. justify-content: center;
  605. align-items: center;
  606. width: 30px;
  607. cursor: pointer;
  608. img {
  609. width: 10px;
  610. height: 14px;
  611. }
  612. }
  613. .down {
  614. width: 30px;
  615. cursor: pointer;
  616. display: flex;
  617. justify-content: center;
  618. align-items: center;
  619. img {
  620. width: 10px;
  621. height: 14px;
  622. }
  623. }
  624. }
  625. .openOrClose {
  626. display: flex;
  627. flex: 1;
  628. .planInfo {
  629. width: 140px;
  630. }
  631. .switch {
  632. }
  633. .planStatus {
  634. margin-left: 16px;
  635. }
  636. }
  637. .showNum {
  638. display: flex;
  639. width: 160px;
  640. /deep/.el-input--small {
  641. width: 60px;
  642. }
  643. }
  644. }
  645. }
  646. .el-button {
  647. float: right;
  648. }
  649. .plus-icon-enter-active {
  650. transition: all 0.8s;
  651. }
  652. .plus-icon-enter {
  653. opacity: 0;
  654. margin-top: 12px;
  655. }
  656. .plus-icon-leave-active {
  657. transition: all 0.8s;
  658. }
  659. .plus-icon-leave-active {
  660. opacity: 0;
  661. margin-top: 12px;
  662. }
  663. }
  664. .leaveBox {
  665. /deep/ .leaveBtn {
  666. // margin-right: 46px;
  667. background-color: #d7d7d7 !important;
  668. border-color: transparent;
  669. }
  670. }
  671. .selectMedicine {
  672. /deep/ .el-input__suffix-inner {
  673. position: relative;
  674. top: -1px;
  675. }
  676. /deep/ .el-icon-circle-close {
  677. position: relative;
  678. top: -2px;
  679. }
  680. }
  681. </style>