From 1000c42b6aca9c0eed21ecf0148da22a2caa5b9a Mon Sep 17 00:00:00 2001 From: tikkhun Date: Thu, 27 Nov 2025 19:09:26 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=AD=97=E5=85=B8=E7=AE=A1=E7=90=86):=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AD=97=E5=85=B8=E7=AE=A1=E7=90=86=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加字典管理页面及相关权限控制 修改产品口味列表显示字段 --- .umirc.ts | 35 ++- src/access.ts | 2 + src/pages/Dict/List/index.tsx | 350 ++++++++++++++++++++++++++++ src/pages/Product/Flavors/index.tsx | 5 +- 4 files changed, 378 insertions(+), 14 deletions(-) create mode 100644 src/pages/Dict/List/index.tsx diff --git a/.umirc.ts b/.umirc.ts index 950faba..44454a2 100644 --- a/.umirc.ts +++ b/.umirc.ts @@ -43,18 +43,31 @@ export default defineConfig({ }, ], }, + { - name: '站点管理', - path: '/site', - access: 'canSeeSite', - routes: [ - { - name: '站点列表', - path: '/site/list', - component: './Site/List', - }, - ], - }, + name: '字典管理', + path: '/dict', + access: 'canSeeDict', + routes: [ + { + name: '字典列表', + path: '/dict/list', + component: './Dict/List', + }, + ], + }, + { + name: '站点管理', + path: '/site', + access: 'canSeeSite', + routes: [ + { + name: '站点列表', + path: '/site/list', + component: './Site/List', + }, + ], + }, { name: '商品管理', path: '/product', diff --git a/src/access.ts b/src/access.ts index c6d252a..cda1792 100644 --- a/src/access.ts +++ b/src/access.ts @@ -10,6 +10,7 @@ export default (initialState: any) => { const canSeeLogistics = (isSuper || isAdmin) || (initialState?.user?.permissions?.includes('logistics') ?? false); const canSeeStatistics = (isSuper || isAdmin) || (initialState?.user?.permissions?.includes('statistics') ?? false); const canSeeSite = (isSuper || isAdmin) || (initialState?.user?.permissions?.includes('site') ?? false); + const canSeeDict = (isSuper || isAdmin) || (initialState?.user?.permissions?.includes('dict') ?? false); return { canSeeOrganiza, @@ -20,5 +21,6 @@ export default (initialState: any) => { canSeeLogistics, canSeeStatistics, canSeeSite, + canSeeDict, }; }; diff --git a/src/pages/Dict/List/index.tsx b/src/pages/Dict/List/index.tsx new file mode 100644 index 0000000..49d01f5 --- /dev/null +++ b/src/pages/Dict/List/index.tsx @@ -0,0 +1,350 @@ +import { PageContainer } from '@ant-design/pro-components'; +import { Input, Button, Table, Layout, Space, Modal, message, Form, Upload } from 'antd'; +import React, { useState, useEffect } from 'react'; +import { request } from '@umijs/max'; +import { UploadOutlined } from '@ant-design/icons'; + +const { Sider, Content } = Layout; + +const DictPage: React.FC = () => { + // 左侧字典列表的状态 + const [dicts, setDicts] = useState([]); + const [loadingDicts, setLoadingDicts] = useState(false); + const [searchText, setSearchText] = useState(''); + const [selectedDict, setSelectedDict] = useState(null); + + // 右侧字典项列表的状态 + const [dictItems, setDictItems] = useState([]); + const [loadingDictItems, setLoadingDictItems] = useState(false); + + // 控制添加字典模态框的显示 + const [isAddDictModalVisible, setIsAddDictModalVisible] = useState(false); + const [newDictName, setNewDictName] = useState(''); + const [newDictTitle, setNewDictTitle] = useState(''); + const [editingDict, setEditingDict] = useState(null); + + // 控制字典项模态框的显示 + const [isDictItemModalVisible, setIsDictItemModalVisible] = useState(false); + const [editingDictItem, setEditingDictItem] = useState(null); + const [dictItemForm, setDictItemForm] = useState({ name: '', title: '', value: '' }); + + // 获取字典列表 + const fetchDicts = async (title?: string) => { + setLoadingDicts(true); + try { + const res = await request('/api/dicts', { params: { title } }); + if (res) { + setDicts(res); + } + } catch (error) { + message.error('获取字典列表失败'); + } + setLoadingDicts(false); + }; + + // 获取字典项列表 + const fetchDictItems = async (dictId?: number) => { + setLoadingDictItems(true); + try { + const res = await request('/api/dict-items', { params: { dictId } }); + if (res) { + setDictItems(res); + } + } catch (error) { + message.error('获取字典项列表失败'); + } + setLoadingDictItems(false); + }; + + // 组件加载时获取数据 + useEffect(() => { + fetchDicts(); + fetchDictItems(); + }, []); + + // 当选择的字典变化时,重新获取字典项 + useEffect(() => { + fetchDictItems(selectedDict?.id); + }, [selectedDict]); + + // 处理字典搜索 + const handleSearch = (value: string) => { + fetchDicts(value); + }; + + // 处理添加字典 + const handleAddDict = async () => { + if (!newDictName || !newDictTitle) { + message.warning('请输入字典名称和标题'); + return; + } + try { + if (editingDict) { + await request(`/api/dicts/${editingDict.id}`, { + method: 'PUT', + data: { name: newDictName, title: newDictTitle }, + }); + message.success('更新成功'); + } else { + await request('/api/dicts', { + method: 'POST', + data: { name: newDictName, title: newDictTitle }, + }); + message.success('添加成功'); + } + setIsAddDictModalVisible(false); + setNewDictName(''); + setNewDictTitle(''); + setEditingDict(null); + fetchDicts(); // 重新获取字典列表 + } catch (error) { + message.error(editingDict ? '更新失败' : '添加失败'); + } + }; + + const handleEditDict = (dict: any) => { + setEditingDict(dict); + setNewDictName(dict.name); + setNewDictTitle(dict.title); + setIsAddDictModalVisible(true); + }; + + // 打开添加字典项模态框 + const handleAddDictItem = () => { + setEditingDictItem(null); + setDictItemForm({ name: '', title: '', value: '' }); + setIsDictItemModalVisible(true); + }; + + // 打开编辑字典项模态框 + const handleEditDictItem = (item: any) => { + setEditingDictItem(item); + setDictItemForm(item); + setIsDictItemModalVisible(true); + }; + + // 处理字典项表单提交(添加/编辑) + const handleDictItemFormSubmit = async () => { + if (!dictItemForm.name || !dictItemForm.title) { + message.warning('请输入名称和标题'); + return; + } + try { + if (editingDictItem) { + // 编辑 + await request(`/api/dict-items/${editingDictItem.id}`, { + method: 'PUT', + data: dictItemForm, + }); + message.success('更新成功'); + } else { + // 添加 + await request('/api/dict-items', { + method: 'POST', + data: { ...dictItemForm, dictId: selectedDict.id }, + }); + message.success('添加成功'); + } + setIsDictItemModalVisible(false); + fetchDictItems(selectedDict.id); + } catch (error) { + message.error(editingDictItem ? '更新失败' : '添加失败'); + } + }; + + // 处理删除字典项 + const handleDeleteDictItem = async (itemId: number) => { + try { + await request(`/api/dict-items/${itemId}`, { method: 'DELETE' }); + message.success('删除成功'); + fetchDictItems(selectedDict.id); + } catch (error) { + message.error('删除失败'); + } + }; + + // 处理删除字典 + const handleDeleteDict = async (dictId: number) => { + try { + await request(`/api/dicts/${dictId}`, { method: 'DELETE' }); + message.success('删除成功'); + fetchDicts(); // 重新获取字典列表 + // 如果删除的是当前选中的字典,则清空右侧列表 + if (selectedDict?.id === dictId) { + setSelectedDict(null); + setDictItems([]); + } + } catch (error) { + message.error('删除失败'); + } + }; + + // 左侧字典列表的列定义 + const dictColumns = [ + + { + title: '名称', + dataIndex: 'name', + key: 'name', + }, + { + title: '标题', + dataIndex: 'title', + key: 'title', + }, + { + title: '操作', + key: 'action', + render: (_: any, record: any) => ( + + + + + ), + }, + ]; + + // 右侧字典项列表的列定义 + const dictItemColumns = [ + { + title: '名称', + dataIndex: 'name', + key: 'name', + }, + { + title: '标题', + dataIndex: 'title', + key: 'title', + }, + { + title: '操作', + key: 'action', + render: (_: any, record: any) => ( + + + + + ), + }, + ]; + + return ( + + + + + setSearchText(e.target.value)} enterButton allowClear /> + + + { + if (info.file.status === 'done') { + message.success(`${info.file.name} 文件上传成功`); + fetchDicts(); + } else if (info.file.status === 'error') { + message.error(`${info.file.name} 文件上传失败`); + } + }} + > + + + + + ({ + onClick: () => { + // 如果点击的是当前已选中的行,则取消选择 + if (selectedDict?.id === record.id) { + setSelectedDict(null); + } else { + setSelectedDict(record); + } + }, + })} + rowClassName={record => (selectedDict?.id === record.id ? 'ant-table-row-selected' : '')} + pagination={false} + /> + + + + + + + { + if (info.file.status === 'done') { + message.success(`${info.file.name} 文件上传成功`); + fetchDictItems(selectedDict.id); + } else if (info.file.status === 'error') { + message.error(`${info.file.name} 文件上传失败`); + } + }} + > + + + + +
+ + + + + setIsDictItemModalVisible(false)} + > +
+ + setDictItemForm({ ...dictItemForm, name: e.target.value })} /> + + + setDictItemForm({ ...dictItemForm, title: e.target.value })} /> + + + setDictItemForm({ ...dictItemForm, value: e.target.value })} /> + + +
+ + setIsAddDictModalVisible(false)} + > +
+ + setNewDictName(e.target.value)} /> + + + setNewDictTitle(e.target.value)} /> + + +
+ + ); +}; + +export default DictPage; diff --git a/src/pages/Product/Flavors/index.tsx b/src/pages/Product/Flavors/index.tsx index e2688f7..358399e 100644 --- a/src/pages/Product/Flavors/index.tsx +++ b/src/pages/Product/Flavors/index.tsx @@ -35,9 +35,8 @@ const List: React.FC = () => { }, }, { - title: '标识', - dataIndex: 'unique_key', - hideInSearch: true, + title: '显示名称', + dataIndex: 'title', }, { title: '更新时间',