소스 검색

系统所有页面实现搜索功能,表头,按钮,菜单的英文适配

wyn 4 달 전
부모
커밋
55bf25720e

+ 120 - 23
src/Dashboard.tsx

@@ -24,6 +24,11 @@ export default function Dashboard() {
   const navigate = useNavigate();
   const location = useLocation();
   const { t, i18n } = useTranslation();
+  
+  // 监听语言变化,强制组件重新渲染
+  useEffect(() => {
+    // 当语言切换时,这个 effect 会重新执行,从而触发组件更新
+  }, [i18n.language]);
   const [activeMenu, setActiveMenu] = useState('dashboard');
   const [activeSubMenu, setActiveSubMenu] = useState('menuManagement');
   const [showUserMenu, setShowUserMenu] = useState(false);
@@ -38,7 +43,10 @@ export default function Dashboard() {
   // 切换语言
   const toggleLanguage = () => {
     const newLang = i18n.language === 'zh' ? 'en' : 'zh';
-    i18n.changeLanguage(newLang);
+    i18n.changeLanguage(newLang).then(() => {
+      // 语言切换后,强制组件更新以确保菜单重新渲染
+      window.dispatchEvent(new Event('languagechange'));
+    });
   };
 
   // 登出处理
@@ -61,6 +69,32 @@ export default function Dashboard() {
 
   // 后端菜单路径到前端菜单key的映射函数
   const mapBackendPathToFrontendKey = (path: string): string | null => {
+    // 处理简短路径(不带斜杠的路径,如 "menuManagement", "dept", "post" 等)
+    // 这些通常是系统配置下的子菜单路径
+    if (!path.startsWith('/')) {
+      // 系统配置子菜单路径
+      if (path === 'menuManagement' || path === 'menu') return 'menuManagement';
+      if (path === 'dept' || path === 'department') return 'departmentManagement';
+      if (path === 'post' || path === 'marsdept' || path === 'position') return 'positionManagement';
+      if (path === 'role') return 'roleManagement';
+      if (path === 'dict' || path === 'dictionary') return 'dictionaryManagement';
+      if (path === 'cabinet') return 'cabinetManagement';
+      
+      // 硬件管理子菜单路径
+      if (path === 'hwcabinet' || path === 'cabinet') return 'cabinet';
+      if (path === 'key') return 'key';
+      if (path === 'lock' || path === 'padlock') return 'padlock';
+      if (path === 'portability' || path === 'portable') return 'portable';
+      
+      // 隔离作业子菜单路径
+      if (path === 'processTemplate' || path === 'processTemplate') return 'processTemplate';
+      if (path === 'job') return 'workManagement';
+      if (path === 'form') return 'formManagement';
+      if (path === 'taskmanagement' || path === 'taskManagement') return 'taskManagement';
+      if (path === 'mytask' || path === 'myTask') return 'myTask';
+      if (path === 'sop') return 'sopManagement';
+    }
+    
     // 客户端系统路径(支持 /clientSystem/xxx 格式)
     if (path.startsWith('/clientSystem')) {
       // 隔离作业子菜单路径(优先处理)
@@ -83,11 +117,11 @@ export default function Dashboard() {
     
     // 系统管理相关
     if (path === '/system' || path.startsWith('/system')) {
-      if (path.includes('menu') || path.endsWith('/menu')) return 'menuManagement';
-      if (path.includes('dept') || path.endsWith('/dept')) return 'departmentManagement';
-      if (path.includes('post') || path.includes('marsdept') || path.endsWith('/post') || path.endsWith('/marsdept')) return 'positionManagement';
+      if (path.includes('menu') || path.endsWith('/menu') || path.includes('/menuManagement')) return 'menuManagement';
+      if (path.includes('dept') || path.endsWith('/dept') || path.includes('/department')) return 'departmentManagement';
+      if (path.includes('post') || path.includes('marsdept') || path.endsWith('/post') || path.endsWith('/marsdept') || path.includes('/position')) return 'positionManagement';
       if (path.includes('role') || path.endsWith('/role')) return 'roleManagement';
-      if (path.includes('dict') || path.endsWith('/dict')) return 'dictionaryManagement';
+      if (path.includes('dict') || path.endsWith('/dict') || path.includes('/dictionary')) return 'dictionaryManagement';
       if (path.includes('cabinet') || path.endsWith('/cabinet')) return 'cabinetManagement';
       return 'systemConfig';
     }
@@ -101,10 +135,10 @@ export default function Dashboard() {
     
     // 硬件管理相关
     if (path === '/hw' || path.startsWith('/hw') || path === '/hardware' || path.startsWith('/hardware')) {
-      if (path.includes('cabinet') || path.includes('work')) return 'cabinet';
+      if (path.includes('hwcabinet') || (path.includes('cabinet') && !path.includes('system')) || path.includes('work')) return 'cabinet';
       if (path.includes('key') || path.includes('keys')) return 'key';
       if (path.includes('lock') || path.includes('lk') || path.includes('padlock')) return 'padlock';
-      if (path.includes('portable') || path.includes('rfid')) return 'portable';
+      if (path.includes('portability') || path.includes('portable') || path.includes('rfid')) return 'portable';
       return 'hardwareManagement';
     }
     
@@ -434,18 +468,44 @@ export default function Dashboard() {
                 } else {
                   childKey = 'isolationWork';
                 }
-              } else if (child.path.includes('/dept')) {
+              } else if (child.path.includes('/dept') || child.path === 'dept' || child.path === 'department') {
                 childKey = 'departmentManagement';
-              } else if (child.path.includes('/menu')) {
+              } else if (child.path.includes('/menu') || child.path === 'menuManagement' || child.path === 'menu') {
                 childKey = 'menuManagement';
-              } else if (child.path.includes('/post') || child.path.includes('/marsdept')) {
+              } else if (child.path.includes('/post') || child.path.includes('/marsdept') || child.path === 'post' || child.path === 'marsdept' || child.path === 'position') {
                 childKey = 'positionManagement';
-              } else if (child.path.includes('/role')) {
+              } else if (child.path.includes('/role') || child.path === 'role') {
                 childKey = 'roleManagement';
-              } else if (child.path.includes('/dict')) {
+              } else if (child.path.includes('/dict') || child.path === 'dict' || child.path === 'dictionary') {
                 childKey = 'dictionaryManagement';
-              } else if (child.path.includes('/cabinet')) {
+              } else if (child.path.includes('/cabinet') || child.path === 'cabinet') {
                 childKey = 'cabinetManagement';
+              } else if (child.path.includes('/hw') || child.path.includes('/hardware') || child.path === 'hwcabinet' || child.path === 'cabinet') {
+                // 硬件管理子菜单
+                if (child.path.includes('hwcabinet') || child.path === 'hwcabinet' || (child.path.includes('cabinet') && !child.path.includes('system'))) {
+                  childKey = 'cabinet';
+                } else if (child.path.includes('key') || child.path === 'key') {
+                  childKey = 'key';
+                } else if (child.path.includes('lock') || child.path === 'lock' || child.path.includes('padlock') || child.path === 'padlock') {
+                  childKey = 'padlock';
+                } else if (child.path.includes('portability') || child.path === 'portability' || child.path.includes('portable') || child.path === 'portable') {
+                  childKey = 'portable';
+                } else {
+                  childKey = 'cabinet'; // 默认
+                }
+              } else if (child.path === 'processTemplate' || child.path === 'processTemplate' || child.path.includes('processTemplate')) {
+                // 隔离作业子菜单路径推断
+                childKey = 'processTemplate';
+              } else if (child.path === 'job' || child.path.includes('/job') || child.path.endsWith('/job')) {
+                childKey = 'workManagement';
+              } else if (child.path === 'form' || child.path.includes('/form') || child.path.endsWith('/form')) {
+                childKey = 'formManagement';
+              } else if (child.path === 'taskmanagement' || child.path === 'taskManagement' || child.path.includes('taskmanagement') || child.path.includes('taskManagement')) {
+                childKey = 'taskManagement';
+              } else if (child.path === 'mytask' || child.path === 'myTask' || child.path.includes('mytask') || child.path.includes('myTask')) {
+                childKey = 'myTask';
+              } else if (child.path === 'sop' || child.path.includes('/sop') || child.path.endsWith('/sop')) {
+                childKey = 'sopManagement';
               } else {
                 // 如果无法推断,使用path作为key(去除特殊字符)
                 childKey = child.path.replace(/[^a-zA-Z0-9]/g, '_') || `child_${child.id}`;
@@ -506,7 +566,7 @@ export default function Dashboard() {
     // console.log('==================');
     
     return result;
-  }, []);
+  }, [i18n.language]);
 
   // 获取通知管理菜单信息(从后端菜单中查找)
   const notificationMenu = useMemo(() => {
@@ -880,7 +940,9 @@ export default function Dashboard() {
                             }`}
                           >
                             <Icon className={`w-4 h-4 ${isActive ? 'text-white' : ''}`} strokeWidth={2.5} />
-                            <span className={`text-sm ${isActive ? 'text-white' : ''}`}>{item.name || t(`nav.${item.key}`)}</span>
+                            <span className={`text-sm ${isActive ? 'text-white' : ''}`}>
+                              {t(`nav.${item.key}`, item.name || item.key)}
+                            </span>
                             <ChevronDown className={`w-3 h-3 transition-transform ${isDropdownOpen ? 'rotate-180' : ''} ${isActive ? 'text-white' : ''}`} />
                           </button>
                         </div>
@@ -959,7 +1021,9 @@ export default function Dashboard() {
                                     }`}>
                                       <IconComponent className="w-4 h-4" strokeWidth={2.5} />
                                     </div>
-                                    <span>{subItem.name || t(`systemConfig.${subItem.key}`)}</span>
+                                    <span>
+                                      {t(`systemConfig.${subItem.key}`, subItem.name || subItem.key)}
+                                    </span>
                                   </button>
                                 );
                               })}
@@ -1009,7 +1073,9 @@ export default function Dashboard() {
                       }`}
                     >
                       <Icon className={`w-4 h-4 ${isActive ? 'text-white' : ''}`} strokeWidth={2.5} />
-                      <span className={`text-sm ${isActive ? 'text-white' : ''}`}>{item.name || t(`nav.${item.key}`)}</span>
+                      <span className={`text-sm ${isActive ? 'text-white' : ''}`}>
+                        {t(`nav.${item.key}`, item.name || item.key)}
+                      </span>
                     </button>
                   );
                 })}
@@ -1024,7 +1090,7 @@ export default function Dashboard() {
                 className="flex items-center gap-2 px-3 py-2 hover:bg-gray-100 rounded-xl transition-colors group"
               >
                 <Globe className="w-4 h-4 text-gray-600 group-hover:rotate-12 transition-transform" />
-                <span className="text-sm text-gray-700">{i18n.language === 'zh' ? 'EN' : '中文'}</span>
+                <span className="text-sm text-gray-700">{i18n.language === 'zh' ? t('nav.switchToEnglish') : t('nav.switchToChinese')}</span>
               </button>
               
               {/* 通知管理 - 点击后进入页面,二级菜单在 tab 标签中显示 */}
@@ -1146,10 +1212,22 @@ export default function Dashboard() {
               <div className="flex items-center gap-2 overflow-x-auto min-w-0">
                 {filteredSubMenuConfig[activeMenu]?.map((item) => {
                   const isActive = activeSubMenu === item.key;
-                  const menuKey = activeMenu === 'userManagement' ? 'userManagement' : 
-                                 activeMenu === 'hardwareManagement' ? 'hardwareManagement' : 
-                                 activeMenu === 'isolationWork' ? 'isolationWork' :
-                                 activeMenu === 'notificationManagement' ? 'notificationManagement' : '';
+                  // 根据主菜单key确定翻译键前缀
+                  let menuKey = '';
+                  if (activeMenu === 'userManagement') {
+                    menuKey = 'userManagement';
+                  } else if (activeMenu === 'hardwareManagement') {
+                    menuKey = 'hardwareManagement';
+                  } else if (activeMenu === 'isolationWork' || item.key === 'processTemplate' || item.key === 'sopManagement' || item.key === 'workManagement' || item.key === 'processDesign' || item.key === 'formManagement' || item.key === 'myTask' || item.key === 'taskManagement') {
+                    menuKey = 'isolationWork';
+                  } else if (activeMenu === 'notificationManagement') {
+                    menuKey = 'notificationManagement';
+                  } else if (activeMenu === 'systemConfig') {
+                    menuKey = 'systemConfig';
+                  } else {
+                    // 默认尝试使用 activeMenu 作为翻译键前缀
+                    menuKey = activeMenu;
+                  }
                   return (
                     <button
                       key={item.key}
@@ -1168,7 +1246,26 @@ export default function Dashboard() {
                       }`}
                     >
                       <span className={isActive ? 'text-white' : ''}>
-                        {item.name || t(`${menuKey}.${item.key}`)}
+                        {(() => {
+                          // 优先尝试使用对应的翻译键
+                          let translationKey = '';
+                          if (menuKey) {
+                            translationKey = `${menuKey}.${item.key}`;
+                          } else if (activeMenu === 'isolationWork') {
+                            // 如果是隔离作业的子菜单,使用 isolationWork
+                            translationKey = `isolationWork.${item.key}`;
+                          } else if (activeMenu === 'notificationManagement') {
+                            // 如果是通知管理的子菜单,尝试使用 userManagement(因为通知管理通常在用户管理下)
+                            translationKey = `userManagement.${item.key}`;
+                          } else {
+                            // 默认尝试使用 activeMenu 作为前缀
+                            translationKey = `${activeMenu}.${item.key}`;
+                          }
+                          // 尝试翻译,如果翻译不存在则使用 item.name
+                          const translation = t(translationKey, item.name || item.key);
+                          // 如果翻译结果等于键本身(说明翻译不存在),使用后备值
+                          return translation === translationKey ? (item.name || item.key) : translation;
+                        })()}
                       </span>
                     </button>
                   );

+ 28 - 26
src/components/DepartmentManagement.tsx

@@ -15,8 +15,10 @@ import { DICT_TYPE, getIntDictOptions, getDictLabel } from '../utils/dict';
 import { dateFormatter } from '../utils/formatTime';
 import { handleTree, TreeNode } from '../utils/tree';
 import DeptForm, { DeptFormRef } from './dept/DeptForm';
+import { useTranslation } from 'react-i18next';
 
 export default function DepartmentManagement() {
+  const { t } = useTranslation();
   const [loading, setLoading] = useState(true);
   const [list, setList] = useState<TreeNode[]>([]);
   const [queryParams, setQueryParams] = useState({
@@ -136,24 +138,24 @@ export default function DepartmentManagement() {
   // 删除按钮操作
   const handleDelete = async (id: number, name: string) => {
     Modal.confirm({
-      title: '确认删除',
+      title: t('common.confirmDelete'),
       icon: <ExclamationCircleOutlined />,
       content: (
         <div>
-          <p>确定要删除部门 <strong>"{name}"</strong> 吗?</p>
-          <p style={{ color: '#ff4d4f', marginTop: '8px' }}>删除后无法恢复,请谨慎操作!</p>
+          <p>{t('common.confirmDeleteText')} <strong>"{name}"</strong>?</p>
+          <p style={{ color: '#ff4d4f', marginTop: '8px' }}>{t('common.confirmDeleteWarning')}</p>
         </div>
       ),
-      okText: '确定删除',
+      okText: t('common.confirmDelete'),
       okType: 'danger',
-      cancelText: '取消',
+      cancelText: t('common.cancel'),
       onOk: async () => {
         try {
           await deptApi.deleteDept(id);
-          toast.success('删除成功');
+          toast.success(t('common.deleteSuccess'));
           await getList();
         } catch (error: any) {
-          toast.error(error.message || '删除失败');
+          toast.error(error.message || t('common.deleteFailed'));
         }
       },
     });
@@ -187,10 +189,10 @@ export default function DepartmentManagement() {
         status: newStatus,
       };
       await deptApi.updateDept(updatedDept);
-      toast.success('状态更新成功');
+      toast.success(t('common.updateSuccess'));
       await getList();
     } catch (error: any) {
-      toast.error(error.message || '状态更新失败');
+      toast.error(error.message || t('common.updateFailed'));
     } finally {
       setDeptStatusUpdating(prev => {
         const newState = { ...prev };
@@ -226,9 +228,9 @@ export default function DepartmentManagement() {
                 ) : (
                   <span className="w-5"></span>
                 )}
-                <span>{(node as any).name || '未命名'}</span>
+                <span>{(node as any).name || t('common.noData')}</span>
                 {isBuiltIn && (
-                  <span className="ml-1 px-2 py-0.5 text-xs font-semibold bg-red-500 text-white rounded">内置</span>
+                  <span className="ml-1 px-2 py-0.5 text-xs font-semibold bg-red-500 text-white rounded">{t('common.yes')}</span>
                 )}
               </div>
             </TableCell>
@@ -271,7 +273,7 @@ export default function DepartmentManagement() {
                     }}
                   >
                     <Edit2 className="w-4 h-4" style={{ color: '#000000' }} />
-                    <span className="ml-1">编辑</span>
+                    <span className="ml-1">{t('common.edit')}</span>
                   </Button>
                 </PermissionWrapper>
                 <PermissionWrapper permission="system:dept:create">
@@ -291,7 +293,7 @@ export default function DepartmentManagement() {
                     }}
                   >
                     <Plus className="w-4 h-4" style={{ color: '#000000' }} />
-                    <span className="ml-1">新增</span>
+                    <span className="ml-1">{t('common.addNew')}</span>
                   </Button>
                 </PermissionWrapper>
                 <PermissionWrapper permission="system:dept:delete">
@@ -316,7 +318,7 @@ export default function DepartmentManagement() {
                     }}
                   >
                     <Trash2 className="w-4 h-4" style={{ color: isBuiltIn ? '#9ca3af' : '#000000' }} />
-                    <span className="ml-1">删除</span>
+                    <span className="ml-1">{t('common.delete')}</span>
                   </Button>
                 </PermissionWrapper>
               </div>
@@ -363,12 +365,12 @@ export default function DepartmentManagement() {
           {/* 搜索输入框 */}
           <div className="flex items-center gap-2 lg:gap-3 flex-wrap flex-1 min-w-0">
             <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">部门名称:</label>
+              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.departmentName')}:</label>
               <Input
                 value={queryParams.name || ''}
                 onChange={(e) => setQueryParams(prev => ({ ...prev, name: e.target.value }))}
                 onPressEnter={handleQuery}
-                placeholder="请输入部门名称"
+                placeholder={t('form.departmentNamePlaceholder')}
                 className="min-w-[150px] max-w-[200px]"
                 allowClear
               />
@@ -383,7 +385,7 @@ export default function DepartmentManagement() {
                 icon={<Search className="w-4 h-4" />}
                 onClick={handleQuery}
               >
-                搜索
+                {t('common.search')}
               </AntButton>
             </PermissionWrapper>
             
@@ -392,7 +394,7 @@ export default function DepartmentManagement() {
                 icon={<RefreshCw className="w-4 h-4" />}
                 onClick={resetQuery}
               >
-                重置
+                {t('common.reset')}
               </AntButton>
             </PermissionWrapper>
             
@@ -402,7 +404,7 @@ export default function DepartmentManagement() {
                 icon={<Plus className="w-4 h-4" />}
                 onClick={() => openForm('create')}
               >
-                新增
+                {t('common.addNew')}
               </AntButton>
             </PermissionWrapper>
             
@@ -410,7 +412,7 @@ export default function DepartmentManagement() {
               icon={isExpandAll ? <ChevronDown className="w-4 h-4" /> : <ChevronRight className="w-4 h-4" />}
               onClick={toggleExpandAll}
             >
-              {isExpandAll ? '折叠' : '展开'}
+              {isExpandAll ? t('common.collapse') : t('common.expand')}
             </AntButton>
           </Space>
         </div>
@@ -422,12 +424,12 @@ export default function DepartmentManagement() {
           <Table>
             <TableHeader>
               <TableRow>
-                <TableHead className="w-[250px]">部门名称</TableHead>
-                <TableHead className="w-[150px]">负责人</TableHead>
-                <TableHead className="w-[80px] text-center">排序</TableHead>
-                <TableHead className="w-[100px] text-center">状态</TableHead>
-                <TableHead className="w-[180px]">创建时间</TableHead>
-                <TableHead className="w-[220px] text-center">操作</TableHead>
+                <TableHead className="w-[250px]">{t('table.departmentName')}</TableHead>
+                <TableHead className="w-[150px]">{t('table.leader')}</TableHead>
+                <TableHead className="w-[80px] text-center">{t('table.sort')}</TableHead>
+                <TableHead className="w-[100px] text-center">{t('table.status')}</TableHead>
+                <TableHead className="w-[180px]">{t('table.createTime')}</TableHead>
+                <TableHead className="w-[220px] text-center">{t('table.operation')}</TableHead>
               </TableRow>
             </TableHeader>
             <TableBody>

+ 85 - 35
src/components/DictTypeManagement.tsx

@@ -14,11 +14,13 @@ import DictDataForm, { DictDataFormRef } from './DictDataForm';
 import type { ColumnsType } from 'antd/es/table';
 import PermissionWrapper from './PermissionWrapper';
 import { hasPermission } from '../utils/permission';
+import { useTranslation } from 'react-i18next';
 
 const { Search: AntSearch } = Input;
 const AntButton = Button;
 
 export default function DictTypeManagement() {
+  const { t } = useTranslation();
   const [loading, setLoading] = useState(true);
   const [list, setList] = useState<DictTypeVO[]>([]);
   const [total, setTotal] = useState(0);
@@ -49,10 +51,22 @@ export default function DictTypeManagement() {
     const currentParams = params || queryParams;
     setLoading(true);
     try {
+      console.log('DictTypeManagement: 开始获取字典类型列表', currentParams);
       const response = await dictTypeApi.getDictTypePage(currentParams);
-      const data = (response as any)?.data || response;
+      console.log('DictTypeManagement: API 响应', response);
       
+      // 处理响应数据 - 兼容不同的响应格式
+      let data;
+      if (response && typeof response === 'object') {
+        // 如果响应有 data 属性,使用 data;否则直接使用 response
+        data = (response as any).data !== undefined ? (response as any).data : response;
+      } else {
+        data = response;
+      }
+      
+      // 确保 data 是对象
       if (!data || typeof data !== 'object') {
+        console.warn('DictTypeManagement: 响应数据格式异常', data);
         setList([]);
         setTotal(0);
         return;
@@ -61,11 +75,20 @@ export default function DictTypeManagement() {
       const typeList = data.list || [];
       setList(typeList);
       setTotal(data.total || 0);
+      console.log('DictTypeManagement: 设置列表数据', typeList, '总数', data.total);
     } catch (error: any) {
-      console.error('获取字典类型列表失败', error);
+      console.error('DictTypeManagement: 获取字典类型列表失败', error);
+      console.error('错误详情:', {
+        message: error?.message,
+        response: error?.response,
+        status: error?.response?.status,
+        data: error?.response?.data,
+      });
       setList([]);
       setTotal(0);
-      const errorMessage = error?.response?.data?.message || error?.message || '获取字典类型列表失败';
+      const errorMessage = error?.response?.data?.message || 
+                          error?.message || 
+                          '获取字典类型列表失败,请检查网络连接或联系管理员';
       toast.error(errorMessage);
     } finally {
       setLoading(false);
@@ -90,15 +113,42 @@ export default function DictTypeManagement() {
         dictType,
         label: dictDataSearchTerm || undefined,
       };
+      console.log('DictTypeManagement: 开始获取字典数据', searchParams);
       const response = await dictDataApi.getDictDataPage(searchParams);
-      const data = (response as any)?.data || response;
+      console.log('DictTypeManagement: 字典数据 API 响应', response);
+      
+      // 处理响应数据 - 兼容不同的响应格式
+      let data;
+      if (response && typeof response === 'object') {
+        data = (response as any).data !== undefined ? (response as any).data : response;
+      } else {
+        data = response;
+      }
+      
+      if (!data || typeof data !== 'object') {
+        console.warn('DictTypeManagement: 字典数据响应格式异常', data);
+        setDictDataList([]);
+        setDictDataTotal(0);
+        return;
+      }
+      
       setDictDataList(data?.list || []);
       setDictDataTotal(data?.total || 0);
+      console.log('DictTypeManagement: 设置字典数据列表', data?.list, '总数', data?.total);
     } catch (error: any) {
-      console.error('获取字典数据失败', error);
+      console.error('DictTypeManagement: 获取字典数据失败', error);
+      console.error('错误详情:', {
+        message: error?.message,
+        response: error?.response,
+        status: error?.response?.status,
+        data: error?.response?.data,
+      });
       setDictDataList([]);
       setDictDataTotal(0);
-      toast.error('获取字典数据失败');
+      const errorMessage = error?.response?.data?.message || 
+                          error?.message || 
+                          '获取字典数据失败,请检查网络连接或联系管理员';
+      toast.error(errorMessage);
     } finally {
       setDictDataLoading(false);
     }
@@ -157,24 +207,24 @@ export default function DictTypeManagement() {
   // 删除字典类型
   const handleDelete = async (id: number, name: string) => {
     Modal.confirm({
-      title: '确认删除',
+      title: t('common.confirmDelete'),
       icon: <ExclamationCircleOutlined />,
       content: (
         <div>
-          <p>确定要删除字典类型 <strong>"{name}"</strong> 吗?</p>
-          <p style={{ color: '#ff4d4f', marginTop: '8px' }}>删除后无法恢复,请谨慎操作!</p>
+          <p>{t('common.confirmDeleteText')} <strong>"{name}"</strong>?</p>
+          <p style={{ color: '#ff4d4f', marginTop: '8px' }}>{t('common.confirmDeleteWarning')}</p>
         </div>
       ),
-      okText: '确定删除',
+      okText: t('common.confirmDelete'),
       okType: 'danger',
-      cancelText: '取消',
+      cancelText: t('common.cancel'),
       onOk: async () => {
         try {
           await dictTypeApi.deleteDictType(id);
-          toast.success('删除成功');
+          toast.success(t('common.deleteSuccess'));
           await getList();
         } catch (error: any) {
-          toast.error(error.message || '删除失败');
+          toast.error(error.message || t('common.deleteFailed'));
         }
       },
     });
@@ -194,7 +244,7 @@ export default function DictTypeManagement() {
       icon: <ExclamationCircleOutlined />,
       content: (
         <div>
-          <p>确定要删除字典数据 <strong>"{label}"</strong> 吗?</p>
+          <p>{t('common.confirmDeleteText')} <strong>"{label}"</strong>?</p>
           <p style={{ color: '#ff4d4f', marginTop: '8px' }}>删除后无法恢复,请谨慎操作!</p>
         </div>
       ),
@@ -204,12 +254,12 @@ export default function DictTypeManagement() {
       onOk: async () => {
         try {
           await dictDataApi.deleteDictData(id);
-          toast.success('删除成功');
+          toast.success(t('common.deleteSuccess'));
           if (currentDictType) {
             await loadDictDataFull(currentDictType.type, dictDataPageParams);
           }
         } catch (error: any) {
-          toast.error(error.message || '删除失败');
+          toast.error(error.message || t('common.deleteFailed'));
         }
       },
     });
@@ -275,7 +325,7 @@ export default function DictTypeManagement() {
       width: 100,
     },
     {
-      title: '状态',
+      title: t('table.status'),
       dataIndex: 'status',
       key: 'status',
       align: 'center',
@@ -314,7 +364,7 @@ export default function DictTypeManagement() {
       },
     },
     {
-      title: '操作',
+      title: t('table.operation'),
       key: 'action',
       align: 'center',
       width: 150,
@@ -410,23 +460,23 @@ export default function DictTypeManagement() {
           {/* 搜索输入框 */}
           <div className="flex items-center gap-2 lg:gap-3 flex-wrap flex-1 min-w-0">
             <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">字典名称:</label>
+              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.dictName')}:</label>
               <Input
                 value={queryParams.name || ''}
                 onChange={(e) => setQueryParams(prev => ({ ...prev, name: e.target.value }))}
                 onPressEnter={handleQuery}
-                placeholder="请输入字典名称"
+                placeholder={t('form.dictNamePlaceholder')}
                 className="min-w-[150px] max-w-[200px]"
                 allowClear
               />
             </div>
             <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">字典类型:</label>
+              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.dictType')}:</label>
               <Input
                 value={queryParams.type || ''}
                 onChange={(e) => setQueryParams(prev => ({ ...prev, type: e.target.value }))}
                 onPressEnter={handleQuery}
-                placeholder="请输入字典类型"
+                placeholder={t('form.dictTypePlaceholder')}
                 className="min-w-[150px] max-w-[200px]"
                 allowClear
               />
@@ -441,7 +491,7 @@ export default function DictTypeManagement() {
                 icon={<Search className="w-4 h-4" />}
                 onClick={handleQuery}
               >
-                搜索
+                {t('common.search')}
               </Button>
             </PermissionWrapper>
             
@@ -450,7 +500,7 @@ export default function DictTypeManagement() {
                 icon={<RefreshCw className="w-4 h-4" />}
                 onClick={resetQuery}
               >
-                重置
+                {t('common.reset')}
               </Button>
             </PermissionWrapper>
             
@@ -460,7 +510,7 @@ export default function DictTypeManagement() {
                 icon={<Plus className="w-4 h-4" />}
                 onClick={() => openForm('create')}
               >
-                新增
+                {t('common.addNew')}
               </Button>
             </PermissionWrapper>
           </Space>
@@ -472,13 +522,13 @@ export default function DictTypeManagement() {
         <UITable>
           <TableHeader>
             <TableRow>
-              <TableHead className="w-[100px] text-center">字典编号</TableHead>
-              <TableHead className="w-[150px]">字典名称</TableHead>
-              <TableHead className="w-[200px]">字典类型</TableHead>
-              <TableHead className="w-[100px] text-center">状态</TableHead>
-              <TableHead>备注</TableHead>
-              <TableHead className="w-[180px] text-center">创建时间</TableHead>
-              <TableHead className="w-[280px] text-center">操作</TableHead>
+              <TableHead className="w-[100px] text-center">{t('table.dictId')}</TableHead>
+              <TableHead className="w-[150px]">{t('table.dictName')}</TableHead>
+              <TableHead className="w-[200px]">{t('table.dictType')}</TableHead>
+              <TableHead className="w-[100px] text-center">{t('table.status')}</TableHead>
+              <TableHead>{t('table.remark')}</TableHead>
+              <TableHead className="w-[180px] text-center">{t('table.createTime')}</TableHead>
+              <TableHead className="w-[280px] text-center">{t('table.operation')}</TableHead>
             </TableRow>
           </TableHeader>
           <TableBody>
@@ -537,7 +587,7 @@ export default function DictTypeManagement() {
                           className="h-8 px-2"
                         >
                           <Edit2 className="w-4 h-4" />
-                          <span className="ml-1">编辑</span>
+                          <span className="ml-1">{t('common.edit')}</span>
                         </UIButton>
                       </PermissionWrapper>
                       <PermissionWrapper permission="system:dict:query">
@@ -559,7 +609,7 @@ export default function DictTypeManagement() {
                           className="h-8 px-2 text-red-600 hover:text-red-700"
                         >
                           <Trash2 className="w-4 h-4" />
-                          <span className="ml-1">删除</span>
+                          <span className="ml-1">{t('common.delete')}</span>
                         </UIButton>
                       </PermissionWrapper>
                     </div>
@@ -618,7 +668,7 @@ export default function DictTypeManagement() {
           {/* 工具栏 */}
           <div className="flex items-center justify-between gap-4">
             <AntSearch
-              placeholder="搜索字典标签"
+              placeholder={t('common.search')}
               value={dictDataSearchTerm}
               onChange={(e) => setDictDataSearchTerm(e.target.value)}
               onSearch={handleDictDataSearch}

+ 1 - 0
src/components/FormDesigner.tsx

@@ -3787,3 +3787,4 @@ export default function FormDesigner() {
     </DndProvider>
   );
 }; 
+

+ 56 - 54
src/components/FormManagement.tsx

@@ -9,8 +9,10 @@ import * as FormApi from '../api/bpm/form';
 import { DICT_TYPE, getDictLabel } from '../utils/dict';
 import { dateFormatter } from '../utils/formatTime';
 import { setConfAndFields2, FormCreateData } from '../utils/formCreate';
+import { useTranslation } from 'react-i18next';
 
 export default function FormManagement() {
+  const { t } = useTranslation();
   const navigate = useNavigate();
   const location = useLocation();
   
@@ -59,7 +61,7 @@ export default function FormManagement() {
     if (field.type === 'card') {
       const children = field.children || [];
       // 优先使用 label(字段名称),如果没有则使用 cardTitle,最后使用默认值
-      const cardTitle = field.label || field.cardTitle || '卡片容器';
+      const cardTitle = field.label || field.cardTitle || t('common.cardContainer');
       return (
         <div key={field.id} style={spanStyle} className="mb-4">
           <Card title={cardTitle} className="w-full">
@@ -132,11 +134,11 @@ export default function FormManagement() {
               label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
               name={field.name || field.field}
               required={field.required && !formConfig.hideRequiredMark}
-              rules={field.required ? [{ required: true, message: field.requiredMessage || '请输入' }] : []}
+              rules={field.required ? [{ required: true, message: field.requiredMessage || t('common.pleaseInput') }] : []}
               help={field.hint}
             >
               <Input.TextArea 
-                placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请输入'} 
+                placeholder={typeof field.placeholder === 'string' ? field.placeholder : t('common.pleaseInput')} 
                 rows={4}
                 allowClear={field.showClear}
                 maxLength={field.maxLength}
@@ -154,11 +156,11 @@ export default function FormManagement() {
               label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
               name={field.name || field.field}
               required={field.required && !formConfig.hideRequiredMark}
-              rules={field.required ? [{ required: true, message: field.requiredMessage || '请输入' }] : []}
+              rules={field.required ? [{ required: true, message: field.requiredMessage || t('common.pleaseInput') }] : []}
               help={field.hint}
             >
               <Input.Password 
-                placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请输入'}
+                placeholder={typeof field.placeholder === 'string' ? field.placeholder : t('common.pleaseInput')}
                 allowClear={field.showClear}
                 maxLength={field.maxLength}
                 readOnly={field.readOnly}
@@ -175,12 +177,12 @@ export default function FormManagement() {
               label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
               name={field.name || field.field}
               required={field.required && !formConfig.hideRequiredMark}
-              rules={field.required ? [{ required: true, message: field.requiredMessage || '请输入' }] : []}
+              rules={field.required ? [{ required: true, message: field.requiredMessage || t('common.pleaseInput') }] : []}
               help={field.hint}
             >
               <InputNumber 
                 style={{ width: '100%' }} 
-                placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请输入'}
+                placeholder={typeof field.placeholder === 'string' ? field.placeholder : t('common.pleaseInput')}
                 max={field.maxLength}
                 readOnly={field.readOnly}
                 disabled={field.disabled}
@@ -196,11 +198,11 @@ export default function FormManagement() {
               label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
               name={field.name || field.field}
               required={field.required && !formConfig.hideRequiredMark}
-              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择' }] : []}
+              rules={field.required ? [{ required: true, message: field.requiredMessage || t('common.pleaseSelect') }] : []}
               help={field.hint}
             >
               <Select
-                placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请选择'}
+                placeholder={typeof field.placeholder === 'string' ? field.placeholder : t('common.pleaseSelect')}
                 allowClear={field.showClear}
                 disabled={field.disabled}
                 size={field.size || 'middle'}
@@ -219,7 +221,7 @@ export default function FormManagement() {
               label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
               name={field.name || field.field}
               required={field.required && !formConfig.hideRequiredMark}
-              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择日期' }] : []}
+              rules={field.required ? [{ required: true, message: field.requiredMessage || t('common.pleaseSelectDate') }] : []}
               help={field.hint}
             >
               <DatePicker 
@@ -239,12 +241,12 @@ export default function FormManagement() {
               label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
               name={field.name || field.field}
               required={field.required && !formConfig.hideRequiredMark}
-              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择日期范围' }] : []}
+              rules={field.required ? [{ required: true, message: field.requiredMessage || t('common.pleaseSelectDateRange') }] : []}
               help={field.hint}
             >
               <DatePicker.RangePicker 
                 className="w-full" 
-                placeholder={Array.isArray(field.placeholder) ? field.placeholder as [string, string] : ['开始日期', '结束日期']}
+                placeholder={Array.isArray(field.placeholder) ? field.placeholder as [string, string] : [t('common.startDate'), t('common.endDate')]}
                 allowClear={field.showClear}
                 disabled={field.disabled}
                 size={field.size || 'middle'}
@@ -259,7 +261,7 @@ export default function FormManagement() {
               label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
               name={field.name || field.field}
               required={field.required && !formConfig.hideRequiredMark}
-              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择日期时间' }] : []}
+              rules={field.required ? [{ required: true, message: field.requiredMessage || t('common.pleaseSelectDateTime') }] : []}
               help={field.hint}
             >
               <DatePicker 
@@ -281,7 +283,7 @@ export default function FormManagement() {
               label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
               name={field.name || field.field}
               required={field.required && !formConfig.hideRequiredMark}
-              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择时间' }] : []}
+              rules={field.required ? [{ required: true, message: field.requiredMessage || t('common.pleaseSelectTime') }] : []}
               help={field.hint}
             >
               <TimePicker 
@@ -302,7 +304,7 @@ export default function FormManagement() {
               label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
               name={field.name || field.field}
               required={field.required && !formConfig.hideRequiredMark}
-              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择' }] : []}
+              rules={field.required ? [{ required: true, message: field.requiredMessage || t('common.pleaseSelect') }] : []}
               help={field.hint}
               valuePropName="checked"
             >
@@ -317,7 +319,7 @@ export default function FormManagement() {
               label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
               name={field.name || field.field}
               required={field.required && !formConfig.hideRequiredMark}
-              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择' }] : []}
+              rules={field.required ? [{ required: true, message: field.requiredMessage || t('common.pleaseSelect') }] : []}
               help={field.hint}
             >
               <Radio.Group disabled={field.disabled}>
@@ -335,7 +337,7 @@ export default function FormManagement() {
               label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
               name={field.name || field.field}
               required={field.required && !formConfig.hideRequiredMark}
-              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择' }] : []}
+              rules={field.required ? [{ required: true, message: field.requiredMessage || t('common.pleaseSelect') }] : []}
               help={field.hint}
             >
               <Checkbox.Group disabled={field.disabled}>
@@ -353,11 +355,11 @@ export default function FormManagement() {
               label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
               name={field.name || field.field}
               required={field.required && !formConfig.hideRequiredMark}
-              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择' }] : []}
+              rules={field.required ? [{ required: true, message: field.requiredMessage || t('common.pleaseSelect') }] : []}
               help={field.hint}
             >
               <Cascader
-                placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请选择'}
+                placeholder={typeof field.placeholder === 'string' ? field.placeholder : t('common.pleaseSelect')}
                 options={field.cascaderOptions || []}
                 className="w-full"
                 allowClear={field.showClear}
@@ -374,7 +376,7 @@ export default function FormManagement() {
               label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
               name={field.name || field.field}
               required={field.required && !formConfig.hideRequiredMark}
-              rules={field.required ? [{ required: true, message: field.requiredMessage || '请上传' }] : []}
+              rules={field.required ? [{ required: true, message: field.requiredMessage || t('common.upload') }] : []}
               help={field.hint}
             >
               <Upload
@@ -385,11 +387,11 @@ export default function FormManagement() {
                 multiple={field.uploadType !== 'single-image'}
               >
                 {field.uploadType === 'file' ? (
-                  <Button icon={<UploadOutlined />}>上传文件</Button>
+                  <Button icon={<UploadOutlined />}>{t('common.uploadFile')}</Button>
                 ) : (
                   <div>
                     <UploadOutlined />
-                    <div style={{ marginTop: 8 }}>上传</div>
+                    <div style={{ marginTop: 8 }}>{t('common.upload')}</div>
                   </div>
                 )}
               </Upload>
@@ -403,12 +405,12 @@ export default function FormManagement() {
               label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
               name={field.name || field.field}
               required={field.required && !formConfig.hideRequiredMark}
-              rules={field.required ? [{ required: true, message: field.requiredMessage || '请输入' }] : []}
+              rules={field.required ? [{ required: true, message: field.requiredMessage || t('common.pleaseInput') }] : []}
               help={field.hint}
             >
               <Input 
                 type={field.inputType || 'text'}
-                placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请输入'}
+                placeholder={typeof field.placeholder === 'string' ? field.placeholder : t('common.pleaseInput')}
                 allowClear={field.showClear}
                 maxLength={field.maxLength}
                 readOnly={field.readOnly}
@@ -433,7 +435,7 @@ export default function FormManagement() {
       setTotal(data.total || 0);
     } catch (error: any) {
       console.error('FormManagement: 获取表单列表失败', error);
-      toast.error(error.message || '获取表单列表失败');
+      toast.error(error.message || t('form.fetchFormListFailed'));
       // 确保即使失败也显示空列表
       setList([]);
       setTotal(0);
@@ -469,17 +471,17 @@ export default function FormManagement() {
   /** 删除按钮操作 */
   const handleDelete = async (id: number) => {
     Modal.confirm({
-      title: '确认删除',
-      content: '确定要删除这条表单数据吗?',
-      okText: '确定',
-      cancelText: '取消',
+      title: t('form.confirmDeleteForm'),
+      content: t('form.confirmDeleteFormText'),
+      okText: t('common.confirm'),
+      cancelText: t('common.cancel'),
       onOk: async () => {
         try {
           await FormApi.deleteForm(id);
-          toast.success('删除成功');
+          toast.success(t('form.deleteFormSuccess'));
           await getList();
         } catch (error: any) {
-          toast.error(error.message || '删除失败');
+          toast.error(error.message || t('form.deleteFormFailed'));
         }
       }
     });
@@ -492,7 +494,7 @@ export default function FormManagement() {
       setConfAndFields2(setDetailData, data.conf, data.fields);
       setDetailVisible(true);
     } catch (error: any) {
-      toast.error(error.message || '获取表单详情失败');
+      toast.error(error.message || t('form.fetchFormDetailFailed'));
     }
   };
 
@@ -518,13 +520,13 @@ export default function FormManagement() {
   // 表格列配置
   const columns: ColumnsType<FormApi.FormVO> = [
     {
-      title: '编号',
+      title: t('form.formId'),
       dataIndex: 'id',
       width: 90,
       align: 'center',
     },
     {
-      title: '表单名',
+      title: t('form.formName'),
       dataIndex: 'name',
       width: 220,
       align: 'center',
@@ -544,7 +546,7 @@ export default function FormManagement() {
       },
     },
     {
-      title: '状态',
+      title: t('form.formStatus'),
       dataIndex: 'status',
       width: 110,
       align: 'center',
@@ -556,13 +558,13 @@ export default function FormManagement() {
               isOpen ? 'bg-green-100 text-green-700' : 'bg-gray-100 text-gray-600'
             }`}
           >
-            {isOpen ? '开启' : '关闭'}
+            {isOpen ? t('form.open') : t('form.closed')}
           </span>
         );
       },
     },
     {
-      title: '备注',
+      title: t('form.formRemark'),
       dataIndex: 'remark',
       width: 260,
       align: 'center',
@@ -580,14 +582,14 @@ export default function FormManagement() {
       },
     },
     {
-      title: '创建时间',
+      title: t('form.formCreateTime'),
       dataIndex: 'createTime',
       width: 180,
       align: 'center',
       render: (text: string) => dateFormatter(text),
     },
     {
-      title: '操作',
+      title: t('form.formOperation'),
       width: 260,
       align: 'center',
       fixed: 'right',
@@ -611,7 +613,7 @@ export default function FormManagement() {
               e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #000000');
             }}
           >
-            复制
+            {t('form.copy')}
           </Button>
           <Button
             type="link"
@@ -631,7 +633,7 @@ export default function FormManagement() {
               e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #000000');
             }}
           >
-            编辑
+            {t('common.edit')}
           </Button>
           <Button
             type="link"
@@ -651,7 +653,7 @@ export default function FormManagement() {
               e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #000000');
             }}
           >
-            预览
+            {t('form.preview')}
           </Button>
           <Button
             type="link"
@@ -671,7 +673,7 @@ export default function FormManagement() {
               e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #000000');
             }}
           >
-            删除
+            {t('common.delete')}
           </Button>
         </Space>
       ),
@@ -689,28 +691,28 @@ export default function FormManagement() {
         <div className="p-4 lg:p-5 border-b border-gray-200/50">
           <div className="flex flex-wrap items-center justify-between gap-3">
             <div className="flex items-center gap-3">
-              <span className="text-sm text-gray-700">表单名:</span>
+              <span className="text-sm text-gray-700">{t('form.formName')}:</span>
               <Input
                 value={searchName}
                 onChange={(e) => setSearchName(e.target.value)}
-                placeholder="请输入表单名"
+                placeholder={t('form.formNamePlaceholder')}
                 allowClear
                 style={{ width: 240 }}
               />
             </div>
             <Space size="small">
               <Button type="primary" icon={<Search className="w-4 h-4" />} onClick={handleSearch}>
-                搜索
+                {t('common.search')}
               </Button>
               <Button icon={<RotateCcw className="w-4 h-4" />} onClick={handleReset}>
-                重置
+                {t('common.reset')}
               </Button>
               <Button
                 type="primary"
                 icon={<Plus className="w-4 h-4" />}
                 onClick={() => openForm('create')}
               >
-                新建
+                {t('form.addForm')}
               </Button>
             </Space>
           </div>
@@ -734,14 +736,14 @@ export default function FormManagement() {
         <div className="bg-white rounded-lg border border-gray-200 px-6 py-4">
           <div className="flex items-center justify-between">
             <div className="text-sm text-gray-600">
-              共 <span className="text-blue-600 font-medium">{total}</span> 条记录
+              {t('form.totalRecords')} <span className="text-blue-600 font-medium">{total}</span> {t('form.recordsUnit')}
             </div>
             <div className="flex gap-2">
               <Button
                 onClick={() => setQueryParams({ ...queryParams, pageNo: queryParams.pageNo - 1 })}
                 disabled={queryParams.pageNo <= 1}
               >
-                上一页
+                {t('common.prevPage')}
               </Button>
               <span className="px-4 py-2 text-sm text-gray-600 flex items-center">
                 {queryParams.pageNo} / {totalPages}
@@ -750,7 +752,7 @@ export default function FormManagement() {
                 onClick={() => setQueryParams({ ...queryParams, pageNo: queryParams.pageNo + 1 })}
                 disabled={queryParams.pageNo >= totalPages}
               >
-                下一页
+                {t('common.nextPage')}
               </Button>
             </div>
           </div>
@@ -759,12 +761,12 @@ export default function FormManagement() {
 
       {/* 表单详情的弹窗 */}
       <Modal
-        title="表单详情"
+        title={t('form.formDetail')}
         open={detailVisible}
         onCancel={() => setDetailVisible(false)}
         footer={[
           <div key="tip" style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', gap: '12px', width: '100%' }}>
-            <span style={{ color: '#ff4d4f', fontSize: '14px' }}>仅为表单预览,点击提交无效</span>
+            <span style={{ color: '#ff4d4f', fontSize: '14px' }}>{t('form.formPreviewTip')}</span>
             <Button
               key="submit"
               type="primary"
@@ -773,7 +775,7 @@ export default function FormManagement() {
                 return;
               }}
             >
-              提交
+              {t('common.submit')}
             </Button>
           </div>,
         ]}

+ 111 - 127
src/components/IsolationWork.tsx

@@ -1,5 +1,6 @@
 import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react';
 import { useNavigate } from 'react-router-dom';
+import { useTranslation } from 'react-i18next';
 import { Plus, Search, Edit2, Trash2, MoreVertical, FileText, Eye, Play, CheckCircle, RefreshCw, Workflow, Hand } from 'lucide-react';
 import { Button, Input, Space, Select, Table as AntdTable, message, Modal, Form, Row, Col, Tabs, Radio, DatePicker, Checkbox, Tooltip } from 'antd';
 import { Button as UIButton } from './ui/button';
@@ -399,6 +400,7 @@ const edgeTypes: EdgeTypes = {
 };
 
 export default function IsolationWork({ subMenu }: IsolationWorkProps) {
+  const { t, i18n } = useTranslation();
   const navigate = useNavigate();
   const [searchTerm, setSearchTerm] = useState('');
   const [showAddModal, setShowAddModal] = useState(false);
@@ -2475,13 +2477,10 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
       return {
         data: filtered,
         columns: [
-          { key: 'name', label: '名称', width: '20%' },
-          { key: 'creator', label: '创建人', width: '10%' },
-          { key: 'createTime', label: '创建时间', width: '15%' },
-          { key: 'version', label: '版本', width: '10%' },
-          { key: 'status', label: '状态', width: '10%' },
-          { key: 'description', label: '描述', width: '25%' },
-          { key: 'useCount', label: '使用次数', width: '10%' },
+          { key: 'name', label: t('table.formName'), width: '20%' },
+          { key: 'status', label: t('table.status'), width: '10%' },
+          { key: 'description', label: t('table.remark'), width: '25%' },
+          { key: 'createTime', label: t('table.createTime'), width: '15%' },
         ],
       };
     } else if (subMenu === '流程设计') {
@@ -2495,28 +2494,28 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
       return {
         data: filtered,
         columns: [
-          { key: 'name', label: '名称', width: '20%' },
-          { key: 'designer', label: '设计人', width: '10%' },
-          { key: 'designTime', label: '设计时间', width: '15%' },
-          { key: 'nodeCount', label: '任务数量', width: '10%' },
-          { key: 'description', label: '描述', width: '25%' },
-          { key: 'status', label: '状态', width: '10%' },
+          { key: 'name', label: t('table.name') || '名称', width: '20%' },
+          { key: 'designer', label: t('table.designer'), width: '10%' },
+          { key: 'designTime', label: t('table.designTime'), width: '15%' },
+          { key: 'nodeCount', label: t('table.nodeCount'), width: '10%' },
+          { key: 'description', label: t('table.description'), width: '25%' },
+          { key: 'status', label: t('table.status'), width: '10%' },
         ],
       };
     } else if (subMenu === '流程模板') {
       return {
         data: templateData,
         columns: [
-          { key: 'code', label: '模板编号', width: '10%' },
-          { key: 'name', label: '模板名称', width: '15%' },
-          { key: 'type', label: '类型', width: '10%' },
-          { key: 'category', label: '分类', width: '10%' },
-          { key: 'steps', label: '步骤数', width: '8%' },
-          { key: 'approvalLevel', label: '审批层级', width: '10%' },
-          { key: 'creator', label: '创建人', width: '8%' },
-          { key: 'status', label: '状态', width: '8%' },
-          { key: 'useCount', label: '使用次数', width: '9%' },
-          { key: 'createTime', label: '创建时间', width: '12%' },
+          { key: 'code', label: t('table.templateCode'), width: '10%' },
+          { key: 'name', label: t('table.templateName'), width: '15%' },
+          { key: 'type', label: t('table.templateType'), width: '10%' },
+          { key: 'category', label: t('table.templateCategory'), width: '10%' },
+          { key: 'steps', label: t('table.stepCount'), width: '8%' },
+          { key: 'approvalLevel', label: t('table.approvalLevel'), width: '10%' },
+          { key: 'creator', label: t('table.creator'), width: '8%' },
+          { key: 'status', label: t('table.status'), width: '8%' },
+          { key: 'useCount', label: t('table.useCount'), width: '9%' },
+          { key: 'createTime', label: t('table.createTime'), width: '12%' },
         ],
       };
     } else if (subMenu === 'SOP管理') {
@@ -2861,61 +2860,46 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
   };
 
   // 表单管理表格列配置
-  const formManagementColumns: ColumnsType<TableRow> = [
+  const formManagementColumns: ColumnsType<TableRow> = useMemo(() => [
     {
-      title: '序号',
+      title: t('table.formId'),
       width: '5%',
       render: (_: any, __: TableRow, index: number) => index + 1,
     },
     {
-      title: '名称',
+      title: t('table.formName'),
       dataIndex: 'name',
       width: '20%',
     },
     {
-      title: '创建人',
-      dataIndex: 'creator',
-      width: '10%',
-    },
-    {
-      title: '创建时间',
-      dataIndex: 'createTime',
-      width: '15%',
-    },
-    {
-      title: '版本',
-      dataIndex: 'version',
-      width: '10%',
-    },
-    {
-      title: '状态',
+      title: t('table.status'),
       dataIndex: 'status',
       width: '10%',
       render: (status: string) => (
         <span
           className={`inline-flex px-3 py-1 rounded-lg text-xs ${
-            status === '启用'
+            status === '启用' || status === t('common.enabled')
               ? 'bg-green-100 text-green-700'
               : 'bg-gray-100 text-gray-700'
           }`}
         >
-          {status}
+          {status === '启用' ? t('common.enabled') : status === '停用' ? t('common.disabled') : status}
         </span>
       ),
     },
     {
-      title: '描述',
+      title: t('table.remark'),
       dataIndex: 'description',
       width: '25%',
       ellipsis: true,
     },
     {
-      title: '使用次数',
-      dataIndex: 'useCount',
-      width: '10%',
+      title: t('table.createTime'),
+      dataIndex: 'createTime',
+      width: '15%',
     },
     {
-      title: '操作',
+      title: t('table.operation'),
       width: '15%',
       align: 'center',
       render: (_: any, record: TableRow) => (
@@ -2938,7 +2922,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
             }}
           >
             <Edit2 className="w-4 h-4" style={{ color: '#000000' }} />
-            <span className="ml-1">编辑</span>
+            <span className="ml-1">{t('common.edit')}</span>
           </UIButton>
           <UIButton
             variant="ghost"
@@ -2958,54 +2942,54 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
             }}
           >
             <Trash2 className="w-4 h-4" style={{ color: '#000000' }} />
-            <span className="ml-1">删除</span>
+            <span className="ml-1">{t('common.delete')}</span>
           </UIButton>
         </div>
       ),
     },
-  ];
+  ], [t, i18n.language]);
 
   // 流程设计表格列配置
-  const processDesignColumns: ColumnsType<WorkflowDesignVO> = [
+  const processDesignColumns: ColumnsType<WorkflowDesignVO> = useMemo(() => [
     {
-      title: '序号',
+      title: t('table.processDesignId'),
       width: '5%',
       render: (_: any, __: WorkflowDesignVO, index: number) => 
         (processDesignPagination.pageNo - 1) * processDesignPagination.pageSize + index + 1,
     },
     {
-      title: '名称',
+      title: t('table.name') || '名称',
       dataIndex: 'name',
       width: '15%',
     },
     {
-      title: '任务数量',
+      title: t('table.nodeCount'),
       dataIndex: 'nodeCount',
       width: '10%',
       render: (count: number) => count ?? 0,
     },
     {
-      title: '状态',
+      title: t('table.status'),
       dataIndex: 'status',
       width: '10%',
       render: (status: number) => {
         if (status === 1) {
           return (
             <span className="inline-flex px-3 py-1 rounded-lg text-xs bg-green-100 text-green-700">
-              启用
+              {t('common.enabled')}
             </span>
           );
         } else {
           return (
             <span className="inline-flex px-3 py-1 rounded-lg text-xs bg-gray-100 text-gray-700">
-              停用
+              {t('common.disabled')}
             </span>
           );
         }
       },
     },
     {
-      title: '创建时间',
+      title: t('table.createTime'),
       dataIndex: 'createTime',
       width: '15%',
       render: (time: string | Date | number) => {
@@ -3018,7 +3002,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
         } else {
           date = time;
         }
-        return date.toLocaleString('zh-CN', {
+        return date.toLocaleString(i18n.language === 'en' ? 'en-US' : 'zh-CN', {
           year: 'numeric',
           month: '2-digit',
           day: '2-digit',
@@ -3029,7 +3013,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
       },
     },
     {
-      title: '更新时间',
+      title: t('table.updateTime'),
       dataIndex: 'updateTime',
       width: '15%',
       render: (time: string | Date | number) => {
@@ -3042,7 +3026,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
         } else {
           date = time;
         }
-        return date.toLocaleString('zh-CN', {
+        return date.toLocaleString(i18n.language === 'en' ? 'en-US' : 'zh-CN', {
           year: 'numeric',
           month: '2-digit',
           day: '2-digit',
@@ -3053,7 +3037,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
       },
     },
     {
-      title: '描述',
+      title: t('table.description'),
       dataIndex: 'description',
       width: '18%',
       render: (desc: string) => {
@@ -3070,7 +3054,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
       },
     },
     {
-      title: '操作',
+      title: t('table.operation'),
       width: '20%',
       align: 'center',
       render: (_: any, record: WorkflowDesignVO) => (
@@ -3133,12 +3117,12 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
             }}
           >
             <Trash2 className="w-4 h-4" style={{ color: '#000000' }} />
-            <span className="ml-0.5">删除</span>
+            <span className="ml-0.5">{t('common.delete')}</span>
           </UIButton>
         </div>
       ),
     },
-  ];
+  ], [t, i18n.language, processDesignPagination]);
 
   // 获取作业状态样式
   const getWorkJobStatusStyle = (status: string | number | undefined): React.CSSProperties => {
@@ -3273,15 +3257,15 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
   };
 
   // 作业管理表格列配置
-  const workJobColumns: ColumnsType<WorkJobVO> = [
+  const workJobColumns: ColumnsType<WorkJobVO> = useMemo(() => [
     {
-      title: '作业编号',
+      title: t('table.workOrderNo'),
       dataIndex: 'orderNo',
       width: '12%',
       render: (orderNo: string, record: WorkJobVO) => orderNo || record.code || '-',
     },
     {
-      title: '作业名称',
+      title: t('table.workName'),
       dataIndex: 'name',
       width: '18%',
       render: (name: string, record: WorkJobVO) => {
@@ -3300,7 +3284,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
       },
     },
     {
-      title: '作业状态',
+      title: t('table.workStatus'),
       dataIndex: 'status',
       width: '10%',
       render: (status: string | number) => {
@@ -3317,13 +3301,13 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
       },
     },
     {
-      title: '当前任务',
+      title: t('table.currentTask'),
       dataIndex: 'currentNodeName',
       width: '12%',
       render: (currentNodeName: string, record: WorkJobVO) => currentNodeName || record.currentNode || '-',
     },
     {
-      title: '作业内容',
+      title: t('table.workContent'),
       dataIndex: 'description',
       width: '20%',
       render: (description: string, record: WorkJobVO) => {
@@ -3342,13 +3326,13 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
       },
     },
     {
-      title: '发起人',
+      title: t('table.initiator'),
       dataIndex: 'initiatorName',
       width: '10%',
       render: (initiatorName: string, record: WorkJobVO) => initiatorName || record.initiator || '-',
     },
     {
-      title: '发起时间',
+      title: t('table.initiationTime'),
       dataIndex: 'initiationTime',
       width: '16%',
       render: (time: string | Date | number, record: WorkJobVO) => {
@@ -3362,7 +3346,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
         } else {
           date = actualTime;
         }
-        return date.toLocaleString('zh-CN', {
+        return date.toLocaleString(i18n.language === 'en' ? 'en-US' : 'zh-CN', {
           year: 'numeric',
           month: '2-digit',
           day: '2-digit',
@@ -3373,7 +3357,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
       },
     },
     {
-      title: '紧急程度',
+      title: t('table.urgencyLevel'),
       dataIndex: 'urgencyLevel',
       minWidth: '180px',
       align: 'center',
@@ -3399,7 +3383,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
       },
     },
     {
-      title: '操作',
+      title: t('table.operation'),
       width: '20%',
       align: 'center',
       fixed: 'right',
@@ -3431,7 +3415,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
             }}
           >
             <Eye className="w-4 h-4" style={{ color: '#000000' }} />
-            <span className="ml-0.5">查看</span>
+            <span className="ml-0.5">{t('table.view')}</span>
           </UIButton>
             {canEdit ? (
           <UIButton
@@ -3452,7 +3436,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
             }}
           >
             <Edit2 className="w-4 h-4" style={{ color: '#000000' }} />
-            <span className="ml-0.5">编辑</span>
+            <span className="ml-0.5">{t('common.edit')}</span>
           </UIButton>
             ) : (
               <UIButton
@@ -3460,10 +3444,10 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                 size="sm"
                 disabled
                 className="h-8 px-2 opacity-50 cursor-not-allowed"
-                title="只有未发布状态才能编辑"
+                title={t('common.editDisabled') || '只有未发布状态才能编辑'}
               >
                 <Edit2 className="w-4 h-4" />
-                <span className="ml-0.5">编辑</span>
+                <span className="ml-0.5">{t('common.edit')}</span>
               </UIButton>
             )}
           <UIButton
@@ -3484,13 +3468,13 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
             }}
           >
             <Trash2 className="w-4 h-4" style={{ color: '#000000' }} />
-            <span className="ml-0.5">删除</span>
+            <span className="ml-0.5">{t('common.delete')}</span>
           </UIButton>
         </div>
         );
       },
     },
-  ];
+  ], [t, i18n.language, jobStatusDictList, urgencyLevelDictList]);
 
   // 如果是表单管理页面,使用特殊的布局
   if (subMenu === '表单管理') {
@@ -3511,27 +3495,27 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
               {/* 搜索输入框 */}
               <div className="flex items-center gap-2 lg:gap-3 flex-wrap flex-1 min-w-0">
                 <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">名称:</label>
+                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.formName')}:</label>
                   <Input
                     value={formManagementQuery.name}
                     onChange={(e) => setFormManagementQuery({ ...formManagementQuery, name: e.target.value })}
                     onPressEnter={handleFormManagementQuery}
-                    placeholder="请输入名称"
+                    placeholder={t('form.formNamePlaceholder')}
                     className="min-w-[150px] max-w-[200px]"
                     allowClear
                   />
                 </div>
                 <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">状态:</label>
+                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.status')}:</label>
                   <Select
                     value={formManagementQuery.status}
                     onChange={(value) => setFormManagementQuery({ ...formManagementQuery, status: value })}
-                    placeholder="请选择状态"
+                    placeholder={t('form.statusPlaceholder') || t('common.pleaseSelect')}
                     className="min-w-[150px] max-w-[200px]"
                     allowClear
                   >
-                    <Select.Option value="启用">启用</Select.Option>
-                    <Select.Option value="停用">停用</Select.Option>
+                    <Select.Option value="启用">{t('common.enabled')}</Select.Option>
+                    <Select.Option value="停用">{t('common.disabled')}</Select.Option>
                   </Select>
                 </div>
               </div>
@@ -3543,7 +3527,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                   icon={<Search className="w-4 h-4" />}
                   onClick={handleFormManagementQuery}
                 >
-                  搜索
+                  {t('common.search')}
                 </Button>
                 
                 <Button
@@ -3553,7 +3537,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                     setFormManagementPagination({ pageNo: 1, pageSize: 10 });
                   }}
                 >
-                  重置
+                  {t('common.reset')}
                 </Button>
                 
                 <Button
@@ -3564,7 +3548,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                     setShowAddModal(true);
                   }}
                 >
-                  新建表单
+                  {t('form.addForm')}
                 </Button>
               </Space>
             </div>
@@ -3587,14 +3571,14 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
           <div className="bg-white rounded-lg border border-gray-200 px-6 py-4">
             <div className="flex items-center justify-between">
               <div className="text-sm text-gray-600">
-                共 <span className="text-blue-600 font-medium">{formManagementTotal}</span> 条记录
+                {t('common.total')} <span className="text-blue-600 font-medium">{formManagementTotal}</span> {t('common.records')}
               </div>
               <div className="flex gap-2">
                 <Button
                   onClick={() => setFormManagementPagination({ ...formManagementPagination, pageNo: formManagementPagination.pageNo - 1 })}
                   disabled={formManagementPagination.pageNo <= 1}
                 >
-                  上一页
+                  {t('common.prevPage')}
                 </Button>
                 <span className="px-4 py-2 text-sm text-gray-600 flex items-center">
                   {formManagementPagination.pageNo} / {formManagementTotalPages}
@@ -3603,7 +3587,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                   onClick={() => setFormManagementPagination({ ...formManagementPagination, pageNo: formManagementPagination.pageNo + 1 })}
                   disabled={formManagementPagination.pageNo >= formManagementTotalPages}
                 >
-                  下一页
+                  {t('common.nextPage')}
                 </Button>
               </div>
             </div>
@@ -3616,7 +3600,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
             <div className="bg-white rounded-2xl shadow-2xl w-full max-w-3xl mx-4 max-h-[90vh] overflow-y-auto animate-in zoom-in duration-200">
               <div className="px-6 py-4 border-b border-gray-200 flex items-center justify-between sticky top-0 bg-white z-10">
                 <h3 className="text-lg text-gray-900">
-                  {editingItem ? '编辑表单管理' : '新建表单管理'}
+                  {editingItem ? t('common.editFormManagement') : t('common.addFormManagement')}
                 </h3>
                 <button
                   onClick={() => setShowAddModal(false)}
@@ -3715,12 +3699,12 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
               {/* 搜索输入框 */}
               <div className="flex items-center gap-2 lg:gap-3 flex-wrap flex-1 min-w-0">
                 <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">名称:</label>
+                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.processDesignName')}:</label>
                   <Input
                     value={processDesignQuery.name}
                     onChange={(e) => setProcessDesignQuery({ ...processDesignQuery, name: e.target.value })}
                     onPressEnter={handleProcessDesignQuery}
-                    placeholder="请输入名称"
+                    placeholder={t('form.processDesignNamePlaceholder')}
                     className="min-w-[150px] max-w-[200px]"
                     allowClear
                   />
@@ -3736,7 +3720,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                   icon={<Search className="w-4 h-4" />}
                   onClick={handleProcessDesignQuery}
                 >
-                  搜索
+                  {t('common.search')}
                 </Button>
                 
                 <Button
@@ -3745,7 +3729,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                     resetProcessDesignQuery();
                   }}
                 >
-                  重置
+                  {t('common.reset')}
                 </Button>
                 
               <Button
@@ -3757,7 +3741,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                   setShowAddModal(true);
                 }}
               >
-                新建流程
+                {t('form.addProcess')}
               </Button>
               </Space>
             </div>
@@ -3781,7 +3765,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
           <div className="bg-white rounded-lg border border-gray-200 px-6 py-4">
             <div className="flex items-center justify-between">
               <div className="text-sm text-gray-600">
-                共 <span className="text-blue-600 font-medium">{processDesignTotal}</span> 条记录
+                {t('common.total')} <span className="text-blue-600 font-medium">{processDesignTotal}</span> {t('common.records')}
               </div>
               <div className="flex gap-2">
                 <Button
@@ -3790,7 +3774,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                   }}
                   disabled={processDesignPagination.pageNo <= 1}
                 >
-                  上一页
+                  {t('common.prevPage')}
                 </Button>
                 <span className="px-4 py-2 text-sm text-gray-600 flex items-center">
                   {processDesignPagination.pageNo} / {processDesignTotalPages}
@@ -3801,7 +3785,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                   }}
                   disabled={processDesignPagination.pageNo >= processDesignTotalPages}
                 >
-                  下一页
+                  {t('common.nextPage')}
                 </Button>
               </div>
             </div>
@@ -4006,22 +3990,22 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
             <div className="flex flex-wrap items-center justify-between gap-3 lg:gap-4">
             <div className="flex flex-wrap items-center gap-3 lg:gap-4">
                 <div className="flex items-center gap-2">
-                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">作业名称:</label>
+                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.workName')}:</label>
               <Input
                 value={workJobQuery.name}
                 onChange={(e) => setWorkJobQuery({ ...workJobQuery, name: e.target.value })}
                 onPressEnter={handleWorkJobQuery}
-                    placeholder="请输入作业名称"
+                    placeholder={t('form.workNamePlaceholder')}
                 allowClear
                     className="min-w-[200px] max-w-[300px]"
               />
                 </div>
                 <div className="flex items-center gap-2">
-                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">作业状态:</label>
+                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.workStatus')}:</label>
               <Select
                 value={workJobQuery.status ?? ''}
                 onChange={(value) => setWorkJobQuery({ ...workJobQuery, status: value || undefined })}
-                    placeholder="请选择作业状态"
+                    placeholder={t('form.workStatusPlaceholder')}
                 allowClear
                 className="w-32"
               >
@@ -4039,7 +4023,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                   icon={<Search className="w-4 h-4" />}
                   onClick={handleWorkJobQuery}
                 >
-                  搜索
+                  {t('common.search')}
                 </Button>
                 <Button
                   icon={<RefreshCw className="w-4 h-4" />}
@@ -4048,7 +4032,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                     getWorkJobList();
                   }}
                 >
-                  重置
+                  {t('common.reset')}
                 </Button>
                 <Button
                   type="primary"
@@ -4064,7 +4048,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                     getWorkflowTemplateList();
                   }}
                 >
-                  发起作业
+                  {t('form.initiateWork')}
                 </Button>
               </Space>
             </div>
@@ -4088,14 +4072,14 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
           <div className="bg-white rounded-lg border border-gray-200 px-6 py-4">
             <div className="flex items-center justify-between">
               <div className="text-sm text-gray-600">
-                共 <span className="text-blue-600 font-medium">{workJobTotal}</span> 条记录
+                {t('common.total')} <span className="text-blue-600 font-medium">{workJobTotal}</span> {t('common.records')}
               </div>
               <div className="flex gap-2">
                 <Button
                   onClick={() => setWorkJobPagination({ ...workJobPagination, pageNo: workJobPagination.pageNo - 1 })}
                   disabled={workJobPagination.pageNo <= 1}
                 >
-                  上一页
+                  {t('common.prevPage')}
                 </Button>
                 <span className="px-4 py-2 text-sm text-gray-600 flex items-center">
                   {workJobPagination.pageNo} / {Math.ceil(workJobTotal / workJobPagination.pageSize) || 1}
@@ -4104,7 +4088,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                   onClick={() => setWorkJobPagination({ ...workJobPagination, pageNo: workJobPagination.pageNo + 1 })}
                   disabled={workJobPagination.pageNo >= Math.ceil(workJobTotal / workJobPagination.pageSize)}
                 >
-                  下一页
+                  {t('common.nextPage')}
                 </Button>
               </div>
             </div>
@@ -6028,7 +6012,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
               <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400" />
               <input
                 type="text"
-                placeholder={`搜索${subMenu}...`}
+                placeholder={subMenu === '流程模板' ? t('form.searchTemplate') : `搜索${subMenu}...`}
                 value={searchTerm}
                 onChange={(e) => setSearchTerm(e.target.value)}
                 className="w-full h-10 pl-10 pr-4 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
@@ -6044,7 +6028,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
             >
               <Plus className="w-4 h-4" strokeWidth={2.5} />
               <span className="text-sm">
-                {subMenu === '流程模板' && '新增模板'}
+                {subMenu === '流程模板' && t('common.addTemplate')}
                 {subMenu === 'SOP管理' && '新增SOP'}
                 {subMenu === '作业管理' && '新建作业'}
               </span>
@@ -6058,7 +6042,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
             <thead>
               <tr className="bg-gradient-to-r from-gray-50 to-gray-100/50 border-b border-gray-200">
                 <th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '5%' }}>
-                  序号
+                  {t('common.serialNumber')}
                 </th>
                 {columns.map((column) => (
                   <th
@@ -6070,7 +6054,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                   </th>
                 ))}
                 <th className="px-6 py-4 text-center text-xs text-gray-600 uppercase tracking-wider" style={{ width: '10%' }}>
-                  操作
+                  {t('table.operation')}
                 </th>
               </tr>
             </thead>
@@ -6124,7 +6108,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                         className="h-8 px-2"
                       >
                         <Eye className="w-4 h-4" />
-                        <span className="ml-1">查看</span>
+                        <span className="ml-1">{t('table.view')}</span>
                       </Button>
                       <Button
                         variant="ghost"
@@ -6133,7 +6117,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                         className="h-8 px-2"
                       >
                         <Edit2 className="w-4 h-4" />
-                        <span className="ml-1">编辑</span>
+                        <span className="ml-1">{t('common.edit')}</span>
                       </Button>
                       <Button
                         variant="ghost"
@@ -6142,7 +6126,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                         className="h-8 px-2 text-red-600 hover:text-red-700"
                       >
                         <Trash2 className="w-4 h-4" />
-                        <span className="ml-1">删除</span>
+                        <span className="ml-1">{t('common.delete')}</span>
                       </Button>
                     </div>
                   </td>
@@ -6159,13 +6143,13 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
         <div className="bg-white rounded-lg border border-gray-200 px-6 py-4">
           <div className="flex items-center justify-between">
             <div className="text-sm text-gray-600">
-              共 <span className="text-blue-600 font-medium">{filteredData.length}</span> 条记录
+              {t('common.total')} <span className="text-blue-600 font-medium">{filteredData.length}</span> {t('common.records')}
             </div>
             <div className="flex gap-2">
               <Button
                 disabled={true}
               >
-                上一页
+                {t('common.prevPage')}
               </Button>
               <span className="px-4 py-2 text-sm text-gray-600 flex items-center">
                 1 / 1
@@ -6173,7 +6157,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
               <Button
                 disabled={true}
               >
-                下一页
+                {t('common.nextPage')}
               </Button>
             </div>
           </div>
@@ -6188,8 +6172,8 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
             <div className="px-6 py-4 border-b border-gray-200 flex items-center justify-between sticky top-0 bg-white z-10">
               <h3 className="text-lg text-gray-900">
                 {editingItem 
-                  ? (subMenu === '流程模板' ? '编辑流程模板' : subMenu === 'SOP管理' ? '编辑SOP' : subMenu === '作业管理' ? '编辑作业' : subMenu === '表单管理' ? '编辑表单管理' : subMenu === '流程设计' ? '编辑流程设计' : '编辑')
-                  : (subMenu === '流程模板' ? '新增流程模板' : subMenu === 'SOP管理' ? '新增SOP' : subMenu === '作业管理' ? '新建作业' : subMenu === '表单管理' ? '新建表单管理' : subMenu === '流程设计' ? '新建流程设计' : '新建')
+                  ? (subMenu === '流程模板' ? t('common.editTemplate') : subMenu === 'SOP管理' ? '编辑SOP' : subMenu === '作业管理' ? t('common.editWork') : subMenu === '表单管理' ? t('common.editFormManagement') : subMenu === '流程设计' ? t('common.editProcessDesign') : t('common.edit'))
+                  : (subMenu === '流程模板' ? t('common.addTemplateTitle') : subMenu === 'SOP管理' ? '新增SOP' : subMenu === '作业管理' ? t('common.addWork') : subMenu === '表单管理' ? t('common.addFormManagement') : subMenu === '流程设计' ? t('common.addProcessDesign') : t('common.addNew'))
                 }
               </h3>
               <button

+ 30 - 29
src/components/KeyManagement.tsx

@@ -17,6 +17,7 @@ interface KeyManagementProps {
 }
 
 export default function KeyManagement({ subMenu }: KeyManagementProps) {
+  const { t } = useTranslation();
   const [loading, setLoading] = useState(true);
   const [list, setList] = useState<KeyVO[]>([]);
   const [total, setTotal] = useState(0);
@@ -70,30 +71,30 @@ export default function KeyManagement({ subMenu }: KeyManagementProps) {
   const handleDelete = async (id?: number) => {
     const ids = id ? [id] : selectedRowKeys.map(key => Number(key));
     if (ids.length === 0) {
-      toast.error('请选择要删除的数据');
+      toast.error(t('common.pleaseSelect') || '请选择要删除的数据');
       return;
     }
 
     Modal.confirm({
-      title: '确认删除',
+      title: t('common.confirmDelete'),
       icon: <ExclamationCircleOutlined />,
       content: (
         <div>
-          <p>确定要删除选中的 {ids.length} 条钥匙数据吗?</p>
-          <p style={{ color: '#ff4d4f', marginTop: '8px' }}>删除后无法恢复,请谨慎操作!</p>
+          <p>{t('common.confirmDeleteText')} {ids.length} {t('common.items') || '条数据'}?</p>
+          <p style={{ color: '#ff4d4f', marginTop: '8px' }}>{t('common.confirmDeleteWarning')}</p>
         </div>
       ),
-      okText: '确定删除',
+      okText: t('common.confirmDelete'),
       okType: 'danger',
-      cancelText: '取消',
+      cancelText: t('common.cancel'),
       onOk: async () => {
         try {
           await keyApi.delKey(ids);
-          toast.success('删除成功');
+          toast.success(t('common.deleteSuccess'));
           setSelectedRowKeys([]);
           await getList();
         } catch (error: any) {
-          toast.error(error.message || '删除失败');
+          toast.error(error.message || t('common.deleteFailed'));
         }
       },
     });
@@ -122,47 +123,47 @@ export default function KeyManagement({ subMenu }: KeyManagementProps) {
           ...formData,
           keyId: formData.keyId || formData.id,
         });
-        toast.success('修改成功');
+        toast.success(t('common.updateSuccess'));
       } else {
         await keyApi.addKey(formData);
-        toast.success('新增成功');
+        toast.success(t('common.addSuccess') || '新增成功');
       }
       setShowKeyForm(false);
       setEditingKey(null);
       await getList();
     } catch (error: any) {
-      toast.error(error.message || '保存失败');
+      toast.error(error.message || t('common.saveFailed') || '保存失败');
     }
   };
 
   // 钥匙列表表格列
   const keyColumns: ColumnsType<KeyVO> = [
     {
-      title: '钥匙名称',
+      title: t('table.keyName'),
       dataIndex: 'keyName',
       width: 180,
     },
     {
-      title: '钥匙NFC',
+      title: t('table.keyNfc'),
       dataIndex: 'keyNfc',
       width: 180,
       ellipsis: true,
     },
     {
-      title: '钥匙型号',
+      title: t('table.keySpec'),
       dataIndex: 'keySpec',
       width: 180,
       ellipsis: true,
       render: (text: string) => text || '-',
     },
     {
-      title: 'MAC地址',
+      title: t('table.macAddress'),
       dataIndex: 'macAddress',
       width: 150,
       render: (text: string) => text || '-',
     },
     {
-      title: '状态',
+      title: t('table.status'),
       dataIndex: 'exStatus',
       width: 100,
       align: 'center',
@@ -173,13 +174,13 @@ export default function KeyManagement({ subMenu }: KeyManagementProps) {
           <span className={`inline-flex px-3 py-1 rounded-lg text-xs ${
             isEnabled ? 'bg-green-100 text-green-700' : 'bg-gray-100 text-gray-700'
           }`}>
-            {isEnabled ? '启用' : '禁用'}
+            {isEnabled ? t('common.enabled') : t('common.disabled')}
           </span>
         );
       },
     },
     {
-      title: '备注',
+      title: t('table.remark'),
       dataIndex: 'exRemark',
       render: (text: string) => {
         const remarkText = text || '-';
@@ -195,19 +196,19 @@ export default function KeyManagement({ subMenu }: KeyManagementProps) {
       },
     },
     {
-      title: '所属硬件',
+      title: t('table.hardwareName'),
       dataIndex: 'hardwareName',
       width: 150,
       render: (text: string) => text || '-',
     },
     {
-      title: '创建时间',
+      title: t('table.createTime'),
       dataIndex: 'createTime',
       width: 180,
       render: (text: string | Date) => text ? dateFormatter(text) : '-',
     },
     {
-      title: '操作',
+      title: t('table.operation'),
       width: 150,
       align: 'center',
       fixed: 'right',
@@ -232,7 +233,7 @@ export default function KeyManagement({ subMenu }: KeyManagementProps) {
               }}
             >
               <Edit2 className="w-4 h-4" style={{ color: '#000000' }} />
-              <span className="ml-1">编辑</span>
+              <span className="ml-1">{t('common.edit')}</span>
             </UIButton>
           </PermissionWrapper>
           <PermissionWrapper permission="iscs:key:delete">
@@ -254,7 +255,7 @@ export default function KeyManagement({ subMenu }: KeyManagementProps) {
               }}
             >
               <Trash2 className="w-4 h-4" style={{ color: '#000000' }} />
-              <span className="ml-1">删除</span>
+              <span className="ml-1">{t('common.delete')}</span>
             </UIButton>
           </PermissionWrapper>
         </div>
@@ -272,12 +273,12 @@ export default function KeyManagement({ subMenu }: KeyManagementProps) {
             {/* 搜索输入框 */}
             <div className="flex items-center gap-2 lg:gap-3 flex-wrap flex-1 min-w-0">
               <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-                <label className="text-sm font-medium text-gray-700 whitespace-nowrap">钥匙名称:</label>
+                <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.keyName')}:</label>
                 <Input
                   value={queryParams.keyName || ''}
                   onChange={(e) => setQueryParams({ ...queryParams, keyName: e.target.value })}
                   onPressEnter={handleQuery}
-                  placeholder="请输入钥匙名称"
+                  placeholder={t('form.keyNamePlaceholder')}
                   className="min-w-[150px] max-w-[200px]"
                   allowClear
                 />
@@ -292,7 +293,7 @@ export default function KeyManagement({ subMenu }: KeyManagementProps) {
                   icon={<Search className="w-4 h-4" />}
                   onClick={handleQuery}
                 >
-                  搜索
+                  {t('common.search')}
                 </Button>
               </PermissionWrapper>
               
@@ -301,7 +302,7 @@ export default function KeyManagement({ subMenu }: KeyManagementProps) {
                   icon={<RefreshCw className="w-4 h-4" />}
                   onClick={resetQuery}
                 >
-                  重置
+                  {t('common.reset')}
                 </Button>
               </PermissionWrapper>
               
@@ -311,7 +312,7 @@ export default function KeyManagement({ subMenu }: KeyManagementProps) {
                   icon={<Plus className="w-4 h-4" />}
                   onClick={() => openKeyForm('create')}
                 >
-                  新增
+                  {t('common.addNew')}
                 </Button>
               </PermissionWrapper>
               
@@ -478,7 +479,7 @@ function KeyFormModal({ visible, editingKey, onCancel, onSave }: KeyFormModalPro
 
   return (
     <Modal
-      title={editingKey ? '编辑钥匙' : '新增钥匙'}
+      title={editingKey ? t('form.editKey') : t('form.addKey')}
       open={visible}
       onOk={handleSubmit}
       onCancel={onCancel}

+ 25 - 23
src/components/MenuManagement.tsx

@@ -19,6 +19,7 @@ import { DICT_TYPE, getDictLabel } from '../utils/dict';
 import { Button as UIButton } from './ui/button';
 import MenuForm, { MenuFormRef } from './MenuForm';
 import PermissionWrapper from './PermissionWrapper';
+import { useTranslation } from 'react-i18next';
 
 interface MenuNode extends MenuVO {
   children?: MenuNode[];
@@ -26,6 +27,7 @@ interface MenuNode extends MenuVO {
 }
 
 export default function MenuManagement() {
+  const { t } = useTranslation();
   const [loading, setLoading] = useState(true);
   const [list, setList] = useState<MenuVO[]>([]);
   const [treeList, setTreeList] = useState<MenuNode[]>([]);
@@ -141,10 +143,10 @@ export default function MenuManagement() {
       onOk: async () => {
         try {
           await menuApi.deleteMenu(id);
-          toast.success('删除成功');
+          toast.success(t('common.deleteSuccess'));
           await getList();
         } catch (error: any) {
-          toast.error(error.message || '删除失败');
+          toast.error(error.message || t('common.deleteFailed'));
         }
       },
     });
@@ -178,10 +180,10 @@ export default function MenuManagement() {
         createTime: menu.createTime,
       };
       await menuApi.updateMenu(updatedMenu);
-      toast.success('状态更新成功');
+      toast.success(t('common.updateSuccess'));
       await getList();
     } catch (error: any) {
-      toast.error(error.message || '状态更新失败');
+      toast.error(error.message || t('common.updateFailed'));
       // 恢复原状态 - 重新获取列表以恢复正确的状态
       await getList();
     } finally {
@@ -312,7 +314,7 @@ export default function MenuManagement() {
   // 表格列定义
   const columns: ColumnsType<MenuNode> = useMemo(() => [
     {
-      title: '菜单名称',
+      title: t('table.menuName'),
       dataIndex: 'name',
       key: 'name',
       width: 250,
@@ -327,7 +329,7 @@ export default function MenuManagement() {
       },
     },
     {
-      title: '图标',
+      title: t('table.icon'),
       dataIndex: 'icon',
       key: 'icon',
       width: 100,
@@ -342,14 +344,14 @@ export default function MenuManagement() {
       },
     },
     {
-      title: '排序',
+      title: t('table.sort'),
       dataIndex: 'sort',
       key: 'sort',
       width: 60,
       align: 'center',
     },
     {
-      title: '权限标识',
+      title: t('table.permission'),
       dataIndex: 'permission',
       key: 'permission',
       width: 300,
@@ -360,7 +362,7 @@ export default function MenuManagement() {
       },
     },
     {
-      title: '组件路径',
+      title: t('table.componentPath'),
       dataIndex: 'component',
       key: 'component',
       width: 500,
@@ -371,7 +373,7 @@ export default function MenuManagement() {
       },
     },
     {
-      title: '组件名称',
+      title: t('table.componentName'),
       dataIndex: 'componentName',
       key: 'componentName',
       width: 200,
@@ -379,7 +381,7 @@ export default function MenuManagement() {
       render: (text: string) => text || '-',
     },
     {
-      title: '状态',
+      title: t('table.status'),
       dataIndex: 'status',
       key: 'status',
       width: 60,
@@ -408,7 +410,7 @@ export default function MenuManagement() {
       },
     },
     {
-      title: '操作',
+      title: t('table.operation'),
       key: 'action',
       width: 240,
       align: 'center',
@@ -432,7 +434,7 @@ export default function MenuManagement() {
                   }}
                 >
                   <Edit2 className="w-4 h-4" style={{ color: '#000000' }} />
-                  <span className="ml-1">编辑</span>
+                  <span className="ml-1">{t('common.edit')}</span>
                 </UIButton>
               </PermissionWrapper>
               <PermissionWrapper permission="system:menu:create">
@@ -452,7 +454,7 @@ export default function MenuManagement() {
                   }}
                 >
                   <Plus className="w-4 h-4" style={{ color: '#000000' }} />
-                  <span className="ml-1">新增</span>
+                  <span className="ml-1">{t('common.addNew')}</span>
                 </UIButton>
               </PermissionWrapper>
               <PermissionWrapper permission="system:menu:delete">
@@ -472,13 +474,13 @@ export default function MenuManagement() {
                   }}
                 >
                   <Trash2 className="w-4 h-4" style={{ color: '#000000' }} />
-                  <span className="ml-1">删除</span>
+                  <span className="ml-1">{t('common.delete')}</span>
                 </UIButton>
               </PermissionWrapper>
             </div>
       ),
     },
-  ], [menuStatusUpdating]);
+  ], [menuStatusUpdating, t]);
 
   return (
     <>
@@ -494,12 +496,12 @@ export default function MenuManagement() {
           {/* 搜索输入框 */}
           <div className="flex items-center gap-2 lg:gap-3 flex-wrap flex-1 min-w-0">
             <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">菜单名称:</label>
+              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.menuName')}:</label>
               <Input
                 value={queryParams.name || ''}
                 onChange={(e) => setQueryParams(prev => ({ ...prev, name: e.target.value }))}
                 onPressEnter={handleQuery}
-                placeholder="请输入菜单名称"
+                placeholder={t('form.menuNamePlaceholder')}
                 className="min-w-[150px] max-w-[200px]"
                 allowClear
               />
@@ -514,7 +516,7 @@ export default function MenuManagement() {
                 icon={<Search className="w-4 h-4" />}
                 onClick={handleQuery}
               >
-                搜索
+                {t('common.search')}
               </Button>
             </PermissionWrapper>
             
@@ -523,7 +525,7 @@ export default function MenuManagement() {
                 icon={<RefreshCw className="w-4 h-4" />}
                 onClick={resetQuery}
               >
-                重置
+                {t('common.reset')}
               </Button>
             </PermissionWrapper>
             
@@ -533,21 +535,21 @@ export default function MenuManagement() {
                 icon={<Plus className="w-4 h-4" />}
                 onClick={() => openForm('create')}
               >
-                新增
+                {t('common.addNew')}
               </Button>
             </PermissionWrapper>
             
             <Button
               onClick={toggleExpandAll}
             >
-              {isExpandAll ? '折叠全部' : '展开全部'}
+              {isExpandAll ? t('common.collapseAll') : t('common.expandAll')}
             </Button>
             
             <Button
               icon={<RefreshCw className="w-4 h-4" />}
               onClick={refreshMenu}
             >
-              刷新缓存
+              {t('common.refreshCache')}
             </Button>
           </Space>
         </div>

+ 43 - 41
src/components/MyTask.tsx

@@ -13,6 +13,7 @@ import { setConfAndFields2, FormCreateData } from '../utils/formCreate';
 import urgecy1Icon from '../assets/urgecy1.png';
 import urgecy2Icon from '../assets/urgecy2.png';
 import urgecy3Icon from '../assets/urgecy3.png';
+import { useTranslation } from 'react-i18next';
 
 // 辅助函数:安全地将值转换为 dayjs 对象
 const safeToDayjs = (value: any): dayjs.Dayjs | null => {
@@ -191,6 +192,7 @@ const convertDateValues = (formValues: any, fields: any[]): any => {
 };
 
 export default function MyTask() {
+  const { t } = useTranslation();
   const navigate = useNavigate();
   
   const [loading, setLoading] = useState(true);
@@ -288,7 +290,7 @@ export default function MyTask() {
       setTotal(pageData.total || 0);
     } catch (error: any) {
       console.error('MyTask: 获取我的任务列表失败', error);
-      toast.error(error.message || '获取我的任务列表失败');
+      toast.error(error.message || t('form.fetchTaskListFailed'));
       setList([]);
       setTotal(0);
     } finally {
@@ -345,7 +347,7 @@ export default function MyTask() {
     if (field.type === 'card') {
       const children = field.children || [];
       // 优先使用 label(字段名称),如果没有则使用 cardTitle,最后使用默认值
-      const cardTitle = field.label || field.cardTitle || '卡片容器';
+      const cardTitle = field.label || field.cardTitle || t('common.cardContainer');
       return (
         <div key={field.id} style={spanStyle} className="mb-4">
           <Card title={cardTitle} className="w-full">
@@ -1547,14 +1549,14 @@ export default function MyTask() {
   // 表格列配置
   const columns: ColumnsType<MyTaskVO> = [
     {
-      title: '作业编号',
+      title: t('form.taskId'),
       dataIndex: 'orderNo',
       width: 180,
       align: 'center',
       render: (text: string) => text || '-',
     },
     {
-      title: '作业名称',
+      title: t('form.taskName'),
       dataIndex: 'name',
       width: 220,
       align: 'center',
@@ -1584,7 +1586,7 @@ export default function MyTask() {
       },
     },
     {
-      title: '当前任务',
+      title: t('form.currentTask'),
       dataIndex: 'currentNodeName',
       width: 180,
       align: 'center',
@@ -1594,7 +1596,7 @@ export default function MyTask() {
       },
     },
     {
-      title: '任务状态',
+      title: t('form.taskStatus'),
       dataIndex: 'approvalStatus',
       width: 120,
       align: 'center',
@@ -1612,7 +1614,7 @@ export default function MyTask() {
       },
     },
     {
-      title: '负责人',
+      title: t('form.responsiblePerson'),
       dataIndex: 'workerUserName',
       width: 150,
       align: 'center',
@@ -1622,7 +1624,7 @@ export default function MyTask() {
       },
     },
     {
-      title: '任务开始时间',
+      title: t('form.taskStartTime'),
       dataIndex: 'workTime',
       width: 180,
       align: 'center',
@@ -1633,7 +1635,7 @@ export default function MyTask() {
       },
     },
     {
-      title: '紧急程度',
+      title: t('form.urgencyLevel'),
       dataIndex: 'urgencyLevel',
       width: 120,
       align: 'center',
@@ -1659,7 +1661,7 @@ export default function MyTask() {
       },
     },
     {
-      title: '操作',
+      title: t('common.operation'),
       width: 120,
       align: 'center',
       fixed: 'right',
@@ -1682,7 +1684,7 @@ export default function MyTask() {
                             statusTextLower.includes('执行完成');
         
         // 根据状态显示不同的文字
-        const buttonText = isInProgress ? '立即处理' : isCompleted ? '查看详情' : '查看详情';
+        const buttonText = isInProgress ? t('form.handleNow') : isCompleted ? t('form.viewDetail') : t('form.viewDetail');
         
         return (
           <Space size="small">
@@ -1727,7 +1729,7 @@ export default function MyTask() {
             <Input
               value={searchKey}
               onChange={(e) => setSearchKey(e.target.value)}
-              placeholder="请输入作业编号或者作业名称进行查询"
+              placeholder={t('form.taskSearchPlaceholder')}
               allowClear
               className="flex-1"
               style={{ minWidth: 200 }}
@@ -1735,10 +1737,10 @@ export default function MyTask() {
             />
             <Space size="small">
               <Button type="primary" icon={<Search className="w-4 h-4" />} onClick={handleSearch}>
-                搜索
+                {t('common.search')}
               </Button>
               <Button icon={<RotateCcw className="w-4 h-4" />} onClick={handleReset}>
-                重置
+                {t('common.reset')}
               </Button>
             </Space>
           </div>
@@ -1754,7 +1756,7 @@ export default function MyTask() {
             pagination={false}
             scroll={{ x: 'max-content' }}
             locale={{
-              emptyText: '暂无数据',
+              emptyText: t('form.noData'),
             }}
           />
         </div>
@@ -1765,14 +1767,14 @@ export default function MyTask() {
         <div className="bg-white rounded-lg border border-gray-200 px-6 py-4">
           <div className="flex items-center justify-between">
             <div className="text-sm text-gray-600">
-              共 <span className="text-blue-600 font-medium">{total}</span> 条记录
+              {t('form.totalRecords')} <span className="text-blue-600 font-medium">{total}</span> {t('form.recordsUnit')}
             </div>
             <div className="flex gap-2">
               <Button
                 onClick={() => setQueryParams({ ...queryParams, pageNo: queryParams.pageNo - 1 })}
                 disabled={queryParams.pageNo <= 1}
               >
-                上一页
+                {t('common.prevPage')}
               </Button>
               <span className="px-4 py-2 text-sm text-gray-600 flex items-center">
                 {queryParams.pageNo} / {totalPages}
@@ -1781,7 +1783,7 @@ export default function MyTask() {
                 onClick={() => setQueryParams({ ...queryParams, pageNo: queryParams.pageNo + 1 })}
                 disabled={queryParams.pageNo >= totalPages}
               >
-                下一页
+                {t('common.nextPage')}
               </Button>
             </div>
           </div>
@@ -1824,7 +1826,7 @@ export default function MyTask() {
         {(() => {
           console.log('MyTask: Modal 内容渲染', { detailLoading, detailData, detailVisible });
           if (detailLoading) {
-            return <div className="py-8 text-center">加载中...</div>;
+            return <div className="py-8 text-center">{t('form.loading')}</div>;
           }
           if (detailData) {
             return (
@@ -1845,7 +1847,7 @@ export default function MyTask() {
                   flexShrink: 0
                 }}></div>
                 <h2 className="text-xl font-semibold mb-2" style={{ color: '#025fff', marginBottom: 0 }}>
-                  {detailData.workName || detailData.name || '作业详情'}
+                  {detailData.workName || detailData.name || t('form.workDetail')}
                 </h2>
                 <span 
                   className="inline-flex px-3 py-1 rounded-full text-xs font-medium"
@@ -1855,10 +1857,10 @@ export default function MyTask() {
                 </span>
               </div>
               <div className="text-sm flex gap-4" style={{ color: '#898f9a', marginTop: '12px' }}>
-                <span>作业编号:{detailData.orderNo || '-'}</span>
-                <span>任务负责人:{detailData.workerUserName || '-'}</span>
-                <span>作业负责人:{detailData.initiatorName || '-'}</span>
-                <span>发起时间:{detailData.workTime ? dateFormatter(detailData.workTime) : '-'}</span>
+                <span>{t('form.workOrderNo')}:{detailData.orderNo || '-'}</span>
+                <span>{t('form.taskResponsible')}:{detailData.workerUserName || '-'}</span>
+                <span>{t('form.workResponsible')}:{detailData.initiatorName || '-'}</span>
+                <span>{t('form.initiationTime')}:{detailData.workTime ? dateFormatter(detailData.workTime) : '-'}</span>
               </div>
             </div>
 
@@ -1938,7 +1940,7 @@ export default function MyTask() {
                             lineHeight: '1.6'
                           }}
                         >
-                          请前往锁控柜进行取锁,取钥匙操作
+                          {t('form.lockCabinetTip')}
                         </div>
                       </Card>
                     </div>
@@ -1954,7 +1956,7 @@ export default function MyTask() {
                       <div className="space-y-6" style={{ padding: '0 24px', flex: 1, overflowY: 'auto', minHeight: 0 }}>
                       {/* 自定义表单 */}
                       {formLoading ? (
-                        <div className="py-8 text-center text-gray-500">表单加载中...</div>
+                        <div className="py-8 text-center text-gray-500">{t('form.formLoading')}</div>
                       ) : formData.rule && formData.rule.length > 0 ? (
                         <div>
                           {(() => {
@@ -2000,7 +2002,7 @@ export default function MyTask() {
                           })()}
                         </div>
                       ) : (
-                        <div className="py-4 text-center text-gray-400 text-sm">暂无表单内容</div>
+                        <div className="py-4 text-center text-gray-400 text-sm">{t('form.noFormContent')}</div>
                       )}
 
                       {/* 审核意见 - label 和 textarea 同一行 */}
@@ -2013,14 +2015,14 @@ export default function MyTask() {
                             flexShrink: 0
                           }}
                         >
-                          审核意见
+                          {t('form.reviewComment')}
                         </label>
                         <div className="flex-1">
                           <Input.TextArea
                             rows={4}
                             value={approvalComment}
                             onChange={(e) => setApprovalComment(e.target.value)}
-                            placeholder="请输入审核意见"
+                            placeholder={t('form.reviewCommentPlaceholder')}
                             maxLength={500}
                             showCount
                             disabled={isApproved}
@@ -2081,7 +2083,7 @@ export default function MyTask() {
                               
                               console.log('MyTask: 调用审核不通过接口', params);
                               await myTaskApi.updateNodeApproval(params);
-                              message.success('审核不通过操作成功');
+                              message.success(t('form.reviewRejectSuccess'));
                               
                               // 关闭弹框
                               setDetailVisible(false);
@@ -2097,13 +2099,13 @@ export default function MyTask() {
                               getList();
                             } catch (error: any) {
                               console.error('MyTask: 审核不通过失败', error);
-                              message.error(error?.message || '审核不通过操作失败');
+                              message.error(error?.message || t('form.reviewRejectFailed'));
                             } finally {
                               setApprovalLoading(false);
                             }
                           }}
                         >
-                          审核不通过
+                          {t('form.reviewReject')}
                         </Button>
                         <Button
                           type="primary"
@@ -2147,7 +2149,7 @@ export default function MyTask() {
                               
                               console.log('MyTask: 调用审核通过接口', params);
                               await myTaskApi.updateNodeApproval(params);
-                              message.success('审核通过操作成功');
+                              message.success(t('form.reviewApproveSuccess'));
                               
                               // 关闭弹框
                               setDetailVisible(false);
@@ -2163,13 +2165,13 @@ export default function MyTask() {
                               getList();
                             } catch (error: any) {
                               console.error('MyTask: 审核通过失败', error);
-                              message.error(error?.message || '审核通过操作失败');
+                              message.error(error?.message || t('form.reviewApproveFailed'));
                             } finally {
                               setApprovalLoading(false);
                             }
                           }}
                         >
-                          审核通过
+                          {t('form.reviewApprove')}
                         </Button>
                       </div>
                     </div>
@@ -2182,7 +2184,7 @@ export default function MyTask() {
                     <div className="space-y-6" style={{ padding: '0 24px', flex: 1, overflowY: 'auto', minHeight: 0 }}>
                     {/* 自定义表单 */}
                     {formLoading ? (
-                      <div className="py-8 text-center text-gray-500">表单加载中...</div>
+                      <div className="py-8 text-center text-gray-500">{t('form.formLoading')}</div>
                     ) : formData.rule && formData.rule.length > 0 ? (
                       <div>
                         {(() => {
@@ -2228,7 +2230,7 @@ export default function MyTask() {
                         })()}
                       </div>
                     ) : (
-                      <div className="py-4 text-center text-gray-400 text-sm">暂无表单内容</div>
+                      <div className="py-4 text-center text-gray-400 text-sm">{t('form.noFormContent')}</div>
                     )}
 
                     </div>
@@ -2251,7 +2253,7 @@ export default function MyTask() {
                           detailForm.resetFields();
                         }}
                       >
-                        取消
+                        {t('common.cancel')}
                       </Button>
                       <Button
                         type="primary"
@@ -2319,7 +2321,7 @@ export default function MyTask() {
                             // 根据节点类型显示不同的成功消息
                             const nodeType = String(detailData?.type || detailData?.nodeType || '').trim();
                             const isComplete = nodeType === 'complete';
-                            message.success(isComplete ? '完成成功' : '提交成功');
+                            message.success(isComplete ? t('form.completeSuccess') : t('common.submit') + t('common.success'));
                             
                             // 关闭弹框
                             setDetailVisible(false);
@@ -2349,7 +2351,7 @@ export default function MyTask() {
                           // 从 detailData.type 或 detailData.nodeType 获取节点类型
                           const nodeType = String(detailData?.type || detailData?.nodeType || '').trim();
                           const isComplete = nodeType === 'complete';
-                          return isComplete ? '完成' : '提交';
+                          return isComplete ? t('form.complete') : t('common.submit');
                         })()}
                       </Button>
                     </div>
@@ -2360,7 +2362,7 @@ export default function MyTask() {
           </div>
             );
           }
-          return <div className="py-8 text-center text-gray-500">暂无数据</div>;
+          return <div className="py-8 text-center text-gray-500">{t('form.noData')}</div>;
         })()}
       </Modal>
     </div>

+ 49 - 48
src/components/PadLockManagement.tsx

@@ -20,6 +20,7 @@ interface PadLockManagementProps {
 }
 
 export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
+  const { t } = useTranslation();
   const [viewMode, setViewMode] = useState<'list' | 'type'>('list'); // 'list' 挂锁列表, 'type' 挂锁类型
   const [loading, setLoading] = useState(true);
   const [list, setList] = useState<PadLockVO[]>([]);
@@ -163,30 +164,30 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
   const handleDelete = async (id?: number) => {
     const ids = id ? [id] : selectedRowKeys.map(key => Number(key));
     if (ids.length === 0) {
-      toast.error('请选择要删除的数据');
+      toast.error(t('common.pleaseSelect') || '请选择要删除的数据');
       return;
     }
 
     Modal.confirm({
-      title: '确认删除',
+      title: t('common.confirmDelete'),
       icon: <ExclamationCircleOutlined />,
       content: (
         <div>
-          <p>确定要删除选中的 {ids.length} 条挂锁数据吗?</p>
-          <p style={{ color: '#ff4d4f', marginTop: '8px' }}>删除后无法恢复,请谨慎操作!</p>
+          <p>{t('common.confirmDeleteText')} {ids.length} {t('common.items') || '条数据'}?</p>
+          <p style={{ color: '#ff4d4f', marginTop: '8px' }}>{t('common.confirmDeleteWarning')}</p>
         </div>
       ),
-      okText: '确定删除',
+      okText: t('common.confirmDelete'),
       okType: 'danger',
-      cancelText: '取消',
+      cancelText: t('common.cancel'),
       onOk: async () => {
         try {
           await padLockApi.delPadLock(ids);
-          toast.success('删除成功');
+          toast.success(t('common.deleteSuccess'));
           setSelectedRowKeys([]);
           await getList();
         } catch (error: any) {
-          toast.error(error.message || '删除失败');
+          toast.error(error.message || t('common.deleteFailed'));
         }
       },
     });
@@ -244,7 +245,7 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
       icon: <ExclamationCircleOutlined />,
       content: (
         <div>
-          <p>确定要删除挂锁类型 <strong>"{name || '该类型'}"</strong> 吗?</p>
+          <p>{t('common.confirmDeleteText')} <strong>"{name || t('common.type') || '该类型'}"</strong>?</p>
           <p style={{ color: '#ff4d4f', marginTop: '8px' }}>删除后无法恢复,请谨慎操作!</p>
         </div>
       ),
@@ -254,10 +255,10 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
       onOk: async () => {
         try {
           await padLockTypeApi.delPadLockType(id);
-          toast.success('删除成功');
+          toast.success(t('common.deleteSuccess'));
           await getTypeList();
         } catch (error: any) {
-          toast.error(error.message || '删除失败');
+          toast.error(error.message || t('common.deleteFailed'));
         }
       },
     });
@@ -337,36 +338,36 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
   // 挂锁列表表格列
   const padLockColumns: ColumnsType<PadLockVO> = [
     {
-      title: '挂锁名称',
+      title: t('table.padLockName'),
       dataIndex: 'lockName',
       width: 200,
     },
     {
-      title: '挂锁NFC',
+      title: t('table.padLockNfc'),
       dataIndex: 'lockNfc',
       width: 180,
       ellipsis: true,
     },
     {
-      title: '所属硬件',
+      title: t('table.hardwareName'),
       dataIndex: 'hardwareName',
       width: 150,
       render: (text: string) => text || '-',
     },
     {
-      title: '挂锁类型',
+      title: t('table.padLockType'),
       dataIndex: 'lockTypeName',
       width: 150,
       render: (text: string) => text || '-',
     },
     {
-      title: '挂锁型号',
+      title: t('table.padLockModel'),
       dataIndex: 'lockSpec',
       width: 150,
       render: (text: string) => text || '-',
     },
     {
-      title: '状态',
+      title: t('table.status'),
       dataIndex: 'exStatus',
       width: 100,
       align: 'center',
@@ -377,13 +378,13 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
           <span className={`inline-flex px-3 py-1 rounded-lg text-xs ${
             isEnabled ? 'bg-green-100 text-green-700' : 'bg-gray-100 text-gray-700'
           }`}>
-            {isEnabled ? '启用' : '禁用'}
+            {isEnabled ? t('common.enabled') : t('common.disabled')}
           </span>
         );
       },
     },
     {
-      title: '备注',
+      title: t('table.remark'),
       dataIndex: 'exRemark',
       render: (text: string) => {
         const remarkText = text || '-';
@@ -399,13 +400,13 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
       },
     },
     {
-      title: '创建时间',
+      title: t('table.createTime'),
       dataIndex: 'createTime',
       width: 180,
       render: (text: string | Date) => text ? dateFormatter(text) : '-',
     },
     {
-      title: '操作',
+      title: t('table.operation'),
       width: 150,
       align: 'center',
       fixed: 'right',
@@ -430,7 +431,7 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
               }}
             >
               <Edit2 className="w-4 h-4" style={{ color: '#000000' }} />
-              <span className="ml-1">编辑</span>
+              <span className="ml-1">{t('common.edit')}</span>
             </UIButton>
           </PermissionWrapper>
           <PermissionWrapper permission="iscs:lock:delete">
@@ -452,7 +453,7 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
               }}
             >
               <Trash2 className="w-4 h-4" style={{ color: '#000000' }} />
-              <span className="ml-1">删除</span>
+              <span className="ml-1">{t('common.delete')}</span>
             </UIButton>
           </PermissionWrapper>
         </div>
@@ -463,13 +464,13 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
   // 挂锁类型表格列(树形表格)
   const padLockTypeColumns: ColumnsType<PadLockTypeVO> = [
     {
-      title: '挂锁类型名称',
+      title: t('table.padLockTypeName'),
       dataIndex: 'lockTypeName',
       width: 200,
       align: 'center',
     },
     {
-      title: '挂锁类型图标',
+      title: t('table.padLockTypeIcon'),
       dataIndex: 'lockTypeIcon',
       width: 120,
       align: 'center',
@@ -490,7 +491,7 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
       },
     },
     {
-      title: '挂锁类型图片',
+      title: t('table.padLockTypeImage'),
       dataIndex: 'lockTypeImg',
       width: 120,
       align: 'center',
@@ -511,14 +512,14 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
       },
     },
     {
-      title: '挂锁型号',
+      title: t('table.padLockModel'),
       dataIndex: 'lockTypeSpec',
       width: 150,
       align: 'center',
       render: (spec: string) => spec || '-',
     },
     {
-      title: '操作',
+      title: t('table.operation'),
       width: 200,
       align: 'center',
       fixed: 'right',
@@ -585,7 +586,7 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
               }}
             >
               <Trash2 className="w-4 h-4" style={{ color: '#000000' }} />
-              <span className="ml-1">删除</span>
+              <span className="ml-1">{t('common.delete')}</span>
             </UIButton>
           )}
         </div>
@@ -605,12 +606,12 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
               {/* 搜索输入框 */}
               <div className="flex items-center gap-2 lg:gap-3 flex-wrap flex-1 min-w-0">
                 <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">挂锁名称:</label>
+                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.padLockName')}:</label>
                   <Input
                     value={queryParams.lockName || ''}
                     onChange={(e) => setQueryParams({ ...queryParams, lockName: e.target.value })}
                     onPressEnter={handleQuery}
-                    placeholder="请输入挂锁名称"
+                    placeholder={t('form.padLockNamePlaceholder')}
                     className="min-w-[150px] max-w-[200px]"
                     allowClear
                   />
@@ -625,7 +626,7 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
                       icon={<Search className="w-4 h-4" />}
                       onClick={handleQuery}
                     >
-                      搜索
+                      {t('common.search')}
                     </Button>
                   </PermissionWrapper>
                   
@@ -634,7 +635,7 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
                       icon={<RefreshCw className="w-4 h-4" />}
                       onClick={resetQuery}
                     >
-                      重置
+                      {t('common.reset')}
                     </Button>
                   </PermissionWrapper>
                   
@@ -644,7 +645,7 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
                       icon={<Plus className="w-4 h-4" />}
                       onClick={() => openPadLockForm('create')}
                     >
-                      新增
+                      {t('common.addNew')}
                     </Button>
                   </PermissionWrapper>
                   
@@ -655,7 +656,7 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
                       onClick={() => handleDelete()}
                       disabled={selectedRowKeys.length === 0}
                     >
-                      批量删除
+                      {t('common.batchDelete')}
                     </Button>
                   </PermissionWrapper>
                   
@@ -663,7 +664,7 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
                     icon={<Settings className="w-4 h-4" />}
                     onClick={() => setViewMode('type')}
                   >
-                    设置挂锁类型
+                    {t('common.setPadLockType')}
                   </Button>
                 </Space>
               </div>
@@ -735,12 +736,12 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
                 {/* 搜索输入框 */}
                 <div className="flex items-center gap-2 lg:gap-3 flex-wrap flex-1 min-w-0">
                   <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-                    <label className="text-sm font-medium text-gray-700 whitespace-nowrap">类型名称:</label>
+                    <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.padLockTypeName')}:</label>
                     <Input
                       value={typeQueryParams.lockTypeName || ''}
                       onChange={(e) => setTypeQueryParams({ ...typeQueryParams, lockTypeName: e.target.value })}
                       onPressEnter={handleTypeQuery}
-                      placeholder="请输入类型名称"
+                      placeholder={t('form.padLockTypeNamePlaceholder')}
                       className="min-w-[150px] max-w-[200px]"
                       allowClear
                     />
@@ -755,7 +756,7 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
                       icon={<Search className="w-4 h-4" />}
                       onClick={handleTypeQuery}
                     >
-                      搜索
+                      {t('common.search')}
                     </Button>
                   </PermissionWrapper>
                   
@@ -764,7 +765,7 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
                       icon={<RefreshCw className="w-4 h-4" />}
                       onClick={resetTypeQuery}
                     >
-                      重置
+                      {t('common.reset')}
                     </Button>
                   </PermissionWrapper>
                   
@@ -774,7 +775,7 @@ export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
                       icon={<Plus className="w-4 h-4" />}
                       onClick={() => openTypeForm('create')}
                     >
-                      新增
+                      {t('common.addNew')}
                     </Button>
                   </PermissionWrapper>
                   
@@ -926,7 +927,7 @@ function TypeFormModal({ visible, editingType, parentTypeId, typeList, onCancel,
 
   return (
     <Modal
-      title={editingType ? '编辑挂锁类型' : '新增挂锁类型'}
+      title={editingType ? t('form.editPadLockType') : t('form.addPadLockType')}
       open={visible}
       onOk={handleSubmit}
       onCancel={onCancel}
@@ -961,7 +962,7 @@ function TypeFormModal({ visible, editingType, parentTypeId, typeList, onCancel,
           name="lockTypeName"
           rules={[{ required: true, message: '请输入挂锁类型名称' }]}
         >
-          <Input placeholder="请输入挂锁类型名称" />
+          <Input placeholder={t('form.padLockTypeNamePlaceholder')} />
         </Form.Item>
         
         <Form.Item
@@ -1123,7 +1124,7 @@ function PadLockFormModal({ visible, editingPadLock, onCancel, onSave }: PadLock
 
   return (
     <Modal
-      title={editingPadLock ? '编辑挂锁' : '新增挂锁'}
+      title={editingPadLock ? t('form.editPadLock') : t('form.addPadLock')}
       open={visible}
       onOk={handleSubmit}
       onCancel={onCancel}
@@ -1140,11 +1141,11 @@ function PadLockFormModal({ visible, editingPadLock, onCancel, onSave }: PadLock
         className="mt-4"
       >
         <Form.Item
-          label="所属硬件"
+          label={t('table.hardwareName')}
           name="hardwareId"
         >
           <Select
-            placeholder="请选择所属硬件"
+            placeholder={t('form.hardwareNamePlaceholder')}
             allowClear
             options={hardwareOptions}
           />
@@ -1199,10 +1200,10 @@ function PadLockFormModal({ visible, editingPadLock, onCancel, onSave }: PadLock
         </Form.Item>
         
         <Form.Item
-          label="备注"
+          label={t('form.remark')}
           name="exRemark"
         >
-          <Input.TextArea placeholder="请输入备注" rows={3} />
+          <Input.TextArea placeholder={t('form.remarkPlaceholder')} rows={3} />
         </Form.Item>
       </Form>
     </Modal>

+ 28 - 26
src/components/PostManagement.tsx

@@ -10,8 +10,10 @@ import { Button as UIButton } from './ui/button';
 import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from './ui/table';
 import PostForm, { PostFormRef } from './PostForm';
 import PermissionWrapper from './PermissionWrapper';
+import { useTranslation } from 'react-i18next';
 
 export default function PostManagement() {
+  const { t } = useTranslation();
   const [loading, setLoading] = useState(true);
   const [list, setList] = useState<PostVO[]>([]);
   const [total, setTotal] = useState(0);
@@ -124,24 +126,24 @@ export default function PostManagement() {
   // 删除岗位
   const handleDelete = async (id: number, name: string) => {
     Modal.confirm({
-      title: '确认删除',
+      title: t('common.confirmDelete'),
       icon: <ExclamationCircleOutlined />,
       content: (
         <div>
-          <p>确定要删除岗位 <strong>"{name}"</strong> 吗?</p>
-          <p style={{ color: '#ff4d4f', marginTop: '8px' }}>删除后无法恢复,请谨慎操作!</p>
+          <p>{t('common.confirmDeleteText')} <strong>"{name}"</strong>?</p>
+          <p style={{ color: '#ff4d4f', marginTop: '8px' }}>{t('common.confirmDeleteWarning')}</p>
         </div>
       ),
-      okText: '确定删除',
+      okText: t('common.confirmDelete'),
       okType: 'danger',
-      cancelText: '取消',
+      cancelText: t('common.cancel'),
       onOk: async () => {
         try {
           await postApi.deletePost(id);
-          toast.success('删除成功');
+          toast.success(t('common.deleteSuccess'));
           await getList();
         } catch (error: any) {
-          toast.error(error.message || '删除失败');
+          toast.error(error.message || t('common.deleteFailed'));
         }
       },
     });
@@ -198,10 +200,10 @@ export default function PostManagement() {
         status: newStatus,
       };
       await postApi.updatePost(updatedPost);
-      toast.success('状态更新成功');
+      toast.success(t('common.updateSuccess'));
       await getList();
     } catch (error: any) {
-      toast.error(error.message || '状态更新失败');
+      toast.error(error.message || t('common.updateFailed'));
     } finally {
       setPostStatusUpdating(prev => {
         const newState = { ...prev };
@@ -225,23 +227,23 @@ export default function PostManagement() {
           {/* 搜索输入框 */}
           <div className="flex items-center gap-2 lg:gap-3 flex-wrap flex-1 min-w-0">
             <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">岗位名称:</label>
+              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.postName')}:</label>
               <Input
                 value={queryParams.name || ''}
                 onChange={(e) => setQueryParams(prev => ({ ...prev, name: e.target.value }))}
                 onPressEnter={handleQuery}
-                placeholder="请输入岗位名称"
+                placeholder={t('form.postNamePlaceholder')}
                 className="min-w-[150px] max-w-[200px]"
                 allowClear
               />
             </div>
             <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">岗位编码:</label>
+              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.postCode')}:</label>
               <Input
                 value={queryParams.code || ''}
                 onChange={(e) => setQueryParams(prev => ({ ...prev, code: e.target.value }))}
                 onPressEnter={handleQuery}
-                placeholder="请输入岗位编码"
+                placeholder={t('form.postCodePlaceholder')}
                 className="min-w-[150px] max-w-[200px]"
                 allowClear
               />
@@ -256,7 +258,7 @@ export default function PostManagement() {
                 icon={<Search className="w-4 h-4" />}
                 onClick={handleQuery}
               >
-                搜索
+                {t('common.search')}
               </Button>
             </PermissionWrapper>
             
@@ -265,7 +267,7 @@ export default function PostManagement() {
                 icon={<RefreshCw className="w-4 h-4" />}
                 onClick={resetQuery}
               >
-                重置
+                {t('common.reset')}
               </Button>
             </PermissionWrapper>
             
@@ -275,7 +277,7 @@ export default function PostManagement() {
                 icon={<Plus className="w-4 h-4" />}
                 onClick={() => openForm('create')}
               >
-                新增
+                {t('common.addNew')}
               </Button>
             </PermissionWrapper>
             
@@ -297,14 +299,14 @@ export default function PostManagement() {
         <Table>
           <TableHeader>
             <TableRow>
-              <TableHead className="w-[80px] text-center">岗位编号</TableHead>
-              <TableHead className="w-[150px]">岗位名称</TableHead>
-              <TableHead className="w-[150px]">岗位编码</TableHead>
-              <TableHead className="w-[100px] text-center">岗位顺序</TableHead>
-              <TableHead>岗位备注</TableHead>
-              <TableHead className="w-[100px] text-center">状态</TableHead>
-              <TableHead className="w-[180px] text-center">创建时间</TableHead>
-              <TableHead className="w-[160px] text-center">操作</TableHead>
+              <TableHead className="w-[80px] text-center">{t('table.postId')}</TableHead>
+              <TableHead className="w-[150px]">{t('table.postName')}</TableHead>
+              <TableHead className="w-[150px]">{t('table.postCode')}</TableHead>
+              <TableHead className="w-[100px] text-center">{t('table.postSort')}</TableHead>
+              <TableHead>{t('table.postRemark')}</TableHead>
+              <TableHead className="w-[100px] text-center">{t('table.status')}</TableHead>
+              <TableHead className="w-[180px] text-center">{t('table.createTime')}</TableHead>
+              <TableHead className="w-[160px] text-center">{t('table.operation')}</TableHead>
             </TableRow>
           </TableHeader>
           <TableBody>
@@ -378,7 +380,7 @@ export default function PostManagement() {
                           }}
                         >
                           <Edit2 className="w-4 h-4" style={{ color: '#000000' }} />
-                          <span className="ml-1">编辑</span>
+                          <span className="ml-1">{t('common.edit')}</span>
                         </UIButton>
                       </PermissionWrapper>
                       <PermissionWrapper permission="system:post:delete">
@@ -398,7 +400,7 @@ export default function PostManagement() {
                           }}
                         >
                           <Trash2 className="w-4 h-4" style={{ color: '#000000' }} />
-                          <span className="ml-1">删除</span>
+                          <span className="ml-1">{t('common.delete')}</span>
                         </UIButton>
                       </PermissionWrapper>
                     </div>

+ 27 - 25
src/components/RoleManagement.tsx

@@ -14,8 +14,10 @@ import RoleAssignMenuForm, { RoleAssignMenuFormRef } from './RoleAssignMenuForm'
 import RoleDataPermissionForm, { RoleDataPermissionFormRef } from './RoleDataPermissionForm';
 import PermissionWrapper from './PermissionWrapper';
 import { hasPermission } from '../utils/permission';
+import { useTranslation } from 'react-i18next';
 
 export default function RoleManagement() {
+  const { t } = useTranslation();
   const [loading, setLoading] = useState(true);
   const [list, setList] = useState<RoleVO[]>([]);
   const [total, setTotal] = useState(0);
@@ -139,24 +141,24 @@ export default function RoleManagement() {
   // 删除角色
   const handleDelete = async (id: number, name: string) => {
     Modal.confirm({
-      title: '确认删除',
+      title: t('common.confirmDelete'),
       icon: <ExclamationCircleOutlined />,
       content: (
         <div>
-          <p>确定要删除角色 <strong>"{name}"</strong> 吗?</p>
-          <p style={{ color: '#ff4d4f', marginTop: '8px' }}>删除后无法恢复,请谨慎操作!</p>
+          <p>{t('common.confirmDeleteText')} <strong>"{name}"</strong>?</p>
+          <p style={{ color: '#ff4d4f', marginTop: '8px' }}>{t('common.confirmDeleteWarning')}</p>
         </div>
       ),
-      okText: '确定删除',
+      okText: t('common.confirmDelete'),
       okType: 'danger',
-      cancelText: '取消',
+      cancelText: t('common.cancel'),
       onOk: async () => {
         try {
           await roleApi.deleteRole(id);
-          toast.success('删除成功');
+          toast.success(t('common.deleteSuccess'));
           await getList();
         } catch (error: any) {
-          toast.error(error.message || '删除失败');
+          toast.error(error.message || t('common.deleteFailed'));
         }
       },
     });
@@ -220,23 +222,23 @@ export default function RoleManagement() {
           {/* 搜索输入框 */}
           <div className="flex items-center gap-2 lg:gap-3 flex-wrap flex-1 min-w-0">
             <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">角色名称:</label>
+              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.roleName')}:</label>
               <Input
                 value={queryParams.name || ''}
                 onChange={(e) => setQueryParams(prev => ({ ...prev, name: e.target.value }))}
                 onPressEnter={handleQuery}
-                placeholder="请输入角色名称"
+                placeholder={t('form.roleNamePlaceholder')}
                 className="min-w-[150px] max-w-[200px]"
                 allowClear
               />
             </div>
             <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">角色标识:</label>
+              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.roleCode')}:</label>
               <Input
                 value={queryParams.code || ''}
                 onChange={(e) => setQueryParams(prev => ({ ...prev, code: e.target.value }))}
                 onPressEnter={handleQuery}
-                placeholder="请输入角色标识"
+                placeholder={t('form.roleCodePlaceholder')}
                 className="min-w-[150px] max-w-[200px]"
                 allowClear
               />
@@ -251,7 +253,7 @@ export default function RoleManagement() {
                 icon={<Search className="w-4 h-4" />}
                 onClick={handleQuery}
               >
-                搜索
+                {t('common.search')}
               </Button>
             </PermissionWrapper>
             
@@ -260,7 +262,7 @@ export default function RoleManagement() {
                 icon={<RefreshCw className="w-4 h-4" />}
                 onClick={resetQuery}
               >
-                重置
+                {t('common.reset')}
               </Button>
             </PermissionWrapper>
             
@@ -270,7 +272,7 @@ export default function RoleManagement() {
                 icon={<Plus className="w-4 h-4" />}
                 onClick={() => openForm('create')}
               >
-                新增
+                {t('common.addNew')}
               </Button>
             </PermissionWrapper>
             
@@ -292,15 +294,15 @@ export default function RoleManagement() {
         <Table>
           <TableHeader>
             <TableRow>
-              <TableHead className="w-[100px] text-center">角色编号</TableHead>
-              <TableHead className="w-[150px]">角色名称</TableHead>
-              <TableHead className="w-[120px] text-center">角色类型</TableHead>
-              <TableHead className="w-[150px]">角色标识</TableHead>
-              <TableHead className="w-[100px] text-center">显示顺序</TableHead>
-              <TableHead>备注</TableHead>
-              <TableHead className="w-[100px] text-center">状态</TableHead>
-              <TableHead className="w-[180px] text-center">创建时间</TableHead>
-              <TableHead className="w-[350px] text-center">操作</TableHead>
+              <TableHead className="w-[100px] text-center">{t('table.roleId')}</TableHead>
+              <TableHead className="w-[150px]">{t('table.roleName')}</TableHead>
+              <TableHead className="w-[120px] text-center">{t('table.status')}</TableHead>
+              <TableHead className="w-[150px]">{t('table.roleCode')}</TableHead>
+              <TableHead className="w-[100px] text-center">{t('table.sort')}</TableHead>
+              <TableHead>{t('table.remark')}</TableHead>
+              <TableHead className="w-[100px] text-center">{t('table.status')}</TableHead>
+              <TableHead className="w-[180px] text-center">{t('table.createTime')}</TableHead>
+              <TableHead className="w-[350px] text-center">{t('table.operation')}</TableHead>
             </TableRow>
           </TableHeader>
           <TableBody>
@@ -367,7 +369,7 @@ export default function RoleManagement() {
                           }}
                         >
                           <Edit2 className="w-4 h-4" style={{ color: '#000000' }} />
-                          <span className="ml-1">编辑</span>
+                          <span className="ml-1">{t('common.edit')}</span>
                         </UIButton>
                       </PermissionWrapper>
                       <PermissionWrapper permission="system:permission:assign-role-menu">
@@ -427,7 +429,7 @@ export default function RoleManagement() {
                           }}
                         >
                           <Trash2 className="w-4 h-4" style={{ color: '#000000' }} />
-                          <span className="ml-1">删除</span>
+                          <span className="ml-1">{t('common.delete')}</span>
                         </UIButton>
                       </PermissionWrapper>
                     </div>

+ 44 - 42
src/components/SegregationPointManagement.tsx

@@ -1,4 +1,4 @@
-import React, { useState, useEffect, useRef } from 'react';
+import React, { useState, useEffect, useRef, useMemo } from 'react';
 import { Plus, Search, RefreshCw, Edit2, Trash2 } from 'lucide-react';
 import { segregationPointApi, SegregationPointVO, PageParam } from '../api/spm/index';
 import { marsDeptApi, MarsDeptVO } from '../api/marsdept/index';
@@ -13,12 +13,14 @@ import { getStrDictOptions, DICT_TYPE } from '../utils/dict';
 import SegregationPointForm, { SegregationPointFormRef } from './SegregationPointForm';
 import { Button as UIButton } from './ui/button';
 import PermissionWrapper from './PermissionWrapper';
+import { useTranslation } from 'react-i18next';
 
 interface SegregationPointManagementProps {
   subMenu?: string;
 }
 
 export default function SegregationPointManagement({ subMenu }: SegregationPointManagementProps) {
+  const { t, i18n } = useTranslation();
   const [loading, setLoading] = useState(true);
   const [list, setList] = useState<SegregationPointVO[]>([]);
   const [total, setTotal] = useState(0);
@@ -70,7 +72,7 @@ export default function SegregationPointManagement({ subMenu }: SegregationPoint
       console.log('SegregationPointManagement: 设置列表数据', { list: data?.list || [], total: data?.total || 0 });
     } catch (error: any) {
       console.error('SegregationPointManagement: 获取列表失败', error);
-      toast.error(error.message || '获取隔离点列表失败');
+      toast.error(error.message || t('common.error') || '获取隔离点列表失败');
     } finally {
       setLoading(false);
     }
@@ -150,40 +152,40 @@ export default function SegregationPointManagement({ subMenu }: SegregationPoint
     const pointIds = id ? [id] : selectedRowKeys.map(key => Number(key));
     
     Modal.confirm({
-      title: '确认删除',
+      title: t('common.confirmDelete'),
       icon: <ExclamationCircleOutlined />,
-      content: `确定要删除选中的 ${pointIds.length} 条数据吗?`,
-      okText: '确定删除',
+      content: `${t('common.confirmDeleteText')} ${pointIds.length} ${t('common.records') || '条数据'}?`,
+      okText: t('common.confirmDelete'),
       okType: 'danger',
-      cancelText: '取消',
+      cancelText: t('common.cancel'),
       onOk: async () => {
         try {
           await segregationPointApi.deleteIsIsolationPointByPointIds(pointIds);
-          toast.success('删除成功');
+          toast.success(t('common.deleteSuccess'));
           setSelectedRowKeys([]);
           await getList();
         } catch (error: any) {
-          toast.error(error.message || '删除失败');
+          toast.error(error.message || t('common.deleteFailed'));
         }
       },
     });
   };
 
   // 表格列配置
-  const columns: ColumnsType<SegregationPointVO> = [
+  const columns: ColumnsType<SegregationPointVO> = useMemo(() => [
     {
-      title: '编号',
+      title: t('table.segregationPointId'),
       dataIndex: 'id',
       width: 100,
       align: 'center',
     },
     {
-      title: '隔离点名称',
+      title: t('table.segregationPointName'),
       dataIndex: 'pointName',
       align: 'center',
     },
     {
-      title: '图标',
+      title: t('table.icon'),
       dataIndex: 'pointIcon',
       width: 100,
       align: 'center',
@@ -195,7 +197,7 @@ export default function SegregationPointManagement({ subMenu }: SegregationPoint
       },
     },
     {
-      title: '开关状态',
+      title: t('table.switchStatus'),
       dataIndex: 'switchStatus',
       width: 100,
       align: 'center',
@@ -216,40 +218,40 @@ export default function SegregationPointManagement({ subMenu }: SegregationPoint
       },
     },
     {
-      title: '隔离点NFC',
+      title: t('table.segregationPointNfc'),
       dataIndex: 'pointNfc',
       align: 'center',
     },
     {
-      title: '岗位',
+      title: t('table.position'),
       dataIndex: 'workstationName',
       align: 'center',
     },
     {
-      title: '设备/工艺',
+      title: t('table.deviceProcess'),
       dataIndex: 'machineryName',
       width: 180,
       align: 'center',
     },
     {
-      title: '锁定站',
+      title: t('table.lotoStation'),
       dataIndex: 'lotoName',
       width: 120,
       align: 'center',
     },
     {
-      title: '隔离点序列号',
+      title: t('table.segregationPointSerial'),
       dataIndex: 'pointSerialNumber',
       width: 120,
       align: 'center',
     },
     {
-      title: '作用',
+      title: t('table.function'),
       dataIndex: 'remark',
       align: 'center',
     },
     {
-      title: '图片',
+      title: t('table.image'),
       dataIndex: 'pointPicture',
       width: 100,
       align: 'center',
@@ -261,7 +263,7 @@ export default function SegregationPointManagement({ subMenu }: SegregationPoint
       },
     },
     {
-      title: '能量源',
+      title: t('table.energySource'),
       dataIndex: 'powerType',
       align: 'center',
       render: (value: string) => {
@@ -270,7 +272,7 @@ export default function SegregationPointManagement({ subMenu }: SegregationPoint
       },
     },
     {
-      title: '操作',
+      title: t('table.operation'),
       width: 150,
       align: 'center',
       fixed: 'right',
@@ -295,7 +297,7 @@ export default function SegregationPointManagement({ subMenu }: SegregationPoint
               }}
             >
               <Edit2 className="w-4 h-4" style={{ color: '#000000' }} />
-              <span className="ml-1">编辑</span>
+              <span className="ml-1">{t('common.edit')}</span>
             </UIButton>
           </PermissionWrapper>
           <PermissionWrapper permission="iscs:point:delete">
@@ -317,13 +319,13 @@ export default function SegregationPointManagement({ subMenu }: SegregationPoint
               }}
             >
               <Trash2 className="w-4 h-4" style={{ color: '#000000' }} />
-              <span className="ml-1">删除</span>
+              <span className="ml-1">{t('common.delete')}</span>
             </UIButton>
           </PermissionWrapper>
         </div>
       ),
     },
-  ];
+  ], [t, i18n.language, powerTypeOptions]);
 
   return (
     <div className="p-6 space-y-4">
@@ -333,55 +335,55 @@ export default function SegregationPointManagement({ subMenu }: SegregationPoint
           {/* 搜索输入框 */}
           <div className="flex items-center gap-2 lg:gap-3 flex-wrap flex-1 min-w-0">
             <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">隔离点名称:</label>
+              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.segregationPointName')}:</label>
               <Input
                 value={queryParams.pointName}
                 onChange={(e) => setQueryParams({ ...queryParams, pointName: e.target.value })}
                 onPressEnter={handleQuery}
-                placeholder="请输入隔离点名称"
+                placeholder={t('form.segregationPointNamePlaceholder')}
                 className="min-w-[150px] max-w-[200px]"
                 allowClear
               />
             </div>
             <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">岗位:</label>
+              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.workstation')}:</label>
               <TreeSelect
                 value={queryParams.workstationId}
                 onChange={(value) => setQueryParams({ ...queryParams, workstationId: value })}
                 treeData={deptOptions}
-                placeholder="选择岗位"
+                placeholder={t('form.workstationPlaceholder')}
                 allowClear
                 className="min-w-[150px] max-w-[200px]"
               />
             </div>
             <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">设备/工艺:</label>
+              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.deviceProcess')}:</label>
               <TreeSelect
                 value={queryParams.machineryId}
                 onChange={(value) => setQueryParams({ ...queryParams, machineryId: value })}
                 treeData={machineryOptions}
-                placeholder="选择设备/工艺"
+                placeholder={t('form.deviceProcessPlaceholder')}
                 allowClear
                 className="min-w-[150px] max-w-[200px]"
               />
             </div>
             <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">锁定站:</label>
+              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.lotoStation')}:</label>
               <Select
                 value={queryParams.lotoId}
                 onChange={(value) => setQueryParams({ ...queryParams, lotoId: value })}
-                placeholder="请选择锁定站"
+                placeholder={t('form.lotoStationPlaceholder')}
                 allowClear
                 className="min-w-[150px] max-w-[200px]"
                 options={lotoOptions}
               />
             </div>
             <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">能量源:</label>
+              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.energySource')}:</label>
               <Select
                 value={queryParams.powerType}
                 onChange={(value) => setQueryParams({ ...queryParams, powerType: value })}
-                placeholder="请选择能量源"
+                placeholder={t('form.energySourcePlaceholder')}
                 allowClear
                 className="min-w-[150px] max-w-[200px]"
                 options={powerTypeOptions}
@@ -397,7 +399,7 @@ export default function SegregationPointManagement({ subMenu }: SegregationPoint
                 icon={<Search />}
                 onClick={handleQuery}
               >
-                搜索
+                {t('common.search')}
               </Button>
             </PermissionWrapper>
             <PermissionWrapper permission="iscs:point:query">
@@ -405,7 +407,7 @@ export default function SegregationPointManagement({ subMenu }: SegregationPoint
                 icon={<RefreshCw />}
                 onClick={resetQuery}
               >
-                重置
+                {t('common.reset')}
               </Button>
             </PermissionWrapper>
             <PermissionWrapper permission="iscs:point:create">
@@ -414,7 +416,7 @@ export default function SegregationPointManagement({ subMenu }: SegregationPoint
                 icon={<Plus />}
                 onClick={() => openForm('create')}
               >
-                新增
+                {t('common.addNew')}
               </Button>
             </PermissionWrapper>
             <PermissionWrapper permission="iscs:point:delete">
@@ -424,7 +426,7 @@ export default function SegregationPointManagement({ subMenu }: SegregationPoint
                 disabled={selectedRowKeys.length === 0}
                 onClick={() => handleDelete()}
               >
-                批量删除
+                {t('common.batchDelete')}
               </Button>
             </PermissionWrapper>
           </Space>
@@ -497,14 +499,14 @@ export default function SegregationPointManagement({ subMenu }: SegregationPoint
         <div className="bg-white rounded-lg border border-gray-200 px-6 py-4">
           <div className="flex items-center justify-between">
             <div className="text-sm text-gray-600">
-              共 <span className="text-blue-600 font-medium">{total}</span> 条记录
+              {t('common.total')} <span className="text-blue-600 font-medium">{total}</span> {t('common.records')}
             </div>
             <div className="flex gap-2">
               <Button
                 onClick={() => setQueryParams({ ...queryParams, current: (queryParams.current || 1) - 1 })}
                 disabled={(queryParams.current || 1) <= 1}
               >
-                上一页
+                {t('common.prevPage')}
               </Button>
               <span className="px-4 py-2 text-sm text-gray-600 flex items-center">
                 {queryParams.current || 1} / {Math.ceil(total / (queryParams.size || 10)) || 1}
@@ -513,7 +515,7 @@ export default function SegregationPointManagement({ subMenu }: SegregationPoint
                 onClick={() => setQueryParams({ ...queryParams, current: (queryParams.current || 1) + 1 })}
                 disabled={(queryParams.current || 1) >= Math.ceil(total / (queryParams.size || 10))}
               >
-                下一页
+                {t('common.nextPage')}
               </Button>
             </div>
           </div>

+ 4 - 1
src/components/SystemConfig.tsx

@@ -441,14 +441,17 @@ export default function SystemConfig({ subMenu }: SystemConfigProps) {
   }
 
   // 字典管理使用专门的组件
-  // 支持多种可能的 subMenu 值:'字典管理'、'dictManagement'、'dict'
+  // 支持多种可能的 subMenu 值:'字典管理'、'dictionaryManagement'、'dictManagement'、'dict'
   const isDictManagement = subMenu === '字典管理' || 
+                           subMenu === 'dictionaryManagement' ||
                            subMenu === 'dictManagement' || 
                            subMenu === 'dict';
   console.log('SystemConfig: 检查字典管理条件,subMenu =', subMenu, '是否匹配:', isDictManagement);
   if (isDictManagement) {
     console.log('SystemConfig: ✅ 匹配成功,渲染字典管理组件');
     return <DictTypeManagement />;
+  } else {
+    console.log('SystemConfig: ❌ 不匹配,继续执行其他逻辑');
   }
 
   // 旧的字典管理代码(已废弃,保留作为备份)

+ 43 - 41
src/components/TaskManagement.tsx

@@ -13,6 +13,7 @@ import { setConfAndFields2, FormCreateData } from '../utils/formCreate';
 import urgecy1Icon from '../assets/urgecy1.png';
 import urgecy2Icon from '../assets/urgecy2.png';
 import urgecy3Icon from '../assets/urgecy3.png';
+import { useTranslation } from 'react-i18next';
 
 // 辅助函数:安全地将值转换为 dayjs 对象
 const safeToDayjs = (value: any): dayjs.Dayjs | null => {
@@ -191,6 +192,7 @@ const convertDateValues = (formValues: any, fields: any[]): any => {
 };
 
 export default function TaskManagement() {
+  const { t } = useTranslation();
   const navigate = useNavigate();
   
   const [loading, setLoading] = useState(true);
@@ -288,7 +290,7 @@ export default function TaskManagement() {
       setTotal(pageData.total || 0);
     } catch (error: any) {
       console.error('TaskManagement: 获取任务管理列表失败', error);
-      toast.error(error.message || '获取任务管理列表失败');
+      toast.error(error.message || t('form.fetchTaskListFailed'));
       setList([]);
       setTotal(0);
     } finally {
@@ -1546,14 +1548,14 @@ export default function TaskManagement() {
   // 表格列配置
   const columns: ColumnsType<MyTaskVO> = [
     {
-      title: '作业编号',
+      title: t('form.taskId'),
       dataIndex: 'orderNo',
       width: 180,
       align: 'center',
       render: (text: string) => text || '-',
     },
     {
-      title: '作业名称',
+      title: t('form.taskName'),
       dataIndex: 'name',
       width: 220,
       align: 'center',
@@ -1583,7 +1585,7 @@ export default function TaskManagement() {
       },
     },
     {
-      title: '当前任务',
+      title: t('form.currentTask'),
       dataIndex: 'currentNodeName',
       width: 180,
       align: 'center',
@@ -1593,7 +1595,7 @@ export default function TaskManagement() {
       },
     },
     {
-      title: '任务状态',
+      title: t('form.taskStatus'),
       dataIndex: 'approvalStatus',
       width: 120,
       align: 'center',
@@ -1611,7 +1613,7 @@ export default function TaskManagement() {
       },
     },
     {
-      title: '负责人',
+      title: t('form.responsiblePerson'),
       dataIndex: 'workerUserName',
       width: 150,
       align: 'center',
@@ -1621,7 +1623,7 @@ export default function TaskManagement() {
       },
     },
     {
-      title: '任务开始时间',
+      title: t('form.taskStartTime'),
       dataIndex: 'workTime',
       width: 180,
       align: 'center',
@@ -1632,7 +1634,7 @@ export default function TaskManagement() {
       },
     },
     {
-      title: '紧急程度',
+      title: t('form.urgencyLevel'),
       dataIndex: 'urgencyLevel',
       width: 120,
       align: 'center',
@@ -1658,7 +1660,7 @@ export default function TaskManagement() {
       },
     },
     {
-      title: '操作',
+      title: t('common.operation'),
       width: 120,
       align: 'center',
       fixed: 'right',
@@ -1681,7 +1683,7 @@ export default function TaskManagement() {
                             statusTextLower.includes('执行完成');
         
         // 根据状态显示不同的文字
-        const buttonText = isInProgress ? '立即处理' : isCompleted ? '查看详情' : '查看详情';
+        const buttonText = isInProgress ? t('form.handleNow') : isCompleted ? t('form.viewDetail') : t('form.viewDetail');
         
         return (
           <Space size="small">
@@ -1726,7 +1728,7 @@ export default function TaskManagement() {
             <Input
               value={searchKey}
               onChange={(e) => setSearchKey(e.target.value)}
-              placeholder="请输入作业编号或者作业名称进行查询"
+              placeholder={t('form.taskSearchPlaceholder')}
               allowClear
               className="flex-1"
               style={{ minWidth: 200 }}
@@ -1734,10 +1736,10 @@ export default function TaskManagement() {
             />
             <Space size="small">
               <Button type="primary" icon={<Search className="w-4 h-4" />} onClick={handleSearch}>
-                搜索
+                {t('common.search')}
               </Button>
               <Button icon={<RotateCcw className="w-4 h-4" />} onClick={handleReset}>
-                重置
+                {t('common.reset')}
               </Button>
             </Space>
           </div>
@@ -1753,7 +1755,7 @@ export default function TaskManagement() {
             pagination={false}
             scroll={{ x: 'max-content' }}
             locale={{
-              emptyText: '暂无数据',
+              emptyText: t('form.noData'),
             }}
           />
         </div>
@@ -1764,14 +1766,14 @@ export default function TaskManagement() {
         <div className="bg-white rounded-lg border border-gray-200 px-6 py-4">
           <div className="flex items-center justify-between">
             <div className="text-sm text-gray-600">
-              共 <span className="text-blue-600 font-medium">{total}</span> 条记录
+              {t('form.totalRecords')} <span className="text-blue-600 font-medium">{total}</span> {t('form.recordsUnit')}
             </div>
             <div className="flex gap-2">
               <Button
                 onClick={() => setQueryParams({ ...queryParams, pageNo: queryParams.pageNo - 1 })}
                 disabled={queryParams.pageNo <= 1}
               >
-                上一页
+                {t('common.prevPage')}
               </Button>
               <span className="px-4 py-2 text-sm text-gray-600 flex items-center">
                 {queryParams.pageNo} / {totalPages}
@@ -1780,7 +1782,7 @@ export default function TaskManagement() {
                 onClick={() => setQueryParams({ ...queryParams, pageNo: queryParams.pageNo + 1 })}
                 disabled={queryParams.pageNo >= totalPages}
               >
-                下一页
+                {t('common.nextPage')}
               </Button>
             </div>
           </div>
@@ -1823,7 +1825,7 @@ export default function TaskManagement() {
         {(() => {
           console.log('TaskManagement: Modal 内容渲染', { detailLoading, detailData, detailVisible });
           if (detailLoading) {
-            return <div className="py-8 text-center">加载中...</div>;
+            return <div className="py-8 text-center">{t('form.loading')}</div>;
           }
           if (detailData) {
             return (
@@ -1843,8 +1845,8 @@ export default function TaskManagement() {
                   borderRadius: '2px',
                   flexShrink: 0
                 }}></div>
-                <h2 className="text-xl font-semibold mb-2" style={{ color: '#025fff', marginBottom: 0 }}>
-                  {detailData.workName || detailData.name || '作业详情'}
+                <                h2 className="text-xl font-semibold mb-2" style={{ color: '#025fff', marginBottom: 0 }}>
+                  {detailData.workName || detailData.name || t('form.workDetail')}
                 </h2>
                 <span 
                   className="inline-flex px-3 py-1 rounded-full text-xs font-medium"
@@ -1854,10 +1856,10 @@ export default function TaskManagement() {
                 </span>
               </div>
               <div className="text-sm flex gap-4" style={{ color: '#898f9a', marginTop: '12px' }}>
-                <span>作业编号:{detailData.orderNo || '-'}</span>
-                <span>作业负责人:{detailData.initiatorName || '-'}</span>
-                <span>任务负责人:{detailData.workerUserName || '-'}</span>
-                <span>发起时间:{detailData.workTime ? dateFormatter(detailData.workTime) : '-'}</span>
+                <span>{t('form.workOrderNo')}:{detailData.orderNo || '-'}</span>
+                <span>{t('form.workResponsible')}:{detailData.initiatorName || '-'}</span>
+                <span>{t('form.taskResponsible')}:{detailData.workerUserName || '-'}</span>
+                <span>{t('form.initiationTime')}:{detailData.workTime ? dateFormatter(detailData.workTime) : '-'}</span>
               </div>
             </div>
 
@@ -1937,7 +1939,7 @@ export default function TaskManagement() {
                             lineHeight: '1.6'
                           }}
                         >
-                          请前往锁控柜进行取锁,取钥匙操作
+                          {t('form.lockCabinetTip')}
                         </div>
                       </Card>
                     </div>
@@ -1953,7 +1955,7 @@ export default function TaskManagement() {
                       <div className="space-y-6" style={{ padding: '0 24px', flex: 1, overflowY: 'auto', minHeight: 0 }}>
                       {/* 自定义表单 */}
                       {formLoading ? (
-                        <div className="py-8 text-center text-gray-500">表单加载中...</div>
+                        <div className="py-8 text-center text-gray-500">{t('form.formLoading')}</div>
                       ) : formData.rule && formData.rule.length > 0 ? (
                         <div>
                           {(() => {
@@ -1999,7 +2001,7 @@ export default function TaskManagement() {
                           })()}
                         </div>
                       ) : (
-                        <div className="py-4 text-center text-gray-400 text-sm">暂无表单内容</div>
+                        <div className="py-4 text-center text-gray-400 text-sm">{t('form.noFormContent')}</div>
                       )}
 
                       {/* 审核意见 - label 和 textarea 同一行 */}
@@ -2012,14 +2014,14 @@ export default function TaskManagement() {
                             flexShrink: 0
                           }}
                         >
-                          审核意见
+                          {t('form.reviewComment')}
                         </label>
                         <div className="flex-1">
                           <Input.TextArea
                             rows={4}
                             value={approvalComment}
                             onChange={(e) => setApprovalComment(e.target.value)}
-                            placeholder="请输入审核意见"
+                            placeholder={t('form.reviewCommentPlaceholder')}
                             maxLength={500}
                             showCount
                             disabled={isApproved}
@@ -2080,7 +2082,7 @@ export default function TaskManagement() {
                               
                               console.log('TaskManagement: 调用审核不通过接口', params);
                               await taskManagementApi.updateNodeApproval(params);
-                              message.success('审核不通过操作成功');
+                              message.success(t('form.reviewRejectSuccess'));
                               
                               // 关闭弹框
                               setDetailVisible(false);
@@ -2096,13 +2098,13 @@ export default function TaskManagement() {
                               getList();
                             } catch (error: any) {
                               console.error('TaskManagement: 审核不通过失败', error);
-                              message.error(error?.message || '审核不通过操作失败');
+                              message.error(error?.message || t('form.reviewRejectFailed'));
                             } finally {
                               setApprovalLoading(false);
                             }
                           }}
                         >
-                          审核不通过
+                          {t('form.reviewReject')}
                         </Button>
                         <Button
                           type="primary"
@@ -2146,7 +2148,7 @@ export default function TaskManagement() {
                               
                               console.log('TaskManagement: 调用审核通过接口', params);
                               await taskManagementApi.updateNodeApproval(params);
-                              message.success('审核通过操作成功');
+                              message.success(t('form.reviewApproveSuccess'));
                               
                               // 关闭弹框
                               setDetailVisible(false);
@@ -2162,13 +2164,13 @@ export default function TaskManagement() {
                               getList();
                             } catch (error: any) {
                               console.error('TaskManagement: 审核通过失败', error);
-                              message.error(error?.message || '审核通过操作失败');
+                              message.error(error?.message || t('form.reviewApproveFailed'));
                             } finally {
                               setApprovalLoading(false);
                             }
                           }}
                         >
-                          审核通过
+                          {t('form.reviewApprove')}
                         </Button>
                       </div>
                     </div>
@@ -2181,7 +2183,7 @@ export default function TaskManagement() {
                     <div className="space-y-6" style={{ padding: '0 24px', flex: 1, overflowY: 'auto', minHeight: 0 }}>
                     {/* 自定义表单 */}
                     {formLoading ? (
-                      <div className="py-8 text-center text-gray-500">表单加载中...</div>
+                      <div className="py-8 text-center text-gray-500">{t('form.formLoading')}</div>
                     ) : formData.rule && formData.rule.length > 0 ? (
                       <div>
                         {(() => {
@@ -2227,7 +2229,7 @@ export default function TaskManagement() {
                         })()}
                       </div>
                     ) : (
-                      <div className="py-4 text-center text-gray-400 text-sm">暂无表单内容</div>
+                      <div className="py-4 text-center text-gray-400 text-sm">{t('form.noFormContent')}</div>
                     )}
 
                     </div>
@@ -2250,7 +2252,7 @@ export default function TaskManagement() {
                           detailForm.resetFields();
                         }}
                       >
-                        取消
+                        {t('common.cancel')}
                       </Button>
                       <Button
                         type="primary"
@@ -2318,7 +2320,7 @@ export default function TaskManagement() {
                             // 根据节点类型显示不同的成功消息
                             const nodeType = String(detailData?.type || detailData?.nodeType || '').trim();
                             const isComplete = nodeType === 'complete';
-                            message.success(isComplete ? '完成成功' : '提交成功');
+                            message.success(isComplete ? t('form.completeSuccess') : t('common.submit') + t('common.success'));
                             
                             // 关闭弹框
                             setDetailVisible(false);
@@ -2348,7 +2350,7 @@ export default function TaskManagement() {
                           // 从 detailData.type 或 detailData.nodeType 获取节点类型
                           const nodeType = String(detailData?.type || detailData?.nodeType || '').trim();
                           const isComplete = nodeType === 'complete';
-                          return isComplete ? '完成' : '提交';
+                          return isComplete ? t('form.complete') : t('common.submit');
                         })()}
                       </Button>
                     </div>
@@ -2359,7 +2361,7 @@ export default function TaskManagement() {
           </div>
             );
           }
-          return <div className="py-8 text-center text-gray-500">暂无数据</div>;
+          return <div className="py-8 text-center text-gray-500">{t('form.noData')}</div>;
         })()}
       </Modal>
     </div>

+ 42 - 42
src/components/UserManagement.tsx

@@ -59,7 +59,7 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
       setList(response.list || []);
       setTotal(response.total || 0);
     } catch (error: any) {
-      toast.error(error.message || '获取用户列表失败');
+      toast.error(error.message || t('common.error') || '获取用户列表失败');
     } finally {
       setLoading(false);
     }
@@ -161,15 +161,15 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
   // 修改用户状态
   const handleStatusChange = async (row: UserVO, newChecked: boolean) => {
     const newStatus = newChecked ? 0 : 1; // 0是开启,1是关闭
-    const text = newStatus === 0 ? '启用' : '停用';
+    const text = newStatus === 0 ? t('common.enabled') : t('common.disabled');
     
     // 使用 antd 的确认弹框
     Modal.confirm({
-      title: '确认操作',
+      title: t('common.confirmOperation') || '确认操作',
       icon: <ExclamationCircleOutlined />,
-      content: `确定要${text}用户"${row.username}"吗?`,
-      okText: '确定',
-      cancelText: '取消',
+      content: `${t('common.confirmText') || '确定要'}${text}${t('common.user') || '用户'}"${row.username}"?`,
+      okText: t('common.confirm'),
+      cancelText: t('common.cancel'),
       onOk: async () => {
         try {
           await userApi.updateUserStatus(row.id, newStatus);
@@ -193,24 +193,24 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
   // 删除用户
   const handleDelete = async (id: number, username?: string) => {
     Modal.confirm({
-      title: '确认删除',
+      title: t('common.confirmDelete'),
       icon: <ExclamationCircleOutlined />,
       content: (
         <div>
-          <p>确定要删除用户 <strong>"{username || '该用户'}"</strong> 吗?</p>
-          <p style={{ color: '#ff4d4f', marginTop: '8px' }}>删除后无法恢复,请谨慎操作!</p>
+          <p>{t('common.confirmDeleteText')} <strong>"{username || t('common.user') || '该用户'}"</strong>?</p>
+          <p style={{ color: '#ff4d4f', marginTop: '8px' }}>{t('common.confirmDeleteWarning')}</p>
         </div>
       ),
-      okText: '确定删除',
+      okText: t('common.confirmDelete'),
       okType: 'danger',
-      cancelText: '取消',
+      cancelText: t('common.cancel'),
       onOk: async () => {
         try {
           await userApi.deleteUser(id);
-          toast.success('删除成功');
+          toast.success(t('common.deleteSuccess'));
           await getList();
         } catch (error: any) {
-          toast.error(error.message || '删除失败');
+          toast.error(error.message || t('common.deleteFailed'));
         }
       },
     });
@@ -226,7 +226,7 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
   // 提交重置密码
   const submitResetPassword = async () => {
     if (!resetPwdPassword.trim()) {
-      toast.error('请输入新密码');
+      toast.error(t('common.pleaseEnter') + t('common.newPassword') || '请输入新密码');
       return;
     }
 
@@ -242,7 +242,7 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
       setResetPwdPassword('');
       setResetPwdUser(null);
     } catch (error: any) {
-      toast.error(error.message || '重置密码失败');
+      toast.error(error.message || t('common.resetPasswordFailed') || '重置密码失败');
     } finally {
       setResetPwdLoading(false);
     }
@@ -262,42 +262,42 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
   // 表格列配置
   const columns: ColumnsType<UserVO> = [
     {
-      title: '序号',
+      title: t('common.serialNumber'),
       width: '5%',
       render: (_: any, __: UserVO, index: number) => {
         return (queryParams.pageNo - 1) * queryParams.pageSize + index + 1;
       },
     },
     {
-      title: '用户编号',
+      title: t('table.userId'),
       dataIndex: 'id',
       width: '8%',
     },
     {
-      title: '账号',
+      title: t('table.username'),
       dataIndex: 'username',
       width: '10%',
     },
     {
-      title: '用户名',
+      title: t('table.nickname'),
       dataIndex: 'nickname',
       width: '10%',
     },
     {
-      title: '手机号码',
+      title: t('table.mobile'),
       dataIndex: 'mobile',
       width: '12%',
       render: (text: string) => text || '-',
     },
     {
-      title: '部门',
+      title: t('table.department'),
       width: '10%',
       render: (_: any, record: UserVO) => {
         return (record as any).deptName || '-';
       },
     },
     {
-      title: '岗位',
+      title: t('table.position'),
       width: '10%',
       render: (_: any, record: UserVO) => {
         // 根据 postIds 匹配岗位名称
@@ -339,7 +339,7 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
       },
     },
     {
-      title: '人脸照片',
+      title: t('table.facePhoto'),
       width: '8%',
       render: (_: any, record: UserVO) => (
         <Button
@@ -347,12 +347,12 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
           onClick={() => openFaceOrFingerForm('face', record)}
           style={{ padding: 0 }}
         >
-          查看
+          {t('common.view')}
         </Button>
       ),
     },
     {
-      title: '状态',
+      title: t('table.status'),
       width: '8%',
       render: (_: any, record: UserVO) => (
         <Switch
@@ -368,26 +368,26 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
       ),
     },
     {
-      title: '操作',
+      title: t('table.operation'),
       width: '10%',
       align: 'center',
       render: (_: any, record: UserVO) => {
         const menuItems = [
           {
             key: 'delete',
-            label: '删除',
+            label: t('common.delete'),
             icon: <DeleteOutlined />,
             onClick: () => handleDelete(record.id, record.username),
           },
           {
             key: 'resetPwd',
-            label: '重置密码',
+            label: t('common.resetPassword'),
             icon: <KeyOutlined />,
             onClick: () => handleResetPwd(record),
           },
           {
             key: 'assignRole',
-            label: '分配角色',
+            label: t('common.assignRole'),
             icon: <UserSwitchOutlined />,
             onClick: () => handleRole(record),
           },
@@ -427,7 +427,7 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
                 }}
               >
                 <Edit2 className="w-4 h-4" style={{ color: '#000000' }} />
-                <span className="ml-1">编辑</span>
+                <span className="ml-1">{t('common.edit')}</span>
               </UIButton>
             </PermissionWrapper>
             {filteredMenuItems.length > 0 && (
@@ -479,7 +479,7 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
                 }}
               >
                 <MoreVertical className="w-4 h-4" style={{ color: '#000000' }} />
-                <span style={{ color: '#000000' }}>更多</span>
+                <span style={{ color: '#000000' }}>{t('common.more')}</span>
               </a>
               </Dropdown>
             )}
@@ -513,34 +513,34 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
               {/* 搜索输入框 */}
               <div className="flex items-center gap-2 lg:gap-3 flex-wrap flex-1 min-w-0">
                 <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">用户名:</label>
+                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.nickname')}:</label>
                   <Input
                     value={queryParams.nickname}
                     onChange={(e) => setQueryParams({ ...queryParams, nickname: e.target.value })}
                     onPressEnter={handleQuery}
-                    placeholder="请输入用户名"
+                    placeholder={t('form.nicknamePlaceholder')}
                     className="min-w-[150px] max-w-[200px]"
                     allowClear
                   />
                 </div>
                 <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">账号:</label>
+                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.username')}:</label>
                   <Input
                     value={queryParams.username}
                     onChange={(e) => setQueryParams({ ...queryParams, username: e.target.value })}
                     onPressEnter={handleQuery}
-                    placeholder="请输入账号"
+                    placeholder={t('form.usernamePlaceholder')}
                     className="min-w-[150px] max-w-[200px]"
                     allowClear
                   />
                 </div>
                 <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">手机号码:</label>
+                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.mobile')}:</label>
                   <Input
                     value={queryParams.mobile}
                     onChange={(e) => setQueryParams({ ...queryParams, mobile: e.target.value })}
                     onPressEnter={handleQuery}
-                    placeholder="请输入手机号码"
+                    placeholder={t('form.mobilePlaceholder')}
                     className="min-w-[150px] max-w-[200px]"
                     allowClear
                   />
@@ -555,7 +555,7 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
                     icon={<Search className="w-4 h-4" />}
                     onClick={handleQuery}
                   >
-                    搜索
+                    {t('common.search')}
                   </Button>
                 </PermissionWrapper>
                 
@@ -564,7 +564,7 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
                     icon={<RefreshCw className="w-4 h-4" />}
                     onClick={resetQuery}
                   >
-                    重置
+                    {t('common.reset')}
                   </Button>
                 </PermissionWrapper>
                 
@@ -574,7 +574,7 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
                     icon={<Plus className="w-4 h-4" />}
                     onClick={() => openForm('create')}
                   >
-                    新增
+                    {t('common.addNew')}
                   </Button>
                 </PermissionWrapper>
                 
@@ -583,7 +583,7 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
                     icon={<Upload className="w-4 h-4" />}
                     onClick={handleImport}
                   >
-                    导入
+                    {t('common.import')}
                   </Button>
                 </PermissionWrapper>
                 
@@ -593,7 +593,7 @@ export default function UserManagement({ subMenu }: UserManagementProps) {
                     onClick={handleExport}
                     loading={exportLoading}
                   >
-                    导出
+                    {t('common.export')}
                   </Button>
                 </PermissionWrapper>
               </Space>

+ 24 - 22
src/components/lockCabinet/HardwareLockCabinetManagement.tsx

@@ -8,9 +8,11 @@ import { Table, Image, Input, Select, Space, Button as AntButton, Tooltip } from
 import { SearchOutlined, ReloadOutlined } from '@ant-design/icons';
 import { Button } from '../ui/button';
 import { useNavigate } from 'react-router-dom';
+import { useTranslation } from 'react-i18next';
 
 export default function HardwareLockCabinetManagement() {
   console.log('HardwareLockCabinetManagement: 组件开始渲染');
+  const { t } = useTranslation();
   const navigate = useNavigate();
   const [loading, setLoading] = useState(true);
   const [list, setList] = useState<LockCabinetVO[]>([]);
@@ -157,9 +159,9 @@ export default function HardwareLockCabinetManagement() {
             {/* 搜索条件 */}
             <div className="flex items-center gap-2 lg:gap-3 flex-wrap flex-1 min-w-0">
               <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-                <label className="text-sm font-medium text-gray-700 whitespace-nowrap">锁柜名称:</label>
+                <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.cabinetName')}:</label>
                 <Input
-                  placeholder="请输入锁柜名称"
+                  placeholder={t('form.cabinetNamePlaceholder')}
                   value={queryParams.cabinetName || ''}
                   onChange={(e) => setQueryParams(prev => ({ ...prev, cabinetName: e.target.value }))}
                   onPressEnter={handleQuery}
@@ -169,9 +171,9 @@ export default function HardwareLockCabinetManagement() {
               </div>
 
               <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-                <label className="text-sm font-medium text-gray-700 whitespace-nowrap">是否在线:</label>
+                <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('common.onlineStatus')}:</label>
                 <Select
-                  placeholder="请选择是否在线"
+                  placeholder={t('common.pleaseSelect')}
                   value={queryParams.isOnline || undefined}
                   onChange={(value) => setQueryParams(prev => ({ ...prev, isOnline: value }))}
                   className="min-w-[150px] max-w-[200px]"
@@ -200,14 +202,14 @@ export default function HardwareLockCabinetManagement() {
                 icon={<SearchOutlined />}
                 onClick={handleQuery}
               >
-                搜索
+                {t('common.search')}
               </AntButton>
               
               <AntButton
                 icon={<ReloadOutlined />}
                 onClick={resetQuery}
               >
-                重置
+                {t('common.reset')}
               </AntButton>
             </Space>
           </div>
@@ -224,38 +226,38 @@ export default function HardwareLockCabinetManagement() {
           loading={loading}
           dataSource={list}
           locale={{
-            emptyText: loading ? '加载中...' : '暂无数据',
+            emptyText: loading ? t('common.loading') : t('common.noData'),
           }}
           columns={[
             {
-              title: '锁柜名称',
+              title: t('table.cabinetName'),
               dataIndex: 'cabinetName',
               key: 'cabinetName',
               width: 150,
             },
             {
-              title: '硬件ID',
+              title: t('table.hardwareId'),
               dataIndex: 'hardwareId',
               key: 'hardwareId',
               width: 120,
               render: (text) => text || '-',
             },
             {
-              title: '硬件序列号',
+              title: t('table.hardwareSerial'),
               dataIndex: 'serialNumber',
               key: 'serialNumber',
               width: 150,
               render: (text) => text || '-',
             },
             {
-              title: '岗位',
+              title: t('table.position'),
               dataIndex: 'workstationName',
               key: 'workstationName',
               width: 150,
               render: (text) => text || '-',
             },
             {
-              title: '图片',
+              title: t('table.image'),
               dataIndex: 'cabinetPicture',
               key: 'cabinetPicture',
               width: 100,
@@ -264,19 +266,19 @@ export default function HardwareLockCabinetManagement() {
                 return (
                   <Image
                     src={url}
-                    alt="图片"
+                    alt={t('table.image')}
                     width={50}
                     height={50}
                     style={{ objectFit: 'cover', cursor: 'pointer' }}
                     preview={{
-                      mask: '查看',
+                      mask: t('common.view'),
                     }}
                   />
                 );
               },
             },
             {
-              title: '图标',
+              title: t('table.icon'),
               dataIndex: 'cabinetIcon',
               key: 'cabinetIcon',
               width: 100,
@@ -285,26 +287,26 @@ export default function HardwareLockCabinetManagement() {
                 return (
                   <Image
                     src={url}
-                    alt="图标"
+                    alt={t('table.icon')}
                     width={50}
                     height={50}
                     style={{ objectFit: 'cover', cursor: 'pointer' }}
                     preview={{
-                      mask: '查看',
+                      mask: t('common.view'),
                     }}
                   />
                 );
               },
             },
             {
-              title: '是否在线',
+              title: t('common.onlineStatus'),
               dataIndex: 'isOnline',
               key: 'isOnline',
               width: 100,
               render: (value: string) => getDictLabel(DICT_TYPE.ISONLINE_STATUS, value) || '-',
             },
             {
-              title: '状态',
+              title: t('table.status'),
               dataIndex: 'status',
               key: 'status',
               width: 100,
@@ -324,7 +326,7 @@ export default function HardwareLockCabinetManagement() {
               },
             },
             {
-              title: '备注',
+              title: t('table.remark'),
               dataIndex: 'remark',
               key: 'remark',
               width: 150,
@@ -342,14 +344,14 @@ export default function HardwareLockCabinetManagement() {
               },
             },
             {
-              title: '创建时间',
+              title: t('table.createTime'),
               dataIndex: 'createTime',
               key: 'createTime',
               width: 180,
               render: (text) => text ? dateFormatter(text) : '-',
             },
             {
-              title: '详情',
+              title: t('common.detail'),
               key: 'detail',
               width: 80,
               align: 'center',

+ 39 - 37
src/components/lockCabinet/SystemLockCabinetManagement.tsx

@@ -12,8 +12,10 @@ import LockCabinetForm, { LockCabinetFormRef } from './LockCabinetForm';
 import { ImageWithFallback } from '../figma/ImageWithFallback';
 import { useNavigate } from 'react-router-dom';
 import PermissionWrapper from '../PermissionWrapper';
+import { useTranslation } from 'react-i18next';
 
 export default function SystemLockCabinetManagement() {
+  const { t } = useTranslation();
   const navigate = useNavigate();
   const [loading, setLoading] = useState(true);
   const [list, setList] = useState<LockCabinetVO[]>([]);
@@ -141,7 +143,7 @@ export default function SystemLockCabinetManagement() {
     if (formRef.current) {
       formRef.current.open(type, id);
     } else {
-      toast.error('表单组件未初始化,请刷新页面重试');
+      toast.error(t('common.formNotInitialized') || '表单组件未初始化,请刷新页面重试');
     }
   };
 
@@ -157,30 +159,30 @@ export default function SystemLockCabinetManagement() {
   const handleDelete = async (id?: number) => {
     const ids = id ? [id] : selectedIds;
     if (ids.length === 0) {
-      toast.error('请选择要删除的数据');
+      toast.error(t('common.pleaseSelect'));
       return;
     }
 
     Modal.confirm({
-      title: '确认删除',
+      title: t('common.confirmDelete'),
       icon: <ExclamationCircleOutlined />,
       content: (
         <div>
-          <p>确定要删除选中的 {ids.length} 条机柜数据吗?</p>
-          <p style={{ color: '#ff4d4f', marginTop: '8px' }}>删除后无法恢复,请谨慎操作!</p>
+          <p>{t('common.confirmDeleteText')} {ids.length} {t('common.items')}?</p>
+          <p style={{ color: '#ff4d4f', marginTop: '8px' }}>{t('common.confirmDeleteWarning')}</p>
         </div>
       ),
-      okText: '确定删除',
+      okText: t('common.confirmDelete'),
       okType: 'danger',
-      cancelText: '取消',
+      cancelText: t('common.cancel'),
       onOk: async () => {
         try {
           await lockCabinetApi.deleteIsLockCabinetByCabinetIds(ids.join(','));
-          toast.success('删除成功');
+          toast.success(t('common.deleteSuccess'));
           setSelectedIds([]);
           await getList();
         } catch (error: any) {
-          toast.error(error.message || '删除失败');
+          toast.error(error.message || t('common.deleteFailed'));
         }
       },
     });
@@ -204,9 +206,9 @@ export default function SystemLockCabinetManagement() {
           {/* 搜索条件 */}
           <div className="flex items-center gap-2 lg:gap-3 flex-wrap flex-1 min-w-0">
             <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">锁柜名称:</label>
+              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('form.cabinetName')}:</label>
               <Input
-                placeholder="请输入锁柜名称"
+                placeholder={t('form.cabinetNamePlaceholder')}
                 value={queryParams.cabinetName || ''}
                 onChange={(e) => setQueryParams(prev => ({ ...prev, cabinetName: e.target.value }))}
                 onPressEnter={handleQuery}
@@ -216,9 +218,9 @@ export default function SystemLockCabinetManagement() {
             </div>
 
             <div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
-              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">是否在线:</label>
+              <label className="text-sm font-medium text-gray-700 whitespace-nowrap">{t('common.onlineStatus')}:</label>
               <Select
-                placeholder="请选择是否在线"
+                placeholder={t('common.pleaseSelect')}
                 value={queryParams.isOnline || undefined}
                 onChange={(value) => setQueryParams(prev => ({ ...prev, isOnline: value }))}
                 className="min-w-[150px] max-w-[200px]"
@@ -232,8 +234,8 @@ export default function SystemLockCabinetManagement() {
                   ))
                 ) : (
                   <>
-                    <Select.Option value="0">离线</Select.Option>
-                    <Select.Option value="1">在线</Select.Option>
+                    <Select.Option value="0">{t('common.offline')}</Select.Option>
+                    <Select.Option value="1">{t('common.online')}</Select.Option>
                   </>
                 )}
               </Select>
@@ -248,7 +250,7 @@ export default function SystemLockCabinetManagement() {
                 icon={<SearchOutlined />}
                 onClick={handleQuery}
               >
-                搜索
+                {t('common.search')}
               </AntButton>
             </PermissionWrapper>
             
@@ -257,7 +259,7 @@ export default function SystemLockCabinetManagement() {
                 icon={<ReloadOutlined />}
                 onClick={resetQuery}
               >
-                重置
+                {t('common.reset')}
               </AntButton>
             </PermissionWrapper>
 
@@ -267,7 +269,7 @@ export default function SystemLockCabinetManagement() {
                 icon={<PlusOutlined />}
                 onClick={() => openForm('create')}
               >
-                新增
+                {t('common.addNew')}
               </AntButton>
             </PermissionWrapper>
 
@@ -298,34 +300,34 @@ export default function SystemLockCabinetManagement() {
           // rowSelection={rowSelection}
           columns={[
             {
-              title: '锁柜名称',
+              title: t('table.cabinetName'),
               dataIndex: 'cabinetName',
               key: 'cabinetName',
               width: 150,
             },
             {
-              title: '硬件ID',
+              title: t('table.hardwareId'),
               dataIndex: 'hardwareId',
               key: 'hardwareId',
               width: 120,
               render: (text) => text || '-',
             },
             {
-              title: '硬件序列号',
+              title: t('table.hardwareSerial'),
               dataIndex: 'serialNumber',
               key: 'serialNumber',
               width: 150,
               render: (text) => text || '-',
             },
             {
-              title: '岗位',
+              title: t('table.position'),
               dataIndex: 'workstationName',
               key: 'workstationName',
               width: 150,
               render: (text) => text || '-',
             },
             {
-              title: '图片',
+              title: t('table.image'),
               dataIndex: 'cabinetPicture',
               key: 'cabinetPicture',
               width: 100,
@@ -334,19 +336,19 @@ export default function SystemLockCabinetManagement() {
                 return (
                   <Image
                     src={url}
-                    alt="图片"
+                    alt={t('table.image')}
                     width={50}
                     height={50}
                     style={{ objectFit: 'cover', cursor: 'pointer' }}
                     preview={{
-                      mask: '查看',
+                      mask: t('common.view'),
                     }}
                   />
                 );
               },
             },
             {
-              title: '图标',
+              title: t('table.icon'),
               dataIndex: 'cabinetIcon',
               key: 'cabinetIcon',
               width: 100,
@@ -355,26 +357,26 @@ export default function SystemLockCabinetManagement() {
                 return (
                   <Image
                     src={url}
-                    alt="图标"
+                    alt={t('table.icon')}
                     width={50}
                     height={50}
                     style={{ objectFit: 'cover', cursor: 'pointer' }}
                     preview={{
-                      mask: '查看',
+                      mask: t('common.view'),
                     }}
                   />
                 );
               },
             },
             {
-              title: '是否在线',
+              title: t('common.onlineStatus'),
               dataIndex: 'isOnline',
               key: 'isOnline',
               width: 100,
               render: (value: string) => getDictLabel(DICT_TYPE.ISONLINE_STATUS, value) || '-',
             },
             {
-              title: '状态',
+              title: t('table.status'),
               dataIndex: 'status',
               key: 'status',
               width: 100,
@@ -394,7 +396,7 @@ export default function SystemLockCabinetManagement() {
               },
             },
             {
-              title: '备注',
+              title: t('table.remark'),
               dataIndex: 'remark',
               key: 'remark',
               width: 150,
@@ -412,14 +414,14 @@ export default function SystemLockCabinetManagement() {
               },
             },
             {
-              title: '创建时间',
+              title: t('table.createTime'),
               dataIndex: 'createTime',
               key: 'createTime',
               width: 180,
               render: (text) => text ? dateFormatter(text) : '-',
             },
             {
-              title: '详情',
+              title: t('common.detail'),
               key: 'detail',
               width: 80,
               align: 'center',
@@ -432,13 +434,13 @@ export default function SystemLockCabinetManagement() {
                     className="h-8 px-2"
                   >
                     <Eye className="w-4 h-4" />
-                    <span className="ml-1">查看</span>
+                    <span className="ml-1">{t('common.view')}</span>
                   </Button>
                 </PermissionWrapper>
               ),
             },
             {
-              title: '操作',
+              title: t('table.operation'),
               key: 'action',
               width: 150,
               align: 'center',
@@ -461,7 +463,7 @@ export default function SystemLockCabinetManagement() {
                       }}
                     >
                       <Edit2 className="w-4 h-4" style={{ color: '#000000' }} />
-                      <span className="ml-1">编辑</span>
+                      <span className="ml-1">{t('common.edit')}</span>
                     </Button>
                   </PermissionWrapper>
                   <PermissionWrapper permission="iscs:lock-cabinet:delete">
@@ -481,7 +483,7 @@ export default function SystemLockCabinetManagement() {
                       }}
                     >
                       <Trash2 className="w-4 h-4" style={{ color: '#000000' }} />
-                      <span className="ml-1">删除</span>
+                      <span className="ml-1">{t('common.delete')}</span>
                     </Button>
                   </PermissionWrapper>
                 </div>

+ 4 - 2
src/components/user/DeptTree.tsx

@@ -4,12 +4,14 @@ import { deptApi } from '../../api/dept';
 import { WorkstationNode } from '../../types';
 import { handleTree } from '../../utils/tree';
 import { toast } from 'sonner';
+import { useTranslation } from 'react-i18next';
 
 interface DeptTreeProps {
   onNodeClick: (node: WorkstationNode) => void;
 }
 
 export default function DeptTree({ onNodeClick }: DeptTreeProps) {
+  const { t } = useTranslation();
   const [deptName, setDeptName] = useState('');
   const [deptList, setDeptList] = useState<WorkstationNode[]>([]);
   const [expandedIds, setExpandedIds] = useState<number[]>([]);
@@ -140,7 +142,7 @@ export default function DeptTree({ onNodeClick }: DeptTreeProps) {
             type="text"
             value={deptName}
             onChange={(e) => setDeptName(e.target.value)}
-            placeholder="请输入部门名称"
+            placeholder={t('form.departmentNamePlaceholder')}
             className="w-full h-9 pl-9 pr-3 bg-gray-50 border border-gray-200 rounded-lg outline-none focus:border-blue-400 focus:ring-2 focus:ring-blue-100 transition-all text-sm"
           />
         </div>
@@ -154,7 +156,7 @@ export default function DeptTree({ onNodeClick }: DeptTreeProps) {
         ) : (
           <div className="space-y-1">
             {deptList.length === 0 ? (
-              <div className="text-center py-8 text-gray-400 text-sm">暂无数据</div>
+              <div className="text-center py-8 text-gray-400 text-sm">{t('common.noData')}</div>
             ) : (
               renderTreeNode(deptList, 0)
             )}

+ 313 - 3
src/locales/en.json

@@ -61,11 +61,14 @@
     "settings": "Settings",
     "logout": "Logout",
     "notifications": "Notifications",
-    "dashboard": "Dashboard"
+    "dashboard": "Dashboard",
+    "switchToEnglish": "EN",
+    "switchToChinese": "中文"
   },
   "systemConfig": {
     "menuManagement": "Menu",
     "departmentManagement": "Department",
+    "positionManagement": "Position",
     "roleManagement": "Role",
     "dictionaryManagement": "Dictionary",
     "cabinetManagement": "Cabinet"
@@ -83,7 +86,11 @@
   "isolationWork": {
     "processTemplate": "Process Template",
     "sopManagement": "SOP",
-    "workManagement": "Work Management"
+    "workManagement": "Work Management",
+    "processDesign": "Process Design",
+    "formManagement": "Form Management",
+    "myTask": "My Tasks",
+    "taskManagement": "Task Management"
   },
   "common": {
     "loading": "Loading...",
@@ -95,12 +102,315 @@
     "delete": "Delete",
     "edit": "Edit",
     "add": "Add",
+    "addNew": "Add New",
     "search": "Search",
     "reset": "Reset",
     "submit": "Submit",
     "back": "Back",
     "next": "Next",
-    "previous": "Previous"
+    "previous": "Previous",
+    "user": "User",
+    "pleaseInput": "Please enter",
+    "pleaseSelectDate": "Please select date",
+    "pleaseSelectDateRange": "Please select date range",
+    "pleaseSelectDateTime": "Please select date time",
+    "pleaseSelectTime": "Please select time",
+    "startDate": "Start Date",
+    "endDate": "End Date",
+    "uploadFile": "Upload File",
+    "upload": "Upload",
+    "cardContainer": "Card Container",
+    "featureInDevelopment": "Feature in Development",
+    "refresh": "Refresh",
+    "refreshCache": "Refresh Cache",
+    "expandAll": "Expand All",
+    "collapseAll": "Collapse All",
+    "expand": "Expand",
+    "collapse": "Collapse",
+    "confirmDelete": "Confirm Delete",
+    "confirmDeleteText": "Are you sure you want to delete",
+    "confirmDeleteWarning": "This action cannot be undone. Please proceed with caution!",
+    "deleteSuccess": "Delete successful",
+    "deleteFailed": "Delete failed",
+    "updateSuccess": "Update successful",
+    "updateFailed": "Update failed",
+    "saveSuccess": "Save successful",
+    "saveFailed": "Save failed",
+    "operation": "Operation",
+    "status": "Status",
+    "enabled": "Enabled",
+    "disabled": "Disabled",
+    "active": "Active",
+    "inactive": "Inactive",
+    "yes": "Yes",
+    "no": "No",
+    "pleaseEnter": "Please enter",
+    "pleaseSelect": "Please select",
+    "noData": "No data",
+    "required": "Required",
+    "onlineStatus": "Online Status",
+    "online": "Online",
+    "offline": "Offline",
+    "batchDelete": "Batch Delete",
+    "detail": "Detail",
+    "view": "View",
+    "items": "items",
+    "import": "Import",
+    "export": "Export",
+    "more": "More",
+    "resetPassword": "Reset Password",
+    "assignRole": "Assign Role",
+    "facePhoto": "Face Photo",
+    "serialNumber": "Serial Number",
+    "userId": "User ID",
+    "username": "Username",
+    "nickname": "Nickname",
+    "mobile": "Mobile",
+    "department": "Department",
+    "confirmOperation": "Confirm Operation",
+    "confirmText": "Are you sure to",
+    "addSuccess": "Add successful",
+    "newPassword": "New Password",
+    "resetPasswordFailed": "Reset Password Failed",
+    "setPadLockType": "Set Padlock Type",
+    "total": "Total",
+    "records": "records",
+    "prevPage": "Previous",
+    "nextPage": "Next",
+    "addTemplate": "Add Template",
+    "editTemplate": "Edit Process Template",
+    "addTemplateTitle": "Add Process Template",
+    "editProcessDesign": "Edit Process Design",
+    "addProcessDesign": "New Process Design",
+    "design": "Design",
+    "editWork": "Edit Work",
+    "addWork": "New Work",
+    "editFormManagement": "Edit Form Management",
+    "addFormManagement": "New Form Management"
+  },
+  "table": {
+    "name": "Name",
+    "menuName": "Menu Name",
+    "icon": "Icon",
+    "sort": "Sort",
+    "permission": "Permission",
+    "componentPath": "Component Path",
+    "componentName": "Component Name",
+    "status": "Status",
+    "operation": "Operation",
+    "createTime": "Create Time",
+    "updateTime": "Update Time",
+    "remark": "Remark",
+    "description": "Description",
+    "departmentName": "Department Name",
+    "leader": "Leader",
+    "roleName": "Role Name",
+    "roleCode": "Role Code",
+    "roleId": "ID",
+    "postName": "Post Name",
+    "postCode": "Post Code",
+    "postId": "Post ID",
+    "postSort": "Post Sort",
+    "postRemark": "Post Remark",
+    "dictName": "Dictionary Name",
+    "dictType": "Dictionary Type",
+    "dictId": "ID",
+    "cabinetName": "Cabinet Name",
+    "hardwareId": "Hardware ID",
+    "hardwareSerial": "Hardware Serial Number",
+    "position": "Position",
+    "image": "Image",
+    "userId": "User ID",
+    "username": "Username",
+    "nickname": "Nickname",
+    "mobile": "Mobile",
+    "department": "Department",
+    "facePhoto": "Face Photo",
+    "keyName": "Key Name",
+    "keyNfc": "Key NFC",
+    "keySpec": "Key Model",
+    "macAddress": "MAC Address",
+    "hardwareName": "Hardware",
+    "padLockName": "Padlock Name",
+    "padLockNfc": "Padlock NFC",
+    "padLockType": "Padlock Type",
+    "padLockModel": "Padlock Model",
+    "padLockTypeName": "Padlock Type Name",
+    "padLockTypeIcon": "Padlock Type Icon",
+    "padLockTypeImage": "Padlock Type Image",
+    "editPadLock": "Edit Padlock",
+    "addPadLock": "Add Padlock",
+    "editPadLockType": "Edit Padlock Type",
+    "addPadLockType": "Add Padlock Type",
+    "segregationPointId": "ID",
+    "segregationPointName": "Segregation Point Name",
+    "segregationPointNfc": "Segregation Point NFC",
+    "segregationPointSerial": "Segregation Point Serial Number",
+    "switchStatus": "Switch Status",
+    "deviceProcess": "Equipment/Process",
+    "lotoStation": "Lockout Station",
+    "energySource": "Energy Source",
+    "function": "Function",
+    "templateCode": "Template Code",
+    "templateName": "Template Name",
+    "templateType": "Type",
+    "templateCategory": "Category",
+    "stepCount": "Step Count",
+    "approvalLevel": "Approval Level",
+    "creator": "Creator",
+    "useCount": "Usage Count",
+    "view": "View",
+    "designer": "Designer",
+    "designTime": "Design Time",
+    "nodeCount": "Task Count",
+    "processDesignId": "ID",
+    "workOrderNo": "Work Order No",
+    "workName": "Work Name",
+    "workStatus": "Work Status",
+    "currentTask": "Current Task",
+    "workContent": "Work Content",
+    "initiator": "Initiator",
+    "initiationTime": "Initiation Time",
+    "urgencyLevel": "Urgency Level",
+    "formName": "Form Name",
+    "formId": "ID",
+    "version": "Version"
+  },
+  "form": {
+    "menuName": "Menu Name",
+    "menuNamePlaceholder": "Please enter menu name",
+    "icon": "Icon",
+    "iconPlaceholder": "Please select icon",
+    "sort": "Sort",
+    "sortPlaceholder": "Please enter sort number",
+    "permission": "Permission",
+    "permissionPlaceholder": "Please enter permission",
+    "componentPath": "Component Path",
+    "componentPathPlaceholder": "Please enter component path",
+    "componentName": "Component Name",
+    "componentNamePlaceholder": "Please enter component name",
+    "status": "Status",
+    "remark": "Remark",
+    "remarkPlaceholder": "Please enter remark",
+    "departmentName": "Department Name",
+    "departmentNamePlaceholder": "Please enter department name",
+    "postName": "Post Name",
+    "postNamePlaceholder": "Please enter post name",
+    "postCode": "Post Code",
+    "postCodePlaceholder": "Please enter post code",
+    "roleName": "Role Name",
+    "roleNamePlaceholder": "Please enter role name",
+    "roleCode": "Role Code",
+    "roleCodePlaceholder": "Please enter role code",
+    "dictName": "Dictionary Name",
+    "dictNamePlaceholder": "Please enter dictionary name",
+    "dictType": "Dictionary Type",
+    "dictTypePlaceholder": "Please enter dictionary type",
+    "cabinetName": "Cabinet Name",
+    "cabinetNamePlaceholder": "Please enter cabinet name",
+    "nickname": "Nickname",
+    "nicknamePlaceholder": "Please enter nickname",
+    "username": "Username",
+    "usernamePlaceholder": "Please enter username",
+    "mobile": "Mobile",
+    "mobilePlaceholder": "Please enter mobile number",
+    "keyName": "Key Name",
+    "keyNamePlaceholder": "Please enter key name",
+    "keyNfc": "Key NFC",
+    "keySpec": "Key Model",
+    "macAddress": "MAC Address",
+    "hardwareName": "Hardware",
+    "editKey": "Edit Key",
+    "addKey": "Add Key",
+    "padLockName": "Padlock Name",
+    "padLockNamePlaceholder": "Please enter padlock name",
+    "padLockCode": "Padlock Code",
+    "padLockCodePlaceholder": "Please enter padlock code",
+    "padLockTypeName": "Padlock Type Name",
+    "padLockTypeNamePlaceholder": "Please enter padlock type name",
+    "padLockTypeCode": "Padlock Type Code",
+    "padLockTypeCodePlaceholder": "Please enter padlock type code",
+    "editPadLock": "Edit Padlock",
+    "addPadLock": "Add Padlock",
+    "editPadLockType": "Edit Padlock Type",
+    "addPadLockType": "Add Padlock Type",
+    "hardwareNamePlaceholder": "Please select hardware",
+    "segregationPointName": "Segregation Point Name",
+    "segregationPointNamePlaceholder": "Please enter segregation point name",
+    "workstation": "Position",
+    "workstationPlaceholder": "Select position",
+    "deviceProcess": "Equipment/Process",
+    "deviceProcessPlaceholder": "Select equipment/process",
+    "lotoStation": "Lockout Station",
+    "lotoStationPlaceholder": "Please select lockout station",
+    "energySource": "Energy Source",
+    "energySourcePlaceholder": "Please select energy source",
+    "templateName": "Template Name",
+    "templateNamePlaceholder": "Please enter template name",
+    "searchTemplate": "Search process template",
+    "processDesignName": "Name",
+    "processDesignNamePlaceholder": "Please enter name",
+    "addProcess": "New Process",
+    "workName": "Work Name",
+    "workNamePlaceholder": "Please enter work name",
+    "workStatus": "Work Status",
+    "workStatusPlaceholder": "Please select work status",
+    "initiateWork": "Initiate Work",
+    "formName": "Form Name",
+    "formNamePlaceholder": "Please enter form name",
+    "addForm": "New Form",
+    "formId": "ID",
+    "formStatus": "Status",
+    "formRemark": "Remark",
+    "formCreateTime": "Create Time",
+    "formOperation": "Operation",
+    "copy": "Copy",
+    "preview": "Preview",
+    "open": "Open",
+    "closed": "Closed",
+    "confirmDeleteForm": "Confirm Delete",
+    "confirmDeleteFormText": "Are you sure you want to delete this form data?",
+    "deleteFormSuccess": "Delete successful",
+    "deleteFormFailed": "Delete failed",
+    "fetchFormListFailed": "Failed to fetch form list",
+    "fetchFormDetailFailed": "Failed to fetch form details",
+    "formDetail": "Form Details",
+    "formPreviewTip": "This is a form preview only, submitting has no effect",
+    "totalRecords": "Total",
+    "recordsUnit": "records",
+    "page": "Page",
+    "taskManagement": "Task Management",
+    "taskSearchPlaceholder": "Please enter work order number or work order name to query",
+    "taskId": "ID",
+    "taskName": "Work Name",
+    "currentTask": "Current Task",
+    "taskStatus": "Task Status",
+    "responsiblePerson": "Responsible Person",
+    "taskStartTime": "Task Start Time",
+    "urgencyLevel": "Urgency Level",
+    "noData": "No data",
+    "handleNow": "Handle Now",
+    "viewDetail": "View Detail",
+    "workDetail": "Work Detail",
+    "workOrderNo": "Work Order No",
+    "workResponsible": "Work Responsible",
+    "taskResponsible": "Task Responsible",
+    "initiationTime": "Initiation Time",
+    "reviewComment": "Review Comment",
+    "reviewCommentPlaceholder": "Please enter review comment",
+    "reviewReject": "Reject",
+    "reviewApprove": "Approve",
+    "reviewRejectSuccess": "Rejection successful",
+    "reviewApproveSuccess": "Approval successful",
+    "reviewRejectFailed": "Rejection failed",
+    "reviewApproveFailed": "Approval failed",
+    "formLoading": "Form loading...",
+    "noFormContent": "No form content",
+    "lockCabinetTip": "Please go to the lock cabinet to get the lock and key",
+    "loading": "Loading...",
+    "completeSuccess": "Completed successfully",
+    "complete": "Complete",
+    "fetchTaskListFailed": "Failed to fetch task list"
   }
 }
 

+ 312 - 3
src/locales/zh.json

@@ -61,11 +61,14 @@
     "settings": "账号设置",
     "logout": "退出登录",
     "notifications": "通知",
-    "dashboard": "驾驶舱"
+    "dashboard": "驾驶舱",
+    "switchToEnglish": "EN",
+    "switchToChinese": "中文"
   },
   "systemConfig": {
     "menuManagement": "菜单管理",
     "departmentManagement": "部门管理",
+    "positionManagement": "岗位管理",
     "roleManagement": "角色管理",
     "dictionaryManagement": "字典管理",
     "cabinetManagement": "机柜管理"
@@ -83,7 +86,11 @@
   "isolationWork": {
     "processTemplate": "流程模板",
     "sopManagement": "SOP管理",
-    "workManagement": "作业管理"
+    "workManagement": "作业管理",
+    "processDesign": "流程设计",
+    "formManagement": "表单管理",
+    "myTask": "我的任务",
+    "taskManagement": "任务管理"
   },
   "common": {
     "loading": "加载中...",
@@ -95,12 +102,314 @@
     "delete": "删除",
     "edit": "编辑",
     "add": "添加",
+    "addNew": "新增",
     "search": "搜索",
     "reset": "重置",
     "submit": "提交",
     "back": "返回",
     "next": "下一步",
-    "previous": "上一步"
+    "previous": "上一步",
+    "user": "用户",
+    "pleaseInput": "请输入",
+    "pleaseSelectDate": "请选择日期",
+    "pleaseSelectDateRange": "请选择日期范围",
+    "pleaseSelectDateTime": "请选择日期时间",
+    "pleaseSelectTime": "请选择时间",
+    "startDate": "开始日期",
+    "endDate": "结束日期",
+    "uploadFile": "上传文件",
+    "upload": "上传",
+    "cardContainer": "卡片容器",
+    "featureInDevelopment": "功能开发中",
+    "refresh": "刷新",
+    "refreshCache": "刷新缓存",
+    "expandAll": "展开全部",
+    "collapseAll": "折叠全部",
+    "expand": "展开",
+    "collapse": "折叠",
+    "confirmDelete": "确认删除",
+    "confirmDeleteText": "确定要删除",
+    "confirmDeleteWarning": "删除后无法恢复,请谨慎操作!",
+    "deleteSuccess": "删除成功",
+    "deleteFailed": "删除失败",
+    "updateSuccess": "更新成功",
+    "updateFailed": "更新失败",
+    "saveSuccess": "保存成功",
+    "saveFailed": "保存失败",
+    "operation": "操作",
+    "status": "状态",
+    "enabled": "启用",
+    "disabled": "禁用",
+    "active": "正常",
+    "inactive": "停用",
+    "yes": "是",
+    "no": "否",
+    "pleaseEnter": "请输入",
+    "pleaseSelect": "请选择",
+    "noData": "暂无数据",
+    "required": "必填",
+    "onlineStatus": "是否在线",
+    "online": "在线",
+    "offline": "离线",
+    "batchDelete": "批量删除",
+    "detail": "详情",
+    "view": "查看",
+    "items": "条数据",
+    "import": "导入",
+    "export": "导出",
+    "more": "更多",
+    "resetPassword": "重置密码",
+    "assignRole": "分配角色",
+    "facePhoto": "人脸照片",
+    "serialNumber": "序号",
+    "userId": "用户编号",
+    "username": "账号",
+    "nickname": "用户名",
+    "mobile": "手机号码",
+    "department": "部门",
+    "confirmOperation": "确认操作",
+    "confirmText": "确定要",
+    "addSuccess": "新增成功",
+    "newPassword": "新密码",
+    "resetPasswordFailed": "重置密码失败",
+    "setPadLockType": "设置挂锁类型",
+    "total": "共",
+    "records": "条记录",
+    "prevPage": "上一页",
+    "nextPage": "下一页",
+    "addTemplate": "新增模板",
+    "editTemplate": "编辑流程模板",
+    "addTemplateTitle": "新增流程模板",
+    "editProcessDesign": "编辑流程设计",
+    "addProcessDesign": "新建流程设计",
+    "design": "设计",
+    "editWork": "编辑作业",
+    "addWork": "新建作业",
+    "editFormManagement": "编辑表单管理",
+    "addFormManagement": "新建表单管理"
+  },
+  "table": {
+    "name": "名称",
+    "menuName": "菜单名称",
+    "icon": "图标",
+    "sort": "排序",
+    "permission": "权限标识",
+    "componentPath": "组件路径",
+    "componentName": "组件名称",
+    "status": "状态",
+    "operation": "操作",
+    "createTime": "创建时间",
+    "updateTime": "更新时间",
+    "remark": "备注",
+    "description": "描述",
+    "departmentName": "部门名称",
+    "leader": "负责人",
+    "roleName": "角色名称",
+    "roleCode": "角色标识",
+    "postName": "岗位名称",
+    "postCode": "岗位编码",
+    "postId": "岗位编号",
+    "postSort": "岗位顺序",
+    "postRemark": "岗位备注",
+    "dictName": "字典名称",
+    "dictType": "字典类型",
+    "dictId": "字典编号",
+    "cabinetName": "机柜名称",
+    "hardwareId": "硬件ID",
+    "hardwareSerial": "硬件序列号",
+    "position": "岗位",
+    "image": "图片",
+    "userId": "用户编号",
+    "username": "账号",
+    "nickname": "用户名",
+    "mobile": "手机号码",
+    "department": "部门",
+    "facePhoto": "人脸照片",
+    "keyName": "钥匙名称",
+    "keyNfc": "钥匙NFC",
+    "keySpec": "钥匙型号",
+    "macAddress": "MAC地址",
+    "hardwareName": "所属硬件",
+    "padLockName": "挂锁名称",
+    "padLockNfc": "挂锁NFC",
+    "padLockType": "挂锁类型",
+    "padLockModel": "挂锁型号",
+    "padLockTypeName": "挂锁类型名称",
+    "padLockTypeIcon": "挂锁类型图标",
+    "padLockTypeImage": "挂锁类型图片",
+    "editPadLock": "编辑挂锁",
+    "addPadLock": "新增挂锁",
+    "editPadLockType": "编辑挂锁类型",
+    "addPadLockType": "新增挂锁类型",
+    "segregationPointId": "编号",
+    "segregationPointName": "隔离点名称",
+    "segregationPointNfc": "隔离点NFC",
+    "segregationPointSerial": "隔离点序列号",
+    "switchStatus": "开关状态",
+    "deviceProcess": "设备/工艺",
+    "lotoStation": "锁定站",
+    "energySource": "能量源",
+    "function": "作用",
+    "templateCode": "模板编号",
+    "templateName": "模板名称",
+    "templateType": "类型",
+    "templateCategory": "分类",
+    "stepCount": "步骤数",
+    "approvalLevel": "审批层级",
+    "creator": "创建人",
+    "useCount": "使用次数",
+    "view": "查看",
+    "designer": "设计人",
+    "designTime": "设计时间",
+    "nodeCount": "任务数量",
+    "processDesignId": "编号",
+    "workOrderNo": "作业编号",
+    "workName": "作业名称",
+    "workStatus": "作业状态",
+    "currentTask": "当前任务",
+    "workContent": "作业内容",
+    "initiator": "发起人",
+    "initiationTime": "发起时间",
+    "urgencyLevel": "紧急程度",
+    "formName": "表单名",
+    "formId": "编号",
+    "version": "版本"
+  },
+  "form": {
+    "menuName": "菜单名称",
+    "menuNamePlaceholder": "请输入菜单名称",
+    "icon": "图标",
+    "iconPlaceholder": "请选择图标",
+    "sort": "排序",
+    "sortPlaceholder": "请输入排序号",
+    "permission": "权限标识",
+    "permissionPlaceholder": "请输入权限标识",
+    "componentPath": "组件路径",
+    "componentPathPlaceholder": "请输入组件路径",
+    "componentName": "组件名称",
+    "componentNamePlaceholder": "请输入组件名称",
+    "status": "状态",
+    "remark": "备注",
+    "remarkPlaceholder": "请输入备注",
+    "departmentName": "部门名称",
+    "departmentNamePlaceholder": "请输入部门名称",
+    "postName": "岗位名称",
+    "postNamePlaceholder": "请输入岗位名称",
+    "postCode": "岗位编码",
+    "postCodePlaceholder": "请输入岗位编码",
+    "roleName": "角色名称",
+    "roleNamePlaceholder": "请输入角色名称",
+    "roleCode": "角色标识",
+    "roleCodePlaceholder": "请输入角色标识",
+    "dictName": "字典名称",
+    "dictNamePlaceholder": "请输入字典名称",
+    "dictType": "字典类型",
+    "dictTypePlaceholder": "请输入字典类型",
+    "cabinetName": "机柜名称",
+    "cabinetNamePlaceholder": "请输入机柜名称",
+    "nickname": "用户名",
+    "nicknamePlaceholder": "请输入用户名",
+    "username": "账号",
+    "usernamePlaceholder": "请输入账号",
+    "mobile": "手机号码",
+    "mobilePlaceholder": "请输入手机号码",
+    "keyName": "钥匙名称",
+    "keyNamePlaceholder": "请输入钥匙名称",
+    "keyNfc": "钥匙NFC",
+    "keySpec": "钥匙型号",
+    "macAddress": "MAC地址",
+    "hardwareName": "所属硬件",
+    "editKey": "编辑钥匙",
+    "addKey": "新增钥匙",
+    "padLockName": "挂锁名称",
+    "padLockNamePlaceholder": "请输入挂锁名称",
+    "padLockCode": "挂锁编号",
+    "padLockCodePlaceholder": "请输入挂锁编号",
+    "padLockTypeName": "挂锁类型名称",
+    "padLockTypeNamePlaceholder": "请输入挂锁类型名称",
+    "padLockTypeCode": "挂锁类型编码",
+    "padLockTypeCodePlaceholder": "请输入挂锁类型编码",
+    "editPadLock": "编辑挂锁",
+    "addPadLock": "新增挂锁",
+    "editPadLockType": "编辑挂锁类型",
+    "addPadLockType": "新增挂锁类型",
+    "hardwareNamePlaceholder": "请选择所属硬件",
+    "segregationPointName": "隔离点名称",
+    "segregationPointNamePlaceholder": "请输入隔离点名称",
+    "workstation": "岗位",
+    "workstationPlaceholder": "选择岗位",
+    "deviceProcess": "设备/工艺",
+    "deviceProcessPlaceholder": "选择设备/工艺",
+    "lotoStation": "锁定站",
+    "lotoStationPlaceholder": "请选择锁定站",
+    "energySource": "能量源",
+    "energySourcePlaceholder": "请选择能量源",
+    "templateName": "模板名称",
+    "templateNamePlaceholder": "请输入模板名称",
+    "searchTemplate": "搜索流程模板",
+    "processDesignName": "名称",
+    "processDesignNamePlaceholder": "请输入名称",
+    "addProcess": "新建流程",
+    "workName": "作业名称",
+    "workNamePlaceholder": "请输入作业名称",
+    "workStatus": "作业状态",
+    "workStatusPlaceholder": "请选择作业状态",
+    "initiateWork": "发起作业",
+    "formName": "表单名",
+    "formNamePlaceholder": "请输入表单名",
+    "addForm": "新建表单",
+    "formId": "编号",
+    "formStatus": "状态",
+    "formRemark": "备注",
+    "formCreateTime": "创建时间",
+    "formOperation": "操作",
+    "copy": "复制",
+    "preview": "预览",
+    "open": "开启",
+    "closed": "关闭",
+    "confirmDeleteForm": "确认删除",
+    "confirmDeleteFormText": "确定要删除这条表单数据吗?",
+    "deleteFormSuccess": "删除成功",
+    "deleteFormFailed": "删除失败",
+    "fetchFormListFailed": "获取表单列表失败",
+    "fetchFormDetailFailed": "获取表单详情失败",
+    "formDetail": "表单详情",
+    "formPreviewTip": "仅为表单预览,点击提交无效",
+    "totalRecords": "共",
+    "recordsUnit": "条记录",
+    "page": "页",
+    "taskManagement": "任务管理",
+    "taskSearchPlaceholder": "请输入作业编号或者作业名称进行查询",
+    "taskId": "作业编号",
+    "taskName": "作业名称",
+    "currentTask": "当前任务",
+    "taskStatus": "任务状态",
+    "responsiblePerson": "负责人",
+    "taskStartTime": "任务开始时间",
+    "urgencyLevel": "紧急程度",
+    "noData": "暂无数据",
+    "handleNow": "立即处理",
+    "viewDetail": "查看详情",
+    "workDetail": "作业详情",
+    "workOrderNo": "作业编号",
+    "workResponsible": "作业负责人",
+    "taskResponsible": "任务负责人",
+    "initiationTime": "发起时间",
+    "reviewComment": "审核意见",
+    "reviewCommentPlaceholder": "请输入审核意见",
+    "reviewReject": "审核不通过",
+    "reviewApprove": "审核通过",
+    "reviewRejectSuccess": "审核不通过操作成功",
+    "reviewApproveSuccess": "审核通过操作成功",
+    "reviewRejectFailed": "审核不通过操作失败",
+    "reviewApproveFailed": "审核通过操作失败",
+    "formLoading": "表单加载中...",
+    "noFormContent": "暂无表单内容",
+    "lockCabinetTip": "请前往锁控柜进行取锁,取钥匙操作",
+    "loading": "加载中...",
+    "completeSuccess": "完成成功",
+    "complete": "完成",
+    "fetchTaskListFailed": "获取任务管理列表失败"
   }
 }
 

+ 2 - 0
src/utils/i18n.ts

@@ -23,6 +23,8 @@ i18n
     },
     fallbackLng: 'zh', // 默认语言
     debug: false,
+    returnEmptyString: false, // 如果翻译不存在,返回键而不是空字符串
+    returnNull: false, // 如果翻译不存在,返回键而不是null
     interpolation: {
       escapeValue: false, // React 已经转义了
     },