<template>
<div>
<el-table
ref="expandTable"
class="expand-table"
:data="tableList"
:show-header="true"
:size="size"
@expand-change="open"
>
<!-- 表格展开 -->
<el-table-column type="expand">
<template slot-scope="props">
<p class="el-title">{{ increment.title }}</p>
<el-form label-position="left" inline class="demo-table-expand">
<el-row>
<!-- 全选按钮 -->
<el-col :span="4">
<div class="grid-content bg-purple">
<div class="col-grid">
<el-checkbox
v-for="(i, v) in props.row.selectAll"
:key="v"
v-model="i.checked"
class="col-checkbox"
:checked="i.checked"
:label="i.value"
@change="handleCkecked(props.row, i, v)"
/>
</div>
</div>
</el-col>
<!-- 单选按钮 -->
<el-col :span="20">
<div class="bg-purple-light">
<div class="grid-boxcheck">
<el-checkbox
v-for="(i, v) in props.row.childrenList"
v-show="i.type == '0'"
:key="v"
v-model="i.checked"
:label="i.name"
:checked="i.checked"
class="prop-checkbox"
@change="changeChecked(props.row, i, v)"
/>
</div>
<div class="grid-boxcheck">
<el-checkbox
v-for="(i, v) in props.row.childrenList"
v-show="i.type == '1'"
:key="v"
v-model="i.checked"
:checked="i.checked"
:label="i.name"
class="row-checkbox"
@change="changeChecked(props.row, i, v)"
/>
</div>
</div>
</el-col>
</el-row>
</el-form>
<!-- 文字 -->
<p class="el-bottom">
<span class="sp-settlement">{{ increment.settlement }}</span>
<span class="sp-receipt">{{ increment.receipt }}</span>
<span class="sp-charge">{{ increment.charge }}</span>
<span class="sp-money">¥{{ monery(props.row) }}</span>
</p>
</template>
</el-table-column>``
<!-- 表格数据栏 -->
<el-table-column
v-for="(item, index) in tableCols"
:key="index"
:render-header="item.column?renderHeader:null"
:label="item.label"
:prop="item.prop"
:width="item.width"
>
<template slot-scope="scope">
<!-- 文字按钮 -->
<div v-if="item.type === 'Button'">
<el-button
v-for="(btn, i) in scope.row.btnList"
:key="i"
:type="btn.type"
@click="changeEvent(scope.row, btn, i)"
>
{{ btn.label }}
</el-button>
</div>
<!--输入框 -->
<div v-if="item.type === 'Input'">
<el-form :model="scope.row" :rules="item.rules">
<el-form-item :prop="item.prop">
<el-input
v-model="scope.row[item.prop]"
:placeholder="item.mold?'':'请输入' + `${item.label}`"
:class="item.mold?'number-input':''"
:type="item.mold"
@change="handleChange(scope.row)"
/>
</el-form-item>
</el-form>
</div>
</template>
</el-table-column>
</el-table>
<div class="add-commodity">
<i class="el-icon-circle-plus-outline" />
<el-button type="text" class="btn-text" @click="addCommodity">
{{ increment.addCommodity }}
</el-button>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator'
import _ from 'lodash'
@Component
export default class FormTable extends Vue {
// 表格型号:big,small,mini
@Prop({
type: String,
default: 'mini'
})
readonly size!: string
@Prop({
type: Object,
default: () => null
})
readonly increment!: object
// 表格数据
@Prop({
type: Array,
default: () => []
})
readonly tableData!: any[]
// 表格列配置
@Prop({
type: Array,
default: () => []
})
readonly tableCols!: any[]
// 表格数据
public tableList: any = []
// 添加商品对象
public form: object = {}
// 输入框change事件
handleChange(row: any) {
const formData = {
tradeName: row.tradeName,
skuModel: row.skuModel,
mount: row.mount,
codeModel: row.codeModel
}
this.$emit('handleChange', formData)
}
removeAaary(_arr: any, _obj: any) {
const length = _arr.length
for (let i = 0; i < length; i++) {
if (_arr[i] === _obj) {
if (i === 0) {
_arr.shift() // 删除并返回数组的第一个元素
return _arr
} else if (i === length - 1) {
_arr.pop() // 删除并返回数组的最后一个元素
return _arr
} else {
_arr.splice(i, 1) // 删除下标为i的元素
return _arr
}
}
}
}
// 操作项 收起服务,删除
changeEvent(row: any, item:any, btn: any, index: number) {
const el:any = this.$refs.expandTable
if (index === 0) {
// eslint-disable-next-line eqeqeq
if (row.open == true) {
btn.label = '收起服务项'
} else {
btn.label = '展开服务项'
}
el.toggleRowExpansion(row)
} else {
this.$emit('removeAaary', row)
this.tableList.splice(row, 1)
}
}
// 表格收起,文字按钮是展开服务项
loopTraversal() {
this.tableList.forEach((v: any) => {
// eslint-disable-next-line eqeqeq
if (v.open == false) {
v.btnList[0].label = '展开服务项'
}
})
}
// 添加商品
addCommodity() {
this.tableList.forEach((i: any) => {
i.open = false
})
this.tableData.forEach((v: any) => {
this.form = _.cloneDeep(v)
})
this.tableList.push(this.form)
this.loopTraversal()
}
// 单选事件
changeChecked(item: any, i: any, v: any) {
const arr: any = item.childrenList.filter(
(ever: any) => ever.type === i.type
)
if (i.type === '0') {
item.selectAll[1].checked = arr.every((v: any) => v.checked)
} else if (i.type === '1') {
item.selectAll[2].checked = arr.every((v: any) => v.checked)
}
item.selectAll[0].checked = item.childrenList.every((v: any) => v.checked)
const valarr: any = item.childrenList.filter((v: any) => v.checked)
this.$emit('changeChecked', valarr)
}
// 全选事件
handleCkecked(row: any, item: any, index: number) {
switch (index) {
case 0:
row.childrenList.forEach((v: any) => {
v.checked = item.checked
})
row.selectAll.forEach((v: any, index: number) => {
// eslint-disable-next-line no-unused-expressions
index !== 0 ? (v.checked = item.checked) : null
})
break
case 1:
row.childrenList.forEach((v: any) => {
// eslint-disable-next-line no-unused-expressions
v.type === '0' ? (v.checked = item.checked) : null
})
break
case 2:
row.childrenList.forEach((v: any) => {
// eslint-disable-next-line no-unused-expressions
v.type === '1' ? (v.checked = item.checked) : null
})
break
default:
break
}
const copyArr: any = [row.selectAll[1], row.selectAll[2]]
row.selectAll[0].checked = copyArr.every(
(v: any, index: number) => v.checked
)
const arr: any = row.childrenList.filter((v: any) => v.checked)
this.$emit('handleCkecked', arr)
}
// 计算服务费
monery(row: any) {
const arr: any = row.childrenList.filter((v: any) => v.checked)
let num = 0
arr.forEach((v: any) => {
num += v.price
})
return num
}
// 表格展开行
open(row: any) {
row.open = !row.open
// eslint-disable-next-line eqeqeq
if (row.open == true) {
row.btnList[0].label = '收起服务项'
} else {
row.btnList[0].label = '展开服务项'
}
}
// 表格表头增加红色*
renderHeader(cerateElement:Function, { column }:any) {
return cerateElement('div', [
cerateElement('span', column.label),
cerateElement('span', {
domProps: {
innerHTML: '*'
},
style: {
color: 'red',
fontSize: '16px',
marginRight: '2px',
marginTop: '1px',
float: 'left'
}
})
])
}
created() {
this.tableList = _.cloneDeep(this.tableData)
}
}
</script>
<style lang="scss">
@import '@/components/formTable/index.scss';
</style>
.col-checkbox {
margin-left: 10px;
margin-top: 10px;
}
.grid-boxcheck {
display: flex;
flex-wrap:wrap;
height: 100%;
.row-checkbox {
padding-bottom: 10px;
width: 150px;
margin-left: 10px;
}
.prop-checkbox {
padding-top: 10px;
margin-left: 10px;
width: 150px;
}
}
.col-grid:nth-child(3) {
padding-bottom: 10px;
}
.bg-purple-dark {
background: #99a9bf;
}
.bg-purple {
position: absolute;
height: 100%;
width: 16%;
background: #f3f3f7;
}
.bg-purple-light {
background: #f8f9fb;
}
.demo-table-expand {
font-size: 0;
}
.demo-table-expand label {
width: 90px;
color: #99a9bf;
}
.demo-table-expand .el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 50%;
}
.number-input {
width: 50px !important;
}
//去掉input为number 箭头
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
input[type='number'] {
-moz-appearance: textfield;
}
.el-table__expanded-cell[class*=cell] {
padding:10px 10px 20px 10px;
}
.el-col-20{
margin-left: 16%;
}
.el-title{
font-weight:600;
margin-bottom: 10px;
}
.el-bottom{
float:right;
margin-top: 10px;
margin-right: 20px;
.sp-money{
color:red;
font-weight: 700;
font-size: 18px;
margin-left: 8px;
}
.sp-charge{
margin-left: 8px;
}
.sp-receipt{
margin-left: 5px;
}
}
.add-commodity{
text-align: center;
height: 50px;
margin-top:10px;
border:1px dashed #D9D9D9;
line-height: 50px;
border-radius: 4px;
}
.btn-text{
color: black;
}
.expand-table{
width: 100%;
}
.el-form-item{
margin-bottom: 16px;
margin-top: 10px;
}
.el-icon-circle-plus-outline:hover{
color: #3c6ef0;
}
.expand-table {
/deep/ .el-icon-arrow-right::before {
content: "\e590";
color: #3c6ef0;
}
}
<template>
<div>
<FormTable
size="mini"
:table-data="tableData"
:increment="increment"
:table-cols="tableCols"
@handleChange="handleChange"
@changeChecked="changeChecked"
@handleCkecked="handleCkecked"
@removeAaary="removeAaary"
/>
<el-button type="primary" size="medium" @click="submit">提交</el-button>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import FormTable from '@/components/formTable/index.vue'
@Component({
components: { FormTable }
})
export default class DemoformTable extends Vue {
public increment: object = {
title: '增值服务',
settlement: '服务项默认结算方式:',
receipt: '收件月结',
charge: '增值服务费',
addCommodity: '增加商品'
}
public tableData: any[] = [
{
skuModel: '',
codeModel: '',
mount: '',
tradeName: '',
open: false,
childrenList: [
{ id: '1', name: '原包装丢失不取', type: '0', checked: false, price: 2 },
{ id: '2', name: '划痕超过3cm不取', type: '1', checked: false, price: 2 },
{ id: '3', name: '原包装破损不取', type: '0', checked: false, price: 2 },
{ id: '4', name: '商品已使用不取', type: '0', checked: false, price: 2 },
{ id: '5', name: '塑封包装不完整不取', type: '0', checked: false, price: 2 },
{ id: '6', name: '校验条码', type: '0', checked: false, price: 2 },
{ id: '7', name: '破损面积大于3cm不取', type: '1', checked: false, price: 2 },
{ id: '8', name: '无外包装不取', type: '0', checked: false, price: 2 },
{ id: '9', name: '破损面积大于3cm不取', type: '1', checked: false, price: 2 },
{ id: '10', name: '破损面积大于3cm不取', type: '1', checked: false, price: 2 },
{ id: '11', name: '测试项可配置', type: '0', checked: false, price: 2 },
{ id: '12', name: '无保修卡不取', type: '0', checked: false, price: 2 },
{ id: '13', name: '原包装丢失', type: '0', checked: false, price: 2 },
{ id: '14', name: '原包装丢失', type: '0', checked: false, price: 2 },
{ id: '15', name: '原包装丢失', type: '0', checked: false, price: 2 },
{ id: '16', name: '原包装丢失', type: '0', checked: false, price: 2 }
],
selectAll: [
{ value: '全部全选', checked: false },
{ value: '检查附件全选', checked: false },
{ value: '检查外观全选', checked: false }
],
btnList: [
{ type: 'text', label: '展开服务项' },
{ type: 'text', label: '删除' }
]
}
]
public tableCols: any[] = [
{ label: '商品名称',
type: 'Input',
prop: 'tradeName',
column: true,
rules: {
tradeName: {
required: true,
trigger: 'blur',
message: '请填写商品名称'
}
} },
{ label: '数量',
type: 'Input',
prop: 'mount',
column: true,
mold: 'number',
rules: {
mount: {
required: true,
trigger: 'blur',
message: '请填写商品数量'
}
} },
{ label: 'SKU', type: 'Input', prop: 'skuModel' },
{ label: '商品条码', type: 'Input', prop: 'codeModel' },
{ label: '操作', type: 'Button' }
]
public obj:any = {}
public arr:any = []
// input
handleChange(obj: any) {
this.obj = obj
}
// 单选
changeChecked(radio: any) {
this.arr = radio
console.log(radio, '单选')
}
// 全选
handleCkecked(all: any) {
this.arr = all
console.log(all, '全选')
}
// 删除
removeAaary(item:any) {
console.log(item, '删除')
}
submit() {
console.log(this.obj, this.arr)
}
}
</script>