Merge remote-tracking branch 'origin/dev-tmp1' into dev-tmp1

dev-tmp1
luotaiqian 2026-08-27 14:07:49 +08:00
commit 2ca70e4f46
16 changed files with 13309 additions and 148 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

@ -15,6 +15,7 @@
"build:development": "cross-env NODE_ENV=development npm run build",
"build:production": "cross-env NODE_ENV=production npm run build",
"code-optimization": "node node_modules/@cqsjjb/scripts/code-optimization.js",
"gen:districts": "node scripts/gen-china-districts.js",
"lint": "eslint --ext .js,.jsx,.tsx --fix src",
"test:enterprise-info": "node docs/test-reports/测试用例/test-enterprise-info-api.mjs",
"test:enterprise-info:granular": "node docs/test-reports/测试用例/test-enterprise-info-granular.mjs"
@ -32,8 +33,6 @@
"docxtemplater": "latest",
"echarts": "^6.1.0",
"history": "^4.10.1",
"lodash-es": "^4.17.21",
"pizzip": "latest",
"react": "^18.2.0",
@ -48,6 +47,7 @@
"@babel/preset-react": "^7.29.7",
"@cqsjjb/scripts": "latest",
"@eslint-react/eslint-plugin": "^2.2.2",
"@province-city-china/data": "^8.5.8",
"babel-loader": "^9.1.3",
"cross-env": "^7.0.3",
"css-loader": "^6.8.1",

12915
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
/**
* 生成全国县级行政区划快照node scripts/gen-china-districts.js
* 数据源devDependency @province-city-china/dataGB/T 2260省市区四级全量
* 输出src/enumerate/chinaDistricts.json仅保留县级约 3300 [code, 名称, +]160KB 左右
* 行政区划调整后重新执行本脚本即可刷新快照
*/
const fs = require("fs");
const path = require("path");
const all = require("@province-city-china/data");
/** 省级名称表code 形如 XX0000 */
const provinceNameByCode = {};
/** 地级名称表code 形如 XXYY00 */
const cityNameByCode = {};
all.forEach((item) => {
const isProvince = item.city === 0 && item.area === 0 && item.town === 0;
const isCity = item.city !== 0 && item.area === 0 && item.town === 0;
if (isProvince) provinceNameByCode[item.province] = item.name;
if (isCity) cityNameByCode[item.province + item.city] = item.name;
});
const districts = all
.filter((item) => item.city !== 0 && item.area !== 0 && item.town === 0)
.map((item) => {
const province = provinceNameByCode[item.province] || "";
const city = cityNameByCode[item.province + item.city] || "";
// 直辖市等省市同名时不重复拼接
const region = city && city !== province ? `${province}${city}` : province;
return [item.code, item.name, region];
});
const outFile = path.join(__dirname, "../src/enumerate/chinaDistricts.json");
fs.writeFileSync(outFile, `${JSON.stringify(districts)}\n`, "utf8");
console.log(`已生成 ${path.relative(process.cwd(), outFile)}${districts.length}`);

View File

@ -1,6 +1,6 @@
import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
/** 教育培训 — 培训课件管理 / 培训课程管理 / 班级管理 */
/** 教育培训 — 培训课件管理 / 培训课程管理 / 班级管理 / 试卷管理(试卷接口统一声明在 courseware 命名空间) */
/** 分页查询课件 */
export const coursewarePage = declareRequest(
@ -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",
@ -222,3 +238,102 @@ export const studentExamPaperInfo = declareRequest(
"studentExamPaperLoading",
"Get > /safetyEval/paperExam/exam/info",
);
/* ------------------------------ 试卷管理 ------------------------------ */
/** 分页查询试卷 */
export const paperPage = declareRequest(
"paperLoading",
"Get > /safetyEval/paper/page",
"paperList: [] | res.data || [] & paperTotal: 0 | res.total || 0",
);
/** 试卷基本信息查询(不含试题列表) */
export const paperBasicInfo = declareRequest(
"paperBasicLoading",
"Get > /safetyEval/paper/paper/basic/info",
);
/** 试卷考试信息查询(基本信息 + 试题列表) */
export const paperExamInfo = declareRequest(
"paperExamLoading",
"Get > /safetyEval/paper/paper/exam/info",
);
/** 自动生成试卷(按课件与题型规则抽题组卷) */
export const paperRuleGenerate = declareRequest(
"paperRuleLoading",
"Post > @/safetyEval/paper/courseware/question/rule",
);
/** 修改试卷基本信息 */
export const paperUpdateBasic = declareRequest(
"paperUpdateLoading",
"Put > @/safetyEval/paper/update/basic",
);
/** 删除试卷 */
export const paperDelete = declareRequest(
"paperLoading",
"Delete > @/safetyEval/paper/{id}",
);
/** 复制试卷 */
export const paperCopy = declareRequest(
"paperCopyLoading",
"Post > @/safetyEval/paper/copy",
);
/** 导入试题模板地址 */
export const paperImportTemplate = declareRequest(
"paperTemplateLoading",
"Get > /safetyEval/paper/import/template",
'paperTemplateUrl: "" | res.data || ""',
);
/**
* 新建试卷-导入试题multipartdeclareRequest 仅支持 json手动 fetch
* @param {FormData} payload paperName/paperTotalScore/paperPassScore/examTime/file
*/
export async function paperImport(payload) {
const res = await fetch(
`${window.process.env.app.API_HOST}/safetyEval/paper/import`,
{
method: "POST",
headers: { token: sessionStorage.getItem("token") },
body: payload,
},
);
return res.json();
}
/** 试卷试题分页查询 */
export const paperQuestionPage = declareRequest(
"paperQuestionLoading",
"Get > /safetyEval/paper/paper/question/page",
"paperQuestionList: [] | res.data || [] & paperQuestionTotal: 0 | res.total || 0",
);
/** 删除试卷习题 */
export const paperQuestionDelete = declareRequest(
"paperQuestionLoading",
"Post > @/safetyEval/paperQuestionRel/delete",
);
/** 新增试卷试题(习题) */
export const paperQuestionSave = declareRequest(
"paperQuestionSaveLoading",
"Post > @/safetyEval/paperQuestionRel/save",
);
/** 查询试卷习题详情(分值取自试卷试题关系) */
export const paperQuestionFind = declareRequest(
"questionFindLoading",
"Get > /safetyEval/paperQuestionRel/find",
);
/** 编辑试卷习题 */
export const paperQuestionModify = declareRequest(
"questionModifyLoading",
"Post > @/safetyEval/paperQuestionRel/modify",
);

View File

@ -1,100 +0,0 @@
import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
/** 教育培训 — 试卷管理 */
/** 分页查询试卷 */
export const paperPage = declareRequest(
"paperLoading",
"Get > /safetyEval/paper/page",
"paperList: [] | res.data || [] & paperTotal: 0 | res.total || 0",
);
/** 试卷基本信息查询(不含试题列表) */
export const paperBasicInfo = declareRequest(
"paperBasicLoading",
"Get > /safetyEval/paper/paper/basic/info",
);
/** 试卷考试信息查询(基本信息 + 试题列表) */
export const paperExamInfo = declareRequest(
"paperExamLoading",
"Get > /safetyEval/paper/paper/exam/info",
);
/** 自动生成试卷(按课件与题型规则抽题组卷) */
export const paperRuleGenerate = declareRequest(
"paperRuleLoading",
"Post > @/safetyEval/paper/courseware/question/rule",
);
/** 修改试卷基本信息 */
export const paperUpdateBasic = declareRequest(
"paperUpdateLoading",
"Put > @/safetyEval/paper/update/basic",
);
/** 删除试卷 */
export const paperDelete = declareRequest(
"paperLoading",
"Delete > @/safetyEval/paper/{id}",
);
/** 复制试卷 */
export const paperCopy = declareRequest(
"paperCopyLoading",
"Post > @/safetyEval/paper/copy",
);
/** 导入试题模板地址 */
export const paperImportTemplate = declareRequest(
"paperTemplateLoading",
"Get > /safetyEval/paper/import/template",
'paperTemplateUrl: "" | res.data || ""',
);
/**
* 新建试卷-导入试题multipartdeclareRequest 仅支持 json手动 fetch
* @param {FormData} payload paperName/paperTotalScore/paperPassScore/examTime/file
*/
export async function paperImport(payload) {
const res = await fetch(
`${window.process.env.app.API_HOST}/safetyEval/paper/import`,
{
method: "POST",
headers: { token: sessionStorage.getItem("token") },
body: payload,
},
);
return res.json();
}
/** 试卷试题分页查询 */
export const paperQuestionPage = declareRequest(
"paperQuestionLoading",
"Get > /safetyEval/paper/paper/question/page",
"paperQuestionList: [] | res.data || [] & paperQuestionTotal: 0 | res.total || 0",
);
/** 删除试卷习题 */
export const paperQuestionDelete = declareRequest(
"paperQuestionLoading",
"Post > @/safetyEval/paperQuestionRel/delete",
);
/** 新增试卷试题(习题) */
export const paperQuestionSave = declareRequest(
"paperQuestionSaveLoading",
"Post > @/safetyEval/paperQuestionRel/save",
);
/** 查询试卷习题详情(分值取自试卷试题关系) */
export const paperQuestionFind = declareRequest(
"questionFindLoading",
"Get > /safetyEval/paperQuestionRel/find",
);
/** 编辑试卷习题 */
export const paperQuestionModify = declareRequest(
"questionModifyLoading",
"Post > @/safetyEval/paperQuestionRel/modify",
);

File diff suppressed because one or more lines are too long

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

@ -8,7 +8,6 @@ export const NS_PERSNONEL_CERTFICATE = defineNamespace("personnelCertificate");
export const NS_CORP_CERTIFICATE = defineNamespace("corpCertificate");
export const NS_USER_CERTIFICATE = defineNamespace("userCertificate");
export const NS_COURSEWARE = defineNamespace("courseware");
export const NS_PAPER = defineNamespace("paper");
export const NS_ORG_INFO = defineNamespace("orgInfo");
export const NS_ORG_QUALIFICATION_CERT = defineNamespace("orgQualificationCert");
export const NS_ORG_DEPARTMENT = defineNamespace("orgDepartment");

View File

@ -0,0 +1,15 @@
/**
* 全国备案属地下拉选项
* 数据来源./chinaDistricts.json `pnpm gen:districts` @province-city-china/data 生成的县级快照
* value 采用省市区县全路径重庆市万州区避免同名区县如北京/长春的朝阳区冲突
* filingTerritoryName 直接存名称字符串的口径保持一致
*/
import CHINA_DISTRICTS from "./chinaDistricts.json";
/** [code, 区县名, 省+市] → { label, value } */
export const NATIONWIDE_DISTRICTS = CHINA_DISTRICTS.map(
([, name, region]) => ({
label: region ? `${name}${region}` : name,
value: region ? `${region}${name}` : name,
}),
);

View File

@ -17,7 +17,7 @@ import {
import { DownloadOutlined, PlusOutlined } from "@ant-design/icons";
import TableAction from "@cqsjjb/jjb-react-admin-component/TableAction";
import { Connect } from "@cqsjjb/jjb-dva-runtime";
import { NS_COURSEWARE, NS_PAPER } from "~/enumerate/namespace";
import { NS_COURSEWARE } from "~/enumerate/namespace";
import {
CLASS_PAPER_TYPE_MAP,
CLASS_PAPER_TYPE_OPTIONS,
@ -156,7 +156,7 @@ function PaperConfigModal({
// 打开且有绑定试卷时才查询基本信息paperId 变化(换绑)后重新查询
useEffect(() => {
if (!open) {
resetModelState?.(NS_PAPER, { paperBasicLoading: false });
resetModelState?.(NS_COURSEWARE, { paperBasicLoading: false });
return;
}
setBasicInfo(null);
@ -285,7 +285,7 @@ function PaperAddModal({
// 切换类型/打开时加载数据:平台试卷查分页,自动生成查课件下拉
useEffect(() => {
if (!open) {
resetModelState?.(NS_PAPER, {
resetModelState?.(NS_COURSEWARE, {
paperLoading: false,
paperRuleLoading: false,
});
@ -660,7 +660,7 @@ function PaperExamPreviewModal({
useEffect(() => {
if (!open) {
resetModelState?.(NS_PAPER, { paperExamLoading: false });
resetModelState?.(NS_COURSEWARE, { paperExamLoading: false });
return;
}
if (!paperId) return;
@ -772,4 +772,4 @@ function PaperExamPreviewModal({
);
}
export default Connect([NS_COURSEWARE, NS_PAPER], true)(ClassPaperConfig);
export default Connect([NS_COURSEWARE], true)(ClassPaperConfig);

View File

@ -1,5 +1,6 @@
import React, { useEffect, useState } from "react";
import {
Alert,
Button,
Checkbox,
Form,
@ -9,15 +10,23 @@ import {
Select,
Space,
Table,
Upload,
message,
} from "antd";
import { DeleteOutlined, ImportOutlined, PlusOutlined } from "@ant-design/icons";
import {
DeleteOutlined,
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";
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,
@ -40,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;
@ -102,6 +112,31 @@ function CoursewareQuestionPage(props) {
});
};
/** 下载试题导入模板(复用试卷导入模板接口):跨域地址下 a.download 无效fetch 转 blob 后触发下载 */
const onDownloadTemplate = async () => {
const res = await props.paperImportTemplate();
const url = res?.paperTemplateUrl || res?.data;
if (!url) {
message.warning("模板地址未配置");
return;
}
try {
const fileRes = await fetch(url);
if (!fileRes.ok) throw new Error(`HTTP ${fileRes.status}`);
const blobUrl = window.URL.createObjectURL(await fileRes.blob());
const link = document.createElement("a");
link.href = blobUrl;
link.download = "试题导入模板.xlsx";
link.style.display = "none";
document.body.appendChild(link);
link.click();
link.remove();
window.URL.revokeObjectURL(blobUrl);
} catch {
message.error("模板下载失败");
}
};
const columns = [
{
title: "序号",
@ -161,10 +196,17 @@ function CoursewareQuestionPage(props) {
>
新增
</Button>
<Button
icon={<DownloadOutlined />}
loading={props.courseware?.paperTemplateLoading}
onClick={onDownloadTemplate}
>
下载导入模板
</Button>
<Button
type="primary"
icon={<ImportOutlined />}
onClick={() => message.info("习题导入功能暂未开放")}
onClick={() => setImportOpen(true)}
>
导入
</Button>
@ -226,6 +268,13 @@ function CoursewareQuestionPage(props) {
}}
/>
<ImportQuestionModal
open={importOpen}
coursewareManagementId={coursewareManagementId}
onCancel={() => setImportOpen(false)}
onSuccess={handleSearch}
/>
<QuestionFormModal
open={!!editQuestion}
mode="edit"
@ -257,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

@ -19,7 +19,7 @@ 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_PAPER, NS_COURSEWARE } from "~/enumerate/namespace";
import { NS_COURSEWARE } from "~/enumerate/namespace";
import { QUESTION_TYPE_MAP, QUESTION_TYPE_OPTIONS } from "~/enumerate/constant";
const { router } = tools;
@ -48,12 +48,12 @@ function PaperQuestionPage(props) {
const [editQuestion, setEditQuestion] = useState(null);
const paperId = router.query?.paperId;
const paperName = router.query?.paperName;
const { paper, courseware } = props;
const { courseware } = props;
const {
paperQuestionList: dataSource,
paperQuestionTotal: total,
paperQuestionLoading: loading,
} = paper || {};
} = courseware || {};
const coursewareOptions = (courseware?.coursewareList || []).map((c) => ({
label: c.coursewareName,
value: c.id,
@ -226,10 +226,10 @@ function PaperQuestionPage(props) {
open={addOpen}
mode="add"
coursewareOptions={coursewareOptions}
confirmLoading={paper?.paperQuestionSaveLoading}
confirmLoading={courseware?.paperQuestionSaveLoading}
onCancel={() => {
setAddOpen(false);
props.resetModelState(NS_PAPER, { paperQuestionSaveLoading: false });
props.resetModelState(NS_COURSEWARE, { paperQuestionSaveLoading: false });
}}
onSubmit={async (values) => {
const res = await props.paperQuestionSave({ paperId, ...values });
@ -247,12 +247,12 @@ function PaperQuestionPage(props) {
paperId={paperId}
questionId={editQuestion?.id}
coursewareOptions={coursewareOptions}
findLoading={paper?.questionFindLoading}
confirmLoading={paper?.questionModifyLoading}
findLoading={courseware?.questionFindLoading}
confirmLoading={courseware?.questionModifyLoading}
questionFind={props.paperQuestionFind}
onCancel={() => {
setEditQuestion(null);
props.resetModelState(NS_PAPER, {
props.resetModelState(NS_COURSEWARE, {
questionFindLoading: false,
questionModifyLoading: false,
});
@ -533,6 +533,6 @@ function QuestionFormModal({
);
}
export default Connect([NS_PAPER, NS_COURSEWARE], true)(
export default Connect([NS_COURSEWARE], true)(
AntdTableFuncControl(PaperQuestionPage),
);

View File

@ -24,9 +24,9 @@ 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_PAPER } from "~/enumerate/namespace";
import { NS_COURSEWARE } from "~/enumerate/namespace";
import { PAPER_TYPE_MAP, PAPER_TYPE_OPTIONS } from "~/enumerate/constant";
import { paperImport } from "~/api/paper";
import { paperImport } from "~/api/courseware";
const { router } = tools;
const { RangePicker } = DatePicker;
@ -53,9 +53,12 @@ function PaperManagePage(props) {
const [editRecord, setEditRecord] = useState(null);
const [copyRecord, setCopyRecord] = useState(null);
const [importOpen, setImportOpen] = useState(false);
const { paper } = props;
const { paperList: dataSource, paperTotal: total, paperLoading: loading } =
paper || {};
const { courseware } = props;
const {
paperList: dataSource,
paperTotal: total,
paperLoading: loading,
} = courseware || {};
const handleSearch = () => {
props.paperPage(router.query);
@ -74,14 +77,28 @@ function PaperManagePage(props) {
handleSearch();
}, []);
/** 下载导入模板 */
/** 下载导入模板:跨域地址下 a.download 无效fetch 转 blob 后触发下载 */
const onDownloadTemplate = async () => {
const res = await props.paperImportTemplate();
const url = res?.paperTemplateUrl || res?.data;
if (url) {
window.open(url);
} else {
if (!url) {
message.warning("模板地址未配置");
return;
}
try {
const fileRes = await fetch(url);
if (!fileRes.ok) throw new Error(`HTTP ${fileRes.status}`);
const blobUrl = window.URL.createObjectURL(await fileRes.blob());
const link = document.createElement("a");
link.href = blobUrl;
link.download = "试题导入模板.xlsx";
link.style.display = "none";
document.body.appendChild(link);
link.click();
link.remove();
window.URL.revokeObjectURL(blobUrl);
} catch {
message.error("模板下载失败");
}
};
@ -186,7 +203,7 @@ function PaperManagePage(props) {
<>
<Button
icon={<DownloadOutlined />}
loading={paper?.paperTemplateLoading}
loading={courseware?.paperTemplateLoading}
onClick={onDownloadTemplate}
>
下载导入模板
@ -261,10 +278,10 @@ function PaperManagePage(props) {
open={!!editRecord}
title="编辑试卷"
initial={editRecord}
confirmLoading={paper?.paperUpdateLoading}
confirmLoading={courseware?.paperUpdateLoading}
onCancel={() => {
setEditRecord(null);
props.resetModelState(NS_PAPER, { paperUpdateLoading: false });
props.resetModelState(NS_COURSEWARE, { paperUpdateLoading: false });
}}
onSubmit={async (values) => {
const res = await props.paperUpdateBasic({
@ -285,10 +302,10 @@ function PaperManagePage(props) {
initial={
copyRecord && { ...copyRecord, paperName: `${copyRecord.paperName}-副本` }
}
confirmLoading={paper?.paperCopyLoading}
confirmLoading={courseware?.paperCopyLoading}
onCancel={() => {
setCopyRecord(null);
props.resetModelState(NS_PAPER, { paperCopyLoading: false });
props.resetModelState(NS_COURSEWARE, { paperCopyLoading: false });
}}
onSubmit={async (values) => {
const res = await props.paperCopy({ id: copyRecord?.id, ...values });
@ -525,6 +542,6 @@ function ImportPaperModal({ open, onCancel, onSuccess }) {
);
}
export default Connect([NS_PAPER], true)(
export default Connect([NS_COURSEWARE], true)(
AntdTableFuncControl(PaperManagePage),
);

View File

@ -1,11 +1,15 @@
import { Form, Input, InputNumber, Row, Col, Select, Checkbox } from "antd";
import { CHONGQING_DISTRICTS } from "~/enumerate/enterpriseOptions";
import { NATIONWIDE_DISTRICTS } from "~/enumerate/nationwideTerritory";
import useIndustryOptions from "~/hooks/useIndustryOptions";
import { FILING_UNIT_TYPE_OPTIONS } from "~/enumerate/qualFilingOptions";
import AttachmentUpload from "~/components/AttachmentUpload";
export default function BasicInfoStep({ form, disabled, mode }) {
const industryOptions = useIndustryOptions();
// /
const territoryOptions =
mode === "application" ? CHONGQING_DISTRICTS : NATIONWIDE_DISTRICTS;
return (
<Form form={form} layout="vertical" disabled={disabled}>
<Row gutter={16}>
@ -27,9 +31,12 @@ export default function BasicInfoStep({ form, disabled, mode }) {
rules={[{ required: !disabled, message: "请选择备案属地" }]}
>
<Select
options={CHONGQING_DISTRICTS}
placeholder="请选择"
options={territoryOptions}
placeholder={
mode === "application" ? "请选择" : "请选择(支持搜索全国区县)"
}
showSearch
allowClear
optionFilterProp="label"
/>
</Form.Item>

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