import React, { useEffect, useRef, useState } from 'react'; import { Button, Card, Form, message, Row, Col, Typography, Divider, Select } from 'antd'; import { CloudUploadOutlined, CheckCircleOutlined } from '@ant-design/icons'; import { useTranslation } from 'react-i18next'; import { getStorageConfig, saveStorageConfig, testStorageConnection } from '@/api/system/sysStorage.ts'; import type { FormColumn } from "@/components/XinFormField/FieldRender"; import XinForm, { type XinFormRef } from "@/components/XinForm"; const { Text, Title } = Typography; interface StorageResponse { default: string; local: { root: string; url: string; visibility: string; }; s3: { key: string; secret: string; region: string; bucket: string; url: string; endpoint: string; use_path_style_endpoint: boolean; }; ftp: { host: string; username: string; password: string; port: number; root: string; passive: boolean; ssl: boolean; timeout: number; }; sftp: { host: string; username: string; password: string; port: number; root: string; timeout: number; private_key: string; passphrase: string; }; } const StorageConfig: React.FC = () => { const { t } = useTranslation(); const formRef = useRef(null); const [form] = Form.useForm(); const [testing, setTesting] = useState(false); const [selectedDisk, setSelectedDisk] = useState('local'); const driverOptions = [ { label: t('system.storage.driver.local'), value: 'local' }, { label: t('system.storage.driver.s3'), value: 's3' }, { label: t('system.storage.driver.ftp'), value: 'ftp' }, { label: t('system.storage.driver.sftp'), value: 'sftp' }, ]; const columns: FormColumn[] = [ { dataIndex: 'default', valueType: 'radioButton', title: t('system.storage.driver'), fieldProps: { options: driverOptions }, required: true, colProps: { span: 24 } }, // 本地存储配置 { fieldRender: () => {t('system.storage.local.title')}, dependency: { dependencies: ['default'], visible: (values) => values.default === 'local' }, colProps: { span: 24 }, noStyle: true }, { dataIndex: ['local', 'url'], valueType: 'text', title: t('system.storage.local.url'), fieldProps: { placeholder: t('system.storage.local.url.placeholder'), }, tooltip: t('system.storage.local.url.tooltip'), colProps: { span: 24 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'local' } }, // S3 配置 { fieldRender: () => {t('system.storage.s3.title')}, dependency: { dependencies: ['default'], visible: (values) => values.default === 's3' }, colProps: { span: 24 }, noStyle: true }, { dataIndex: ['s3', 'key'], valueType: 'text', title: t('system.storage.s3.key'), fieldProps: { placeholder: t('system.storage.s3.key.placeholder'), }, required: true, colProps: { span: 12 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 's3' } }, { dataIndex: ['s3', 'secret'], valueType: 'password', title: t('system.storage.s3.secret'), fieldProps: { placeholder: t('system.storage.s3.secret.placeholder'), }, required: true, colProps: { span: 12 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 's3' } }, { dataIndex: ['s3', 'region'], valueType: 'text', title: t('system.storage.s3.region'), fieldProps: { placeholder: t('system.storage.s3.region.placeholder'), }, required: true, colProps: { span: 12 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 's3' } }, { dataIndex: ['s3', 'bucket'], valueType: 'text', title: t('system.storage.s3.bucket'), fieldProps: { placeholder: t('system.storage.s3.bucket.placeholder'), }, required: true, colProps: { span: 12 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 's3' } }, { dataIndex: ['s3', 'endpoint'], valueType: 'text', title: t('system.storage.s3.endpoint'), fieldProps: { placeholder: t('system.storage.s3.endpoint.placeholder'), }, tooltip: t('system.storage.s3.endpoint.tooltip'), colProps: { span: 12 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 's3' } }, { dataIndex: ['s3', 'url'], valueType: 'text', title: t('system.storage.s3.url'), fieldProps: { placeholder: t('system.storage.s3.url.placeholder'), }, tooltip: t('system.storage.s3.url.tooltip'), colProps: { span: 12 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 's3' } }, { dataIndex: ['s3', 'use_path_style_endpoint'], valueType: 'switch', title: t('system.storage.s3.path_style'), tooltip: t('system.storage.s3.path_style.tooltip'), colProps: { span: 12 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 's3' } }, // FTP 配置 { fieldRender: () => {t('system.storage.ftp.title')}, dependency: { dependencies: ['default'], visible: (values) => values.default === 'ftp' }, colProps: { span: 24 }, noStyle: true }, { dataIndex: ['ftp', 'host'], valueType: 'text', title: t('system.storage.ftp.host'), fieldProps: { placeholder: t('system.storage.ftp.host.placeholder'), }, required: true, colProps: { span: 16 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'ftp' } }, { dataIndex: ['ftp', 'port'], valueType: 'digit', title: t('system.storage.ftp.port'), fieldProps: { placeholder: t('system.storage.ftp.port.placeholder'), }, colProps: { span: 8 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'ftp' } }, { dataIndex: ['ftp', 'username'], valueType: 'text', title: t('system.storage.ftp.username'), fieldProps: { placeholder: t('system.storage.ftp.username.placeholder'), }, required: true, colProps: { span: 12 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'ftp' } }, { dataIndex: ['ftp', 'password'], valueType: 'password', title: t('system.storage.ftp.password'), fieldProps: { placeholder: t('system.storage.ftp.password.placeholder'), }, required: true, colProps: { span: 12 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'ftp' } }, { dataIndex: ['ftp', 'root'], valueType: 'text', title: t('system.storage.ftp.root'), fieldProps: { placeholder: t('system.storage.ftp.root.placeholder'), }, tooltip: t('system.storage.ftp.root.tooltip'), colProps: { span: 12 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'ftp' } }, { dataIndex: ['ftp', 'timeout'], valueType: 'digit', title: t('system.storage.ftp.timeout'), fieldProps: { placeholder: t('system.storage.ftp.timeout.placeholder'), addonAfter: t('system.storage.ftp.timeout.suffix') }, colProps: { span: 12 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'ftp' } }, { dataIndex: ['ftp', 'passive'], valueType: 'switch', title: t('system.storage.ftp.passive'), tooltip: t('system.storage.ftp.passive.tooltip'), colProps: { span: 8 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'ftp' } }, { dataIndex: ['ftp', 'ssl'], valueType: 'switch', title: t('system.storage.ftp.ssl'), tooltip: t('system.storage.ftp.ssl.tooltip'), colProps: { span: 8 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'ftp' } }, // SFTP 配置 { fieldRender: () => {t('system.storage.sftp.title')}, dependency: { dependencies: ['default'], visible: (values) => values.default === 'sftp' }, colProps: { span: 24 }, noStyle: true }, { dataIndex: ['sftp', 'host'], valueType: 'text', title: t('system.storage.sftp.host'), fieldProps: { placeholder: t('system.storage.sftp.host.placeholder'), }, required: true, colProps: { span: 16 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'sftp' } }, { dataIndex: ['sftp', 'port'], valueType: 'digit', title: t('system.storage.sftp.port'), fieldProps: { placeholder: t('system.storage.sftp.port.placeholder'), }, colProps: { span: 8 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'sftp' } }, { dataIndex: ['sftp', 'username'], valueType: 'text', title: t('system.storage.sftp.username'), fieldProps: { placeholder: t('system.storage.sftp.username.placeholder'), }, required: true, colProps: { span: 12 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'sftp' } }, { dataIndex: ['sftp', 'password'], valueType: 'password', title: t('system.storage.sftp.password'), fieldProps: { placeholder: t('system.storage.sftp.password.placeholder'), }, tooltip: t('system.storage.sftp.password.tooltip'), colProps: { span: 12 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'sftp' } }, { dataIndex: ['sftp', 'root'], valueType: 'text', title: t('system.storage.sftp.root'), fieldProps: { placeholder: t('system.storage.sftp.root.placeholder'), }, tooltip: t('system.storage.sftp.root.tooltip'), colProps: { span: 12 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'sftp' } }, { dataIndex: ['sftp', 'timeout'], valueType: 'digit', title: t('system.storage.sftp.timeout'), fieldProps: { placeholder: t('system.storage.sftp.timeout.placeholder'), addonAfter: t('system.storage.sftp.timeout.suffix') }, colProps: { span: 12 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'sftp' } }, { dataIndex: ['sftp', 'private_key'], valueType: 'textarea', title: t('system.storage.sftp.private_key'), fieldProps: { placeholder: t('system.storage.sftp.private_key.placeholder'), rows: 4 }, tooltip: t('system.storage.sftp.private_key.tooltip'), colProps: { span: 24 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'sftp' } }, { dataIndex: ['sftp', 'passphrase'], valueType: 'password', title: t('system.storage.sftp.passphrase'), fieldProps: { placeholder: t('system.storage.sftp.passphrase.placeholder'), }, tooltip: t('system.storage.sftp.passphrase.tooltip'), colProps: { span: 24 }, dependency: { dependencies: ['default'], visible: (values) => values.default === 'sftp' } } ]; useEffect(() => { loadConfig(); }, []); const loadConfig = async () => { const { data } = await getStorageConfig(); if (data.success) { const configData = data.data as StorageResponse; form.setFieldsValue(configData); setSelectedDisk(configData.default || 'local'); } }; const onFinish = async (values: any) => { await saveStorageConfig(values); message.success(t('system.storage.save.success')); }; const onValuesChange = (changedValues: any) => { if (changedValues.default) { setSelectedDisk(changedValues.default); } }; const onTestConnection = async () => { try { setTesting(true); await testStorageConnection(selectedDisk); message.success(t('system.storage.test.success')); } finally { setTesting(false); } }; return ( <>
{t('system.storage.page.title')} {t('system.storage.page.description')}