From 6acae8d648bb7c6ccedb38fb5c3b3df2f135aa97 Mon Sep 17 00:00:00 2001 From: tangjie <122778500@qq.com> Date: Fri, 21 Aug 2026 15:45:34 +0800 Subject: [PATCH] feat --- jjb.config.js | 4 +- src/api/courseware/index.js | 27 +- src/enumerate/constant/index.js | 15 + .../EduTraining/ClassManage/index.js | 278 ++++++++++++ .../EduTraining/CourseManage/Add/index.js | 414 ++++++++++++++++++ .../EduTraining/CourseManage/List/index.js | 202 +++++++++ .../EduTraining/CourseManage/index.js | 301 +------------ src/pages/Container/Layout/menuConfig.js | 7 +- 8 files changed, 947 insertions(+), 301 deletions(-) create mode 100644 src/pages/Container/EduTraining/ClassManage/index.js create mode 100644 src/pages/Container/EduTraining/CourseManage/Add/index.js create mode 100644 src/pages/Container/EduTraining/CourseManage/List/index.js diff --git a/jjb.config.js b/jjb.config.js index b974c27..509411b 100644 --- a/jjb.config.js +++ b/jjb.config.js @@ -13,8 +13,8 @@ module.exports = { //API_HOST: "http://localhost:80", // API_HOST: "http://192.168.0.134", - // API_HOST: "http://192.168.0.150", //太浅 - API_HOST: "https://gbs-gateway.qhdsafety.com", + API_HOST: "http://192.168.0.150", //太浅 + // API_HOST: "https://gbs-gateway.qhdsafety.com", // API_HOST: "http://192.168.0.103", //huwei }, production: { diff --git a/src/api/courseware/index.js b/src/api/courseware/index.js index 11ecbee..d3bcb22 100644 --- a/src/api/courseware/index.js +++ b/src/api/courseware/index.js @@ -1,6 +1,6 @@ import { declareRequest } from "@cqsjjb/jjb-dva-runtime"; -/** 教育培训 — 培训课件管理 / 培训课程管理 */ +/** 教育培训 — 培训课件管理 / 培训课程管理 / 班级管理 */ /** 分页查询课件 */ export const coursewarePage = declareRequest( @@ -39,3 +39,28 @@ export const coursePage = declareRequest( "Get > /safetyEval/courseManagement/page", "courseList: [] | res.data || [] & courseTotal: 0 | res.total || 0", ); + +/** 新增课程 */ +export const courseAdd = declareRequest( + "courseConfirmLoading", + "Post > @/safetyEval/courseManagement/save", +); + +/** 课程详情 */ +export const courseDetail = declareRequest( + "courseDetailLoading", + "Get > /safetyEval/courseManagement/get", +); + +/** 修改课程 */ +export const courseModify = declareRequest( + "courseConfirmLoading", + "Post > @/safetyEval/courseManagement/modify", +); + +/** 分页查询班级 */ +export const classPage = declareRequest( + "classLoading", + "Get > /safetyEval/classManagement/page", + "classList: [] | res.data || [] & classTotal: 0 | res.total || 0", +); diff --git a/src/enumerate/constant/index.js b/src/enumerate/constant/index.js index e707c43..0d0def3 100644 --- a/src/enumerate/constant/index.js +++ b/src/enumerate/constant/index.js @@ -662,6 +662,21 @@ export const COURSEWARE_TYPE_MAP = COURSEWARE_TYPE_OPTIONS.reduce( {}, ); +/** 班级状态(0未申请/1待开班/2培训中/3培训结束) */ +export const CLASS_STATUS_OPTIONS = [ + { label: "未申请", value: 0 }, + { label: "待开班", value: 1 }, + { label: "培训中", value: 2 }, + { label: "培训结束", value: 3 }, +]; + +export const CLASS_STATUS_MAP = { + 0: { label: "未申请", status: "default" }, + 1: { label: "待开班", status: "warning" }, + 2: { label: "培训中", status: "processing" }, + 3: { label: "培训结束", status: "success" }, +}; + /** 试卷类型(fixed平台试卷/config_rule规则试卷) */ export const PAPER_TYPE_OPTIONS = [ { label: "平台试卷", value: "fixed" }, diff --git a/src/pages/Container/EduTraining/ClassManage/index.js b/src/pages/Container/EduTraining/ClassManage/index.js new file mode 100644 index 0000000..67955b9 --- /dev/null +++ b/src/pages/Container/EduTraining/ClassManage/index.js @@ -0,0 +1,278 @@ +import { useEffect } from "react"; +import { Badge, Button, Form, Input, Modal, Table, message } from "antd"; +import dayjs from "dayjs"; +import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout"; +import TableAction from "@cqsjjb/jjb-react-admin-component/TableAction"; +import ControlWrapper from "@cqsjjb/jjb-react-admin-component/ControlWrapper"; +import SearchForm from "~/components/SearchForm"; +import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd"; +import { Connect } from "@cqsjjb/jjb-dva-runtime"; +import { tools } from "@cqsjjb/jjb-common-lib"; +import { NS_COURSEWARE } from "~/enumerate/namespace"; +import { + CLASS_STATUS_MAP, + CLASS_STATUS_OPTIONS, + COURSEWARE_TRAINING_TYPE_MAP, + COURSEWARE_TRAINING_TYPE_OPTIONS, +} from "~/enumerate/constant"; + +const { router } = tools; + +/** 涉及学员人员数 / 完成人员数:学员统计接口未接入,暂用假数据 */ +const MOCK_STUDENT_COUNT = 10; +const MOCK_COMPLETED_COUNT = 5; +/** 班级总人次:同上,暂用假数据 */ +const MOCK_TOTAL_PERSON_TIMES = 93; + +/** 搜索表单值 → 查询参数:培训时间范围拆为后端字段(yyyy-MM-dd) */ +const buildQuery = (value) => { + const { trainingDateRange, ...rest } = value || {}; + return { + ...rest, + ...(trainingDateRange?.[0] + ? { startDateBegin: trainingDateRange[0].format("YYYY-MM-DD") } + : {}), + ...(trainingDateRange?.[1] + ? { endDateEnd: trainingDateRange[1].format("YYYY-MM-DD") } + : {}), + current: 1, + size: 10, + }; +}; + +/** 教育培训 — 班级管理 */ +function ClassManagePage(props) { + const [searchForm] = Form.useForm(); + const { courseware } = props; + const { classList, classTotal: total, classLoading: loading } = + courseware || {}; + + const handleSearch = () => { + props.classPage(router.query); + }; + + useEffect(() => { + const { startDateBegin, endDateEnd, ...rest } = router.query; + searchForm.setFieldsValue({ + ...rest, + ...(startDateBegin && endDateEnd + ? { trainingDateRange: [dayjs(startDateBegin), dayjs(endDateEnd)] } + : {}), + }); + handleSearch(); + }, []); + + const onDelete = (record) => { + Modal.confirm({ + title: "提示", + content: "数据将会删除,您是否确认删除?", + okText: "是", + cancelText: "否", + onOk: () => { + message.info(`班级「${record.className}」删除接口待接入`); + }, + }); + }; + + const columns = [ + { + title: "序号", + width: 70, + fixed: "left", + render: (_, __, index) => { + const current = Number(router.query.current) || 1; + const size = Number(router.query.size) || 10; + return (current - 1) * size + index + 1; + }, + }, + { + title: "参训单位", + dataIndex: "unitName", + width: 180, + ellipsis: true, + render: (v) => v || "-", + }, + { + title: "班级名称", + dataIndex: "className", + width: 180, + ellipsis: true, + }, + { + title: "班级编码", + dataIndex: "classCode", + width: 180, + }, + { + title: "培训类型", + dataIndex: "trainingType", + width: 160, + ellipsis: true, + render: (v) => COURSEWARE_TRAINING_TYPE_MAP[v] ?? (v || "-"), + }, + { + title: "培训开始时间", + dataIndex: "startDate", + width: 120, + render: (v) => v || "-", + }, + { + title: "结束时间", + dataIndex: "endDate", + width: 120, + render: (v) => v || "-", + }, + { + title: "涉及学员人员数", + dataIndex: "studentCount", + width: 120, + render: () => MOCK_STUDENT_COUNT, + }, + { + title: "完成人员数", + dataIndex: "completedCount", + width: 100, + render: () => MOCK_COMPLETED_COUNT, + }, + { + title: "班级状态", + dataIndex: "status", + width: 100, + render: (v) => { + const item = CLASS_STATUS_MAP[v]; + return item ? : "-"; + }, + }, + { + title: "操作", + width: 240, + fixed: "right", + render: (_, record) => ( + + + + + {record.status === 2 && ( + + )} + + + ), + }, + ]; + + return ( + + + + , + + + , + + + , + + + , + + + , + ]} + onReset={(value) => { + router.query = buildQuery(value); + handleSearch(); + }} + onFinish={(value) => { + router.query = buildQuery(value); + handleSearch(); + }} + /> + + + + `共 ${t} 条`, + current: Number(router.query.current) || 1, + pageSize: Number(router.query.size) || 10, + onChange: (page, pageSize) => { + router.query = { ...router.query, current: page, size: pageSize }; + handleSearch(); + }, + }} + /> + + ); +} + +export default Connect( + [NS_COURSEWARE], + true, +)(AntdTableFuncControl(ClassManagePage)); diff --git a/src/pages/Container/EduTraining/CourseManage/Add/index.js b/src/pages/Container/EduTraining/CourseManage/Add/index.js new file mode 100644 index 0000000..d135918 --- /dev/null +++ b/src/pages/Container/EduTraining/CourseManage/Add/index.js @@ -0,0 +1,414 @@ +import { useEffect, useState } from "react"; +import { + Button, + Form, + Input, + Modal, + Select, + Space, + Spin, + Table, + message, +} from "antd"; +import { DeleteOutlined, PlusOutlined } from "@ant-design/icons"; +import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout"; +import TableAction from "@cqsjjb/jjb-react-admin-component/TableAction"; +import { Connect } from "@cqsjjb/jjb-dva-runtime"; +import PreviewUrlButton from "~/components/PreviewUrlButton"; +import { tools } from "@cqsjjb/jjb-common-lib"; +import AttachmentUpload from "~/components/AttachmentUpload"; +import { NS_COURSEWARE } from "~/enumerate/namespace"; +import { + COURSEWARE_TRAINING_TYPE_MAP, + COURSEWARE_TRAINING_TYPE_OPTIONS, +} from "~/enumerate/constant"; + +const { TextArea } = Input; +const { router } = tools; + +/** 教育培训 — 新增/编辑课程 */ +function CourseAddPage(props) { + const [form] = Form.useForm(); + const [selectOpen, setSelectOpen] = useState(false); + const courseId = router.query.courseId; + const isEdit = !!courseId; + // 查看模式:仅展示不可编辑 + const isView = router.query.mode === "view"; + // 编辑模式:详情就绪后再挂载表单,通过 initialValues 回显;新增模式直接挂载 + + const confirmLoading = props.courseware?.courseConfirmLoading; + const { courseDetailLoading } = props.courseware; + + useEffect(() => { + if (!isEdit) return; + (async () => { + const res = await props.courseDetail({ id: courseId }); + if (res?.success !== false && res?.data) { + form.setFieldsValue({ + courseName: res.data.courseName, + trainingType: res.data.trainingType, + courseDescription: res.data.courseDescription, + courseCover: JSON.parse(res.data.courseCover || "[]"), + courseRelCoursewareDTOList: (res.data.courseRelCoursewareVOList || []).map( + ({ + coursewareId, + coursewareName, + coursewareDocument, + classHourDuration, + creditHours, + sort, + }) => ({ + coursewareId, + coursewareName, + coursewareDocument, + classHourDuration, + creditHours, + sort, + }), + ), + }) + } else { + props.history.goBack(); + } + })(); + }, []); + + const handleSubmit = async () => { + try { + const values = await form.validateFields(); + // 封面组件值为 fileList 数组,提交时序列化为 JSON 数组字符串 + values.courseCover = values.courseCover?.length + ? JSON.stringify(values.courseCover) + : undefined; + // 归属课件:Form.List 未注册字段(coursewareId 等)不在 validateFields 结果中,从表单 store 取完整数据并附带排序 + const relList = form.getFieldValue("courseRelCoursewareDTOList") || []; + values.courseRelCoursewareDTOList = relList.length + ? relList.map((item, index) => ({ ...item, sort: index + 1 })) + : undefined; + const res = await (isEdit + ? props.courseModify({ id: courseId, ...values }) + : props.courseAdd(values)); + if (res?.success !== false) { + message.success("保存成功"); + props.history.goBack(); + } + } catch { + // 表单校验失败或请求异常,由 antd / http 层提示 + } + }; + + + + return ( + + + + + ) + } + > + + {( + <> +

课程基本信息

+
+ + + + +