若依开发笔记-4:源码分析

若依源码阅读

本章我们将围绕入门案例生成的课程管理进行讲解,包含前后端代码的分析,以及前后端代码交互的流程,通过这部分的学习,不仅能让我们掌握若依的基础业务逻辑,在此基础上还能为我们日后的定制开发提供强有力的支撑。

前端代码分析

index.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
 <!-- 搜索表单 start -->
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
// :model双向绑定,将前端录入的条件封装成响应式对象 -->
// v-show 控制搜索栏是显示还是隐藏
<el-form-item label="课程编码" prop="code">
<el-input
v-model="queryParams.code"
placeholder="请输入课程编码"
clearable //清除用户输入的文本恢复到占位符提示信息
@keyup.enter="handleQuery"//键盘的回车事件
/>
</el-form-item>
<el-form-item label="课程学科" prop="subject">
<el-select v-model="queryParams.subject" placeholder="请选择课程学科" clearable>
<el-option
v-for="dict in course_subject"
:key="dict.value"
:label="dict.label" //下拉列表展示的是label属性字典标签
:value="dict.value" //用户提交的是value属性,字典值
/>
</el-select>
</el-form-item>
<el-form-item label="课程名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入课程名称"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="适用人群" prop="applicablePerson">
<el-input
v-model="queryParams.applicablePerson"
placeholder="请输入适用人群"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 搜索表单 end -->

<!-- 按钮区域 start -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary" //控制菜单的颜色
plain //控制菜单的样式
icon="Plus" ///控制菜单的图标参考ELement的官方文档进行设置
@click="handleAdd"
//v-hasPermi自定义的属性结合IBAC权限控制模型来完成菜单按钮的显示或隐藏
v-hasPermi="['course:course:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single" //控制该按钮是否可用
@click="handleUpdate"
v-hasPermi="['course:course:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple" //multiple使下拉框变为多选下拉框
@click="handleDelete"
v-hasPermi="['course:course:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['course:course:export']"
>导出</el-button>
</el-col>
//showSearch控制搜索栏是显示还是隐藏
//触发queryTable事件调用getList方法重新加载表格展示的数据。
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 按钮区域end -->

数据展示

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
 <!-- 数据展示表格 start -->
// v-loading一个指令,用于控制表格的加载状态 ,如果后台网络很慢,
//网络迟迟没有回应,那么前端就会出现一个加载中的状态。

//:data一个绑定属性,用于指定表格的数据源,表格进行遍历,展示每一条数据。
//@selection-change一个事件的监听器 ,用于监听选中行的变化
<el-table v-loading="loading" :data="courseList" @selection-change="handleSelectionChange">
//type="selection"用户勾选一个复选框,这边就会处触发一个事件监听,
//调用handleSelectionChange方法,来处理后续的业务逻辑

<el-table-column type="selection" width="55" align="center" />
//通过label指令来指定列的标题
<el-table-column label="课程id" align="center" prop="id" />
<el-table-column label="课程编码" align="center" prop="code" />
<el-table-column label="课程学科" align="center" prop="subject">
//模板插槽,通过"scope"获取整个表格的数据,"scope.row.subject"取到当前行拿到字典值,
//然后把字典值交给tag组件,该组件就拿字典值匹配字典数据列表,找到该
//字典值对应的字典标签,然后显示到前端页面。
<template #default="scope">
<dict-tag :options="course_subject" :value="scope.row.subject"/>
</template>
</el-table-column>
<el-table-column label="课程名称" align="center" prop="name" />
<el-table-column label="价格" align="center" prop="price" />
<el-table-column label="适用人群" align="center" prop="applicablePerson" />
<el-table-column label="课程介绍" align="center" prop="info" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
//link type="primary" icon="Edit"这三个属性是CSS样式和按钮的图标
//@click="handleUpdate(scope.row)" 给该按钮绑定了一个点击事件,
//用户点击按钮会调用handleUpdate方法把当前行的数据传给当前方法去执行业务逻辑。
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['course:course:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['course:course:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 数据展示表格 end -->

分页区域

1
2
3
4
5
6
7
8
<!-- 分页区域 start -->
<pagination
v-show="total>0" <!--返回的数据>0就会显示,反之就会隐藏 -->
:total="total" //展示总条数
v-model:page="queryParams.pageNum" //展示分页页码,并对当前页进行高亮显示
v-model:limit="queryParams.pageSize"//展示每页显示的条数
@pagination="getList"//分页事件,比如修改每页显示条数,从第2页跳到第7页
/>

添加对话框

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
 <!-- 添加或修改课程管理对话框 -->
//<el-dialog 该标签默认在页面是隐藏的当用户点击新增或修改按钮时通过双向绑定
//将open的属性值改为true,那么对话框就可以弹出了填充完弹出的对话框数据点击确认按钮
//将对话框元素添加到body元素上就可以在页面进行弹框展示了
//"title"通过属性进行动态绑定因为新增跟修改使用同一个对话框
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
//通过model来完成双向绑定,用户输入的数据都会封装到form表单。
//rules就是表单的规则,比如哪些是用户必须输入的。
<el-form ref="courseRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="课程编码" prop="code">
<el-input v-model="form.code" placeholder="请输入课程编码" />
</el-form-item>
<el-form-item label="课程学科" prop="subject">
<el-select v-model="form.subject" placeholder="请选择课程学科">
<el-option
v-for="dict in course_subject"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="课程名称" prop="name">
<el-input v-model="form.name" placeholder="请输入课程名称" />
</el-form-item>
<el-form-item label="价格" prop="price">
<el-input v-model="form.price" placeholder="请输入价格" />
</el-form-item>
<el-form-item label="适用人群" prop="applicablePerson">
<el-input v-model="form.applicablePerson" placeholder="请输入适用人群" />
</el-form-item>
<el-form-item label="课程介绍" prop="info">
<el-input v-model="form.info" placeholder="请输入课程介绍" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</template>
</el-dialog>
</div>
</template>

<script setup name="Course">

js代码

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
172
173
// 引入后端api接口
import { listCourse, getCourse, delCourse, addCourse, updateCourse } from "@/api/course/course";
// 获取当前实例代理对象,用于访问组件数据、方法
const { proxy } = getCurrentInstance();
// 获取课程学科的数据字典
const { course_subject } = proxy.useDict('course_subject');
// 列表数据
const courseList = ref([]);
// 是否显示弹框
const open = ref(false);
// 是否显示加载状态
const loading = ref(true);
// 是否显示搜索栏
const showSearch = ref(true);
// 复选框,被选中id的数组
const ids = ref([]);
// 复选框,是否单选,用于高亮修改、删除按钮
const single = ref(true);
// 复选框,是否多选,仅高亮删除按钮
const multiple = ref(true);
// 总(记录)条数
const total = ref(0);
// 用于区分新增、修改对话框标题
const title = ref("");
// 定义reactive响应式对象
const data = reactive({
// 新增或修改表单数据
form: {},
// 搜索条件参数
queryParams: {
pageNum: 1,
pageSize: 10,
code: null,
subject: null,
name: null,
applicablePerson: null,
},
// 表单校验规则
rules: {
code: [
{ required: true, message: "课程编码不能为空", trigger: "blur" }
],
subject: [
{ required: true, message: "课程学科不能为空", trigger: "change" }
],
name: [
{ required: true, message: "课程名称不能为空", trigger: "blur" }
],
price: [
{ required: true, message: "价格不能为空", trigger: "blur" }
],
applicablePerson: [
{ required: true, message: "适用人群不能为空", trigger: "blur" }
],
info: [
{ required: true, message: "课程介绍不能为空", trigger: "blur" }
],
}
});
// 将data对象的三个属性,转换为ref响应式对象
const { queryParams, form, rules } = toRefs(data);

/** 查询课程管理列表 */
function getList() {
loading.value = true;
listCourse(queryParams.value).then(response => {
courseList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}

// 取消按钮
function cancel() {
open.value = false;
reset();
}

// 表单重置
function reset() {
form.value = {
id: null,
code: null,
subject: null,
name: null,
price: null,
applicablePerson: null,
info: null,
createTime: null,
updateTime: null
};
proxy.resetForm("courseRef");
}

/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}

/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
}

// 多选框选中数据
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
}

/** 新增按钮操作 */
function handleAdd() {
reset();
open.value = true;
title.value = "添加课程管理";
}

/** 修改按钮操作 */
function handleUpdate(row) {
reset();
const _id = row.id || ids.value
getCourse(_id).then(response => {
form.value = response.data;
open.value = true;
title.value = "修改课程管理";
});
}

/** 提交按钮 */
function submitForm() {
proxy.$refs["courseRef"].validate(valid => {
if (valid) {
if (form.value.id != null) {
updateCourse(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功");
open.value = false;
getList();
});
} else {
addCourse(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功");
open.value = false;
getList();
});
}
}
});
}

/** 删除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value;
proxy.$modal.confirm('是否确认删除课程管理编号为"' + _ids + '"的数据项?').then(function() {
return delCourse(_ids);
}).then(() => {
getList();
proxy.$modal.msgSuccess("删除成功");
}).catch(() => {});
}

/** 导出按钮操作 */
function handleExport() {
proxy.download('course/course/export', {
...queryParams.value
}, `course_${new Date().getTime()}.xlsx`)
}

// 页面加载时执行-查询课程管理列表
getList();
</script>

总前端代码

找到src/views/course/course/index.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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
<template>
<div class="app-container">

<!-- 搜索表单 start -->
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="课程编码" prop="code">
<el-input
v-model="queryParams.code"
placeholder="请输入课程编码"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="课程学科" prop="subject">
<el-select v-model="queryParams.subject" placeholder="请选择课程学科" clearable>
<el-option
v-for="dict in course_subject"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="课程名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入课程名称"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="适用人群" prop="applicablePerson">
<el-input
v-model="queryParams.applicablePerson"
placeholder="请输入适用人群"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 搜索表单 end -->

<!-- 按钮区域 start -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['course:course:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['course:course:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['course:course:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['course:course:export']"
>导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 按钮区域end -->

<!-- 数据展示表格 start -->
<el-table v-loading="loading" :data="courseList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="课程id" align="center" prop="id" />
<el-table-column label="课程编码" align="center" prop="code" />
<el-table-column label="课程学科" align="center" prop="subject">
<template #default="scope">
<dict-tag :options="course_subject" :value="scope.row.subject"/>
</template>
</el-table-column>
<el-table-column label="课程名称" align="center" prop="name" />
<el-table-column label="价格" align="center" prop="price" />
<el-table-column label="适用人群" align="center" prop="applicablePerson" />
<el-table-column label="课程介绍" align="center" prop="info" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['course:course:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['course:course:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 数据展示表格 end -->

<!-- 分页区域 start -->
<pagination
v-show="total>0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<!-- 分页区域 end -->

<!-- 添加或修改课程管理对话框 -->
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
<el-form ref="courseRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="课程编码" prop="code">
<el-input v-model="form.code" placeholder="请输入课程编码" />
</el-form-item>
<el-form-item label="课程学科" prop="subject">
<el-select v-model="form.subject" placeholder="请选择课程学科">
<el-option
v-for="dict in course_subject"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="课程名称" prop="name">
<el-input v-model="form.name" placeholder="请输入课程名称" />
</el-form-item>
<el-form-item label="价格" prop="price">
<el-input v-model="form.price" placeholder="请输入价格" />
</el-form-item>
<el-form-item label="适用人群" prop="applicablePerson">
<el-input v-model="form.applicablePerson" placeholder="请输入适用人群" />
</el-form-item>
<el-form-item label="课程介绍" prop="info">
<el-input v-model="form.info" placeholder="请输入课程介绍" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</template>
</el-dialog>
</div>
</template>

<script setup name="Course">



// 引入后端api接口
import { listCourse, getCourse, delCourse, addCourse, updateCourse } from "@/api/course/course";
// 获取当前实例代理对象,用于访问组件数据、方法
const { proxy } = getCurrentInstance();
// 获取课程学科的数据字典
const { course_subject } = proxy.useDict('course_subject');
// 列表数据
const courseList = ref([]);
// 是否显示弹框
const open = ref(false);
// 是否显示加载状态
const loading = ref(true);
// 是否显示搜索栏
const showSearch = ref(true);
// 复选框,被选中id的数组
const ids = ref([]);
// 复选框,是否单选,用于高亮修改、删除按钮
const single = ref(true);
// 复选框,是否多选,仅高亮删除按钮
const multiple = ref(true);
// 总(记录)条数
const total = ref(0);
// 用于区分新增、修改对话框标题
const title = ref("");
// 定义reactive响应式对象
const data = reactive({
// 新增或修改表单数据
form: {},
// 搜索条件参数
queryParams: {
pageNum: 1,
pageSize: 10,
code: null,
subject: null,
name: null,
applicablePerson: null,
},
// 表单校验规则
rules: {
code: [
{ required: true, message: "课程编码不能为空", trigger: "blur" }
],
subject: [
{ required: true, message: "课程学科不能为空", trigger: "change" }
],
name: [
{ required: true, message: "课程名称不能为空", trigger: "blur" }
],
price: [
{ required: true, message: "价格不能为空", trigger: "blur" }
],
applicablePerson: [
{ required: true, message: "适用人群不能为空", trigger: "blur" }
],
info: [
{ required: true, message: "课程介绍不能为空", trigger: "blur" }
],
}
});
// 将data对象的三个属性,转换为ref响应式对象
const { queryParams, form, rules } = toRefs(data);

/** 查询课程管理列表 */
function getList() {
loading.value = true;
listCourse(queryParams.value).then(response => {
courseList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}

// 取消按钮
function cancel() {
open.value = false;
reset();
}

// 表单重置
function reset() {
form.value = {
id: null,
code: null,
subject: null,
name: null,
price: null,
applicablePerson: null,
info: null,
createTime: null,
updateTime: null
};
proxy.resetForm("courseRef");
}

/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}

/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
}

// 多选框选中数据
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
}

/** 新增按钮操作 */
function handleAdd() {
reset();
open.value = true;
title.value = "添加课程管理";
}

/** 修改按钮操作 */
function handleUpdate(row) {
reset();
const _id = row.id || ids.value
getCourse(_id).then(response => {
form.value = response.data;
open.value = true;
title.value = "修改课程管理";
});
}

/** 提交按钮 */
function submitForm() {
proxy.$refs["courseRef"].validate(valid => {
if (valid) {
if (form.value.id != null) {
updateCourse(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功");
open.value = false;
getList();
});
} else {
addCourse(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功");
open.value = false;
getList();
});
}
}
});
}

/** 删除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value;
proxy.$modal.confirm('是否确认删除课程管理编号为"' + _ids + '"的数据项?').then(function() {
return delCourse(_ids);
}).then(() => {
getList();
proxy.$modal.msgSuccess("删除成功");
}).catch(() => {});
}

/** 导出按钮操作 */
function handleExport() {
proxy.download('course/course/export', {
...queryParams.value
}, `course_${new Date().getTime()}.xlsx`)
}

// 页面加载时执行-查询课程管理列表
getList();
</script>

后端代码分析

CourseController

ruoyi-admin模块下找到这个类:com.ruoyi.web.controller.course.CourseController里面有5个对应的方法接口,详细代码如下:

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
package com.sky.course.controller;

import com.sky.common.annotation.Log;
import com.sky.common.core.controller.BaseController;
import com.sky.common.core.domain.AjaxResult;
import com.sky.common.core.page.TableDataInfo;
import com.sky.common.enums.BusinessType;
import com.sky.common.utils.poi.ExcelUtil;
import com.sky.course.domain.Course;
import com.sky.course.service.ICourseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
* 课程管理Controller
*
* @author itheima
*/
@RestController
@RequestMapping("/course/course")
public class CourseController extends BaseController
{
@Autowired
private ICourseService courseService;

/**
* 查询课程管理列表
*/
@PreAuthorize("@ss.hasPermi('course:course:list')")
@GetMapping("/list")
public TableDataInfo list(Course course)
{
//1. 开启分页
startPage();
//2. 查询课程列表
List<Course> list = courseService.selectCourseList(course);
//3. 返回表格分页数据对象
return getDataTable(list);
}

/**
* 导出课程管理列表
*/
@PreAuthorize("@ss.hasPermi('course:course:export')")
@Log(title = "课程管理", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, Course course)
{
List<Course> list = courseService.selectCourseList(course);
ExcelUtil<Course> util = new ExcelUtil<Course>(Course.class);
util.exportExcel(response, list, "课程管理数据");
}

/**
* 获取课程管理详细信息
*/
@PreAuthorize("@ss.hasPermi('course:course:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(courseService.selectCourseById(id));
}

/**
* 新增课程管理
*/
@PreAuthorize("@ss.hasPermi('course:course:add')")
@Log(title = "课程管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody Course course)
{
return toAjax(courseService.insertCourse(course));
}

/**
* 修改课程管理
*/
@PreAuthorize("@ss.hasPermi('course:course:edit')")
@Log(title = "课程管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody Course course)
{
return toAjax(courseService.updateCourse(course));
}

/**
* 删除课程管理
*/
//spring security安全框架提供的一个注解。
@PreAuthorize("@ss.hasPermi('course:course:remove')")
@Log(title = "课程管理", businessType = BusinessType.DELETE)//记录用户操作日志
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(courseService.deleteCourseByIds(ids));
}
}

BaseController

Controller继承了BaseController,其中BaseController详细定义如下图:

TableDataInfo

分页查询统一返回对象:表格分页数据对象

AjaxResult

增删改查统一返回对象:操作消息提醒

BaseEntity

所有实体类默认继承的BaseEntity基类

权限注解

@PreAuthorize 注解是 Spring Security 框架中用来做权限检查的
它在运行方法前先验证权限,权限够就放行,不够就拦截

权限控制流程图

前后端交互流程

查询课程管理列表

接口文档

跨域

在前端开发中,跨域是一个常见的问题,特别是在使用Vue框架进行开发时。跨域是指在浏览器中发送的AJAX请求的目标地址与当前页面的地址不在同一个域下,这会导致浏览器的同源策略产生限制,从而阻止了跨域请求的发送。然而,我们可以通过代理服务器来解决这个问题

代理服务器是位于客户端和目标服务器之间的一台服务器,它接收客户端发送的请求,并将请求转发给目标服务器。通过在代理服务器上进行请求转发,可以绕过浏览器的同源策略限制,从而实现跨域请求
在vue.config.js文件中添加以下内容: