组合数据实现
-
实现组合数据的目的是为了实现客户端前端轮播图、导航按钮、菜单等动态配置。
-
此功能可以在后台动态配置前端需要的字段内容,具体效果如下图所示
具体实现
数据库设计
-
组合数据分类表 实现对数据的分类
create table sys_group_category ( id bigint unsigned not null auto_increment comment 'ID', category_name varchar(100) default '' comment '数据组名称', category_info varchar(255) default '' comment '数据提示', category_key varchar(63) default '' comment '数据字段', content text comment '数据组字段', category_type tinyint default 0 comment '分类类型', del_flag tinyint default 0 comment '删除状态', status tinyint default 0 comment '数据状态', create_by varchar(64) default '' comment '创建者', create_time datetime comment '创建时间', update_by varchar(64) default '' comment '更新者', update_time datetime comment '更新时间', primary key (id) ); alter table sys_group_category comment '组合数据分类表';
-
组合数据表 具体的数据
create table sys_group_data ( id bigint unsigned not null auto_increment comment 'ID', category_id bigint default 0 comment '分类ID', group_value text comment '数据组值', group_key varchar(63) default '' comment '数据字段', sort int(4) default 0 comment '排序', del_flag tinyint default 0 comment '删除状态', status tinyint default 0 comment '数据状态', create_by varchar(64) default '' comment '创建者', create_time datetime comment '创建时间', update_by varchar(64) default '' comment '更新者', update_time datetime comment '更新时间', primary key (id) ); alter table sys_group_data comment '组合数据表';
动态表格编辑
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px">
<el-form-item label="数据组名称" prop="categoryName">
<el-input v-model="queryParams.categoryName" placeholder="请输入数据组名称" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="数据字段" prop="categoryKey">
<el-input v-model="queryParams.categoryKey" placeholder="请输入数据字段" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['system:sysGroupCategory:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['system:sysGroupCategory:remove']">删除</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="sysGroupCategoryList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="编号" align="center" prop="id" width="60" />
<el-table-column label="数据组名称" align="center" prop="categoryName" />
<el-table-column label="数据字段" align="center" prop="categoryKey" />
<el-table-column label="数据介绍" align="center" prop="categoryInfo" />
<el-table-column label="数据状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.common_data_status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:sysGroupCategory:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-s-order" @click="gotoDataList(scope.row)" v-hasPermi="['system:sysGroupCategory:edit']">数据列表</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:sysGroupCategory:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<!-- 添加或修改组合数据分类对话框 -->
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="数据组名称" prop="categoryName">
<el-input v-model="form.categoryName" placeholder="请输入数据组名称" />
</el-form-item>
<el-form-item label="数据字段" prop="categoryKey">
<el-input v-model="form.categoryKey" placeholder="请输入数据字段" />
</el-form-item>
<el-form-item label="数据介绍" prop="categoryInfo">
<el-input v-model="form.categoryInfo" placeholder="请输入数据提示" />
</el-form-item>
<el-form-item v-for="(item, index) in form.fields" :label="'字段' + (index + 1)" :key="item.key" :prop="'fields.' + index + '.value'">
<el-row>
<el-col :span="6">
<el-input v-model="item.name" placeholder="字段名称"></el-input>
</el-col>
<el-col :span="6">
<el-input v-model="item.field" placeholder="字段"></el-input>
</el-col>
<el-col :span="6">
<el-select v-model="item.type" placeholder="字段类型">
<el-option label="文本框" value="input" />
<el-option label="文本域" value="textarea" />
<el-option label="下拉框" value="select" />
<el-option label="单选框" value="radio" />
<el-option label="复选框" value="checkbox" />
<el-option label="日期控件" value="datetime" />
<el-option label="图片上传" value="imageUpload" />
<el-option label="文件上传" value="fileUpload" />
<el-option label="富文本控件" value="editor" />
</el-select>
</el-col>
<el-col :span="6">
<el-button @click.prevent="removeFields(item)">删除</el-button>
</el-col>
</el-row>
</el-form-item>
<el-form-item>
<el-button @click="addFields">新增字段</el-button>
</el-form-item>
<el-form-item label="数据状态">
<el-radio-group v-model="form.status">
<el-radio v-for="dict in dict.type.common_data_status" :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
listSysGroupCategory,
getSysGroupCategory,
delSysGroupCategory,
addSysGroupCategory,
updateSysGroupCategory,
} from "@/api/system/sysGroupCategory";
export default {
name: "SysGroupCategory",
dicts: ["common_data_status"],
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 组合数据分类表格数据
sysGroupCategoryList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
categoryName: null,
categoryInfo: null,
categoryKey: null,
content: null,
categoryType: null,
status: null,
},
// 表单参数
form: {
fields: [],
},
// 表单校验
rules: {},
};
},
created() {
this.getList();
},
methods: {
// 跳转数据列表
gotoDataList(row) {
this.$router.push({
path: "/system/group-data/index/" + row.id,
});
},
// 移除字段
removeFields(item) {
var index = this.form.fields.indexOf(item);
if (index !== -1) {
this.form.fields.splice(index, 1);
}
},
// 添加字段
addFields() {
this.form.fields.push({
name: "",
field: "",
type: "",
params: "",
});
},
/** 查询组合数据分类列表 */
getList() {
this.loading = true;
listSysGroupCategory(this.queryParams).then((response) => {
this.sysGroupCategoryList = response.rows;
this.total = response.total;
this.loading = false;
});
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
this.form = {
id: null,
categoryName: null,
categoryInfo: null,
categoryKey: null,
content: "",
fields: [],
categoryType: null,
delFlag: null,
status: 0,
createBy: null,
createTime: null,
updateBy: null,
updateTime: null,
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map((item) => item.id);
this.single = selection.length !== 1;
this.multiple = !selection.length;
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加组合数据分类";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const id = row.id || this.ids;
getSysGroupCategory(id).then((response) => {
let form = response.data;
form.fields = JSON.parse(form.content);
this.form = form;
this.open = true;
this.title = "修改组合数据分类";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate((valid) => {
if (valid) {
let form = this.form;
form.content = JSON.stringify(this.form.fields);
if (this.form.id != null) {
updateSysGroupCategory(form).then((response) => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addSysGroupCategory(form).then((response) => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal
.confirm('是否确认删除组合数据分类编号为"' + ids + '"的数据项?')
.then(function () {
return delSysGroupCategory(ids);
})
.then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
})
.catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
this.download(
"system/sysGroupCategory/export",
{
...this.queryParams,
},
`sysGroupCategory_${new Date().getTime()}.xlsx`
);
},
},
};
</script>
动态字段展示
<template>
<div class="app-container">
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['system:sysGroupCategory:add']">新增</el-button>
</el-col>
</el-row>
<el-table v-loading="loading" :data="sysGroupDataList">
<el-table-column label="编号" align="center" prop="id" width="60" />
<el-table-column v-for="(item, index) in tableColumn" :key="index" :label="item.name" :prop="'groupValue.' + item.field " align="center" />
<el-table-column label="数据字段" align="center" prop="groupKey" />
<el-table-column label="数据状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.common_data_status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:sysGroupCategory:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:sysGroupCategory:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<!-- 添加或修改组合数据对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<div v-for="(item, index) in tableColumn" :key="index">
<el-form-item :label="item.name">
<el-input v-model="form.groupValue[item.field]" placeholder="请输入数据字段" v-if="item.type == 'input'" />
<image-upload v-model="form.groupValue[item.field]" v-if="item.type == 'imageUpload'" :limit="1" />
</el-form-item>
</div>
<el-form-item label="排序" prop="sort">
<el-input v-model="form.sort" placeholder="请输入排序" type="number" />
</el-form-item>
<el-form-item label="数据状态">
<el-radio-group v-model="form.status">
<el-radio v-for="dict in dict.type.common_data_status" :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { getSysGroupCategory } from "@/api/system/sysGroupCategory";
import {
listSysGroupData,
getSysGroupData,
delSysGroupData,
addSysGroupData,
updateSysGroupData,
} from "@/api/system/sysGroupData";
export default {
dicts: ["common_data_status"],
data() {
return {
categoryId: 0,
tableData: [],
tableColumn: [],
categoryInfo: {},
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 组合数据表格数据
sysGroupDataList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
categoryId: null,
groupValue: null,
groupKey: null,
sort: null,
status: null,
},
// 表单参数
form: {
groupValue: {},
},
// 表单校验
rules: {},
};
},
created() {
const categoryId = this.$route.params && this.$route.params.categoryId;
this.categoryId = categoryId;
this.getSysGroupCategoryInfo();
this.getList();
},
methods: {
getSysGroupCategoryInfo() {
getSysGroupCategory(this.categoryId).then((res) => {
this.categoryInfo = res.data;
this.tableColumn = JSON.parse(res.data.content);
});
},
// 表单重置
reset() {
let tableColumn = this.tableColumn;
let groupValue = {};
tableColumn.forEach((item) => {
groupValue[item.field] = null;
});
this.form = {
id: null,
categoryId: null,
groupValue: groupValue,
groupKey: null,
sort: null,
delFlag: null,
status: 0,
createBy: null,
createTime: null,
updateBy: null,
updateTime: null,
};
this.resetForm("form");
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加组合数据";
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate((valid) => {
if (valid) {
this.form.groupValue = JSON.stringify(this.form.groupValue);
this.form.categoryId = this.categoryId;
console.log(this.categoryInfo);
this.form.groupKey = this.categoryInfo.categoryKey;
if (this.form.id != null) {
updateSysGroupData(this.form).then((response) => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addSysGroupData(this.form).then((response) => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
getList() {
this.loading = true;
listSysGroupData({
categoryId: this.categoryId,
}).then((response) => {
let sysGroupDataList = response.rows;
sysGroupDataList.forEach((item) => {
item.groupValue = JSON.parse(item.groupValue);
});
this.sysGroupDataList = sysGroupDataList;
console.log(sysGroupDataList);
this.total = response.total;
this.loading = false;
});
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const id = row.id || this.ids;
getSysGroupData(id).then((response) => {
this.form = response.data;
this.form.groupValue = JSON.parse(this.form.groupValue);
this.open = true;
this.title = "修改组合数据";
});
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal
.confirm('是否确认删除组合数据编号为"' + ids + '"的数据项?')
.then(function () {
return delSysGroupData(ids);
})
.then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
})
.catch(() => { });
},
},
};
</script>
<style>
</style>
组合数据查询
/**
* 查询组合数据列表 通过key
* @param key
* @return
*/
@Override
public List<JSONObject> selectSysGroupDataListByKey(String key) {
List<SysGroupData> sysGroupData = sysGroupDataMapper.selectSysGroupDataListByKey(key);
List<JSONObject> collect = sysGroupData.stream().map(item -> JSONUtil.parseObj(item.getGroupValue())).collect(Collectors.toList());
return collect;
}
首页信息获取
/**
* 首页信息
* @return
*/
@Override
public R homeInfo() {
// 获取首页轮播图
List<JSONObject> banners = sysGroupDataService.selectSysGroupDataListByKey("index_banner");
// 获取首页菜单栏
List<JSONObject> menus = sysGroupDataService.selectSysGroupDataListByKey("index_menu");
HomeInfoVo homeInfoVo = new HomeInfoVo(menus, banners);
return R.ok(homeInfoVo);
}
客户端首页
<template>
<view class="">
<!-- 轮播图 -->
<swiper class="screen-swiper square-dot" :indicator-dots="true" :circular="true"
:autoplay="true" interval="5000" duration="500">
<swiper-item v-for="(item,index) in banners" :key="index">
<image :src="item.img" mode="aspectFill" ></image>
</swiper-item>
</swiper>
<!-- 导航栏 -->
<view class="cu-list grid solids-bottom col-4 no-border">
<view class="cu-item align-center" v-for="(item, index) in menus" :key="index">
<view class="cu-avatar lg round" :style="{ backgroundImage: `url(${item.img})` }"></view>
<text>{{ item.name }}</text>
</view>
</view>
</view>
</template>
<script>
import { homeInfo } from '@/api/api.js'
export default {
data() {
return {
banners: [], // 轮播图
menus: [], // 导航菜单
}
},
onLoad() {
homeInfo().then(res => {
this.banners = res.data.banners;
this.menus = res.data.menus;
})
},
methods: {
}
}
</script>
效果如下图所示:
完整代码
gitee.com/zouhuu_admin/RuoYi-Vue-Staging