This commit is contained in:
Eeeros 2026-03-26 10:20:48 +08:00
commit bc5b64b255
2 changed files with 73 additions and 91 deletions

View File

@ -1,7 +1,7 @@
import React, { useState, useCallback } from 'react';
import './FeedbackModal.scss';
import { createMemo } from '../../forums/api';
import { message, Upload } from 'antd';
import { message, Upload, Icon } from 'antd';
import { httpUrl } from '../../forums/fetch';
//
@ -20,9 +20,9 @@ function FeedbackModal({ visible, onClose, onSuccess }) {
title: '',
description: '',
});
const [fileList, setFileList] = useState([]);
const [errors, setErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
const [fileList, setFileList] = useState([]);
//
const handleInputChange = useCallback((field, value) => {
@ -40,21 +40,18 @@ function FeedbackModal({ visible, onClose, onSuccess }) {
}, [errors]);
//
const beforeUpload = useCallback((file) => {
const beforeUpload = (file) => {
const isLt100M = file.size / 1024 / 1024 < 100;
if (!isLt100M) {
message.error('文件大小必须小于100MB!');
}
return isLt100M;
}, []);
};
//
const handleFileChange = useCallback((info) => {
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
const newFileList = info.fileList || [];
setFileList(newFileList);
}
}, []);
//
const handleFileChange = ({ fileList: newFileList }) => {
setFileList(newFileList);
};
//
const validateForm = useCallback(() => {
@ -75,17 +72,16 @@ function FeedbackModal({ visible, onClose, onSuccess }) {
setIsSubmitting(true);
try {
// ID
const attachmentIdArray = fileList.map(item => {
// 使 response.id item.id
return item.response && item.response.id ? item.response.id : item.id;
}).filter(id => id); // undefined/null
// IDforums/edit
const attachmentIdArray = fileList.map(item =>
item.response && item.response.id ? item.response.id : item.id ? item.id : item
);
// 11
const params = {
forum_id: 11,
children_forum_id: '0',
attachments: attachmentIdArray.length > 0 ? attachmentIdArray : undefined,
attachments: attachmentIdArray,
memo: {
subject: formData.title,
content: formData.description,
@ -111,13 +107,13 @@ function FeedbackModal({ visible, onClose, onSuccess }) {
} finally {
setIsSubmitting(false);
}
}, [formData, fileList, validateForm, onClose, onSuccess]);
}, [formData, validateForm, fileList, onClose, onSuccess]);
//
const handleCancel = useCallback(() => {
setFormData({ title: '', description: '' });
setFileList([]);
setErrors({});
setFileList([]);
onClose?.();
}, [onClose]);
@ -190,28 +186,23 @@ function FeedbackModal({ visible, onClose, onSuccess }) {
{errors.description && <span className="feedback-form-error">{errors.description}</span>}
</div>
{/* 附件上传 */}
{/* 附件上传 - 参考forums/edit配置 */}
<div className="feedback-form-item">
<div className="feedback-form-label">
<span>附件</span>
</div>
<div className="feedback-form-upload">
<Upload.Dragger
className="feedback-upload-dragger"
<Upload.Dragger
action={`${httpUrl}/api/attachments.json`}
beforeUpload={beforeUpload}
onChange={handleFileChange}
fileList={fileList}
multiple={true}
className="feedback-upload-dragger"
>
<p className="ant-upload-drag-icon">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 2L12 14M12 2L8 6M12 2L16 6" stroke="#4953e6" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M2 17L2 19C2 20.1046 2.89543 21 4 21L20 21C21.1046 21 22 20.1046 22 19L22 17" stroke="#4953e6" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
<Icon type="inbox" />
</p>
<p className="feedback-upload-text">点击或拖拽文件到此区域上传</p>
<p className="feedback-upload-hint">文件大小不超过 100MB</p>
<p className="mt10">点击或拖拽文件到此区域上传文件大小不超过 100MB</p>
</Upload.Dragger>
</div>
</div>

View File

@ -239,66 +239,9 @@ $transition-duration: 0.3s;
// 上传区域
.feedback-form-upload {
width: 100%;
}
// Ant Design Upload.Dragger 样式覆盖
.feedback-upload-dragger {
.ant-upload {
padding: 20px !important;
background: #fafafa !important;
border: 1px dashed $border-color !important;
border-radius: 8px !important;
transition: all $transition-duration ease;
&:hover {
border-color: $primary-color !important;
background: rgba($primary-color, 0.02) !important;
}
&.ant-upload-drag-hover {
border-color: $primary-color !important;
background: rgba($primary-color, 0.05) !important;
}
}
.ant-upload-drag-icon {
margin-bottom: 12px;
svg {
display: block;
margin: 0 auto;
}
}
.feedback-upload-text {
font-family: 'Alibaba PuHuiTi', 'PingFang SC', sans-serif;
font-size: 14px;
color: $text-primary;
line-height: 1.5;
margin-bottom: 4px;
}
.feedback-upload-hint {
font-family: 'Alibaba PuHuiTi', 'PingFang SC', sans-serif;
font-size: 12px;
color: $text-muted;
line-height: 1.4;
}
// 文件列表样式
.ant-upload-list {
margin-top: 12px;
.ant-upload-list-item {
font-family: 'Alibaba PuHuiTi', 'PingFang SC', sans-serif;
font-size: 13px;
&:hover {
background-color: rgba($primary-color, 0.02);
}
}
}
display: flex;
align-items: center;
gap: 12px;
}
// 隐藏文件输入
@ -306,7 +249,7 @@ $transition-duration: 0.3s;
display: none;
}
// 上传按钮旧版保留兼容性
// 上传按钮
.feedback-form-upload-btn {
display: inline-flex;
align-items: center;
@ -336,7 +279,7 @@ $transition-duration: 0.3s;
}
}
// 文件名旧版保留兼容性
// 文件名
.feedback-form-file-name {
font-family: 'Alibaba PuHuiTi', 'PingFang SC', sans-serif;
font-size: 13px;
@ -347,6 +290,54 @@ $transition-duration: 0.3s;
white-space: nowrap;
}
// Upload.Dragger 样式 - 参考forums/edit配置
.feedback-upload-dragger {
width: 100%;
.ant-upload {
&.ant-upload-drag {
background: #fafafa;
border: 1px dashed $border-color;
border-radius: $border-radius-input;
padding: 16px;
&:hover {
border-color: $primary-color;
}
.ant-upload-drag-icon {
margin-bottom: 8px;
.anticon {
font-size: 32px;
color: $primary-color;
}
}
p {
font-family: 'Alibaba PuHuiTi', 'PingFang SC', sans-serif;
font-size: 13px;
color: $text-muted;
margin: 0;
}
}
}
// 文件列表样式
.ant-upload-list {
margin-top: 8px;
.ant-upload-list-item {
font-family: 'Alibaba PuHuiTi', 'PingFang SC', sans-serif;
font-size: 13px;
&:hover {
background-color: rgba($primary-color, 0.02);
}
}
}
}
// 弹窗底部
.feedback-modal-footer {
position: relative;