1. 前言

我们本章节的内容主要是基于开源框架 Ruoyi-Vue 进行的改造,改造的模块为字典管理

本章节的内容会把 前面八篇文章的所有知识点全部融合进来,如下代码可能会存在一些冗余。但是可以将所学的只是串起来

2. 准备工作

项目地址:https://gitee.com/y_project/RuoYi-Vue

部署文档:http://doc.ruoyi.vip/ruoyi-vue/document/hjbs.html#%E9%83%A8%E7%BD%B2%E7%B3%BB%E7%BB%9F

项目代码:https://cdn.jsdelivr.net/gh/wicksonZhang/static-source-cdn/images/202308142321915.zip

3. 改造目标

主要改造的是前端页面信息

  • 界面信息

image-20230814135701182

image-20230814135727420

3.1. 老项目结构

  • 项目结构

    两个界面都是通过一个 Vue 页面就解决了,但这只是针对简单的页面信息可以这样构建。

    但这样也带了如下坏处

    • 可读性差: 一个页面包含大量的代码,包括多个不同的功能点,使得代码量巨大。这会导致代码的可读性变差,阅读和理解代码会变得困难。
    • 维护困难: 当一个组件包含太多的功能时,任何更改都可能影响到其他部分的功能,增加了维护的复杂性。如果有多人合作开发,更难协调工作。
    • 复用性差: 功能点紧密耦合在一个组件中,难以将某个功能独立出来,进行重复使用。
    • 测试困难: 难以进行有效的单元测试,因为需要同时考虑多个不同的功能点,增加了测试的复杂性。
    • 性能下降: 当页面中包含过多的功能点和状态时,可能会影响页面的性能,导致加载速度变慢,渲染变得缓慢。
    • 可维护性下降: 当代码组织不好时,新成员很难快速理解代码结构和逻辑,降低了项目的可维护性。
    • 逻辑混乱: 当很多功能混合在一个页面中时,不同功能的逻辑可能会相互干扰,导致代码混乱和错误。

image-20230814135932180

3.2. 新项目结构

image-20230814231850355

4. 具体实现

我们将一个表单拆分为四大块

  • 高级查询
  • 监听按钮
  • 表单数据
  • 新增编辑

4.1. 高级查询

  • dictQuery.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<template>
<el-form :model="queryParams" ref="queryForm" size="small" v-show="showSearch" label-width="68px" :inline="true" >
<el-form-item label="字典名称" prop="dictName">
<el-input
v-model="queryParams.dictName"
placeholder="请输入字典名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="字典类型" prop="dictType">
<el-input
v-model="queryParams.dictType"
placeholder="请输入字典类型"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="字典状态" clearable style="width: 240px">
<el-option v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</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>
</template>

<script>
import { EventBus } from '@/utils/eventBus';

export default {
name: 'dictQuery',
dicts: ['sys_normal_disable'],
data() {
return {
queryParams: {},
// 日期范围
dateRange: [],
showSearch: true
}
},
created() {
EventBus.$on('dictToolbarSearch', obj => {
this.showSearch = obj.showSearch
});
},
methods : {
/**
* 搜索按钮
*/
handleQuery() {
let queryForm = {
queryParams: this.queryParams,
dateRange: this.dateRange
}
this.$emit('onQuery', queryForm)
},
/**
* 重置按钮
*/
resetQuery() {
this.queryParams = {},
this.dateRange = []
}
}
}

</script>

4.2. 监听按钮

  • dictToolbar.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<template>
<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:dict:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['system:dict:edit']">修改</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:dict:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['system:dict:export']">导出</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-refresh" size="mini" @click="handleRefreshCache" v-hasPermi="['system:dict:remove']">刷新缓存</el-button>
</el-col>
</el-row>
</template>
<script>
import { EventBus } from '@/utils/eventBus';
import { getType, delType, refreshCache } from "@/api/system/dict/type";

export default {
name: 'dictToolbar',
props: {
// 选中数组
ids: {
type: Array,
require: true
},
// 非单个禁用
single: {
type: Boolean,
require: true
},
// 非多个禁用
multiple: {
type: Boolean,
require: true
},
// 表单参数
queryParams: {
type: Object
}
},
data() {
return {
// 显示搜索条件
showSearch: true
}
},
methods : {
/**
* 新增按钮操作
*/
handleAdd() {
console.log("handleAdd()")
EventBus.$emit('dictToolbarObj', {open: true, form: {}, title: "新增字典类型"});
},
/**
* 修改按钮操作
*/
handleUpdate(row) {
const dictId = row.dictId || this.ids
getType(dictId).then(response => {
if(response.data){
EventBus.$emit('dictToolbarObj', {open: true, form : response.data, title : "修改字典类型"});
}
});
},
/**
* 删除按钮操作
*/
handleDelete(row) {
const dictIds = row.dictId || this.ids;
this.$modal.confirm('是否确认删除字典编号为"' + dictIds + '"的数据项?')
.then(function () { return delType(dictIds); })
.then(() => {
this.$emit("onFlush");
this.$modal.msgSuccess("删除成功");
})
.catch(() => {});
},
/**
* 导出按钮操作
*/
handleExport() {
this.download('system/dict/type/export', {
...this.queryParams
}, `type_${new Date().getTime()}.xlsx`)
},
/**
* 刷新缓存按钮操作
*/
handleRefreshCache() {
refreshCache().then(() => {
this.$modal.msgSuccess("刷新成功");
this.$store.dispatch('dict/cleanDict');
});
}
}
}
</script>

4.3. 表单数据

  • dictPage.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<!-- 字典管理-列表 -->
<template>
<div class="app-container">
<!-- 高级搜索 -->
<dict-query @onQuery="onQuery"></dict-query>

<!-- 监听按钮数据 -->
<dict-toolbar ref="editOrDelete"
@onFlush="onFlush"
:single="this.single"
:multiple="this.multiple"
:ids="this.ids"
:queryParams="this.queryParams">
</dict-toolbar>

<!-- 列表信息-start -->
<el-table v-loading="loading" :data="typeList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="字典编号" align="center" prop="dictId" />
<el-table-column label="字典名称" align="center" prop="dictName" :show-overflow-tooltip="true" />
<el-table-column label="字典类型" align="center" :show-overflow-tooltip="true">
<template slot-scope="scope">
<router-link :to="'/system/dict-data/index/' + scope.row.dictId" class="link-type">
<span>{{ scope.row.dictType }}</span>
</router-link>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</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:dict:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['system:dict: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"/>
<!-- 列表信息-end -->

<!--字段新增编辑-->
<dict-add-edit ref="addEditCard" @onSuccess="onSuccess"></dict-add-edit>
</div>
</template>

<script>
import dictQuery from "./dictQuery.vue";
import dictToolbar from "./dictToolbar.vue";
import { listType } from "@/api/system/dict/type";
import DictAddEdit from "./dictAddEdit.vue";

export default {
name: "dictPage",
components: { dictQuery, dictToolbar, DictAddEdit },
dicts: ["sys_normal_disable"],
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 字典表格数据
typeList: [],
// 表单参数
queryParams: {
pageNum: 1,
pageSize: 10,
dictName: undefined,
dictType: undefined,
status: undefined,
},
// 时间数据范围
dateRange: [],
//
queryForm: {},
// 总条数
total: 0,
};
},
/**
* 当所有节点初始化之后调用接口
*/
mounted() {
this.getList();
},
methods: {
/**
* 修改按钮操作
*/
handleUpdate(row) {
this.$refs["editOrDelete"].handleUpdate(row);
},
/**
* 删除按钮操作
*/
handleDelete(row) {
this.$refs["editOrDelete"].handleDelete(row);
},
/**
* 查询字典类型列表
*/
getList() {
this.loading = true;
listType(this.addDateRange(this.queryParams, this.dateRange)).then(
(response) => {
this.typeList = response.rows;
this.total = response.total;
this.loading = false;
}
);
},
/**
* 搜索按钮
*/
onQuery(queryForm = {}) {
this.queryParams = queryForm.queryParams;
this.dateRange = queryForm.dateRange;
this.getList();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map((item) => item.dictId);
this.single = selection.length != 1;
this.multiple = !selection.length;
},
/**
* 刷新页面
*/
onFlush() {
this.getList();
},
/**
* 新增成功之后调用父组件
*/
onSuccess() {
this.getList();
},
},
};
</script>

4.4. 新增页面

  • dictAddEdit.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<template>
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="字典名称" prop="dictName">
<el-input v-model="form.dictName" placeholder="请输入字典名称" />
</el-form-item>
<el-form-item label="字典类型" prop="dictType">
<el-input v-model="form.dictType" placeholder="请输入字典类型" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
</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>
</template>

<script>
import { EventBus } from '@/utils/eventBus';
import { updateType, addType } from "@/api/system/dict/type";

export default {
name: 'dictAddEdit',
dicts: ['sys_normal_disable'],
data() {
return {
title : '',
// 是否显示弹出层
open: false,
// 表单参数
form: {},
// 表单校验
rules: {
dictName: [
{ required: true, message: "字典名称不能为空", trigger: "blur" }
],
dictType: [
{ required: true, message: "字典类型不能为空", trigger: "blur" }
]
}
}
},
created() {
EventBus.$on('dictToolbarObj', obj => {
this.open = obj.open;
this.form = obj.form;
this.title = obj.title
});
},
methods : {
/**
* 提交表单
*/
submitForm() {
this.$refs.form.validate(valid => {
if (valid) {
if (this.form.dictId != undefined) {
updateType(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.$emit('onSuccess')
});
} else {
addType(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/**
* 取消表单
*/
cancel() {
this.$refs.form.clearValidate()
this.open = false
this.form = {}
}
}
}
</script>