第一种
<template><div class="time_table"><div style="margin-bottom: 10px"><el-button @click="addRowFn">新增</el-button></div><el-form ref="costForm" :model="formData"><el-table :data="formData.tableData" style="width: 100%" :value="tableData"><el-table-column prop="productId" label="所属产品(集成选非产线)" type="productId"><template #header><span style="color: red; margin-right: 4px">*</span><span>所属产品(集成选非产线)</span></template><template slot-scope="scope"><div v-if="!selectSure"><div style="display: flex; justify-content: space-between"><div> {{ scope.row.productId }} </div><div v-if="scope.$index != cellIndexInput" @click="gropeFn(scope, scope.row)"><el-icon class="el-icon-search"></el-icon></div></div></div><div v-if="scope.row.productId == '' || scope.row.productId == null"><div class="titelno-style">{{ `请填写所属产品` }}</div></div><div v-if="scope.$index == cellIndexInput && tableId == scope.row.id" style="display: flex; justify-content: space-between"><div class="about"><el-selectv-model="selectValue"placeholder="请选择":popper-append-to-body="false"@remove-tag="removetag"@clear="clearall"clearablefilterablecollapse-tagsref="select"@change="changelabel"><el-input style="width: 260px; margin: 10px" placeholder="输入关键字进行过滤" v-model="filterText"> </el-input><el-option :value="selectTree" class="setstyle" disabled><el-tree:filter-node-method="filterNode":data="list"@node-click="handleNodeClick":props="defaultProps"ref="tree"node-key="id"default-expand-allhighlight-current></el-tree></el-option></el-select></div></div><div v-if="scope.$index !== cellIndexInput && selectSure"><div style="display: flex; justify-content: space-between"><div> {{ scope.row.productId }} </div><div v-if="scope.$index != cellIndexInput" @click="gropeFn(scope, scope.row)"> <el-icon class="el-icon-search"></el-icon> </div></div></div></template></el-table-column><el-table-column prop="productMoney" label="产品金额" type="productMoney"><template #header><span style="color: red; margin-right: 4px">*</span><span>产品金额</span></template><template slot-scope="scope"><div v-if="!numberSure"><div style="display: flex; justify-content: space-between"><div> {{ scope.row.productMoney | currencyFormat }} </div><div v-if="scope.$index != cellIndexnumber" @click="gropesFn(scope, scope.row, scope.row.productMoney)"><el-icon class="el-icon-search"></el-icon></div></div></div><div v-if="scope.row.productMoney == '' || scope.row.productMoney == null"><div class="titelno-style">{{ `请填写所属金额` }}</div></div><div v-if="scope.$index == cellIndexnumber && tablelistId == scope.row.id" style="display: flex; justify-content: space-between"><inputNumberA:values="values":newDates="newDates":rowinputNumber="rowinputNumber"@close="closeinputNumberFn"@change="changeinputNumberFn"></inputNumberA><!-- <el-form-item :prop="`tableData.${scope.$index}.productMoney`" :rules="[{ required: true, message: '请输入' }]"><el-input v-model.trim="scope.row.productMoney" @keyup.native="handleNumberType" style="width: 250px" placeholder="请输入"></el-input></el-form-item> --></div><div style="display: flex; justify-content: space-between" v-if="scope.$index !== cellIndexnumber && numberSure"><div>$ {{ scope.row.productMoney | currencyFormat }} </div><div @click="gropesFn(scope, scope.row)"><el-icon class="el-icon-search"></el-icon></div></div></template></el-table-column><el-table-column prop="answer" label="操作"><template slot-scope="scope"><el-button @click="delOptionFn(scope.$index, tableData)">删除</el-button></template></el-table-column></el-table></el-form></div>
</template><script>
import inputNumberA from './inputNumber.vue'function filterTreeData(treeData) {return treeData.filter((item) => {if (isNotEmpty(item.children)) {item.disabled = trueitem.children = filterTreeData(item.children)}return item})
}
function isNotEmpty(arr) {return arr && Array.isArray(arr) && arr.length > 0
}
function addToTreeFn(treeData, type1) {treeData.forEach((node) => {if (node.children && node.children.length > 0) {addToTreeFn(node.children, type1)} else {node.sos = type1}})
}export default {name: 'timeTable',props: {value: {type: Array,default: () => [{}],},},components: {inputNumberA,},data() {return {dialogVisible: true,selectValue: '',selectTree: [],expandedList: [],filterText: '', //input搜索rowinputNumber: {},list: [],defaultProps: {children: 'children',label: 'label',},nameValue: '',defaultValue: [], //tree唯一的idvalues: '',newDates: {},formData: {// tableData: [...this.value],tableData: [],},tableId: '',cellIndexInput: null,cellIndexnumber: null,prodectmark: null,options: [], //节点下拉框数据selectSure: false,numberSure: false,tablelistId: '',//验证规则rules: {// productId: [// {// required: true,// message: '请输入姓名',// trigger: ['blur', 'change'],// },// ],sex: [{required: true,message: '请选择性别',trigger: ['blur', 'change'],},],},tableData: [],}},watch: {tableData: {handler(newval) {this.$emit('input', newval)},deep: true,},selectValue(newValue) {this.changelabel(newValue)},// 搜索filterText(val) {this.$refs.tree.filter(val)},value: {handler(newval) {this.handleFn(newval)console.log(newval, 'newval_____')},deep: true,},},created() {console.log(this.value, 'yyiyyyyyyyyyyyyy')// this.fetchEntryTimeDic()// this.listFn()this.treeFn()},methods: {handleFn(val) {// this.formData.tableData = val// const v = val// const vo = v.map((item) => {// return { productId: item.productName, productMoney: item.productMoney, productName: item.productId }// })this.formData.tableData = val},changelabel(val) {console.log('changelabel----', val)},// 下拉框移除removetag() {this.$refs.tree.setCheckedKeys([])},// 可清空的单选模式下用户点击清空按钮时触发clearall() {this.selectTree = []this.$nextTick(() => {this.$refs.tree.setCheckedNodes([])})},handleNodeClick(data, node) {let arr = []if (data.sos === '1') {arr.push(data)this.selectTree = arr[0]this.selectValue = this.selectTree.labelthis.$nextTick(() => {if (this.selectValue !== '') {this.$emit('treechagelist', this.selectTree, this.row1)this.cellIndexInput = null}})}},// 模糊查询(搜索过滤),实质为筛选出树形控件中符合输入条件的选项,过滤掉其他选项filterNode(value, data) {console.log(value, 'kkkkkkkkkkkkkkkk')if (!value) return truelet filterRes = data.label.indexOf(value) !== -1return filterRes},treeFn() {// 接口treeAPI().then((res) => {this.list = resthis.selectValue = ''addToTreeFn(this.list, '1')filterTreeData(this.list)})},gropeFn(v, row) {console.log(row, v, 'gropeFn-----------', row.productId)this.selectValue = row.productIdconsole.log(this.selectValue, ' this.selectValue ')this.selectSure = truethis.tableId = row.idthis.cellIndexInput = v.$indexthis.rows = rowthis.row1 = vconsole.log(row.id, ' row.id')},gropesFn(v, row, i) {console.log(v, row, 'gropesFn', i)this.numberSure = truethis.tablelistId = row.idthis.cellIndexnumber = v.$indexthis.values = ithis.newDates = v},//表格的单元格单机 ---> 将每行的isEdit改成truerowClickFn(row, column, event) {this.$set(row, 'isEdit', true)},// 新增addRowFn() {this.formData.tableData.unshift({productMoney: '',productId: '',productName: '',})this.selectValue = ''},// 下面的数据保存addFn(id, tableData) {tableData.orderNum = Number(tableData.orderNum)// 存起来数据localStorage.setItem('tableData', JSON.stringify(tableData)),// 取出来localStorage.getItem('tableData')this.tableData = JSON.parse(localStorage.getItem('tableData'))this.tableData.forEach((item) => {item.orderNum = Number(item.orderNum)})if (!tableData[id].productMoney) {return this.$message.error('请您填写描述信息哦~')}},delOptionFn(index) {this.formData.tableData.splice(index, 1)},async upOption(row) {console.log(row)},closeinputNumberFn() {this.handleChange()},handleChange() {this.inputNumberSure = falsethis.cellIndexNumber = null},changeinputNumberFn(val, v, row) {this.$emit('inputnumberchagelist', Number(val), row)this.cellIndexnumber = null},handleClose() {this.dialogVisible = false},},
}
</script><style lang="scss" scoped>
/* ::v-deep.el-table--fit {border-right: 0;border-bottom: 0;margin-left: -55px;
} */
.titelno-style {color: red;font-size: 8px;
}
.setstyle {min-height: 200px;padding: 0 !important;margin: 0;overflow: auto;cursor: default !important;
}
</style>
inputNumber.vue文件
<template><div class="cell-input-number"><input type="number" class="cell-input-inner" ref="inputEl" size="mini" v-model.trim="newValue" @blur="handleBlur" :min="mins" :max="maxs" /></div>
</template><script>
export default {props: {values: {type: [String, Number],required: false,default: '',},rowinputNumber: {type: Object,default: () => {},},newDates: {type: Object,default: () => {},},},data() {return {newValue: '',currentHeight: this.height,mins: 0,maxs: 0,}},created() {console.log(this.rowinputNumber, 'rowinputNumberrowinputNumber')},mounted() {this.newValue = this.values// 用户双击后,让其处于获取焦点的状态this.$refs.inputEl.focus()},methods: {formatInput(val) {console.log(val, 'hhhhhhhhhhhhhhhhhhhh')},parseInput() {},checknum() {},numberChangeFn(event) {console.log(event, 'yyyyyyy')},handleInput(event) {console.log(event, 'event')const { values, selectionStart, selectionEnd } = event.target// 只保留数字和小数点let pureValue = values.replace(/[^\d.]/g, '')// 如果小数点超过一个,只保留第一个const idx = pureValue.indexOf('.')if (idx !== -1 && pureValue.indexOf('.', idx + 1) !== -1) {pureValue = pureValue.slice(0, idx + 1) + pureValue.slice(idx + 1).replace(/\./g, '')}// 如果小数点在开头,前面加 0const isBeginningWithDot = pureValue[0] === '.'let newValue = isBeginningWithDot ? `0${pureValue}` : pureValue// 根据光标位置修改输入值const num = Number(newValue)if (num > 0 && selectionStart !== selectionEnd) {const start = Math.max(selectionStart, newValue.indexOf(num))const end = Math.min(selectionEnd, newValue.indexOf(num) + String(num).length)newValue = newValue.slice(0, start) + num + newValue.slice(end, newValue.length)}// 更新输入框中的值和组件中的值event.target.values = newValuethis.newValue = newValue},handleBlur() {if (this.newValue !== this.values) {if (this.newValue === '') {this.newValue = 0}this.$emit('change', this.newValue, this.rowinputNumber, this.newDates)}this.$emit('close')},},
}
</script><style lang="scss">
.cell-input-number {width: 100%;height: 100%;background-color: #fff;font-size: inherit;box-shadow: 0 0 24px #0000002e;.cell-input-inner {margin: 0;padding: 2px 8px;font-size: inherit;border: none;outline: none;width: 100%;height: 100%;background-color: transparent;line-height: 23px;resize: none;overflow: hidden;white-space: pre-wrap;word-break: break-all;font-family: inherit;box-sizing: border-box;}
}
</style>
父页面
拿到数据传递给子去,然后进项本地储存 ,监听
inputnumberchagelistFn(i, row) {this.$set(this.value[row.$index], 'productMoney', i)localStorage.setItem('mutate-1', JSON.stringify(this.value))},treechagelistFn(i, row) {this.$set(this.value[row.$index], 'productId', i.label)localStorage.setItem('mutate-1', JSON.stringify(this.value))this.$set(this.value[row.$index], 'id', i.id)},
第二种写法
<template><div class="time_table"><el-card style="margin-bottom: 20px"><div slot="header" class="clearfix"><el-button type="text" @click="newlyAddedFn">新增</el-button></div><el-table border :data="tableData" style="width: 100%" :value="tableData"><el-table-column label="序号" width="100px" align="center"><template slot-scope="scope">{{ scope.$index + 1 }}</template></el-table-column><el-table-column prop="productId" label="xxxxx"><template slot-scope="scope"><el-select:filter-method="filterMethod"filterable:ref="'productId' + scope.$index"v-model="tableData[scope.$index]['productId']"placeholder="请选择文档类别"clearable><el-option :value="tableData[scope.$index]['productId']" style="height: auto"><el-tree:filter-node-method="filterNode":ref="'categoryNameTree' + scope.$index":data="data"node-key="id":props="defaultProps"@node-click="getTypeList(scope.$index, scope)":expand-on-click-node="false"default-expand-all><span slot-scope="{ node }">{{ node.label }}</span></el-tree></el-option></el-select><div style="color: red; font-size: 12px" v-if="JSON.stringify(scope.row) == '{}' || scope.row.productId == ''"> 请选择所属产品(集成选非产线) </div></template></el-table-column><el-table-column prop="productMoney" label="产品金额" :sortable="true"><template slot-scope="scope"><el-input type="number" v-model="scope.row.productMoney" placeholder="请输入数字"> </el-input><divstyle="color: red; font-size: 12px"v-if="JSON.stringify(scope.row) == '{}' || scope.row.productMoney == null || scope.row.productMoney == 0 || scope.row.productMoney == ''">请输入产品金额</div></template></el-table-column><el-table-column prop="answer" label="操作" width="100px"><template slot-scope="{ row }"><el-button type="text" @click="delOption(row, tableData)"><span style="color: red">删除</span></el-button></template></el-table-column></el-table><div class="money-style"><div class="amount-to-style">合计:</div><div class="total-quotation-style">{{ preSignMoney | currencyFormat }}</div></div></el-card></div>
</template><script>export default {name: 'induction',props: {value: {type: Array,default: () => [],},},data() {return {preSignMoney: '',categoryId: null,tableData: [{}],options: [],data: [],dialogVisible: false,defaultProps: {children: 'children',label: 'label',},}},created() {this.getListFn()this.tableData = this.value},watch: {tableData: {handler(newval) {this.$emit('input', newval)this.countFn(newval)},deep: true,},value(val) {this.tableData = val},},methods: {countFn(data) {const total = data.reduce((accumulator, currentItem) => {return Number(accumulator) + Number(currentItem.productMoney)}, 0)this.preSignMoney = total},// 新增newlyAddedFn() {this.tableData.unshift({ productMoney: '', productId: '', productName: '' })},// 删除delOption(index, data) {data.splice(index, 1)},getListFn() {treeAPI().then((res) => {this.data = res})},filterNode(value, data) {if (!value) return truereturn data.label.indexOf(value) !== -1},filterMethod(value) {this.$refs.tree.filter(value)},clearValue() {this.$refs.tree.setCurrentKey(null)},getTypeList(index, row) {console.log(index, 'ccvcv', row)// .getCurrentKey()获取到当前要选择节点的key值// 使用此方法必须设置 node-key 属性,若没有节点被选中则返回 nullconst nodeId = this.$refs['categoryNameTree' + index].getCurrentKey()// .getNode(nodeId) 根据 data 或者 key 拿到 Tree 组件中的 nodeconst node = this.$refs['categoryNameTree' + index].getNode(nodeId)if (node.childNodes.length === 0) {// 根据index给当前元素的categoryName参数赋值this.$set(this.tableData[index], 'productId', node.label)this.$set(this.tableData[index], 'label', node.data.id)// 此时页面上已经可以动态选择// 这一步是通过判断当前元素的v-model是否有值来控制el-option是否隐藏if (this.tableData[index].productId) {// .blur()用来隐藏当前展开的下拉选择框this.$refs['productId' + index].blur()}} else {this.$message({message: '请勾选子级',type: 'warring',})}},},
}
</script>
<style lang="scss" scoped>
.money-style {height: 46px;font-size: 16px;// margin-top: 20px;border-right: 1px solid #d9dbe0;border-left: 1px solid #d9dbe0;border-bottom: 1px solid #d9dbe0;line-height: 23px;display: -webkit-box;.amount-to-style {width: 50%;text-align: center;line-height: 44px;border-right: 1px solid #d9dbe0;}.total-quotation-style {text-align: center;line-height: 44px;width: 50%;}
}
</style>
父页面
inputChange(val) {this.tablesProps = val},