【Web應用】若依框架:基礎篇14 源碼閱讀-后端代碼分析-課程管理模塊前后端代碼分析

文章目錄

  • 一、課程管理模塊前端代碼截圖
  • 二、前端代碼及分析
    • 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. 組件初始化

  1. 模板渲染

    • 組件模板中定義了一個課程管理的界面,包括搜索表單、操作按鈕、課程列表表格、分頁組件以及添加/修改課程的對話框。
    • 使用了 Element Plus 組件庫(如 el-formel-tableel-dialog 等)。
  2. 腳本初始化

    • 引入了課程管理的 API 請求函數(listCoursegetCoursedelCourseaddCourseupdateCourse)。
    • 定義了組件的響應式數據,包括課程列表(courseList)、查詢參數(queryParams)、表單數據(form)、對話框狀態(open)等。
    • 從字典中獲取課程學科數據(course_subject)。
  3. 初始化請求

    • 調用 getList() 方法獲取課程列表數據,渲染到表格中。

2. 查詢操作

  1. 搜索表單

    • 用戶可以在搜索表單中輸入課程編碼、選擇課程學科、輸入課程名稱和適用人群。
    • 點擊“搜索”按鈕時,觸發 handleQuery() 方法。
    • handleQuery() 方法將 pageNum 重置為 1,然后調用 getList() 方法。
  2. 重置表單

    • 點擊“重置”按鈕時,觸發 resetQuery() 方法。
    • resetQuery() 方法重置查詢表單,然后調用 handleQuery() 方法重新獲取數據。

3. 列表操作

  1. 表格數據

    • 課程列表數據通過 el-table 渲染,每行數據包括課程 ID、編碼、學科、名稱、價格、適用人群和介紹。
    • 表格支持多選,選中數據后更新 idssinglemultiple 狀態。
  2. 操作按鈕

    • 新增:點擊“新增”按鈕時,觸發 handleAdd() 方法,重置表單并打開對話框。
    • 修改:點擊“修改”按鈕時,觸發 handleUpdate() 方法,獲取課程詳情并打開對話框。
    • 刪除:點擊“刪除”按鈕時,觸發 handleDelete() 方法,彈出確認對話框,確認后調用 delCourse() 刪除課程。
    • 導出:點擊“導出”按鈕時,觸發 handleExport() 方法,調用 proxy.download() 導出課程數據。

4. 對話框操作

  1. 添加/修改課程

    • 對話框中包含課程表單,用戶可以輸入課程編碼、選擇學科、輸入名稱、價格、適用人群和介紹。
    • 點擊“確定”按鈕時,觸發 submitForm() 方法。
    • submitForm() 方法驗證表單數據,根據是否有 id 決定是新增還是修改課程,調用 addCourse()updateCourse() 方法。
    • 操作成功后,關閉對話框并重新獲取課程列表。
  2. 取消操作

    • 點擊“取消”按鈕時,觸發 cancel() 方法,關閉對話框并重置表單。

5. API 請求

  1. 請求函數
    • listCourse(query):發送 GET 請求,獲取課程列表數據。
    • getCourse(id):發送 GET 請求,獲取單個課程的詳細信息。
    • addCourse(data):發送 POST 請求,新增課程。
    • updateCourse(data):發送 PUT 請求,修改課程。
    • delCourse(id):發送 DELETE 請求,刪除課程。

6. 執行流程總結

  1. 組件初始化時,調用 getList() 獲取課程列表。
  2. 用戶通過搜索表單或分頁組件觸發查詢操作,調用 getList() 更新數據。
  3. 用戶點擊操作按鈕(新增、修改、刪除、導出)時,觸發相應的方法。
  4. 對話框中的表單提交時,調用 submitForm() 方法,根據操作類型調用對應的 API 請求。
  5. API 請求成功后,更新界面數據(如關閉對話框、重新獲取列表等)。

關鍵點

  • 響應式數據:使用 refreactive 定義響應式數據,確保界面實時更新。
  • API 請求:通過 request 工具函數封裝 HTTP 請求,簡化代碼。
  • 表單驗證:使用 el-form 的驗證規則確保用戶輸入的有效性。
  • 組件通信:通過 propsemit 實現父子組件通信(如 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 包下的四個綠色類文件(CourseControllerCourseCourseMapperICourseService)通常在若依(RuoYi)框架中扮演不同的角色,它們之間的調用關系如下:

1. Course

  • 角色:領域模型(Domain Model)或實體類。
  • 作用:表示課程(Course)的基本信息,通常與數據庫中的 course 表對應。它包含了課程的屬性,如課程名稱、描述、創建時間等。
  • 調用關系:不直接調用其他類,而是被其他類(如 CourseMapperCourseService)使用。

2. CourseMapper 接口

  • 角色:數據訪問層(DAO)。
  • 作用:定義了與數據庫交互的方法,如插入、查詢、更新和刪除課程信息。通常使用 MyBatis 框架,通過 XML 映射文件或注解實現 SQL 語句。
  • 調用關系
    • CourseService 調用,用于執行數據庫操作。
    • 依賴于 Course 類,因為它的方法通常以 Course 對象作為參數或返回值。

3. ICourseService 接口

  • 角色:服務層接口。
  • 作用:定義了與課程相關的業務邏輯方法,如添加課程、查詢課程列表等。它是對外暴露的業務接口。
  • 調用關系
    • CourseController 調用,用于處理業務邏輯。
    • 依賴于 CourseMapper,因為業務邏輯可能需要訪問數據庫。

4. CourseController

  • 角色:控制層(Controller)。
  • 作用:處理 HTTP 請求,接收前端傳來的參數,調用 CourseService 的方法執行業務邏輯,并返回響應結果。
  • 調用關系
    • 調用 ICourseService 的方法,執行業務邏輯。
    • 依賴于 Course 類,因為請求參數和響應數據通常以 Course 對象的形式傳遞。

調用關系總結

  1. 前端請求CourseController
  2. CourseController → 調用 ICourseService 的方法。
  3. ICourseService 的實現類 → 調用 CourseMapper 的方法。
  4. CourseMapper → 執行數據庫操作,操作 Course 對象。
  5. 最終結果通過 CourseController 返回給前端。

示例流程

假設有一個添加課程的請求:

  1. 前端發送添加課程的請求到 CourseController
  2. CourseController 調用 ICourseService.addCourse() 方法。
  3. CourseServiceImplICourseService 的實現類)調用 CourseMapper.insertCourse() 方法。
  4. CourseMapper 執行 SQL 插入語句,將課程信息存入數據庫。
  5. 返回操作結果,最終由 CourseController 返回給前端。

這種分層架構(Controller-Service-Mapper-Domain)是典型的 Web 應用設計模式,有助于代碼的模塊化和可維護性。

七、前后端交互執行流程

我們可以詳細講解整個前后端交互的過程與步驟。以下是完整的交互流程:


1. 初始化階段

前端操作
  1. 組件加載
    • Vue 組件初始化時,調用 getList() 方法。
    • getList() 方法調用 listCourse(queryParams) API 請求,向后端發送 GET 請求,攜帶查詢參數(如 pageNumpageSizecode 等)。
后端處理
  1. 接收請求
    • 后端 CourseController 接收 /course/course/list 的 GET 請求。
  2. 業務邏輯
    • 調用 ICourseService.listCourse(queryParams) 方法,查詢數據庫獲取課程列表。
  3. 返回數據
    • 返回查詢結果,格式通常為 { rows: [...], total: number }
前端響應
  1. 數據渲染
    • 前端接收后端返回的數據,更新 courseListtotal,渲染到表格和分頁組件。

2. 查詢操作

前端操作
  1. 用戶輸入查詢條件
    • 用戶在搜索表單中輸入課程編碼、選擇學科等。
  2. 觸發查詢
    • 點擊“搜索”按鈕,調用 handleQuery() 方法。
    • handleQuery() 重置 pageNum 為 1,并調用 getList()
后端處理
  1. 接收請求
    • 后端接收新的查詢參數,重復初始化階段的查詢邏輯。
  2. 返回數據
    • 返回符合查詢條件的課程列表。
前端響應
  1. 更新界面
    • 前端更新 courseListtotal,表格重新渲染。

3. 新增課程

前端操作
  1. 打開對話框
    • 點擊“新增”按鈕,調用 handleAdd() 方法,打開對話框并重置表單。
  2. 提交表單
    • 用戶填寫課程信息,點擊“確定”按鈕,調用 submitForm() 方法。
    • submitForm() 驗證表單數據,調用 addCourse(form) API 請求,向后端發送 POST 請求,攜帶課程數據。
后端處理
  1. 接收請求
    • 后端 CourseController 接收 /course/course 的 POST 請求。
  2. 業務邏輯
    • 調用 ICourseService.addCourse(course) 方法,將課程數據插入數據庫。
  3. 返回結果
    • 返回操作結果(如成功或失敗信息)。
前端響應
  1. 成功處理
    • 前端接收成功響應,關閉對話框,調用 getList() 重新獲取課程列表。
  2. 失敗處理
    • 顯示錯誤提示(如 proxy.$modal.msgError("新增失敗"))。

4. 修改課程

前端操作
  1. 打開對話框
    • 點擊“修改”按鈕,調用 handleUpdate(row) 方法。
    • 調用 getCourse(id) API 請求,獲取課程詳情。
  2. 填充表單
    • 后端返回課程詳情,填充到表單中。
  3. 提交表單
    • 用戶修改信息后點擊“確定”,調用 submitForm() 方法。
    • submitForm() 驗證數據,調用 updateCourse(form) API 請求,向后端發送 PUT 請求,攜帶更新后的課程數據。
后端處理
  1. 接收請求
    • 后端 CourseController 接收 /course/course 的 PUT 請求。
  2. 業務邏輯
    • 調用 ICourseService.updateCourse(course) 方法,更新數據庫中的課程數據。
  3. 返回結果
    • 返回操作結果。
前端響應
  1. 成功處理
    • 前端接收成功響應,關閉對話框,調用 getList() 重新獲取課程列表。
  2. 失敗處理
    • 顯示錯誤提示。

5. 刪除課程

前端操作
  1. 觸發刪除
    • 點擊“刪除”按鈕,調用 handleDelete(row) 方法。
    • 彈出確認對話框,用戶確認后調用 delCourse(ids) API 請求,向后端發送 DELETE 請求,攜帶課程 ID。
后端處理
  1. 接收請求
    • 后端 CourseController 接收 /course/course/{id} 的 DELETE 請求。
  2. 業務邏輯
    • 調用 ICourseService.deleteCourseById(id) 方法,從數據庫中刪除課程數據。
  3. 返回結果
    • 返回操作結果。
前端響應
  1. 成功處理
    • 前端接收成功響應,調用 getList() 重新獲取課程列表。
  2. 失敗處理
    • 顯示錯誤提示。

6. 導出操作

前端操作
  1. 觸發導出
    • 點擊“導出”按鈕,調用 handleExport() 方法。
    • 調用 proxy.download() 方法,向后端發送導出請求,攜帶查詢參數。
后端處理
  1. 接收請求
    • 后端 CourseController 接收 /course/course/export 的請求。
  2. 業務邏輯
    • 調用 ICourseService.exportCourse(queryParams) 方法,生成 Excel 文件。
  3. 返回文件
    • 返回文件流,前端下載。
前端響應
  1. 下載文件
    • 前端接收文件流,觸發瀏覽器下載。

7. 總結:前后端交互流程

  1. 前端發起請求
    • 用戶操作(如查詢、新增、修改、刪除、導出)觸發前端 API 請求。
  2. 后端處理請求
    • 后端 Controller 接收請求,調用 Service 層處理業務邏輯,操作數據庫。
  3. 后端返回響應
    • 返回 JSON 數據或文件流。
  4. 前端處理響應
    • 成功時更新界面數據或觸發下載。
    • 失敗時顯示錯誤提示。

關鍵點

  • API 設計:前后端通過 RESTful API 交互,明確請求路徑、方法和參數。
  • 數據格式:通常使用 JSON 格式傳輸數據,導出時使用文件流。
  • 錯誤處理:前后端均需處理異常情況(如網絡錯誤、數據驗證失敗)。
  • 用戶體驗:前端通過加載狀態(如 v-loading)和提示信息(如 msgSuccess)優化用戶體驗。

通過以上流程,前后端協同工作,實現了課程管理的完整功能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/84078.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/84078.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/84078.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深入理解系統:UML類圖

UML類圖 類圖&#xff08;class diagram&#xff09; 描述系統中的對象類型&#xff0c;以及存在于它們之間的各種靜態關系。 正向工程&#xff08;forward engineering&#xff09;在編寫代碼之前畫UML圖。 逆向工程&#xff08;reverse engineering&#xff09;從已有代碼建…

DeepSeek12-Open WebUI 知識庫配置詳細步驟

&#x1f4da; Open WebUI 知識庫配置詳細步驟&#xff08;中英文對照&#xff09; &#x1f310; 界面語言切換 # 首次登錄后切換語言&#xff1a; 1. 點擊左下角用戶頭像 → Settings 2. 在 "General" 選項卡找到 "Language" 3. 選擇 中文(簡體)/Engli…

Python網絡設備批量配置腳本解析

目錄 腳本概述 代碼解析 導入模塊 日志配置 核心函數config_device 主程序邏輯 使用說明 腳本優化建議 完整代碼 腳本概述 這是一個使用Python編寫的網絡設備批量配置腳本&#xff0c;主要功能是通過SSH協議批量登錄多臺網絡設備&#xff08;如路由器、交換機等&…

Z-FOLD: A Frustratingly Easy Post-Training Quantization Scheme for LLMs

文章目錄 摘要1 引言2 相關工作2.1 量化2.2 大型語言模型的量化 3 Z-FOLD3.1 新引入的參數 ζ3.2 參數整合&#xff08;ζ 折疊&#xff09;3.3 使用校準集的微調 4 實驗4.1 實驗設置4.2 與其他方法的比較4.3 Z-FOLD 的泛化能力4.4 Z-FOLD 的可移植性4.5 消融研究 5 結論6 限制…

交流電機深度解析:從基礎到實戰的全面指南

簡介 交流電機作為現代工業中不可或缺的動力設備,廣泛應用于各個領域。本文將帶你深入了解交流電機,從最基礎的概念和工作原理開始,逐步介紹其類型、結構、關鍵參數等基礎知識。同時,我們會探討交流電機在企業級開發研發中的技術實戰,包括控制技術、調速方法、建模與仿真…

【靶場】XXE-Lab xxe漏洞

前言 學習xxe漏洞,搭了個XXE-Lab的靶場 一、搭建靶場 現在需要登錄,不知道用戶名密碼,先隨便試試抓包 二、判斷是否存在xxe漏洞 1.首先登錄抓包 看到xml數據解析,由此判斷和xxe漏洞有關,但還不確定xxe漏洞是否存在。 2.嘗試xxe 漏洞 判斷是否存在xxe漏洞 A.send to …

【C++特殊工具與技術】優化內存分配(三):operator new函數和opertor delete函數

目錄 一、基礎概念&#xff1a;operator new與operator delete的本質 1.1 標準庫提供的operator new接口 1.2 標準庫operator delete的接口 1.3 關鍵特性總結 二、new表達式與operator new的調用鏈解析 2.1 new表達式的底層步驟 2.2 示例&#xff1a;觀察new表達式的調用…

[c#]判定當前軟件是否用管理員權限打開

有時一些軟件的邏輯中需要使用管理員權限對某些文件進行修改時&#xff0c;那么該軟件在執行或者打開的場合&#xff0c;就需要用使用管理員身份運行才能達到效果。那么在c#里&#xff0c;如何判定該軟件是否是對管理員身份運的呢&#xff1f; 1.取得當前的windows用戶。 2.取得…

如果在main中拋出異常,該如何處理

#采用 setDefaultUncaughtExceptionHandler 進行全局兜底 public static void main(String[] args) { Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> { System.err.println("全局捕獲異常: " ex.getMessage()); ex.printStackTrace(); System.exi…

HBM 讀的那些事

如下所示&#xff0c;為HBM讀的時序。注意這里說的HBM是和HBM3是有區別的. RL 的配置,是通過MR2來實現的 WDQS貌似和CK同頻。這幅圖告訴你&#xff0c;WDQS和CK的源頭是一樣的&#xff0c;都來自PLL&#xff0c;而且中間沒有經過倍頻操作。所以兩者頻率基本是一致的。這是HBM的…

省略號和可變參數模板

本文主要介紹如何展開可變參數的參數包 1.C語言的va_list展開可變參數 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 聲明va_list類型的變量va_list args;// 使用va_start將可變參數寫入變量argsva_start(args, count);for (in…

三十五、面向對象底層邏輯-Spring MVC中AbstractXlsxStreamingView的設計

在Web應用開發中&#xff0c;大數據量的Excel導出功能是常見需求。傳統Apache POI的XSSF實現方式在處理超大數據集時&#xff0c;會因全量加載到內存導致OOM&#xff08;內存溢出&#xff09;問題。Spring MVC提供的AbstractXlsxStreamingView通過流式處理機制&#xff0c;有效…

【大模型:知識圖譜】--3.py2neo連接圖數據庫neo4j

【圖數據庫】--Neo4j 安裝_neo4j安裝-CSDN博客 需要打開圖數據庫Neo4j&#xff0c; neo4j console 目錄 1.圖數據庫--連接 2.圖數據庫--操作 2.1.創建節點 2.2.刪除節點 2.3.增改屬性 2.4.建立關系 2.5.查詢節點 2.6.查詢關系 3.圖數據庫--實例 1.圖數據庫--連接 fr…

基于dify的營養分析工作流:3分鐘生成個人營養分析報告

你去醫院做體檢&#xff0c;需要多久拿到體檢報告呢&#xff1f;醫院會為每位病人做一份多維度的健康報告嗎&#xff1f;"人工報告需1小時/份&#xff1f;數據誤差率高達35%&#xff1f;傳統工具無法個性化&#xff1f; Dify工作流AI模型的組合拳&#xff0c;正在重塑健康…

Web后端基礎(基礎知識)

BS架構&#xff1a;Browser/Server&#xff0c;瀏覽器/服務器架構模式。客戶端只需要瀏覽器&#xff0c;應用程序的邏輯和數據都存儲在服務端。 優點&#xff1a;維護方便缺點&#xff1a;體驗一般 CS架構&#xff1a;Client/Server&#xff0c;客戶端/服務器架構模式。需要單獨…

MySQL(56)什么是復合索引?

復合索引&#xff08;Composite Index&#xff09;&#xff0c;也稱為多列索引&#xff0c;是在數據庫表的多列上創建的索引。它可以提高涉及多個列的查詢性能&#xff0c;通過組合多個列的值來索引數據。復合索引特別適用于需要同時過濾多列的查詢。 復合索引的優點 提高多列…

高并發下的緩存擊穿/雪崩解決方案

有效解決緩存擊穿和雪崩的方法包括&#xff1a;1. 使用互斥鎖處理緩存擊穿&#xff1b;2. 采用熔斷器模式防止雪崩&#xff1b;3. 實施緩存預熱和降級策略&#xff1b;4. 利用分片和多級緩存分散請求壓力。這些方法各有優劣&#xff0c;需根據實際業務場景靈活調整和結合使用。…

【讀論文】OpenAI o3與o4系統模型技術報告解讀

回顧一下,4月16日,OpenAI發布了一份關于其o系列新模型——OpenAI o3和OpenAI o4-mini——的System Card。這份文檔不僅揭示了這兩款模型在推理能力和工具使用方面的顯著進步,也詳細闡述了其訓練方法、數據來源、安全評估以及在圖像理解生成、數學推理等多個核心領域的表現。…

第1課、LangChain 介紹

LangChain 介紹 LangChain 是一個以大語言模型&#xff08;LLM, Large Language Model&#xff09;為核心的開發框架&#xff0c;旨在幫助開發者高效地將如 GPT-4 等大型語言模型與外部數據源和計算資源集成&#xff0c;構建智能化應用。 1.1 工作原理 如上圖所示&#xff…

【論文閱讀28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆開、篩優質因子&#xff0c;再用 CNN-BiLSTM-Attention 來動態預測每個子序列&#xff0c;最后重構出總位移&#xff0c;預測效果超越傳統模型。 文章目錄 1 引言2 方法2.1 位移時間序列加性模型2.2 變分模態分解 (VMD) 具體步驟2.3.1 樣本熵&#xff08;S…