dev-tmp1
tangjie 2026-08-27 11:55:12 +08:00
parent e3c66c1f71
commit 69ecb5ffba
5 changed files with 148 additions and 12 deletions

View File

@ -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: {

View File

@ -64,6 +64,22 @@ export const coursewareQuestionDelete = declareRequest(
"Post > @/safetyEval/question/del/{questionId}",
);
/**
* 课件习题-导入试题multipartdeclareRequest 仅支持 json手动 fetch
* @param {FormData} payload coursewareManagementId/file
*/
export async function questionImport(payload) {
const res = await fetch(
`${window.process.env.app.API_HOST}/safetyEval/question/import`,
{
method: "POST",
headers: { token: sessionStorage.getItem("token") },
body: payload,
},
);
return res.json();
}
/** 批量删除习题(请求体:{ questionIds } */
export const coursewareQuestionBatchDelete = declareRequest(
"coursewareQuestionLoading",

View File

@ -213,6 +213,7 @@ export const EVALUATOR_OPTIONS = [
/** 职称等级 */
export const TITLE_LEVEL_OPTIONS = [
{ value: "NONE", label: "无" },
{ value: "SENIOR", label: "高级" },
{ value: "MIDDLE", label: "中级" },
{ value: "JUNIOR", label: "初级" },

View File

@ -1,5 +1,6 @@
import React, { useEffect, useState } from "react";
import {
Alert,
Button,
Checkbox,
Form,
@ -9,6 +10,7 @@ import {
Select,
Space,
Table,
Upload,
message,
} from "antd";
import {
@ -16,6 +18,7 @@ import {
DownloadOutlined,
ImportOutlined,
PlusOutlined,
UploadOutlined,
} from "@ant-design/icons";
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
import TableAction from "@cqsjjb/jjb-react-admin-component/TableAction";
@ -23,6 +26,7 @@ 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 { questionImport } from "~/api/courseware";
import {
QUESTION_TYPE_MAP,
QUESTION_TYPE_OPTIONS,
@ -45,6 +49,7 @@ const buildDefaultOptions = (questionType) =>
/** 课件习题管理(由课件列表「课件习题」进入) */
function CoursewareQuestionPage(props) {
const [addOpen, setAddOpen] = useState(false);
const [importOpen, setImportOpen] = useState(false);
const [editQuestion, setEditQuestion] = useState(null);
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
const coursewareName = router.query?.coursewareName;
@ -201,7 +206,7 @@ function CoursewareQuestionPage(props) {
<Button
type="primary"
icon={<ImportOutlined />}
onClick={() => message.info("习题导入功能暂未开放")}
onClick={() => setImportOpen(true)}
>
导入
</Button>
@ -263,6 +268,13 @@ function CoursewareQuestionPage(props) {
}}
/>
<ImportQuestionModal
open={importOpen}
coursewareManagementId={coursewareManagementId}
onCancel={() => setImportOpen(false)}
onSuccess={handleSearch}
/>
<QuestionFormModal
open={!!editQuestion}
mode="edit"
@ -294,6 +306,107 @@ function CoursewareQuestionPage(props) {
);
}
/** 导入习题弹窗按课件id导入 Excel成功后展示导入结果 */
function ImportQuestionModal({
open,
coursewareManagementId,
onCancel,
onSuccess,
}) {
const [form] = Form.useForm();
const [uploading, setUploading] = useState(false);
const [result, setResult] = useState(null);
useEffect(() => {
if (!open) {
form.resetFields();
setResult(null);
setUploading(false);
}
}, [open]);
const handleOk = async () => {
// 已导入成功时确定按钮即关闭
if (result) {
onCancel();
return;
}
try {
const values = await form.validateFields();
const formData = new FormData();
formData.append("coursewareManagementId", coursewareManagementId);
formData.append("file", values.file[0].originFileObj);
setUploading(true);
const res = await questionImport(formData);
if (res?.success !== false) {
setResult(res?.data || {});
onSuccess();
}
} catch {
// validation error
} finally {
setUploading(false);
}
};
const errorColumns = [
{ title: "行号", dataIndex: "rowIndex", width: 70 },
{ title: "sheet页", dataIndex: "sheetName", width: 120 },
{ title: "异常原因", dataIndex: "errorMessage", ellipsis: true },
];
return (
<Modal
open={open}
destroyOnHidden
title="导入习题"
width={560}
okText={result ? "关闭" : "开始导入"}
confirmLoading={uploading}
onOk={handleOk}
onCancel={onCancel}
>
{result ? (
<>
<Alert
type={result.errors?.length ? "warning" : "success"}
message={`成功导入 ${result.successCount ?? 0} 条试题${
result.errors?.length ? `,失败 ${result.errors.length}` : ""
}`}
showIcon
style={{ marginBottom: 12 }}
/>
{!!result.errors?.length && (
<Table
size="small"
rowKey={(e) => `${e.rowIndex}-${e.sheetName}`}
columns={errorColumns}
dataSource={result.errors}
pagination={false}
scroll={{ y: 240 }}
/>
)}
</>
) : (
<Form form={form} layout="vertical" scrollToFirstError>
<Form.Item
name="file"
label="试题Excel文件"
valuePropName="fileList"
getValueFromEvent={(e) => (Array.isArray(e) ? e : e?.fileList)}
rules={[{ required: true, message: "请上传试题Excel文件" }]}
extra="第一个sheet单选题第二个sheet多选题第三个sheet判断题"
>
<Upload accept=".xls,.xlsx" maxCount={1} beforeUpload={() => false}>
<Button icon={<UploadOutlined />}>选择文件</Button>
</Upload>
</Form.Item>
</Form>
)}
</Modal>
);
}
/** 新增/编辑习题弹窗(仅支持单选/多选/判断;编辑时先调查询接口回填) */
function QuestionFormModal({
open,

View File

@ -7,6 +7,7 @@ import {
CHONGQING_DISTRICTS,
QUALIFICATION_INDUSTRY_OPTIONS_MAP,
} from "~/enumerate/enterpriseOptions";
import { NATIONWIDE_DISTRICTS } from "~/enumerate/nationwideTerritory";
import {
FILING_FORM_MODE,
getFilingStatusOptions,
@ -245,19 +246,24 @@ export default function FilingListTable({
allowClear
/>
</Form.Item>,
<Form.Item key="filingTerritoryCode" name="filingTerritoryCode">
<Form.Item key="filingTerritoryName" name="filingTerritoryName">
<ControlWrapper.Select
label="备案属地"
placeholder="请输入"
placeholder={
mode === FILING_FORM_MODE.APPLICATION
? "请输入"
: "请选择(支持搜索全国区县)"
}
allowClear
showSearch
optionFilterProp="label"
style={{ width: "100%" }}
>
{CHONGQING_DISTRICTS.map((d) => (
<Select.Option key={d.value} value={d.value}>
{d.label}
</Select.Option>
))}
</ControlWrapper.Select>
options={
mode === FILING_FORM_MODE.APPLICATION
? CHONGQING_DISTRICTS
: NATIONWIDE_DISTRICTS
}
/>
</Form.Item>,
mode !== 'application' && <Form.Item key="filingNo" name="filingNo">
<ControlWrapper.Input