169 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <script>
 | |
| import AiDialogBtn from "dui/packages/layout/AiDialogBtn.vue";
 | |
| 
 | |
| export default {
 | |
|   name: "tableEditor",
 | |
|   components: {AiDialogBtn},
 | |
|   model: {
 | |
|     event: "input",
 | |
|     prop: "tableData"
 | |
|   },
 | |
|   props: {
 | |
|     label: String,
 | |
|     tableData: {default: () => []},
 | |
|     configs: {default: () => []}
 | |
|   },
 | |
|   data() {
 | |
|     return {
 | |
|       form: {}
 | |
|     }
 | |
|   },
 | |
|   computed: {
 | |
|     option() {
 | |
|       return {
 | |
|         size: 'mini',
 | |
|         filterDic: true,
 | |
|         cellBtn: true,
 | |
|         menuWidth: 120,
 | |
|         addBtn: false,
 | |
|         columnBtn: false,
 | |
|         refreshBtn: false,
 | |
|         border: true,
 | |
|         delBtnText: " ",
 | |
|         editBtnText: " ",
 | |
|         saveBtnText: " ",
 | |
|         saveBtnIcon: "el-icon-check",
 | |
|         cancelBtnText: " ",
 | |
|         cancelBtnIcon: "el-icon-close",
 | |
|         column: this.configs.map(e => {
 | |
|           const item = this.$copy(e)
 | |
|           delete item.$index
 | |
|           delete item.$cellEdit
 | |
|           return {...item, cell: true}
 | |
|         })
 | |
|       }
 | |
|     },
 | |
|     columns: v => v.configs,
 | |
|     records: v => v.tableData.map(e => ({$cellEdit: true, ...e}))
 | |
|   },
 | |
|   methods: {
 | |
|     rowSave(form, done) {
 | |
|       this.$emit("input", this.records)
 | |
|       this.$emit("data", this.getFormatData())
 | |
|       done()
 | |
|     },
 | |
|     rowDel(form, index) {
 | |
|       this.$confirm("是否要删除该行?").then(() => {
 | |
|         this.records.splice(index, 1)
 | |
|         this.$emit("data", this.getFormatData())
 | |
|       }).catch(() => 0)
 | |
|     },
 | |
|     getFormatData() {
 | |
|       return this.configs.map((c, i) => {
 | |
|         const item = {name: c.label}
 | |
|         this.records.map((row, j) => item[`v${j || ""}`] = row[`c${i || ""}`])
 | |
|         return item
 | |
|       })
 | |
|     },
 | |
|     addColumn() {
 | |
|       return this.$refs.addColumn.validate().then(() => {
 | |
|         const cols = this.$copy(this.configs)
 | |
|         const prop = `c${cols.length}`
 | |
|         cols.push({label: this.form.label, prop})
 | |
|         return this.$emit("update:configs", cols)
 | |
|       })
 | |
|     }
 | |
|   },
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <template>
 | |
|   <section class="tableEditor">
 | |
|     <avue-crud :option="option" :data="records" @row-save="rowSave" @row-cancel="rowSave" @row-del="rowDel">
 | |
|       <template v-for="col in columns" :slot="`${col.prop}Header`" slot-scope="{column = {}}">
 | |
|         <el-input class="headerInput" v-model="column.label" clearable placeholder="请输入列名" @change="$emit('update:configs', columns)"/>
 | |
|       </template>
 | |
|       <template v-if="label" v-slot:menuLeft>
 | |
|         <div class="label" v-text="label"/>
 | |
|       </template>
 | |
|       <template v-slot:menuRight>
 | |
|         <div class="flex">
 | |
|           <ai-dialog-btn dialogTitle="增加列" appendToBody :submit="addColumn" @closed="form={}" width="400px">
 | |
|             <div slot="btn" class="el-icon-plus pointer">增加列</div>
 | |
|             <el-form ref="addColumn" :model="form" size="small" labelWidth="60px">
 | |
|               <el-form-item label="列名" :rule="{required:true, message:'请输入列名'}">
 | |
|                 <el-input v-model="form.label" clearable placeholder="请输入列名"/>
 | |
|               </el-form-item>
 | |
|             </el-form>
 | |
|           </ai-dialog-btn>
 | |
|           <div class="el-icon-plus pointer mar-l8" @click="records.push({$cellEdit: true})">增加数据</div>
 | |
|         </div>
 | |
|       </template>
 | |
|     </avue-crud>
 | |
|   </section>
 | |
| </template>
 | |
| <style scoped lang="scss">
 | |
| .tableEditor {
 | |
|   width: 100%;
 | |
|   height: auto;
 | |
|   margin-bottom: 10px;
 | |
| 
 | |
|   :deep(.avue-crud__body) {
 | |
|     background-color: transparent;
 | |
| 
 | |
|     .avue-crud__header, .el-table, tr {
 | |
|       background-color: transparent;
 | |
|     }
 | |
| 
 | |
|     .avue-crud__header {
 | |
|       min-height: unset;
 | |
|     }
 | |
| 
 | |
|     .el-table__cell {
 | |
|       color: white;
 | |
|       background-color: #1D2127;
 | |
| 
 | |
|       input:disabled {
 | |
|         background-color: transparent;
 | |
|         border-color: transparent;
 | |
|         color: white;
 | |
|         padding: 0;
 | |
|       }
 | |
| 
 | |
|       &:last-of-type {
 | |
|         border-left: 1px solid #fff;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     .label {
 | |
|       width: 60px;
 | |
|       color: #FFFFFF;
 | |
|       font-size: 12px;
 | |
|       text-align: right;
 | |
|     }
 | |
| 
 | |
|     .el-icon-plus {
 | |
|       font-size: 12px;
 | |
|       color: $primaryColor;
 | |
|       line-height: 18px;
 | |
| 
 | |
|       &:before {
 | |
|         margin-right: 4px;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   &:last-of-type {
 | |
|     margin-bottom: 0;
 | |
|   }
 | |
| 
 | |
|   :deep(.headerInput) {
 | |
|     .el-input__inner {
 | |
|       padding: 0;
 | |
|       border: none;
 | |
|       background: transparent;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| </style>
 |