【Web应用】若依框架:基础篇14 源码阅读-后端代码分析-课程管理模块前后端代码分析

发布于:2025-06-05 ⋅ 阅读:(31) ⋅ 点赞:(0)


一、课程管理模块前端代码截图

在这里插入图片描述

二、前端代码及分析

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-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>

    <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>

    <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>
    
    <pagination
      v-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-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">
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 = 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>

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
{
    @Autowired
    private 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)
    @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));
    }

    /**
     * 删除课程管理
     */
    @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
{
    @Autowired
    private 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)
    @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));
    }

    /**
     * 删除课程管理
     */
    @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
{
    @Autowired
    private 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)
    @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));
    }

    /**
     * 删除课程管理
     */
    @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
{
    @Autowired
    private 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)
    @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));
    }

    /**
     * 删除课程管理
     */
    @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)优化用户体验。

通过以上流程,前后端协同工作,实现了课程管理的完整功能。


网站公告

今日签到

点亮在社区的每一天
去签到