当前位置:   article > 正文

基于element UI 显示编辑表格_elementui 可编辑表格

elementui 可编辑表格

基于element ui 实现编辑表格,支持文本、下拉、日期、链接等形式,实现了回车到下一个输入框,每一个回车都可以触发业务回车事件,例如计算小计;最后一格回车可以触发自动增行等效果。

实现效果如下

组件入口 index.vue

  1. <template>
  2. <my-form :model="tableDataTmp" ref="tableForm" class="edit-table-dialog" @submit.native.prevent :class="{'edit-table-disabled': disabled}">
  3. <el-row justify="end" type="flex">
  4. <div class="title-tag" v-if="title">{{ title }}</div>
  5. <slot name='btn-more-before'></slot>
  6. <el-button type="primary" plain size="small" icon="el-icon-plus" @click="addRow" v-if="!disabled && (options.showAddBtn==undefined || options.showAddBtn==null || options.showAddBtn)">新增行</el-button>
  7. <el-button type="primary" plain size="small" icon="el-icon-delete" @click="deleteRow" v-if="!disabled && (options.showDelBtn==undefined || options.showDelBtn==null || options.showDelBtn)">删除行</el-button>
  8. <slot name="btn-more"></slot>
  9. </el-row>
  10. <el-table ref="editTableRef" border :data="tableDataTmp.tableData" row-key="__rowKey" @selection-change="selectionChange" @select="handleSelect" class="edit-table" :row-class-name="tableRowClassName" :height="height" empty-text=" ">
  11. <template v-for="item in columnData">
  12. <column ref="columnRef" :key="item.label" :columnInfo="item" :options="options" :tableRules="tableRules" :rowKey="rowKey" :defaultShowEdit="defaultShowEdit"
  13. :selectList="selectList" :isDiff="isDiff" :disabled="disabled" :editIndex="editIndex" @editFocus="editFocus" @keyupEnter="keyupEnter" @onfocus="onfocus" @link="clickLink"></column>
  14. </template>
  15. </el-table>
  16. <table-dialog ref="tableDialogRef" :open.sync="open" :tabName="tabName" :tabParams="tabParams" :hideColumns="hideColumns" @oncheck="oncheck"></table-dialog>
  17. </my-form>
  18. </template>
  19. <script>
  20. import MyForm from './form/form.vue'
  21. import Column from './column.vue'
  22. import TableDialog from '@/components/TableDialog/index.vue'
  23. export default {
  24. name: "EditTable",
  25. components: { TableDialog, MyForm, Column },
  26. props: {
  27. height: {
  28. type: [String, Number]
  29. },
  30. columnData: {
  31. type: Array,
  32. default: () => {
  33. return []
  34. }
  35. },
  36. emptyRow: {
  37. type: Object,
  38. default: () => {
  39. return {}
  40. }
  41. },
  42. tableData: {
  43. type: Array,
  44. default: () => {
  45. return []
  46. }
  47. },
  48. tableRules: {
  49. type: Object,
  50. default: () => {
  51. return {}
  52. }
  53. },
  54. options: {
  55. type: Object,
  56. default: () => {
  57. return {
  58. showAddBtn: true,
  59. showDelBtn: true
  60. }
  61. }
  62. },
  63. rowKey: {
  64. type: [String, Function]
  65. },
  66. defaultShowEdit: {
  67. type: Boolean,
  68. default: false
  69. },
  70. // 是否显示比对
  71. isDiff: {
  72. type: Boolean,
  73. default: false
  74. },
  75. disabled: {
  76. type: Boolean,
  77. default: false
  78. },
  79. title: {
  80. type: String,
  81. default: ''
  82. },
  83. },
  84. data() {
  85. return {
  86. tableDataTmp: {
  87. tableData: []
  88. },
  89. // 末级列数据
  90. columnDataLast: [],
  91. tabName: null,
  92. tabParams: {},
  93. hideColumns: null,
  94. editIndex: '', // 当前编辑单元格
  95. open: false,
  96. chooseData: {},
  97. selections: [],
  98. rowids: [],
  99. selectList: [],
  100. isEnter: false // 是否回车
  101. }
  102. },
  103. created() {},
  104. watch: {
  105. 'tableData': {
  106. handler() {
  107. let rowKeyTmp = new Date().getTime()
  108. this.tableData.forEach((tb, index) => {
  109. tb.rowEdit = (tb.rowEdit === undefined || tb.rowEdit === null) ? true : tb.rowEdit
  110. if (!tb.__rowKey) {
  111. tb.__rowKey = tb[this.rowKey] || (rowKeyTmp+'_'+index)
  112. }
  113. });
  114. this.tableDataTmp = { tableData: this.tableData }
  115. },
  116. immediate: true
  117. },
  118. 'columnData': {
  119. handler() {
  120. let columnDataLast = []
  121. let func = (list, level) => {
  122. list.forEach((item, index)=>{
  123. if (item.children && item.children.length>0) {
  124. func(item.children, level+'_'+index)
  125. } else {
  126. columnDataLast.push({ ...item, level__: level+'_'+index })
  127. // 如果没有设置renderHeader,且是必填字段,添加必填星号
  128. if (this.tableRules[item.prop] && !item.renderHeader) {
  129. let valIndex = this.tableRules[item.prop].findIndex((validate)=>{
  130. return validate.required
  131. })
  132. if (valIndex > -1) {
  133. item.renderHeader = (h, data)=>{
  134. return [
  135. h('span', { style: 'color: #F56C6C;margin-right: 5px;' }, '*'),
  136. h('span', item.label)
  137. ]
  138. }
  139. }
  140. }
  141. // 如果是dataSelect类型,预处理数据
  142. if (item.editType === 'dataSelect') {
  143. // let _options = { ...item.selectData, headers: { hideMessage: true } }
  144. // request(_options).then((rsp)=>{
  145. // this.$set(this.cacheSelectData, item.prop, rsp.data)
  146. // })
  147. }
  148. }
  149. })
  150. }
  151. func(this.columnData, 'a')
  152. this.columnDataLast = columnDataLast
  153. },
  154. deep: true,
  155. immediate: true
  156. }
  157. },
  158. methods: {
  159. // 表格行样式
  160. tableRowClassName({row, rowIndex}) {
  161. if (!this.isDiff) return ''
  162. if (row.DELROW) {
  163. return 'warning-row';
  164. } else if (row.ADDROW) {
  165. return 'success-row';
  166. }
  167. return '';
  168. },
  169. addRow() {
  170. let index = this.tableDataTmp.tableData.length
  171. let row = { __rowKey: new Date().getTime() }
  172. if(this.emptyRow) row = { ...row, ...this.emptyRow }
  173. this.tableDataTmp.tableData.splice(index, 0, row)
  174. // this.$emit('update:tableData', this.tableDataTmp.tableData)
  175. },
  176. deleteRow() {
  177. if (!this.rowids || this.rowids.length==0) {
  178. this.$modal.msgError("请选择要删除的行");
  179. return
  180. }
  181. this.rowids.forEach((id)=>{
  182. let index = this.tableDataTmp.tableData.findIndex(item=>(item.__rowKey==id))
  183. this.tableDataTmp.tableData.splice(index, 1)
  184. })
  185. // this.$emit('update:tableData', this.tableDataTmp.tableData)
  186. },
  187. selectionChange (selections) {
  188. this.selections = selections
  189. this.rowids = this.selections.map(item=>item.__rowKey)
  190. this.$emit('selection-change', selections)
  191. },
  192. handleSelect(selection, row) {
  193. this.$emit('select', selection, row)
  194. },
  195. getSelection () {
  196. return this.selections
  197. },
  198. selectSame (sameList, checked) {
  199. this.$nextTick(()=>{
  200. sameList.forEach(item=>{
  201. this.$refs.editTableRef.toggleRowSelection(item, checked)
  202. })
  203. })
  204. },
  205. onfocus(index_) {
  206. setTimeout(async () => {
  207. if (this.disabled) return false
  208. this.editIndex = index_
  209. const { rowIndex, colIndex, row, columnConfig, columnValue } = this.getCommonData()
  210. if (columnConfig.editType === 'select') {
  211. row[columnConfig.valprop || columnConfig.prop] = null
  212. this.selectList = await columnConfig.selectData.getData(row)
  213. row[columnConfig.valprop || columnConfig.prop] = columnValue
  214. }
  215. this.$nextTick(() => {
  216. const editEl = this.getElementRef(rowIndex, colIndex)
  217. if (columnConfig.editType === 'select') {
  218. editEl.toggleMenu()
  219. } else {
  220. editEl && editEl.focus()
  221. }
  222. })
  223. }, 200) // 日期回车下一个是下拉时,触发了下拉的回车事件,触发了两次回车
  224. },
  225. getElementRef (rowIndex, colIndex) {
  226. let columnConfig = this.columnDataLast[colIndex]
  227. let levels = columnConfig.level__.split('_')
  228. let editEl = this
  229. for(let n = 1;n<levels.length;n++) {
  230. editEl = editEl.$refs['columnRef'][parseInt(levels[n])]
  231. }
  232. editEl = editEl.$refs['flaga-' + rowIndex + '-' + columnConfig.prop].$children[1]
  233. // if (columnConfig.editType === 'dataSelect') {
  234. // editEl = editEl.$children[0]
  235. // }
  236. return editEl
  237. },
  238. getCommonData () {
  239. let indexs = this.editIndex.split('-')
  240. let rowIndex = parseInt(indexs[0])
  241. let colProp = indexs[1]
  242. let colIndex = this.columnDataLast.findIndex((item)=>item.prop===colProp)
  243. let columnConfig = this.columnDataLast[colIndex]
  244. let row = this.tableDataTmp.tableData[rowIndex]
  245. let columnValue = columnConfig.editType === 'select' ? row[columnConfig.valprop || columnConfig.prop] : row[columnConfig.prop]
  246. return {rowIndex, colProp, colIndex, columnConfig, row, columnValue}
  247. },
  248. // 进入下一个可编辑单元格
  249. nextStep() {
  250. if (!this.editIndex) {
  251. return false
  252. }
  253. let { rowIndex, colIndex, columnConfig } = this.getCommonData()
  254. let nextColIndex = -1
  255. // 查找当前行下一个可编辑项
  256. if (colIndex < this.columnDataLast.length - 1) {
  257. for (let ind = colIndex + 1; ind < this.columnDataLast.length; ind++) {
  258. if (this.columnDataLast[ind].edit && this.columnDataLast[ind].editType !== 'link') {
  259. nextColIndex = ind
  260. columnConfig = this.columnDataLast[ind]
  261. break
  262. }
  263. }
  264. }
  265. let editEl = this.getElementRef(rowIndex, colIndex)
  266. // 找到下一个编辑列
  267. if (nextColIndex !== -1) {
  268. editEl.blur()
  269. this.onfocus(rowIndex + '-' + columnConfig.prop)
  270. }
  271. // 未找到判断是否有下一行,有下一行进入下一行第一个
  272. else if (rowIndex < this.tableDataTmp.tableData.length - 1) {
  273. let nextRowIndex = this.tableDataTmp.tableData.findIndex((row, index)=>{
  274. return index > rowIndex && row.rowEdit
  275. })
  276. if (nextRowIndex > -1) {
  277. for (let ind = 0; ind < this.columnDataLast.length; ind++) {
  278. if (this.columnDataLast[ind].edit && this.columnDataLast[ind].editType !== 'link') {
  279. nextColIndex = ind
  280. columnConfig = this.columnDataLast[ind]
  281. break
  282. }
  283. }
  284. // const editEl = this.getElementRef(rowIndex, colIndex)
  285. editEl.blur()
  286. this.onfocus(nextRowIndex + '-' + columnConfig.prop)
  287. }
  288. }
  289. },
  290. // 聚焦
  291. editFocus(index_) {
  292. this.editIndex = index_
  293. // let {rowIndex, colIndex, columnConfig, row, columnValue} = this.getCommonData()
  294. // let editEl = this.getElementRef(rowIndex, colIndex)
  295. // if (columnConfig.editType === 'select') {
  296. // editEl.toggleMenu()
  297. // } else {
  298. // editEl.focus()
  299. // }
  300. },
  301. next () {
  302. let {rowIndex, colIndex, columnConfig, row, columnValue} = this.getCommonData()
  303. if (columnConfig.editType === 'date') {
  304. this.nextStep()
  305. return
  306. } else if (columnConfig.editType === 'dialog') {
  307. this.nextStep()
  308. } else {
  309. this.nextStep()
  310. }
  311. },
  312. // 回车事件
  313. keyupEnter(isNext=true, e) {
  314. // console.log('====', isNext, this.isEnter, e)
  315. if (isNext) {
  316. this.isEnter = true
  317. } else if (!isNext) {
  318. let curField = this.getCommonData()
  319. // 展示下拉项时,不要执行操作 | dialog失焦时不执行操作
  320. if (curField.columnConfig.editType === 'select' && e == true) {
  321. return false
  322. } else if (curField.columnConfig.editType === 'dialog') {
  323. return false
  324. }
  325. // 如果当前已标记为回车,不执行接下来的操作
  326. if (this.isEnter) {
  327. this.isEnter = false
  328. return
  329. }
  330. // 下面这段逻辑暂时好像不需要
  331. // else {
  332. // let curField = this.getCommonData()
  333. // if (curField.columnConfig.editType === 'select' && ) {
  334. // // e===false && (this.editIndex=null)
  335. // } else {
  336. // this.editIndex = null
  337. // }
  338. // }
  339. }
  340. // console.log('====keyupEnter', this.editIndex)
  341. let {rowIndex, colIndex, columnConfig, row, columnValue} = this.getCommonData()
  342. // 如果是弹框,直接弹框
  343. if (columnConfig.editType === 'dialog') {
  344. // 单元格内容
  345. this.tabName = columnConfig.dialogData.tabName
  346. let tabParams = { [columnConfig.prop]: columnValue }
  347. // 解析传入参数
  348. let tabParamsIn = {}
  349. if (columnConfig.dialogData.tabParams && typeof columnConfig.dialogData.tabParams == 'function') {
  350. tabParamsIn = columnConfig.dialogData.tabParams(row)
  351. } else if (columnConfig.dialogData.tabParams) {
  352. tabParamsIn = columnConfig.dialogData.tabParams
  353. }
  354. tabParams = {...tabParamsIn, ...tabParams}
  355. this.tabParams = tabParams
  356. this.hideColumns = columnConfig.dialogData.hideColumns
  357. this.open = true
  358. this.$nextTick(()=>{
  359. this.$refs.tableDialogRef.focusDialog()
  360. })
  361. return
  362. } else if (columnConfig.editType === 'select') {
  363. let current = this.selectList.find(item=>item[columnConfig.selectData.value] == columnValue)
  364. if (!current) current = {}
  365. this.chooseData = current
  366. let updateFields = (columnConfig.selectData ? columnConfig.selectData.updateFields : null)
  367. if (!updateFields && columnConfig.selectData) {
  368. let defaultUpdateFields = {}
  369. if (columnConfig.valprop) {
  370. defaultUpdateFields = { [columnConfig.valprop]: columnConfig.selectData.value, [columnConfig.prop]: columnConfig.selectData.label }
  371. } else {
  372. defaultUpdateFields = { [columnConfig.prop]: columnConfig.selectData.value }
  373. }
  374. updateFields = defaultUpdateFields
  375. }
  376. this.updateChooseData(rowIndex, updateFields, true)
  377. }
  378. this.validateNext(isNext)
  379. },
  380. // 验证与下一步
  381. validateNext (isNext = true) {
  382. let {rowIndex, colIndex, columnConfig, row, columnValue} = this.getCommonData()
  383. if (columnConfig.editType !== 'dialog') {
  384. // this.$emit('update:tableData', this.tableDataTmp.tableData)
  385. }
  386. // 弹框传递额外参数
  387. let otherParams = (columnConfig.editType === 'dialog') ? this.updateChooseData(rowIndex, (columnConfig.dialogData ? columnConfig.dialogData.updateFields : null)) : null
  388. // let otherParams = JSON.parse(JSON.stringify(this.tableDataTmp.tableData[rowIndex]))
  389. // 验证单元格数据,验证不通过不继续执行
  390. this.$refs.tableForm.validateField('tableData.'+rowIndex+'.'+columnConfig.prop, (result) => {
  391. if (result) {
  392. if (columnConfig.editType === 'dialog') this.$modal.msgError(result)
  393. return
  394. }
  395. if (columnConfig.editType === 'dialog') {
  396. this.updateChooseData(rowIndex, (columnConfig.dialogData ? columnConfig.dialogData.updateFields : null), true)
  397. // this.$emit('update:tableData', this.tableDataTmp.tableData)
  398. this.open = false
  399. }
  400. // 判断是否跳转到下一步
  401. let next = isNext ? this.next : ()=>{}
  402. // 判断是否有业务回调 判断是否跳转到下一步
  403. if (columnConfig.callback) {
  404. columnConfig.callback({index: rowIndex, row: row, isEnter: isNext}, next )
  405. return
  406. }
  407. next()
  408. }, otherParams)
  409. },
  410. // 弹框选择带回
  411. oncheck (chooseData) {
  412. if (!chooseData) return;
  413. this.chooseData = chooseData
  414. // let {rowIndex, columnConfig} = this.getCommonData()
  415. // this.updateChooseData(rowIndex, (columnConfig.dialogData ? columnConfig.dialogData.updateFields : null), true)
  416. // this.open = false
  417. this.validateNext()
  418. },
  419. /**
  420. * 更新弹框数据。isTemp传true-更新数据,传false-返回临时数据
  421. */
  422. updateChooseData (rowIndex, updateFields, isTemp = false) {
  423. let tmpData = JSON.parse(JSON.stringify(this.tableDataTmp.tableData[rowIndex]))
  424. if (updateFields) {
  425. if (updateFields instanceof Array) {
  426. updateFields.forEach((key) => {
  427. tmpData[key] = this.chooseData[key]
  428. isTemp && this.$set(this.tableDataTmp.tableData[rowIndex], key, this.chooseData[key])
  429. })
  430. } else {
  431. var objkeys = Object.keys(updateFields)
  432. objkeys.forEach((key) => {
  433. tmpData[key] = this.chooseData[updateFields[key]]
  434. isTemp && this.$set(this.tableDataTmp.tableData[rowIndex], key, this.chooseData[updateFields[key]])
  435. })
  436. }
  437. }
  438. return tmpData
  439. },
  440. validate (callback) {
  441. return new Promise((resolve, reject) => {
  442. this.$refs.tableForm.validate(callback).then((result)=>{
  443. resolve(result)
  444. }).catch(e=>{
  445. let errorArr = Object.values(e)
  446. this.$modal.msgError(errorArr[0][0].message);
  447. reject(e)
  448. })
  449. })
  450. },
  451. validateRow (index, callback) {
  452. return this.$refs.tableForm.validateRow(index, callback)
  453. },
  454. resetTableform() {
  455. this.resetForm('tableForm')
  456. },
  457. clickLink(prop, scope) {
  458. this.$emit('link', prop, scope)
  459. }
  460. },
  461. };
  462. </script>
  463. <style lang="scss" scoped>
  464. // .edit-table-dialog ::v-deep .table-form-item.is-error:hover .el-form-item__error{
  465. // display: block!important;
  466. // }
  467. .edit-table-dialog{
  468. // 标题按钮行
  469. .title-tag {
  470. margin: 4px 0;
  471. flex-grow: 1;
  472. }
  473. .edit-table {
  474. margin-top: 10px;
  475. ::v-deep .el-table__body-wrapper {
  476. tr:hover > td.el-table__cell{
  477. background-color: #fff;
  478. }
  479. // overflow: unset; // 超出的字段滚动
  480. .el-table__cell {
  481. padding: 0!important;
  482. &.el-table-column--selection .el-checkbox {
  483. margin-left: 16px;
  484. }
  485. .cell {
  486. // overflow: unset;
  487. padding: 0!important;
  488. .column-text {
  489. width: 100%;
  490. height: 48px;
  491. line-height: 48px;
  492. overflow: hidden;
  493. text-overflow: ellipsis;
  494. white-space: nowrap;
  495. display: flex;
  496. justify-content: center;
  497. align-items: center;
  498. .edit-border {
  499. cursor: pointer;
  500. }
  501. .date {
  502. position: relative;
  503. width: calc(100% - 12px);
  504. height: 36px;
  505. line-height: 36px;
  506. border: 1px solid #F0F2F7;
  507. border-radius: 4px;
  508. text-align: left;
  509. &::before {
  510. content: "";
  511. font-family: "element-icons";
  512. color: #C0C4CC;
  513. width: 30px;
  514. position: relative;
  515. top: -1px;
  516. line-height: 34px;
  517. text-align: center;
  518. display: inline-block;
  519. }
  520. }
  521. .select {
  522. position: relative;
  523. width: calc(100% - 12px);
  524. height: 36px;
  525. line-height: 36px;
  526. border: 1px solid #F0F2F7;
  527. border-radius: 4px;
  528. text-align: left;
  529. padding: 0 30px 0 10px;
  530. &::after {
  531. content: "";
  532. color: #C0C4CC;
  533. font-size: 14px;
  534. font-family: "element-icons";
  535. width: 25px;
  536. text-align: center;
  537. display: inline-block;
  538. position: absolute;
  539. right: 5px;
  540. top: 0;
  541. transform: rotate(180deg);
  542. }
  543. }
  544. .input {
  545. position: relative;
  546. width: calc(100% - 12px);
  547. height: 36px;
  548. line-height: 36px;
  549. border: 1px solid #F0F2F7;
  550. border-radius: 4px;
  551. text-align: left;
  552. padding: 0 10px;
  553. }
  554. .dialog {
  555. position: relative;
  556. width: calc(100% - 12px);
  557. height: 36px;
  558. line-height: 36px;
  559. border: 1px solid #F0F2F7;
  560. border-radius: 4px;
  561. text-align: left;
  562. padding: 0 10px;
  563. &::after {
  564. content: "";
  565. color: #C0C4CC;
  566. font-size: 14px;
  567. font-family: "element-icons";
  568. width: 25px;
  569. text-align: center;
  570. display: inline-block;
  571. position: absolute;
  572. right: 4px;
  573. top: 0;
  574. }
  575. }
  576. }
  577. .table-form-item {
  578. margin: 0;
  579. .diff-tag {
  580. display: none;
  581. }
  582. /**.edit-tag {
  583. position: absolute;
  584. top: 0;
  585. left: 0;
  586. width: 8px!important;
  587. height: 0;
  588. border-left: 8px solid #1890ff;
  589. border-bottom: 5px solid #fff;
  590. z-index: 1;
  591. }
  592. &.is-error .edit-tag{
  593. border-left-color: #ff4949;
  594. } */
  595. /** 错误 */
  596. &.is-error .edit-border {
  597. background: #FFF7F5;
  598. border: 1px solid #F2B1A7;
  599. }
  600. &.diff{
  601. color: #ff4949;
  602. .diff-tag{
  603. display: block;
  604. position: absolute;
  605. top: 30px;
  606. left: 0;
  607. }
  608. }
  609. .el-form-item__content{
  610. & >div >div{
  611. width: calc(100% - 14px);
  612. &.has-unit {
  613. width: 80%;
  614. float: left;
  615. }
  616. // .el-date-editor,.el-input {
  617. // width: calc(100% - 12px);
  618. // }
  619. /*&.el-select .el-input input {
  620. height: 45px;
  621. line-height: 45px;
  622. border-radius: 0;
  623. border-color: #fff;
  624. padding: 0 30px 0 10px;
  625. &:focus {
  626. outline: none;
  627. border-color: #1890ff;
  628. }
  629. }
  630. &.el-input input {
  631. height: 45px;
  632. line-height: 45px;
  633. border-radius: 0;
  634. border-color: #fff;
  635. padding: 0 30px 0 10px;
  636. &:focus {
  637. outline: none;
  638. border-color: #1890ff;
  639. }
  640. }
  641. &.el-date-editor input {
  642. height: 45px;
  643. line-height: 45px;
  644. border-radius: 0;
  645. padding: 0 30px;
  646. }*/
  647. }
  648. .el-form-item__error{
  649. display: none;
  650. position: absolute;
  651. top: unset;
  652. bottom: 42px;
  653. left: 0;
  654. background-color: antiquewhite;
  655. z-index: 999999;
  656. width: 100%;
  657. padding: 10px;
  658. border-radius: 5px;
  659. line-height: 20px;
  660. &::after{
  661. content: "";
  662. height: 0;
  663. width: 0;
  664. border: 4px solid transparent;
  665. border-top-color: antiquewhite;
  666. position: absolute;
  667. top: 100%;
  668. right: 20px;
  669. }
  670. }
  671. }
  672. }
  673. }
  674. /** 复选框 */
  675. &.el-table-column--selection .cell {
  676. padding: 0 10px;
  677. }
  678. }
  679. .el-table__empty-block {
  680. background-image: none;
  681. min-height: 60px!important;;
  682. margin-bottom: 0;
  683. span {
  684. bottom: 0;
  685. }
  686. }
  687. }
  688. ::v-deep .warning-row {
  689. background: oldlace;
  690. }
  691. ::v-deep .success-row {
  692. background: #f0f9eb;
  693. }
  694. }
  695. &.edit-table-disabled .edit-table {
  696. ::v-deep .el-table__body-wrapper {
  697. .el-table__cell .column-text .edit-border{
  698. cursor: not-allowed;
  699. background-color: #f9f9f9!important;
  700. border-color: #f0f2f7;
  701. color: #BBBBBB;
  702. }
  703. }
  704. }
  705. }
  706. .no-btns {
  707. .edit-table {
  708. margin-top: 0;
  709. }
  710. }
  711. </style>

column.vue

  1. import Vue from 'vue';
  2. // import { hasClass, addClass, removeClass } from 'element-ui/src/utils/dom';
  3. // import ElCheckbox from 'element-ui/packages/checkbox';
  4. // import FilterPanel from './filter-panel.vue';
  5. // import LayoutObserver from './layout-observer';
  6. // import { mapStates } from './store/helper';
  7. export default {
  8. name: 'EditColumnRender',
  9. props: {
  10. column: {
  11. type: Object
  12. },
  13. scope: {
  14. type: Object
  15. },
  16. store: {
  17. type: Object
  18. // required: true
  19. },
  20. },
  21. render(h) {
  22. return (
  23. <div>
  24. {
  25. this.column.renderTemp
  26. ? this.column.renderTemp.call(this._renderProxy, h, { column: this.column, scope: this.scope, store: this.store, _self: this.$parent.$vnode.context })
  27. : ''
  28. }
  29. </div>
  30. );
  31. },
  32. components: {
  33. },
  34. created() {
  35. },
  36. mounted() {
  37. },
  38. beforeDestroy() {
  39. },
  40. methods: {
  41. },
  42. data() {
  43. return {
  44. draggingColumn: null,
  45. dragging: false,
  46. dragState: {}
  47. };
  48. }
  49. };

支持column-render.js ,支持render自定义列内容

  1. import Vue from 'vue';
  2. // import { hasClass, addClass, removeClass } from 'element-ui/src/utils/dom';
  3. // import ElCheckbox from 'element-ui/packages/checkbox';
  4. // import FilterPanel from './filter-panel.vue';
  5. // import LayoutObserver from './layout-observer';
  6. // import { mapStates } from './store/helper';
  7. export default {
  8. name: 'EditColumnRender',
  9. props: {
  10. column: {
  11. type: Object
  12. },
  13. scope: {
  14. type: Object
  15. },
  16. store: {
  17. type: Object
  18. // required: true
  19. },
  20. },
  21. render(h) {
  22. return (
  23. <div>
  24. {
  25. this.column.renderTemp
  26. ? this.column.renderTemp.call(this._renderProxy, h, { column: this.column, scope: this.scope, store: this.store, _self: this.$parent.$vnode.context })
  27. : ''
  28. }
  29. </div>
  30. );
  31. },
  32. components: {
  33. },
  34. created() {
  35. },
  36. mounted() {
  37. },
  38. beforeDestroy() {
  39. },
  40. methods: {
  41. },
  42. data() {
  43. return {
  44. draggingColumn: null,
  45. dragging: false,
  46. dragState: {}
  47. };
  48. }
  49. };

使用方法如下

我这里全局引用了,你也可以局部引用进来

  1. <edit-table
  2. ref="editTable"
  3. :empty-row="emptyRow"
  4. :column-data="columnData"
  5. :table-data.sync="tableData"
  6. :table-rules="tableRules"
  7. row-key="id"
  8. ></edit-table>
  1. data() {
  2. return {
  3. symbolList: [
  4. {label: '相似', value: "%%%"},
  5. {label: '左相似', value: "%%"},
  6. {label: '右相似', value: "%"},
  7. {label: '大于', value: ">"},
  8. {label: '大于等于', value: ">="},
  9. {label: '等于', value: "="},
  10. {label: '小于', value: "<"},
  11. {label: '小于等于', value: "<="}
  12. ],
  13. relationList: [
  14. {label: '并且', value: '&&'},
  15. {label: '或者', value: '||'}
  16. ],
  17. columnData: [
  18. { prop: 'name', type: 'selection' },
  19. {
  20. label: "列名",
  21. prop: "queryColumn",
  22. edit: true,
  23. editType: "select",
  24. selectData: {
  25. label: "desc",
  26. value: "value",
  27. getData: () => {
  28. return this.fields
  29. }
  30. },
  31. format: (scope) => {
  32. let current = this.fields.find(
  33. (item) => item.value === scope.row.queryColumn
  34. );
  35. if (current) return current.desc;
  36. }
  37. },
  38. {
  39. label: "计算符",
  40. prop: "querySymbol",
  41. edit: true,
  42. editType: "select",
  43. selectData: {
  44. label: "label",
  45. value: "value",
  46. getData: () => {
  47. return this.symbolList
  48. }
  49. },
  50. format: (scope) => {
  51. let current = this.symbolList.find(
  52. (item) => item.value === scope.row.querySymbol
  53. );
  54. if (current) return current.label;
  55. }
  56. },
  57. { label: "值", prop: "queryValue", edit: true, editType: 'template', renderTemp: (h, {scope})=>{
  58. return h(ColumnEdit, {
  59. props: {
  60. column: 'queryValue',
  61. scope: scope
  62. }
  63. }
  64. )
  65. }},
  66. {
  67. label: "列关系",
  68. prop: "queryRelation",
  69. edit: true,
  70. editType: "select",
  71. selectData: {
  72. label: "label",
  73. value: "value",
  74. getData: () => {
  75. return this.relationList
  76. }
  77. },
  78. format: (scope) => {
  79. let current = this.relationList.find(
  80. (item) => item.value === scope.row.queryRelation
  81. );
  82. if (current) return current.label;
  83. }
  84. },
  85. ],
  86. emptyRow: {
  87. queryColumn: null,
  88. querySymbol: null,
  89. queryValue: null,
  90. queryRelation: '&&'
  91. },
  92. tableData: [],
  93. tableRules: {
  94. queryColumn: [
  95. { required: true, message: "列名不能为空", trigger: "change" },
  96. ],
  97. querySymbol: [
  98. { required: true, message: "计算符不能为空", trigger: "change" },
  99. ],
  100. queryValue: [
  101. { required: true, message: "值不能为空", trigger: "change" },
  102. ],
  103. queryRelation: [
  104. { required: true, message: "列关系不能为空", trigger: "change" },
  105. ],
  106. },
  107. };

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/201124
推荐阅读
相关标签
  

闽ICP备14008679号