From 72a874516bd8c0a17a815c6671896c238f23cb5f Mon Sep 17 00:00:00 2001
From: sunqh <253801736@qq.com>
Date: Tue, 14 Apr 2026 11:14:48 +0800
Subject: [PATCH] =?UTF-8?q?=E9=85=8D=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/pages/Config/index.tsx | 337 ++++++++++++++++++++++++++++++-------
1 file changed, 278 insertions(+), 59 deletions(-)
diff --git a/src/pages/Config/index.tsx b/src/pages/Config/index.tsx
index 480491b..fdd37f7 100644
--- a/src/pages/Config/index.tsx
+++ b/src/pages/Config/index.tsx
@@ -1,4 +1,4 @@
-import { FileTextOutlined, UploadOutlined } from '@ant-design/icons';
+import { DeleteOutlined, FileTextOutlined } from '@ant-design/icons';
import {
Button,
Checkbox,
@@ -10,14 +10,49 @@ import {
Modal,
message,
Select,
+ Space,
Switch,
Table,
Tag,
- Upload,
} from 'antd';
import dayjs from 'dayjs';
import { useEffect, useState } from 'react';
+const EditableForm = ({ value = [], onChange, schema }: any) => {
+ // 兼容性处理:从 columns 中提取字段定义
+ const fields = schema?.columns || [];
+
+ // 假设 form 模式操作的是数组的第一个对象
+ const data = value[0] || {};
+
+ const handleFieldChange = (dataIndex: string, val: any) => {
+ const newData = [{ ...data, [dataIndex]: val }];
+ onChange?.(newData); // 保持数据结构依然是 [{...}]
+ };
+
+ return (
+
+ {fields.map((col: any) => (
+
+
{col.title}
+
handleFieldChange(col.dataIndex, e.target.value)}
+ />
+
+ ))}
+
+ );
+};
+
// --- 复杂类型:可编辑表格组件 (用于分段价格等 array + table 模式) ---
interface EditableTableProps {
value?: any[];
@@ -31,19 +66,18 @@ interface EditableTableProps {
};
}
const EditableTable = ({ value = [], onChange, schema }: EditableTableProps) => {
- const columns = (schema?.columns || []).map((col: any) => ({
+ // --- 1. 字段定义 ---
+ const baseColumns = (schema?.columns || []).map((col: any) => ({
title: col.title,
dataIndex: col.dataIndex,
render: (text: any, record: any, index: number) => {
const inputProps = {
value: text,
- // 这里 val 可能是 Event 对象也可能是数值,antd 的 InputNumber 直接返回 val
- // 普通 Input 返回 e.target.value
onChange: (e: any) => {
const val = e?.target ? e.target.value : e;
const newData = [...value];
newData[index] = { ...newData[index], [col.dataIndex]: val };
- onChange?.(newData); // 使用可选链调用,安全消灭波浪线
+ onChange?.(newData);
},
};
@@ -51,25 +85,51 @@ const EditableTable = ({ value = [], onChange, schema }: EditableTableProps) =>
},
}));
+ // --- 2. 操作列 (删除) ---
+ const columns = [
+ {
+ title: '操作',
+ width: 70,
+ align: 'center' as const,
+ render: (_: any, __: any, index: number) => (
+ }
+ onClick={() => {
+ const newData = [...value];
+ newData.splice(index, 1);
+ onChange?.(newData);
+ }}
+ />
+ ),
+ },
+ ...baseColumns,
+ ];
+
return (
-
+
+ {/* --- 3. 顶部操作栏 (全部对齐左侧) --- */}
+
+
+
+ 共 {value.length} 条记录
+
+
+ {/* --- 4. 表格主体 --- */}
i.toString()}
+ scroll={{ y: 300 }}
/>
-
);
};
@@ -110,12 +170,12 @@ const ConfigList = () => {
label: '通知方式',
type: 'array',
value: [1, 2],
- array_config: '{"mode":"checkbox"}',
+ array_config: '{"mode":"checkbox", "multiple":"true"}',
options: '[{"label":"短信","value":1},{"label":"邮件","value":2}]',
},
{ id: 8, config_key: 'birth_date', label: '日期', type: 'date', value: '2026-01-01' },
{ id: 9, config_key: 'expire_time', label: '时间', type: 'datetime', value: '2026-01-01 12:00:00' },
- { id: 10, config_key: 'logo', label: 'Logo', type: 'file', value: [{ url: '/logo.png', name: 'logo.png' }] },
+ //{ id: 10, config_key: 'logo', label: 'Logo', type: 'file', value: [{ url: '/logo.png', name: 'logo.png' }] },
{
id: 11,
config_key: 'price',
@@ -130,6 +190,45 @@ const ConfigList = () => {
schema:
'{"columns":[{"title":"最小","dataIndex":"min","type":"int"},{"title":"最大","dataIndex":"max","type":"int"},{"title":"价格","dataIndex":"price","type":"int"}]}',
},
+ {
+ id: 12,
+ config_key: 'admin_info',
+ label: '管理员信息',
+ type: 'array',
+ value: [{ name: '张三', phone: '李四' }],
+ array_config: '{"mode":"form"}',
+ schema:
+ '{"columns":[{"title":"管理员姓名","dataIndex":"name","type":"string","placeholder":"请输入姓名"},{"title":"管理员手机号","dataIndex":"phone","type":"string","placeholder":"请输入手机号"}]}',
+ },
+ {
+ id: 13,
+ config_key: 'audit_status',
+ label: '审核状态',
+ type: 'select',
+ value: 1,
+ options: '[{"label":"待审核","value":1},{"label":"通过","value":2},{"label":"驳回","value":3}]',
+ props: '{"placeholder":"请选择状态"}',
+ },
+ {
+ id: 14,
+ config_key: 'user_roles',
+ label: '关联角色',
+ type: 'array',
+ value: ['admin'], // 初始选中的值
+ array_config: '{"mode":"select", "multiple": true}', // 核心标志位
+ options:
+ '[{"label":"超级管理员","value":"admin"},{"label":"运营","value":"editor"},{"label":"财务","value":"finance"}]',
+ },
+ {
+ id: 15,
+ config_key: 'single_check',
+ label: '单选确认',
+ type: 'array',
+ value: [1],
+ // 增加 single 属性
+ array_config: '{"mode":"checkbox", "multiple":"false"}',
+ options: '[{"label":"选项A","value":1},{"label":"选项B","value":2}]',
+ },
];
setData(
@@ -153,7 +252,7 @@ const ConfigList = () => {
const { type, props, options, array_config, schema } = item;
// 1. 获取该配置项当前的实时值 (用于 tags 模式下合并临时选项)
- const currentValue = form.getFieldValue(item.config_key) || [];
+ //const currentValue = form.getFieldValue(item.config_key) || [];
switch (type) {
case 'string':
@@ -162,18 +261,20 @@ const ConfigList = () => {
return ;
case 'int':
return ;
+ case 'select':
+ return ;
case 'bool':
return ;
case 'date':
return ;
case 'datetime':
return ;
- case 'file':
- return (
- false}>
- }>选择文件
-
- );
+ // case 'file':
+ // return (
+ // false}>
+ // }>选择文件
+ //
+ // );
case 'array': {
const mode = array_config?.mode;
@@ -184,43 +285,93 @@ const ConfigList = () => {
return ;
}
- // 2. 处理复选框模式 (Checkbox)
- if (mode === 'checkbox') {
- return ;
- }
-
- // 3. 处理下拉选择与标签模式 (Select / Tags)
- if (mode === 'select' || mode === 'tags') {
- // 【关键】始终以原始 options 为基准,防止预设选项丢失
- const mergedOptions = [...(options || [])];
-
- // 如果是 tags 模式,需要把当前已输入但不在 options 里的值临时加入下拉列表
- // 这样可以保证“已选即显示”,但不会影响原始 options 的持久性
- if (mode === 'tags' && Array.isArray(currentValue)) {
- currentValue.forEach((v) => {
- const exists = mergedOptions.some((opt) => opt.value === v);
- if (!exists) {
- // 如果是用户新输入的,动态补全到当前渲染列表里
- mergedOptions.push({ label: String(v), value: v });
- }
- });
- }
-
+ if (mode === 'form') {
return (
-