safety-eval-service-frontend/src/pages/Container/EduTraining/CourseManage/index.js

300 lines
8.5 KiB
JavaScript
Raw Normal View History

2026-08-19 13:47:08 +08:00
import { useEffect, useState } from "react";
import {
Badge,
Button,
Descriptions,
Form,
Modal,
Table,
message,
} from "antd";
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 PreviewUrlButton from "~/components/PreviewUrlButton";
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 {
COURSEWARE_STATUS_MAP,
COURSEWARE_STATUS_OPTIONS,
COURSEWARE_TRAINING_TYPE_MAP,
COURSEWARE_TRAINING_TYPE_OPTIONS,
} from "~/enumerate/constant";
const { router } = tools;
/** 解析课件文档字段JSON 数组字符串,容错非法格式 */
const parseCoursewareDocument = (raw) => {
if (!raw) return [];
try {
const parsed = JSON.parse(raw);
return Array.isArray(parsed) ? parsed : [];
} catch {
return [];
}
};
/** 培训课程管理 */
function CourseManagePage(props) {
const [searchForm] = Form.useForm();
const [viewRecord, setViewRecord] = useState(null);
const { courseware } = props;
const { courseList: dataSource, courseTotal: total, courseLoading: loading } =
courseware || {};
const handleSearch = () => {
props.coursePage(router.query);
};
useEffect(() => {
searchForm.setFieldsValue(router.query);
handleSearch();
}, []);
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: "courseName",
width: 260,
ellipsis: true,
},
{
title: "课程描述",
dataIndex: "courseDescription",
width: 320,
ellipsis: true,
},
{
title: "课程状态",
dataIndex: "status",
width: 90,
render: (v) => {
const item = COURSEWARE_STATUS_MAP[v];
return item ? <Badge status={item.status} text={item.label} /> : "-";
},
},
{
title: "总课时",
dataIndex: "classHourDuration",
width: 90,
render: (v) => (v == null ? "-" : v),
},
{
title: "上传单位",
dataIndex: "uploadUnit",
width: 200,
ellipsis: true,
},
{
title: "是否已使用",
dataIndex: "used",
width: 100,
render: (v) => (v === 1 ? "已使用" : "未使用"),
},
{
title: "操作",
width: 200,
fixed: "right",
render: (_, record) => (
<TableAction>
<Button
type="link"
size="small"
onClick={() => setViewRecord(record)}
>
查看
</Button>
<Button
type="link"
size="small"
onClick={() => message.info("课程启用/禁用接口待接入")}
>
{record.status === 1 ? "禁用" : "启用"}
</Button>
<Button
type="link"
size="small"
onClick={() => message.info("课程编辑接口待接入")}
>
编辑
</Button>
<Button
danger
type="link"
size="small"
onClick={() => message.info("课程删除接口待接入")}
>
删除
</Button>
</TableAction>
),
},
];
const relatedCourseware = viewRecord?.courseRelCoursewareVOList || [];
return (
<PageLayout title="培训课程管理">
<SearchForm
style={{ marginBottom: 24 }}
form={searchForm}
loading={loading}
formLine={[
<Form.Item key="courseName" name="courseName">
<ControlWrapper.Input
label="课程名称"
placeholder="请输入名称"
allowClear
maxLength={50}
/>
</Form.Item>,
<Form.Item key="trainingType" name="trainingType">
<ControlWrapper.Select
label="培训类型"
placeholder="请选择"
allowClear
style={{ width: "100%" }}
options={COURSEWARE_TRAINING_TYPE_OPTIONS}
/>
</Form.Item>,
<Form.Item key="status" name="status">
<ControlWrapper.Select
label="课程状态"
placeholder="请选择课程状态"
allowClear
style={{ width: "100%" }}
options={COURSEWARE_STATUS_OPTIONS}
/>
</Form.Item>,
]}
onReset={(value) => {
router.query = { ...value, current: 1, size: 10 };
handleSearch();
}}
onFinish={(value) => {
router.query = { ...value, current: 1, size: 10 };
handleSearch();
}}
/>
<Table
rowKey="id"
columns={columns}
dataSource={Array.isArray(dataSource) ? dataSource : []}
scroll={{ x: 1500, y: props.scrollY }}
loading={loading}
pagination={{
total,
showSizeChanger: true,
showQuickJumper: true,
showTotal: (t) => `${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();
},
}}
/>
<Modal
title="课程详情"
open={!!viewRecord}
width={760}
footer={null}
onCancel={() => setViewRecord(null)}
>
<Descriptions column={2} bordered size="small">
<Descriptions.Item label="课程名称" span={2}>
{viewRecord?.courseName || "-"}
</Descriptions.Item>
<Descriptions.Item label="培训类型">
{COURSEWARE_TRAINING_TYPE_MAP[viewRecord?.trainingType]
?? (viewRecord?.trainingType || "-")}
</Descriptions.Item>
<Descriptions.Item label="课程状态">
{COURSEWARE_STATUS_MAP[viewRecord?.status]?.label || "-"}
</Descriptions.Item>
<Descriptions.Item label="总课时">
{viewRecord?.classHourDuration ?? "-"}
</Descriptions.Item>
<Descriptions.Item label="是否已使用">
{viewRecord?.used === 1 ? "已使用" : "未使用"}
</Descriptions.Item>
<Descriptions.Item label="上传单位" span={2}>
{viewRecord?.uploadUnit || "-"}
</Descriptions.Item>
<Descriptions.Item label="课程描述" span={2}>
{viewRecord?.courseDescription || "-"}
</Descriptions.Item>
</Descriptions>
<div style={{ marginTop: 16, marginBottom: 8, fontWeight: 600 }}>
关联课件
</div>
<Table
rowKey={(row) => row.coursewareId}
size="small"
columns={[
{ title: "序号", width: 60, render: (_, __, i) => i + 1 },
{
title: "课件名称",
dataIndex: "coursewareName",
ellipsis: true,
},
{
title: "课时时长(小时)",
dataIndex: "classHourDuration",
width: 130,
render: (v) => (v == null ? "-" : v),
},
{
title: "学时",
dataIndex: "creditHours",
width: 90,
render: (v) => (v == null ? "-" : v),
},
{
title: "课件文档",
dataIndex: "coursewareDocument",
width: 160,
render: (raw) => {
const files = parseCoursewareDocument(raw);
return files.length ? (
files.map((f, i) => (
<PreviewUrlButton key={f.uid || i} url={f.url}>
{f.name || f.url}
</PreviewUrlButton>
))
) : (
"-"
);
},
},
]}
dataSource={relatedCourseware}
pagination={false}
/>
</Modal>
</PageLayout>
);
}
export default Connect(
[NS_COURSEWARE],
true,
)(AntdTableFuncControl(CourseManagePage));