先上效果图:
说明: 横 和 纵 都是遍历出来的 从数据库取出来的
input 是一个个填的 最下面有一个提交保存的按钮
跟这个表格很类似:
一、问题是这样的:后台传了xArr = [x1, x2,...,xn]和yArr = [y1, y2, ..yn]两个数组,前端要渲染出表格并且可以填写每个单元格的值,然后按照一定数据结构保存并传给后台,并且再次获取这个数据结构和数组xArr、yArr可以自己渲染出这个表?实现新增和修改的功能;
y1, y2,...,yn作为列名,x1,x2, ..., xn作为第一列数据,此业务模型是一种常见的表格,只不过要求行列都不固定,由后台数据提供并且动态生成。还要能够实现修改功能。本质上是一个动态渲染可编辑Table的问题。难点在于动态构建表格并且实现数据展示和保存。
二、思路:
(1)数据转换成表格后,处理起来就简单了,如果以常见的Table组件为例,只需要构建columns和dataSource两个数组数据即可渲染出表格;
(2)渲染出表格后,表格每一个余下的单元格都要可输入,可以考虑单元格利用render渲染出Input组件,通过Input的操作onChange或onBlur去改变数据并存储。
(3)数组是引用类型,可以利用引用类型只要没有深拷贝或改变指针指向内存地址就不变的原理,方便记录操作后的数据。
三、解决方法:
(1)动态构建columns(表格列数据)和dataSource(表格数据源)渲染出表格。(Table可参考 https://ant.design/components/table-cn/#header)
表格添加Input并且根据onChange/onBlur事件动态记录dataSource的变化。
四、完整代码:
<template>
<!-- 广播播放优先级配置管理 -->
<div class="staple">
<div class="listfile">
<Row>
<Col span="24">广播播放优先级配置管理</Col>
</Row>
<Table border ref="selection" :columns="historyColumns" :data="historyData" height="500">
<!-- <Table border ref="selection" :columns="historyColumns" :data="historyData" height="500" id="tips" v-on:mouseenter="visible" @mouseleave="invisible"> -->
<span v-show="seen">123</span>
</Table>
<div slot="footer" style="margin-top:10px;">
<Row :gutter="20" type="flex" justify="end">
<Col span="2">
<Button type="primary" long @click="handleSave()">保存</Button>
</Col>
<Col span="2">
<Button long @click="cancelAdd()">取消</Button>
</Col>
</Row>
</div>
</div>
</div>
</template>
<script>
import Cookies from "js-cookie";
export default {
// el:"#tips",
data() {
const letter = this.$store.state.parameter.deserve; //字典
return {
seen: false,
priorityType: letter.M407, //优先级类型(数据字典M407)
broadcastinfoType: letter.M408, //广播信息类型(数据字典M408)
historyColumns: [
{ title: "#", key: "key", align: "center" },
{
title: "优先级类型A",key: "priorityType",align: "center",
render: (h, params) => {
return h("Input", {
props: {
// type: 'primary',
placeholder: "请输入...",
value: params.row.priorityType
}
}
// params.row.priorityType
);
}
},
{ title: "广播信息类型B",key: "broadcastinfoType",align: "center",
render: (h, params) => {
return h("Input", {
props: {
placeholder: "请输入...",
value: params.row.broadcastinfoType
}
});
}
}
],
historyData: [],
record: [], // 修改后的值
originData: [], // 存放接口数据的
list:[], // 数据库--初始化
// 提交的变量
editAll: {
priorityInfoList: []
}
};
},
methods: {
initSql() {
// 根据 字典 补全数据库数据
let list = []; // 全部的数据 的初始值 level 都为 0
this.priorityType.map( v => {
this.broadcastinfoType.map( item => {
list.push({
broadcastinfoType: item.itemValue,
priorityType: v.itemValue,
level: 0,
lastmodifytime: "2019-03-25 00:00:00",
reamrk: "123456",
createuserid:this.$store.state.user.userId,
createusername: this.$store.state.user.userName,
})
})
})
// console.log("list:",list);
// 2 调一下 接口 得到
// 查询所有
this.$axios({
method: "get",
url: this.baseURL + "/priority/PriorityInfo/list_All",
})
.then(res => {
// console.log("接口:", res.data);
this.originData = res.data;
// console.log("this.originData:", this.originData);
// 3 把接口的值存在list 里面
list.map(v => {
this.originData.map(item => {
if (v.broadcastinfoType === item.broadcastinfoType && v.priorityType === item.priorityType) {
v.level = item.level
}
})
})
})
.catch(error => {});
// 4 发送请求给后台 把list 传过去 调保存接口
this.editAll.priorityInfoList = list;
this.$axios({
// 修改优先级信息
method: "post",
data: this.editAll,
headers: { "Content-Type": "application/json" },
url: this.baseURL + "/priority/PriorityInfo/update_Priority "
})
.then(res => {
// console.log("000000:",res.data);
})
.catch(error => {});
// 5 重新调查询接口
this.search_all();
},
// 鼠标移入移出事件
// visible:function(){
// this.seen = true;
// },
// invisible:function(){
// this.seen = false;
// },
// 查询所有
search_all() {
this.$axios({
method: "get",
url: this.baseURL + "/priority/PriorityInfo/list_All",
})
.then(res => {
console.log("查询所有1:", res);
this.editAll.priorityInfoList = res.data; // 用于存放tab 里面的默认的初始值
})
.catch(error => {});
},
//保存- 修改
handleSave() {
// 那你就根据你修改过的数 来修改原本的数
// 然后把原本的数提交
console.log("this.record;", this.record, this.editAll.priorityInfoList); // 所有改变的值
this.editAll.priorityInfoList.map(v => {
this.record.map(item => {
if (v.broadcastinfoType === item.broadcastinfoType && v.priorityType === item.priorityType) {
v.level = item.level
}
})
})
this.$axios({
// 修改优先级信息
method: "post",
data: this.editAll,
headers: { "Content-Type": "application/json" },
url: this.baseURL + "/priority/PriorityInfo/update_Priority "
})
.then(res => {
console.log(res.data);
this.search_all(); //查询所有的接口
//优化性能:
// 1.其实保存提交完了,最后也要清空下记录值,
// 2.以便没刷新页面都时候继续提交出问题
})
.catch(error => {});
},
//取消
cancelAdd(name) {
this.initTabe(); //清空刚刚输入的值
this.record = []; // 点取消了,初始化记录值
},
// 获取历史记录信息
handleListApproveHistory() {
// 保存取到的所有数据
this.ajaxHistoryData = this.TestData;
// this.dataCount = this.TestData.length;
// 初始化显示,小于每页显示条数,全显,大于每页显示条数,取前每页条数显示
if (this.TestData.length < this.pageSize) {
this.historyData = this.ajaxHistoryData;
} else {
this.historyData = this.ajaxHistoryData.slice(0, this.pageSize);
}
},
render(h, params) {
let priorityType_name = params.column.title; // name
let priorityType_code = params.column.key; // 编号
let broadcastinfoType_name = params.row.key; // name
let broadcastinfoType_code = "";
this.broadcastinfoType.map(v => {
if (v.itemName === broadcastinfoType_name) {
broadcastinfoType_code = v.itemValue; // 拿到 name
}
});
let value = "";
// 设置值-----从原来的接口查值放到input
this.editAll.priorityInfoList.map(v => {
if (
v.priorityType === priorityType_code &&
v.broadcastinfoType === broadcastinfoType_code
) {
value = v.level;
}
});
return (
<input type="text" class="ipt" placeholder="" value={value} onChange={e => {
this.record.push({
priorityType: priorityType_code,
broadcastinfoType: broadcastinfoType_code,
level: Number(e.target.value),
lastmodifytime: "2019-01-01 00:00:00",
reamrk: "123456",
createuserid: this.$store.state.user.userId,
createusername: this.$store.state.user.userName
});
console.log(params.index,priorityType_code,broadcastinfoType_code,e.target.value);}}/>
);
},
initTabe() {
// 1 初始化 y 轴
this.historyData = [];
this.broadcastinfoType.map((v, i) => {
// console.log("this.historyData:",this.historyData, v,);
this.historyData.push({ key: v.itemName });
});
// 2 初始化 x值
this.historyColumns = [{ title: "#", key: "key", width: 180 }];
this.priorityType.map((v, i) => {
this.$set(this.historyData[i], v.itemValue, 2);
let temp = { title: v.itemName, key: v.itemValue, render: this.render };
this.historyColumns.push(temp);
});
}
},
created() {
this.initSql(); // 给数据库一个初始值
this.search_all(); //查询所有的接口
this.initTabe(); // 初始化列表
},
mounted() {}
};
</script>
<style type="text/css">
.ivu-tabs-nav {width: 1300px !important;}
.ivu-tabs-nav .ivu-tabs-tab {float: left !important;}
.ivu-tabs-ink-bar {height: 0 !important;}
.caption {padding-right: 0px;}
.listfile {padding: 15px 0 15px 0;}
.vue-treeselect__control {height: 33px !important;}
.ivu-col-span-8 {width: 47% !important;}
.ipt {width: 130% !important;border-radius: 2px !important;border-width: 1px !important;outline: none !important;height: 24px !important;box-shadow: none;border: 1px solid #dcdee2 !important;}
.ipt:focus {border-color: #2d8cf0;}
</style>
注意事项:
1.const letter = this.$store.state.parameter.deserve; //字典
2.priorityType: letter.M407, //优先级类型(数据字典M407)
3.broadcastinfoType: letter.M408, //广播信息类型(数据字典M408)
这3个是我数据库字典里面的数据,想用的话就替换吧;
这里面其实还有一个初始化的处理;等有空在详细拿出来说, 如有更好的办法请指出来,感谢大家留言,谢谢!