|
|
@@ -1,8 +1,8 @@
|
|
|
import React, { useState, useEffect } from 'react';
|
|
|
-import { Table, Card, Tabs, Button, Space, Tag, Switch, Popconfirm, message, Modal, Form, Input, Select, Upload } from 'antd';
|
|
|
-import { PlusOutlined, EditOutlined, DeleteOutlined, EyeOutlined, LinkOutlined } from '@ant-design/icons';
|
|
|
+import { Table, Card, Tabs, Button, Space, Tag, Switch, Popconfirm, message, Modal, Form, Input, Select, Upload, Image } from 'antd';
|
|
|
+import { PlusOutlined, EditOutlined, DeleteOutlined, EyeOutlined, LinkOutlined, UploadOutlined } from '@ant-design/icons';
|
|
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
|
-import { homeIconClient } from '@/client/api';
|
|
|
+import { homeIconClient, fileClient } from '@/client/api';
|
|
|
import type { HomeIcon } from '@/server/modules/home/home-icon.entity';
|
|
|
import type { File as FileType } from '@/server/modules/files/file.entity';
|
|
|
import type { InferResponseType, InferRequestType } from 'hono/client';
|
|
|
@@ -157,10 +157,30 @@ const HomeIconsPage: React.FC = () => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- const handleUploadSuccess = (fileKey: string, fileUrl: string, file: FileType) => {
|
|
|
- // 这里需要获取刚上传的文件ID
|
|
|
- // 实际项目中,上传成功后应该返回文件ID
|
|
|
- message.success('文件上传成功,请填写其他信息后提交');
|
|
|
+ const [fileModalVisible, setFileModalVisible] = useState(false);
|
|
|
+
|
|
|
+ // 获取文件列表
|
|
|
+ const { data: filesData } = useQuery({
|
|
|
+ queryKey: ['files-for-selection'],
|
|
|
+ queryFn: async () => {
|
|
|
+ const response = await fileClient.$get({
|
|
|
+ query: { page: 1, pageSize: 50, keyword: 'image' }
|
|
|
+ });
|
|
|
+ if (response.status !== 200) throw new Error('获取文件列表失败');
|
|
|
+ return response.json();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ const handleUploadSuccess = (fileKey: string, fileUrl: string, file: any) => {
|
|
|
+ message.success('文件上传成功!请在文件管理页面查看文件ID,然后选择文件');
|
|
|
+ // 刷新文件列表
|
|
|
+ queryClient.invalidateQueries({ queryKey: ['files-for-selection'] });
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleSelectFile = (file: FileType) => {
|
|
|
+ form.setFieldsValue({ fileId: file.id });
|
|
|
+ setFileModalVisible(false);
|
|
|
+ message.success(`已选择文件: ${file.name}`);
|
|
|
};
|
|
|
|
|
|
const columns = [
|
|
|
@@ -324,9 +344,68 @@ const HomeIconsPage: React.FC = () => {
|
|
|
<Form.Item
|
|
|
name="fileId"
|
|
|
label="图标文件"
|
|
|
- rules={[{ required: true, message: '请上传图标文件' }]}
|
|
|
+ rules={[{ required: true, message: '请选择图标文件' }]}
|
|
|
>
|
|
|
- <Input type="number" placeholder="请输入文件ID" />
|
|
|
+ <div style={{ display: 'flex', gap: '8px' }}>
|
|
|
+ <Input
|
|
|
+ type="number"
|
|
|
+ placeholder="请选择或上传图标文件"
|
|
|
+ readOnly
|
|
|
+ style={{ flex: 1 }}
|
|
|
+ />
|
|
|
+ <Button
|
|
|
+ type="default"
|
|
|
+ icon={<EyeOutlined />}
|
|
|
+ onClick={() => setFileModalVisible(true)}
|
|
|
+ >
|
|
|
+ 选择文件
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </Form.Item>
|
|
|
+
|
|
|
+ <Form.Item
|
|
|
+ noStyle
|
|
|
+ shouldUpdate={(prevValues, currentValues) => prevValues.fileId !== currentValues.fileId}
|
|
|
+ >
|
|
|
+ {({ getFieldValue }) => {
|
|
|
+ const fileId = getFieldValue('fileId');
|
|
|
+ const selectedFile = filesData?.data?.find((f: FileType) => f.id === fileId);
|
|
|
+
|
|
|
+ return fileId && selectedFile ? (
|
|
|
+ <div style={{
|
|
|
+ padding: '12px',
|
|
|
+ backgroundColor: '#f6ffed',
|
|
|
+ border: '1px solid #b7eb8f',
|
|
|
+ borderRadius: '4px',
|
|
|
+ marginBottom: '16px',
|
|
|
+ display: 'flex',
|
|
|
+ alignItems: 'center',
|
|
|
+ gap: '12px'
|
|
|
+ }}>
|
|
|
+ <Image
|
|
|
+ src={selectedFile.path}
|
|
|
+ alt={selectedFile.name}
|
|
|
+ style={{ width: 60, height: 60, objectFit: 'cover', borderRadius: 4 }}
|
|
|
+ />
|
|
|
+ <div>
|
|
|
+ <div style={{ fontWeight: 'bold' }}>{selectedFile.name}</div>
|
|
|
+ <div style={{ color: '#666', fontSize: '12px' }}>ID: {selectedFile.id}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ ) : (
|
|
|
+ <div style={{
|
|
|
+ padding: '8px 12px',
|
|
|
+ backgroundColor: '#fff7e6',
|
|
|
+ border: '1px solid #ffd591',
|
|
|
+ borderRadius: '4px',
|
|
|
+ marginBottom: '16px'
|
|
|
+ }}>
|
|
|
+ <span style={{ color: '#fa8c16', fontSize: '14px' }}>
|
|
|
+ ⚠️ 请选择图标文件,支持上传新文件或从已有文件中选择
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }}
|
|
|
</Form.Item>
|
|
|
|
|
|
<Form.Item
|
|
|
@@ -370,6 +449,75 @@ const HomeIconsPage: React.FC = () => {
|
|
|
</Form.Item>
|
|
|
</Form>
|
|
|
</Modal>
|
|
|
+
|
|
|
+ {/* 文件选择模态框 */}
|
|
|
+ <Modal
|
|
|
+ title="选择图标文件"
|
|
|
+ open={fileModalVisible}
|
|
|
+ onCancel={() => setFileModalVisible(false)}
|
|
|
+ width={800}
|
|
|
+ footer={null}
|
|
|
+ >
|
|
|
+ <div style={{ marginBottom: 16 }}>
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ icon={<UploadOutlined />}
|
|
|
+ onClick={() => setFileModalVisible(false)}
|
|
|
+ style={{ marginRight: 8 }}
|
|
|
+ >
|
|
|
+ 上传新文件
|
|
|
+ </Button>
|
|
|
+ <span style={{ color: '#666', fontSize: '12px' }}>
|
|
|
+ 提示:先上传文件,然后从列表中选择
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div style={{ maxHeight: 400, overflowY: 'auto' }}>
|
|
|
+ {filesData?.data?.filter((f: FileType) => f.type?.startsWith('image/')).map((file: FileType) => (
|
|
|
+ <div
|
|
|
+ key={file.id}
|
|
|
+ style={{
|
|
|
+ display: 'flex',
|
|
|
+ alignItems: 'center',
|
|
|
+ padding: '12px',
|
|
|
+ border: '1px solid #f0f0f0',
|
|
|
+ borderRadius: '4px',
|
|
|
+ marginBottom: '8px',
|
|
|
+ cursor: 'pointer',
|
|
|
+ transition: 'all 0.3s'
|
|
|
+ }}
|
|
|
+ onClick={() => handleSelectFile(file)}
|
|
|
+ onMouseEnter={(e) => {
|
|
|
+ e.currentTarget.style.backgroundColor = '#f6ffed';
|
|
|
+ e.currentTarget.style.borderColor = '#b7eb8f';
|
|
|
+ }}
|
|
|
+ onMouseLeave={(e) => {
|
|
|
+ e.currentTarget.style.backgroundColor = '';
|
|
|
+ e.currentTarget.style.borderColor = '#f0f0f0';
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Image
|
|
|
+ src={file.path}
|
|
|
+ alt={file.name}
|
|
|
+ style={{ width: 60, height: 60, objectFit: 'cover', borderRadius: 4, marginRight: 12 }}
|
|
|
+ />
|
|
|
+ <div style={{ flex: 1 }}>
|
|
|
+ <div style={{ fontWeight: 'bold', marginBottom: '4px' }}>{file.name}</div>
|
|
|
+ <div style={{ color: '#666', fontSize: '12px' }}>
|
|
|
+ ID: {file.id} | 大小: {((file.size || 0) / 1024 / 1024).toFixed(2)}MB
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <Button type="primary" size="small">选择</Button>
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {(!filesData?.data || filesData.data.filter((f: FileType) => f.type?.startsWith('image/')).length === 0) && (
|
|
|
+ <div style={{ textAlign: 'center', padding: '40px', color: '#999' }}>
|
|
|
+ 暂无图片文件,请先上传
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </Modal>
|
|
|
</div>
|
|
|
);
|
|
|
};
|