From 20e32587ecbab27e4436f2f64a15faa3c89e4f41 Mon Sep 17 00:00:00 2001
From: pyt <626651354@qq.com>
Date: 星期二, 20 五月 2025 21:39:59 +0800
Subject: [PATCH] Merge branch 'master' of http://120.76.84.145:10101/gitblit/r/H5/threeSide

---
 management/src/pages/appeal-management/detail.jsx |  235 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 224 insertions(+), 11 deletions(-)

diff --git a/management/src/pages/appeal-management/detail.jsx b/management/src/pages/appeal-management/detail.jsx
index e8d4ae5..950943f 100644
--- a/management/src/pages/appeal-management/detail.jsx
+++ b/management/src/pages/appeal-management/detail.jsx
@@ -1,13 +1,14 @@
 import { buildProTableDataSource, sendRequest, showDelConfirm } from '@/utils/antdUtils';
 import { PageContainer, ProTable } from '@ant-design/pro-components';
-import { Button, Card, Select, Space, Descriptions, Divider, Steps, message } from 'antd';
+import { Button, Card, Select, Space, Descriptions, Divider, Steps, message, Modal, Form, Input, Upload, Popconfirm } from 'antd';
 import { useRef, useState, useEffect } from 'react';
 import { Access, useAccess } from 'umi'
 import { history, useLocation } from "@umijs/max"
-import { getDetail } from './service';
+import { getDetail, editProgress, deleteProgress } from './service';
 import moment from 'moment';
 import './index.less';
-import {downLoad } from '@/utils/utils';
+import {downLoad, customRequest } from '@/utils/utils';
+import { PlusOutlined } from '@ant-design/icons';
 
 const Account = () => {
     const actionRef = useRef();
@@ -16,6 +17,22 @@
     const [detail, setDetail] = useState({});
     const searchParams = new URLSearchParams(useLocation().search);
     const id = searchParams.get('id');
+    const [editModalVisible, setEditModalVisible] = useState(false);
+    const [editProgressData, setEditProgressData] = useState(null);
+    const [editForm] = Form.useForm();
+    const [loading, setLoading] = useState(false);
+    const [imgFileList, setImgFileList] = useState([]);
+    const [videoFileList, setVideoFileList] = useState([]);
+    const [previewVisible, setPreviewVisible] = useState(false);
+    const [previewImage, setPreviewImage] = useState('');
+    const [previewType, setPreviewType] = useState('image'); // 'image' or 'video'
+    const uploadConfig = {
+        name: 'file',
+        action: 'https://huacheng.psciio.com/api/huacheng-communitybackstage/communitypartybuilding/uploadimage',
+        headers: {
+            Authorization: 'Bearer ' + localStorage.getItem('token'),
+        },
+    };
 
     useEffect(() => {
         getDetail({ id: id }).then((res) => {
@@ -111,6 +128,117 @@
             span: 4,
         },
     ];
+
+    // 上传前校验
+    const beforeUpload = (file) => {
+        return new Promise((resolve, reject) => {
+            if (file.name.includes(',')) {
+                message.warning('上传文件不能包含英文逗号(,)');
+                return Upload.LIST_IGNORE;
+            }
+            setLoading(true);
+            resolve(file);
+        });
+    };
+
+    // 图片上传change
+    const handleImgChange = ({ file, fileList: newFileList }) => {
+        if (file.status === 'error' || (file.status === 'done' && file.response && file.response.code !== 200)) {
+            setLoading(false);
+            setImgFileList([]);
+            message.error('上传失败');
+            editForm.setFieldValue('imgUrl', []);
+            return;
+        }
+        if (file.status === 'done' && file.response && file.response.code === 200) {
+            setLoading(false);
+            message.success('上传成功');
+        }
+        let urls = newFileList.map(item => {
+            if (item.status === 'done' && item.response && item.response.data) {
+                item.url = item.response.data;
+            }
+            return item.url || item.url;
+        }).filter(Boolean);
+        setImgFileList(newFileList);
+        editForm.setFieldValue('imgUrl', urls);
+    };
+
+    // 视频上传change
+    const handleVideoChange = ({ file, fileList: newFileList }) => {
+        if (file.status === 'error' || (file.status === 'done' && file.response && file.response.code !== 200)) {
+            setLoading(false);
+            setVideoFileList([]);
+            message.error('上传失败');
+            editForm.setFieldValue('videoUrl', []);
+            return;
+        }
+        if (file.status === 'done' && file.response && file.response.code === 200) {
+            setLoading(false);
+            message.success('上传成功');
+        }
+        let urls = newFileList.map(item => {
+            if (item.status === 'done' && item.response && item.response.data) {
+                item.url = item.response.data;
+            }
+            return item.url || item.url;
+        }).filter(Boolean);
+        setVideoFileList(newFileList);
+        editForm.setFieldValue('videoUrl', urls);
+    };
+
+    // 办理进度编辑提交
+    const handleEditProgress = async () => {
+        try {
+            setLoading(true);
+            console.log('editProgressData', editProgressData);
+            
+            const values = await editForm.validateFields();
+            await editProgress({
+                complaintId: id,
+                describe: values.describe,
+                id: editProgressData.id,
+                imgUrl: (values.imgUrl || []).join(','),
+                video: (values.videoUrl || []).join(',')
+            });
+            message.success('编辑成功');
+            setEditModalVisible(false);
+            getDetail({ id }).then((res) => setDetail(res.data));
+        } catch (e) {
+            // 校验或请求失败
+        } finally {
+            setLoading(false);
+        }
+    };
+
+    // 办理进度删除
+    const handleDeleteProgress = async (progressId) => {
+        try {
+            await deleteProgress({ id: progressId });
+            message.success('删除成功');
+            getDetail({ id }).then((res) => setDetail(res.data));
+        } catch (e) {
+            message.error('删除失败');
+        }
+    };
+
+    // 在弹窗打开时同步 fileList
+    useEffect(() => {
+        if (editModalVisible && editProgressData) {
+            setImgFileList((editProgressData.imgUrl ? editProgressData.imgUrl.split(',') : []).map((url, idx) => ({ uid: idx, url, status: 'done' })));
+            setVideoFileList((editProgressData.video ? editProgressData.video.split(',') : []).map((url, idx) => ({ uid: idx, url, status: 'done' })));
+            editForm.setFieldsValue({
+                describe: editProgressData.describe,
+                imgUrl: editProgressData.imgUrl ? editProgressData.imgUrl.split(',') : [],
+                videoUrl: editProgressData.video ? editProgressData.video.split(',') : [],
+            });
+        }
+        if (!editModalVisible) {
+            setImgFileList([]);
+            setVideoFileList([]);
+        }
+    }, [editModalVisible, editProgressData]);
+
     return (
         <div>
             <PageContainer className={'appeal-management-detail'} header={{ breadcrumb: {} }} title="述求详情" >
@@ -121,22 +249,34 @@
                         <Descriptions title="办理进度" column={1}>
                             {detail.complaintProgresses?.length > 0 ? detail.complaintProgresses.map((item, index) => (
                                 <Descriptions.Item key={index}>
-                                    <Card style={{ width: '800px' }} title={item.createByName} extra={moment(item.createTime).format('YYYY-MM-DD HH:mm:ss')}>
+                                    <Card style={{ width: '800px', position: 'relative' }} title={item.createByName} extra={moment(item.createTime).format('YYYY-MM-DD HH:mm:ss')}>
                                         <Descriptions column={1} >
-                                            <Descriptions.Item>
-                                                {item.describe}
-                                            </Descriptions.Item>
+                                            <Descriptions.Item>{item.describe}</Descriptions.Item>
                                             <Descriptions.Item label={'上传图片'}>
-                                                {item.imgUrl && (item.imgUrl || '').split(',').map((item, index) => (
-                                                    <img width={80} style={{ marginRight: '10px' }} height={80} src={item} key={index} alt="example" />
+                                                {item.imgUrl && (item.imgUrl || '').split(',').map((img, idx) => (
+                                                    <img width={80} style={{ marginRight: '10px' }} height={80} src={img} key={idx} alt="example" />
                                                 ))}
                                             </Descriptions.Item>
                                             <Descriptions.Item label={'上传视频'}>
-                                                {item.videoUrl && (item.videoUrl || '').split(',').map((item, index) => (
-                                                    <video width={280} style={{ marginRight: '10px' }} src={item} key={index} controls></video>
+                                                {item.video && item.video.split(',').map((video, idx) => (
+                                                    <video width={280} style={{ marginRight: '10px' }} src={video} key={idx} controls></video>
                                                 ))}
                                             </Descriptions.Item>
                                         </Descriptions>
+                                        <div style={{ position: 'absolute', right: 24, bottom: 16 }}>
+                                            <Button size="small" type="primary" style={{ marginRight: 8 }} onClick={() => {
+                                                setEditProgressData(item);
+                                                setEditModalVisible(true);
+                                                editForm.setFieldsValue({
+                                                    describe: item.describe,
+                                                    imgUrl: item.imgUrl ? item.imgUrl.split(',') : [],
+                                                    videoUrl: item.video ? item.video.split(',') : [],
+                                                });
+                                            }}>编辑</Button>
+                                            <Popconfirm title="确定要删除该办理进度吗?" onConfirm={() => handleDeleteProgress(item.id)} okText="确定" cancelText="取消">
+                                                <Button size="small" danger>删除</Button>
+                                            </Popconfirm>
+                                        </div>
                                     </Card>
                                 </Descriptions.Item>
                             )) : <Descriptions.Item span={4} >暂无办理进度</Descriptions.Item>}
@@ -252,7 +392,80 @@
                     </div>
                 </Card>
 
+                <Modal
+                    title="编辑办理进度"
+                    open={editModalVisible}
+                    onCancel={() => setEditModalVisible(false)}
+                    onOk={handleEditProgress}
+                    confirmLoading={loading}
+                    destroyOnClose
+                    width={600}
+                >
+                    <Form form={editForm} layout="vertical" initialValues={{ describe: '', imgUrl: [], videoUrl: [] }}>
+                        <Form.Item name="describe" label="办理进度描述" rules={[{ required: true, message: '请输入办理进度描述' }]}> 
+                            <Input.TextArea rows={4} maxLength={500} showCount />
+                        </Form.Item>
+                        <Form.Item name="imgUrl" label="图片:">
+                            <Upload
+                                {...uploadConfig}
+                                listType="picture-card"
+                                maxCount={9}
+                                beforeUpload={beforeUpload}
+                                onChange={handleImgChange}
+                                onRemove={() => {
+                                    setImgFileList([]);
+                                    editForm.setFieldValue('imgUrl', []);
+                                }}
+                                showUploadList={{ showPreviewIcon: true }}
+                                accept="image/*"
+                                fileList={imgFileList}
+                                onPreview={file => {
+                                    setPreviewType('image');
+                                    setPreviewImage(file.url || file.thumbUrl);
+                                    setPreviewVisible(true);
+                                }}
+                            >
+                                {imgFileList.length < 9 && <PlusOutlined />}
+                            </Upload>
+                        </Form.Item>
+                        <Form.Item name="videoUrl" label="视频:">
+                            <Upload
+                                {...uploadConfig}
+                                listType="picture-card"
+                                maxCount={9}
+                                beforeUpload={beforeUpload}
+                                onChange={handleVideoChange}
+                                onRemove={() => {
+                                    setVideoFileList([]);
+                                    editForm.setFieldValue('videoUrl', []);
+                                }}
+                                showUploadList={{ showPreviewIcon: true }}
+                                accept="video/*"
+                                fileList={videoFileList}
+                                onPreview={file => {
+                                    setPreviewType('video');
+                                    setPreviewImage(file.url || file.thumbUrl);
+                                    setPreviewVisible(true);
+                                }}
+                            >
+                                {videoFileList.length < 9 && <PlusOutlined />}
+                            </Upload>
+                        </Form.Item>
+                    </Form>
+                </Modal>
 
+                <Modal
+                    open={previewVisible}
+                    footer={null}
+                    onCancel={() => setPreviewVisible(false)}
+                    width={previewType === 'video' ? 800 : 600}
+                >
+                    {previewType === 'image' ? (
+                        <img alt="预览" style={{ width: '100%' }} src={previewImage} />
+                    ) : (
+                        <video style={{ width: '100%' }} src={previewImage} controls autoPlay />
+                    )}
+                </Modal>
             </PageContainer>
         </div>
     );

--
Gitblit v1.7.1