Plan
- 优化白名单功能,增加修改数据模块,使可以通过前端CRUD单个服务名。
难点:
- 要考虑设计问题:整条服务名列表是一个字符串,单条服务名以”;"间隔,如com.ids;com.systemui; 现在需要实现点击“修改按钮”,能对单条服务名进行增删改。讨论过后可以两种实现方案,一种是仿造微信白名单功能,一种是用列表来展示出整条服务名列表中的每一个服务名。
- 要考虑用户乱输入数据情况,比如输入多个“;;;”输入中文“;”,忘记输入“;",加了很多空格等的情况
- 不能在数据库新建表,因为导师说会造成数据冗余。
- 要实现点击“修改数据”出现的弹窗实现全覆盖页面,给用户感觉是新打开了一个页面,但其实是一个弹窗。
效果:
优化前:
优化后:
第一种:1.仿造微信白名单实现效果如下,这种导师说用户改动自由度太高,容易造成数据错误,所以不行
最终采用第二种:列表来实现,效果如下:
点击"修改数据"后弹出如下:
新增功能:
编辑功能:
用户可在此弹出框对单个服务名进行增删改,操作完后可点击“提交”按钮,就实现了修改服务名列表数据,同时版本号会+1。点击“关闭”会提示如下:
Do
第一步:增加"修改数据"按钮,和对应弹出框
<template>
<div class="execution">
<basic-container>
<el-row :gutter="10">
<el-col :span="this.clickObj ? 0 : 24">
<el-button type="primary" @click="handleAdd">新增</el-button>
<avue-crud
ref="crud"
:page.sync="page"
:data="tableData"
:table-loading="tableLoading"
:option="tableOption"
v-model="form"
@on-load="getPage"
@refresh-change="refreshChange"
@row-update="handleUpdate"
@row-save="handleSave"
@row-del="handleDel"
@sort-change="sortChange"
@search-change="searchChange"
>
<template slot="menu" slot-scope="scope">
<el-button
type="text"
icon="el-icon-view"
size="small"
plain
@click="handleItem(scope.row, scope.index)"
>修改数据
</el-button>
</template>
</avue-crud>
<!-- 用户新增对话框 -->
<el-dialog
:title="dialog.title"
:visible.sync="dialog.open"
width="1000px"
append-to-body
row-key="id"
>
<template>
<div>
<span style="margin-left: 10px">服务名称列表</span>
</div>
<el-input
required="true"
v-model="dialog.serviceNameList"
:rows="3"
type="textarea"
placeholder="请输入服务名称列表"
/>
<div>
<span style="margin-left: 10px">车厂名称</span>
</div>
<el-select
placeholder="请选择车厂"
v-model="dialog.vehicleFactoryName"
>
<el-option
required="true"
v-for="item in dialog.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="handleSave">确 定</el-button>
<el-button @click="dialog.open = false">取 消</el-button>
</div>
</el-dialog>
</el-col>
<el-col :span="24" v-if="this.clickObj">
<el-card class="box-card">
<el-header>
<h3 style="float: left">
<i class="el-icon-document-copy"></i>
服务名列表{{ this.clickObj.type }}
</h3>
<el-row style="float: right">
<el-button type="success" @click="handleUpdate">提交</el-button>
<el-button type="danger" @click="handleItem()">关闭</el-button>
</el-row>
</el-header>
<avue-crud
ref="crud"
:page.sync="page2"
:data="tableData2"
:table-loading="tableLoading"
:option="tableOption2"
:before-open="beforeOpen2"
v-model="form2"
@on-load="getPage2"
@refresh-change="refreshChange2"
@row-update="handleUpdate2"
@row-save="handleSave2"
@row-del="handleDel2"
@sort-change="sortChange2"
@search-change="searchChange2"
>
</avue-crud>
</el-card>
</el-col>
</el-row>
</basic-container>
</div>
</template>
其中: 实现点击“修改数据”出现的弹窗实现全覆盖页面,给用户感觉是新打开了一个页面,但其实是一个弹窗。
**答案:**通过定义一个clickObj,并给弹出的avue添加:before-open="beforeOpen2"具体如下:
beforeOpen2方法:
beforeOpen2(done) {
this.$set(this.form2, "id", this.clickObj.id);
this.$set(this.form2, "type", this.clickObj.type);
done();
},
第二步:添加table
export const tableOption = {
dialogDrag: true,
border: true,
indexLabel: '序号',
stripe: true,
menuAlign: 'center',
align: 'center',
menuType: 'text',
searchShow: false,
excelBtn: false,
printBtn: false,
addBtn: false,
editBtn: false,
delBtn: false,
viewBtn: false,
selection: false,
column: [
{
type: 'textarea',
label: '服务名列表',
prop: 'serviceNameList',
search: false,
slot: true,
width: 500,
headerslot: true,
},
{
label: '版本',
prop: 'version',
search: false,
slot: true,
headerslot: true,
},
{
label: '车厂',
prop: 'vehicleFactoryName',
search: false,
slot: true,
headerslot: true,
type: 'select',
dicData: [{
label: '一',
value: 'w'
}, {
label: '上',
value: 's'
}]
},
{
label: '创建时间',
prop: 'createTime',
display: false,
rules: [
{
required: true,
message: '请输入创建时间',
trigger: 'blur'
},
],
format: 'yyyy-MM-dd HH:mm:ss',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
}
]
}
export const tableOption2 = {
dialogDrag: true,
border: true,
indexLabel: '序号',
stripe: true,
menuAlign: 'center',
align: 'center',
menuType: 'text',
searchShow: false,
excelBtn: false,
printBtn: false,
addBtn: true,
editBtn: true,
delBtn: true,
viewBtn: false,
selection: false,
menu: true,
columnBtn: false,
refreshBtn:false,
searchBtn:false,
addTitle:"新增单个服务名",
column: [
{
type: 'input',
label: '服务名列表',
prop: 'serviceNameModifyList',
slot: true,
headerslot: true,
}
]
}
第三步:前后端交互js
```javascript
import ajaxRequest from '../ajaxRequest'
export function getPage(query) {
return ajaxRequest({
url: '/whitelist/page',
method: 'get',
params: query
})
}
export function addObj(obj) {
return ajaxRequest({
url: '/whitelist',
method: 'post',
data: obj
})
}
export function getObj(id) {
return ajaxRequest({
url: '/whitelist/' + id,
method: 'get'
})
}
export function delObj(id) {
return ajaxRequest({
url: '/whitelist/' + id,
method: 'delete'
})
}
export function putObj(obj) {
return ajaxRequest({
url: '/whitelist',
method: 'put',
data: obj
})
}
第四步:添加相应方法
<script>
import {
addObj,
delObj,
getPage,
putObj,
getObj,
} from "@/api/whiteList/whiteList";
import { tableOption, tableOption2 } from "@/constant/whiteList/whiteList";
export default {
name: "whiteList",
data() {
return {
clickObj: null,
//白名单列表
dialog: {
title: "新增白名单",
open: false,
serviceNameList: "",
vehicleFactoryName: "",
options: [
{
value: "w",
label: "一",
},
{
value: "s",
label: "上",
},
],
},
tableData: [],
page: {
total: 0, // 总页数
pageNum: 1, // 当前页数
pageSize: 10, // 每页显示多少条
ascs: [], //升序字段
descs: "create_time", //降序字段
},
paramsSearch: {},
tableLoading: false,
tableOption: tableOption,
//修改数据列表
form2: {},
tableData2: [],
page2: {
total: 0, // 总页数
currentPage: 1, // 当前页数
pageSize: 10, // 每页显示多少条
},
tableLoading2: false,
tableOption2: tableOption2,
paramsSubmit: {
id: "",
serviceNameList: "",
},
};
},
created() {},
mounted: function () {},
computed: {},
methods: {
handleAdd() {
this.dialog.open = true;
},
searchChange(params, done) {
params = this.filterForm(params);
this.paramsSearch = params;
this.page.currentPage = 1;
this.getPage(this.page, params);
done();
},
sortChange(val) {
let prop = val.prop
? val.prop.replace(/([A-Z])/g, "_$1").toLowerCase()
: "";
if (val.order == "ascending") {
this.page.descs = [];
this.page.ascs = prop;
} else if (val.order == "descending") {
this.page.ascs = [];
this.page.descs = prop;
} else {
this.page.ascs = [];
this.page.descs = [];
}
this.getPage(this.page);
},
getPage(page, params) {
this.tableLoading = true;
getPage(
Object.assign(
{
status: 1,
current: page.currentPage,
size: page.pageSize,
descs: this.page.descs,
ascs: this.page.ascs,
},
params,
this.paramsSearch
)
)
.then((response) => {
this.tableData = response.data.records;
this.page.total = response.data.total;
(this.page.currentPage = page.currentPage),
(this.page.pageSize = page.pageSize),
(this.tableLoading = false);
})
.catch(() => {
this.tableLoading = false;
});
},
/**
* @title 数据删除
* @param row 为当前的数据
* @param index 为当前删除数据的行数
*
**/
handleDel: function (row, index) {
var _this = this;
this.$confirm("是否确认删除此数据", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
return delObj(row.id);
})
.then((data) => {
_this.$message({
showClose: true,
message: "删除成功",
type: "success",
});
this.getPage(this.page);
})
.catch(function (err) {});
},
/**
* @title 数据更新
* @param row 为当前的数据
* @param index 为当前更新数据的行数
* @param done 为表单关闭函数
*
**/
handleUpdate: function (row, index, done, loading) {
var str = new String();
for (let rows of this.tableData2) {
str += rows.serviceNameModifyList;
}
this.paramsSubmit.serviceNameList = str;
putObj(this.paramsSubmit)
.then((data) => {
this.clickObj = null;
this.$message({
showClose: true,
message: "修改成功",
type: "success",
});
this.getPage(this.page);
done();
})
.catch(() => {
loading();
});
},
/**
* @title 数据添加
* @param row 为当前的数据
* @param done 为表单关闭函数
*
**/
handleSave: function () {
this.dialog.serviceNameList= this.dialog.serviceNameList.trim();
if(this.dialog.serviceNameList.substr(-1)!=";"){
this.dialog.serviceNameList+=";";
}
addObj(
Object.assign({
vehicleFactoryName: this.dialog.vehicleFactoryName,
serviceNameList: this.dialog.serviceNameList,
})
)
.then((resp) => {
if (resp.ok === false) {
this.$message({
showClose: true,
message: "添加失败, " + resp.msg,
type: "fail",
});
done();
this.getPage(this.page);
} else {
this.$message({
showClose: true,
message: "添加成功",
type: "success",
});
this.resetDialog();
this.dialog.open = false;
this.getPage(this.page);
}
})
.catch(() => {
loading();
});
},
/**
* 重置表单
*/
resetDialog() {
this.dialog.serviceNameList = "";
this.dialog.vehicleFactoryName = "";
},
/**
* 刷新回调
*/
refreshChange(page) {
this.getPage(this.page);
},
handleItem: function (row) {
let isExecution = true;
if (row) {
this.clickObj = row;
this.paramsSubmit.id = row.id;
this.page2.currentPage = 1;
this.getPage2(row, this.page2, isExecution);
} else {
this.$confirm("此操作将不会保存你的修改, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
this.clickObj = null;
});
}
},
beforeOpen2(done) {
this.$set(this.form2, "id", this.clickObj.id);
this.$set(this.form2, "type", this.clickObj.type);
done();
},
getPage2(row, index, isExecution, params) {
this.tableLoading2 = true;
getObj(row.id).then((response) => {
if (isExecution) {
var strs = new Array(); //定义一数组
strs=response.data.serviceNameList;
strs = strs.split(";");
strs = strs.slice(0, -1);//去掉最后的空格
const returnList = [];
for (let serviceName of strs) {
let obj = {
serviceNameModifyList: serviceName + ";",
};
returnList.push(obj);
}
this.tableData2 = returnList;
}
this.page2.total = returnList.length;
});
},
/**
* @title 数据更新
* @param row 为当前的数据
* @param index 为当前更新数据的行数
* @param done 为表单关闭函数
*
**/
handleUpdate2: function (row, index, done, loading) {
this.$message({
showClose: true,
message: "修改成功",
type: "success",
});
loading();
done();
this.getPage2(row, index);
var serviceNameModifyStr = this.dealStr(row.serviceNameModifyList);
this.tableData2[index].serviceNameModifyList = serviceNameModifyStr + ";";
},
/**
* @title 数据删除
* @param row 为当前的数据
* @param index 为当前删除数据的行数
*
**/
handleDel2: function (row, index) {
var _this = this;
this.$confirm("是否确认删除此数据", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then((data) => {
_this.$message({
showClose: true,
message: "删除成功",
type: "success",
});
this.getPage2(row, index);
this.tableData2.splice(index, 1);
})
.catch(function (err) {});
},
/**
* @title 数据添加
* @param row 为当前的数据
* @param done 为表单关闭函数
*
**/
handleSave2: function (row, done, loading) {
var str = row.serviceNameModifyList;
str = this.dealStr(str);
let obj = {
serviceNameModifyList: str + ";",
};
this.tableData2.unshift(obj);
this.$message({
showClose: true,
message: "添加成功",
type: "success",
});
done();
loading();
},
/**
* @title 处理字符串
* @param str 为当前的数据
*
**/
dealStr(str) {
str = str.replaceAll(";", ""); //去掉所有;
str = str.replaceAll(";", ""); //去掉所有中文;
str = str.trim(); //把数据进行去前后的空格和换行
return str;
},
},
};
</script>
<style lang="scss" scoped>
@import "~@/styles/commonCss.scss";
</style>
其中,点击提交按钮是 调用handleUpdate方法,把paramsSubmit传入后端进行修改修改服务名列表,因此后端也要修改。
第五步:后端
第一步:WhiteListUpdateDTO
@Data
public class WhiteListUpdateDTO {
private String id;
/**
* 服务名称列表
*/
private String serviceNameList;
}
第二步:control
@ApiOperation(value = "修改白名单记录")
@PutMapping
public R update(@RequestBody WhiteListUpdateDTO whiteListUpdateDTO) {
return R.ok(whiteListService.updateWhiteList(whiteListUpdateDTO));
}
第三步 :WhiteListService
public interface WhiteListService extends IService<WhiteList> {
R updateWhiteList(WhiteListUpdateDTO whiteListUpdateDTO);
}
第四步:WhiteListServiceImpl
@DubboService(version = "1.0.0")
public class WhiteListServiceImpl extends ServiceImpl<WhiteListDao, WhiteList> implements WhiteListService {
@Override
public R updateWhiteList(WhiteListUpdateDTO whiteListUpdateDTO) {
if (StrUtil.isBlank(whiteListUpdateDTO.getId())) {
return R.failed("id值不能为空,请检查!");
}
WhiteList whiteList = whiteListDao.selectById(whiteListUpdateDTO.getId());
if(ObjectUtil.isNull(whiteList)){
return R.failed("id值有误,请检查!");
}
//校验变更
if (ObjectUtil.equal(whiteListUpdateDTO.getServiceNameList(), whiteList.getServiceNameList())) {
return R.failed("服务名称列表没有变化,请检查!");
}
whiteList.setServiceNameList(whiteListUpdateDTO.getServiceNameList());
whiteList.setVersion(getNewVersionByRecord(whiteList));
whiteListDao.updateById(whiteList);
return R.ok();
}
/**
* @Description: 更新版本号进行自增
*/
private int getNewVersionByRecord(WhiteList whiteListRecord) {
int newVersion;
if (ObjectUtil.isNull(whiteListRecord)) {
return 0;
}
newVersion = whiteListRecord.getVersion() + 1;
return newVersion;
}
}