AddTermSet.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. <style lang="less" scoped>
  2. // @import "../../less/admin.less";
  3. #AddRuleContent {
  4. width: 100%;
  5. min-width: 1000px;
  6. padding: 20px;
  7. padding-top: 50px;
  8. padding-bottom: 0;
  9. box-sizing: border-box;
  10. .form {
  11. width: 100%;
  12. }
  13. .remark {
  14. font-size: 14px;
  15. color: #606266;
  16. position: relative;
  17. left: 34px;
  18. top: -10px;
  19. padding-right: 30px;
  20. }
  21. .left_header {
  22. height: 40px;
  23. display: flex;
  24. justify-content: space-between;
  25. .tips {
  26. margin-top: 15px;
  27. }
  28. .inp {
  29. width: 150px;
  30. /deep/.el-input__inner {
  31. height: 30px;
  32. margin-top: 10px;
  33. }
  34. }
  35. }
  36. .right_header {
  37. display: flex;
  38. }
  39. .table_form {
  40. width: 100%;
  41. box-sizing: border-box;
  42. background: #fff;
  43. padding: 20px;
  44. padding-bottom: 0;
  45. display: flex;
  46. flex-wrap: wrap;
  47. }
  48. .table_content {
  49. min-height: 200px;
  50. height: calc(100vh - 264px);
  51. margin-top: 10px;
  52. .table_left {
  53. width: 45%;
  54. float: left;
  55. margin-right: 10px;
  56. background: #ffffff;
  57. padding: 0 2%;
  58. .left_box {
  59. margin: 30px 0;
  60. overflow: hidden;
  61. }
  62. .tabs {
  63. max-width: 100%;
  64. min-width: 100%;
  65. }
  66. .form_btn {
  67. display: flex;
  68. justify-content: flex-end;
  69. padding-bottom: 15px;
  70. }
  71. }
  72. .table_right {
  73. width: 45%;
  74. float: right;
  75. background: #ffffff;
  76. padding: 0 2%;
  77. .right_box {
  78. margin: 30px 0;
  79. overflow: hidden;
  80. }
  81. .tabs {
  82. max-width: 100%;
  83. min-width: 100%;
  84. }
  85. .inp {
  86. width: 100px;
  87. /deep/.el-input__inner {
  88. height: 30px;
  89. margin-top: 10px;
  90. }
  91. }
  92. .inps {
  93. margin-right: 10px;
  94. }
  95. .form_btn {
  96. display: flex;
  97. justify-content: space-between;
  98. padding-bottom: 15px;
  99. }
  100. }
  101. }
  102. /deep/.el-select-dropdown__item.hover,
  103. .el-select-dropdown__item:hover {
  104. color: #48c5d7;
  105. }
  106. /deep/ .el-form--inline .el-form-item__label {
  107. font-size: 14px;
  108. color: #606266;
  109. }
  110. /deep/ .el-input--mini .el-input__inner,
  111. .el-select {
  112. width: 100%;
  113. font-size: 14px;
  114. }
  115. /deep/ .el-form-item.is-success .el-input__inner,
  116. .el-form-item.is-success .el-textarea__inner {
  117. border-color: #c9c9c9 !important;
  118. }
  119. /deep/ .el-form-item.is-success .el-textarea__inner {
  120. border-color: #c9c9c9 !important;
  121. }
  122. /deep/ .el-form-item.is-success .el-textarea__inner {
  123. border-color: #c9c9c9 !important;
  124. }
  125. /deep/ .el-table th.gutter{
  126. display: table-cell!important;
  127. }
  128. }
  129. .test_box {
  130. min-height: 300px;
  131. max-height: 300px;
  132. outline: 0;
  133. border: 1px solid #dcdfe6;
  134. font-size: 14px;
  135. line-height: 1.5;
  136. word-wrap: break-word;
  137. overflow-x: hidden;
  138. overflow-y: auto;
  139. border-radius: 4px;
  140. margin-top: 6px;
  141. padding: 10px 15px;
  142. }
  143. </style>
  144. <style scoped>
  145. </style>
  146. <template>
  147. <div>
  148. <crumbs :title="title" :param="$route.params" linkTo="TermSet"></crumbs>
  149. <div id="AddRuleContent">
  150. <div class="table_form">
  151. <el-form
  152. size="mini"
  153. :inline="true"
  154. class="demo-form-inline form"
  155. :model="form"
  156. :rules="rules"
  157. >
  158. <el-form-item label-width="130px" label="术语集合类型:" prop="collectionLibType">
  159. <el-select
  160. v-model="form.collectionLibType"
  161. placeholder="请选择"
  162. @change="getConceptLibType"
  163. :disabled="sign==2?true:false"
  164. :title="form.collectionLibName"
  165. >
  166. <el-option
  167. v-for="item in ruleTypeList"
  168. :key="item.val"
  169. :label="item.name"
  170. :value="item.val"
  171. ></el-option>
  172. </el-select>
  173. </el-form-item>
  174. <!-- 规则术语类型: -->
  175. <el-form-item label-width="130px" label="术语集合名称:" prop="collectionLibName">
  176. <el-select
  177. clearable
  178. remote
  179. filterable
  180. v-model.trim="form.collectionLibName"
  181. placeholder="请输入"
  182. :remote-method="searchLibName"
  183. @change="getCollectionLib"
  184. :disabled="sign==2?true:false"
  185. value-key="conceptId"
  186. :title="form.collectionLibName"
  187. >
  188. <el-option
  189. v-for="item in ruleTermTypeList"
  190. :key="item.conceptId"
  191. :label="item.conceptName"
  192. :value="item.conceptName"
  193. ></el-option>
  194. </el-select>
  195. </el-form-item>
  196. </el-form>
  197. <div class="remark">说明:{{form.collectionRemark}}</div>
  198. </div>
  199. <div class="table_content" v-if="onshow">
  200. <div class="table_left">
  201. <div class="left_header">
  202. <h5 class="tips">关联的术语({{form.concepts.length}})</h5>
  203. <div style="display:flex">
  204. <el-input v-model="searchtext" @input="searchList" placeholder="关键词" class="inp"></el-input>
  205. <span style="display:flex;align-items: center;margin:0 5px">-</span>
  206. <el-input v-model="searchtext2" @input="searchList" placeholder="关键词" class="inp"></el-input>
  207. </div>
  208. </div>
  209. <div class="left_box">
  210. <el-table
  211. :data="leftList"
  212. border
  213. min-height="200"
  214. max-height="500"
  215. class="tabs"
  216. :header-row-style="{height:'40px'}"
  217. :header-cell-style="{height:'40px',padding:'0',background:'#f7f7f7'}"
  218. >
  219. <el-table-column prop="conceptLibName" :show-overflow-tooltip="true" label="术语名称"></el-table-column>
  220. <el-table-column label="操作" fixed="right">
  221. <template slot-scope="scope">
  222. <el-button
  223. type="text"
  224. size="small"
  225. class="delete"
  226. @click="showDelDialog(scope.row)"
  227. >移除</el-button>
  228. </template>
  229. </el-table-column>
  230. </el-table>
  231. </div>
  232. <div class="form_btn">
  233. <el-button type="primary" size="medium " @click="saveSet">确定</el-button>
  234. </div>
  235. </div>
  236. <div class="table_right">
  237. <div class="right_header">
  238. <el-select
  239. v-model="formInline.logicalOperator"
  240. class="inp inps"
  241. @change="searchConcept"
  242. >
  243. <el-option label="and" value="0"></el-option>
  244. <el-option label="or" value="1"></el-option>
  245. </el-select>
  246. <el-input
  247. v-model="formInline.name1"
  248. @input="searchConcept"
  249. placeholder="关键词"
  250. class="inp"
  251. ></el-input>
  252. <span style="display:flex;align-items: center;margin:0 5px">-</span>
  253. <el-input
  254. v-model="formInline.name2"
  255. @input="searchConcept"
  256. placeholder="关键词"
  257. class="inp"
  258. ></el-input>
  259. <span style="display:flex;align-items: center;margin:0 5px">-</span>
  260. <el-input
  261. v-model="formInline.name3"
  262. @input="searchConcept"
  263. placeholder="关键词"
  264. class="inp"
  265. ></el-input>
  266. </div>
  267. <div class="right_box">
  268. <el-table
  269. :data="conceptList"
  270. border
  271. min-height="200"
  272. max-height="500"
  273. class="tabs"
  274. @row-click="btn"
  275. :header-row-style="{height:'40px'}"
  276. :header-cell-style="{height:'40px',padding:'0',background:'#f7f7f7'}"
  277. @selection-change="handleSelectionChange"
  278. >
  279. <el-table-column type="selection"></el-table-column>
  280. <el-table-column prop="conceptName" :show-overflow-tooltip="true" label="术语名称"></el-table-column>
  281. </el-table>
  282. </div>
  283. <div class="form_btn">
  284. <el-button size="medium " @click="add" icon="el-icon-caret-left">添加</el-button>
  285. <el-button size="medium " @click="dialogVisible = true">文本批量添加</el-button>
  286. </div>
  287. </div>
  288. </div>
  289. </div>
  290. <el-dialog
  291. :title="'请输入要添加到关联的标准术语(每行一个)'+'共'+len+'行'"
  292. :visible.sync="dialogVisible"
  293. width="30%"
  294. @close="collectcancel"
  295. :close-on-click-modal="false"
  296. >
  297. <div
  298. class="test_box"
  299. contenteditable="true"
  300. ref="msg"
  301. style="white-space: pre-wrap"
  302. @input="handleInput"
  303. ></div>
  304. <span slot="footer" class="dialog-footer">
  305. <el-button @click="cancel">取 消</el-button>
  306. <el-button type="primary" @click="collectionMatch">确 定</el-button>
  307. <el-button @click="collectcancel">保存并关闭</el-button>
  308. </span>
  309. </el-dialog>
  310. </div>
  311. </template>
  312. <script type="text/javascript">
  313. import api from '@api/knowledgeLib.js';
  314. import AddNewRuleTable from './AddNewRuleTable';
  315. import axios from 'axios';
  316. export default {
  317. name: 'AddRule',
  318. data() {
  319. return {
  320. title: '术语集合内容维护-添加',
  321. formInline: {
  322. logicalOperator: '0',
  323. name1: '',
  324. name2: '',
  325. name3: ''
  326. },
  327. innerText: '',
  328. ruleTypeList: [],
  329. ruleTermTypeList: [],
  330. conceptList: [],
  331. conceptText: '',
  332. excludedConceptIds: [],
  333. type: [],
  334. leftList: [],
  335. multipleSelection: [],
  336. sign: 1,
  337. searchtext: '',
  338. searchtext2: '',
  339. dialogVisible: false,
  340. form: {
  341. collectionLibType: '',
  342. collectionLibName: '',
  343. concepts: [],
  344. conceptLibType: '',
  345. collectionRemark: '',
  346. collectionId: ''
  347. },
  348. whether: false,
  349. editCount: -1, // 页面会否被编辑 >0被编辑 =0 未编辑
  350. startCount: -1,
  351. isSaveSuccess: false, // 是否保存成功
  352. timeout: null,
  353. rules: {
  354. collectionLibType: [
  355. { required: true, message: '请选择术语集合类型', trigger: 'change' }
  356. ],
  357. collectionLibName: [
  358. { required: true, message: '请选择术语集合名称', trigger: 'change' }
  359. ]
  360. },
  361. Math: 88,
  362. English: 77,
  363. chemistry: 99
  364. };
  365. },
  366. created() {
  367. this.getDict();
  368. const param = this.$route.params;
  369. let info = param.data;
  370. if (info) {
  371. this.title = '术语集合内容维护-' + '修改';
  372. this.form.collectionLibType = JSON.stringify(info.collectionLibType);
  373. this.form.collectionLibName = info.collectionLibName;
  374. this.form.concepts = info.concepts;
  375. this.form.conceptLibType = info.concepts[0].conceptLibType;
  376. this.form.collectionId = info.collectionId;
  377. this.form.collectionRemark = info.collectionRemark;
  378. this.leftList = info.concepts;
  379. this.sign = 2;
  380. this.$nextTick(() => {
  381. this.getIds(this.form.concepts);
  382. this.getTreeSearchList();
  383. });
  384. }
  385. setTimeout(() => {
  386. this.startCount = this.editCount;
  387. }, 500);
  388. },
  389. methods: {
  390. handleInput(event) {
  391. let text = event.target.innerText;
  392. this.innerText = text.replace(/(^\s*)|(\s*$)/g, '');
  393. },
  394. cancel() {
  395. this.$refs.msg.innerHTML = '';
  396. this.innerText = '';
  397. this.dialogVisible = false;
  398. },
  399. collectcancel() {
  400. this.dialogVisible = false;
  401. },
  402. cancelRequest() {
  403. if (typeof this.source === 'function') {
  404. this.source('终止请求');
  405. }
  406. },
  407. getDict() {
  408. api
  409. .zskgetDict()
  410. .then(res => {
  411. if (res.data.code == '0') {
  412. const data = res.data.data;
  413. this.ruleTypeList = data[63];
  414. this.type = data[61];
  415. }
  416. })
  417. .catch(error => {
  418. console.log(error);
  419. });
  420. },
  421. //过滤集合id
  422. getIds(arr) {
  423. arr.forEach((item, index) => {
  424. this.excludedConceptIds.push(item.conceptId);
  425. });
  426. },
  427. //获取术语集合名称
  428. searchLibName(val) {
  429. api
  430. .getSearchConcept({
  431. excludedConceptIds: [0],
  432. libType: this.form.collectionLibType,
  433. name: val
  434. })
  435. .then(res => {
  436. if (res.data.code == '0') {
  437. const data = res.data.data;
  438. this.ruleTermTypeList = data;
  439. }
  440. })
  441. .catch(error => {
  442. console.log(error);
  443. });
  444. },
  445. searchList() {
  446. let concepts, val;
  447. if (
  448. (this.searchtext != '' && this.searchtext2 == '') ||
  449. (this.searchtext == '' && this.searchtext2 != '')
  450. ) {
  451. concepts = JSON.parse(JSON.stringify(this.form.concepts));
  452. val = this.searchtext != '' ? this.searchtext : this.searchtext2;
  453. } else if (this.searchtext != '' && this.searchtext2 != '') {
  454. concepts = JSON.parse(JSON.stringify(this.leftList));
  455. val = this.searchtext2;
  456. } else if (this.searchtext == '' && this.searchtext2 == '') {
  457. this.leftList = JSON.parse(JSON.stringify(this.form.concepts));
  458. return;
  459. }
  460. let str = '.*' + val + '.*';
  461. let reg = new RegExp(str);
  462. let arr = [];
  463. //通过附加信息查询
  464. for (var i = 0; i < concepts.length; i++) {
  465. if (reg.test(concepts[i].conceptLibName)) {
  466. arr.push(concepts[i]);
  467. }
  468. }
  469. this.leftList = arr;
  470. },
  471. getCollectionLib(newValue) {
  472. this.ruleTermTypeList.forEach(item => {
  473. if (newValue == item.conceptName) {
  474. // this.form.collectionLibName = item.conceptName;
  475. this.form.collectionId = item.conceptId;
  476. this.form.collectionRemark = item.remark;
  477. }
  478. });
  479. },
  480. // 基础术语
  481. searchConcept(e) {
  482. if (this.timeout) {
  483. clearTimeout(this.timeout);
  484. }
  485. this.timeout = setTimeout(() => {
  486. this.getTreeSearchList();
  487. }, 800);
  488. },
  489. async getTreeSearchList() {
  490. this.whether = true;
  491. const params = {
  492. libType: this.form.conceptLibType,
  493. names: [
  494. this.formInline.name1,
  495. this.formInline.name2,
  496. this.formInline.name3
  497. ],
  498. excludedConceptIds: this.excludedConceptIds,
  499. logicalOperator: this.formInline.logicalOperator
  500. };
  501. const data = await api.searchCollectionConceptVO(params);
  502. if (data.data.code == '0') {
  503. this.conceptList = data.data.data;
  504. this.whether = false;
  505. }
  506. },
  507. btn(row) {
  508. if (this.whether) {
  509. return;
  510. }
  511. let concepts = {
  512. conceptId: row.conceptId,
  513. conceptLibType: row.libType,
  514. conceptLibName: row.conceptName
  515. };
  516. this.excludedConceptIds.push(row.conceptId);
  517. this.form.concepts.push(concepts);
  518. this.leftList = this.form.concepts;
  519. this.conceptList = [];
  520. this.searchtext = '';
  521. this.searchtext2 = '';
  522. this.$nextTick(() => {
  523. setTimeout(() => {
  524. this.getTreeSearchList();
  525. }, 150);
  526. });
  527. },
  528. handleSelectionChange(val) {
  529. this.multipleSelection = val;
  530. },
  531. add() {
  532. if (this.multipleSelection.length == 0) {
  533. this.$message({
  534. message: '数据不能为空',
  535. type: 'error'
  536. });
  537. return;
  538. }
  539. this.processing(this.multipleSelection);
  540. this.searchtext = '';
  541. this.searchtext2 = '';
  542. },
  543. //去重
  544. unique(arr) {
  545. let obj = {};
  546. arr = arr.reduce(function(item, next) {
  547. obj[next.conceptId] ? '' : (obj[next.conceptId] = true && item.push(next));
  548. return item;
  549. }, []);
  550. return arr
  551. },
  552. //处理数据
  553. processing(arr) {
  554. if (this.whether) {
  555. return;
  556. }
  557. arr.forEach(it => {
  558. let concepts = {
  559. conceptId: it.conceptId,
  560. conceptLibType: it.libType ? it.libType : it.conceptLibType,
  561. conceptLibName: it.conceptName ? it.conceptName : it.conceptLibName
  562. };
  563. this.excludedConceptIds.push(it.conceptId);
  564. this.form.concepts.push(concepts);
  565. });
  566. this.leftList = this.unique(this.form.concepts);;
  567. this.conceptList = [];
  568. this.multipleSelection = [];
  569. this.$nextTick(() => {
  570. setTimeout(() => {
  571. this.getTreeSearchList();
  572. }, 150);
  573. });
  574. },
  575. // 切换术语类型
  576. getConceptLibType() {
  577. this.type.forEach(it => {
  578. let id = it.val.split('-');
  579. if (this.form.collectionLibType == id[0]) {
  580. this.form.conceptLibType = id[2];
  581. }
  582. });
  583. this.clearData();
  584. },
  585. // 移除术语
  586. showDelDialog(row) {
  587. this.form.concepts.forEach((item, index) => {
  588. if (item.conceptId == row.conceptId) {
  589. this.form.concepts.splice(index, 1);
  590. this.excludedConceptIds.splice(index, 1);
  591. }
  592. });
  593. this.getTreeSearchList();
  594. },
  595. saveSet() {
  596. let params = {
  597. ...this.form,
  598. relationId: 0
  599. };
  600. api.saveOrUpdateRecord(params).then(res => {
  601. if (res.data.code == 0) {
  602. this.$message({
  603. message: '操作成功',
  604. type: 'success'
  605. });
  606. this.isSaveSuccess = true;
  607. this.$router.push({
  608. name: 'TermSet',
  609. params: Object.assign({}, this.$route.params, { currentPage: 1 })
  610. });
  611. } else {
  612. this.$message({
  613. message: res.data.msg,
  614. type: 'warning'
  615. });
  616. }
  617. });
  618. },
  619. collectionMatch() {
  620. if (this.innerText.length == 0) {
  621. this.$message({
  622. message: '术语名称不能为空',
  623. type: 'error'
  624. });
  625. return;
  626. }
  627. let params = {
  628. conceptLibNames: this.innerText,
  629. conceptLibType: this.form.conceptLibType
  630. };
  631. api
  632. .collectionMatch(params)
  633. .then(res => {
  634. if (res.data.code == '0') {
  635. const data = res.data.data;
  636. let text = '';
  637. if (data.unMatchList.length > 0) {
  638. data.unMatchList.forEach(it => {
  639. text += it.conceptLibName + '\n';
  640. });
  641. this.$message({
  642. message: '列表中存在非标准术语',
  643. type: 'error'
  644. });
  645. }
  646. if (data.matchList.length > 0) {
  647. this.processing(data.matchList);
  648. if (data.unMatchList.length == 0) {
  649. this.dialogVisible = false;
  650. }
  651. }
  652. this.$refs.msg.innerHTML = text;
  653. this.innerText = text;
  654. }
  655. })
  656. .catch(error => {
  657. console.log(error);
  658. });
  659. },
  660. clearData() {
  661. this.form.collectionLibName = '';
  662. this.conceptText = '';
  663. this.ruleTermTypeList = [];
  664. this.form.concepts = [];
  665. this.getTreeSearchList();
  666. }
  667. },
  668. watch: {
  669. form: {
  670. handler(newName, oldName) {
  671. this.editCount++;
  672. },
  673. deep: true,
  674. immediate: true
  675. }
  676. },
  677. beforeRouteLeave(to, from, next) {
  678. if (
  679. this.startCount !== this.editCount &&
  680. this.form.concepts.length > 0 &&
  681. !this.isSaveSuccess
  682. ) {
  683. this.$alert('还有未保存的内容,确定要退出当前页面吗?', '提示', {
  684. confirmButtonText: '确定',
  685. // cancelButtonText: '取消',
  686. // cancelButtonClass: 'leaveBtn',
  687. // customClass: 'leaveBox',
  688. type: 'warning'
  689. })
  690. .then(() => {
  691. next();
  692. })
  693. .catch(() => {});
  694. } else {
  695. next();
  696. }
  697. },
  698. computed: {
  699. onshow() {
  700. return (
  701. this.form.collectionLibType != '' && this.form.collectionLibName != ''
  702. );
  703. },
  704. len() {
  705. let arr = this.innerText.split('\n');
  706. let len = 0;
  707. arr.forEach(it => {
  708. if (it != '') {
  709. len++;
  710. }
  711. });
  712. return len;
  713. }
  714. }
  715. };
  716. </script>