feat: align frontend document and rule management flows
This commit is contained in:
+127
-19
@@ -14,6 +14,7 @@ import {
|
||||
buildUploadErrorDetails,
|
||||
getTodayDocuments,
|
||||
getDocumentTypes,
|
||||
getDocumentSubtypeGroups,
|
||||
getDocumentsStatus,
|
||||
uploadFileToBinary,
|
||||
uploadDocumentToServer,
|
||||
@@ -22,6 +23,7 @@ import {
|
||||
checkDocumentDuplicate,
|
||||
type Document,
|
||||
type DocumentType,
|
||||
type DocumentSubtypeGroup,
|
||||
type UploadErrorDetails,
|
||||
type UploadResult,
|
||||
DocumentStatus
|
||||
@@ -29,7 +31,6 @@ import {
|
||||
import { updateDocumentAuditStatus } from "~/api/evaluation_points/rules-files";
|
||||
import { links as fileTypeTagLinks } from "~/components/ui/FileTypeTag";
|
||||
import { getQueueStatus, type QueueStatus } from "~/api/queue";
|
||||
import { CONTRACT_TYPES, DEFAULT_CONTRACT_TYPE } from "~/constants/contractTypes";
|
||||
|
||||
export function links() {
|
||||
return [
|
||||
@@ -132,9 +133,11 @@ async function handleFileUpload(
|
||||
fileName: string,
|
||||
fileType: string,
|
||||
documentType: FileType,
|
||||
groupId: number | null,
|
||||
priority: Priority,
|
||||
region: string,
|
||||
createdBy?: number,
|
||||
attachments?: File[],
|
||||
jwtToken?: string,
|
||||
): Promise<UploadResult> {
|
||||
const speed = priority === Priority.NORMAL ? "normal" : "urgent";
|
||||
@@ -144,8 +147,10 @@ async function handleFileUpload(
|
||||
fileName,
|
||||
fileType,
|
||||
Number(documentType),
|
||||
groupId,
|
||||
region,
|
||||
createdBy,
|
||||
attachments,
|
||||
true,
|
||||
speed,
|
||||
jwtToken,
|
||||
@@ -331,6 +336,7 @@ export default function FilesUpload() {
|
||||
// 获取 sessionStorage 中的 documentTypeIds 值
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [documentTypeIds, setDocumentTypeIds] = useState<number[] | null>(null);
|
||||
const [selectedModuleId, setSelectedModuleId] = useState<number | null>(null);
|
||||
|
||||
// 使用 useLoaderData 获取初始数据
|
||||
const loaderData = useLoaderData<LoaderData>();
|
||||
@@ -344,7 +350,9 @@ export default function FilesUpload() {
|
||||
const [documentNumber, setDocumentNumber] = useState<string>("");
|
||||
const [remark, setRemark] = useState<string>("");
|
||||
const [currentFiles, setCurrentFiles] = useState<File[]>([]);
|
||||
const [attributeType, setAttributeType] = useState<string>(DEFAULT_CONTRACT_TYPE);
|
||||
const [subtypeGroups, setSubtypeGroups] = useState<DocumentSubtypeGroup[]>([]);
|
||||
const [selectedGroupId, setSelectedGroupId] = useState<string>("");
|
||||
const [groupOptionsLoading, setGroupOptionsLoading] = useState(false);
|
||||
|
||||
// 合同文件上传状态
|
||||
// 这些变量暂时未使用,但保留以备将来扩展
|
||||
@@ -393,6 +401,16 @@ export default function FilesUpload() {
|
||||
loaderData.documentTypes.find(type => type.id.toString() === fileType) ||
|
||||
null;
|
||||
|
||||
const getSubtypeDisplayName = (group: DocumentSubtypeGroup | null | undefined) =>
|
||||
group?.displayName || group?.name || "";
|
||||
|
||||
const selectedSubtypeGroup = subtypeGroups.find(group => String(group.id) === selectedGroupId) || null;
|
||||
const hasMultipleSubtypeGroups = subtypeGroups.length > 1;
|
||||
const singleSubtypeGroup = subtypeGroups.length === 1 ? subtypeGroups[0] : null;
|
||||
const isSingleDefaultSubtype = !!(singleSubtypeGroup && singleSubtypeGroup.isDefault);
|
||||
const selectedRootGroupName = selectedSubtypeGroup?.rootGroupName || singleSubtypeGroup?.rootGroupName || "";
|
||||
const selectedEntryModuleName = selectedSubtypeGroup?.entryModuleName || singleSubtypeGroup?.entryModuleName || "";
|
||||
|
||||
const clearUploadErrorDetails = () => {
|
||||
setUploadErrorDetails(null);
|
||||
};
|
||||
@@ -444,6 +462,8 @@ export default function FilesUpload() {
|
||||
? nextSelectedModuleId
|
||||
: null;
|
||||
|
||||
setSelectedModuleId(normalizedModuleId);
|
||||
|
||||
if (cancelled) {
|
||||
return;
|
||||
}
|
||||
@@ -842,6 +862,51 @@ export default function FilesUpload() {
|
||||
setFileTypeError("上传文件之前请选择文件类型");
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
|
||||
const loadSubtypeGroups = async () => {
|
||||
if (!fileType) {
|
||||
setSubtypeGroups([]);
|
||||
setSelectedGroupId("");
|
||||
return;
|
||||
}
|
||||
|
||||
setGroupOptionsLoading(true);
|
||||
try {
|
||||
const response = await getDocumentSubtypeGroups(
|
||||
Number(fileType),
|
||||
loaderData.frontendJWT || undefined,
|
||||
selectedModuleId,
|
||||
);
|
||||
if (cancelled) return;
|
||||
if ("error" in response || !response.data) {
|
||||
setSubtypeGroups([]);
|
||||
setSelectedGroupId("");
|
||||
return;
|
||||
}
|
||||
|
||||
const groups = response.data;
|
||||
setSubtypeGroups(groups);
|
||||
setSelectedGroupId((currentValue) => {
|
||||
if (groups.some((item) => String(item.id) === currentValue)) {
|
||||
return currentValue;
|
||||
}
|
||||
return groups.length === 1 ? String(groups[0].id) : "";
|
||||
});
|
||||
} finally {
|
||||
if (!cancelled) {
|
||||
setGroupOptionsLoading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void loadSubtypeGroups();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [fileType, loaderData.frontendJWT, selectedModuleId]);
|
||||
|
||||
// 处理合同主文件选择
|
||||
const handleContractMainFilesSelected = (files: FileList) => {
|
||||
@@ -1260,8 +1325,8 @@ export default function FilesUpload() {
|
||||
const createdBy = loaderData.userInfo?.user_id as number | undefined;
|
||||
const uploadResp = await handleFileUpload(
|
||||
binaryData, mainFile.name, mainFile.type,
|
||||
fileType as FileType, priority,
|
||||
region, createdBy, loaderData.frontendJWT || undefined,
|
||||
fileType as FileType, selectedGroupId ? Number(selectedGroupId) : null, priority,
|
||||
region, createdBy, attachmentFiles, loaderData.frontendJWT || undefined,
|
||||
);
|
||||
|
||||
if (!uploadResp.success) {
|
||||
@@ -1350,6 +1415,10 @@ export default function FilesUpload() {
|
||||
toastService.error('请先选择文件类型');
|
||||
return;
|
||||
}
|
||||
if (subtypeGroups.length > 1 && !selectedGroupId) {
|
||||
toastService.error('请先选择子类型后再上传');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否为合同类型
|
||||
const selectedType = loaderData.documentTypes.find(t => t.id.toString() === fileType);
|
||||
@@ -1596,8 +1665,8 @@ export default function FilesUpload() {
|
||||
const createdBy = loaderData.userInfo?.user_id as number | undefined;
|
||||
const uploadPromise = handleFileUpload(
|
||||
binaryData, file.name, file.type,
|
||||
fileType as FileType, priority,
|
||||
region, createdBy, loaderData.frontendJWT || undefined,
|
||||
fileType as FileType, selectedGroupId ? Number(selectedGroupId) : null, priority,
|
||||
region, createdBy, undefined, loaderData.frontendJWT || undefined,
|
||||
);
|
||||
|
||||
const timeoutPromise = new Promise<UploadResult>((_, reject) => {
|
||||
@@ -2362,27 +2431,66 @@ export default function FilesUpload() {
|
||||
</select>
|
||||
<div className="form-tip">优先级影响文档在队列中的处理顺序</div>
|
||||
</div>
|
||||
{/* 子类型(专属类型)- 始终显示 */}
|
||||
{/* 子类型(二级分组) */}
|
||||
<div className="form-group">
|
||||
<label htmlFor="attribute-type-select" className="form-label">
|
||||
子类型 <span className="required">*</span>
|
||||
</label>
|
||||
<select
|
||||
id="attribute-type-select"
|
||||
name="attributeType"
|
||||
name="groupId"
|
||||
className="form-select"
|
||||
value={attributeType}
|
||||
onChange={(e) => setAttributeType(e.target.value)}
|
||||
disabled={uploadStage !== "idle"}
|
||||
required
|
||||
value={selectedGroupId}
|
||||
onChange={(e) => setSelectedGroupId(e.target.value)}
|
||||
disabled={uploadStage !== "idle" || !fileType || groupOptionsLoading || subtypeGroups.length <= 1}
|
||||
required={subtypeGroups.length > 1}
|
||||
>
|
||||
{CONTRACT_TYPES.map(type => (
|
||||
<option key={type.value} value={type.value}>
|
||||
{type.label}
|
||||
{!fileType ? (
|
||||
<option value="">请先选择文件类型</option>
|
||||
) : groupOptionsLoading ? (
|
||||
<option value="">子类型加载中...</option>
|
||||
) : subtypeGroups.length === 0 ? (
|
||||
<option value="">当前文档类型暂无二级分组</option>
|
||||
) : subtypeGroups.length === 1 ? (
|
||||
<option value={String(subtypeGroups[0].id)}>
|
||||
{getSubtypeDisplayName(subtypeGroups[0])}
|
||||
</option>
|
||||
))}
|
||||
) : (
|
||||
<>
|
||||
<option value="">请选择子类型</option>
|
||||
{subtypeGroups.map((group) => (
|
||||
<option key={group.id} value={String(group.id)}>
|
||||
{getSubtypeDisplayName(group)}
|
||||
</option>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</select>
|
||||
<div className="form-tip">选择文档专属类型以应用对应的审核规则(合同大类请选择技术/租赁/买卖等)</div>
|
||||
<div className="form-tip">
|
||||
{!fileType
|
||||
? "请先选择文件类型,再确定本次上传实际命中的子类型。"
|
||||
: groupOptionsLoading
|
||||
? "正在加载当前文档类型下可用的子类型配置。"
|
||||
: subtypeGroups.length === 0
|
||||
? "当前文档类型在当前入口下还没有可用子类型,请先到评查点分组管理补齐“一级分组 / 二级分组 / 规则集”绑定。"
|
||||
: hasMultipleSubtypeGroups
|
||||
? "同一文档类型在当前入口下已拆分多个子类型,请选择本次上传实际命中的子类型。"
|
||||
: isSingleDefaultSubtype
|
||||
? "当前文档类型在当前入口下尚未拆分业务子类型,系统将按默认子类型处理;后续可在评查点分组管理中继续细分。"
|
||||
: "当前文档类型在当前入口下仅配置了一个子类型,系统会自动带出该子类型。"}
|
||||
</div>
|
||||
{selectedRootGroupName ? (
|
||||
<div className="form-tip">
|
||||
所属一级分组:{selectedRootGroupName}
|
||||
{selectedEntryModuleName ? ` · 入口模块:${selectedEntryModuleName}` : ""}
|
||||
</div>
|
||||
) : null}
|
||||
{selectedSubtypeGroup ? (
|
||||
<div className="form-tip">
|
||||
当前命中:{getSubtypeDisplayName(selectedSubtypeGroup)}
|
||||
{selectedSubtypeGroup.displayHint ? ` · ${selectedSubtypeGroup.displayHint}` : ""}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label htmlFor="docNumber" className="form-label">文档编号</label>
|
||||
@@ -2783,7 +2891,7 @@ export default function FilesUpload() {
|
||||
<i className="ri-checkbox-circle-line text-xl mr-2"></i>
|
||||
<span className="font-medium">评查成功</span>
|
||||
</div>
|
||||
<p className="text-sm text-green-700">文件已成功上传并评查完成,请查看结果</p>
|
||||
<p className="text-sm text-green-700">文件已成功上传并评查完成,请查看详情。</p>
|
||||
</div>
|
||||
|
||||
{/* <div className="flex justify-end">
|
||||
@@ -2792,7 +2900,7 @@ export default function FilesUpload() {
|
||||
icon="ri-file-search-line"
|
||||
|
||||
>
|
||||
查看详情并审核
|
||||
查看详情
|
||||
</Button>
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user