From 5da98bec378d4d0cba19f42db197ea2b3f78104d Mon Sep 17 00:00:00 2001 From: LiuJiaNan <15703339975@163.com> Date: Fri, 5 Dec 2025 10:19:05 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9A=90=E6=82=A3=E4=BF=AE=E6=94=B9=2012.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BranchCompany/Average/Ledger/Add/index.js | 193 +++++++++++++----- 1 file changed, 141 insertions(+), 52 deletions(-) diff --git a/src/pages/Container/BranchCompany/Average/Ledger/Add/index.js b/src/pages/Container/BranchCompany/Average/Ledger/Add/index.js index f012fa2..b19311c 100644 --- a/src/pages/Container/BranchCompany/Average/Ledger/Add/index.js +++ b/src/pages/Container/BranchCompany/Average/Ledger/Add/index.js @@ -40,7 +40,7 @@ function Add(props) { const [currentProcessHiddenIndex, setCurrentProcessHiddenIndex] = useState(-1); const [imageSelectModalOpen, setImageSelectModalOpen] = useState(false); const [uploadedImages, setUploadedImages] = useState([]); - const [processedImages, setProcessedImages] = useState([]); + const processedImages = useRef([]); const [modalTitle, setModalTitle] = useState("选择图片进行AI识别"); const [hiddenPartType, setHiddenPartType] = useState("select"); @@ -103,13 +103,34 @@ function Add(props) { getConfirmUserList(); }, []); - const getAIHiddenImageRecognize = async (selectedImage = null) => { + /** + * AI识别图片处理函数 + * @param {object} selectedImage - 要识别的图片,如果为空则使用第一张图片 + * @param {boolean} isReset - 是否为重新AI识别(用户点击AI识别按钮) + * @param {boolean} isSelectOther - 是否为选择其他图片识别 + */ + const getAIHiddenImageRecognize = async (selectedImage = null, isReset = false, isSelectOther = false) => { const hiddenImageFiles = form.getFieldValue("hiddenImageFiles"); const imageToProcess = selectedImage || hiddenImageFiles[0]; - if (imageToProcess && !processedImages.includes(imageToProcess)) { - setProcessedImages([...processedImages, imageToProcess]); + // 如果是重新识别(用户点击AI识别按钮),重置所有状态包括已处理图片 + // 这样用户可以重新开始完整的AI识别流程 + if (isReset) { + processedImages.current = []; // 清空已处理图片 + form.setFieldValue("isAi", ""); // 清空AI识别标记 + } + // 如果是重新识别或选择其他图片,重置AI相关状态 + // 重新识别:重置所有状态,选择其他图片:只重置AI相关状态,保留已处理图片记录 + if (isReset || isSelectOther) { + setAiHiddens([]); // 清空AI识别结果 + setSelectHiddens([]); // 清空已选择的隐患 + setCurrentProcessHiddenIndex(-1); // 重置当前处理的隐患索引 + form.setFieldValue("hiddenDesc", ""); // 清空隐患描述 + form.setFieldValue("legalBasis", ""); // 清空法律依据 + form.setFieldValue("rectificationDescr", ""); // 清空整改描述 + form.setFieldValue("aiBatch", ""); // 清空批次号 + aiHiddenImageRecognizeFilePath.current = ""; } if (!aiHiddenImageRecognizeFilePath.current) { @@ -119,10 +140,31 @@ function Add(props) { } const { data } = await props["hiddenAiRecognize"]({ hiddenUrl: "https://pic.rmb.bdstatic.com/bjh/news/0a68c2681805fcaea506d922f024420c.png" }); // const { data } = await props["hiddenAiRecognize"]({ hiddenUrl: getFileUrl() + aiHiddenImageRecognizeFilePath.current }); - setAiHiddens((data?.aiHiddens || []).map(item => ({ ...JSON.parse(item), id: createGuid() }))); - setAiHiddenModalOpen(true); - // await deleteFile({ files: [{ filePath: aiHiddenImageRecognizeFilePath.current }] }); + if (data?.aiHiddens) { + setAiHiddens(data?.aiHiddens.map(item => ({ ...JSON.parse(item), id: createGuid() }))); + + // 使用setTimeout确保状态更新在正确的时机 + setTimeout(() => { + const isAlreadyProcessed = processedImages.current.some(processedImg => + (processedImg.url && processedImg.url === imageToProcess.url) + || (processedImg.name && processedImg.name === imageToProcess.name) + || (processedImg.uid && processedImg.uid === imageToProcess.uid), + ); + + if (imageToProcess && !isAlreadyProcessed) { + processedImages.current = [...processedImages.current, imageToProcess]; + } + }, 0); + + setAiHiddenModalOpen(true); + // await deleteFile({ files: [{ filePath: aiHiddenImageRecognizeFilePath.current }] }); + } }; + + /** + * 处理AI识别按钮点击事件 + * 重新开始AI识别流程,重置所有状态 + */ const handleAiRecognizeClick = () => { const hiddenImageFiles = form.getFieldValue("hiddenImageFiles"); if (!hiddenImageFiles || hiddenImageFiles.length === 0) { @@ -130,45 +172,50 @@ function Add(props) { return; } - setProcessedImages([]); - setAiHiddens([]); - setSelectHiddens([]); - setCurrentProcessHiddenIndex(-1); - form.setFieldValue("isAi", ""); - form.setFieldValue("hiddenDesc", ""); - form.setFieldValue("legalBasis", ""); - form.setFieldValue("rectificationDescr", ""); - if (hiddenImageFiles.length === 1) { - getAIHiddenImageRecognize(hiddenImageFiles[0]); + // 只有一张图片,直接进行AI识别,标记为重新识别以重置所有状态 + getAIHiddenImageRecognize(hiddenImageFiles[0], true); } else { + // 多张图片,显示图片选择弹窗让用户选择 setUploadedImages(hiddenImageFiles); - setModalTitle("选择图片进行AI识别"); + setModalTitle("选择图片进行AI识别"); // 标题用于区分操作类型 setImageSelectModalOpen(true); } }; + /** + * 处理选择其他图片按钮点击事件 + * 显示确认对话框,确认后打开图片选择弹窗(只显示未处理的图片) + */ const handleSelectOtherImage = () => { Modal.confirm({ title: "确认切换图片", content: "当前有未处理完的隐患信息,确认后进入选择图片,选择图片重新AI识别,将丢弃之前没有处理完的隐患", onOk: () => { - setAiHiddens([]); - setSelectHiddens([]); - setCurrentProcessHiddenIndex(-1); - form.setFieldValue("isAi", ""); - form.setFieldValue("hiddenDesc", ""); - form.setFieldValue("legalBasis", ""); - form.setFieldValue("rectificationDescr", ""); - + // 获取所有上传的图片 const hiddenImageFiles = form.getFieldValue("hiddenImageFiles"); - const unprocessedImages = hiddenImageFiles.filter(img => - !processedImages.includes(img), - ); + // 过滤出未处理的图片(排除已处理过的图片) + const unprocessedImages = hiddenImageFiles.filter((img) => { + const isProcessed = processedImages.current.some(processedImg => + (processedImg.url && processedImg.url === img.url) + || (processedImg.name && processedImg.name === img.name) + || (processedImg.uid && processedImg.uid === img.uid), + ); + return !isProcessed; + }); + // 如果没有未处理的图片,提示用户 + if (unprocessedImages.length === 0) { + message.info("所有图片都已处理完毕"); + return; + } + + // 设置要显示的图片(未处理图片) setUploadedImages(unprocessedImages); + // 设置弹窗标题,用于区分是选择其他图片操作 setModalTitle("选择其他图片进行AI识别"); + // 打开图片选择弹窗 setImageSelectModalOpen(true); }, }); @@ -176,9 +223,18 @@ function Add(props) { const getUnprocessedImagesCount = () => { const hiddenImageFiles = form.getFieldValue("hiddenImageFiles") || []; - return hiddenImageFiles.filter(img => - !processedImages.includes(img), - ).length; + + // 使用图片URL或name进行比较,而不是对象引用 + const unprocessedCount = hiddenImageFiles.filter((img) => { + const isProcessed = processedImages.current.some(processedImg => + (processedImg.url && processedImg.url === img.url) + || (processedImg.name && processedImg.name === img.name) + || (processedImg.uid && processedImg.uid === img.uid), + ); + return !isProcessed; + }).length; + + return unprocessedCount; }; const onMergeHidden = (selectedRowKeys) => { @@ -267,20 +323,39 @@ function Add(props) { loading={deleteFileLoading || uploadFileLoading || getFileLoading || props.ledger.ledgerLoading} values={defaultValues} onFinish={onSubmit} - showSubmitButton={false} - showCancelButton={false} + onFinishFailed={() => { + if (isExistNextOneHidden()) { + setCurrentProcessHiddenIndex(currentProcessHiddenIndex + 1); + const currentValues = form.getFieldsValue(); + const hiddenImageFiles = form.getFieldValue("hiddenImageFiles"); + const resetValues = {}; + Object.keys(currentValues).forEach((key) => { + resetValues[key] = undefined; + }); + form.setFieldsValue({ + ...resetValues, + ...defaultValues, + isAi: 1, + hiddenImageFiles, + hiddenDesc: selectHiddens[currentProcessHiddenIndex + 1].hiddenDescr, + legalBasis: selectHiddens[currentProcessHiddenIndex + 1].legalBasis, + rectificationDescr: selectHiddens[currentProcessHiddenIndex + 1].rectificationSuggestions, + }); + } + else { + props.history.goBack(); + } + }} + submitButtonText={isExistNextOneHidden() ? "提交并下一个" : "提交"} extraActionButtons={[ - , - ...(isAi === 1 && processedImages.length > 0 && getUnprocessedImagesCount() > 0 - ? [ - , - ] - : []), - , + isAi === 1 && getUnprocessedImagesCount() > 0 + && ( + + ), ]} options={[ { @@ -292,14 +367,15 @@ function Add(props) { listType="picture-card" onRemove={() => { if (isAi === 1) { + setAiHiddens([]); + setSelectHiddens([]); + setCurrentProcessHiddenIndex(-1); form.setFieldValue("isAi", ""); form.setFieldValue("hiddenDesc", ""); form.setFieldValue("legalBasis", ""); form.setFieldValue("rectificationDescr", ""); + form.setFieldValue("aiBatch", ""); aiHiddenImageRecognizeFilePath.current = ""; - setSelectHiddens([]); - setAiHiddens([]); - setCurrentProcessHiddenIndex(-1); } }} onGetRemoveFile={(file) => { @@ -327,6 +403,7 @@ function Add(props) { span: 24, }, { name: "isAi", label: "是否AI识别隐患", onlyForLabel: true }, + { name: "aiBatch", label: "AI识别隐患批次号", onlyForLabel: true }, { name: "hiddenDesc", label: "隐患描述", render: FORM_ITEM_RENDER_ENUM.TEXTAREA, span: 24 }, { name: "legalBasis", @@ -663,6 +740,7 @@ function Add(props) { form.setFieldValue("hiddenDesc", selectedRows[0].hiddenDescr); form.setFieldValue("legalBasis", selectedRows[0].legalBasis); form.setFieldValue("rectificationDescr", selectedRows[0].rectificationSuggestions); + form.setFieldValue("aiBatch", createGuid()); }} onMergeHidden={onMergeHidden} /> @@ -674,8 +752,8 @@ function Add(props) { title={modalTitle} images={uploadedImages} onCancel={() => setImageSelectModalOpen(false)} - onConfirm={(selectedImage) => { - getAIHiddenImageRecognize(selectedImage); + onConfirm={(selectedImage, isReset = false, isSelectOther) => { + getAIHiddenImageRecognize(selectedImage, isReset, isSelectOther); }} /> ) @@ -754,16 +832,27 @@ const AiHiddenModal = (props) => { ); }; +/** + * 图片选择弹窗组件 + * 用于AI识别和选择其他图片时的图片选择 + */ const ImageSelectModal = (props) => { const [selectedImage, setSelectedImage] = useState(null); + /** + * 确认选择图片并开始AI识别 + * 根据弹窗标题判断操作类型,传递相应的参数 + */ const handleConfirm = () => { if (!selectedImage) { message.warning("请选择一张图片进行AI识别"); return; } - props.onConfirm(selectedImage); - props.onCancel(); + // 根据标题判断操作类型,传递相应的参数给父组件 + const isReset = props.title === "选择图片进行AI识别"; // 重新AI识别:重置所有状态 + const isSelectOther = props.title === "选择其他图片进行AI识别"; // 选择其他图片:保留已处理图片记录 + props.onConfirm(selectedImage, isReset, isSelectOther); + props.onCancel(); // 关闭弹窗 }; return (