配置按钮权限

博主这里就不贴SQL了,自行手动添加一下吧。

更改表结构

ALTER TABLE `tienchin_course`
MODIFY COLUMN `info` varchar(255) NULL DEFAULT NULL COMMENT '课程简介' AFTER `apply_to`;

后端

更改实体类数据类型

Course.java:

/**
* 课程简介
*/
private String info; // get set 略过

插入测试数据

INSERT INTO `TienChin`.`tienchin_course` (`course_id`, `type`, `name`, `price`, `apply_to`, `info`, `remark`, `create_by`, `update_by`, `create_time`, `update_time`, `del_flag`) VALUES (1, 1, '爵士舞', 2999, 1, '爵士舞入门', NULL, NULL, NULL, NULL, '2023-09-24 02:11:21', '0');

CourseController.java

/**
* <p>
* 前端控制器
* </p>
*
* @author BNTang
* @since 2023-09-23
*/
@RestController
@RequestMapping("/tienchin/course")
public class CourseController extends BaseController { @Resource
private ICourseService iCourseService; @PreAuthorize("hasPermission('tienchin:course:list')")
@GetMapping("/list")
TableDataInfo list() {
startPage();
return getDataTable(iCourseService.selectCourseList());
}
}

ICourseService.java

/**
* <p>
* 服务类
* </p>
*
* @author BNTang
* @since 2023-09-23
*/
public interface ICourseService extends IService<Course> { /**
* 查询课程列表
*
* @return 课程列表
*/
List<Course> selectCourseList();
}

CourseServiceImpl.java

/**
* <p>
* 服务实现类
* </p>
*
* @author BNTang
* @since 2023-09-23
*/
@Service
public class CourseServiceImpl
extends ServiceImpl<CourseMapper, Course>
implements ICourseService { @Resource
private CourseMapper courseMapper; @Override
public List<Course> selectCourseList() {
return courseMapper.selectCourseList();
}
}

CourseMapper.java

/**
* <p>
* Mapper 接口
* </p>
*
* @author BNTang
* @since 2023-09-23
*/
public interface CourseMapper extends BaseMapper<Course> { /**
* 查询课程列表
*
* @return 课程列表
*/
List<Course> selectCourseList();
}

CourseMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="top.it6666.course.mapper.CourseMapper">
<select id="selectCourseList" resultType="top.it6666.course.entity.Course">
SELECT *
FROM tienchin_course
WHERE del_flag = 0
</select>
</mapper>

前端

course.js

import request from '@/utils/request'

/**
* 查询课程列表
* @param query 查询条件参数
* @returns {*} 查询结果
*/
export function listCourse(query) {
return request({
url: '/tienchin/course/list',
method: 'get',
params: query
})
} /**
* 查询渠道列表
* @returns {*} 查询结果
*/
export function listChannel() {
return request({
url: '/tienchin/activity/channel/list',
method: 'get'
})
} /**
* 查询课程详细
* @param activityId 课程ID
* @returns {*} 查询结果
*/
export function getInfo(activityId) {
return request({
url: '/tienchin/activity/' + activityId,
method: 'get'
})
} // 查询课程详细
export function getCourse(activityId) {
return request({
url: '/tienchin/activity/' + activityId,
method: 'get'
})
} // 新增课程
export function addCourse(data) {
return request({
url: '/tienchin/activity',
method: 'post',
data: data
})
} // 修改课程
export function updateCourse(data) {
return request({
url: '/tienchin/activity',
method: 'put',
data: data
})
} // 删除课程
export function delCourse(activityIds) {
return request({
url: '/tienchin/activity/' + activityIds,
method: 'delete'
})
}

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="courseName">
<el-input
v-model="queryParams.courseName"
placeholder="请输入课程名称"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="渠道名称" prop="channelId">
<el-select
v-model="queryParams.channelId"
placeholder="请选择渠道名称"
clearable
>
<el-option
v-for="channel in channelList"
:key="channel.channelId"
:label="channel.channelName"
:value="channel.channelId"
/>
</el-select>
</el-form-item>
<el-form-item label="课程状态" prop="courseStatus">
<el-select
v-model="queryParams.courseStatus"
placeholder="请选择课程状态"
clearable
>
<el-option
v-for="dict in course_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="课程类型" prop="courseType">
<el-select
v-model="queryParams.courseType"
placeholder="请选择课程类型"
clearable
>
<el-option
v-for="dict in course_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</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="['tienchin:course:create']"
>新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['tienchin:course:edit']"
>修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['tienchin:course:remove']"
>删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['tienchin: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="课程编号" align="center" prop="courseId" :show-overflow-tooltip="true"/>
<el-table-column label="课程类型" align="center">
<template #default="scope">
<dict-tag :options="course_type" :value="scope.row.type"/>
</template>
</el-table-column>
<el-table-column label="课程名称" align="center" :show-overflow-tooltip="true" prop="name"/>
<el-table-column label="课程价格" align="center" :show-overflow-tooltip="true" prop="price"/>
<el-table-column label="课程适用人群" align="center" width="120">
<template #default="scope">
<dict-tag :options="course_apply_to" :value="scope.row.applyTo"/>
</template>
</el-table-column>
<el-table-column label="课程简介" :show-overflow-tooltip="true" width="180" align="center" prop="info"/>
<el-table-column label="课程备注" :show-overflow-tooltip="true" width="180" align="center" prop="remark"/>
<el-table-column label="创建时间" align="center" prop="createTime">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
<template #default="scope">
<el-button
type="text"
icon="Edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['tienchin:course:edit']"
>修改
</el-button>
<el-button
type="text"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['tienchin: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-row>
<el-col :span="12">
<el-form-item label="渠道来源" prop="channelId">
<el-select
v-model="form.channelId"
placeholder="请选择渠道来源"
clearable
style="width: 240px;"
>
<el-option
v-for="channel in channelList"
:key="channel.channelId"
:label="channel.channelName"
:value="channel.channelId"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="课程名称" prop="courseName">
<el-input v-model="form.courseName" placeholder="请输入课程名称"/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="课程时间" style="width: 100%;" prop="courseTime">
<el-date-picker
style="width: 100%;"
v-model="form.courseTime"
format="YYYY-MM-DD HH:mm:ss"
type="datetimerange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="课程简介" prop="courseInfo">
<el-input v-model="form.courseInfo" placeholder="请输入课程简介"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="课程类型" prop="courseType">
<el-select
v-model="form.courseType"
placeholder="请选择课程类型"
clearable
style="width: 240px;"
>
<el-option
v-for="dict in course_type"
:key="dict.value"
:label="dict.label"
:value="parseInt(dict.value)"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="15">
<el-form-item label="折扣券" prop="discount" v-if="parseInt(form.courseType) === 1">
<el-input-number
v-model="form.discount"
placeholder="请输入折扣值"
:precision="2"
:step="0.1"
:max="10"
:min="0"
style="width: 100%;"
/>
</el-form-item>
<el-form-item label="代金券" prop="voucher" v-if="parseInt(form.courseType) === 2">
<el-input-number
v-model="form.voucher"
placeholder="请输入代金券面值"
:precision="2"
:step="100"
:min="0"
style="width: 100%;"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" 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 {
addCourse,
listCourse,
listChannel,
getInfo,
updateCourse,
delCourse
} from "@/api/tienchin/course"; const {proxy} = getCurrentInstance();
const {
course_type,
course_apply_to,
} = proxy.useDict('course_type', 'course_apply_to'); const courseList = ref([]);
const channelList = 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,
courseName: undefined,
channelId: undefined,
courseStatus: undefined,
courseType: undefined
},
rules: {
channelId: [{required: true, message: "渠道来源不能为空", trigger: "blur"}],
courseName: [{required: true, message: "课程名称不能为空", trigger: "blur"}],
courseTime: [{required: true, message: "课程时间不能为空", trigger: "blur"}],
courseInfo: [{required: true, message: "课程简介不能为空", trigger: "blur"}],
courseType: [{required: true, message: "课程类型不能为空", trigger: "blur"}],
discount: [{required: true, message: "折扣值不能为空", trigger: "blur"}],
voucher: [{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 = {
channelId: undefined,
courseName: undefined,
courseTime: undefined,
courseInfo: undefined,
courseType: undefined,
discount: undefined,
voucher: undefined,
remark: undefined
};
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.courseId);
single.value = selection.length !== 1;
multiple.value = !selection.length;
} /** 新增按钮操作 */
function handleAdd() {
reset();
// handelChannelList();
open.value = true;
title.value = "添加课程";
} /** 修改按钮操作 */
function handleUpdate(row) {
reset();
// 加载渠道列表
// handelChannelList(); const courseId = row.courseId || ids.value;
getInfo(courseId).then(response => {
form.value = response.data;
form.value.courseTime = [form.value.beginTime, form.value.endTime]; open.value = true;
title.value = "修改课程";
});
} /** 提交按钮 */
function submitForm() {
proxy.$refs["courseRef"].validate(valid => {
if (valid) {
if (form.value.courseId !== undefined) {
form.value.beginTime = formatDate(form.value.courseTime[0]);
form.value.endTime = formatDate(form.value.courseTime[1]); // 删除掉,form 中的 updateTime 字段
// 删除掉,form 中的 createTime 字段
delete form.value.updateTime;
delete form.value.createTime; updateCourse(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功");
open.value = false;
getList();
});
} else {
form.value.beginTime = formatDate(form.value.courseTime[0]);
form.value.endTime = formatDate(form.value.courseTime[1]);
addCourse(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功");
open.value = false;
getList();
});
}
}
});
} /** 删除按钮操作 */
function handleDelete(row) {
const courseIds = row.courseId || ids.value;
proxy.$modal.confirm('是否确认删除课程编号为"' + courseIds + '"的数据项?').then(function () {
return delCourse(courseIds);
}).then(() => {
getList();
proxy.$modal.msgSuccess("删除成功");
}).catch(() => {
});
} /** 导出按钮操作 */
function handleExport() {
proxy.download("tienchin/course/export", {
...queryParams.value
}, `course_${new Date().getTime()}.xlsx`);
} /**
* 获取渠道列表
*/
function handelChannelList() {
listChannel().then(response => {
channelList.value = response.data;
});
} function formatDate(isoDateString) {
// 创建一个新的日期对象
var date = new Date(isoDateString); // 提取年、月、日、小时、分钟和秒
var year = date.getFullYear();
var month = (date.getMonth() + 1).toString().padStart(2, "0");
var day = date.getDate().toString().padStart(2, "0");
var hours = date.getHours().toString().padStart(2, "0");
var minutes = date.getMinutes().toString().padStart(2, "0");
var seconds = date.getSeconds().toString().padStart(2, "0"); // 构建格式化后的日期时间字符串
var formattedDate = year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds; // 返回格式化后的日期时间字符串
return formattedDate;
} handelChannelList();
getList();
</script>

TienChin-课程管理-展示课程列表的更多相关文章

  1. 阶段5 3.微服务项目【学成在线】_day07 课程管理实战_06-课程营销实战分析

    课程营销信息包括课程价格.课程有效期等信息. 课程营销信息使用course_market表存储. 接口我们要提供两个. 接口1先查询课程营销的信息,在页面展示. 接口2:叫做更新,如果发现数据不存在就 ...

  2. 阶段5 3.微服务项目【学成在线】_day07 课程管理实战_05-课程修改实战分析

    3 课程信息修改 3.1 需求分析 课程添加成功进入课程管理页面,通过课程管理页面修改课程的基本信息.编辑课程图片.编辑课程营销信息等. 本小节实现修改课程. 3.2 课程管理页面说明 3.2.1 页 ...

  3. 阶段5 3.微服务项目【学成在线】_day07 课程管理实战_04-新增课程-数据字典

    课程的等级是个单选按钮 2.3 数据字典 2.3.1介绍 在新增课程界面需要选择课程等级.课程状态等,这些信息统一采用数据字典管理的方式. 本项目对一些业务的分类配置信息,比如:课程等级.课程状态.用 ...

  4. 阶段5 3.微服务项目【学成在线】_day07 课程管理实战_03-新增课程-课程分类查询

    2 新增课程 2.1 需求分析 用户操作流程如下: 1.用户进入“我的课程”页面,点击“新增课程”,进入新增课程页面 2.填写课程信息,选择课程分类.课程等级.学习模式等. 3.信息填写完毕,点击“提 ...

  5. day81:luffy:课程分类页面&课程信息页面&指定分类显示课程信息&分页显示课程信息

    目录 1.构建课程前端初始页面 2.course后端的准备工作 3.后端实现课程分类列表接口 4.前端发送请求-获取课程分类信息 5.后端实现课程列表信息的接口 6.前端显示列表课程信息 7.按照指定 ...

  6. OCM_第一天课程:OCM课程环境搭建

    注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...

  7. 【Python】通过python代码实现demo_test环境的登录,通过csv/txt/excel文件批量添加课程并开启课程操作--(刚开始 项目 页面 模块 元素这种鸟 被称作pageobject 等这些搞完 然后把你的定位器、数据 和脚本在分离 就是传说中那个叫数据驱动 的鸟)

    一.1.通过csv文件批量导入数据 1 from selenium import webdriver from time import ctime,sleep import csv #循环读取每一行每 ...

  8. 优雅智慧女性课程班 - 公开课程 - 课程介绍 - 中国人民大学商学院EDP中心

    优雅智慧女性课程班 - 公开课程 - 课程介绍 - 中国人民大学商学院EDP中心 优雅智慧女性课程班 课程总览 思想睿智成熟,外表美丽自信,气质优雅端庄,是魅力女性所应具备的特性.在当今不确定环境下, ...

  9. 小菜菜mysql练习解读分析1——查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数

    查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数 好的,第一道题,刚开始做,就栽了个跟头,爽歪歪,至于怎么栽跟头的 ——需要分析题目,查询的是 ...

  10. 巨蟒django之CRM2 展示客户列表&&分页

    1.展示客户列表 点击画红线中的views,进入下列界面 路径的查找顺序:应该是先查找外层的templates里边的html,然后查找app里边的templates 另一个会按照app的顺序进行寻找, ...

随机推荐

  1. Mapper that could not be found

    现象1 mapper 资源扫不到 resources 建的是 目录 ,不是 package 所以如果直接 a.b 的方式创建,会扫描不到 mapper.xml 文件 现象2 缺少配置文件 HisDru ...

  2. CompletableFuture 打桌球的应用

    CompletableFuture 使用 @Test public void billiardTest() throws Exception { // 创建点外卖线程: CompletableFutu ...

  3. Mac 播放 swf Flash文件

    Flash已不再支持,swf 文件彻底打不开了(一些教程),通过PD虚拟,安装 windows 操作系统在里在装了 flash 播放器使用了一段时间,始终不方便.于是找到了如下方法 首先安装:Adob ...

  4. 『NexT』,一款 NexT 风格的 Typora 主题

    很喜欢 Hexo 中的 Next 主题,便想要在 Typora 中书写时获得和在 Hexo 中一样的预览效果,翻了一下Typora的theme仓库发现已经有dalao (知乎@Bill Chen)写了 ...

  5. the server responded with a status of 413 (Request Entity Too Large) 解决

    前端上传文件,本地测试好的,放到服务器上出现了这个错误:the server responded with a status of 413 (Request Entity Too Large) 问题原 ...

  6. uni-app实现登录功能

    https://www.bilibili.com/video/BV1jy4y1B7pw?p=140&spm_id_from=pageDriver uniapp封装request,设置请求头与t ...

  7. 基于java+springboot的租房网站、房屋出租管理系统

    该系统是基于java+springboot+vue开发的租房管理系统.是给师弟开发的课程作业.学习过程中,遇到问题可以留言咨询. 演示地址 前台地址: http://zf.gitapp.cn 后台地址 ...

  8. 小景的Dba之路--impdp导入数据问题报错排查总结

    小景最近在工作中遇到了一个问题,用impdp做数据导入的时候,有以下报错,下面是问题排查过程: 首先看到了ORA-01950:no privileges on tablespace 'PUBDATA' ...

  9. WPF|分享一个登录界面设计

    分享一个登录界面,先看效果图: 准备 文中使用到了一些图标: 我们可以从 iconfont免费下载: 代码简单说明 请随手创建一个WPF项目(.NET Framework..NET 5\6\7皆可), ...

  10. [java] JSP post 提交乱码 解决方案

    //在post提交的页面顶部插入下列代码 <% request.setCharacterEncoding("UTF-8"); %>