scale-table.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. <style lang="less" scoped>
  2. .scaleTable {
  3. min-height: 100px;
  4. .table_box {
  5. padding: 0 30px;
  6. }
  7. .btn_box {
  8. width: 100%;
  9. height: 100%;
  10. display: flex;
  11. align-items: center;
  12. justify-content: space-around;
  13. .btn_div {
  14. flex: 1;
  15. display: flex;
  16. align-items: center;
  17. justify-content: center;
  18. }
  19. img {
  20. width: 16px;
  21. height: 16px;
  22. cursor: pointer;
  23. }
  24. }
  25. .table_select_btn {
  26. display: flex;
  27. flex-direction: column;
  28. justify-content: center;
  29. align-items: center;
  30. /deep/ .el-button--text {
  31. padding: 3px 0;
  32. margin: 0;
  33. }
  34. }
  35. /deep/.el-input--mini .el-input__inner {
  36. width: 100%;
  37. }
  38. /deep/.el-table th {
  39. padding: 0;
  40. }
  41. }
  42. /deep/.el-table th,
  43. .el-table tr {
  44. height: 50px;
  45. background: #e3eaf4;
  46. }
  47. /deep/.el-table th {
  48. padding: 0;
  49. }
  50. .custom_table_header {
  51. vertical-align: middle;
  52. &::before {
  53. content: "*";
  54. color: red;
  55. font-size: 12px;
  56. margin-right: 4px;
  57. }
  58. }
  59. /deep/.el-form-item--mini.el-form-item,
  60. .el-form-item--small.el-form-item {
  61. padding: 18px 0;
  62. position: static;
  63. }
  64. /deep/ .el-textarea__inner {
  65. overflow-y: hidden;
  66. }
  67. .cell_center_box {
  68. /deep/ .el-input__inner {
  69. // width: 40px;
  70. text-align: center;
  71. }
  72. }
  73. /deep/.el-select--mini {
  74. width: 100%;
  75. }
  76. /deep/ .el-input--mini {
  77. font-size: 14px;
  78. }
  79. /deep/ .el-form-item.is-success .el-input__inner,
  80. .el-form-item.is-success .el-textarea__inner {
  81. border-color: #c9c9c9 !important;
  82. }
  83. /deep/ .el-form-item.is-success .el-textarea__inner {
  84. border-color: #c9c9c9 !important;
  85. }
  86. /deep/ .el-form-item.is-success .el-textarea__inner {
  87. border-color: #c9c9c9 !important;
  88. }
  89. </style>
  90. <template>
  91. <div class="scaleTable" :id="`scaleTableRef[${tableIndex}]`">
  92. <div class="table_box">
  93. <el-table
  94. v-if="tableShow"
  95. :data="tableData"
  96. header-row-class-name="header_row_class_name"
  97. border
  98. style="width: 100%; margin: 20px 0"
  99. :span-method="objectSpanMethod"
  100. :ref="`scaleTableRef[${tableIndex}]`"
  101. >
  102. <el-table-column prop="issueId" label="组" width="70px">
  103. <template slot-scope="scope">
  104. <div class="btn_box">
  105. <div class="btn_div">
  106. <img
  107. @click="
  108. $emit('CHANGE_TABLE_ROW', {
  109. type: 1,
  110. tableIndex,
  111. rowIndex: scope.$index,
  112. groupId: scope.row.groupId
  113. })
  114. "
  115. src="../../../images/add-new-rule-sub.png"
  116. alt=""
  117. />
  118. </div>
  119. <div
  120. class="btn_div"
  121. v-if="imposeRestrictionsRemoveOnGroup(scope.row.groupId)"
  122. >
  123. <img
  124. @click="
  125. $emit('CHANGE_TABLE_ROW', {
  126. type: -1,
  127. tableIndex,
  128. groupId: scope.row.groupId
  129. })
  130. "
  131. src="../../../images/add-new-rule-del.png"
  132. alt=""
  133. />
  134. </div>
  135. </div>
  136. </template>
  137. </el-table-column>
  138. <el-table-column prop="groupId" label="问题" width="70px">
  139. <template slot-scope="scope">
  140. <div class="btn_box">
  141. <div class="btn_div">
  142. <img
  143. @click="
  144. $emit('CHANGE_TABLE_ROW', {
  145. type: 2,
  146. tableIndex,
  147. rowIndex: scope.$index,
  148. groupId: scope.row.groupId,
  149. issueId: scope.row.issueId
  150. })
  151. "
  152. src="../../../images/add-new-rule-sub.png"
  153. alt=""
  154. />
  155. </div>
  156. <div
  157. class="btn_div"
  158. v-if="
  159. imposeRestrictionsRemoveOnIssue({
  160. groupId: scope.row.groupId,
  161. issueId: scope.row.issueId
  162. })
  163. "
  164. >
  165. <img
  166. @click="
  167. $emit('CHANGE_TABLE_ROW', {
  168. type: -2,
  169. tableIndex,
  170. issueId: scope.row.issueId
  171. })
  172. "
  173. src="../../../images/add-new-rule-del.png"
  174. alt=""
  175. />
  176. </div>
  177. </div>
  178. </template>
  179. </el-table-column>
  180. <el-table-column prop="two_selectType" label="选择" width="70px">
  181. <template slot-scope="scope">
  182. <div class="table_select_btn">
  183. <el-button
  184. @click="handleSelectTypeBtn(scope.$index, 1)"
  185. :style="scope.row.two_selectType != 1 ? { color: '#999' } : ''"
  186. type="text"
  187. >单选</el-button
  188. >
  189. <el-button
  190. :style="scope.row.two_selectType != 2 ? { color: '#999' } : ''"
  191. @click="handleSelectTypeBtn(scope.$index, 2)"
  192. type="text"
  193. >多选</el-button
  194. >
  195. </div>
  196. </template>
  197. </el-table-column>
  198. <el-table-column prop="two_content" label="问题内容">
  199. <template slot="header">
  200. <div class="custom_table_header">问题内容</div>
  201. </template>
  202. <template slot-scope="scope">
  203. <el-form-item
  204. :prop="`klScaleParent[${tableIndex}].klScaleSaveGroup[${scope.$index}].two_content`"
  205. :rules="rules.issueContent"
  206. >
  207. <el-input
  208. :ref="`klScaleParent[${tableIndex}].klScaleSaveGroup[${scope.$index}].two_content`"
  209. type="textarea"
  210. rows="1"
  211. :autosize="true"
  212. resize="none"
  213. v-model="scope.row.two_content"
  214. clearable
  215. maxlength="300"
  216. placeholder="请输入"
  217. ></el-input>
  218. </el-form-item>
  219. </template>
  220. </el-table-column>
  221. <el-table-column
  222. prop="two_factor"
  223. label="系数"
  224. width="90px"
  225. v-if="tableResultType === 1"
  226. >
  227. <template slot-scope="scope">
  228. <div class="cell_center_box">
  229. <el-form-item
  230. :prop="`klScaleParent[${tableIndex}].klScaleSaveGroup[${scope.$index}].two_factor`"
  231. :rules="rules.issueFactor"
  232. >
  233. <el-input
  234. type="number"
  235. v-model.number="scope.row.two_factor"
  236. placeholder="请输入"
  237. ></el-input>
  238. </el-form-item>
  239. </div>
  240. </template>
  241. </el-table-column>
  242. <el-table-column
  243. prop="two_constant"
  244. label="常数"
  245. width="90px"
  246. v-if="tableResultType === 1"
  247. >
  248. <template slot-scope="scope">
  249. <div class="cell_center_box">
  250. <el-form-item
  251. :prop="`klScaleParent[${tableIndex}].klScaleSaveGroup[${scope.$index}].two_constant`"
  252. :rules="rules.issueConstant"
  253. >
  254. <el-input
  255. type="number"
  256. v-model.number="scope.row.two_constant"
  257. placeholder="请输入"
  258. style="text-align: center"
  259. ></el-input>
  260. </el-form-item>
  261. </div>
  262. </template>
  263. </el-table-column>
  264. <el-table-column prop="issueId" label="选项个数" width="80px">
  265. <template slot-scope="scope">
  266. <div>
  267. {{ optionLength(scope.row.issueId) }}
  268. </div>
  269. </template>
  270. </el-table-column>
  271. <el-table-column prop="orderNo" label="选项" width="70px">
  272. <template slot-scope="scope">
  273. <div class="btn_box">
  274. <div class="btn_div">
  275. <img
  276. @click="
  277. $emit('CHANGE_TABLE_ROW', {
  278. type: 3,
  279. tableIndex,
  280. rowIndex: scope.$index,
  281. groupId: scope.row.groupId,
  282. issueId: scope.row.issueId
  283. })
  284. "
  285. src="../../../images/add-new-rule-sub.png"
  286. alt=""
  287. />
  288. </div>
  289. <div
  290. class="btn_div"
  291. v-if="imposeRestrictionsRemoveOnOption(scope.row.issueId)"
  292. >
  293. <img
  294. @click="
  295. $emit('CHANGE_TABLE_ROW', {
  296. type: -3,
  297. tableIndex,
  298. rowIndex: scope.$index
  299. })
  300. "
  301. src="../../../images/add-new-rule-del.png"
  302. alt=""
  303. />
  304. </div>
  305. </div>
  306. </template>
  307. </el-table-column>
  308. <el-table-column
  309. prop="content"
  310. label="选项内容"
  311. :width="tableResultType === 1 ? '200px' : ''"
  312. >
  313. <template slot="header">
  314. <div class="custom_table_header">选项内容</div>
  315. </template>
  316. <template slot-scope="scope">
  317. <el-form-item
  318. :prop="`klScaleParent[${tableIndex}].klScaleSaveGroup[${scope.$index}].content`"
  319. :rules="rules.content"
  320. >
  321. <el-input
  322. :ref="`klScaleParent[${tableIndex}].klScaleSaveGroup[${scope.$index}].content`"
  323. type="textarea"
  324. rows="1"
  325. :autosize="true"
  326. resize="none"
  327. v-model="scope.row.content"
  328. clearable
  329. maxlength="300"
  330. placeholder="请输入"
  331. ></el-input>
  332. </el-form-item>
  333. </template>
  334. </el-table-column>
  335. <el-table-column
  336. prop="content"
  337. label="编码"
  338. :width="tableResultType === 2 ? '200px' : ''"
  339. v-if="tableResultType === 1"
  340. >
  341. <template slot-scope="scope">
  342. <el-form-item
  343. ><el-select
  344. clearable
  345. remote
  346. filterable
  347. :remote-method="searchRuleCode"
  348. @focus="ruleCodeFocus(scope.$index)"
  349. v-model.trim="scope.row.ruleCode"
  350. >
  351. <el-option
  352. v-for="item in scope.row.ruleCodeList"
  353. :key="item.code"
  354. :value="item.code"
  355. >
  356. <span>{{ item.name }}</span>
  357. <span>({{ item.code }})</span>
  358. </el-option>
  359. </el-select>
  360. </el-form-item>
  361. </template>
  362. </el-table-column>
  363. <el-table-column
  364. prop="content"
  365. label="分值"
  366. v-if="tableResultType === 1"
  367. >
  368. <template slot="header">
  369. <div class="custom_table_header">分值</div>
  370. </template>
  371. <template slot-scope="scope">
  372. <el-form-item
  373. :prop="`klScaleParent[${tableIndex}].klScaleSaveGroup[${scope.$index}].score`"
  374. :rules="rules.score"
  375. >
  376. <el-input
  377. type="number"
  378. maxlength="6"
  379. v-model.number="scope.row.score"
  380. clearable
  381. placeholder="请输入"
  382. ></el-input>
  383. </el-form-item>
  384. </template>
  385. </el-table-column>
  386. <el-table-column
  387. prop="result"
  388. label="结果"
  389. width="200px"
  390. v-if="tableResultType === 2"
  391. >
  392. <template slot="header">
  393. <div class="custom_table_header">结果</div>
  394. </template>
  395. <template slot-scope="scope">
  396. <el-form-item
  397. :prop="`klScaleParent[${tableIndex}].klScaleSaveGroup[${scope.$index}].result`"
  398. :rules="rules.result"
  399. >
  400. <el-input
  401. :ref="`klScaleParent[${tableIndex}].klScaleSaveGroup[${scope.$index}].result`"
  402. type="textarea"
  403. rows="1"
  404. :autosize="true"
  405. resize="none"
  406. v-model="scope.row.result"
  407. clearable
  408. maxlength="300"
  409. placeholder="请输入"
  410. ></el-input>
  411. </el-form-item>
  412. </template>
  413. </el-table-column>
  414. <el-table-column
  415. prop="pushInfo"
  416. label="建议"
  417. v-if="tableResultType === 2"
  418. >
  419. <template slot-scope="scope">
  420. <el-form-item
  421. :prop="`klScaleParent[${tableIndex}].klScaleSaveGroup[${scope.$index}].pushInfo`"
  422. :rules="rules.pushInfo"
  423. >
  424. <el-input
  425. :ref="`klScaleParent[${tableIndex}].klScaleSaveGroup[${scope.$index}].pushInfo`"
  426. type="textarea"
  427. rows="1"
  428. :autosize="true"
  429. resize="none"
  430. v-model="scope.row.pushInfo"
  431. clearable
  432. maxlength="500"
  433. placeholder="请输入"
  434. ></el-input>
  435. </el-form-item>
  436. </template>
  437. </el-table-column>
  438. </el-table>
  439. </div>
  440. </div>
  441. </template>
  442. <script>
  443. import rules from "./rules";
  444. import api from "@api/knowledgeTree.js";
  445. export default {
  446. name: "scaleTable",
  447. data() {
  448. return {
  449. tableShow: true,
  450. rules: rules,
  451. ruleCodeIndex: null
  452. };
  453. },
  454. methods: {
  455. resizeTable() {
  456. setTimeout(() => {
  457. this.tableData.forEach((item, index) => {
  458. this.$refs[
  459. `klScaleParent[${this.tableIndex}].klScaleSaveGroup[${index}].content`
  460. ] &&
  461. this.$refs[
  462. `klScaleParent[${this.tableIndex}].klScaleSaveGroup[${index}].content`
  463. ].resizeTextarea();
  464. this.$refs[
  465. `klScaleParent[${this.tableIndex}].klScaleSaveGroup[${index}].two_content`
  466. ] &&
  467. this.$refs[
  468. `klScaleParent[${this.tableIndex}].klScaleSaveGroup[${index}].two_content`
  469. ].resizeTextarea();
  470. this.$refs[
  471. `klScaleParent[${this.tableIndex}].klScaleSaveGroup[${index}].result`
  472. ] &&
  473. this.$refs[
  474. `klScaleParent[${this.tableIndex}].klScaleSaveGroup[${index}].result`
  475. ].resizeTextarea();
  476. this.$refs[
  477. `klScaleParent[${this.tableIndex}].klScaleSaveGroup[${index}].pushInfo`
  478. ] &&
  479. this.$refs[
  480. `klScaleParent[${this.tableIndex}].klScaleSaveGroup[${index}].pushInfo`
  481. ].resizeTextarea();
  482. });
  483. }, 500);
  484. },
  485. ruleCodeFocus(index) {
  486. this.ruleCodeIndex = index;
  487. },
  488. searchRuleCode(val) {
  489. api
  490. .searchRuleCode({ name: val === "" ? null : val, type: 1 })
  491. .then((res) => {
  492. if (res.data.code == "0") {
  493. this.$emit(
  494. "CHANGE_FORM_DATA",
  495. this.tableIndex,
  496. this.ruleCodeIndex,
  497. "ruleCodeList",
  498. res.data.data
  499. );
  500. }
  501. });
  502. },
  503. addGroup() {},
  504. // 单选、多选
  505. handleSelectTypeBtn(index, type) {
  506. this.$emit(
  507. "CHANGE_FORM_DATA",
  508. this.tableIndex,
  509. index,
  510. "two_selectType",
  511. type
  512. );
  513. },
  514. // 计算表格选项内容的值
  515. optionLength(val) {
  516. if (val || val === 0) {
  517. const accordWithThis = this.tableData.filter(
  518. (item) => item.issueId === val
  519. );
  520. return accordWithThis.length ? accordWithThis.length : 0;
  521. }
  522. },
  523. // 表格合并单元格逻辑
  524. getSpanArr(data) {
  525. this.spanArr = [];
  526. this.spanArr1 = [];
  527. for (var i = 0; i < data.length; i++) {
  528. if (i === 0) {
  529. // 如果是第一条记录(即索引是0的时候),向数组中加入1
  530. /** *
  531. * 例子:
  532. * name:1
  533. * name:1
  534. * name:2
  535. * name:2
  536. * 最终结果:spanArr = [2,0,2,0]
  537. */
  538. this.spanArr.push(1);
  539. this.pos = 0;
  540. this.spanArr1.push(1);
  541. this.pos1 = 0;
  542. } else {
  543. if (data[i].groupId === data[i - 1].groupId) {
  544. // 如果remark相等就累加,并且push 0
  545. this.spanArr[this.pos] += 1;
  546. this.spanArr.push(0);
  547. } else {
  548. // 不相等push 1,并且pos 要换成当前下标
  549. this.spanArr.push(1);
  550. this.pos = i;
  551. }
  552. if (data[i].issueId === data[i - 1].issueId) {
  553. // 如果remark相等就累加,并且push 0
  554. this.spanArr1[this.pos1] += 1;
  555. this.spanArr1.push(0);
  556. } else {
  557. // 不相等push 1,并且pos 要换成当前下标
  558. this.spanArr1.push(1);
  559. this.pos1 = i;
  560. }
  561. }
  562. }
  563. },
  564. objectSpanMethod({ row, column, rowIndex, columnIndex }) {
  565. if (columnIndex == 0) {
  566. const _row = this.spanArr[rowIndex];
  567. const _col = _row > 0 ? 1 : 0;
  568. return {
  569. rowspan: _row,
  570. colspan: _col
  571. };
  572. } else if (
  573. column.label == "问题" ||
  574. column.label == "选择" ||
  575. column.label == "问题内容" ||
  576. column.label == "系数" ||
  577. column.label == "常数" ||
  578. column.label == "选项个数"
  579. ) {
  580. const _row = this.spanArr1[rowIndex];
  581. const _col = _row > 0 ? 1 : 0;
  582. return {
  583. rowspan: _row,
  584. colspan: _col
  585. };
  586. }
  587. },
  588. // 删除组限制:剩余一组时隐藏删除按钮
  589. imposeRestrictionsRemoveOnGroup(groupId) {
  590. // 查找有没有其他组存在 如果为0的话则不存在
  591. const otherGroupLength = this.tableData.filter(
  592. (item) => item.groupId !== groupId
  593. ).length;
  594. return otherGroupLength;
  595. },
  596. // 删除问题限制:该组剩余一个问题时隐藏删除按钮
  597. imposeRestrictionsRemoveOnIssue(val) {
  598. const { groupId, issueId } = val;
  599. // 获取该组所有的issus
  600. const thisGroups = this.tableData.filter(
  601. (item) => item.groupId === groupId
  602. );
  603. // 查找该组有没有其他问题 otherIssueLength为0表示只有当前一个问题存在 所以隐藏删除按钮
  604. const otherIssueLength = thisGroups.filter(
  605. (item) => item.issueId !== issueId
  606. ).length;
  607. if (otherIssueLength) {
  608. return true;
  609. }
  610. return false;
  611. },
  612. // 删除选项限制:该问题剩余一个选项时隐藏删除按钮
  613. imposeRestrictionsRemoveOnOption(issueId) {
  614. // 查找同组的问题,如果只有一个问题则隐藏删除按钮
  615. const thisOptionByissueIdLenth = this.tableData.filter(
  616. (item) => item.issueId === issueId
  617. ).length;
  618. if (thisOptionByissueIdLenth > 1) {
  619. return true;
  620. }
  621. return false;
  622. }
  623. },
  624. created() {
  625. this.getSpanArr(this.tableData);
  626. },
  627. watch: {
  628. tableData: {
  629. handler() {
  630. this.getSpanArr(this.tableData);
  631. },
  632. deep: true
  633. },
  634. tableResultType() {
  635. this.tableShow = false;
  636. setTimeout(() => {
  637. this.tableShow = true;
  638. });
  639. }
  640. },
  641. props: {
  642. tableData: {
  643. default: []
  644. },
  645. tableIndex: {
  646. required: true
  647. },
  648. tableResultType: {
  649. required: true,
  650. default: 2
  651. }
  652. }
  653. };
  654. </script>