240 lines
6.6 KiB
JavaScript
240 lines
6.6 KiB
JavaScript
import React, { useEffect, useMemo } from "react";
|
||
import { Button, Form, Input, message, Modal, Select } from "antd";
|
||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||
import { NS_QUAL_EXPERT, NS_QUAL_REVIEW } from "~/enumerate/namespace";
|
||
import { REVIEW_RESULT_OPTIONS } from "../reviewPageQuery";
|
||
|
||
const { TextArea } = Input;
|
||
|
||
/**
|
||
* 审核操作弹窗(原型 modal-review-action)
|
||
* - 评价分析:已核验材料 / 符合 / 不符合 / 条件未满足 四卡
|
||
* - 表单:审核结果(通过/待定/不通过)、指派专家、综合审核意见
|
||
* - 底部:取消 / 📤 提交 / ✅ 通过
|
||
* @param {boolean} open
|
||
* @param {string|number} filingId - 备案申请ID
|
||
* @param {function} onCancel
|
||
* @param {function} onSuccess - 审核成功后回调(刷新列表等)
|
||
*/
|
||
const statStyle = {
|
||
background: "#fff",
|
||
border: "1px solid #e2e8f0",
|
||
borderRadius: 8,
|
||
padding: "0.4rem",
|
||
textAlign: "center",
|
||
};
|
||
const statLabelStyle = { fontSize: "0.7rem", color: "#64748b" };
|
||
|
||
const ReviewModal = (props) => {
|
||
const {
|
||
open,
|
||
filingId,
|
||
isChange = false,
|
||
legalPassCount = 0,
|
||
legalFailCount = 0,
|
||
legalWarnCount = 0,
|
||
onCancel,
|
||
onSuccess,
|
||
} = props;
|
||
const {
|
||
qualExpert,
|
||
qualReview,
|
||
queryExpertPage,
|
||
reviewSubmit,
|
||
changeReviewSubmit,
|
||
} = props;
|
||
const { qualExpertList } = qualExpert || {};
|
||
const { qualReviewSubmitLoading } = qualReview || {};
|
||
|
||
const [form] = Form.useForm();
|
||
|
||
useEffect(() => {
|
||
if (open) {
|
||
form.resetFields();
|
||
queryExpertPage({ current: 1, size: 100 });
|
||
}
|
||
}, [open]);
|
||
|
||
const expertOptions = useMemo(
|
||
() =>
|
||
(qualExpertList || []).map((item) => ({
|
||
label: item.userName,
|
||
value: item.id,
|
||
expert: item,
|
||
})),
|
||
[qualExpertList],
|
||
);
|
||
|
||
const doSubmit = async (values, passQuick) => {
|
||
const selected = expertOptions.find(
|
||
(o) => o.value === values.filingExpertId,
|
||
);
|
||
const result = passQuick ? 1 : values.reviewResult;
|
||
const resultLabel =
|
||
REVIEW_RESULT_OPTIONS.find((r) => r.value === result)?.label || "通过";
|
||
const submitAction = isChange ? changeReviewSubmit : reviewSubmit;
|
||
const params = {
|
||
filingId,
|
||
reviewResult: result,
|
||
reviewResultRemark: passQuick ? "审核通过" : resultLabel,
|
||
filingExpertId: values.filingExpertId,
|
||
filingExpertName: selected?.expert?.userName,
|
||
reviewOpinion: values.reviewOpinion || (passQuick ? "审核通过" : ""),
|
||
};
|
||
if (isChange) {
|
||
params.id = params.filingId;
|
||
delete params.filingId;
|
||
}
|
||
const res = await submitAction(params);
|
||
if (res?.success !== false) {
|
||
message.success(passQuick ? "审核通过!" : "审核提交成功");
|
||
onCancel();
|
||
onSuccess?.();
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
|
||
const handleSubmit = async () => {
|
||
const values = await form.validateFields();
|
||
await doSubmit(values, false);
|
||
};
|
||
|
||
const handlePass = async () => {
|
||
const values = form.getFieldsValue();
|
||
await doSubmit(values, true);
|
||
};
|
||
|
||
const totalChecked = legalPassCount + legalFailCount + legalWarnCount;
|
||
|
||
return (
|
||
<Modal
|
||
title="📋 审核操作"
|
||
open={open}
|
||
onCancel={onCancel}
|
||
width={620}
|
||
footer={
|
||
<div style={{ display: "flex", justifyContent: "flex-end", gap: 8 }}>
|
||
<Button onClick={onCancel}>取消</Button>
|
||
<Button loading={qualReviewSubmitLoading} onClick={handlePass}>
|
||
通过
|
||
</Button>
|
||
<Button
|
||
loading={qualReviewSubmitLoading}
|
||
onClick={handleSubmit}
|
||
type="primary"
|
||
>
|
||
提交
|
||
</Button>
|
||
</div>
|
||
}
|
||
>
|
||
<div
|
||
style={{
|
||
background: "#f8fafc",
|
||
border: "1px solid #e2e8f0",
|
||
borderRadius: 8,
|
||
padding: "0.75rem",
|
||
marginBottom: "1rem",
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
fontSize: "0.88rem",
|
||
fontWeight: 600,
|
||
marginBottom: "0.5rem",
|
||
}}
|
||
>
|
||
📊 评价分析
|
||
</div>
|
||
<div
|
||
style={{
|
||
display: "grid",
|
||
gridTemplateColumns: "1fr 1fr 1fr 1fr",
|
||
gap: "0.4rem",
|
||
}}
|
||
>
|
||
<div style={statStyle}>
|
||
<div style={statLabelStyle}>已核验材料</div>
|
||
<div
|
||
style={{ fontSize: "1.1rem", fontWeight: 700, color: "#059669" }}
|
||
>
|
||
{totalChecked}
|
||
</div>
|
||
</div>
|
||
<div style={statStyle}>
|
||
<div style={statLabelStyle}>符合</div>
|
||
<div
|
||
style={{ fontSize: "1.1rem", fontWeight: 700, color: "#059669" }}
|
||
>
|
||
{legalPassCount}
|
||
</div>
|
||
</div>
|
||
<div style={statStyle}>
|
||
<div style={statLabelStyle}>不符合</div>
|
||
<div
|
||
style={{ fontSize: "1.1rem", fontWeight: 700, color: "#dc2626" }}
|
||
>
|
||
{legalFailCount}
|
||
</div>
|
||
</div>
|
||
<div style={statStyle}>
|
||
<div style={statLabelStyle}>风险提醒</div>
|
||
<div
|
||
style={{ fontSize: "1.1rem", fontWeight: 700, color: "#d97706" }}
|
||
>
|
||
{legalWarnCount}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<Form
|
||
form={form}
|
||
layout="vertical"
|
||
style={{ marginTop: "0.5rem" }}
|
||
scrollToFirstError
|
||
>
|
||
<Form.Item
|
||
label="审核结果"
|
||
name="reviewResult"
|
||
rules={[{ required: true, message: "请选择审核结果" }]}
|
||
>
|
||
<Select placeholder="请选择">
|
||
{REVIEW_RESULT_OPTIONS.map((item) => (
|
||
<Select.Option key={item.value} value={item.value}>
|
||
{item.label}
|
||
</Select.Option>
|
||
))}
|
||
</Select>
|
||
</Form.Item>
|
||
|
||
{!isChange && (
|
||
<Form.Item label="指派专家" name="filingExpertId">
|
||
<Select
|
||
placeholder="请选择"
|
||
showSearch
|
||
optionFilterProp="label"
|
||
options={expertOptions}
|
||
/>
|
||
</Form.Item>
|
||
)}
|
||
|
||
<Form.Item
|
||
label="综合审核意见"
|
||
name="reviewOpinion"
|
||
rules={[{ required: true, message: "请输入综合审核意见" }]}
|
||
>
|
||
<TextArea
|
||
rows={3}
|
||
placeholder="请输入综合审核意见..."
|
||
maxLength={200}
|
||
/>
|
||
</Form.Item>
|
||
</Form>
|
||
</Modal>
|
||
);
|
||
};
|
||
|
||
export default Connect([NS_QUAL_EXPERT, NS_QUAL_REVIEW], true)(ReviewModal);
|