需求
做成一个可以手动增加删除列表行的功能,因为现在前端用的是layui,所以先尝试使用Layui的列表来实现
layui实现
layui的数据表格,有两种方式,一种是通过url从后台获取数据,另一种是已知数据来绘制,通过设置data,
后台获取数据官方案例:
table.render({
elem: '#test'
,url:'/demo/table/user/'
,cellMinWidth: 80 //全局定义常规单元格的最小宽度,layui 2.2.1 新增
,cols: [[
{field:'id', width:80, title: 'ID', sort: true}
,{field:'username', width:80, title: '用户名'}
,{field:'sex', width:80, title: '性别', sort: true}
,{field:'city', width:80, title: '城市'}
,{field:'sign', title: '签名', width: '30%', minWidth: 100} //minWidth:局部定义当前单元格的最小宽度,layui 2.2.1 新增
,{field:'experience', title: '积分', sort: true}
,{field:'score', title: '评分', sort: true}
,{field:'classify', title: '职业'}
,{field:'wealth', width:137, title: '财富', sort: true}
]]
});
});
已知数据案例
layui.use('table', function(){
var table = layui.table;
//展示已知数据
table.render({
elem: '#demo'
,cols: [[ //标题栏
{field: 'id', title: 'ID', width: 80, sort: true}
,{field: 'username', title: '用户名', width: 120}
,{field: 'email', title: '邮箱', minWidth: 150}
,{field: 'sign', title: '签名', minWidth: 160}
,{field: 'sex', title: '性别', width: 80}
,{field: 'city', title: '城市', width: 100}
,{field: 'experience', title: '积分', width: 80, sort: true}
]]
,data: [{
"id": "10001"
,"username": "杜甫"
,"email": "xianxin@layui.com"
,"sex": "男"
,"city": "浙江杭州"
,"sign": "人生恰似一场修行"
,"experience": "116"
,"ip": "192.168.0.8"
,"logins": "108"
,"joinTime": "2016-10-14"
}, {
"id": "10002"
,"username": "李白"
,"email": "xianxin@layui.com"
,"sex": "男"
,"city": "浙江杭州"
,"sign": "人生恰似一场修行"
,"experience": "12"
,"ip": "192.168.0.8"
,"logins": "106"
,"joinTime": "2016-10-14"
,"LAY_CHECKED": true
}, {
"id": "10003"
,"username": "王勃"
,"email": "xianxin@layui.com"
,"sex": "男"
,"city": "浙江杭州"
,"sign": "人生恰似一场修行"
,"experience": "65"
,"ip": "192.168.0.8"
,"logins": "106"
,"joinTime": "2016-10-14"
}, {
"id": "10004"
,"username": "贤心"
,"email": "xianxin@layui.com"
,"sex": "男"
,"city": "浙江杭州"
,"sign": "人生恰似一场修行"
,"experience": "666"
,"ip": "192.168.0.8"
,"logins": "106"
,"joinTime": "2016-10-14"
}, {
"id": "10005"
,"username": "贤心"
,"email": "xianxin@layui.com"
,"sex": "男"
,"city": "浙江杭州"
,"sign": "人生恰似一场修行"
,"experience": "86"
,"ip": "192.168.0.8"
,"logins": "106"
,"joinTime": "2016-10-14"
}]
//,skin: 'line' //表格风格
,even: true
//,page: true //是否显示分页
//,limits: [5, 7, 10]
//,limit: 5 //每页默认显示的数量
});
});
我的思路就是,从后台获取数据,然后增加一列,就是在现有数据后,拼一行空数据,然后刷新页面
比如
//事件,如果当前页面有一些按钮的点击事件,可以添加在这里
var active = {
//新增一行
add: function () {
//空数据
var newData = {
pathologyNumber: ""
, specimenNumber: ""
, esophagealDistanceStart: ""
, esophagealDistanceEnd: ""
}
var dataList = getDataList("dataTable");//table的id
//拼接新内容
var newDataList = dataList.concat(newData);
table.reload("dataTable", {
data: newDataList
})
}
};
$('.layui-btn.btn-action').on('click', function () {
var type = $(this).data('type');
active[type] ? active[type].call(this) : '';
});
/**
* 获取列表数据
*/
function getDataList(tableId) {
if (table.cache[tableId]) {
return table.cache[tableId];
}
return [];
}
但是我的列表数据是从后台获取,所以坑就在这里,我前台拼接了数据,刷新列表,会从后台重新拉取数据,把拼接的数据覆盖掉,所以这种拼接,应该是只适合已知数据的那种列表。因为刚接触layui,所以对使用layui实现增加删除列表行存在几个疑问:1.怎么能刷新列表的时候,不从后台拉取数据,2.怎么上传列表中的数据到后台。
使用layui实现需求,因为刷新问题,以及提交数据问题,没有实现
html实现
实现效果:
数据库设计思路:列表首页作为一个A表,保存表Aid,然后列表项,设计一张表B,里边有个表Bid,与Aid关联,添加数据,列表首页数据保存到A表,将列表项保存到B,修改数据时,先将B中与A关联的数据删掉,将列表首页数据保存到A,列表项保存到B,删除A中数据时,将B中关联数据删除,查询数据,先查询A中的数据,然后通过Aid从B表中获取关联数据
html实现就比较简单,就是手动写列表项布局,在列表中拼接,删除,具体实现
列表布局实现
<div class="layui-form-item">
<div class="layui-inline upDown">
<div class="layui-input-block">
<table class="layui-table" style="width: 100%;" lay-filter="demo" >
<thead>
<tr>
<th rowspan="2">1号</th>
<th rowspan="2">2号</th>
<th rowspan="2">3距离/点位()</th>
<th rowspan="2">4部位</th>
<th rowspan="2">5膜</th>
<th rowspan="2">6诊断</th>
<th rowspan="2">7诊断依据</th>
<th colspan="5">8依据</th>
<th rowspan="2">9备注</th>
<th rowspan="2" >操作</th>
</tr>
<tr>
<th>类型</th>
<th>程度</th>
<th>深度</th>
<th>萎缩</th>
<th>化生</th>
</tr>
</thead>
<tbody id="dynamic-table">
</tbody>
</table>
</div>
</div>
</div>
进入页面,调用后台接口加载数据
var idRecord = 1;
function loadDatas(aData){
idRecord=1;
var id=""
if(aData!=null){
id=aData.id
}
$.ajax({
type: "GET",
url: _CONTEXT_PATH +'mg/digest/diagnosisItems/' + id,
error: function (errorRes) {
layer.msg(errorRes.responseText, function () {});
},
success: function (responseData) {
for (var k in responseData.body) {
requestDatas(responseData.body[k]);
}
}
});
}
处理html
//请求参数据组装表格
function requestDatas(d) {
var trHtml = '<tr id="dynamic-line-' + idRecord + '">'
+ '<td><input id="pathology_number-' + idRecord + '" type="text" value="' + (d.pathologyNumber == null ? "" : d.pathologyNumber) + '" class="layui-input"></td>'
+ '<td><input id="specimen_number-' + idRecord + '" type="text" value="' + (d.specimenNumber == null ? "" : d.specimenNumber) + '" class="layui-input"></td>'
+ '<td><div>' +
'<div style="display: flex;justify-content: center;align-items: center;"><input id="esophageal_distance_start-' + idRecord + '" type="text" value="' + (d.esophagealDistanceStart == null ? "" : d.esophagealDistanceStart) + '" class="layui-input" > ' +
'——<input id="esophageal_distance_end-' + idRecord + '" type="text" value="' + (d.esophagealDistanceEnd == null ? "" : d.esophagealDistanceEnd) + '" class="layui-input">cm</div></br>' +
'<div style="display: flex;justify-content: center;align-items: center;"><input id="esophageal_point_start-' + idRecord + '" type="text" value="' + (d.esophagealPointStart == null ? "" : d.esophagealPointStart) + '" class="layui-input">' +
'——<input id="esophageal_point_end-' + idRecord + '" type="text" value="' + (d.esophagealPointEnd == null ? "" : d.esophagealPointEnd) + '" class="layui-input">点 </div></div></td>'
+ '<td><input id="gastric_site-' + idRecord + '" type="text" value="' + (d.gastricSite == null ? "" : d.gastricSite) + '" class="layui-input"></td>'
+ '<td><input id="lamina_propria-' + idRecord + '" type="text" value="' + (d.laminaPropria == null ? "" : d.laminaPropria) + '" class="layui-input"></td>'
+ '<td><input id="pathologic_diagnosis-' + idRecord + '" type="text" value="' + (d.pathologicDiagnosis == null ? "" : d.pathologicDiagnosis) + '" class="layui-input"></td>'
+ '<td><input id="esophagitis_diagnostic-' + idRecord + '" type="text" value="' + (d.esophagitisDiagnostic == null ? "" : d.esophagitisDiagnostic) + '" class="layui-input"></td>'
+ '<td><input id="inflammation_type-' + idRecord + '" type="text" value="' + (d.inflammationType == null ? "" : d.inflammationType) + '" class="layui-input"></td>'
+ '<td><input id="inflammation_degree-' + idRecord + '" type="text" value="' + (d.inflammationDegree == null ? "" : d.inflammationDegree) + '" class="layui-input"></td>'
+ '<td><input id="inflammation_depth-' + idRecord + '" type="text" value="' + (d.inflammationDepth == null ? "" : d.inflammationDepth) + '" class="layui-input"></td>'
+ '<td><input id="atrophy-' + idRecord + '" type="text" value="' + (d.atrophy == null ? "" : d.atrophy) + '" class="layui-input"></td>'
+ '<td><input id="metaplasia-' + idRecord + '" type="text" value="' + (d.metaplasia == null ? "" : d.metaplasia) + '" class="layui-input"></td>'
+ '<td><input id="remarks-' + idRecord + '" type="text" value="' + (d.remarks == null ? "" : d.remarks) + '" class="layui-input"></td>'
+ '<td>'
+"<button id='" + idRecord + "' type=\"button\" class=\"layui-btn layui-btn-xs relation\" >删除</button>"
+ '</td></tr>'
$('#dynamic-table').append(trHtml);
console.log("#dynamic-table:"+ $('#dynamic-table').html())
//删除按钮
$(".relation").on("click", function () {
var id = $(this).attr("id");
console.log("id:"+id)
$("#dynamic-line-" + id).remove();
});
idRecord++;
}
新增按钮
addItems=function (){
var newData = {
pathologyNumber: ""
, specimenNumber: ""
, esophagealDistanceStart: ""
, esophagealDistanceEnd: ""
, esophagealPointStart: ""
, esophagealPointEnd: ""
, experience: ""
, gastricSite: ""
, laminaPropria: ""
, pathologicDiagnosis: ""
, esophagitisDiagnostic: ""
, inflammationType: ""
, inflammationDegree: ""
, inflammationDepth: ""
, atrophy: ""
, metaplasia: ""
, remarks: ""
}
requestDatas(newData);
}
提交数据
/*--TODO 重用区 Start */
function confirm(field, isNew, id) {
//组合api参数数数组据
var saveDataAry = [];
for (var i = 1; i < idRecord; i++) {
//没有被禁用i
if ($('#dynamic-line-' +i ).val() !=null) {
var data = {
"pathologyNumber": $("#pathology_number-" + i).val(),
"specimenNumber": $("#specimen_number-" + i).val(),
"esophagealDistanceStart": $('#esophageal_distance_start-' + i).val(),
"esophagealDistanceEnd": $('#esophageal_distance_end-' + i).val(),
"esophagealPointStart": $('#esophageal_point_start-' + i).val(),
"esophagealPointEnd": $('#esophageal_point_end-' + i).val(),
"gastricSite": $('#gastric_site-' + i).val(),
"laminaPropria": $('#lamina_propria-' + i).val(),
"pathologicDiagnosis": $('#pathologic_diagnosis-' + i).val(),
"esophagitisDiagnostic": $('#esophagitis_diagnostic-' + i).val(),
"inflammationType": $('#inflammation_type-' + i).val(),
"inflammationDegree": $('#inflammation_degree-' + i).val(),
"inflammationDepth": $('#inflammation_depth-' + i).val(),
"atrophy": $('#atrophy-' + i).val(),
"metaplasia": $('#metaplasia-' + i).val(),
"remarks": $('#remarks-' + i).val(),
};
saveDataAry.push(data)
}
}
field.params=JSON.stringify(saveDataAry);
//新增
if (isNew == 1) {
$.ajax({
type: "POST",
url: _CONTEXT_PATH + "mg/digest/diagnosis",
data: field,
error: function (errorRes) {
console.log(errorRes);
if (errorRes.status == 401) {
window.location.replace(_CONTEXT_PATH + errorRes.responseText);
} else {
layer.msg(errorRes.responseText, function () {
});
}
},
success: function (responseData) {
if (responseData.result) {
layer.msg("提交成功", {icon: 1, shift: 0, time: 1500, shade: 0.6}, function () {
});
} else {
layer.msg(responseData.message, {
icon: 2,
shift: 0,
time: 1500,
shade: 0.6
}, function () {
});
}
}
});
} else {
//更新
$.ajax({
type: "PUT",
url: _CONTEXT_PATH + `mg/digest/diagnosis/${id}`,
data: field,
error: function (errorRes) {
if (errorRes.status == 401) {
window.location.replace(_CONTEXT_PATH + errorRes.responseText);
} else {
layer.msg(errorRes.responseText, function () {
});
}
},
success: function (responseData) {
if (responseData.result) {
layer.msg("更新成功", {icon: 1, shift: 0, time: 1500, shade: 0.6}, function () {
});
} else {
layer.msg("操作失败", {icon: 1, shift: 0, time: 1500, shade: 0.6}, function () {
});
}
}
});
}
}
后台接收数据
@PostMapping(value= "/diagnosis")
@ResponseBody
public ComServiceResVo create(@Valid @ModelAttribute DigestiveDiagnosisEntity data, BindingResult result) {
if(result.hasErrors()) {
return ComServiceResVo.badRequest(result.getAllErrors().get(0).getDefaultMessage());
}
List<DigestiveDiagnosisItemEntity> paramEntities=new ArrayList<>();
if(!StringUtil.isEmpty(data.getParams())){
Gson gson = new Gson();
paramEntities = gson.fromJson(data.getParams(), new TypeToken<List<DigestiveDiagnosisItemEntity>>(){}.getType());
}
return diagnosisService.save(data,paramEntities);
}
service中的方法
/**
* 保存实体
*
* @param vo
* @return
*/
public ComServiceResVo save(DigestiveDiagnosisEntity vo, List<DigestiveDiagnosisItemEntity> paramEntities)
{
DigestiveDiagnosisEntity sp = digestiveDiagnosisRepository.save(vo);
for (DigestiveDiagnosisItemEntity paramEntity : paramEntities) {
paramEntity.setDiagnosisId(vo.getId() + "");
itemRepository.save(paramEntity);
}
return ComServiceResVo.ok(sp);
}
/**
* 保存实体
*
* @param vo
* @return
*/
public ComServiceResVo save(DigestiveDiagnosisEntity vo, List<DigestiveDiagnosisItemEntity> paramEntities)
{
DigestiveDiagnosisEntity sp = digestiveDiagnosisRepository.save(vo);
for (DigestiveDiagnosisItemEntity paramEntity : paramEntities) {
paramEntity.setDiagnosisId(vo.getId() + "");
itemRepository.save(paramEntity);
}
return ComServiceResVo.ok(sp);
}
/**
* 根据diagnosisId获取字表中的值
* @param diagnosisId
* @return
*/
public List<DigestiveDiagnosisItemEntity> getParams(String diagnosisId) {
return itemRepository.findAllByDiagnosisIdAndLogicDelFalse(diagnosisId);
}
/**
* 更新实体
* @param vo
* @return
*/
public ComServiceResVo update (DigestiveDiagnosisEntity vo, List<DigestiveDiagnosisItemEntity> paramEntities)
{
Optional<DigestiveDiagnosisEntity> opt = digestiveDiagnosisRepository.findById(vo.getId());
if (opt.isPresent())
{
DigestiveDiagnosisEntity entity = opt.get();
BeanUtils.copyProperties(vo,entity, new String[]{"createTime","creater","updateTime","updater"});
digestiveDiagnosisRepository.save(entity);
//先删除DigestiveDiagnosisItemEntity中 对应参数
itemRepository.deleteAllByDiagnosisId(entity.getId() + "");
for (DigestiveDiagnosisItemEntity paramEntity : paramEntities) {
paramEntity.setDiagnosisId(entity.getId() + "");
itemRepository.save(paramEntity);
}
return ComServiceResVo.ok("保存成功");
}
else
{
return ComServiceResVo.badRequest("该记录不存在或已经被删除");
}
}
小知识点:
1.layui中接收后台model的方式
model.addAttribute("data",data);
前台获取
let aData = [[${data}]];
2.layui,点击按钮,页面会刷新,如何处理
button,input type=button按钮在IE和w3c,firefox浏览器区别:
当在IE浏览器下面时,button标签按钮,input标签type属性为button的按钮是一样的功能,不会对表单进行任何操作。
但是在W3C浏览器,如Firefox下就需要注意了,button标签按钮会提交表单,而input标签type属性为button不会对表单进行任何操作。
解决办法:
方法一:将button标签更换为input
<input class="layui-btn test" >test</input>
方法二:
<button type="button" class="layui-btn test" >test</button>