文章目錄
- 一、課程管理模塊前端代碼截圖
- 二、前端代碼及分析
- index.vue
- course.js
- 三、前端執行流程
- 1. 組件初始化
- 2. 查詢操作
- 3. 列表操作
- 4. 對話框操作
- 5. API 請求
- 6. 執行流程總結
- 關鍵點
- 四、課程管理模塊后端代碼截圖
- 五、后端代碼塊
- CourseController
- ICourseService
- CourseMapper
- Course
- 六、后端執行邏輯
- 1. `Course` 類
- 2. `CourseMapper` 接口
- 3. `ICourseService` 接口
- 4. `CourseController` 類
- 調用關系總結
- 示例流程
- 七、前后端交互執行流程
- **1. 初始化階段**
- **前端操作**
- **后端處理**
- **前端響應**
- **2. 查詢操作**
- **前端操作**
- **后端處理**
- **前端響應**
- **3. 新增課程**
- **前端操作**
- **后端處理**
- **前端響應**
- **4. 修改課程**
- **前端操作**
- **后端處理**
- **前端響應**
- **5. 刪除課程**
- **前端操作**
- **后端處理**
- **前端響應**
- **6. 導出操作**
- **前端操作**
- **后端處理**
- **前端響應**
- **7. 總結:前后端交互流程**
- **關鍵點**
一、課程管理模塊前端代碼截圖
二、前端代碼及分析
index.vue
<template><div class="app-container"><el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px"><el-form-item label="課程編碼" prop="code"><el-inputv-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-optionv-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-inputv-model="queryParams.name"placeholder="請輸入課程名稱"clearable@keyup.enter="handleQuery"/></el-form-item><el-form-item label="適用人群" prop="applicablePerson"><el-inputv-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><el-row :gutter="10" class="mb8"><el-col :span="1.5"><el-buttontype="primary"plainicon="Plus"@click="handleAdd"v-hasPermi="['course:course:add']">新增</el-button></el-col><el-col :span="1.5"><el-buttontype="success"plainicon="Edit":disabled="single"@click="handleUpdate"v-hasPermi="['course:course:edit']">修改</el-button></el-col><el-col :span="1.5"><el-buttontype="danger"plainicon="Delete":disabled="multiple"@click="handleDelete"v-hasPermi="['course:course:remove']">刪除</el-button></el-col><el-col :span="1.5"><el-buttontype="warning"plainicon="Download"@click="handleExport"v-hasPermi="['course:course:export']">導出</el-button></el-col><right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar></el-row><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><paginationv-show="total>0":total="total"v-model:page="queryParams.pageNum"v-model:limit="queryParams.pageSize"@pagination="getList"/><!-- 添加或修改課程管理對話框 --><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-optionv-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">
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)
const ids = ref([])
const single = ref(true)
const multiple = ref(true)
const total = ref(0)
const title = ref("")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" }],}
})const { queryParams, form, rules } = toRefs(data)/** 查詢課程管理列表 */
function getList() {loading.value = truelistCourse(queryParams.value).then(response => {courseList.value = response.rowstotal.value = response.totalloading.value = false})
}// 取消按鈕
function cancel() {open.value = falsereset()
}// 表單重置
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 = 1getList()
}/** 重置按鈕操作 */
function resetQuery() {proxy.resetForm("queryRef")handleQuery()
}// 多選框選中數據
function handleSelectionChange(selection) {ids.value = selection.map(item => item.id)single.value = selection.length != 1multiple.value = !selection.length
}/** 新增按鈕操作 */
function handleAdd() {reset()open.value = truetitle.value = "添加課程管理"
}/** 修改按鈕操作 */
function handleUpdate(row) {reset()const _id = row.id || ids.valuegetCourse(_id).then(response => {form.value = response.dataopen.value = truetitle.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 = falsegetList()})} else {addCourse(form.value).then(response => {proxy.$modal.msgSuccess("新增成功")open.value = falsegetList()})}}})
}/** 刪除按鈕操作 */
function handleDelete(row) {const _ids = row.id || ids.valueproxy.$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>
course.js
import request from '@/utils/request'// 查詢課程管理列表
export function listCourse(query) {return request({url: '/course/course/list',method: 'get',params: query})
}// 查詢課程管理詳細
export function getCourse(id) {return request({url: '/course/course/' + id,method: 'get'})
}// 新增課程管理
export function addCourse(data) {return request({url: '/course/course',method: 'post',data: data})
}// 修改課程管理
export function updateCourse(data) {return request({url: '/course/course',method: 'put',data: data})
}// 刪除課程管理
export function delCourse(id) {return request({url: '/course/course/' + id,method: 'delete'})
}
三、前端執行流程
根據提供的 Vue 組件代碼和 API 請求代碼,我們可以分析出前端在執行過程中的主要步驟和邏輯。以下是詳細的執行過程分析:
1. 組件初始化
-
模板渲染:
- 組件模板中定義了一個課程管理的界面,包括搜索表單、操作按鈕、課程列表表格、分頁組件以及添加/修改課程的對話框。
- 使用了 Element Plus 組件庫(如
el-form
、el-table
、el-dialog
等)。
-
腳本初始化:
- 引入了課程管理的 API 請求函數(
listCourse
、getCourse
、delCourse
、addCourse
、updateCourse
)。 - 定義了組件的響應式數據,包括課程列表(
courseList
)、查詢參數(queryParams
)、表單數據(form
)、對話框狀態(open
)等。 - 從字典中獲取課程學科數據(
course_subject
)。
- 引入了課程管理的 API 請求函數(
-
初始化請求:
- 調用
getList()
方法獲取課程列表數據,渲染到表格中。
- 調用
2. 查詢操作
-
搜索表單:
- 用戶可以在搜索表單中輸入課程編碼、選擇課程學科、輸入課程名稱和適用人群。
- 點擊“搜索”按鈕時,觸發
handleQuery()
方法。 handleQuery()
方法將pageNum
重置為 1,然后調用getList()
方法。
-
重置表單:
- 點擊“重置”按鈕時,觸發
resetQuery()
方法。 resetQuery()
方法重置查詢表單,然后調用handleQuery()
方法重新獲取數據。
- 點擊“重置”按鈕時,觸發
3. 列表操作
-
表格數據:
- 課程列表數據通過
el-table
渲染,每行數據包括課程 ID、編碼、學科、名稱、價格、適用人群和介紹。 - 表格支持多選,選中數據后更新
ids
、single
和multiple
狀態。
- 課程列表數據通過
-
操作按鈕:
- 新增:點擊“新增”按鈕時,觸發
handleAdd()
方法,重置表單并打開對話框。 - 修改:點擊“修改”按鈕時,觸發
handleUpdate()
方法,獲取課程詳情并打開對話框。 - 刪除:點擊“刪除”按鈕時,觸發
handleDelete()
方法,彈出確認對話框,確認后調用delCourse()
刪除課程。 - 導出:點擊“導出”按鈕時,觸發
handleExport()
方法,調用proxy.download()
導出課程數據。
- 新增:點擊“新增”按鈕時,觸發
4. 對話框操作
-
添加/修改課程:
- 對話框中包含課程表單,用戶可以輸入課程編碼、選擇學科、輸入名稱、價格、適用人群和介紹。
- 點擊“確定”按鈕時,觸發
submitForm()
方法。 submitForm()
方法驗證表單數據,根據是否有id
決定是新增還是修改課程,調用addCourse()
或updateCourse()
方法。- 操作成功后,關閉對話框并重新獲取課程列表。
-
取消操作:
- 點擊“取消”按鈕時,觸發
cancel()
方法,關閉對話框并重置表單。
- 點擊“取消”按鈕時,觸發
5. API 請求
- 請求函數:
listCourse(query)
:發送 GET 請求,獲取課程列表數據。getCourse(id)
:發送 GET 請求,獲取單個課程的詳細信息。addCourse(data)
:發送 POST 請求,新增課程。updateCourse(data)
:發送 PUT 請求,修改課程。delCourse(id)
:發送 DELETE 請求,刪除課程。
6. 執行流程總結
- 組件初始化時,調用
getList()
獲取課程列表。 - 用戶通過搜索表單或分頁組件觸發查詢操作,調用
getList()
更新數據。 - 用戶點擊操作按鈕(新增、修改、刪除、導出)時,觸發相應的方法。
- 對話框中的表單提交時,調用
submitForm()
方法,根據操作類型調用對應的 API 請求。 - API 請求成功后,更新界面數據(如關閉對話框、重新獲取列表等)。
關鍵點
- 響應式數據:使用
ref
和reactive
定義響應式數據,確保界面實時更新。 - API 請求:通過
request
工具函數封裝 HTTP 請求,簡化代碼。 - 表單驗證:使用
el-form
的驗證規則確保用戶輸入的有效性。 - 組件通信:通過
props
和emit
實現父子組件通信(如right-toolbar
組件)。
通過以上分析,可以清晰地了解該前端組件的執行過程和邏輯。
四、課程管理模塊后端代碼截圖
五、后端代碼塊
CourseController
package com.ruoyi.course.controller;import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.course.domain.Course;
import com.ruoyi.course.service.ICourseService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;/*** 課程管理Controller* * @author ruoyi* @date 2025-05-27*/
@RestController
@RequestMapping("/course/course")
public class CourseController extends BaseController
{@Autowiredprivate ICourseService courseService;/*** 查詢課程管理列表*/@PreAuthorize("@ss.hasPermi('course:course:list')")@GetMapping("/list")public TableDataInfo list(Course course){startPage();List<Course> list = courseService.selectCourseList(course);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)@PostMappingpublic AjaxResult add(@RequestBody Course course){return toAjax(courseService.insertCourse(course));}/*** 修改課程管理*/@PreAuthorize("@ss.hasPermi('course:course:edit')")@Log(title = "課程管理", businessType = BusinessType.UPDATE)@PutMappingpublic AjaxResult edit(@RequestBody Course course){return toAjax(courseService.updateCourse(course));}/*** 刪除課程管理*/@PreAuthorize("@ss.hasPermi('course:course:remove')")@Log(title = "課程管理", businessType = BusinessType.DELETE)@DeleteMapping("/{ids}")public AjaxResult remove(@PathVariable Long[] ids){return toAjax(courseService.deleteCourseByIds(ids));}
}
ICourseService
package com.ruoyi.course.controller;import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.course.domain.Course;
import com.ruoyi.course.service.ICourseService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;/*** 課程管理Controller* * @author ruoyi* @date 2025-05-27*/
@RestController
@RequestMapping("/course/course")
public class CourseController extends BaseController
{@Autowiredprivate ICourseService courseService;/*** 查詢課程管理列表*/@PreAuthorize("@ss.hasPermi('course:course:list')")@GetMapping("/list")public TableDataInfo list(Course course){startPage();List<Course> list = courseService.selectCourseList(course);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)@PostMappingpublic AjaxResult add(@RequestBody Course course){return toAjax(courseService.insertCourse(course));}/*** 修改課程管理*/@PreAuthorize("@ss.hasPermi('course:course:edit')")@Log(title = "課程管理", businessType = BusinessType.UPDATE)@PutMappingpublic AjaxResult edit(@RequestBody Course course){return toAjax(courseService.updateCourse(course));}/*** 刪除課程管理*/@PreAuthorize("@ss.hasPermi('course:course:remove')")@Log(title = "課程管理", businessType = BusinessType.DELETE)@DeleteMapping("/{ids}")public AjaxResult remove(@PathVariable Long[] ids){return toAjax(courseService.deleteCourseByIds(ids));}
}
CourseMapper
package com.ruoyi.course.controller;import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.course.domain.Course;
import com.ruoyi.course.service.ICourseService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;/*** 課程管理Controller* * @author ruoyi* @date 2025-05-27*/
@RestController
@RequestMapping("/course/course")
public class CourseController extends BaseController
{@Autowiredprivate ICourseService courseService;/*** 查詢課程管理列表*/@PreAuthorize("@ss.hasPermi('course:course:list')")@GetMapping("/list")public TableDataInfo list(Course course){startPage();List<Course> list = courseService.selectCourseList(course);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)@PostMappingpublic AjaxResult add(@RequestBody Course course){return toAjax(courseService.insertCourse(course));}/*** 修改課程管理*/@PreAuthorize("@ss.hasPermi('course:course:edit')")@Log(title = "課程管理", businessType = BusinessType.UPDATE)@PutMappingpublic AjaxResult edit(@RequestBody Course course){return toAjax(courseService.updateCourse(course));}/*** 刪除課程管理*/@PreAuthorize("@ss.hasPermi('course:course:remove')")@Log(title = "課程管理", businessType = BusinessType.DELETE)@DeleteMapping("/{ids}")public AjaxResult remove(@PathVariable Long[] ids){return toAjax(courseService.deleteCourseByIds(ids));}
}
Course
package com.ruoyi.course.controller;import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.course.domain.Course;
import com.ruoyi.course.service.ICourseService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;/*** 課程管理Controller* * @author ruoyi* @date 2025-05-27*/
@RestController
@RequestMapping("/course/course")
public class CourseController extends BaseController
{@Autowiredprivate ICourseService courseService;/*** 查詢課程管理列表*/@PreAuthorize("@ss.hasPermi('course:course:list')")@GetMapping("/list")public TableDataInfo list(Course course){startPage();List<Course> list = courseService.selectCourseList(course);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)@PostMappingpublic AjaxResult add(@RequestBody Course course){return toAjax(courseService.insertCourse(course));}/*** 修改課程管理*/@PreAuthorize("@ss.hasPermi('course:course:edit')")@Log(title = "課程管理", businessType = BusinessType.UPDATE)@PutMappingpublic AjaxResult edit(@RequestBody Course course){return toAjax(courseService.updateCourse(course));}/*** 刪除課程管理*/@PreAuthorize("@ss.hasPermi('course:course:remove')")@Log(title = "課程管理", businessType = BusinessType.DELETE)@DeleteMapping("/{ids}")public AjaxResult remove(@PathVariable Long[] ids){return toAjax(courseService.deleteCourseByIds(ids));}
}
六、后端執行邏輯
在這個項目結構中,course
包下的四個綠色類文件(CourseController
、Course
、CourseMapper
、ICourseService
)通常在若依(RuoYi)框架中扮演不同的角色,它們之間的調用關系如下:
1. Course
類
- 角色:領域模型(Domain Model)或實體類。
- 作用:表示課程(Course)的基本信息,通常與數據庫中的
course
表對應。它包含了課程的屬性,如課程名稱、描述、創建時間等。 - 調用關系:不直接調用其他類,而是被其他類(如
CourseMapper
、CourseService
)使用。
2. CourseMapper
接口
- 角色:數據訪問層(DAO)。
- 作用:定義了與數據庫交互的方法,如插入、查詢、更新和刪除課程信息。通常使用 MyBatis 框架,通過 XML 映射文件或注解實現 SQL 語句。
- 調用關系:
- 被
CourseService
調用,用于執行數據庫操作。 - 依賴于
Course
類,因為它的方法通常以Course
對象作為參數或返回值。
- 被
3. ICourseService
接口
- 角色:服務層接口。
- 作用:定義了與課程相關的業務邏輯方法,如添加課程、查詢課程列表等。它是對外暴露的業務接口。
- 調用關系:
- 被
CourseController
調用,用于處理業務邏輯。 - 依賴于
CourseMapper
,因為業務邏輯可能需要訪問數據庫。
- 被
4. CourseController
類
- 角色:控制層(Controller)。
- 作用:處理 HTTP 請求,接收前端傳來的參數,調用
CourseService
的方法執行業務邏輯,并返回響應結果。 - 調用關系:
- 調用
ICourseService
的方法,執行業務邏輯。 - 依賴于
Course
類,因為請求參數和響應數據通常以Course
對象的形式傳遞。
- 調用
調用關系總結
- 前端請求 →
CourseController
。 CourseController
→ 調用ICourseService
的方法。ICourseService
的實現類 → 調用CourseMapper
的方法。CourseMapper
→ 執行數據庫操作,操作Course
對象。- 最終結果通過
CourseController
返回給前端。
示例流程
假設有一個添加課程的請求:
- 前端發送添加課程的請求到
CourseController
。 CourseController
調用ICourseService.addCourse()
方法。CourseServiceImpl
(ICourseService
的實現類)調用CourseMapper.insertCourse()
方法。CourseMapper
執行 SQL 插入語句,將課程信息存入數據庫。- 返回操作結果,最終由
CourseController
返回給前端。
這種分層架構(Controller-Service-Mapper-Domain)是典型的 Web 應用設計模式,有助于代碼的模塊化和可維護性。
七、前后端交互執行流程
我們可以詳細講解整個前后端交互的過程與步驟。以下是完整的交互流程:
1. 初始化階段
前端操作
- 組件加載:
- Vue 組件初始化時,調用
getList()
方法。 getList()
方法調用listCourse(queryParams)
API 請求,向后端發送 GET 請求,攜帶查詢參數(如pageNum
、pageSize
、code
等)。
- Vue 組件初始化時,調用
后端處理
- 接收請求:
- 后端
CourseController
接收/course/course/list
的 GET 請求。
- 后端
- 業務邏輯:
- 調用
ICourseService.listCourse(queryParams)
方法,查詢數據庫獲取課程列表。
- 調用
- 返回數據:
- 返回查詢結果,格式通常為
{ rows: [...], total: number }
。
- 返回查詢結果,格式通常為
前端響應
- 數據渲染:
- 前端接收后端返回的數據,更新
courseList
和total
,渲染到表格和分頁組件。
- 前端接收后端返回的數據,更新
2. 查詢操作
前端操作
- 用戶輸入查詢條件:
- 用戶在搜索表單中輸入課程編碼、選擇學科等。
- 觸發查詢:
- 點擊“搜索”按鈕,調用
handleQuery()
方法。 handleQuery()
重置pageNum
為 1,并調用getList()
。
- 點擊“搜索”按鈕,調用
后端處理
- 接收請求:
- 后端接收新的查詢參數,重復初始化階段的查詢邏輯。
- 返回數據:
- 返回符合查詢條件的課程列表。
前端響應
- 更新界面:
- 前端更新
courseList
和total
,表格重新渲染。
- 前端更新
3. 新增課程
前端操作
- 打開對話框:
- 點擊“新增”按鈕,調用
handleAdd()
方法,打開對話框并重置表單。
- 點擊“新增”按鈕,調用
- 提交表單:
- 用戶填寫課程信息,點擊“確定”按鈕,調用
submitForm()
方法。 submitForm()
驗證表單數據,調用addCourse(form)
API 請求,向后端發送 POST 請求,攜帶課程數據。
- 用戶填寫課程信息,點擊“確定”按鈕,調用
后端處理
- 接收請求:
- 后端
CourseController
接收/course/course
的 POST 請求。
- 后端
- 業務邏輯:
- 調用
ICourseService.addCourse(course)
方法,將課程數據插入數據庫。
- 調用
- 返回結果:
- 返回操作結果(如成功或失敗信息)。
前端響應
- 成功處理:
- 前端接收成功響應,關閉對話框,調用
getList()
重新獲取課程列表。
- 前端接收成功響應,關閉對話框,調用
- 失敗處理:
- 顯示錯誤提示(如
proxy.$modal.msgError("新增失敗")
)。
- 顯示錯誤提示(如
4. 修改課程
前端操作
- 打開對話框:
- 點擊“修改”按鈕,調用
handleUpdate(row)
方法。 - 調用
getCourse(id)
API 請求,獲取課程詳情。
- 點擊“修改”按鈕,調用
- 填充表單:
- 后端返回課程詳情,填充到表單中。
- 提交表單:
- 用戶修改信息后點擊“確定”,調用
submitForm()
方法。 submitForm()
驗證數據,調用updateCourse(form)
API 請求,向后端發送 PUT 請求,攜帶更新后的課程數據。
- 用戶修改信息后點擊“確定”,調用
后端處理
- 接收請求:
- 后端
CourseController
接收/course/course
的 PUT 請求。
- 后端
- 業務邏輯:
- 調用
ICourseService.updateCourse(course)
方法,更新數據庫中的課程數據。
- 調用
- 返回結果:
- 返回操作結果。
前端響應
- 成功處理:
- 前端接收成功響應,關閉對話框,調用
getList()
重新獲取課程列表。
- 前端接收成功響應,關閉對話框,調用
- 失敗處理:
- 顯示錯誤提示。
5. 刪除課程
前端操作
- 觸發刪除:
- 點擊“刪除”按鈕,調用
handleDelete(row)
方法。 - 彈出確認對話框,用戶確認后調用
delCourse(ids)
API 請求,向后端發送 DELETE 請求,攜帶課程 ID。
- 點擊“刪除”按鈕,調用
后端處理
- 接收請求:
- 后端
CourseController
接收/course/course/{id}
的 DELETE 請求。
- 后端
- 業務邏輯:
- 調用
ICourseService.deleteCourseById(id)
方法,從數據庫中刪除課程數據。
- 調用
- 返回結果:
- 返回操作結果。
前端響應
- 成功處理:
- 前端接收成功響應,調用
getList()
重新獲取課程列表。
- 前端接收成功響應,調用
- 失敗處理:
- 顯示錯誤提示。
6. 導出操作
前端操作
- 觸發導出:
- 點擊“導出”按鈕,調用
handleExport()
方法。 - 調用
proxy.download()
方法,向后端發送導出請求,攜帶查詢參數。
- 點擊“導出”按鈕,調用
后端處理
- 接收請求:
- 后端
CourseController
接收/course/course/export
的請求。
- 后端
- 業務邏輯:
- 調用
ICourseService.exportCourse(queryParams)
方法,生成 Excel 文件。
- 調用
- 返回文件:
- 返回文件流,前端下載。
前端響應
- 下載文件:
- 前端接收文件流,觸發瀏覽器下載。
7. 總結:前后端交互流程
- 前端發起請求:
- 用戶操作(如查詢、新增、修改、刪除、導出)觸發前端 API 請求。
- 后端處理請求:
- 后端
Controller
接收請求,調用Service
層處理業務邏輯,操作數據庫。
- 后端
- 后端返回響應:
- 返回 JSON 數據或文件流。
- 前端處理響應:
- 成功時更新界面數據或觸發下載。
- 失敗時顯示錯誤提示。
關鍵點
- API 設計:前后端通過 RESTful API 交互,明確請求路徑、方法和參數。
- 數據格式:通常使用 JSON 格式傳輸數據,導出時使用文件流。
- 錯誤處理:前后端均需處理異常情況(如網絡錯誤、數據驗證失敗)。
- 用戶體驗:前端通過加載狀態(如
v-loading
)和提示信息(如msgSuccess
)優化用戶體驗。
通過以上流程,前后端協同工作,實現了課程管理的完整功能。