import { buildProTableDataSource, sendRequest, showDelConfirm } from '@/utils/antdUtils';
|
import { PageContainer, ProTable } from '@ant-design/pro-components';
|
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, editProgress, deleteProgress } from './service';
|
import moment from 'moment';
|
import './index.less';
|
import {downLoad, customRequest } from '@/utils/utils';
|
import { PlusOutlined } from '@ant-design/icons';
|
|
const Account = () => {
|
const actionRef = useRef();
|
const addViewRef = useRef();
|
const [current, setCurrent] = useState(0);
|
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) => {
|
setDetail(res.data);
|
});
|
}, []);
|
|
const items = [
|
{
|
key: '1',
|
label: '述求状态',
|
children: ['正在办理', '延期办理', '超时办理', '已办结', '待审核', '上报待审核'][detail.status] || '已办结',
|
},
|
{
|
key: '2',
|
label: '述求号',
|
children: detail.serialNumber,
|
},
|
{
|
key: '3',
|
label: '',
|
children: '',
|
},
|
{
|
key: '4',
|
label: '',
|
children: '',
|
},
|
{
|
key: '5',
|
label: '发生时间',
|
children: moment(detail.time).format('YYYY-MM-DD HH:mm:ss'),
|
},
|
{
|
key: '6',
|
label: '问题类型',
|
children: detail.problemType,
|
},
|
{
|
key: '7',
|
label: '群众姓名',
|
children: detail.name,
|
},
|
{
|
key: '8',
|
label: '联系电话',
|
children: detail.contactNumber,
|
},
|
{
|
key: '9',
|
label: '发生地点',
|
children: detail.location,
|
},
|
{
|
key: '10',
|
label: '详细地址',
|
children: detail.detailedAddress,
|
},
|
{
|
key: '11',
|
label: '录入人',
|
children: detail.reportUserName,
|
},
|
{
|
key: '12',
|
label: '联系电话',
|
children: detail.reportUserPhone,
|
},
|
{
|
key: '13',
|
label: '问题描述',
|
children: detail.descriptionContent,
|
span: 4,
|
},
|
{
|
key: '14',
|
label: '上传图片',
|
children: <>
|
{detail.images && (detail.images || '').split(',').map((item, index) => (
|
<img width={80} height={80} src={item} key={index} alt="example" />
|
))}
|
</>,
|
span: 4,
|
},
|
{
|
key: '15',
|
label: '上传视频',
|
children: <>
|
{detail.videos && (detail.videos || '').split(',').map((item, index) => (
|
<video width={280} src={item} key={index} controls></video>
|
))}
|
</>,
|
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="述求详情" >
|
<Card>
|
<Descriptions column={4} title="基础信息" items={items} />
|
<Divider />
|
<div>
|
<Descriptions title="办理进度" column={1}>
|
{detail.complaintProgresses?.length > 0 ? detail.complaintProgresses.map((item, index) => (
|
<Descriptions.Item key={index}>
|
<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 label={'上传图片'}>
|
{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.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>}
|
</Descriptions>
|
</div>
|
|
<Divider />
|
{detail.complaintFlows?.length > 0 && <><Descriptions title="述求流转" >
|
|
<Descriptions.Item span={4}>
|
<div style={{ width: '100%', overflowX: 'auto' }} >
|
<Steps size="small" >
|
{detail.complaintFlows && detail.complaintFlows.map((item, index) => (
|
<Steps.Item status={'process'} key={index} title={item.name} description={<span>{item.type == 1 ? '下派' : '上报'} <span>{moment(item.createTime).format('YYYY-MM-DD HH:mm:ss')}</span> </span>} />
|
))}
|
</Steps>
|
</div>
|
</Descriptions.Item>
|
</Descriptions>
|
<Divider /></>}
|
{[3, 4].includes(detail.status) &&
|
<Descriptions title="办结情况" >
|
<Descriptions.Item span={4}>
|
<Card style={{ width: '800px' }} extra={<div style={{ width: '750px', display: 'flex', justifyContent: 'space-between' }}>
|
<span>办结时间:{moment(detail.completionTime).format('YYYY-MM-DD HH:mm:ss')}</span>
|
<span>办结人员:{detail.completionUsername}</span>
|
<span>联系电话:{detail.completionUserPhone}</span>
|
</div>}>
|
<Descriptions column={1} >
|
<Descriptions.Item>
|
{detail.completionDescription}
|
</Descriptions.Item>
|
<Descriptions.Item label={'上传图片'}>
|
{detail.completionImages && detail.completionImages.split(',').map((item, index) => (
|
<img width={80} height={80} style={{ marginRight: '10px' }} src={item} key={index} alt="example" />
|
))}
|
</Descriptions.Item>
|
<Descriptions.Item label={'上传视频'}>
|
{detail.completionVideos && detail.completionVideos.split(',').map((item, index) => (
|
<video width={280} style={{ marginRight: '10px' }} src={item} key={index} controls></video>
|
))}
|
</Descriptions.Item>
|
</Descriptions>
|
</Card>
|
</Descriptions.Item>
|
</Descriptions>}
|
{detail.complaintComment &&
|
<Descriptions title="办结评价" style={{ marginTop: '20px' }} >
|
<Descriptions.Item span={4}>
|
<Card style={{ width: '800px' }} extra={<div style={{ width: '750px', display: 'flex', justifyContent: 'flex-start' }}>
|
<span>评价打分:{['不满意', '一般', '满意', '非常满意'][detail.complaintComment?.rate]}</span>
|
</div>}>
|
<Descriptions column={1} >
|
<Descriptions.Item>
|
{detail.complaintComment?.content}
|
</Descriptions.Item>
|
<Descriptions.Item label={'上传图片'}>
|
{detail.complaintComment?.imgUrl && detail.complaintComment?.imgUrl.split(',').map((item, index) => (
|
<img width={80} height={80} style={{ marginRight: '10px' }} src={item} key={index} alt="example" />
|
))}
|
</Descriptions.Item>
|
<Descriptions.Item label={'上传视频'}>
|
{detail.complaintComment?.video && detail.complaintComment?.video.split(',').map((item, index) => (
|
<video width={280} style={{ marginRight: '10px' }} src={item} key={index} controls></video>
|
))}
|
</Descriptions.Item>
|
</Descriptions>
|
</Card>
|
</Descriptions.Item>
|
</Descriptions>
|
}
|
|
|
<div style={{ marginTop: '20px', display: 'flex', justifyContent: 'center' }}>
|
<Button onClick={() => {
|
try {
|
history.go(-1);
|
} catch (error) {
|
message.error('返回失败,请重试');
|
console.error('Navigation error:', error);
|
}
|
}} style={{ marginRight: '20px' }} >关闭</Button>
|
<Button type="primary" onClick={() => {
|
try {
|
downLoad(`/api/huacheng-sangeshenbian/complaint/download-file/${id}/1`, '社区问题单导出.docx');
|
// TODO: Implement export functionality
|
message.success('导出成功');
|
} catch (error) {
|
message.error('导出失败,请重试');
|
console.error('Export error:', error);
|
}
|
}} style={{ marginRight: '20px' }}>社区问题单导出</Button>
|
<Button type="primary" onClick={() => {
|
try {
|
downLoad(`/api/huacheng-sangeshenbian/complaint/download-file/${id}/2`, '问题处理单导出.docx');
|
// TODO: Implement export functionality
|
message.success('导出成功');
|
} catch (error) {
|
message.error('导出失败,请重试');
|
console.error('Export error:', error);
|
}
|
}} style={{ marginRight: '20px' }}>问题处理单导出</Button>
|
<Button type="primary" onClick={() => {
|
try {
|
downLoad(`/api/huacheng-sangeshenbian/complaint/download-file/${id}/3`, '协调通知单导出.docx');
|
// TODO: Implement export functionality
|
message.success('导出成功');
|
} catch (error) {
|
message.error('导出失败,请重试');
|
console.error('Export error:', error);
|
}
|
}} >协调通知单导出</Button>
|
</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>
|
);
|
};
|
|
export default Account;
|