feat
parent
d12fd88685
commit
45beeabf85
|
|
@ -1,109 +0,0 @@
|
||||||
{
|
|
||||||
"openapi": "3.0.1",
|
|
||||||
"info": {
|
|
||||||
"title": "分页查询学员考试记录",
|
|
||||||
"description": "同步自 Apifox(学员考试记录),int64 主键按前端精度规范落为 string",
|
|
||||||
"version": "1.0.0"
|
|
||||||
},
|
|
||||||
"paths": {
|
|
||||||
"/safetyEval/classStudentExamRecord/page": {
|
|
||||||
"get": {
|
|
||||||
"summary": "分页查询学员考试记录",
|
|
||||||
"tags": ["学员考试记录"],
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "current",
|
|
||||||
"in": "query",
|
|
||||||
"description": "当前页(默认1)",
|
|
||||||
"required": false,
|
|
||||||
"schema": { "type": "integer", "default": 1 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "size",
|
|
||||||
"in": "query",
|
|
||||||
"description": "每页条数(默认10)",
|
|
||||||
"required": false,
|
|
||||||
"schema": { "type": "integer", "default": 10 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "classId",
|
|
||||||
"in": "query",
|
|
||||||
"description": "所属班级ID(后端 Long;前端按字符串保证精度)",
|
|
||||||
"required": false,
|
|
||||||
"schema": { "type": "string" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "studentId",
|
|
||||||
"in": "query",
|
|
||||||
"description": "学员ID(后端 Long;前端按字符串保证精度)",
|
|
||||||
"required": false,
|
|
||||||
"schema": { "type": "string" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "examId",
|
|
||||||
"in": "query",
|
|
||||||
"description": "试卷id(后端 Long;前端按字符串保证精度)",
|
|
||||||
"required": false,
|
|
||||||
"schema": { "type": "string" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "passed",
|
|
||||||
"in": "query",
|
|
||||||
"description": "是否通过(0-未通过,1-通过)",
|
|
||||||
"required": false,
|
|
||||||
"schema": { "type": "integer" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": { "$ref": "#/components/schemas/PageResponseClassStudentExamRecordVO" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"components": {
|
|
||||||
"schemas": {
|
|
||||||
"PageResponseClassStudentExamRecordVO": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"success": { "type": "boolean", "description": "是否成功" },
|
|
||||||
"code": { "type": "string", "description": "响应码" },
|
|
||||||
"message": { "type": "string", "description": "响应消息" },
|
|
||||||
"errMessage": { "type": "string", "description": "错误响应消息" },
|
|
||||||
"data": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "响应数据",
|
|
||||||
"items": { "$ref": "#/components/schemas/ClassStudentExamRecordVO" }
|
|
||||||
},
|
|
||||||
"total": { "type": "integer", "description": "总条数" }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ClassStudentExamRecordVO": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "学员考试记录",
|
|
||||||
"properties": {
|
|
||||||
"id": { "type": "string", "description": "主键" },
|
|
||||||
"studentId": { "type": "string", "description": "学员ID(后端 Long;前端按字符串保证精度)" },
|
|
||||||
"studentName": { "type": "string", "description": "学员名称" },
|
|
||||||
"classId": { "type": "string", "description": "所属班级ID(后端 Long;前端按字符串保证精度)" },
|
|
||||||
"paperName": { "type": "string", "description": "试卷名称" },
|
|
||||||
"paperId": { "type": "string", "description": "试卷id(后端 Long;前端按字符串保证精度)" },
|
|
||||||
"score": { "type": "number", "description": "得分" },
|
|
||||||
"passed": { "type": "integer", "description": "是否通过(0-未通过,1-通过)" },
|
|
||||||
"wrongCount": { "type": "integer", "description": "错误题数" },
|
|
||||||
"accuracy": { "type": "number", "description": "正确率(百分比)" },
|
|
||||||
"startTime": { "type": "string", "description": "考试开始时间" },
|
|
||||||
"endTime": { "type": "string", "description": "考试结束时间" },
|
|
||||||
"className": { "type": "string", "description": "app: 班级名称" },
|
|
||||||
"examDurationMinutes": { "type": "integer", "description": "app: 考试时长分钟" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
/**
|
|
||||||
* GET /safetyEval/classStudentExamRecord/page —— 分页查询学员考试记录
|
|
||||||
* 契约见同目录 spec.json
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** 分页查询入参 */
|
|
||||||
export interface ClassStudentExamRecordPageQuery {
|
|
||||||
/** 当前页(默认1) */
|
|
||||||
current?: number;
|
|
||||||
/** 每页条数(默认10) */
|
|
||||||
size?: number;
|
|
||||||
/** 所属班级ID(后端 Long;前端按字符串保证精度) */
|
|
||||||
classId?: string;
|
|
||||||
/** 学员ID(后端 Long;前端按字符串保证精度) */
|
|
||||||
studentId?: string;
|
|
||||||
/** 试卷id(后端 Long;前端按字符串保证精度) */
|
|
||||||
examId?: string;
|
|
||||||
/** 是否通过(0-未通过,1-通过) */
|
|
||||||
passed?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 学员考试记录 */
|
|
||||||
export interface ClassStudentExamRecordVO {
|
|
||||||
/** 主键 */
|
|
||||||
id?: string;
|
|
||||||
/** 学员ID(后端 Long;前端按字符串保证精度) */
|
|
||||||
studentId?: string;
|
|
||||||
/** 学员名称 */
|
|
||||||
studentName?: string;
|
|
||||||
/** 所属班级ID(后端 Long;前端按字符串保证精度) */
|
|
||||||
classId?: string;
|
|
||||||
/** 试卷名称 */
|
|
||||||
paperName?: string;
|
|
||||||
/** 试卷id(后端 Long;前端按字符串保证精度) */
|
|
||||||
paperId?: string;
|
|
||||||
/** 得分 */
|
|
||||||
score?: number;
|
|
||||||
/** 是否通过(0-未通过,1-通过) */
|
|
||||||
passed?: number;
|
|
||||||
/** 错误题数 */
|
|
||||||
wrongCount?: number;
|
|
||||||
/** 正确率(百分比) */
|
|
||||||
accuracy?: number;
|
|
||||||
/** 考试开始时间 */
|
|
||||||
startTime?: string;
|
|
||||||
/** 考试结束时间 */
|
|
||||||
endTime?: string;
|
|
||||||
/** app: 班级名称 */
|
|
||||||
className?: string;
|
|
||||||
/** app: 考试时长分钟 */
|
|
||||||
examDurationMinutes?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 响应体 */
|
|
||||||
export interface PageResponseClassStudentExamRecordVO {
|
|
||||||
success?: boolean;
|
|
||||||
code?: string;
|
|
||||||
message?: string;
|
|
||||||
errMessage?: string;
|
|
||||||
data?: ClassStudentExamRecordVO[];
|
|
||||||
total?: number;
|
|
||||||
}
|
|
||||||
|
|
@ -1,122 +0,0 @@
|
||||||
{
|
|
||||||
"openapi": "3.0.1",
|
|
||||||
"info": {
|
|
||||||
"title": "分页查询学员学习记录",
|
|
||||||
"description": "同步自 Apifox(学员学习记录),int64 主键按前端精度规范落为 string",
|
|
||||||
"version": "1.0.0"
|
|
||||||
},
|
|
||||||
"paths": {
|
|
||||||
"/safetyEval/classStudentLearningRecord/page": {
|
|
||||||
"get": {
|
|
||||||
"summary": "分页查询学员学习记录",
|
|
||||||
"tags": ["学员学习记录"],
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "current",
|
|
||||||
"in": "query",
|
|
||||||
"description": "当前页(默认1)",
|
|
||||||
"required": false,
|
|
||||||
"schema": { "type": "integer", "default": 1 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "size",
|
|
||||||
"in": "query",
|
|
||||||
"description": "每页条数(默认10)",
|
|
||||||
"required": false,
|
|
||||||
"schema": { "type": "integer", "default": 10 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "classId",
|
|
||||||
"in": "query",
|
|
||||||
"description": "所属班级ID(后端 Long;前端按字符串保证精度)",
|
|
||||||
"required": false,
|
|
||||||
"schema": { "type": "string" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "studentId",
|
|
||||||
"in": "query",
|
|
||||||
"description": "学员ID(后端 Long;前端按字符串保证精度)",
|
|
||||||
"required": false,
|
|
||||||
"schema": { "type": "string" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "courseId",
|
|
||||||
"in": "query",
|
|
||||||
"description": "课程ID(后端 Long;前端按字符串保证精度)",
|
|
||||||
"required": false,
|
|
||||||
"schema": { "type": "string" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "studyStatus",
|
|
||||||
"in": "query",
|
|
||||||
"description": "学习状态:0-未学习,1-学习中,2-已完成",
|
|
||||||
"required": false,
|
|
||||||
"schema": { "type": "integer" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/PageResponseClassStudentLearningRecordVO"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"components": {
|
|
||||||
"schemas": {
|
|
||||||
"PageResponseClassStudentLearningRecordVO": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"success": { "type": "boolean", "description": "是否成功" },
|
|
||||||
"code": { "type": "string", "description": "响应码" },
|
|
||||||
"message": { "type": "string", "description": "响应消息" },
|
|
||||||
"errMessage": { "type": "string", "description": "错误响应消息" },
|
|
||||||
"data": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "响应数据",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/ClassStudentLearningRecordVO"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"total": { "type": "integer", "description": "总条数" }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ClassStudentLearningRecordVO": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "学员学习记录(节点级)",
|
|
||||||
"properties": {
|
|
||||||
"id": { "type": "string", "description": "主键" },
|
|
||||||
"studentId": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "学员ID(后端 Long;前端按字符串保证精度)"
|
|
||||||
},
|
|
||||||
"classId": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "所属班级ID(后端 Long;前端按字符串保证精度)"
|
|
||||||
},
|
|
||||||
"courseId": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "课程ID(后端 Long;前端按字符串保证精度)"
|
|
||||||
},
|
|
||||||
"courseName": { "type": "string", "description": "课程名称" },
|
|
||||||
"coursewareName": { "type": "string", "description": "小节点名称" },
|
|
||||||
"studyStatus": {
|
|
||||||
"type": "integer",
|
|
||||||
"description": "学习状态:0-未学习,1-学习中,2-已完成"
|
|
||||||
},
|
|
||||||
"learningProgress": { "type": "string", "description": "学习情况" },
|
|
||||||
"startTime": { "type": "string", "description": "开始学习时间" },
|
|
||||||
"endTime": { "type": "string", "description": "完成时间" },
|
|
||||||
"lastWatchTime": { "type": "string", "description": "最近观看时间" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
/**
|
|
||||||
* GET /safetyEval/classStudentLearningRecord/page —— 分页查询学员学习记录
|
|
||||||
* 契约见同目录 spec.json
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** 分页查询入参 */
|
|
||||||
export interface ClassStudentLearningRecordPageQuery {
|
|
||||||
/** 当前页(默认1) */
|
|
||||||
current?: number;
|
|
||||||
/** 每页条数(默认10) */
|
|
||||||
size?: number;
|
|
||||||
/** 所属班级ID(后端 Long;前端按字符串保证精度) */
|
|
||||||
classId?: string;
|
|
||||||
/** 学员ID(后端 Long;前端按字符串保证精度) */
|
|
||||||
studentId?: string;
|
|
||||||
/** 课程ID(后端 Long;前端按字符串保证精度) */
|
|
||||||
courseId?: string;
|
|
||||||
/** 学习状态:0-未学习,1-学习中,2-已完成 */
|
|
||||||
studyStatus?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 学员学习记录(节点级) */
|
|
||||||
export interface ClassStudentLearningRecordVO {
|
|
||||||
/** 主键 */
|
|
||||||
id?: string;
|
|
||||||
/** 学员ID(后端 Long;前端按字符串保证精度) */
|
|
||||||
studentId?: string;
|
|
||||||
/** 所属班级ID(后端 Long;前端按字符串保证精度) */
|
|
||||||
classId?: string;
|
|
||||||
/** 课程ID(后端 Long;前端按字符串保证精度) */
|
|
||||||
courseId?: string;
|
|
||||||
/** 课程名称 */
|
|
||||||
courseName?: string;
|
|
||||||
/** 小节点名称 */
|
|
||||||
coursewareName?: string;
|
|
||||||
/** 学习状态:0-未学习,1-学习中,2-已完成 */
|
|
||||||
studyStatus?: number;
|
|
||||||
/** 学习情况 */
|
|
||||||
learningProgress?: string;
|
|
||||||
/** 开始学习时间 */
|
|
||||||
startTime?: string;
|
|
||||||
/** 完成时间 */
|
|
||||||
endTime?: string;
|
|
||||||
/** 最近观看时间 */
|
|
||||||
lastWatchTime?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 分页响应体 */
|
|
||||||
export interface PageResponseClassStudentLearningRecordVO {
|
|
||||||
success?: boolean;
|
|
||||||
code?: string;
|
|
||||||
message?: string;
|
|
||||||
errMessage?: string;
|
|
||||||
data?: ClassStudentLearningRecordVO[];
|
|
||||||
total?: number;
|
|
||||||
}
|
|
||||||
|
|
@ -210,3 +210,9 @@ export const classStudentExamRecordPage = declareRequest(
|
||||||
"Get > /safetyEval/classStudentExamRecord/page",
|
"Get > /safetyEval/classStudentExamRecord/page",
|
||||||
"examRecordList: [] | res.data || [] & examRecordTotal: 0 | res.total || 0",
|
"examRecordList: [] | res.data || [] & examRecordTotal: 0 | res.total || 0",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/** 考试试卷信息查询(按考试记录id,含试题列表及参考答案) */
|
||||||
|
export const studentExamPaperInfo = declareRequest(
|
||||||
|
"studentExamPaperLoading",
|
||||||
|
"Get > /safetyEval/paperExam/exam/info",
|
||||||
|
);
|
||||||
|
|
|
||||||
|
|
@ -710,8 +710,8 @@ export const CLASS_STUDENT_FACE_AUTH_MAP = {
|
||||||
export const CLASS_STUDENT_STUDY_STATUS_OPTIONS = [
|
export const CLASS_STUDENT_STUDY_STATUS_OPTIONS = [
|
||||||
{ label: "未学习", value: 0 },
|
{ label: "未学习", value: 0 },
|
||||||
{ label: "学习中", value: 1 },
|
{ label: "学习中", value: 1 },
|
||||||
{ label: "已学完", value: 2 },
|
|
||||||
{ label: "已完成", value: 3 },
|
{ label: "已完成", value: 2 },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const CLASS_STUDENT_STUDY_STATUS_MAP = CLASS_STUDENT_STUDY_STATUS_OPTIONS.reduce(
|
export const CLASS_STUDENT_STUDY_STATUS_MAP = CLASS_STUDENT_STUDY_STATUS_OPTIONS.reduce(
|
||||||
|
|
@ -743,7 +743,7 @@ export const CLASS_STUDENT_EXAM_STATUS_OPTIONS = [
|
||||||
{ label: "待考试", value: 1 },
|
{ label: "待考试", value: 1 },
|
||||||
{ label: "考试未通过", value: 2 },
|
{ label: "考试未通过", value: 2 },
|
||||||
{ label: "考试通过", value: 3 },
|
{ label: "考试通过", value: 3 },
|
||||||
{ label: "未参加", value: 4 },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export const CLASS_STUDENT_EXAM_STATUS_MAP = CLASS_STUDENT_EXAM_STATUS_OPTIONS.reduce(
|
export const CLASS_STUDENT_EXAM_STATUS_MAP = CLASS_STUDENT_EXAM_STATUS_OPTIONS.reduce(
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import SearchForm from "~/components/SearchForm";
|
||||||
import TableAction from "@cqsjjb/jjb-react-admin-component/TableAction";
|
import TableAction from "@cqsjjb/jjb-react-admin-component/TableAction";
|
||||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||||
import { NS_COURSEWARE } from "~/enumerate/namespace";
|
import { NS_COURSEWARE } from "~/enumerate/namespace";
|
||||||
|
|
||||||
import StaffViewModal from "~/components/StaffViewModal";
|
import StaffViewModal from "~/components/StaffViewModal";
|
||||||
import {
|
import {
|
||||||
CLASS_STUDENT_EXAM_STATUS_OPTIONS,
|
CLASS_STUDENT_EXAM_STATUS_OPTIONS,
|
||||||
|
|
@ -32,7 +33,7 @@ const buildQuery = (value) => {
|
||||||
|
|
||||||
/** 班级详情 — 学员 Tab:班级学员查询 */
|
/** 班级详情 — 学员 Tab:班级学员查询 */
|
||||||
function ClassStudentTab(props) {
|
function ClassStudentTab(props) {
|
||||||
const { classId } = props;
|
const { classId, form } = props;
|
||||||
const [searchForm] = Form.useForm();
|
const [searchForm] = Form.useForm();
|
||||||
const [query, setQuery] = useState({ current: 1, size: 10 });
|
const [query, setQuery] = useState({ current: 1, size: 10 });
|
||||||
const [selectOpen, setSelectOpen] = useState(false);
|
const [selectOpen, setSelectOpen] = useState(false);
|
||||||
|
|
@ -228,7 +229,7 @@ function ClassStudentTab(props) {
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
columns={columns}
|
columns={columns}
|
||||||
dataSource={tableSource}
|
dataSource={tableSource}
|
||||||
scroll={{ x: 1400 }}
|
scroll={{ x: 1400, y: 400 }}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
pagination={{
|
pagination={{
|
||||||
total,
|
total,
|
||||||
|
|
@ -265,6 +266,7 @@ function ClassStudentTab(props) {
|
||||||
studentName: userName,
|
studentName: userName,
|
||||||
department: deptName,
|
department: deptName,
|
||||||
phone: account,
|
phone: account,
|
||||||
|
examStatus: form.getFieldValue("openExam"),
|
||||||
studentId: studentId || id,
|
studentId: studentId || id,
|
||||||
fileNumber: fileNumber|| id,
|
fileNumber: fileNumber|| id,
|
||||||
unitName: unitName,
|
unitName: unitName,
|
||||||
|
|
@ -395,4 +397,4 @@ function StudentSelectModal({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Connect([NS_COURSEWARE], true)(ClassStudentTab);
|
export default Connect([NS_COURSEWARE], true)((ClassStudentTab) );
|
||||||
|
|
|
||||||
|
|
@ -297,7 +297,7 @@ function ClassAddPage(props) {
|
||||||
label: "学员",
|
label: "学员",
|
||||||
disabled: !unlocked,
|
disabled: !unlocked,
|
||||||
children: unlocked ? (
|
children: unlocked ? (
|
||||||
<StudentTab classId={savedClassId} history={props.history} />
|
<StudentTab classId={savedClassId} history={props.history} form={form} />
|
||||||
) : null,
|
) : null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { Button, Empty, Modal, Tag } from "antd";
|
||||||
|
import { NS_COURSEWARE } from "~/enumerate/namespace";
|
||||||
|
import {
|
||||||
|
EXAM_RECORD_PASSED_MAP,
|
||||||
|
QUESTION_TYPE_MAP,
|
||||||
|
} from "~/enumerate/constant";
|
||||||
|
|
||||||
|
/** 区块标题 */
|
||||||
|
const SectionTitle = ({ children }) => (
|
||||||
|
<div className="srd-detail__section-title">{children}</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
/** label: value 字段 */
|
||||||
|
const Field = ({ label, value }) => (
|
||||||
|
<div className="srd-detail__field">
|
||||||
|
<span className="srd-detail__label">{label}:</span>
|
||||||
|
<span className="srd-detail__value">{value ?? "-"}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 考试详情弹窗:学员信息 + 试卷基本信息 + 试卷内容(试题列表) */
|
||||||
|
function ExamDetailModal({
|
||||||
|
open,
|
||||||
|
record,
|
||||||
|
loading,
|
||||||
|
fetchPaperInfo,
|
||||||
|
resetModelState,
|
||||||
|
onClose,
|
||||||
|
}) {
|
||||||
|
const [info, setInfo] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) {
|
||||||
|
resetModelState?.(NS_COURSEWARE, { studentExamPaperLoading: false });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!record?.id) return;
|
||||||
|
setInfo(null);
|
||||||
|
fetchPaperInfo({ paperExamId: record.id }).then((res) => {
|
||||||
|
if (res?.success !== false) setInfo(res?.data || null);
|
||||||
|
});
|
||||||
|
}, [open, record?.id]);
|
||||||
|
|
||||||
|
const basic = info?.paperBasicInfoVO || {};
|
||||||
|
const questionList = Array.isArray(info?.questionVOList)
|
||||||
|
? info.questionVOList
|
||||||
|
: [];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
open={open}
|
||||||
|
title={`考试详情${record?.studentName ? ` - ${record.studentName}` : ""}`}
|
||||||
|
width={980}
|
||||||
|
footer={
|
||||||
|
<Button onClick={onClose}>关闭</Button>
|
||||||
|
}
|
||||||
|
destroyOnHidden
|
||||||
|
loading={loading}
|
||||||
|
onCancel={onClose}
|
||||||
|
className="srd-detail"
|
||||||
|
>
|
||||||
|
<SectionTitle>考试学员信息</SectionTitle>
|
||||||
|
<div className="srd-detail__grid">
|
||||||
|
<Field label="考试学员" value={record?.studentName} />
|
||||||
|
<Field
|
||||||
|
label="状态"
|
||||||
|
value={
|
||||||
|
record?.passed != null ? (
|
||||||
|
<Tag color={record.passed === 1 ? "green" : "red"}>
|
||||||
|
{EXAM_RECORD_PASSED_MAP[record.passed]}
|
||||||
|
</Tag>
|
||||||
|
) : (
|
||||||
|
"-"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Field label="学员得分" value={record?.score} />
|
||||||
|
<Field label="考试时间" value={record?.startTime} />
|
||||||
|
<Field
|
||||||
|
label="答题时长"
|
||||||
|
value={
|
||||||
|
record?.examDurationMinutes != null
|
||||||
|
? `${record.examDurationMinutes}分钟`
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<SectionTitle>试卷基本信息</SectionTitle>
|
||||||
|
<div className="srd-detail__grid">
|
||||||
|
<Field label="试卷名称" value={basic.paperName} />
|
||||||
|
<Field
|
||||||
|
label="考试时长"
|
||||||
|
value={basic.examTime != null ? `${basic.examTime}分钟` : undefined}
|
||||||
|
/>
|
||||||
|
<Field label="总分" value={basic.paperTotalScore} />
|
||||||
|
<Field label="合格分数" value={basic.paperPassScore} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<SectionTitle>试卷内容信息</SectionTitle>
|
||||||
|
<div className="srd-detail__count">
|
||||||
|
试题数量:<strong>{questionList.length}</strong>
|
||||||
|
</div>
|
||||||
|
{questionList.length === 0 ? (
|
||||||
|
<Empty
|
||||||
|
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||||
|
description="暂无试题"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="srd-detail__questions">
|
||||||
|
{questionList.map((q, index) => (
|
||||||
|
<div key={q.id} className="srd-detail__question">
|
||||||
|
<div className="srd-detail__question-title">
|
||||||
|
{index + 1}. {q.title || "-"}
|
||||||
|
</div>
|
||||||
|
<div className="srd-detail__question-meta">
|
||||||
|
题型:{QUESTION_TYPE_MAP[q.questionType] || q.questionType || "-"}
|
||||||
|
<span className="srd-detail__question-score">
|
||||||
|
分值:{q.questionScore ?? q.score ?? "-"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{(q.questionOptionVOList || []).length > 0 && (
|
||||||
|
<div className="srd-detail__options">
|
||||||
|
{q.questionOptionVOList.map((o) => (
|
||||||
|
<div key={o.id} className="srd-detail__option">
|
||||||
|
{o.optionKey}. {o.optionText}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="srd-detail__question-info">
|
||||||
|
参考答案:{q.answer || "-"}
|
||||||
|
</div>
|
||||||
|
<div className="srd-detail__question-info">
|
||||||
|
答案解析:{q.analysis || "-"}
|
||||||
|
</div>
|
||||||
|
<div className="srd-detail__question-info">
|
||||||
|
关联课程:{q.coursewareManagementName || "-"}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ExamDetailModal;
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Form, Table, Tabs } from "antd";
|
import { Button, Form, Table, Tabs } from "antd";
|
||||||
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
||||||
import ControlWrapper from "@cqsjjb/jjb-react-admin-component/ControlWrapper";
|
import ControlWrapper from "@cqsjjb/jjb-react-admin-component/ControlWrapper";
|
||||||
|
import TableAction from "@cqsjjb/jjb-react-admin-component/TableAction";
|
||||||
import SearchForm from "~/components/SearchForm";
|
import SearchForm from "~/components/SearchForm";
|
||||||
import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd";
|
import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd";
|
||||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||||
|
|
@ -12,6 +13,8 @@ import {
|
||||||
LEARNING_RECORD_STUDY_STATUS_MAP,
|
LEARNING_RECORD_STUDY_STATUS_MAP,
|
||||||
LEARNING_RECORD_STUDY_STATUS_OPTIONS,
|
LEARNING_RECORD_STUDY_STATUS_OPTIONS,
|
||||||
} from "~/enumerate/constant";
|
} from "~/enumerate/constant";
|
||||||
|
import ExamDetailModal from "./ExamDetailModal";
|
||||||
|
import "./index.less";
|
||||||
|
|
||||||
const { router } = tools;
|
const { router } = tools;
|
||||||
|
|
||||||
|
|
@ -21,6 +24,7 @@ function ClassStudyRecordPage(props) {
|
||||||
const [examSearchForm] = Form.useForm();
|
const [examSearchForm] = Form.useForm();
|
||||||
const [activeTab, setActiveTab] = useState("study");
|
const [activeTab, setActiveTab] = useState("study");
|
||||||
const [examQuery, setExamQuery] = useState({ current: 1, size: 10 });
|
const [examQuery, setExamQuery] = useState({ current: 1, size: 10 });
|
||||||
|
const [examDetailRecord, setExamDetailRecord] = useState(null);
|
||||||
const studentName = router.query?.studentName;
|
const studentName = router.query?.studentName;
|
||||||
const {
|
const {
|
||||||
learningRecordList: dataSource,
|
learningRecordList: dataSource,
|
||||||
|
|
@ -29,6 +33,7 @@ function ClassStudyRecordPage(props) {
|
||||||
examRecordList: examDataSource,
|
examRecordList: examDataSource,
|
||||||
examRecordTotal: examTotal,
|
examRecordTotal: examTotal,
|
||||||
examRecordLoading: examLoading,
|
examRecordLoading: examLoading,
|
||||||
|
studentExamPaperLoading: examDetailLoading,
|
||||||
} = props.courseware || {};
|
} = props.courseware || {};
|
||||||
|
|
||||||
const handleSearch = () => {
|
const handleSearch = () => {
|
||||||
|
|
@ -169,6 +174,23 @@ function ClassStudyRecordPage(props) {
|
||||||
width: 170,
|
width: 170,
|
||||||
render: (v) => v || "-",
|
render: (v) => v || "-",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "操作",
|
||||||
|
key: "action",
|
||||||
|
width: 110,
|
||||||
|
fixed: "right",
|
||||||
|
render: (_, record) => (
|
||||||
|
<TableAction>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
onClick={() => setExamDetailRecord(record)}
|
||||||
|
>
|
||||||
|
考试详情
|
||||||
|
</Button>
|
||||||
|
</TableAction>
|
||||||
|
),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/** 考试记录搜索/重置:试卷名称接口暂未支持,先行透传 */
|
/** 考试记录搜索/重置:试卷名称接口暂未支持,先行透传 */
|
||||||
|
|
@ -302,6 +324,15 @@ function ClassStudyRecordPage(props) {
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<ExamDetailModal
|
||||||
|
open={!!examDetailRecord}
|
||||||
|
record={examDetailRecord}
|
||||||
|
loading={examDetailLoading}
|
||||||
|
fetchPaperInfo={props.studentExamPaperInfo}
|
||||||
|
resetModelState={props.resetModelState}
|
||||||
|
onClose={() => setExamDetailRecord(null)}
|
||||||
|
/>
|
||||||
</PageLayout>
|
</PageLayout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/* StudyRecord — 考试详情弹窗样式(前缀 srd-) */
|
||||||
|
.srd-detail {
|
||||||
|
&__section-title {
|
||||||
|
margin: 16px 0 12px;
|
||||||
|
padding-left: 8px;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.2;
|
||||||
|
border-left: 3px solid #fa8c16;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
row-gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
color: rgba(0, 0, 0, 45%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__value {
|
||||||
|
color: rgba(0, 0, 0, 88%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__count {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
color: rgba(0, 0, 0, 65%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__questions {
|
||||||
|
max-height: 420px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__question {
|
||||||
|
padding: 12px 0;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-title {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-meta {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
color: rgba(0, 0, 0, 65%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&-score {
|
||||||
|
margin-left: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-info {
|
||||||
|
margin-top: 6px;
|
||||||
|
color: rgba(0, 0, 0, 65%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__options {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
row-gap: 6px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__option {
|
||||||
|
color: rgba(0, 0, 0, 85%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -213,18 +213,18 @@ const menuItems = [
|
||||||
label: "项目踏勘监管",
|
label: "项目踏勘监管",
|
||||||
icon: <EnvironmentOutlined />,
|
icon: <EnvironmentOutlined />,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
key: "/safetyEval/container/Supervision/EvalPortrait",
|
|
||||||
label: "安全评价画像",
|
|
||||||
icon: <PieChartOutlined />,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
key: "/safetyEval/container/Supervision/EvalReportDatabase",
|
key: "/safetyEval/container/Supervision/EvalReportDatabase",
|
||||||
label: "安评报告数据库",
|
label: "历史报告数据库",
|
||||||
icon: <FileProtectOutlined />,
|
icon: <FileProtectOutlined />,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "/safetyEval/container/Supervision/EvalPortrait",
|
||||||
|
label: "安评机构画像",
|
||||||
|
icon: <PieChartOutlined />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: "/safetyEval/container/MonitorManage/RiskCenter",
|
key: "/safetyEval/container/MonitorManage/RiskCenter",
|
||||||
label: "风险预警中心",
|
label: "风险预警中心",
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,7 @@ const EvalPortrait = (props) => {
|
||||||
return (
|
return (
|
||||||
<ConfigProvider theme={PROTO_THEME}>
|
<ConfigProvider theme={PROTO_THEME}>
|
||||||
<PageLayout
|
<PageLayout
|
||||||
title="安全评价画像"
|
title="安评机构画像"
|
||||||
extra={
|
extra={
|
||||||
<Button onClick={openRules}>指标说明</Button>
|
<Button onClick={openRules}>指标说明</Button>
|
||||||
}
|
}
|
||||||
|
|
@ -284,7 +284,7 @@ const EvalPortrait = (props) => {
|
||||||
|
|
||||||
{/* 查看画像 — 对齐原型 institutionProfile */}
|
{/* 查看画像 — 对齐原型 institutionProfile */}
|
||||||
<Modal
|
<Modal
|
||||||
title={detail ? `安全评价画像 - ${detail.orgName}` : "安全评价画像"}
|
title={detail ? `安评机构画像 - ${detail.orgName}` : "安评机构画像"}
|
||||||
open={detailOpen}
|
open={detailOpen}
|
||||||
onCancel={() => setDetailOpen(false)}
|
onCancel={() => setDetailOpen(false)}
|
||||||
width={980}
|
width={980}
|
||||||
|
|
|
||||||
|
|
@ -714,7 +714,7 @@ const EvalReportDatabase = (props) => {
|
||||||
await downloadBinaryPost(
|
await downloadBinaryPost(
|
||||||
"/safetyEval/regulator/eval-report/export-catalog",
|
"/safetyEval/regulator/eval-report/export-catalog",
|
||||||
body,
|
body,
|
||||||
`安评报告数据库目录_${dayjs().format("YYYYMMDDHHmmss")}.csv`,
|
`历史报告数据库目录_${dayjs().format("YYYYMMDDHHmmss")}.csv`,
|
||||||
);
|
);
|
||||||
message.success("目录导出已开始");
|
message.success("目录导出已开始");
|
||||||
setExportVisible(false);
|
setExportVisible(false);
|
||||||
|
|
@ -929,7 +929,7 @@ const EvalReportDatabase = (props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConfigProvider theme={PROTO_THEME}>
|
<ConfigProvider theme={PROTO_THEME}>
|
||||||
<PageLayout title="安评报告数据库">
|
<PageLayout title="历史报告数据库">
|
||||||
<div className="redb-page">
|
<div className="redb-page">
|
||||||
<div className="redb-summary-cards">
|
<div className="redb-summary-cards">
|
||||||
<div className="redb-summary-card">
|
<div className="redb-summary-card">
|
||||||
|
|
@ -1265,7 +1265,7 @@ const EvalReportDatabase = (props) => {
|
||||||
|
|
||||||
{/* 导出目录 — 对齐原型 export */}
|
{/* 导出目录 — 对齐原型 export */}
|
||||||
<Modal
|
<Modal
|
||||||
title="安评报告数据库目录"
|
title="历史报告数据库目录"
|
||||||
open={exportVisible}
|
open={exportVisible}
|
||||||
onCancel={() => setExportVisible(false)}
|
onCancel={() => setExportVisible(false)}
|
||||||
onOk={handleExportOk}
|
onOk={handleExportOk}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue