AddTermSet.vue 20 KB

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