LinkEle.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. <template>
  2. <el-dialog
  3. class="dialog-set"
  4. :visible.sync="visible"
  5. width="70%"
  6. append-to-body
  7. >
  8. <div slot="title" class="dialog-title">
  9. <div>
  10. <i class="el-icon-connection" ></i>
  11. <span style="margin-left: 10px;">关联元素</span>
  12. </div>
  13. <div class="marginTop-10">设置获取数据的元素位置,用于回显数据到相应位置</div>
  14. </div>
  15. <div class="conditions-container">
  16. <!-- 左侧条件列表 -->
  17. <div class="conditions-left">
  18. <div class="condition-header">
  19. <i class="el-icon-s-operation" style="color: rgb(46, 123, 115);"></i>
  20. <span>参数列表</span>
  21. </div>
  22. <div class="condition-list">
  23. <div class="condition-item">
  24. <span
  25. v-for="(item, index) in paramList"
  26. :key="index"
  27. :class="{ active: activeIndex === index }"
  28. @click="handleSelect1(index, item)"
  29. >
  30. {{ item.symbolName }}
  31. </span>
  32. </div>
  33. </div>
  34. </div>
  35. <!-- 右侧操作列表 -->
  36. <div class="conditions-right">
  37. <div class="condition-header1">
  38. <div class="header-left">
  39. <i class="el-icon-s-operation" style="color: rgb(46, 123, 115);"></i>
  40. <span>条件列表</span>
  41. </div>
  42. <div class="header-right">
  43. <el-button
  44. type="primary"
  45. size="small"
  46. :style="{ background: 'rgb(37, 80, 162)', borderColor: 'rgb(37, 80, 162)' }"
  47. @click="addCondition"
  48. >
  49. <i class="el-icon-plus"></i>
  50. 添加元素
  51. </el-button>
  52. <el-button
  53. type="success"
  54. size="small"
  55. @click="saveEle"
  56. >
  57. <i class="el-icon-check"></i>
  58. 保存元素
  59. </el-button>
  60. </div>
  61. </div>
  62. <div class="condition-list">
  63. <div class="condition-item1">
  64. <div
  65. v-for="(item, index) in paramList[activeIndex].group"
  66. :key="index"
  67. >
  68. <div>
  69. <span>
  70. <div class="condition-header-content">
  71. <div style="color: black;">
  72. {{item.privateName}}
  73. </div>
  74. <i class="el-icon-close" @click.stop="handleDeleteItem(item,index)"></i>
  75. </div>
  76. <div class="code-list">
  77. <div class="code-item">
  78. {{ item.elementNames}}
  79. </div>
  80. </div>
  81. </span>
  82. </div>
  83. </div>
  84. </div>
  85. </div>
  86. </div>
  87. </div>
  88. <div class="result-container">
  89. <div class="condition-header">
  90. <i class="el-icon-connection" style="color: rgb(46, 123, 115);"></i>
  91. <span>关联关系</span>
  92. </div>
  93. <div class="link-list">
  94. <div v-for="(item, index) in linkListData" :key="index" class="link-item" :class="{ clicked: item.clicked }" @click="toggleClick(item, index)">
  95. <i class="el-icon-close" @click.stop="handleDeleteLinkItem(item,index)"></i>
  96. <div class="link-name">
  97. <span>{{ item.symbolName }}</span>
  98. </div>
  99. <div>
  100. <i class="el-icon-connection" style="color: black; font-size: larger;"></i>
  101. </div>
  102. <div class="code-list">
  103. <div v-for="(codeItem, codeIndex) in item.group" :key="codeIndex" class="code-item">
  104. <div class="code-title">{{ codeItem.privateName }}</div>
  105. <div class="code-detail">{{ codeItem.elementNames }}</div>
  106. </div>
  107. </div>
  108. </div>
  109. </div>
  110. </div>
  111. <div slot="footer" class="dialog-footer">
  112. <el-button type="primary" @click="handleConfirm" :style="{ background: 'rgb(37, 80, 162)', borderColor: 'rgb(37, 80, 162)' }">保存</el-button>
  113. </div>
  114. <div style="height: 100%;">
  115. <el-drawer
  116. class="dialog-set"
  117. :visible.sync="addDialogVisible"
  118. width="80%"
  119. height="80%"
  120. append-to-body
  121. direction="ttb"
  122. >
  123. <div slot="title" class="dialog-title">
  124. <div>
  125. <i class="el-icon-plus" ></i>
  126. <span style="margin-left: 10px;">添加元素</span>
  127. </div>
  128. <div class="marginTop-10">根据表单选择回显的元素位置。根据条件判定后,自动将满足条件的数据回显到选择的元素位置</div>
  129. </div>
  130. <div class="condition-header1-title">
  131. <span>选择表单</span>
  132. </div>
  133. <div class="condition-header1-table">
  134. <el-table
  135. :data="tableData"
  136. height="250"
  137. border
  138. style="width: 100%">
  139. <el-table-column
  140. prop="tableName"
  141. label="表单名称"
  142. >
  143. </el-table-column>
  144. <el-table-column
  145. align="center"
  146. prop="tableType"
  147. :formatter="formatTableType"
  148. width="100"
  149. label="表单类型"
  150. ></el-table-column>
  151. <el-table-column
  152. width="150"
  153. label="操作"
  154. >
  155. <template slot-scope="scope">
  156. <el-button
  157. v-if="!scope.row.isSelected"
  158. type="text"
  159. size="small"
  160. @click="handleRowSelect(scope.row)"
  161. >
  162. 选择
  163. </el-button>
  164. <el-button
  165. v-else
  166. type="text"
  167. size="small"
  168. style="color: #F56C6C;"
  169. @click="handleCancelSelect(scope.row)"
  170. >
  171. 取消选择
  172. </el-button>
  173. </template>
  174. </el-table-column>
  175. </el-table>
  176. </div>
  177. <div class="condition-header1-title" style="margin-top: 10px;">
  178. <span>选择元素</span>
  179. </div>
  180. <div class="condition-header1-html-box">
  181. <check-ele-html
  182. :key="pkeyId"
  183. :pkeyId="pkeyId"
  184. @element-selected="handleElementSelected"
  185. ></check-ele-html>
  186. </div>
  187. <div class="dialog-footer">
  188. <el-button type="primary" @click="confirmAdd" :style="{ background: 'rgb(37, 80, 162)', borderColor: 'rgb(37, 80, 162)' }">确认添加</el-button>
  189. </div>
  190. </el-drawer>
  191. </div>
  192. </el-dialog>
  193. </template>
  194. <script>
  195. import { getDictionary } from "@/api/system/dict";
  196. import { findNodeTableByCondition as selectByNodeTable} from "@/api/manager/wbsprivate";
  197. import checkEleHtml from "./checkEleHtml.vue";
  198. import {saveElementJoin,deleteElementJoin,getElementJoin } from "@/api/ruleManage/fileRule.js";
  199. export default {
  200. name: 'ConditionsSet',
  201. components: {
  202. checkEleHtml
  203. },
  204. data() {
  205. return {
  206. visible: false,
  207. treeId: '', // 树节点pid
  208. treePid: '', // 树节点父id
  209. deatailId: '', // 详情ID
  210. jId: '', // 技术指标ID
  211. paramList: [
  212. {
  213. symbolName: '',
  214. group:[
  215. ]
  216. }
  217. ] , // 参数列表数据
  218. activeIndex: 0, // 当前选中的参数索引
  219. addDialogVisible: false,
  220. tableData: [
  221. ],
  222. tableTypelist: [],
  223. pkeyId: '', // 主键ID
  224. id:'',
  225. projectid:'',
  226. checkTableRow: {}, // 当前选中的表单行数据
  227. checkEleList: [], // 存储选中的元素
  228. linkListData: [
  229. ], // 关联关系数据
  230. }
  231. },
  232. methods: {
  233. show(val,treeId,id,projectid,deatailId,tid,Jid) {
  234. this.jId = Jid;
  235. this.getTableTypelist();
  236. this.visible = true
  237. if(val.length > 0&&val[0].name) {
  238. this.treeId = treeId
  239. this.id = id
  240. this.deatailId = deatailId
  241. this.projectid = projectid
  242. this.paramList=val
  243. this.treePid=tid
  244. val.forEach((item,index)=>{
  245. this.handleSelect(index)
  246. })
  247. this.activeIndex = 0
  248. }else{
  249. this.paramList = []
  250. this.treeId = ''
  251. }
  252. this.getLinkSetData(this.deatailId,this.jId);
  253. },
  254. async getLinkSetData(id, groupId) {
  255. try {
  256. const res = await getElementJoin({ id, groupId });
  257. if (res.data.code === 200) {
  258. console.log(res.data.data, '获取的关系数据');
  259. this.linkListData = res.data.data; // 直接返回数据
  260. } else {
  261. this.$message.error(res.data.msg);
  262. throw new Error(res.data.msg); // 抛出错误,以便在调用处处理
  263. }
  264. } catch (error) {
  265. // 这里可以添加额外的错误处理逻辑,例如记录日志
  266. throw error; // 重新抛出错误,以便在调用处捕获
  267. }
  268. },
  269. async handleSelect(index) {
  270. this.activeIndex = index
  271. let leftId = this.paramList[index].id
  272. let arr= await this.getRelationData(this.deatailId,this.Jid,leftId)
  273. if(arr.length>0){
  274. this.$nextTick(()=>{
  275. // this.paramList[index].group = arr[0]['group']
  276. this.$set(this.paramList, index, { ...this.paramList[index], group: arr[0]['group'] });
  277. })
  278. }else{
  279. this.paramList[index].group = []
  280. }
  281. },
  282. async getRelationData(id, groupId,leftId){
  283. try {
  284. const res = await getElementJoin({ id, groupId, leftId });
  285. if (res.data.code === 200) {
  286. console.log(res.data.data, '获取的条件设置数据');
  287. return res.data.data; // 直接返回数据
  288. } else {
  289. this.$message.error(res.data.msg);
  290. throw new Error(res.data.msg); // 抛出错误,以便在调用处处理
  291. }
  292. } catch (error) {
  293. // 这里可以添加额外的错误处理逻辑,例如记录日志
  294. throw error; // 重新抛出错误,以便在调用处捕获
  295. }
  296. },
  297. getTableTypelist() {
  298. getDictionary({
  299. code:'trial_table_type',
  300. }).then((res) => {
  301. res.data.data.forEach((element) => {
  302. element.dictKey = Number(element.dictKey);
  303. });
  304. this.tableTypelist = res.data.data;
  305. });
  306. },
  307. async getTableData(){
  308. const { data: res } = await selectByNodeTable( this.treePid,this.projectid, this.id);
  309. if (res.code === 200) {
  310. console.log(Array.isArray(res.data));
  311. if (Array.isArray(res.data)) {
  312. this.tableData = res.data
  313. } else {
  314. this.tableData = []
  315. this.$message.error('获取表单数据失败,请先关联清表');
  316. }
  317. }
  318. },
  319. hide() {
  320. this.visible = false
  321. },
  322. handleConfirm() {
  323. saveElementJoin(this.linkListData,this.deatailId).then((res)=>{
  324. if(res.data.code === 200) {
  325. this.$message({
  326. type: 'success',
  327. message: res.data.msg,
  328. })
  329. }else{
  330. this.$message({
  331. type: 'error',
  332. message: res.data.msg,
  333. })
  334. }
  335. })
  336. this.hide()
  337. this.$emit('confirm')
  338. },
  339. toggleClick(item, index) {
  340. this.linkListData.forEach(listItem => {
  341. this.$set(listItem, 'clicked', false);
  342. });
  343. this.$set(item, 'clicked', !item.clicked);
  344. let clickedIndex = this.paramList.findIndex(listItem => listItem.id === item.id);
  345. console.log(clickedIndex, 'clickedIndex');
  346. this.activeIndex = clickedIndex;
  347. },
  348. handleDeleteLinkItem(item,index){
  349. this.$confirm('删除后,数据将无法恢复,是否确认删除!', '提示', {
  350. confirmButtonText: '确定',
  351. cancelButtonText: '取消',
  352. type: 'warning'
  353. }).then(() => {
  354. deleteElementJoin({leftId:item.id}).then((res) => {
  355. if(res.data.code==200){
  356. this.$message.success(res.data.msg);
  357. this.linkListData.splice(index, 1);
  358. this.getLinkSetData(this.deatailId);
  359. }else{
  360. this.$message.error(res.data.msg);
  361. }
  362. });
  363. }).catch(() => {
  364. this.$message.info('已取消删除');
  365. })
  366. },
  367. addCondition() {
  368. // 添加条件逻辑
  369. this.addDialogVisible = true
  370. this.pkeyId = ''
  371. this.getTableData();
  372. },
  373. handleSelect1(index) {
  374. this.activeIndex = index
  375. },
  376. handleDeleteItem(item, index) {
  377. this.paramList[this.activeIndex].group.splice(index, 1)
  378. this.$forceUpdate();
  379. },
  380. confirmAdd() {
  381. if (this.checkEleList.length === 0) {
  382. this.$message.error('请先选择元素');
  383. return;
  384. }
  385. if (this.checkTableRow.pkeyId === undefined || this.checkTableRow.pkeyId === '') {
  386. this.$message.error('请先选择表单');
  387. return;
  388. }
  389. const selectedCodes = this.checkEleList.map(ele => ({
  390. colName: ele.keyName,
  391. colKey: ele.elementId
  392. }));
  393. console.log(selectedCodes,'selectedCodes');
  394. console.log(this.paramList,'this.paramList');
  395. let objArr={}
  396. const elementNames = selectedCodes.map(code => code.colName).join(' ');
  397. objArr={
  398. privateName: this.checkTableRow.tableName,
  399. privateId: this.checkTableRow.pkeyId,
  400. elementNames: elementNames,
  401. keys: selectedCodes,
  402. }
  403. this.paramList[this.activeIndex].group.push(objArr);
  404. this.addDialogVisible = false;
  405. this.$message.success('添加成功');
  406. },
  407. handleElementSelected(val) {
  408. console.log(val, '选中的元素');
  409. this.checkEleList = val;
  410. },
  411. //保存条件
  412. saveEle(){
  413. console.log(this.paramList,'保存条件');
  414. const filteredArr = this.paramList.filter(item => item.group.length !== 0);
  415. this.linkListData = JSON.parse(JSON.stringify(filteredArr));
  416. },
  417. formatTableType(row, column, cellValue) {
  418. for (let i = 0; i < this.tableTypelist.length; i++) {
  419. if (this.tableTypelist[i].dictKey == cellValue) {
  420. return this.tableTypelist[i].dictValue;
  421. }
  422. }
  423. return cellValue;
  424. },
  425. handleRowSelect(row) {
  426. // 设置选中状态
  427. // 先取消其他行的选中状态
  428. this.tableData.forEach(item => {
  429. if(item !== row) {
  430. this.$set(item, 'isSelected', false)
  431. }
  432. })
  433. this.pkeyId = row.pkeyId; // 更新主键ID
  434. this.checkTableRow = row; // 更新当前选中的表单行数据
  435. // 设置当前行选中状态
  436. this.$set(row, 'isSelected', true)
  437. },
  438. handleCancelSelect(row) {
  439. this.checkTableRow = {}; // 清除当前选中的表单行数据
  440. this.pkeyId = ''; // 清除主键ID
  441. // 取消选中状态
  442. this.$set(row, 'isSelected', false)
  443. }
  444. }
  445. }
  446. </script>
  447. <style lang="scss" scoped>
  448. .conditions-container {
  449. display: flex;
  450. gap: 20px;
  451. font-weight: bold;
  452. // height: 200px;
  453. .green-txt{
  454. color: rgb(46, 123, 115);;
  455. }
  456. .conditions-left,
  457. .conditions-right {
  458. flex: 1;
  459. border: 1px solid #EBEEF5;
  460. border-radius: 4px;
  461. background: #f5f7fa;
  462. }
  463. .condition-list,
  464. .condition-content {
  465. padding: 10px;
  466. }
  467. .condition-item {
  468. span {
  469. display: inline-block;
  470. padding: 8px 8px;
  471. margin: 5px;
  472. background: white;
  473. color: #409EFF;
  474. border-radius: 4px;
  475. cursor: pointer; // 添加指针样式
  476. transition: all 0.3s; // 添加过渡效果
  477. &.active { // 选中状态
  478. background: #67C23A;;
  479. color: white;
  480. }
  481. }
  482. }
  483. .content-item {
  484. margin-bottom: 10px;
  485. padding: 10px;
  486. border: 1px solid #EBEEF5;
  487. border-radius: 4px;
  488. .item-title {
  489. display: flex;
  490. gap: 10px;
  491. align-items: center;
  492. span {
  493. &:first-child {
  494. color: #666;
  495. }
  496. &:nth-child(2) {
  497. color: #409EFF;
  498. }
  499. &:last-child {
  500. color: #666;
  501. }
  502. }
  503. }
  504. }
  505. }
  506. .dialog-title {
  507. display: flex;
  508. flex-direction: column;
  509. color:white ;
  510. padding: 10px;
  511. font-size: 14px;
  512. .marginTop-20{
  513. margin-top: 10px;
  514. }
  515. background: rgb(37, 80, 162);
  516. .el-dialog__header{
  517. padding: 0px;
  518. }
  519. }
  520. .condition-header1 {
  521. display: flex;
  522. justify-content: space-between; // 两端对齐
  523. align-items: center;
  524. padding: 10px;
  525. border-bottom: 1px solid #EBEEF5;
  526. .header-left {
  527. display: flex;
  528. align-items: center;
  529. span {
  530. font-weight: bold;
  531. margin-left: 10px;
  532. }
  533. }
  534. .header-right {
  535. display: flex;
  536. gap: 10px; // 按钮间距
  537. .el-button {
  538. padding: 7px 15px;
  539. &:hover {
  540. opacity: 0.8;
  541. }
  542. }
  543. }
  544. }
  545. .code-list{
  546. display: flex;
  547. font-weight: bold;
  548. .code-item{
  549. margin-right: 5px;
  550. margin-top: 5px;
  551. flex-shrink: 0; // 防止元素在Flex容器中收缩
  552. min-width: 100px;
  553. max-width: 200px;
  554. overflow-x: auto;
  555. white-space: nowrap;
  556. }
  557. }
  558. .condition-item1 {
  559. display: flex;
  560. span {
  561. margin-left: 5px;
  562. display: inline-block;
  563. padding: 8px 8px;
  564. background: rgb(213, 222, 255);;
  565. color: rgba(37,80,162,1);
  566. border-radius: 4px;
  567. cursor: pointer; // 添加指针样式
  568. transition: all 0.3s; // 添加过渡效果
  569. height: 40px;
  570. }
  571. }
  572. .condition-header-content {
  573. display: flex;
  574. justify-content: space-between;
  575. align-items: center;
  576. width: 100%;
  577. .delete-icon {
  578. color: #F56C6C;
  579. cursor: pointer;
  580. font-size: 16px;
  581. &:hover {
  582. opacity: 0.8;
  583. }
  584. }
  585. }
  586. .result-container{
  587. width: 100%;
  588. border: 1px solid #EBEEF5;
  589. border-radius: 4px;
  590. background: #f5f7fa;
  591. margin-top: 10px;
  592. }
  593. .condition-header {
  594. display: flex;
  595. // justify-content: space-between;
  596. align-items: center;
  597. padding: 10px;
  598. border-bottom: 1px solid #EBEEF5;
  599. span {
  600. font-weight: bold;
  601. margin-left: 10px;
  602. }
  603. }
  604. .link-list{
  605. max-height: 350px;
  606. overflow-y: auto;
  607. padding: 10px;
  608. font-weight: bold;
  609. .link-item{
  610. display: flex;
  611. align-items: center;
  612. padding: 10px;
  613. background-color: white;
  614. border-radius: 10px;
  615. cursor: pointer; // 添加指针样式
  616. position: relative; // 添加相对定位
  617. margin-bottom: 10px;
  618. &.clicked {
  619. background-color: #e0e0e0; // 点击时的背景色
  620. }
  621. .el-icon-close {
  622. position: absolute; // 绝对定位
  623. top: 30%; // 垂直居中
  624. right: 10px; // 距离右侧10px
  625. transform: translateY(-50%); // 垂直方向上的偏移量,确保图标垂直居中
  626. color: #F56C6C; // 删除图标的颜色
  627. cursor: pointer; // 添加指针样式
  628. font-size: 16px; // 图标大小
  629. &:hover {
  630. opacity: 0.8; // 悬停效果
  631. }
  632. }
  633. .link-name{
  634. flex-shrink: 0;
  635. background-color: rgb(167, 224, 218);
  636. color: rgba(46, 123, 115, 1);
  637. border-radius: 5px;
  638. text-align: center;
  639. padding:8px;
  640. margin-right: 15px;
  641. }
  642. .code-list{
  643. margin-left: 15px;
  644. display: flex;
  645. overflow-x: auto;
  646. font-weight: bold;
  647. .code-item {
  648. // display: flex;
  649. margin-bottom: 10px;
  650. flex-shrink: 0;
  651. margin-left: 5px;
  652. padding:8px;
  653. background: rgb(213, 222, 255);;
  654. color: #409EFF;
  655. border-radius: 4px;
  656. transition: all 0.3s; // 添加过渡效果
  657. height: 50px;
  658. .code-title{
  659. color: black;
  660. margin-bottom: 10px;
  661. }
  662. .code-detail{
  663. color: rgba(37,80,162,1);
  664. }
  665. }
  666. }
  667. }
  668. }
  669. </style>
  670. <style lang="scss">
  671. .dialog-set {
  672. .el-drawer__header{
  673. padding: 0px;
  674. background: rgb(37, 80, 162);
  675. font-family: 16px;
  676. }
  677. // ...现有样式...
  678. .el-drawer {
  679. height: 95% !important; // 增加抽屉高度
  680. .el-drawer__body {
  681. height: calc(100% - 100px); // 减去头部和底部的高度
  682. overflow-y: auto; // 添加滚动
  683. padding: 20px;
  684. }
  685. .dialog-footer {
  686. position: absolute;
  687. bottom: 0;
  688. width: 100%;
  689. padding: 10px 20px;
  690. text-align: center;
  691. background: white;
  692. border-top: 1px solid #EBEEF5;
  693. }
  694. }
  695. }
  696. </style>