|
|
@@ -11,6 +11,8 @@ import {
|
|
|
Form,
|
|
|
Input,
|
|
|
Space,
|
|
|
+ Switch,
|
|
|
+ Upload,
|
|
|
} from "antd";
|
|
|
import type { TableProps } from "antd";
|
|
|
import {
|
|
|
@@ -19,7 +21,10 @@ import {
|
|
|
DeleteOutlined,
|
|
|
ReloadOutlined,
|
|
|
SearchOutlined,
|
|
|
+ UploadOutlined,
|
|
|
+ LoadingOutlined,
|
|
|
} from "@ant-design/icons";
|
|
|
+import type { RcFile } from "antd/es/upload";
|
|
|
import type { ConfigForm, ConfigItem } from "@/api/config";
|
|
|
import {
|
|
|
addConfig,
|
|
|
@@ -28,6 +33,7 @@ import {
|
|
|
getConfigPage,
|
|
|
updateConfig,
|
|
|
} from "@/api/config";
|
|
|
+import { uploadImage } from "@/api/storage";
|
|
|
|
|
|
const { Title, Text } = Typography;
|
|
|
const { TextArea } = Input;
|
|
|
@@ -39,6 +45,8 @@ export function ConfigPage() {
|
|
|
const [submitting, setSubmitting] = useState(false);
|
|
|
const [modalOpen, setModalOpen] = useState(false);
|
|
|
const [editingKey, setEditingKey] = useState<string | null>(null);
|
|
|
+ const [advancedValue, setAdvancedValue] = useState(false);
|
|
|
+ const [uploading, setUploading] = useState(false);
|
|
|
const [total, setTotal] = useState(0);
|
|
|
const [keyword, setKeyword] = useState("");
|
|
|
const [query, setQuery] = useState({ page: 1, size: 10, keyword: undefined as string | undefined });
|
|
|
@@ -76,12 +84,14 @@ export function ConfigPage() {
|
|
|
|
|
|
function openAdd() {
|
|
|
setEditingKey(null);
|
|
|
+ setAdvancedValue(false);
|
|
|
form.resetFields();
|
|
|
setModalOpen(true);
|
|
|
}
|
|
|
|
|
|
async function openEdit(record: ConfigItem) {
|
|
|
setEditingKey(record.configKey);
|
|
|
+ setAdvancedValue(false);
|
|
|
setModalOpen(true);
|
|
|
try {
|
|
|
const detail = await getConfig(record.configKey);
|
|
|
@@ -97,6 +107,22 @@ export function ConfigPage() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ async function handleValueUpload(file: RcFile) {
|
|
|
+ setUploading(true);
|
|
|
+ try {
|
|
|
+ const url = await uploadImage(file, "config/value/");
|
|
|
+ const currentValue = form.getFieldValue("configValue") || "";
|
|
|
+ const nextValue = currentValue ? `${currentValue}\n${url}` : url;
|
|
|
+ form.setFieldValue("configValue", nextValue);
|
|
|
+ message.success(t("config.uploadAppendSuccess"));
|
|
|
+ } catch {
|
|
|
+ message.error(t("upload.failed"));
|
|
|
+ } finally {
|
|
|
+ setUploading(false);
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
async function handleSubmit() {
|
|
|
try {
|
|
|
const values = await form.validateFields();
|
|
|
@@ -110,6 +136,7 @@ export function ConfigPage() {
|
|
|
}
|
|
|
setModalOpen(false);
|
|
|
setEditingKey(null);
|
|
|
+ setAdvancedValue(false);
|
|
|
form.resetFields();
|
|
|
fetchData();
|
|
|
} catch {
|
|
|
@@ -268,6 +295,7 @@ export function ConfigPage() {
|
|
|
onCancel={() => {
|
|
|
setModalOpen(false);
|
|
|
setEditingKey(null);
|
|
|
+ setAdvancedValue(false);
|
|
|
form.resetFields();
|
|
|
}}
|
|
|
onOk={handleSubmit}
|
|
|
@@ -285,11 +313,43 @@ export function ConfigPage() {
|
|
|
disabled={!!editingKey}
|
|
|
/>
|
|
|
</Form.Item>
|
|
|
- <Form.Item name="configValue" label={t("config.fieldValue")}>
|
|
|
- <TextArea
|
|
|
- rows={4}
|
|
|
- placeholder={t("config.valuePlaceholder")}
|
|
|
- />
|
|
|
+ <Form.Item
|
|
|
+ label={(
|
|
|
+ <div className="flex items-center gap-3">
|
|
|
+ <span>{t("config.fieldValue")}</span>
|
|
|
+ <div className="flex items-center gap-2">
|
|
|
+ <span className="text-xs text-gray-500">{t("config.advanced")}</span>
|
|
|
+ <Switch size="small" checked={advancedValue} onChange={setAdvancedValue} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ >
|
|
|
+ <div>
|
|
|
+ <Form.Item name="configValue" noStyle>
|
|
|
+ <TextArea
|
|
|
+ rows={4}
|
|
|
+ placeholder={t("config.valuePlaceholder")}
|
|
|
+ />
|
|
|
+ </Form.Item>
|
|
|
+ {advancedValue && (
|
|
|
+ <div className="mt-3 flex items-center gap-3 flex-wrap">
|
|
|
+ <Upload
|
|
|
+ showUploadList={false}
|
|
|
+ beforeUpload={handleValueUpload}
|
|
|
+ >
|
|
|
+ <Button
|
|
|
+ icon={uploading ? <LoadingOutlined /> : <UploadOutlined />}
|
|
|
+ loading={uploading}
|
|
|
+ >
|
|
|
+ {t("config.appendUploadBtn")}
|
|
|
+ </Button>
|
|
|
+ </Upload>
|
|
|
+ <Text type="secondary" style={{ fontSize: 12 }}>
|
|
|
+ {t("config.appendUploadTip")}
|
|
|
+ </Text>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
</Form.Item>
|
|
|
<Form.Item name="remark" label={t("config.fieldRemark")}>
|
|
|
<TextArea
|