Browse Source

feat: update:更新国际化

叶静 1 tháng trước cách đây
mục cha
commit
27eaaf51d2

+ 22 - 22
src/config/menuConfig.ts

@@ -12,7 +12,7 @@ export function getStaticMenuData() {
 				id: '1000',
 				parentId: '-1',
 				weight: 1,
-				name: '订单管理',
+				name: 'menu.orderManage',
 				path: '/order',
 				componentPath: null,
 				meta: {
@@ -21,7 +21,7 @@ export function getStaticMenuData() {
 					isKeepAlive: false,
 					icon: 'iconfont icon-document-record',
 					isAffix: false,
-					title: '订单管理',
+					title: 'menu.orderManage',
 					isHide: false,
 				},
 				sortOrder: 1,
@@ -32,7 +32,7 @@ export function getStaticMenuData() {
 						id: '1001',
 						parentId: '1000',
 						weight: 0,
-						name: '代收订单',
+						name: 'menu.payOrder',
 						path: '/order/payOrder/index',
 						componentPath: null,
 						meta: {
@@ -41,7 +41,7 @@ export function getStaticMenuData() {
 							isKeepAlive: true,
 							icon: 'iconfont icon-document-record',
 							isAffix: false,
-							title: '代收订单',
+							title: 'menu.payOrder',
 							isHide: false,
 						},
 						sortOrder: 1,
@@ -52,7 +52,7 @@ export function getStaticMenuData() {
 						id: '1002',
 						parentId: '1000',
 						weight: 0,
-						name: '代付订单',
+						name: 'menu.withdrawOrder',
 						path: '/order/withdrawOrder/index',
 						componentPath: null,
 						meta: {
@@ -61,7 +61,7 @@ export function getStaticMenuData() {
 							isKeepAlive: true,
 							icon: 'iconfont icon-document-record',
 							isAffix: false,
-							title: '代付订单',
+							title: 'menu.withdrawOrder',
 							isHide: false,
 						},
 						sortOrder: 2,
@@ -74,7 +74,7 @@ export function getStaticMenuData() {
 				id: '2000',
 				parentId: '-1',
 				weight: 1,
-				name: '支付配置',
+				name: 'menu.paymentConfig',
 				path: '/payment',
 				componentPath: null,
 				meta: {
@@ -83,7 +83,7 @@ export function getStaticMenuData() {
 					isKeepAlive: false,
 					icon: 'iconfont icon-shujuyuanguanli',
 					isAffix: false,
-					title: '支付配置',
+					title: 'menu.paymentConfig',
 					isHide: false,
 				},
 				sortOrder: 2,
@@ -94,7 +94,7 @@ export function getStaticMenuData() {
 						id: '2001',
 						parentId: '2000',
 						weight: 0,
-						name: '支付通道',
+						name: 'menu.paymentChannel',
 						path: '/payment/channel/index',
 						componentPath: null,
 						meta: {
@@ -103,7 +103,7 @@ export function getStaticMenuData() {
 							isKeepAlive: true,
 							icon: 'iconfont icon-shujuyuanguanli',
 							isAffix: false,
-							title: '支付通道',
+							title: 'menu.paymentChannel',
 							isHide: false,
 						},
 						sortOrder: 1,
@@ -116,7 +116,7 @@ export function getStaticMenuData() {
 				id: '3000',
 				parentId: '-1',
 				weight: 1,
-				name: '结算管理',
+				name: 'menu.settlementManage',
 				path: '/settlement',
 				componentPath: null,
 				meta: {
@@ -125,7 +125,7 @@ export function getStaticMenuData() {
 					isKeepAlive: false,
 					icon: 'iconfont icon-lingpai',
 					isAffix: false,
-					title: '结算管理',
+					title: 'menu.settlementManage',
 					isHide: false,
 				},
 				sortOrder: 3,
@@ -136,7 +136,7 @@ export function getStaticMenuData() {
 						id: '3001',
 						parentId: '3000',
 						weight: 0,
-						name: '申请结算',
+						name: 'menu.applySettlement',
 						path: '/settlement/apply/index',
 						componentPath: null,
 						meta: {
@@ -145,7 +145,7 @@ export function getStaticMenuData() {
 							isKeepAlive: false,
 							icon: 'iconfont icon-lingpai',
 							isAffix: false,
-							title: '申请结算',
+							title: 'menu.applySettlement',
 							isHide: false,
 						},
 						sortOrder: 1,
@@ -156,7 +156,7 @@ export function getStaticMenuData() {
 						id: '3002',
 						parentId: '3000',
 						weight: 0,
-						name: '结算记录',
+						name: 'menu.settlementRecord',
 						path: '/settlement/record/index',
 						componentPath: null,
 						meta: {
@@ -165,7 +165,7 @@ export function getStaticMenuData() {
 							isKeepAlive: false,
 							icon: 'iconfont icon-lingpai',
 							isAffix: false,
-							title: '结算记录',
+							title: 'menu.settlementRecord',
 							isHide: false,
 						},
 						sortOrder: 2,
@@ -176,7 +176,7 @@ export function getStaticMenuData() {
 						id: '3003',
 						parentId: '3000',
 						weight: 0,
-						name: '资金明细',
+						name: 'menu.fundFlow',
 						path: '/settlement/fundFlow/index',
 						componentPath: null,
 						meta: {
@@ -185,7 +185,7 @@ export function getStaticMenuData() {
 							isKeepAlive: false,
 							icon: 'iconfont icon-lingpai',
 							isAffix: false,
-							title: '资金明细',
+							title: 'menu.fundFlow',
 							isHide: false,
 						},
 						sortOrder: 3,
@@ -198,7 +198,7 @@ export function getStaticMenuData() {
 				id: '4000',
 				parentId: '-1',
 				weight: 1,
-				name: '系统设置',
+				name: 'menu.systemSettings',
 				path: '/settings',
 				componentPath: null,
 				meta: {
@@ -207,7 +207,7 @@ export function getStaticMenuData() {
 					isKeepAlive: false,
 					icon: 'iconfont icon-xitongshezhi',
 					isAffix: false,
-					title: '系统设置',
+					title: 'menu.systemSettings',
 					isHide: false,
 				},
 				sortOrder: 4,
@@ -218,7 +218,7 @@ export function getStaticMenuData() {
 						id: '4001',
 						parentId: '4000',
 						weight: 0,
-						name: '安全中心',
+						name: 'menu.securityCenter',
 						path: '/settings/security/index',
 						componentPath: null,
 						meta: {
@@ -227,7 +227,7 @@ export function getStaticMenuData() {
 							isKeepAlive: false,
 							icon: 'iconfont icon-xitongshezhi',
 							isAffix: false,
-							title: '安全中心',
+							title: 'menu.securityCenter',
 							isHide: false,
 						},
 						sortOrder: 0,

+ 1 - 1
src/hooks/message.ts

@@ -1,5 +1,5 @@
 import { ElMessage, ElMessageBox } from 'element-plus';
-import { i18n } from '../i18n';
+import { i18n } from '../locales';
 
 const { t } = i18n.global;
 

+ 0 - 91
src/i18n/index.ts

@@ -1,91 +0,0 @@
-import {createI18n} from 'vue-i18n';
-import pinia from '/@/stores/index';
-import {storeToRefs} from 'pinia';
-import {useThemeConfig} from '/@/stores/themeConfig';
-import {info} from '/@/api/admin/i18n';
-
-// 定义语言国际化内容
-
-/**
- * 说明:
- * 须在 pages 下新建文件夹(建议 `要国际化界面目录` 与 `i18n 目录` 相同,方便查找),
- * 注意国际化定义的字段,不要与原有的定义字段相同。
- * 1、/src/i18n/lang 下的 ts 为框架的国际化内容
- * 2、/src/i18n/pages 下的 ts 为各界面的国际化内容
- */
-
-// element plus 自带国际化
-import enLocale from 'element-plus/es/locale/lang/en';
-import zhcnLocale from 'element-plus/es/locale/lang/zh-cn';
-
-// 定义变量内容
-const messages = {};
-const element = {en: enLocale, 'zh-cn': zhcnLocale};
-const itemize = {en: [] as any[], 'zh-cn': [] as any[]};
-const modules: Record<string, any> = import.meta.glob('./**/*.ts', {eager: true});
-const pages: Record<string, any> = import.meta.glob('./../../**/**/**/i18n/*.ts', {eager: true});
-
-// 对自动引入的 modules 进行分类 en、zh-cn、zh-tw
-for (const path in modules) {
-    const key = path.match(/(\S+)\/(\S+).ts/);
-    if (itemize[key![2]]) itemize[key![2]].push(modules[path].default);
-    else itemize[key![2]] = modules[path];
-}
-for (const path in pages) {
-    const key = path.match(/(\S+)\/(\S+).ts/);
-    if (itemize[key![2]]) itemize[key![2]].push(pages[path].default);
-    else itemize[key![2]] = pages[path];
-}
-
-// 合并数组对象(非标准数组对象,数组中对象的每项 key、value 都不同)
-function mergeArrObj<T>(list: T, key: string) {
-    let obj = {};
-    list[key].forEach((i: EmptyObjectType) => {
-        obj = Object.assign({}, obj, i);
-    });
-    return obj;
-}
-
-for (const key in itemize) {
-    messages[key] = {
-        name: key,
-        el: element[key].el,
-        ...mergeArrObj(itemize, key),
-    };
-}
-
-// 读取 pinia 默认语言
-const stores = useThemeConfig(pinia);
-const {themeConfig} = storeToRefs(stores);
-
-// 导出语言国际化
-export const i18n = createI18n({
-    legacy: false,
-    silentTranslationWarn: true,
-    missingWarn: false,
-    silentFallbackWarn: true,
-    fallbackWarn: false,
-    locale: themeConfig.value.globalI18n,
-    fallbackLocale: zhcnLocale.name,
-    messages,
-});
-
-await fetchI18n()
-
-// 远程获取i18n
-async function fetchI18n() {
-    const infoI18n = await info();
-    const messageLocal = {};
-    const itemizeLocal = {en: [] as any[], 'zh-cn': [] as any[]};
-    itemizeLocal['zh-cn'].push(...infoI18n.data.data['zh-cn']);
-    itemizeLocal.en.push(...infoI18n.data.data.en);
-    for (const key in itemizeLocal) {
-        messageLocal[key] = {
-            name: key,
-            ...mergeArrObj(itemizeLocal, key),
-        };
-    }
-    i18n.global.mergeLocaleMessage('zh-cn', messageLocal['zh-cn']);
-    i18n.global.mergeLocaleMessage('en', messageLocal['en']);
-    i18n.global.locale.value = themeConfig.value.globalI18n;
-}

+ 0 - 231
src/i18n/lang/en.ts

@@ -1,231 +0,0 @@
-export default {
-	timeGreeting: {
-		dawn: 'Good early morning',
-		morning: 'Good morning',
-		forenoon: 'Good forenoon',
-		noon: 'Good noon',
-		afternoon: 'Good afternoon',
-		evening: 'Good evening',
-		night: 'Good night',
-		lateNight: 'Good late night',
-	},
-	router: {
-		home: 'Home',
-		system: 'System',
-		systemMenu: 'System Menu',
-		systemRole: 'System Role',
-		systemUser: 'System User',
-		systemDept: 'System Department',
-		systemDic: 'System Dictionary',
-		limits: 'Permissions',
-		limitsFrontEnd: 'Front End',
-		limitsFrontEndPage: 'Front End Page',
-		limitsFrontEndBtn: 'Front End Button',
-		limitsBackEnd: 'Back End',
-		limitsBackEndEndPage: 'Back End Page',
-		menu: 'Menu',
-		menu1: 'Menu 1',
-		menu11: 'Menu 1-1',
-		menu12: 'Menu 1-2',
-		menu121: 'Menu 1-2-1',
-		menu122: 'Menu 1-2-2',
-		menu13: 'Menu 1-3',
-		menu2: 'Menu 2',
-		funIndex: 'Functions',
-		funTagsView: 'Tags View',
-		funCountup: 'Count Up',
-		funWangEditor: 'Wang Editor',
-		funCropper: 'Cropper',
-		funQrcode: 'QR Code',
-		funEchartsMap: 'Echarts Map',
-		funPrintJs: 'PrintJS',
-		funClipboard: 'Copy and Cut',
-		funGridLayout: 'Drag Layout',
-		funSplitpanes: 'Split Pane',
-		funDragVerify: 'Validator',
-		pagesIndex: 'Pages',
-		pagesFiltering: 'Filtering',
-		pagesFilteringDetails: 'Filtering Details',
-		pagesFilteringDetails1: 'Filtering Details 1',
-		pagesIocnfont: 'Icon Font Icon',
-		pagesElement: 'Element Icon',
-		pagesAwesome: 'Awesome Icon',
-		pagesFormAdapt: 'Form Adapt',
-		pagesTableRules: 'Table Rules',
-		pagesFormI18n: 'Form I18n',
-		pagesFormRules: 'Multi-Form Validation',
-		pagesDynamicForm: 'Dynamic Complex Form',
-		pagesWorkflow: 'Workflow',
-		pagesListAdapt: 'List Adapt',
-		pagesWaterfall: 'Waterfall',
-		pagesSteps: 'Steps',
-		pagesPreview: 'Large Preview',
-		pagesWaves: 'Wave Effect',
-		pagesTree: 'Tree Alter Table',
-		pagesDrag: 'Drag Command',
-		pagesLazyImg: 'Image Lazy Loading',
-		makeIndex: 'Make Index',
-		makeSelector: 'Icon Selector',
-		makeNoticeBar: 'Notification Bar',
-		makeSvgDemo: 'Svgicon Demo',
-		makeTableDemo: 'Table Demo',
-		paramsIndex: 'Routing Parameters',
-		paramsCommon: 'General Routing',
-		paramsDynamic: 'Dynamic Routing',
-		paramsCommonDetails: 'General Routing Details',
-		paramsDynamicDetails: 'Dynamic Routing Details',
-		chartIndex: 'Chart Index',
-		visualizingIndex: 'Visualizing Index',
-		visualizingLinkDemo1: 'Visualizing Link Demo 1',
-		visualizingLinkDemo2: 'Visualizing Link Demo 2',
-		personal: 'Personal',
-		tools: 'Tools',
-		layoutLinkView: 'Link View',
-		layoutIframeViewOne: 'Iframe View One',
-		layoutIframeViewTwo: 'Iframe View Two',
-	},
-	staticRoutes: {
-		login: 'Login',
-		authredirect: 'Auth Redirect',
-		expire: 'Password Expire',
-		signIn: 'Sign In',
-		notFound: 'Not Found',
-		noPower: 'No Power',
-	},
-	user: {
-		title0: 'Component Size',
-		title1: 'Language Switching',
-		title2: 'Menu Search',
-		title3: 'Layout Configuration',
-		title4: 'News',
-		title5: 'Full Screen On',
-		title6: 'Full Screen Off',
-		dropdownLarge: 'Large',
-		dropdownDefault: 'Default',
-		dropdownSmall: 'Small',
-		dropdown1: 'Home Page',
-		dropdown2: 'Personal Center',
-		dropdown3: 'Tenant Switch',
-		dropdown4: 'Current Tenant',
-		dropdown5: 'Log Out',
-		searchPlaceholder: 'Menu Search: Supports Chinese and Routing Path',
-		newTitle: 'Notice',
-		newBtn: 'All',
-		newGo: 'Go to the Notification Center',
-		newDesc: 'No Notice',
-		logOutTitle: 'Tips',
-		logOutMessage: 'This Operation Will Log Out. Do You Want to Continue?',
-		logOutConfirm: 'Determine',
-		logOutCancel: 'Cancel',
-		logOutExit: 'Exiting',
-	},
-	tagsView: {
-		refresh: 'Refresh',
-		close: 'Close',
-		closeOther: 'Close Other',
-		closeAll: 'Close All',
-		fullscreen: 'Fullscreen',
-		closeFullscreen: 'Close Fullscreen',
-		favorite: 'Favorite',
-		favoriteMax: 'The number of shortcut navigation exceeds the upper limit. Please remove some shortcuts'
-	},
-	notFound: {
-		foundTitle: 'Wrong Address Input, Please Re-enter the Address~',
-		foundMsg: 'You Can Check the Web Address First, and Then Re-enter or Give Us Feedback.',
-		foundBtn: 'Back to Home Page',
-	},
-	noAccess: {
-		accessTitle: 'You Are Not Authorized to Operate~',
-		accessMsg: 'Contact Information: Add QQ Group Discussion 665452019',
-		accessBtn: 'Reauthorization',
-	},
-	layout: {
-		configTitle: 'Layout Configuration',
-		oneTitle: 'Global Themes',
-		twoTopTitle: 'Top Bar Set Up',
-		twoMenuTitle: 'Menu Set Up',
-		twoColumnsTitle: 'Columns Set Up',
-		twoTopBar: 'Top Bar Background',
-		twoTopBarColor: 'Top Bar Default Font Color',
-		twoIsTopBarColorGradual: 'Top Bar Gradient',
-		twoMenuBar: 'Menu Background',
-		twoMenuBarColor: 'Menu Default Font Color',
-		twoMenuBarActiveColor: 'Menu Highlight Color',
-		twoIsMenuBarColorGradual: 'Menu Gradient',
-		twoColumnsMenuBar: 'Column Menu Background',
-		twoColumnsMenuBarColor: 'Default Font Color Bar Menu',
-		twoIsColumnsMenuBarColorGradual: 'Column Gradient',
-		twoIsColumnsMenuHoverPreload: 'Column Menu Hover Preload',
-		threeTitle: 'Interface Settings',
-		threeIsCollapse: 'Menu Horizontal Collapse',
-		threeIsUniqueOpened: 'Menu Accordion',
-		threeIsFixedHeader: 'Fixed Header',
-		threeIsClassicSplitMenu: 'Classic Layout Split Menu',
-		threeIsLockScreen: 'Open the Lock Screen',
-		threeLockScreenTime: 'Screen Locking (s/s)',
-		fourTitle: 'Interface Display',
-		fourIsShowLogo: 'Sidebar Logo',
-		fourIsBreadcrumb: 'Open Breadcrumb',
-		fourIsBreadcrumbIcon: 'Open Breadcrumb Icon',
-		fourIsTagsview: 'Open Tagsview',
-		fourIsTagsviewIcon: 'Open Tagsview Icon',
-		fourIsCacheTagsView: 'Enable Tagsview Cache',
-		fourIsSortableTagsView: 'Enable Tagsview Drag',
-		fourIsShareTagsView: 'Enable Tagsview Sharing',
-		fourIsFooter: 'Open Footer',
-		fourIsGrayscale: 'Grey Model',
-		fourIsInvert: 'Color Weak Mode',
-		fourIsDark: 'Dark Mode',
-		fourIsWartermark: 'Turn on Watermark',
-		fourWartermarkText: 'Watermark Copy',
-		fourIsChat: 'LLaMA Chat',
-		fiveTitle: 'Other Settings',
-		fiveTagsStyle: 'Tagsview Style',
-		fiveAnimation: 'Page Animation',
-		fiveColumnsAsideStyle: 'Column Style',
-		fiveColumnsAsideLayout: 'Column Layout',
-		sixTitle: 'Layout Switch',
-		sixDefaults: 'One',
-		sixClassic: 'Two',
-		sixTransverse: 'Three',
-		sixColumns: 'Four',
-		tipText: 'Click the Button Below to Copy the Layout Configuration to `/src/stores/themeConfig.ts`. It Has Been Modified In.',
-		copyText: 'Replication Configuration',
-		resetText: 'Restore Default',
-		copyTextSuccess: 'Copy Succeeded!',
-		copyTextError: 'Copy Failed!',
-	},
-	upgrade: {
-		title: 'New Version',
-		msg: 'The New Version is Available, Please Update It Now! Dont Worry, the Update is Fast!',
-		desc: 'Prompt: Update Will Restore the Default Configuration',
-		btnOne: 'Cruel Refusal',
-		btnTwo: 'Update Now',
-		btnTwoLoading: 'Updating',
-	},
-	tenantSelector: {
-		title: 'Switch Tenant',
-		searchPlaceholder: 'Search tenant name, domain or website',
-		noData: 'No tenant data available',
-		current: 'Current',
-		selected: 'Selected',
-		loadError: 'Failed to load tenant list',
-		selectTip: 'Please select a tenant to switch',
-		sameError: 'Already in this tenant, no need to switch',
-		confirmTitle: 'Switch Tenant Confirmation',
-		confirmMessage: 'Are you sure to switch to tenant "{name}"? The page will refresh after switching.',
-		switchSuccess: 'Tenant switched successfully, refreshing page...',
-		switchError: 'Failed to switch tenant, please try again'
-	},
-	common: {
-		cancel: 'Cancel',
-		confirm: 'Confirm',
-		confirmButtonText: 'Confirm',
-		cancelButtonText: 'Cancel'
-	},
-	message: {
-		box: {
-			title: 'Tips'
-		}
-	},
-};

+ 0 - 218
src/i18n/lang/zh-cn.ts

@@ -1,218 +0,0 @@
-// 定义内容
-export default {
-	timeGreeting: {
-		dawn: '凌晨好',
-		morning: '早上好',
-		forenoon: '上午好',
-		noon: '中午好',
-		afternoon: '下午好',
-		evening: '傍晚好',
-		night: '晚上好',
-		lateNight: '夜里好',
-	},
-	router: {
-		home: '首页',
-		system: '系统设置',
-		systemMenu: '菜单管理',
-		systemRole: '角色管理',
-		systemUser: '用户管理',
-		systemDept: '部门管理',
-		systemDic: '字典管理',
-		limits: '权限管理',
-		limitsFrontEnd: '前端控制',
-		limitsFrontEndPage: '页面权限',
-		limitsFrontEndBtn: '按钮权限',
-		limitsBackEnd: '后端控制',
-		limitsBackEndEndPage: '页面权限',
-		funIndex: '功能',
-		funTagsView: 'tagsView 操作',
-		funCountup: '数字滚动',
-		funWangEditor: 'Editor 编辑器',
-		funCropper: '图片裁剪',
-		funQrcode: '二维码生成',
-		funEchartsMap: '地理坐标/地图',
-		funPrintJs: '页面打印',
-		funClipboard: '复制剪切',
-		funGridLayout: '拖拽布局',
-		funSplitpanes: '窗格拆分器',
-		funDragVerify: '验证器',
-		pagesIndex: '页面',
-		pagesFiltering: '过滤筛选组件',
-		pagesFilteringDetails: '过滤筛选组件详情',
-		pagesFilteringDetails1: '过滤筛选组件详情111',
-		pagesIocnfont: 'ali 字体图标',
-		pagesElement: 'ele 字体图标',
-		pagesAwesome: 'awe 字体图标',
-		pagesFormAdapt: '表单自适应',
-		pagesTableRules: '表单表格验证',
-		pagesFormI18n: '表单国际化',
-		pagesFormRules: '多表单验证',
-		pagesDynamicForm: '动态复杂表单',
-		pagesWorkflow: '工作流',
-		pagesListAdapt: '列表自适应',
-		pagesWaterfall: '瀑布屏',
-		pagesSteps: '步骤条',
-		pagesPreview: '大图预览',
-		pagesWaves: '波浪效果',
-		pagesTree: '树形改表格',
-		pagesDrag: '拖动指令',
-		pagesLazyImg: '图片懒加载',
-		makeIndex: '组件封装',
-		makeSelector: '图标选择器',
-		makeNoticeBar: '滚动通知栏',
-		makeSvgDemo: 'svgIcon 演示',
-		makeTableDemo: '表格封装演示',
-		paramsIndex: '路由参数',
-		paramsCommon: '普通路由',
-		paramsDynamic: '动态路由',
-		paramsCommonDetails: '普通路由详情',
-		paramsDynamicDetails: '动态路由详情',
-		chartIndex: '大数据图表',
-		visualizingIndex: '数据可视化',
-		visualizingLinkDemo1: '数据可视化演示1',
-		visualizingLinkDemo2: '数据可视化演示2',
-		personal: '个人中心',
-		tools: '工具类集合',
-		layoutLinkView: '外链',
-		layoutIframeViewOne: '内嵌 iframe1',
-		layoutIframeViewTwo: '内嵌 iframe2',
-	},
-	staticRoutes: {
-		login: '登录',
-		authredirect: '回调页',
-		expire: '密码过期',
-		signIn: '登录',
-		notFound: '找不到此页面',
-		noPower: '没有权限',
-	},
-	user: {
-		title0: '组件大小',
-		title1: '语言切换',
-		title2: '菜单搜索',
-		title3: '布局配置',
-		title4: '消息',
-		title5: '开全屏',
-		title6: '关全屏',
-		dropdownLarge: '大型',
-		dropdownDefault: '默认',
-		dropdownSmall: '小型',
-		dropdown1: '首页',
-		dropdown2: '个人中心',
-		dropdown3: '切换租户',
-		dropdown4: '当前租户',
-		dropdown5: '退出登录',
-		searchPlaceholder: '菜单搜索:支持中文、路由路径',
-		newTitle: '通知',
-		newBtn: '全部',
-		newGo: '前往通知中心',
-		newDesc: '暂无通知',
-		logOutTitle: '提示',
-		logOutMessage: '此操作将退出登录, 是否继续?',
-		logOutConfirm: '确定',
-		logOutCancel: '取消',
-		logOutExit: '退出中',
-	},
-	tagsView: {
-		refresh: '刷新',
-		close: '关闭',
-		closeOther: '关闭其它',
-		closeAll: '全部关闭',
-		fullscreen: '当前页全屏',
-		closeFullscreen: '关闭全屏',
-		favorite: '收藏',
-		favoriteMax: '快捷导航数量超过上限,请移除部分'
-	},
-	notFound: {
-		foundTitle: '地址输入错误,请重新输入地址~',
-		foundMsg: '您可以先检查网址,然后重新输入或给我们反馈问题。',
-		foundBtn: '返回首页',
-	},
-	noAccess: {
-		accessTitle: '您未被授权,没有操作权限~',
-		accessMsg: '联系方式:加QQ群探讨 665452019',
-		accessBtn: '重新授权',
-	},
-	layout: {
-		configTitle: '布局配置',
-		oneTitle: '全局主题',
-		twoTopTitle: '顶栏设置',
-		twoMenuTitle: '菜单设置',
-		twoColumnsTitle: '分栏设置',
-		twoTopBar: '顶栏背景',
-		twoTopBarColor: '顶栏默认字体颜色',
-		twoIsTopBarColorGradual: '顶栏背景渐变',
-		twoMenuBar: '菜单背景',
-		twoMenuBarColor: '菜单默认字体颜色',
-		twoMenuBarActiveColor: '菜单高亮背景色',
-		twoIsMenuBarColorGradual: '菜单背景渐变',
-		twoColumnsMenuBar: '分栏菜单背景',
-		twoColumnsMenuBarColor: '分栏菜单默认字体颜色',
-		twoIsColumnsMenuBarColorGradual: '分栏菜单背景渐变',
-		twoIsColumnsMenuHoverPreload: '分栏菜单鼠标悬停预加载',
-		threeTitle: '界面设置',
-		threeIsCollapse: '菜单水平折叠',
-		threeIsUniqueOpened: '菜单手风琴',
-		threeIsFixedHeader: '固定 Header',
-		threeIsClassicSplitMenu: '经典布局顶部菜单',
-		threeIsLockScreen: '开启锁屏',
-		threeLockScreenTime: '自动锁屏(s/秒)',
-		fourTitle: '界面显示',
-		fourIsShowLogo: '侧边栏 Logo',
-		fourIsBreadcrumb: '开启 Breadcrumb',
-		fourIsBreadcrumbIcon: '开启 Breadcrumb 图标',
-		fourIsTagsview: '开启 Tagsview',
-		fourIsTagsviewIcon: '开启 Tagsview 图标',
-		fourIsCacheTagsView: '开启 TagsView 缓存',
-		fourIsSortableTagsView: '开启 TagsView 拖拽',
-		fourIsShareTagsView: '开启 TagsView 共用',
-		fourIsFooter: '开启 Footer',
-		fourIsGrayscale: '灰色模式',
-		fourIsInvert: '色弱模式',
-		fourIsDark: '深色模式',
-		fourIsWartermark: '开启水印',
-		fourIsChat: '开启AI助手',
-		fourWartermarkText: '水印文案',
-		fiveTitle: '其它设置',
-		fiveTagsStyle: 'Tagsview 风格',
-		fiveAnimation: '主页面切换动画',
-		fiveColumnsAsideStyle: '分栏高亮风格',
-		fiveColumnsAsideLayout: '分栏布局风格',
-		sixTitle: '布局切换',
-		sixDefaults: '左侧',
-		sixClassic: '左顶',
-		sixTransverse: '横向',
-		sixColumns: '分栏',
-		tipText: '点击下方按钮,复制布局配置去 `src/stores/themeConfig.ts` 中修改。',
-		copyText: '一键复制配置',
-		resetText: '一键恢复默认',
-		copyTextSuccess: '复制成功!',
-		copyTextError: '复制失败!',
-	},
-	upgrade: {
-		title: '新版本升级',
-		msg: '新版本来啦,马上更新尝鲜吧!不用担心,更新很快的哦!',
-		desc: '提示:更新会还原默认配置',
-		btnOne: '残忍拒绝',
-		btnTwo: '马上更新',
-		btnTwoLoading: '更新中',
-	},
-	tenantSelector: {
-		title: '切换租户',
-		searchPlaceholder: '搜索租户名称、域名或网站名',
-		noData: '暂无租户数据',
-		current: '当前租户',
-		selected: '已选择',
-		loadError: '加载租户列表失败',
-		selectTip: '请选择要切换的租户',
-		sameError: '当前已是该租户,无需切换',
-		confirmTitle: '切换租户确认',
-		confirmMessage: '确定要切换到租户 "{name}" 吗?切换后页面将刷新。',
-		switchSuccess: '租户切换成功,即将刷新页面...',
-		switchError: '租户切换失败,请重试'
-	},
-	message: {
-		box: {
-			title: '提示'
-		}
-	},
-};

+ 0 - 36
src/i18n/pages/form/en.ts

@@ -1,36 +0,0 @@
-// Improved versions of each word or sentence
-export default {
-	common: {
-		queryBtn: 'Query',
-		addBtn: 'Add',
-		editBtn: 'Edit',
-		delBtn: 'Delete',
-		viewBtn: 'View',
-		detailBtn: 'Details',
-		exportBtn: 'Export',
-		expandBtn: 'expand/phrase ',
-		refreshCacheBtn: 'Refresh cache',
-		importBtn: 'Import',
-		importUserTip: 'Import user',
-		queryDeptTip: 'Enter department name',
-		resetBtn: 'Reset',
-		copyBtn:'Copy',
-		action: 'Action',
-		optSuccessText: 'Operation successful',
-		optConfirmText: 'Confirm this operation?',
-		editSuccessText: 'Successfully edited',
-		addSuccessText: 'Successfully added',
-		delSuccessText: 'Successfully deleted',
-		delConfirmText: 'This operation will permanently delete',
-		confirmButtonText: 'Confirm',
-		cancelButtonText: 'Cancel',
-		download: 'Download',
-		expand: 'Expand',
-		selectAll: 'SelectAll',
-	},
-	message: {
-		box: {
-			title: 'System prompt',
-		},
-	},
-};

+ 0 - 35
src/i18n/pages/form/zh-cn.ts

@@ -1,35 +0,0 @@
-// 定义通用内容
-export default {
-	common: {
-		queryBtn: '查询',
-		addBtn: '新 增',
-		editBtn: '修 改',
-		expandBtn: '展开/折叠',
-		delBtn: '删除',
-		viewBtn: '查看',
-		detailBtn: '详情',
-		refreshCacheBtn: '刷新缓存',
-		exportBtn: '导出',
-		importBtn: '导入',
-		queryDeptTip: '请输入部门名称',
-		resetBtn: '重置',
-		copyBtn: '复制',
-		action: '操作',
-		optSuccessText: '操作成功',
-		editSuccessText: '修改成功',
-		addSuccessText: '添加成功',
-		delSuccessText: '删除成功',
-		delConfirmText: '此操作将永久删除',
-		optConfirmText: '是否确认本操作',
-		confirmButtonText: '确 认',
-		cancelButtonText: '取 消',
-		download: '下载',
-		expand: '展开/折叠',
-		selectAll: '全选/不全选',
-	},
-	message: {
-		box: {
-			title: '系统提示',
-		},
-	},
-};

+ 0 - 99
src/i18n/pages/login/en.ts

@@ -1,99 +0,0 @@
-export default {
-	label: {
-		one1: 'Account login',
-		two2: 'SMS login',
-		three3: 'Social login',
-		register: 'Create account',
-	},
-	link: {
-		one3: 'Third party login',
-		two4: 'Links',
-	},
-	password: {
-		accountPlaceholder1: 'The username "admin" is common, please use another',
-		accountPlaceholder2: 'Password',
-		accountPlaceholder3: 'Please enter the verification code',
-		phonePlaceholder4: 'Please enter your phone number',
-		tenantPlaceholder: 'Please select tenant',
-		accountBtnText: 'Sign in',
-		resetBtnText: 'Reset',
-		registerBtnText: 'Create account',
-		readAccept: 'I have read and accept',
-		privacyPolicy: 'the Privacy Policy',
-		oldPassword: 'Please enter old password',
-		newPassword: 'Please enter new password',
-		confirmPassword: 'Please confirm new password',
-		backToLogin: 'Back to login',
-		mobileLogin: 'Mobile Login',
-		createAccount: 'Create Account',
-		imageCodeTip: 'Please enter code',
-		forgetPassword: 'Forgot Password',
-	},
-	mobile: {
-		placeholder1: 'Please enter your mobile number',
-		placeholder2: 'Please enter the verification code',
-		codeText: 'Get code',
-		btnText: 'Sign in',
-		mobileLogin: 'Mobile Login',
-		backToLogin: 'Back to login',
-		createAccount: 'Create Account',
-		sendSuccess: 'Verification code sent successfully',
-		seconds: 'seconds to resend',
-		mobileRequired: 'Please enter your mobile number',
-		codeRequired: 'Please enter verification code',
-		codeLength: 'Verification code must be 4 digits',
-		sendFailed: 'Failed to send verification code',
-		loginSuccess: 'Login successful',
-		loginFailed: 'Login failed',
-		signIn: 'Sign In',
-	},
-	forget: {
-		newPasswordPlaceholder: 'Please enter new password',
-		confirmPasswordPlaceholder: 'Please confirm new password',
-		passwordEmpty: 'Password cannot be empty',
-		passwordLength: 'Password length must be between 6 and 20 characters',
-		passwordRule: 'The two passwords do not match',
-		passwordScore: 'Password strength is too low',
-	},
-	scan: {
-		text: 'Use your mobile device to scan and quickly log in or create an account',
-		wechatApp: 'Scan with WeChat',
-		appErrorTip: 'The login fails because the application is not configured',
-	},
-	signInText: 'Welcome back!',
-	browserMsgText:
-		'Tip: For best results, we recommend using Google Chrome, Microsoft Edge (version 80 or higher), or the 360 browser with speed mode enabled.',
-	expire: {
-		oldPassword: 'Please enter old password',
-		newPassword: 'Please enter new password',
-		confirmPassword: 'Please confirm new password',
-		passwordRule: 'The two passwords do not match',
-		passwordScore: 'Password strength is too low',
-		resetSuccess: 'Password reset successfully',
-	},
-	tenantSelect: {
-		select: 'Select Tenant',
-		loadError: 'Failed to get tenant list',
-	},
-	verify: {
-		imageCode: 'Please enter verification code',
-	},
-	register: {
-		tenantEmpty: 'Please select a tenant',
-		tenantLoadError: 'Failed to load tenant list',
-		usernameEmpty: 'Username cannot be empty',
-		usernameLength: 'Username length must be between 5 and 20 characters',
-		phoneEmpty: 'Phone number cannot be empty',
-		passwordEmpty: 'Password cannot be empty',
-		passwordLength: 'Password length must be between 6 and 20 characters',
-		passwordStrength: 'Password strength is too low',
-		termsRequired: 'Please read and accept the terms',
-	},
-	divider: {
-		or: 'or',
-	},
-	socialLogin: {
-		wechatWork: 'WeCom',
-		dingtalk: 'DingTalk',
-	},
-};

+ 0 - 96
src/i18n/pages/login/zh-cn.ts

@@ -1,96 +0,0 @@
-// 定义内容
-export default {
-	label: {
-		one1: '用户名登录',
-		two2: '手机号登录',
-		three3: '社交登录',
-		register: '注册账号',
-	},
-	link: {
-		one3: '第三方登录',
-		two4: '友情链接',
-	},
-	password: {
-		accountPlaceholder1: '请输入用户名',
-		accountPlaceholder2: '请输入密码',
-		accountPlaceholder3: '请输入验证码',
-		phonePlaceholder4: '请输入手机号',
-		tenantPlaceholder: '请选择租户',
-		accountBtnText: '登 录',
-		registerBtnText: '注 册',
-		resetBtnText: '重 置',
-		readAccept: '我已仔细阅读并接受',
-		privacyPolicy: '《隐私政策》',
-		oldPassword: '请输入原密码',
-		newPassword: '请输入新密码',
-		confirmPassword: '请确认新密码',
-		backToLogin: '返回登录',
-		mobileLogin: '验证码登录',
-		createAccount: '注册账号',
-		imageCodeTip: '请输入验证码',
-		forgetPassword: '找回密码',
-	},
-	mobile: {
-		placeholder1: '请输入手机号',
-		placeholder2: '请输入验证码',
-		codeText: '获取验证码',
-		btnText: '登 录',
-		mobileLogin: '验证码登录',
-		backToLogin: '返回登录',
-		createAccount: '注册账号',
-		sendSuccess: '验证码发送成功',
-		seconds: '秒后重发',
-		mobileRequired: '请输入手机号码',
-		codeRequired: '请输入验证码',
-		codeLength: '验证码必须是4位数字',
-		sendFailed: '发送验证码失败',
-		loginSuccess: '登录成功',
-		loginFailed: '登录失败',
-		signIn: '登 录',
-	},
-	forget: {
-		newPasswordPlaceholder: '请输入新密码',
-		confirmPasswordPlaceholder: '请确认新密码',
-		passwordEmpty: '密码不能为空',
-		passwordLength: '用户密码长度必须介于 6 和 20 之间',
-		passwordRule: '两次输入的密码不一致',
-		passwordScore: '密码强度太低',
-	},
-	scan: {
-		text: '打开手机扫一扫,快速登录/注册',
-		wechatApp: '微信扫码体验移动端',
-		appErrorTip: '应用未配置,登录失败',
-	},
-	signInText: '欢迎回来!',
-	browserMsgText: '* 温馨提示:建议使用谷歌、Microsoft Edge,版本 80 及以上浏览器,360浏览器请使用极速模式',
-	expire: {
-		oldPassword: '请输入原密码',
-		newPassword: '请输入新密码',
-		confirmPassword: '请确认新密码',
-		passwordRule: '两次输入的密码不一致',
-		passwordScore: '密码强度太低',
-		resetSuccess: '密码重置成功',
-	},
-	tenantSelect: {
-		select: '选择租户',
-		loadError: '获取租户列表失败',
-	},
-	register: {
-		tenantEmpty: '请选择租户',
-		tenantLoadError: '获取租户列表失败',
-		usernameEmpty: '用户名不能为空',
-		usernameLength: '用户名称长度必须介于 5 和 20 之间',
-		phoneEmpty: '手机号不能为空',
-		passwordEmpty: '密码不能为空',
-		passwordLength: '用户密码长度必须介于 6 和 20 之间',
-		passwordStrength: '密码强度太低',
-		termsRequired: '请阅读并同意条款',
-	},
-	divider: {
-		or: '或',
-	},
-	socialLogin: {
-		wechatWork: '企微',
-		dingtalk: '钉钉',
-	},
-};

+ 57 - 49
src/layout/logo/index.vue

@@ -1,82 +1,90 @@
 <template>
-  <div class="layout-logo" v-if="setShowLogo" @click="onThemeConfigChange">
-    <span :style="{color:setFontColor}">{{ themeConfig.globalTitle }}</span>
-  </div>
-  <div class="layout-logo-size" v-else @click="onThemeConfigChange">
-    <img :src="logoMini" class="layout-logo-size-img"/>
-  </div>
+	<div class="layout-logo" v-if="setShowLogo" @click="onThemeConfigChange">
+		<span :style="{ color: setFontColor }">{{ displayTitle }}</span>
+	</div>
+	<div class="layout-logo-size" v-else @click="onThemeConfigChange">
+		<img :src="logoMini" class="layout-logo-size-img" />
+	</div>
 </template>
 
 <script setup lang="ts" name="layoutLogo">
-import {useThemeConfig} from '/@/stores/themeConfig';
+import { useThemeConfig } from '/@/stores/themeConfig';
 import logoMini from '/@/assets/logo-mini.svg';
+import { useI18n } from 'vue-i18n';
+
+const { t } = useI18n();
 
 // 定义变量内容
 const storesThemeConfig = useThemeConfig();
-const {themeConfig} = storeToRefs(storesThemeConfig);
+const { themeConfig } = storeToRefs(storesThemeConfig);
 
 // 设置 logo 的显示。classic 经典布局默认显示 logo
 const setShowLogo = computed(() => {
-  let {isCollapse, layout} = themeConfig.value;
-  return !isCollapse || layout === 'classic' || document.body.clientWidth < 1000;
+	let { isCollapse, layout } = themeConfig.value;
+	return !isCollapse || layout === 'classic' || document.body.clientWidth < 1000;
 });
 
 // 设置 title 的显示颜色。根据布局模式自动显示
 const setFontColor = computed(() => {
-  let {layout} = themeConfig.value;
-  return layout === 'classic' || layout === 'transverse' ? `var(--next-bg-topBarColor)` : 'var(--el-color-primary)';
+	let { layout } = themeConfig.value;
+	return layout === 'classic' || layout === 'transverse' ? `var(--next-bg-topBarColor)` : 'var(--el-color-primary)';
+});
+
+// 显示标题(支持国际化)
+const displayTitle = computed(() => {
+	return t('app.title');
 });
 
 // logo 点击实现菜单展开/收起
 const onThemeConfigChange = () => {
-  if (themeConfig.value.layout === 'transverse') return false;
-  themeConfig.value.isCollapse = !themeConfig.value.isCollapse;
+	if (themeConfig.value.layout === 'transverse') return false;
+	themeConfig.value.isCollapse = !themeConfig.value.isCollapse;
 };
 </script>
 
 <style scoped lang="scss">
 .layout-logo {
-  width: 220px;
-  height: 50px;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  box-shadow: rgb(0 21 41 / 2%) 0px 1px 4px;
-  font-size: 16px;
-  cursor: pointer;
-  animation: logoAnimation 0.3s ease-in-out;
+	width: 220px;
+	height: 50px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	box-shadow: rgb(0 21 41 / 2%) 0px 1px 4px;
+	font-size: 16px;
+	cursor: pointer;
+	animation: logoAnimation 0.3s ease-in-out;
 
-  span {
-    white-space: nowrap;
-    display: inline-block;
-    font-size: 21.5px;
-    font-weight: 700;
-    white-space: nowrap;
-  }
+	span {
+		white-space: nowrap;
+		display: inline-block;
+		font-size: 21.5px;
+		font-weight: 700;
+		white-space: nowrap;
+	}
 
-  &:hover {
-    span {
-      color: var(--color-primary-light-2);
-    }
-  }
+	&:hover {
+		span {
+			color: var(--color-primary-light-2);
+		}
+	}
 }
 
 .layout-logo-size {
-  width: 100%;
-  height: 50px;
-  display: flex;
-  cursor: pointer;
-  animation: logoAnimation 0.3s ease-in-out;
+	width: 100%;
+	height: 50px;
+	display: flex;
+	cursor: pointer;
+	animation: logoAnimation 0.3s ease-in-out;
 
-  &-img {
-    width: 20px;
-    margin: auto;
-  }
+	&-img {
+		width: 20px;
+		margin: auto;
+	}
 
-  &:hover {
-    img {
-      animation: logoAnimation 0.3s ease-in-out;
-    }
-  }
+	&:hover {
+		img {
+			animation: logoAnimation 0.3s ease-in-out;
+		}
+	}
 }
 </style>

+ 11 - 11
src/layout/navBars/breadcrumb/user.vue

@@ -47,7 +47,10 @@
 		</div>
 		<el-dropdown :show-timeout="70" :hide-timeout="50" @command="onHandleCommandClick">
 			<span class="layout-navbars-breadcrumb-user-link">
-				<img :src="userInfos.user.avatar?.startsWith('http') ? userInfos.user.avatar : baseURL + userInfos.user.avatar" class="layout-navbars-breadcrumb-user-link-photo mr5" />
+				<img
+					:src="userInfos.user.avatar?.startsWith('http') ? userInfos.user.avatar : baseURL + userInfos.user.avatar"
+					class="layout-navbars-breadcrumb-user-link-photo mr5"
+				/>
 				{{ userInfos.user.username }}
 				<el-icon class="el-icon--right">
 					<ele-ArrowDown />
@@ -67,12 +70,7 @@
 		<Search ref="searchRef" />
 		<global-websocket uri="/admin/ws/info" v-if="websocketEnable" @rollback="rollback" />
 		<personal-drawer ref="personalDrawerRef"></personal-drawer>
-		<tenant-selector 
-			ref="tenantSelectorRef" 
-			:tenant-list="tenantList" 
-			:loading="tenantLoading"
-			@change="onTenantChange"
-		></tenant-selector>
+		<tenant-selector ref="tenantSelectorRef" :tenant-list="tenantList" :loading="tenantLoading" @change="onTenantChange"></tenant-selector>
 	</div>
 </template>
 
@@ -134,7 +132,7 @@ const shouldShowTenantOption = computed(() => {
 const currentTenantName = computed(() => {
 	if (tenantList.value.length <= 1) return null;
 	const currentTenantId = Session.getTenant();
-	const currentTenant = tenantList.value.find(tenant => tenant.id === currentTenantId);
+	const currentTenant = tenantList.value.find((tenant) => tenant.id === currentTenantId);
 	return currentTenant?.name || null;
 });
 
@@ -238,7 +236,9 @@ const onLanguageChange = (lang: string) => {
 	Local.remove('themeConfig');
 	themeConfig.value.globalI18n = lang;
 	Local.set('themeConfig', themeConfig.value);
-	locale.value = lang;
+	// 映射旧格式语言代码到新格式
+	const localeMap: Record<string, string> = { 'zh-cn': 'zh-CN', en: 'en-US' };
+	locale.value = localeMap[lang] || lang;
 	other.useTitle();
 	initI18nOrSize('globalI18n', 'disabledI18n');
 };
@@ -256,7 +256,7 @@ const initI18nOrSize = (value: string, attr: string) => {
 
 // 获取到消息
 const rollback = (msg: string) => {
-			useMsg().setMsg({ label: 'websocket消息', value: msg, time: formatAxisI18n(new Date(), t) });
+	useMsg().setMsg({ label: 'websocket消息', value: msg, time: formatAxisI18n(new Date(), t) });
 };
 
 // 获取是否显示未读
@@ -295,7 +295,7 @@ onMounted(() => {
 	}
 
 	getIsDot();
-	
+
 	// 加载租户列表
 	loadTenantList();
 });

+ 594 - 0
src/locales/en-US/index.json

@@ -0,0 +1,594 @@
+{
+	"app": {
+		"title": "Agent System"
+	},
+	"timeGreeting": {
+		"dawn": "Good early morning",
+		"morning": "Good morning",
+		"forenoon": "Good forenoon",
+		"noon": "Good noon",
+		"afternoon": "Good afternoon",
+		"evening": "Good evening",
+		"night": "Good night",
+		"lateNight": "Good late night"
+	},
+	"menu": {
+		"orderManage": "Order Management",
+		"payOrder": "Pay Orders",
+		"withdrawOrder": "Withdraw Orders",
+		"paymentConfig": "Payment Config",
+		"paymentChannel": "Payment Channel",
+		"settlementManage": "Settlement",
+		"applySettlement": "Apply Settlement",
+		"settlementRecord": "Settlement Record",
+		"fundFlow": "Fund Flow",
+		"systemSettings": "System Settings",
+		"securityCenter": "Security Center"
+	},
+	"router": {
+		"home": "Home",
+		"system": "System",
+		"systemMenu": "System Menu",
+		"systemRole": "System Role",
+		"systemUser": "System User",
+		"systemDept": "System Department",
+		"systemDic": "System Dictionary",
+		"limits": "Permissions",
+		"limitsFrontEnd": "Front End",
+		"limitsFrontEndPage": "Front End Page",
+		"limitsFrontEndBtn": "Front End Button",
+		"limitsBackEnd": "Back End",
+		"limitsBackEndEndPage": "Back End Page",
+		"menu": "Menu",
+		"menu1": "Menu 1",
+		"menu11": "Menu 1-1",
+		"menu12": "Menu 1-2",
+		"menu121": "Menu 1-2-1",
+		"menu122": "Menu 1-2-2",
+		"menu13": "Menu 1-3",
+		"menu2": "Menu 2",
+		"funIndex": "Functions",
+		"funTagsView": "Tags View",
+		"funCountup": "Count Up",
+		"funWangEditor": "Wang Editor",
+		"funCropper": "Cropper",
+		"funQrcode": "QR Code",
+		"funEchartsMap": "Echarts Map",
+		"funPrintJs": "PrintJS",
+		"funClipboard": "Copy and Cut",
+		"funGridLayout": "Drag Layout",
+		"funSplitpanes": "Split Pane",
+		"funDragVerify": "Validator",
+		"pagesIndex": "Pages",
+		"pagesFiltering": "Filtering",
+		"pagesFilteringDetails": "Filtering Details",
+		"pagesFilteringDetails1": "Filtering Details 1",
+		"pagesIocnfont": "Icon Font Icon",
+		"pagesElement": "Element Icon",
+		"pagesAwesome": "Awesome Icon",
+		"pagesFormAdapt": "Form Adapt",
+		"pagesTableRules": "Table Rules",
+		"pagesFormI18n": "Form I18n",
+		"pagesFormRules": "Multi-Form Validation",
+		"pagesDynamicForm": "Dynamic Complex Form",
+		"pagesWorkflow": "Workflow",
+		"pagesListAdapt": "List Adapt",
+		"pagesWaterfall": "Waterfall",
+		"pagesSteps": "Steps",
+		"pagesPreview": "Large Preview",
+		"pagesWaves": "Wave Effect",
+		"pagesTree": "Tree Alter Table",
+		"pagesDrag": "Drag Command",
+		"pagesLazyImg": "Image Lazy Loading",
+		"makeIndex": "Make Index",
+		"makeSelector": "Icon Selector",
+		"makeNoticeBar": "Notification Bar",
+		"makeSvgDemo": "Svgicon Demo",
+		"makeTableDemo": "Table Demo",
+		"paramsIndex": "Routing Parameters",
+		"paramsCommon": "General Routing",
+		"paramsDynamic": "Dynamic Routing",
+		"paramsCommonDetails": "General Routing Details",
+		"paramsDynamicDetails": "Dynamic Routing Details",
+		"chartIndex": "Chart Index",
+		"visualizingIndex": "Visualizing Index",
+		"visualizingLinkDemo1": "Visualizing Link Demo 1",
+		"visualizingLinkDemo2": "Visualizing Link Demo 2",
+		"personal": "Personal",
+		"tools": "Tools",
+		"layoutLinkView": "Link View",
+		"layoutIframeViewOne": "Iframe View One",
+		"layoutIframeViewTwo": "Iframe View Two"
+	},
+	"staticRoutes": {
+		"login": "Login",
+		"authredirect": "Auth Redirect",
+		"expire": "Password Expire",
+		"signIn": "Sign In",
+		"notFound": "Not Found",
+		"noPower": "No Power"
+	},
+	"user": {
+		"title0": "Component Size",
+		"title1": "Language Switching",
+		"title2": "Menu Search",
+		"title3": "Layout Configuration",
+		"title4": "News",
+		"title5": "Full Screen On",
+		"title6": "Full Screen Off",
+		"dropdownLarge": "Large",
+		"dropdownDefault": "Default",
+		"dropdownSmall": "Small",
+		"dropdown1": "Home Page",
+		"dropdown2": "Personal Center",
+		"dropdown3": "Tenant Switch",
+		"dropdown4": "Current Tenant",
+		"dropdown5": "Log Out",
+		"searchPlaceholder": "Menu Search: Supports Chinese and Routing Path",
+		"newTitle": "Notice",
+		"newBtn": "All",
+		"newGo": "Go to the Notification Center",
+		"newDesc": "No Notice",
+		"logOutTitle": "Tips",
+		"logOutMessage": "This Operation Will Log Out. Do You Want to Continue?",
+		"logOutConfirm": "Determine",
+		"logOutCancel": "Cancel",
+		"logOutExit": "Exiting"
+	},
+	"tagsView": {
+		"refresh": "Refresh",
+		"close": "Close",
+		"closeOther": "Close Other",
+		"closeAll": "Close All",
+		"fullscreen": "Fullscreen",
+		"closeFullscreen": "Close Fullscreen",
+		"favorite": "Favorite",
+		"favoriteMax": "The number of shortcut navigation exceeds the upper limit. Please remove some shortcuts"
+	},
+	"notFound": {
+		"foundTitle": "Wrong Address Input, Please Re-enter the Address~",
+		"foundMsg": "You Can Check the Web Address First, and Then Re-enter or Give Us Feedback.",
+		"foundBtn": "Back to Home Page"
+	},
+	"noAccess": {
+		"accessTitle": "You Are Not Authorized to Operate~",
+		"accessMsg": "Contact Information: Add QQ Group Discussion 665452019",
+		"accessBtn": "Reauthorization"
+	},
+	"layout": {
+		"configTitle": "Layout Configuration",
+		"oneTitle": "Global Themes",
+		"twoTopTitle": "Top Bar Set Up",
+		"twoMenuTitle": "Menu Set Up",
+		"twoColumnsTitle": "Columns Set Up",
+		"twoTopBar": "Top Bar Background",
+		"twoTopBarColor": "Top Bar Default Font Color",
+		"twoIsTopBarColorGradual": "Top Bar Gradient",
+		"twoMenuBar": "Menu Background",
+		"twoMenuBarColor": "Menu Default Font Color",
+		"twoMenuBarActiveColor": "Menu Highlight Color",
+		"twoIsMenuBarColorGradual": "Menu Gradient",
+		"twoColumnsMenuBar": "Column Menu Background",
+		"twoColumnsMenuBarColor": "Default Font Color Bar Menu",
+		"twoIsColumnsMenuBarColorGradual": "Column Gradient",
+		"twoIsColumnsMenuHoverPreload": "Column Menu Hover Preload",
+		"threeTitle": "Interface Settings",
+		"threeIsCollapse": "Menu Horizontal Collapse",
+		"threeIsUniqueOpened": "Menu Accordion",
+		"threeIsFixedHeader": "Fixed Header",
+		"threeIsClassicSplitMenu": "Classic Layout Split Menu",
+		"threeIsLockScreen": "Open the Lock Screen",
+		"threeLockScreenTime": "Screen Locking (s/s)",
+		"fourTitle": "Interface Display",
+		"fourIsShowLogo": "Sidebar Logo",
+		"fourIsBreadcrumb": "Open Breadcrumb",
+		"fourIsBreadcrumbIcon": "Open Breadcrumb Icon",
+		"fourIsTagsview": "Open Tagsview",
+		"fourIsTagsviewIcon": "Open Tagsview Icon",
+		"fourIsCacheTagsView": "Enable Tagsview Cache",
+		"fourIsSortableTagsView": "Enable Tagsview Drag",
+		"fourIsShareTagsView": "Enable Tagsview Sharing",
+		"fourIsFooter": "Open Footer",
+		"fourIsGrayscale": "Grey Model",
+		"fourIsInvert": "Color Weak Mode",
+		"fourIsDark": "Dark Mode",
+		"fourIsWartermark": "Turn on Watermark",
+		"fourWartermarkText": "Watermark Copy",
+		"fourIsChat": "LLaMA Chat",
+		"fiveTitle": "Other Settings",
+		"fiveTagsStyle": "Tagsview Style",
+		"fiveAnimation": "Page Animation",
+		"fiveColumnsAsideStyle": "Column Style",
+		"fiveColumnsAsideLayout": "Column Layout",
+		"sixTitle": "Layout Switch",
+		"sixDefaults": "One",
+		"sixClassic": "Two",
+		"sixTransverse": "Three",
+		"sixColumns": "Four",
+		"tipText": "Click the Button Below to Copy the Layout Configuration to `/src/stores/themeConfig.ts`. It Has Been Modified In.",
+		"copyText": "Replication Configuration",
+		"resetText": "Restore Default",
+		"copyTextSuccess": "Copy Succeeded!",
+		"copyTextError": "Copy Failed!"
+	},
+	"upgrade": {
+		"title": "New Version",
+		"msg": "The New Version is Available, Please Update It Now! Dont Worry, the Update is Fast!",
+		"desc": "Prompt: Update Will Restore the Default Configuration",
+		"btnOne": "Cruel Refusal",
+		"btnTwo": "Update Now",
+		"btnTwoLoading": "Updating"
+	},
+	"tenantSelector": {
+		"title": "Switch Tenant",
+		"searchPlaceholder": "Search tenant name, domain or website",
+		"noData": "No tenant data available",
+		"current": "Current",
+		"selected": "Selected",
+		"loadError": "Failed to load tenant list",
+		"selectTip": "Please select a tenant to switch",
+		"sameError": "Already in this tenant, no need to switch",
+		"confirmTitle": "Switch Tenant Confirmation",
+		"confirmMessage": "Are you sure to switch to tenant \"{name}\"? The page will refresh after switching.",
+		"switchSuccess": "Tenant switched successfully, refreshing page...",
+		"switchError": "Failed to switch tenant, please try again"
+	},
+	"common": {
+		"queryBtn": "Query",
+		"addBtn": "Add",
+		"editBtn": "Edit",
+		"delBtn": "Delete",
+		"viewBtn": "View",
+		"detailBtn": "Details",
+		"exportBtn": "Export",
+		"expandBtn": "expand/phrase ",
+		"refreshCacheBtn": "Refresh cache",
+		"importBtn": "Import",
+		"importUserTip": "Import user",
+		"queryDeptTip": "Enter department name",
+		"resetBtn": "Reset",
+		"copyBtn": "Copy",
+		"action": "Action",
+		"optSuccessText": "Operation successful",
+		"optConfirmText": "Confirm this operation?",
+		"editSuccessText": "Successfully edited",
+		"addSuccessText": "Successfully added",
+		"delSuccessText": "Successfully deleted",
+		"delConfirmText": "This operation will permanently delete",
+		"confirmButtonText": "Confirm",
+		"cancelButtonText": "Cancel",
+		"download": "Download",
+		"expand": "Expand",
+		"selectAll": "SelectAll",
+		"cancel": "Cancel",
+		"confirm": "Confirm"
+	},
+	"message": {
+		"box": {
+			"title": "System prompt"
+		}
+	},
+	"label": {
+		"one1": "Account login",
+		"two2": "SMS login",
+		"three3": "Social login",
+		"register": "Create account"
+	},
+	"link": {
+		"one3": "Third party login",
+		"two4": "Links"
+	},
+	"password": {
+		"accountPlaceholder1": "Please enter username",
+		"accountPlaceholder2": "Password",
+		"accountPlaceholder3": "Please enter the verification code",
+		"phonePlaceholder4": "Please enter your phone number",
+		"tenantPlaceholder": "Please select tenant",
+		"accountBtnText": "Sign in",
+		"resetBtnText": "Reset",
+		"registerBtnText": "Create account",
+		"readAccept": "I have read and accept",
+		"privacyPolicy": "the Privacy Policy",
+		"oldPassword": "Please enter old password",
+		"newPassword": "Please enter new password",
+		"confirmPassword": "Please confirm new password",
+		"backToLogin": "Back to login",
+		"mobileLogin": "Mobile Login",
+		"createAccount": "Create Account",
+		"imageCodeTip": "Please enter code",
+		"forgetPassword": "Forgot Password",
+		"googleCaptchaPlaceholder": "Google Authenticator code (optional)"
+	},
+	"mobile": {
+		"placeholder1": "Please enter your mobile number",
+		"placeholder2": "Please enter the verification code",
+		"codeText": "Get code",
+		"btnText": "Sign in",
+		"mobileLogin": "Mobile Login",
+		"backToLogin": "Back to login",
+		"createAccount": "Create Account",
+		"sendSuccess": "Verification code sent successfully",
+		"seconds": "seconds to resend",
+		"mobileRequired": "Please enter your mobile number",
+		"codeRequired": "Please enter verification code",
+		"codeLength": "Verification code must be 4 digits",
+		"sendFailed": "Failed to send verification code",
+		"loginSuccess": "Login successful",
+		"loginFailed": "Login failed",
+		"signIn": "Sign In"
+	},
+	"forget": {
+		"newPasswordPlaceholder": "Please enter new password",
+		"confirmPasswordPlaceholder": "Please confirm new password",
+		"passwordEmpty": "Password cannot be empty",
+		"passwordLength": "Password length must be between 6 and 20 characters",
+		"passwordRule": "The two passwords do not match",
+		"passwordScore": "Password strength is too low"
+	},
+	"scan": {
+		"text": "Use your mobile device to scan and quickly log in or create an account",
+		"wechatApp": "Scan with WeChat",
+		"appErrorTip": "The login fails because the application is not configured"
+	},
+	"signInText": "Welcome back!",
+	"browserMsgText": "Tip: For best results, we recommend using Google Chrome, Microsoft Edge (version 80 or higher), or the 360 browser with speed mode enabled.",
+	"expire": {
+		"oldPassword": "Please enter old password",
+		"newPassword": "Please enter new password",
+		"confirmPassword": "Please confirm new password",
+		"passwordRule": "The two passwords do not match",
+		"passwordScore": "Password strength is too low",
+		"resetSuccess": "Password reset successfully"
+	},
+	"tenantSelect": {
+		"select": "Select Tenant",
+		"loadError": "Failed to get tenant list"
+	},
+	"verify": {
+		"imageCode": "Please enter verification code"
+	},
+	"register": {
+		"tenantEmpty": "Please select a tenant",
+		"tenantLoadError": "Failed to load tenant list",
+		"usernameEmpty": "Username cannot be empty",
+		"usernameLength": "Username length must be between 5 and 20 characters",
+		"phoneEmpty": "Phone number cannot be empty",
+		"passwordEmpty": "Password cannot be empty",
+		"passwordLength": "Password length must be between 6 and 20 characters",
+		"passwordStrength": "Password strength is too low",
+		"termsRequired": "Please read and accept the terms"
+	},
+	"divider": {
+		"or": "or"
+	},
+	"socialLogin": {
+		"wechatWork": "WeCom",
+		"dingtalk": "DingTalk"
+	},
+	"personal": {
+		"name": "Personal Info",
+		"basicInfo": "Basic Info",
+		"securityInfo": "Security Info",
+		"merchantNo": "Merchant No",
+		"nickname": "Nickname",
+		"nicknamePlaceholder": "Please enter nickname",
+		"realName": "Name",
+		"realNamePlaceholder": "Please enter name",
+		"phone": "Phone",
+		"phonePlaceholder": "Please enter phone",
+		"email": "Email",
+		"emailPlaceholder": "Please enter email",
+		"oldPassword": "Old Password",
+		"oldPasswordPlaceholder": "Please enter password",
+		"newPassword": "New Password",
+		"newPasswordPlaceholder": "Please enter new password",
+		"confirmPassword": "Confirm Password",
+		"confirmPasswordPlaceholder": "Please repeat password",
+		"changePassword": "Change Password",
+		"updateInfo": "Update Info",
+		"passwordRule": "The two passwords do not match",
+		"passwordScore": "Password strength is too low"
+	},
+	"dashboard": {
+		"submitOrder": "Submit Orders",
+		"payOrder": "Pay Orders",
+		"withdrawOrder": "Withdraw Orders",
+		"withdrawSuccess": "Withdraw Success",
+		"paySuccessRate": "Pay Success Rate",
+		"amount": "Amount",
+		"loadFailed": "Failed to load statistics"
+	},
+	"payment": {
+		"channel": {
+			"channelName": "Channel Name",
+			"channelNamePlaceholder": "Please enter channel name",
+			"paymentName": "Payment Method",
+			"paymentNamePlaceholder": "Please enter payment method",
+			"paymentType": "Payment Type",
+			"paymentTypePlaceholder": "Please select payment type",
+			"paymentTypePay": "Payout",
+			"paymentTypeHarvest": "Collection",
+			"agentFeeType": "Agent Fee Type",
+			"agentFeeRate": "Agent Fee Rate",
+			"agentFeeFixed": "Agent Fee Fixed",
+			"feeTypePercentage": "Percentage",
+			"feeTypeFixed": "Fixed",
+			"feeTypeMixed": "Mixed",
+			"refresh": "Refresh",
+			"fetchFailed": "Failed to fetch rate info"
+		}
+	},
+	"order": {
+		"payOrder": {
+			"title": "Pay Order",
+			"mchOrderNo": "Merchant Order No",
+			"mchOrderNoPlaceholder": "Please enter merchant order number",
+			"transactionId": "Platform Order No",
+			"transactionIdPlaceholder": "Please enter platform order number",
+			"merchantName": "Merchant Name",
+			"merchantNamePlaceholder": "Please enter merchant name",
+			"orderStatus": "Order Status",
+			"orderStatusPlaceholder": "Please select order status",
+			"createOrder": "Created",
+			"paySuccess": "Pay Success",
+			"payFail": "Pay Failed",
+			"cancelOrder": "Cancelled",
+			"payTimeout": "Pay Timeout",
+			"submitOrders": "Submitted Orders",
+			"totalOrderAmount": "Total Order Amount",
+			"paidOrders": "Paid Orders",
+			"paidTotalAmount": "Paid Total Amount",
+			"channelName": "Channel Name",
+			"submitAmount": "Submit Amount",
+			"actualAmount": "Actual Amount",
+			"createTime": "Create Time",
+			"operation": "Operation",
+			"notifyLog": "Notify Log",
+			"detail": "Pay Order Detail",
+			"orderId": "Order ID",
+			"appId": "App ID",
+			"currency": "Currency",
+			"orderAmount": "Order Amount",
+			"paidAmount": "Paid Amount",
+			"paymentChannelId": "Payment Channel ID",
+			"paymentChannelName": "Payment Channel Name",
+			"merchantId": "Merchant ID",
+			"agentId": "Agent ID",
+			"merchantFeeType": "Merchant Fee Type",
+			"merchantFee": "Merchant Fee",
+			"merchantFeeRate": "Merchant Fee Rate",
+			"merchantFeeFixed": "Merchant Fee Fixed",
+			"agentFeeType": "Agent Fee Type",
+			"agentFee": "Agent Fee",
+			"agentFeeRate": "Agent Fee Rate",
+			"agentFeeFixed": "Agent Fee Fixed",
+			"feeTypePercentage": "Percentage",
+			"feeTypeFixed": "Fixed",
+			"feeTypeMixed": "Percentage + Fixed",
+			"clientIp": "Client IP",
+			"device": "Device",
+			"subject": "Subject",
+			"body": "Body",
+			"returnUrl": "Return URL",
+			"notifyUrl": "Notify URL",
+			"extraParams": "Extra Params",
+			"reqTime": "Request Time",
+			"payCompleteTime": "Pay Complete Time",
+			"updateTime": "Update Time",
+			"close": "Close"
+		},
+		"withdrawOrder": {
+			"title": "Withdraw Order",
+			"detail": "Withdraw Order Detail",
+			"withdrawSuccess": "Withdraw Success",
+			"withdrawFail": "Withdraw Failed",
+			"currencyType": "Currency",
+			"paymentTypeId": "Payment Type ID",
+			"feeStatus": "Fee Status",
+			"feeStatusSuccess": "Success",
+			"feeStatusFail": "Failed",
+			"payeeName": "Payee Name",
+			"payeePhone": "Payee Phone",
+			"bankAccount": "Bank Account",
+			"bankName": "Bank Name",
+			"payeeEmail": "Payee Email",
+			"completeTime": "Complete Time"
+		},
+		"notifyLog": {
+			"title": "Notify Log",
+			"orderNo": "Order No",
+			"notifyStatus": "Notify Status",
+			"currentNotifyTimes": "Current Notify Times",
+			"maxNotifyTimes": "Max Notify Times",
+			"lastExecuteTime": "Last Execute Time",
+			"nextNotifyTime": "Next Notify Time",
+			"notifyUrl": "Notify URL",
+			"failReason": "Fail Reason",
+			"notifyLogList": "Notify Log List",
+			"notifyTimes": "Notify #{n}",
+			"pending": "Pending",
+			"success": "Success",
+			"fail": "Failed",
+			"processing": "Processing",
+			"responseResult": "Response Result",
+			"noResponse": "No Response",
+			"noNotifyLog": "No notify log",
+			"fetchFailed": "Failed to fetch notify log"
+		}
+	},
+	"settlement": {
+		"fundFlow": {
+			"availableBalance": "Available Balance",
+			"totalAmount": "Total Amount",
+			"totalFreezeAmount": "Total Frozen Amount",
+			"totalWithdrawAmount": "Total Withdrawn Amount",
+			"orderNo": "Order No",
+			"orderNoPlaceholder": "Please enter order number",
+			"orderType": "Order Type",
+			"orderTypePlaceholder": "Please select order type",
+			"payOrder": "Pay Order",
+			"withdrawOrder": "Withdraw Order",
+			"walletType": "Wallet Type",
+			"walletTypePlaceholder": "Please select wallet type",
+			"walletTotal": "Total",
+			"walletUse": "Available",
+			"walletFreeze": "Frozen",
+			"walletWithdraw": "Withdrawn",
+			"walletWithdrawTotal": "Total Withdrawn",
+			"orderCreateTime": "Order Create Time",
+			"payTime": "Pay Time",
+			"to": "to",
+			"startTime": "Start Time",
+			"endTime": "End Time",
+			"beforeAmount": "Before Amount",
+			"changeAmount": "Change Amount",
+			"afterAmount": "After Amount",
+			"businessOrder": "Business Order",
+			"orderAmount": "Order Amount",
+			"createTime": "Create Time"
+		},
+		"apply": {
+			"title": "Apply Settlement",
+			"availableAmount": "Available Amount",
+			"withdrawAmount": "Withdraw Amount",
+			"withdrawAmountPlaceholder": "Please enter withdraw amount",
+			"withdrawAmountRequired": "Please enter withdraw amount",
+			"withdrawAmountExceed": "Withdraw amount cannot exceed available amount",
+			"withdrawType": "Withdraw Type",
+			"withdrawTypeRequired": "Please select withdraw type",
+			"bankCard": "Bank Card",
+			"usdt": "USDT",
+			"bankName": "Bank Name",
+			"bankNamePlaceholder": "Please enter bank name",
+			"bankNameRequired": "Please enter bank name",
+			"bankAccount": "Bank Account",
+			"bankAccountPlaceholder": "Please enter bank account/USDT address",
+			"bankAccountRequired": "Please enter bank account/USDT address",
+			"realName": "Real Name",
+			"realNamePlaceholder": "Please enter real name",
+			"realNameRequired": "Please enter real name",
+			"submit": "Submit",
+			"submitSuccess": "Application submitted successfully"
+		},
+		"record": {
+			"realName": "Real Name",
+			"realNamePlaceholder": "Please enter real name",
+			"bankAccount": "Bank Account",
+			"bankAccountPlaceholder": "Please enter bank account",
+			"auditStatus": "Audit Status",
+			"auditStatusPlaceholder": "Please select audit status",
+			"pending": "Pending",
+			"approved": "Approved",
+			"rejected": "Rejected",
+			"agentName": "Agent Name",
+			"withdrawAmount": "Withdraw Amount",
+			"withdrawType": "Withdraw Type",
+			"bankCard": "Bank Card",
+			"usdt": "USDT",
+			"bankName": "Bank Name",
+			"rejectReason": "Reject Reason",
+			"applyTime": "Apply Time",
+			"createTime": "Create Time"
+		}
+	}
+}

+ 111 - 0
src/locales/index.ts

@@ -0,0 +1,111 @@
+import { createI18n } from 'vue-i18n';
+import pinia from '/@/stores/index';
+import { storeToRefs } from 'pinia';
+import { useThemeConfig } from '/@/stores/themeConfig';
+import { info } from '/@/api/admin/i18n';
+
+// element plus 自带国际化
+import enLocale from 'element-plus/es/locale/lang/en';
+import zhcnLocale from 'element-plus/es/locale/lang/zh-cn';
+
+import zhCN from './zh-CN/index.json';
+import enUS from './en-US/index.json';
+
+// 语言代码映射(兼容旧格式)
+const localeMap: Record<string, 'zh-CN' | 'en-US'> = {
+	'zh-cn': 'zh-CN',
+	'zh-CN': 'zh-CN',
+	en: 'en-US',
+	'en-US': 'en-US',
+};
+
+const messages = {
+	'zh-CN': {
+		name: 'zh-CN',
+		el: zhcnLocale.el,
+		...zhCN,
+	},
+	'en-US': {
+		name: 'en-US',
+		el: enLocale.el,
+		...enUS,
+	},
+};
+
+// 读取 pinia 默认语言
+const stores = useThemeConfig(pinia);
+const { themeConfig } = storeToRefs(stores);
+
+// 获取并标准化语言代码
+const getLocale = (locale: string): 'zh-CN' | 'en-US' => localeMap[locale] || 'zh-CN';
+const defaultLocale = getLocale(localStorage.getItem('locale') || themeConfig.value.globalI18n || 'zh-CN');
+
+// 导出语言国际化
+export const i18n = createI18n({
+	legacy: false,
+	silentTranslationWarn: true,
+	missingWarn: false,
+	silentFallbackWarn: true,
+	fallbackWarn: false,
+	locale: defaultLocale,
+	fallbackLocale: 'zh-CN',
+	messages,
+	globalInjection: true,
+});
+
+// 初始化时设置 data-locale 属性
+if (typeof document !== 'undefined') {
+	document.querySelector('html')?.setAttribute('lang', defaultLocale);
+	document.querySelector('html')?.setAttribute('data-locale', defaultLocale);
+}
+
+await fetchI18n();
+
+// 远程获取i18n
+async function fetchI18n() {
+	const infoI18n = await info();
+	const messageLocal: Record<string, any> = {};
+	const itemizeLocal: Record<string, any[]> = { 'en-US': [], 'zh-CN': [] };
+	itemizeLocal['zh-CN'].push(...(infoI18n.data.data['zh-cn'] || []));
+	itemizeLocal['en-US'].push(...(infoI18n.data.data.en || []));
+
+	for (const key in itemizeLocal) {
+		messageLocal[key] = {
+			name: key,
+			...mergeArrObj(itemizeLocal, key),
+		};
+	}
+
+	i18n.global.mergeLocaleMessage('zh-CN', messageLocal['zh-CN']);
+	i18n.global.mergeLocaleMessage('en-US', messageLocal['en-US']);
+	i18n.global.locale.value = getLocale(themeConfig.value.globalI18n);
+}
+
+// 合并数组对象
+function mergeArrObj<T extends Record<string, any[]>>(list: T, key: string) {
+	let obj: Record<string, any> = {};
+	list[key].forEach((i: Record<string, any>) => {
+		obj = Object.assign({}, obj, i);
+	});
+	return obj;
+}
+
+export default i18n;
+
+// 导出语言代码映射函数
+export { getLocale };
+
+// 导出语言切换函数
+export function setLanguage(locale: string) {
+	const normalizedLocale = getLocale(locale);
+	i18n.global.locale.value = normalizedLocale;
+	localStorage.setItem('locale', normalizedLocale);
+	document.querySelector('html')?.setAttribute('lang', normalizedLocale);
+	// 设置 data-locale 属性用于样式适配
+	document.querySelector('html')?.setAttribute('data-locale', normalizedLocale);
+}
+
+// 导出当前语言
+export function getCurrentLanguage() {
+	return i18n.global.locale.value;
+}

+ 582 - 0
src/locales/zh-CN/index.json

@@ -0,0 +1,582 @@
+{
+	"app": {
+		"title": "代理商系统"
+	},
+	"timeGreeting": {
+		"dawn": "凌晨好",
+		"morning": "早上好",
+		"forenoon": "上午好",
+		"noon": "中午好",
+		"afternoon": "下午好",
+		"evening": "傍晚好",
+		"night": "晚上好",
+		"lateNight": "夜里好"
+	},
+	"menu": {
+		"orderManage": "订单管理",
+		"payOrder": "代收订单",
+		"withdrawOrder": "代付订单",
+		"paymentConfig": "支付配置",
+		"paymentChannel": "支付通道",
+		"settlementManage": "结算管理",
+		"applySettlement": "申请结算",
+		"settlementRecord": "结算记录",
+		"fundFlow": "资金明细",
+		"systemSettings": "系统设置",
+		"securityCenter": "安全中心"
+	},
+	"router": {
+		"home": "首页",
+		"system": "系统设置",
+		"systemMenu": "菜单管理",
+		"systemRole": "角色管理",
+		"systemUser": "用户管理",
+		"systemDept": "部门管理",
+		"systemDic": "字典管理",
+		"limits": "权限管理",
+		"limitsFrontEnd": "前端控制",
+		"limitsFrontEndPage": "页面权限",
+		"limitsFrontEndBtn": "按钮权限",
+		"limitsBackEnd": "后端控制",
+		"limitsBackEndEndPage": "页面权限",
+		"funIndex": "功能",
+		"funTagsView": "tagsView 操作",
+		"funCountup": "数字滚动",
+		"funWangEditor": "Editor 编辑器",
+		"funCropper": "图片裁剪",
+		"funQrcode": "二维码生成",
+		"funEchartsMap": "地理坐标/地图",
+		"funPrintJs": "页面打印",
+		"funClipboard": "复制剪切",
+		"funGridLayout": "拖拽布局",
+		"funSplitpanes": "窗格拆分器",
+		"funDragVerify": "验证器",
+		"pagesIndex": "页面",
+		"pagesFiltering": "过滤筛选组件",
+		"pagesFilteringDetails": "过滤筛选组件详情",
+		"pagesFilteringDetails1": "过滤筛选组件详情111",
+		"pagesIocnfont": "ali 字体图标",
+		"pagesElement": "ele 字体图标",
+		"pagesAwesome": "awe 字体图标",
+		"pagesFormAdapt": "表单自适应",
+		"pagesTableRules": "表单表格验证",
+		"pagesFormI18n": "表单国际化",
+		"pagesFormRules": "多表单验证",
+		"pagesDynamicForm": "动态复杂表单",
+		"pagesWorkflow": "工作流",
+		"pagesListAdapt": "列表自适应",
+		"pagesWaterfall": "瀑布屏",
+		"pagesSteps": "步骤条",
+		"pagesPreview": "大图预览",
+		"pagesWaves": "波浪效果",
+		"pagesTree": "树形改表格",
+		"pagesDrag": "拖动指令",
+		"pagesLazyImg": "图片懒加载",
+		"makeIndex": "组件封装",
+		"makeSelector": "图标选择器",
+		"makeNoticeBar": "滚动通知栏",
+		"makeSvgDemo": "svgIcon 演示",
+		"makeTableDemo": "表格封装演示",
+		"paramsIndex": "路由参数",
+		"paramsCommon": "普通路由",
+		"paramsDynamic": "动态路由",
+		"paramsCommonDetails": "普通路由详情",
+		"paramsDynamicDetails": "动态路由详情",
+		"chartIndex": "大数据图表",
+		"visualizingIndex": "数据可视化",
+		"visualizingLinkDemo1": "数据可视化演示1",
+		"visualizingLinkDemo2": "数据可视化演示2",
+		"personal": "个人中心",
+		"tools": "工具类集合",
+		"layoutLinkView": "外链",
+		"layoutIframeViewOne": "内嵌 iframe1",
+		"layoutIframeViewTwo": "内嵌 iframe2"
+	},
+	"staticRoutes": {
+		"login": "登录",
+		"authredirect": "回调页",
+		"expire": "密码过期",
+		"signIn": "登录",
+		"notFound": "找不到此页面",
+		"noPower": "没有权限"
+	},
+	"user": {
+		"title0": "组件大小",
+		"title1": "语言切换",
+		"title2": "菜单搜索",
+		"title3": "布局配置",
+		"title4": "消息",
+		"title5": "开全屏",
+		"title6": "关全屏",
+		"dropdownLarge": "大型",
+		"dropdownDefault": "默认",
+		"dropdownSmall": "小型",
+		"dropdown1": "首页",
+		"dropdown2": "个人中心",
+		"dropdown3": "切换租户",
+		"dropdown4": "当前租户",
+		"dropdown5": "退出登录",
+		"searchPlaceholder": "菜单搜索:支持中文、路由路径",
+		"newTitle": "通知",
+		"newBtn": "全部",
+		"newGo": "前往通知中心",
+		"newDesc": "暂无通知",
+		"logOutTitle": "提示",
+		"logOutMessage": "此操作将退出登录, 是否继续?",
+		"logOutConfirm": "确定",
+		"logOutCancel": "取消",
+		"logOutExit": "退出中"
+	},
+	"tagsView": {
+		"refresh": "刷新",
+		"close": "关闭",
+		"closeOther": "关闭其它",
+		"closeAll": "全部关闭",
+		"fullscreen": "当前页全屏",
+		"closeFullscreen": "关闭全屏",
+		"favorite": "收藏",
+		"favoriteMax": "快捷导航数量超过上限,请移除部分"
+	},
+	"notFound": {
+		"foundTitle": "地址输入错误,请重新输入地址~",
+		"foundMsg": "您可以先检查网址,然后重新输入或给我们反馈问题。",
+		"foundBtn": "返回首页"
+	},
+	"noAccess": {
+		"accessTitle": "您未被授权,没有操作权限~",
+		"accessMsg": "联系方式:加QQ群探讨 665452019",
+		"accessBtn": "重新授权"
+	},
+	"layout": {
+		"configTitle": "布局配置",
+		"oneTitle": "全局主题",
+		"twoTopTitle": "顶栏设置",
+		"twoMenuTitle": "菜单设置",
+		"twoColumnsTitle": "分栏设置",
+		"twoTopBar": "顶栏背景",
+		"twoTopBarColor": "顶栏默认字体颜色",
+		"twoIsTopBarColorGradual": "顶栏背景渐变",
+		"twoMenuBar": "菜单背景",
+		"twoMenuBarColor": "菜单默认字体颜色",
+		"twoMenuBarActiveColor": "菜单高亮背景色",
+		"twoIsMenuBarColorGradual": "菜单背景渐变",
+		"twoColumnsMenuBar": "分栏菜单背景",
+		"twoColumnsMenuBarColor": "分栏菜单默认字体颜色",
+		"twoIsColumnsMenuBarColorGradual": "分栏菜单背景渐变",
+		"twoIsColumnsMenuHoverPreload": "分栏菜单鼠标悬停预加载",
+		"threeTitle": "界面设置",
+		"threeIsCollapse": "菜单水平折叠",
+		"threeIsUniqueOpened": "菜单手风琴",
+		"threeIsFixedHeader": "固定 Header",
+		"threeIsClassicSplitMenu": "经典布局顶部菜单",
+		"threeIsLockScreen": "开启锁屏",
+		"threeLockScreenTime": "自动锁屏(s/秒)",
+		"fourTitle": "界面显示",
+		"fourIsShowLogo": "侧边栏 Logo",
+		"fourIsBreadcrumb": "开启 Breadcrumb",
+		"fourIsBreadcrumbIcon": "开启 Breadcrumb 图标",
+		"fourIsTagsview": "开启 Tagsview",
+		"fourIsTagsviewIcon": "开启 Tagsview 图标",
+		"fourIsCacheTagsView": "开启 TagsView 缓存",
+		"fourIsSortableTagsView": "开启 TagsView 拖拽",
+		"fourIsShareTagsView": "开启 TagsView 共用",
+		"fourIsFooter": "开启 Footer",
+		"fourIsGrayscale": "灰色模式",
+		"fourIsInvert": "色弱模式",
+		"fourIsDark": "深色模式",
+		"fourIsWartermark": "开启水印",
+		"fourIsChat": "开启AI助手",
+		"fourWartermarkText": "水印文案",
+		"fiveTitle": "其它设置",
+		"fiveTagsStyle": "Tagsview 风格",
+		"fiveAnimation": "主页面切换动画",
+		"fiveColumnsAsideStyle": "分栏高亮风格",
+		"fiveColumnsAsideLayout": "分栏布局风格",
+		"sixTitle": "布局切换",
+		"sixDefaults": "左侧",
+		"sixClassic": "左顶",
+		"sixTransverse": "横向",
+		"sixColumns": "分栏",
+		"tipText": "点击下方按钮,复制布局配置去 `src/stores/themeConfig.ts` 中修改。",
+		"copyText": "一键复制配置",
+		"resetText": "一键恢复默认",
+		"copyTextSuccess": "复制成功!",
+		"copyTextError": "复制失败!"
+	},
+	"upgrade": {
+		"title": "新版本升级",
+		"msg": "新版本来啦,马上更新尝鲜吧!不用担心,更新很快的哦!",
+		"desc": "提示:更新会还原默认配置",
+		"btnOne": "残忍拒绝",
+		"btnTwo": "马上更新",
+		"btnTwoLoading": "更新中"
+	},
+	"tenantSelector": {
+		"title": "切换租户",
+		"searchPlaceholder": "搜索租户名称、域名或网站名",
+		"noData": "暂无租户数据",
+		"current": "当前租户",
+		"selected": "已选择",
+		"loadError": "加载租户列表失败",
+		"selectTip": "请选择要切换的租户",
+		"sameError": "当前已是该租户,无需切换",
+		"confirmTitle": "切换租户确认",
+		"confirmMessage": "确定要切换到租户 \"{name}\" 吗?切换后页面将刷新。",
+		"switchSuccess": "租户切换成功,即将刷新页面...",
+		"switchError": "租户切换失败,请重试"
+	},
+	"common": {
+		"queryBtn": "查询",
+		"addBtn": "新 增",
+		"editBtn": "修 改",
+		"expandBtn": "展开/折叠",
+		"delBtn": "删除",
+		"viewBtn": "查看",
+		"detailBtn": "详情",
+		"refreshCacheBtn": "刷新缓存",
+		"exportBtn": "导出",
+		"importBtn": "导入",
+		"queryDeptTip": "请输入部门名称",
+		"resetBtn": "重置",
+		"copyBtn": "复制",
+		"action": "操作",
+		"optSuccessText": "操作成功",
+		"editSuccessText": "修改成功",
+		"addSuccessText": "添加成功",
+		"delSuccessText": "删除成功",
+		"delConfirmText": "此操作将永久删除",
+		"optConfirmText": "是否确认本操作",
+		"confirmButtonText": "确 认",
+		"cancelButtonText": "取 消",
+		"download": "下载",
+		"expand": "展开/折叠",
+		"selectAll": "全选/不全选",
+		"cancel": "取消",
+		"confirm": "确认"
+	},
+	"message": {
+		"box": {
+			"title": "系统提示"
+		}
+	},
+	"label": {
+		"one1": "用户名登录",
+		"two2": "手机号登录",
+		"three3": "社交登录",
+		"register": "注册账号"
+	},
+	"link": {
+		"one3": "第三方登录",
+		"two4": "友情链接"
+	},
+	"password": {
+		"accountPlaceholder1": "请输入用户名",
+		"accountPlaceholder2": "请输入密码",
+		"accountPlaceholder3": "请输入验证码",
+		"phonePlaceholder4": "请输入手机号",
+		"tenantPlaceholder": "请选择租户",
+		"accountBtnText": "登 录",
+		"registerBtnText": "注 册",
+		"resetBtnText": "重 置",
+		"readAccept": "我已仔细阅读并接受",
+		"privacyPolicy": "《隐私政策》",
+		"oldPassword": "请输入原密码",
+		"newPassword": "请输入新密码",
+		"confirmPassword": "请确认新密码",
+		"backToLogin": "返回登录",
+		"mobileLogin": "验证码登录",
+		"createAccount": "注册账号",
+		"imageCodeTip": "请输入验证码",
+		"forgetPassword": "找回密码",
+		"googleCaptchaPlaceholder": "谷歌验证码(若没有可以不填)"
+	},
+	"mobile": {
+		"placeholder1": "请输入手机号",
+		"placeholder2": "请输入验证码",
+		"codeText": "获取验证码",
+		"btnText": "登 录",
+		"mobileLogin": "验证码登录",
+		"backToLogin": "返回登录",
+		"createAccount": "注册账号",
+		"sendSuccess": "验证码发送成功",
+		"seconds": "秒后重发",
+		"mobileRequired": "请输入手机号码",
+		"codeRequired": "请输入验证码",
+		"codeLength": "验证码必须是4位数字",
+		"sendFailed": "发送验证码失败",
+		"loginSuccess": "登录成功",
+		"loginFailed": "登录失败",
+		"signIn": "登 录"
+	},
+	"forget": {
+		"newPasswordPlaceholder": "请输入新密码",
+		"confirmPasswordPlaceholder": "请确认新密码",
+		"passwordEmpty": "密码不能为空",
+		"passwordLength": "用户密码长度必须介于 6 和 20 之间",
+		"passwordRule": "两次输入的密码不一致",
+		"passwordScore": "密码强度太低"
+	},
+	"scan": {
+		"text": "打开手机扫一扫,快速登录/注册",
+		"wechatApp": "微信扫码体验移动端",
+		"appErrorTip": "应用未配置,登录失败"
+	},
+	"signInText": "欢迎回来!",
+	"browserMsgText": "* 温馨提示:建议使用谷歌、Microsoft Edge,版本 80 及以上浏览器,360浏览器请使用极速模式",
+	"expire": {
+		"oldPassword": "请输入原密码",
+		"newPassword": "请输入新密码",
+		"confirmPassword": "请确认新密码",
+		"passwordRule": "两次输入的密码不一致",
+		"passwordScore": "密码强度太低",
+		"resetSuccess": "密码重置成功"
+	},
+	"tenantSelect": {
+		"select": "选择租户",
+		"loadError": "获取租户列表失败"
+	},
+	"register": {
+		"tenantEmpty": "请选择租户",
+		"tenantLoadError": "获取租户列表失败",
+		"usernameEmpty": "用户名不能为空",
+		"usernameLength": "用户名称长度必须介于 5 和 20 之间",
+		"phoneEmpty": "手机号不能为空",
+		"passwordEmpty": "密码不能为空",
+		"passwordLength": "用户密码长度必须介于 6 和 20 之间",
+		"passwordStrength": "密码强度太低",
+		"termsRequired": "请阅读并同意条款"
+	},
+	"divider": {
+		"or": "或"
+	},
+	"socialLogin": {
+		"wechatWork": "企微",
+		"dingtalk": "钉钉"
+	},
+	"personal": {
+		"name": "个人信息",
+		"basicInfo": "基本信息",
+		"securityInfo": "安全信息",
+		"merchantNo": "商户号",
+		"nickname": "昵称",
+		"nicknamePlaceholder": "请输入昵称",
+		"realName": "姓名",
+		"realNamePlaceholder": "请输入姓名",
+		"phone": "手机",
+		"phonePlaceholder": "请输入手机",
+		"email": "邮箱",
+		"emailPlaceholder": "请输入邮箱",
+		"oldPassword": "原密码",
+		"oldPasswordPlaceholder": "请输入密码",
+		"newPassword": "新密码",
+		"newPasswordPlaceholder": "请输入新密码",
+		"confirmPassword": "确认密码",
+		"confirmPasswordPlaceholder": "请重复密码",
+		"changePassword": "修改密码",
+		"updateInfo": "更新个人信息",
+		"passwordRule": "两次输入密码不一致",
+		"passwordScore": "密码等级太低"
+	},
+	"dashboard": {
+		"submitOrder": "提交订单",
+		"payOrder": "支付订单",
+		"withdrawOrder": "提现订单",
+		"withdrawSuccess": "提现成功",
+		"paySuccessRate": "支付成功率",
+		"amount": "金额",
+		"loadFailed": "加载统计数据失败"
+	},
+	"payment": {
+		"channel": {
+			"channelName": "通道名称",
+			"channelNamePlaceholder": "请输入通道名称",
+			"paymentName": "支付方式",
+			"paymentNamePlaceholder": "请输入支付方式",
+			"paymentType": "支付类别",
+			"paymentTypePlaceholder": "请选择支付类别",
+			"paymentTypePay": "代付",
+			"paymentTypeHarvest": "代收",
+			"agentFeeType": "代理商手续费类型",
+			"agentFeeRate": "代理商手续费比例",
+			"agentFeeFixed": "代理商手续费固定金额",
+			"feeTypePercentage": "百分比",
+			"feeTypeFixed": "固定金额",
+			"feeTypeMixed": "混合",
+			"refresh": "刷新",
+			"fetchFailed": "获取费率信息失败"
+		}
+	},
+	"order": {
+		"payOrder": {
+			"title": "代收订单",
+			"mchOrderNo": "商户订单号",
+			"mchOrderNoPlaceholder": "请输入商户订单号",
+			"transactionId": "平台订单号",
+			"transactionIdPlaceholder": "请输入平台订单号",
+			"merchantName": "商户名称",
+			"merchantNamePlaceholder": "请输入商户名称",
+			"orderStatus": "订单状态",
+			"orderStatusPlaceholder": "请选择订单状态",
+			"createOrder": "创建订单",
+			"paySuccess": "支付成功",
+			"payFail": "支付失败",
+			"cancelOrder": "取消订单",
+			"payTimeout": "支付超时",
+			"submitOrders": "提交订单数",
+			"totalOrderAmount": "订单总金额",
+			"paidOrders": "已付订单数",
+			"paidTotalAmount": "已付总金额",
+			"channelName": "通道名称",
+			"submitAmount": "提交金额",
+			"actualAmount": "实际金额",
+			"createTime": "创建时间",
+			"operation": "操作",
+			"notifyLog": "回调日志",
+			"detail": "代收订单详情",
+			"orderId": "订单ID",
+			"appId": "AppId",
+			"currency": "币种",
+			"orderAmount": "订单金额",
+			"paidAmount": "实付金额",
+			"paymentChannelId": "支付通道ID",
+			"paymentChannelName": "支付通道名称",
+			"merchantId": "商户ID",
+			"agentId": "代理商ID",
+			"merchantFeeType": "商户手续费类型",
+			"merchantFee": "商户手续费",
+			"merchantFeeRate": "商户手续费比例",
+			"merchantFeeFixed": "商户手续费固定金额",
+			"agentFeeType": "代理商手续费类型",
+			"agentFee": "代理商手续费",
+			"agentFeeRate": "代理商手续费比例",
+			"agentFeeFixed": "代理商手续费固定金额",
+			"feeTypePercentage": "百分比",
+			"feeTypeFixed": "固定",
+			"feeTypeMixed": "百分比+固定",
+			"clientIp": "客户端IP",
+			"device": "设备",
+			"subject": "主题",
+			"body": "内容",
+			"returnUrl": "前端跳转URL",
+			"notifyUrl": "后台回调URL",
+			"extraParams": "扩展参数",
+			"reqTime": "请求时间",
+			"payCompleteTime": "支付完成时间",
+			"updateTime": "更新时间",
+			"close": "关闭"
+		},
+		"withdrawOrder": {
+			"title": "代付订单",
+			"detail": "代付订单详情",
+			"withdrawSuccess": "提现成功",
+			"withdrawFail": "提现失败",
+			"currencyType": "币种",
+			"paymentTypeId": "通道类型ID",
+			"feeStatus": "费率状态",
+			"feeStatusSuccess": "成功",
+			"feeStatusFail": "失败",
+			"payeeName": "收款人姓名",
+			"payeePhone": "收款人电话",
+			"bankAccount": "银行账号",
+			"bankName": "银行名称",
+			"payeeEmail": "收款人邮箱",
+			"completeTime": "完成时间"
+		},
+		"notifyLog": {
+			"title": "回调日志",
+			"orderNo": "订单号",
+			"notifyStatus": "通知状态",
+			"currentNotifyTimes": "当前通知次数",
+			"maxNotifyTimes": "最大通知次数",
+			"lastExecuteTime": "最后执行时间",
+			"nextNotifyTime": "下次通知时间",
+			"notifyUrl": "通知地址",
+			"failReason": "失败原因",
+			"notifyLogList": "通知日志",
+			"notifyTimes": "第 {n} 次通知",
+			"pending": "待通知",
+			"success": "通知成功",
+			"fail": "通知失败",
+			"processing": "通知中",
+			"responseResult": "响应结果",
+			"noResponse": "无响应",
+			"noNotifyLog": "暂无通知日志",
+			"fetchFailed": "获取回调日志失败"
+		}
+	},
+	"settlement": {
+		"fundFlow": {
+			"availableBalance": "可用余额",
+			"totalAmount": "总金额",
+			"totalFreezeAmount": "总冻结金额",
+			"totalWithdrawAmount": "总提现金额",
+			"orderNo": "订单号",
+			"orderNoPlaceholder": "请输入订单号",
+			"orderType": "订单类型",
+			"orderTypePlaceholder": "请选择订单类型",
+			"payOrder": "支付订单",
+			"withdrawOrder": "提现订单",
+			"walletType": "操作钱包类型",
+			"walletTypePlaceholder": "请选择钱包类型",
+			"walletTotal": "总金额",
+			"walletUse": "可用金额",
+			"walletFreeze": "冻结金额",
+			"walletWithdraw": "提现金额",
+			"walletWithdrawTotal": "提现总金额",
+			"orderCreateTime": "订单创建时间",
+			"payTime": "支付时间",
+			"to": "至",
+			"startTime": "开始时间",
+			"endTime": "结束时间",
+			"beforeAmount": "变更前余额",
+			"changeAmount": "变更金额",
+			"afterAmount": "变更后余额",
+			"businessOrder": "业务订单",
+			"orderAmount": "订单金额",
+			"createTime": "创建时间"
+		},
+		"apply": {
+			"title": "申请结算",
+			"availableAmount": "可提现金额",
+			"withdrawAmount": "提现金额",
+			"withdrawAmountPlaceholder": "请输入提现金额",
+			"withdrawAmountRequired": "请输入提现金额",
+			"withdrawAmountExceed": "提现金额不能超过可提现金额",
+			"withdrawType": "提现类型",
+			"withdrawTypeRequired": "请选择提现类型",
+			"bankCard": "银行卡",
+			"usdt": "USDT",
+			"bankName": "银行名称",
+			"bankNamePlaceholder": "请输入银行名称",
+			"bankNameRequired": "请输入银行名称",
+			"bankAccount": "银行卡账号",
+			"bankAccountPlaceholder": "请输入银行卡账号/USDT地址",
+			"bankAccountRequired": "请输入银行卡账号/USDT地址",
+			"realName": "真实姓名",
+			"realNamePlaceholder": "请输入真实姓名",
+			"realNameRequired": "请输入真实姓名",
+			"submit": "提交申请",
+			"submitSuccess": "申请提交成功"
+		},
+		"record": {
+			"realName": "真实姓名",
+			"realNamePlaceholder": "请输入真实姓名",
+			"bankAccount": "银行卡账号",
+			"bankAccountPlaceholder": "请输入银行卡账号",
+			"auditStatus": "审核状态",
+			"auditStatusPlaceholder": "请选择审核状态",
+			"pending": "待审核",
+			"approved": "通过",
+			"rejected": "拒绝",
+			"agentName": "代理名称",
+			"withdrawAmount": "提现金额",
+			"withdrawType": "提现类型",
+			"bankCard": "银行卡",
+			"usdt": "USDT",
+			"bankName": "银行名称",
+			"rejectReason": "拒绝原因",
+			"applyTime": "申请时间",
+			"createTime": "创建时间"
+		}
+	}
+}

+ 1 - 1
src/main.ts

@@ -4,7 +4,7 @@ import App from './App.vue';
 import router from './router';
 import { directive } from '/@/directive';
 import Components from '/@/components';
-import { i18n } from '/@/i18n';
+import { i18n } from '/@/locales';
 import { properties } from '/@/utils/globalProperties';
 import { initAntiDebug } from './utils/antiDebug';
 

+ 3 - 3
src/stores/tagsViewRoutes.ts

@@ -2,7 +2,7 @@ import { defineStore } from 'pinia';
 import { Session } from '/@/utils/storage';
 import { useMessage } from '/@/hooks/message';
 import { useThemeConfig } from '/@/stores/themeConfig';
-import { i18n } from '/@/i18n/index';
+import { i18n } from '/@/locales';
 
 /**
  * TagsView 路由列表
@@ -28,8 +28,8 @@ export const useTagsViewRoutes = defineStore('tagsViewRoutes', {
 			const { themeConfig } = storeToRefs(storesThemeConfig);
 			// 判断已经存储的长度,如果超过主题设置则警告
 			if (this.favoriteRoutes.length > themeConfig.value.quickLinkNum) {
-				useMessage().error(i18n.global.t('tagsView.favoriteMax'))
-				return
+				useMessage().error(i18n.global.t('tagsView.favoriteMax'));
+				return;
 			}
 			this.favoriteRoutes.unshift(item);
 		},

+ 321 - 322
src/utils/other.ts

@@ -1,30 +1,29 @@
-import {nextTick} from 'vue';
+import { nextTick } from 'vue';
 import router from '/@/router/index';
 import pinia from '/@/stores/index';
-import {storeToRefs} from 'pinia';
-import {useThemeConfig} from '/@/stores/themeConfig';
-import {i18n} from '/@/i18n/index';
-import {Local} from '/@/utils/storage';
-import {verifyUrl} from '/@/utils/toolsValidate';
+import { storeToRefs } from 'pinia';
+import { useThemeConfig } from '/@/stores/themeConfig';
+import { i18n } from '/@/locales';
+import { Local } from '/@/utils/storage';
+import { verifyUrl } from '/@/utils/toolsValidate';
 import request from '/@/utils/request';
-import {useMessage} from '/@/hooks/message';
+import { useMessage } from '/@/hooks/message';
 import * as CryptoJS from 'crypto-js';
-import {sm4} from 'sm-crypto'
-import {validateNull} from './validate';
-
+import { sm4 } from 'sm-crypto';
+import { validateNull } from './validate';
 
 /**
  * 设置浏览器标题国际化
  * @method const title = useTitle(); ==> title()
  */
 export function useTitle() {
-    const stores = useThemeConfig(pinia);
-    const {themeConfig} = storeToRefs(stores);
-    nextTick(() => {
-        let globalTitle: string = themeConfig.value.globalTitle;
-        let webTitle = setTagsViewNameI18n(router.currentRoute.value);
-        document.title = `${webTitle} - ${globalTitle}` || globalTitle;
-    });
+	const stores = useThemeConfig(pinia);
+	const { themeConfig } = storeToRefs(stores);
+	nextTick(() => {
+		let globalTitle: string = themeConfig.value.globalTitle;
+		let webTitle = setTagsViewNameI18n(router.currentRoute.value);
+		document.title = `${webTitle} - ${globalTitle}` || globalTitle;
+	});
 }
 
 /**
@@ -33,24 +32,24 @@ export function useTitle() {
  * @returns 返回当前 tagsViewName 名称
  */
 export function setTagsViewNameI18n(item: any) {
-    let tagsViewName: string = '';
-    const {query, params} = item;
-    //修复tagsViewName匹配到其他含下列单词的路由
-    const pattern = /^\{("(zh-cn|en|zh-tw)":"[^,]+",?){1,3}}$/;
-    if (query?.tagsViewName || params?.tagsViewName) {
-        if (pattern.test(query?.tagsViewName) || pattern.test(params?.tagsViewName)) {
-            // 国际化
-            const urlTagsParams = (query?.tagsViewName && JSON.parse(query?.tagsViewName)) || (params?.tagsViewName && JSON.parse(params?.tagsViewName));
-            tagsViewName = urlTagsParams[i18n.global.locale.value];
-        } else {
-            // 非国际化
-            tagsViewName = query?.tagsViewName || params?.tagsViewName;
-        }
-    } else {
-        // 非自定义 tagsView 名称
-        tagsViewName = i18n.global.t(item.name);
-    }
-    return tagsViewName;
+	let tagsViewName: string = '';
+	const { query, params } = item;
+	//修复tagsViewName匹配到其他含下列单词的路由
+	const pattern = /^\{("(zh-cn|en|zh-tw)":"[^,]+",?){1,3}}$/;
+	if (query?.tagsViewName || params?.tagsViewName) {
+		if (pattern.test(query?.tagsViewName) || pattern.test(params?.tagsViewName)) {
+			// 国际化
+			const urlTagsParams = (query?.tagsViewName && JSON.parse(query?.tagsViewName)) || (params?.tagsViewName && JSON.parse(params?.tagsViewName));
+			tagsViewName = urlTagsParams[i18n.global.locale.value];
+		} else {
+			// 非国际化
+			tagsViewName = query?.tagsViewName || params?.tagsViewName;
+		}
+	} else {
+		// 非自定义 tagsView 名称
+		tagsViewName = i18n.global.t(item.name);
+	}
+	return tagsViewName;
 }
 
 /**
@@ -60,21 +59,21 @@ export function setTagsViewNameI18n(item: any) {
  * @description data-xxx 属性用于存储页面或应用程序的私有自定义数据
  */
 export const lazyImg = (el: string, arr: EmptyArrayType) => {
-    const io = new IntersectionObserver((res) => {
-        res.forEach((v: any) => {
-            if (v.isIntersecting) {
-                const {img, key} = v.target.dataset;
-                v.target.src = img;
-                v.target.onload = () => {
-                    io.unobserve(v.target);
-                    arr[key]['loading'] = false;
-                };
-            }
-        });
-    });
-    nextTick(() => {
-        document.querySelectorAll(el).forEach((img) => io.observe(img));
-    });
+	const io = new IntersectionObserver((res) => {
+		res.forEach((v: any) => {
+			if (v.isIntersecting) {
+				const { img, key } = v.target.dataset;
+				v.target.src = img;
+				v.target.onload = () => {
+					io.unobserve(v.target);
+					arr[key]['loading'] = false;
+				};
+			}
+		});
+	});
+	nextTick(() => {
+		document.querySelectorAll(el).forEach((img) => io.observe(img));
+	});
 };
 
 /**
@@ -82,9 +81,9 @@ export const lazyImg = (el: string, arr: EmptyArrayType) => {
  * @returns 返回 `window.localStorage` 中读取的缓存值 `globalComponentSize`
  */
 export const globalComponentSize = (): string => {
-    const stores = useThemeConfig(pinia);
-    const {themeConfig} = storeToRefs(stores);
-    return Local.get('themeConfig')?.globalComponentSize || themeConfig.value?.globalComponentSize;
+	const stores = useThemeConfig(pinia);
+	const { themeConfig } = storeToRefs(stores);
+	return Local.get('themeConfig')?.globalComponentSize || themeConfig.value?.globalComponentSize;
 };
 
 /**
@@ -93,35 +92,35 @@ export const globalComponentSize = (): string => {
  * @returns 克隆后的对象
  */
 export function deepClone(obj: EmptyObjectType) {
-    let newObj: EmptyObjectType;
-    try {
-        newObj = obj.push ? [] : {};
-    } catch (error) {
-        newObj = {};
-    }
-    for (let attr in obj) {
-        if (obj[attr] && typeof obj[attr] === 'object') {
-            newObj[attr] = deepClone(obj[attr]);
-        } else {
-            newObj[attr] = obj[attr];
-        }
-    }
-    return newObj;
+	let newObj: EmptyObjectType;
+	try {
+		newObj = obj.push ? [] : {};
+	} catch (error) {
+		newObj = {};
+	}
+	for (let attr in obj) {
+		if (obj[attr] && typeof obj[attr] === 'object') {
+			newObj[attr] = deepClone(obj[attr]);
+		} else {
+			newObj[attr] = obj[attr];
+		}
+	}
+	return newObj;
 }
 
 /**
  * 判断是否是移动端
  */
 export function isMobile() {
-    if (
-        navigator.userAgent.match(
-            /('phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone')/i
-        )
-    ) {
-        return true;
-    } else {
-        return false;
-    }
+	if (
+		navigator.userAgent.match(
+			/('phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone')/i
+		)
+	) {
+		return true;
+	} else {
+		return false;
+	}
 }
 
 /**
@@ -131,18 +130,18 @@ export function isMobile() {
  * @returns 删除空值后的数组对象
  */
 export function handleEmpty(list: EmptyArrayType) {
-    const arr = [] as any[];
-    for (const i in list) {
-        const d = [] as any[];
-        for (const j in list[i]) {
-            d.push(list[i][j]);
-        }
-        const leng = d.filter((item) => item === '').length;
-        if (leng !== d.length) {
-            arr.push(list[i]);
-        }
-    }
-    return arr;
+	const arr = [] as any[];
+	for (const i in list) {
+		const d = [] as any[];
+		for (const j in list[i]) {
+			d.push(list[i][j]);
+		}
+		const leng = d.filter((item) => item === '').length;
+		if (leng !== d.length) {
+			arr.push(list[i]);
+		}
+	}
+	return arr;
 }
 
 /**
@@ -150,55 +149,55 @@ export function handleEmpty(list: EmptyArrayType) {
  * @param val 当前点击项菜单
  */
 export function handleOpenLink(val: RouteItem) {
-    router.push(val.path);
-    if (verifyUrl(<string>val.meta?.isLink)) window.open(val.meta?.isLink);
-    else window.open(`${val.meta?.isLink}`);
+	router.push(val.path);
+	if (verifyUrl(<string>val.meta?.isLink)) window.open(val.meta?.isLink);
+	else window.open(`${val.meta?.isLink}`);
 }
 
 /**
  * 打开小窗口
  */
 export const openWindow = (url: string, title: string, w: number, h: number) => {
-    // @ts-ignore
-    const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
-    // @ts-ignore
-    const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;
-
-    const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
-    const height = window.innerHeight
-        ? window.innerHeight
-        : document.documentElement.clientHeight
-            ? document.documentElement.clientHeight
-            : screen.height;
-
-    const left = width / 2 - w / 2 + dualScreenLeft;
-    const top = height / 2 - h / 2 + dualScreenTop;
-    return window.open(
-        url,
-        title,
-        'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=' +
-        w +
-        ', height=' +
-        h +
-        ', top=' +
-        top +
-        ', left=' +
-        left
-    );
+	// @ts-ignore
+	const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
+	// @ts-ignore
+	const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;
+
+	const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
+	const height = window.innerHeight
+		? window.innerHeight
+		: document.documentElement.clientHeight
+		? document.documentElement.clientHeight
+		: screen.height;
+
+	const left = width / 2 - w / 2 + dualScreenLeft;
+	const top = height / 2 - h / 2 + dualScreenTop;
+	return window.open(
+		url,
+		title,
+		'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=' +
+			w +
+			', height=' +
+			h +
+			', top=' +
+			top +
+			', left=' +
+			left
+	);
 };
 
 /**
  *加密处理
  */
 export function encryption(src: string, keyWord: string) {
-    const key = CryptoJS.enc.Utf8.parse(keyWord);
-    // 加密
-    var encrypted = CryptoJS.AES.encrypt(src, key, {
-        iv: key,
-        mode: CryptoJS.mode.CFB,
-        padding: CryptoJS.pad.NoPadding,
-    });
-    return encrypted.toString();
+	const key = CryptoJS.enc.Utf8.parse(keyWord);
+	// 加密
+	var encrypted = CryptoJS.AES.encrypt(src, key, {
+		iv: key,
+		mode: CryptoJS.mode.CFB,
+		padding: CryptoJS.pad.NoPadding,
+	});
+	return encrypted.toString();
 }
 
 /**
@@ -207,22 +206,22 @@ export function encryption(src: string, keyWord: string) {
  * @returns 明文
  */
 export function decryption(src: string, keyWord: string) {
-    const key = CryptoJS.enc.Utf8.parse(keyWord);
-    // 解密逻辑
-    var decryptd = CryptoJS.AES.decrypt(src, key, {
-        iv: key,
-        mode: CryptoJS.mode.CFB,
-        padding: CryptoJS.pad.NoPadding,
-    });
-
-    return decryptd.toString(CryptoJS.enc.Utf8);
+	const key = CryptoJS.enc.Utf8.parse(keyWord);
+	// 解密逻辑
+	var decryptd = CryptoJS.AES.decrypt(src, key, {
+		iv: key,
+		mode: CryptoJS.mode.CFB,
+		padding: CryptoJS.pad.NoPadding,
+	});
+
+	return decryptd.toString(CryptoJS.enc.Utf8);
 }
 
 /**
  * SM4加密处理
  */
 export function sm4Encryption(src: string, keyWord: string) {
-    return sm4.encrypt(src, keyWord);
+	return sm4.encrypt(src, keyWord);
 }
 
 /**
@@ -231,7 +230,7 @@ export function sm4Encryption(src: string, keyWord: string) {
  * @returns 明文
  */
 export function sm4Decryption(src: string, keyWord: string) {
-    return sm4.decrypt(src, keyWord);
+	return sm4.decrypt(src, keyWord);
 }
 
 /**
@@ -240,8 +239,8 @@ export function sm4Decryption(src: string, keyWord: string) {
  * @returns 密文
  */
 export function base64Encrypt(src: string) {
-    const encodedWord = CryptoJS.enc.Utf8.parse(src);
-    return CryptoJS.enc.Base64.stringify(encodedWord);
+	const encodedWord = CryptoJS.enc.Utf8.parse(src);
+	return CryptoJS.enc.Base64.stringify(encodedWord);
 }
 
 /**
@@ -252,14 +251,14 @@ export function base64Encrypt(src: string) {
  * @returns {*}
  */
 export function downBlobFile(url: any, query: any, fileName: string) {
-    return request({
-        url: url,
-        method: 'get',
-        responseType: 'blob',
-        params: query,
-    }).then((response) => {
-        handleBlobFile(response, fileName);
-    });
+	return request({
+		url: url,
+		method: 'get',
+		responseType: 'blob',
+		params: query,
+	}).then((response) => {
+		handleBlobFile(response, fileName);
+	});
 }
 
 /**
@@ -268,26 +267,26 @@ export function downBlobFile(url: any, query: any, fileName: string) {
  * @returns
  */
 export function handleBlobFile(response: any, fileName: string) {
-    // 处理返回的文件流
-    const blob = response;
-    if (blob && blob.size === 0) {
-        useMessage().error('内容为空,无法下载');
-        return;
-    }
-    const link = document.createElement('a');
-
-    // 兼容一下 入参不是 File Blob 类型情况
-    var binaryData = [] as any;
-    binaryData.push(response);
-    link.href = window.URL.createObjectURL(new Blob(binaryData));
-    link.download = fileName;
-    document.body.appendChild(link);
-    link.click();
-    window.setTimeout(function () {
-        // @ts-ignore
-        URL.revokeObjectURL(blob);
-        document.body.removeChild(link);
-    }, 0);
+	// 处理返回的文件流
+	const blob = response;
+	if (blob && blob.size === 0) {
+		useMessage().error('内容为空,无法下载');
+		return;
+	}
+	const link = document.createElement('a');
+
+	// 兼容一下 入参不是 File Blob 类型情况
+	var binaryData = [] as any;
+	binaryData.push(response);
+	link.href = window.URL.createObjectURL(new Blob(binaryData));
+	link.download = fileName;
+	document.body.appendChild(link);
+	link.click();
+	window.setTimeout(function () {
+		// @ts-ignore
+		URL.revokeObjectURL(blob);
+		document.body.removeChild(link);
+	}, 0);
 }
 
 /**
@@ -295,31 +294,31 @@ export function handleBlobFile(response: any, fileName: string) {
  * @return string
  */
 export function generateUUID() {
-    if (typeof crypto === 'object') {
-        if (typeof crypto.randomUUID === 'function') {
-            return crypto.randomUUID();
-        }
-        if (typeof crypto.getRandomValues === 'function' && typeof Uint8Array === 'function') {
-            const callback = (c: any) => {
-                const num = Number(c);
-                return (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString(16);
-            };
-            return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, callback);
-        }
-    }
-    let timestamp = new Date().getTime();
-    let performanceNow = (typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0;
-    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
-        let random = Math.random() * 16;
-        if (timestamp > 0) {
-            random = (timestamp + random) % 16 | 0;
-            timestamp = Math.floor(timestamp / 16);
-        } else {
-            random = (performanceNow + random) % 16 | 0;
-            performanceNow = Math.floor(performanceNow / 16);
-        }
-        return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16);
-    });
+	if (typeof crypto === 'object') {
+		if (typeof crypto.randomUUID === 'function') {
+			return crypto.randomUUID();
+		}
+		if (typeof crypto.getRandomValues === 'function' && typeof Uint8Array === 'function') {
+			const callback = (c: any) => {
+				const num = Number(c);
+				return (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString(16);
+			};
+			return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, callback);
+		}
+	}
+	let timestamp = new Date().getTime();
+	let performanceNow = (typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0;
+	return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
+		let random = Math.random() * 16;
+		if (timestamp > 0) {
+			random = (timestamp + random) % 16 | 0;
+			timestamp = Math.floor(timestamp / 16);
+		} else {
+			random = (performanceNow + random) % 16 | 0;
+			performanceNow = Math.floor(performanceNow / 16);
+		}
+		return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16);
+	});
 }
 
 /**
@@ -334,96 +333,96 @@ export function generateUUID() {
  * @method handleOpenLink 打开外部链接
  */
 const other = {
-    useTitle: () => {
-        useTitle();
-    },
-    setTagsViewNameI18n(route: RouteToFrom) {
-        return setTagsViewNameI18n(route);
-    },
-    lazyImg: (el: string, arr: EmptyArrayType) => {
-        lazyImg(el, arr);
-    },
-    globalComponentSize: () => {
-        return globalComponentSize();
-    },
-    deepClone: (obj: EmptyObjectType) => {
-        return deepClone(obj);
-    },
-    isMobile: () => {
-        return isMobile();
-    },
-    handleEmpty: (list: EmptyArrayType) => {
-        return handleEmpty(list);
-    },
-    handleOpenLink: (val: RouteItem) => {
-        handleOpenLink(val);
-    },
-    encryption: (src: string, keyWord: string) => {
-        return encryption(src, keyWord);
-    },
-    decryption: (src: string, keyWord: string) => {
-        return decryption(src, keyWord);
-    },
-    base64Encrypt: (data: any) => {
-        return base64Encrypt(data);
-    },
-    downBlobFile: (url: any, query: any, fileName: string) => {
-        return downBlobFile(url, query, fileName);
-    },
-    toUnderline: (str: string) => {
-        return toUnderline(str);
-    },
-    openWindow: (url: string, title: string, w: number, h: number) => {
-        return openWindow(url, title, w, h);
-    },
-    getQueryString: (url: string, paraName: string) => {
-        return getQueryString(url, paraName);
-    },
-    adaptationUrl: (url?: string) => {
-        return adaptationUrl(url);
-    },
-    resolveAllEunuchNodeId: (json: any[], idArr: any[], temp: any[] = []) => {
-        return resolveAllEunuchNodeId(json, idArr, temp);
-    },
-    getNonDuplicateID: () => {
-        return getNonDuplicateID();
-    },
-
-    addUnit: (value: string | number, unit = 'px') => {
-        return addUnit(value, unit);
-    },
-    validateNull: (value: any) => {
-        return validateNull(value);
-    },
-    getNumberRadixNum: (input: Number) => {
-        return getNumberRadixNum(input);
-    }
+	useTitle: () => {
+		useTitle();
+	},
+	setTagsViewNameI18n(route: RouteToFrom) {
+		return setTagsViewNameI18n(route);
+	},
+	lazyImg: (el: string, arr: EmptyArrayType) => {
+		lazyImg(el, arr);
+	},
+	globalComponentSize: () => {
+		return globalComponentSize();
+	},
+	deepClone: (obj: EmptyObjectType) => {
+		return deepClone(obj);
+	},
+	isMobile: () => {
+		return isMobile();
+	},
+	handleEmpty: (list: EmptyArrayType) => {
+		return handleEmpty(list);
+	},
+	handleOpenLink: (val: RouteItem) => {
+		handleOpenLink(val);
+	},
+	encryption: (src: string, keyWord: string) => {
+		return encryption(src, keyWord);
+	},
+	decryption: (src: string, keyWord: string) => {
+		return decryption(src, keyWord);
+	},
+	base64Encrypt: (data: any) => {
+		return base64Encrypt(data);
+	},
+	downBlobFile: (url: any, query: any, fileName: string) => {
+		return downBlobFile(url, query, fileName);
+	},
+	toUnderline: (str: string) => {
+		return toUnderline(str);
+	},
+	openWindow: (url: string, title: string, w: number, h: number) => {
+		return openWindow(url, title, w, h);
+	},
+	getQueryString: (url: string, paraName: string) => {
+		return getQueryString(url, paraName);
+	},
+	adaptationUrl: (url?: string) => {
+		return adaptationUrl(url);
+	},
+	resolveAllEunuchNodeId: (json: any[], idArr: any[], temp: any[] = []) => {
+		return resolveAllEunuchNodeId(json, idArr, temp);
+	},
+	getNonDuplicateID: () => {
+		return getNonDuplicateID();
+	},
+
+	addUnit: (value: string | number, unit = 'px') => {
+		return addUnit(value, unit);
+	},
+	validateNull: (value: any) => {
+		return validateNull(value);
+	},
+	getNumberRadixNum: (input: Number) => {
+		return getNumberRadixNum(input);
+	},
 };
 
 export function getNumberRadixNum(input: Number) {
-    let strings = input.toString().split(".");
-    if (strings.length <= 1) {
-        return 0;
-    }
-    return strings[1].toString().length;
-};
+	let strings = input.toString().split('.');
+	if (strings.length <= 1) {
+		return 0;
+	}
+	return strings[1].toString().length;
+}
 
 export function getQueryString(url: string, paraName: string) {
-    const arrObj = url.split('?');
-    if (arrObj.length > 1) {
-        const arrPara = arrObj[1].split('&');
-        let arr;
-        for (let i = 0; i < arrPara.length; i++) {
-            arr = arrPara[i].split('=');
-            // eslint-disable-next-line eqeqeq
-            if (arr != null && arr[0] == paraName) {
-                return arr[1];
-            }
-        }
-        return '';
-    } else {
-        return '';
-    }
+	const arrObj = url.split('?');
+	if (arrObj.length > 1) {
+		const arrPara = arrObj[1].split('&');
+		let arr;
+		for (let i = 0; i < arrPara.length; i++) {
+			arr = arrPara[i].split('=');
+			// eslint-disable-next-line eqeqeq
+			if (arr != null && arr[0] == paraName) {
+				return arr[1];
+			}
+		}
+		return '';
+	} else {
+		return '';
+	}
 }
 
 /**
@@ -436,31 +435,31 @@ export function getQueryString(url: string, paraName: string) {
  * @returns {*}
  */
 export function handleTree(data: any, id: any, parentId: any, children: any, rootId: any) {
-    id = id || 'id';
-    parentId = parentId || 'parentId';
-    children = children || 'children';
-    rootId =
-        rootId ||
-        Math.min.apply(
-            Math,
-            data.map((item: any) => {
-                return item[parentId];
-            })
-        ) ||
-        0;
-    //对源数据深度克隆
-    const cloneData = JSON.parse(JSON.stringify(data));
-    //循环所有项
-    const treeData = cloneData.filter((father: any) => {
-        const branchArr = cloneData.filter((child: any) => {
-            //返回每一项的子级数组
-            return father[id] === child[parentId];
-        });
-        branchArr.length > 0 ? (father[children] = branchArr) : '';
-        //返回第一层
-        return father[parentId] === rootId;
-    });
-    return treeData !== '' ? treeData : data;
+	id = id || 'id';
+	parentId = parentId || 'parentId';
+	children = children || 'children';
+	rootId =
+		rootId ||
+		Math.min.apply(
+			Math,
+			data.map((item: any) => {
+				return item[parentId];
+			})
+		) ||
+		0;
+	//对源数据深度克隆
+	const cloneData = JSON.parse(JSON.stringify(data));
+	//循环所有项
+	const treeData = cloneData.filter((father: any) => {
+		const branchArr = cloneData.filter((child: any) => {
+			//返回每一项的子级数组
+			return father[id] === child[parentId];
+		});
+		branchArr.length > 0 ? (father[children] = branchArr) : '';
+		//返回第一层
+		return father[parentId] === rootId;
+	});
+	return treeData !== '' ? treeData : data;
 }
 
 /**
@@ -468,14 +467,14 @@ export function handleTree(data: any, id: any, parentId: any, children: any, roo
  * @returns
  */
 const resolveAllEunuchNodeId = (json: any[], idArr: any[], temp: any[] = []) => {
-    for (const item of json) {
-        if (item.children && item.children.length !== 0) {
-            resolveAllEunuchNodeId(item.children, idArr, temp);
-        } else {
-            temp.push(...idArr.filter((id) => id === item.id));
-        }
-    }
-    return temp;
+	for (const item of json) {
+		if (item.children && item.children.length !== 0) {
+			resolveAllEunuchNodeId(item.children, idArr, temp);
+		} else {
+			temp.push(...idArr.filter((id) => id === item.id));
+		}
+	}
+	return temp;
 };
 
 /**
@@ -484,7 +483,7 @@ const resolveAllEunuchNodeId = (json: any[], idArr: any[], temp: any[] = []) =>
  * @returns 下划线
  */
 export function toUnderline(str: string) {
-    return str.replace(/([A-Z])/g, '_$1').toLowerCase();
+	return str.replace(/([A-Z])/g, '_$1').toLowerCase();
 }
 
 /**
@@ -495,14 +494,14 @@ export function toUnderline(str: string) {
  * @param originUrl 原始路径
  */
 const adaptationUrl = (originUrl?: string) => {
-    // 微服务架构 不做路径转换,为空不做路径转换
-    const isMicro = import.meta.env.VITE_IS_MICRO;
-    if (validateNull(isMicro) || isMicro === 'true') {
-        return originUrl;
-    }
-
-    // 转为 /admin 路由前缀的请求
-    return `/admin/${originUrl?.split('/').splice(2).join('/')}`;
+	// 微服务架构 不做路径转换,为空不做路径转换
+	const isMicro = import.meta.env.VITE_IS_MICRO;
+	if (validateNull(isMicro) || isMicro === 'true') {
+		return originUrl;
+	}
+
+	// 转为 /admin 路由前缀的请求
+	return `/admin/${originUrl?.split('/').splice(2).join('/')}`;
 };
 
 /**
@@ -511,9 +510,9 @@ const adaptationUrl = (originUrl?: string) => {
  * @return { String } id
  */
 const getNonDuplicateID = (length = 8) => {
-    let idStr = Date.now().toString(36);
-    idStr += Math.random().toString(36).substring(3, length);
-    return idStr;
+	let idStr = Date.now().toString(36);
+	idStr += Math.random().toString(36).substring(3, length);
+	return idStr;
 };
 
 /**
@@ -522,7 +521,7 @@ const getNonDuplicateID = (length = 8) => {
  * @param {String} unit 单位 px em rem
  */
 const addUnit = (value: string | number, unit = 'px') => {
-    return !Object.is(Number(value), NaN) ? `${value}${unit}` : value;
+	return !Object.is(Number(value), NaN) ? `${value}${unit}` : value;
 };
 
 // 统一批量导出

+ 30 - 20
src/views/admin/system/user/personal.vue

@@ -1,7 +1,7 @@
 <template>
 	<el-drawer v-model="visible" :title="$t('personal.name')" size="40%">
 		<el-tabs style="height: 200px" class="demo-tabs">
-			<el-tab-pane label="基本信息" v-loading="loading">
+			<el-tab-pane :label="$t('personal.basicInfo')" v-loading="loading">
 				<template #label>
 					<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
 						<path
@@ -10,33 +10,33 @@
 							d="M17.982 18.725A7.488 7.488 0 0 0 12 15.75a7.488 7.488 0 0 0-5.982 2.975m11.963 0a9 9 0 1 0-11.963 0m11.963 0A8.966 8.966 0 0 1 12 21a8.966 8.966 0 0 1-5.982-2.275M15 9.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"
 						/>
 					</svg>
-					基本信息
+					{{ $t('personal.basicInfo') }}
 				</template>
 				<el-form :model="formData" :rules="ruleForm" label-width="100px" class="mt30" ref="formdataRef">
 					<el-row :gutter="20">
 						<el-col :span="24" class="mb20" v-if="formData?.appId">
-							<el-form-item label="商户号">
+							<el-form-item :label="$t('personal.merchantNo')">
 								<el-input v-model="formData.appId" readonly></el-input>
 							</el-form-item>
 						</el-col>
 						<el-col :span="24" class="mb20" v-if="formData?.nickname">
-							<el-form-item label="昵称" prop="nickname">
-								<el-input v-model="formData.nickname" placeholder="请输入昵称" clearable readonly></el-input>
+							<el-form-item :label="$t('personal.nickname')" prop="nickname">
+								<el-input v-model="formData.nickname" :placeholder="$t('personal.nicknamePlaceholder')" clearable readonly></el-input>
 							</el-form-item>
 						</el-col>
 						<el-col :span="24" class="mb20" v-if="formData?.name">
-							<el-form-item label="姓名" prop="name">
-								<el-input v-model="formData.name" placeholder="请输入姓名" clearable readonly></el-input>
+							<el-form-item :label="$t('personal.realName')" prop="name">
+								<el-input v-model="formData.name" :placeholder="$t('personal.realNamePlaceholder')" clearable readonly></el-input>
 							</el-form-item>
 						</el-col>
 						<el-col :span="24" class="mb20" v-if="formData?.phone">
-							<el-form-item label="手机" prop="phone">
-								<el-input v-model="formData.phone" placeholder="请输入手机" clearable readonly></el-input>
+							<el-form-item :label="$t('personal.phone')" prop="phone">
+								<el-input v-model="formData.phone" :placeholder="$t('personal.phonePlaceholder')" clearable readonly></el-input>
 							</el-form-item>
 						</el-col>
 						<el-col :span="24" class="mb20" v-if="formData?.email">
-							<el-form-item label="邮箱" prop="email">
-								<el-input v-model="formData.email" placeholder="请输入邮箱" clearable readonly></el-input>
+							<el-form-item :label="$t('personal.email')" prop="email">
+								<el-input v-model="formData.email" :placeholder="$t('personal.emailPlaceholder')" clearable readonly></el-input>
 							</el-form-item>
 						</el-col>
 						<!-- <el-col :span="24" class="mb20">
@@ -47,7 +47,7 @@
 					</el-row>
 				</el-form>
 			</el-tab-pane>
-			<el-tab-pane label="安全信息">
+			<el-tab-pane :label="$t('personal.securityInfo')">
 				<template #label>
 					<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
 						<path
@@ -56,13 +56,18 @@
 							d="M9 12.75 11.25 15 15 9.75m-3-7.036A11.959 11.959 0 0 1 3.598 6 11.99 11.99 0 0 0 3 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285Z"
 						/>
 					</svg>
-					安全信息
+					{{ $t('personal.securityInfo') }}
 				</template>
 				<el-form :model="passwordFormData" :rules="passwordRuleForm" label-width="100px" class="mt30" ref="passwordFormdataRef">
 					<el-row :gutter="20">
 						<el-col :span="24" class="mb20">
-							<el-form-item label="原密码" prop="password">
-								<el-input v-model="passwordFormData.password" :type="showPassword ? 'text' : 'password'" placeholder="请输入密码" clearable>
+							<el-form-item :label="$t('personal.oldPassword')" prop="password">
+								<el-input
+									v-model="passwordFormData.password"
+									:type="showPassword ? 'text' : 'password'"
+									:placeholder="$t('personal.oldPasswordPlaceholder')"
+									clearable
+								>
 									<template #suffix>
 										<i
 											class="iconfont el-input__icon login-content-password"
@@ -75,25 +80,30 @@
 							</el-form-item>
 						</el-col>
 						<el-col :span="24" class="mb20">
-							<el-form-item label="新密码" prop="newpassword1">
+							<el-form-item :label="$t('personal.newPassword')" prop="newpassword1">
 								<strength-meter
 									v-model="passwordFormData.newpassword1"
 									:minlength="6"
 									:maxlength="16"
-									placeholder="请输入新密码"
+									:placeholder="$t('personal.newPasswordPlaceholder')"
 									@score="passwordScore"
 								></strength-meter>
 								<!--									<el-input v-model="passwordFormData.newpassword1" clearable type="password"></el-input>-->
 							</el-form-item>
 						</el-col>
 						<el-col :span="24" class="mb20">
-							<el-form-item label="确认密码" prop="newpassword2">
-								<strength-meter v-model="passwordFormData.newpassword2" :minlength="6" :maxlength="16" placeholder="请重复密码"></strength-meter>
+							<el-form-item :label="$t('personal.confirmPassword')" prop="newpassword2">
+								<strength-meter
+									v-model="passwordFormData.newpassword2"
+									:minlength="6"
+									:maxlength="16"
+									:placeholder="$t('personal.confirmPasswordPlaceholder')"
+								></strength-meter>
 							</el-form-item>
 						</el-col>
 						<el-col :span="24" class="mb20">
 							<el-form-item>
-								<el-button type="primary" @click="handleChangePassword"> 修改密码 </el-button>
+								<el-button type="primary" @click="handleChangePassword">{{ $t('personal.changePassword') }}</el-button>
 							</el-form-item>
 						</el-col>
 					</el-row>

+ 14 - 11
src/views/home/index.vue

@@ -9,9 +9,9 @@
 							<el-icon :size="28"><DocumentAdd /></el-icon>
 						</div>
 						<div class="stat-info">
-							<div class="stat-title">提交订单</div>
+							<div class="stat-title">{{ $t('dashboard.submitOrder') }}</div>
 							<div class="stat-number">{{ statistics.submitCreateNum || 0 }}</div>
-							<div class="stat-desc">金额: {{ formatAmount(statistics.submitCreateAmount) }}</div>
+							<div class="stat-desc">{{ $t('dashboard.amount') }}: {{ formatAmount(statistics.submitCreateAmount) }}</div>
 						</div>
 					</div>
 				</el-card>
@@ -25,9 +25,9 @@
 							<el-icon :size="28"><Wallet /></el-icon>
 						</div>
 						<div class="stat-info">
-							<div class="stat-title">支付订单</div>
+							<div class="stat-title">{{ $t('dashboard.payOrder') }}</div>
 							<div class="stat-number">{{ statistics.payOrderNum || 0 }}</div>
-							<div class="stat-desc">金额: {{ formatAmount(statistics.payOrderAmount) }}</div>
+							<div class="stat-desc">{{ $t('dashboard.amount') }}: {{ formatAmount(statistics.payOrderAmount) }}</div>
 						</div>
 					</div>
 				</el-card>
@@ -41,9 +41,9 @@
 							<el-icon :size="28"><Money /></el-icon>
 						</div>
 						<div class="stat-info">
-							<div class="stat-title">提现订单</div>
+							<div class="stat-title">{{ $t('dashboard.withdrawOrder') }}</div>
 							<div class="stat-number">{{ statistics.withdrawOrderNum || 0 }}</div>
-							<div class="stat-desc">金额: {{ formatAmount(statistics.withdrawOrderAmount) }}</div>
+							<div class="stat-desc">{{ $t('dashboard.amount') }}: {{ formatAmount(statistics.withdrawOrderAmount) }}</div>
 						</div>
 					</div>
 				</el-card>
@@ -57,9 +57,9 @@
 							<el-icon :size="28"><CircleCheck /></el-icon>
 						</div>
 						<div class="stat-info">
-							<div class="stat-title">提现成功</div>
+							<div class="stat-title">{{ $t('dashboard.withdrawSuccess') }}</div>
 							<div class="stat-number">{{ statistics.withdrawOrderSuccessNum || 0 }}</div>
-							<div class="stat-desc">金额: {{ formatAmount(statistics.withdrawOrderSuccessAmount) }}</div>
+							<div class="stat-desc">{{ $t('dashboard.amount') }}: {{ formatAmount(statistics.withdrawOrderSuccessAmount) }}</div>
 						</div>
 					</div>
 				</el-card>
@@ -75,7 +75,7 @@
 							<el-icon :size="40"><TrendCharts /></el-icon>
 						</div>
 						<div class="rate-info">
-							<div class="rate-title">支付成功率</div>
+							<div class="rate-title">{{ $t('dashboard.paySuccessRate') }}</div>
 							<div class="rate-number">{{ formatRate(statistics.paySuccessRate) }}</div>
 						</div>
 						<div class="rate-progress">
@@ -90,6 +90,9 @@
 
 <script setup lang="ts" name="dashboard">
 import { ref, onMounted } from 'vue';
+import { useI18n } from 'vue-i18n';
+
+const { t } = useI18n();
 import { DocumentAdd, Wallet, Money, CircleCheck, TrendCharts } from '@element-plus/icons-vue';
 import { getIndexStatistics } from '/@/api/statistics/index';
 import { ElMessage } from 'element-plus';
@@ -129,10 +132,10 @@ const loadStatistics = async () => {
 		if (res.code === 0) {
 			statistics.value = res.data;
 		} else {
-			ElMessage.error(res.msg || '加载统计数据失败');
+			ElMessage.error(res.msg || t('dashboard.loadFailed'));
 		}
 	} catch (error) {
-		ElMessage.error('加载统计数据失败');
+		ElMessage.error(t('dashboard.loadFailed'));
 	} finally {
 		loading.value = false;
 	}

+ 5 - 5
src/views/login/component/control.vue

@@ -37,13 +37,14 @@
 import { useThemeConfig } from '/@/stores/themeConfig';
 import { useI18n } from 'vue-i18n';
 import { Local } from '/@/utils/storage';
+import { setLanguage } from '/@/locales/index';
 import other from '/@/utils/other';
 import { useDark } from '@vueuse/core';
 
 // 定义变量内容
 const storesThemeConfig = useThemeConfig();
 const { themeConfig } = storeToRefs(storesThemeConfig);
-const { locale } = useI18n();
+useI18n();
 
 // 语言切换状态
 const state = reactive({
@@ -59,7 +60,7 @@ const onLanguageChange = (lang: string) => {
 	Local.remove('themeConfig');
 	themeConfig.value.globalI18n = lang;
 	Local.set('themeConfig', themeConfig.value);
-	locale.value = lang;
+	setLanguage(lang); // 使用正确的语言切换函数
 	state.disabledI18n = lang;
 	other.useTitle();
 };
@@ -104,12 +105,11 @@ const initLanguage = () => {
 	if (Local.get('themeConfig')) {
 		state.disabledI18n = Local.get('themeConfig').globalI18n;
 		// 确保 i18n locale 与存储的语言保持一致
-
-		locale.value = state.disabledI18n;
+		setLanguage(state.disabledI18n);
 	} else {
 		// 如果没有存储的主题配置,设置默认语言
 		state.disabledI18n = 'zh-cn';
-		locale.value = 'zh-cn';
+		setLanguage('zh-cn');
 		// 保存默认配置
 		themeConfig.value.globalI18n = 'zh-cn';
 		Local.set('themeConfig', themeConfig.value);

+ 1 - 1
src/views/login/component/password.vue

@@ -43,7 +43,7 @@
 			<el-input
 				text
 				maxlength="6"
-				placeholder="谷歌验证码(若没有可以不填)"
+				:placeholder="$t('password.googleCaptchaPlaceholder')"
 				v-model="state.ruleForm.googleCaptcha"
 				clearable
 				autocomplete="off"

+ 6 - 1
src/views/login/index.vue

@@ -22,7 +22,7 @@
 				<!-- 右侧登录表单区域 -->
 				<div class="w-full px-5 py-16 md:w-[45%] md:px-12">
 					<div class="mb-16 text-center">
-						<h1 class="text-4xl font-bold text-gray-900 dark:text-white tracking-wide font-['Inter']">{{ getThemeConfig.globalTitle }}</h1>
+						<h1 class="text-4xl font-bold text-gray-900 dark:text-white tracking-wide font-['Inter']">{{ displayTitle }}</h1>
 						<!-- 租户选择 -->
 						<div class="mt-6" v-if="tenantEnable">
 							<tenant class="shadow-sm" />
@@ -110,6 +110,11 @@ const getThemeConfig = computed(() => {
 	return themeConfig.value;
 });
 
+// 显示标题(支持国际化)
+const displayTitle = computed(() => {
+	return t('app.title');
+});
+
 // 登录成功后的跳转处理事件
 const signInSuccess = async () => {
 	const isNoPower = await initBackEndControlRoutes();

+ 45 - 47
src/views/order/payOrder/detail.vue

@@ -1,91 +1,89 @@
 <template>
-	<el-dialog :close-on-click-modal="false" title="代收订单详情" draggable v-model="visible" width="900px">
+	<el-dialog :close-on-click-modal="false" :title="$t('order.payOrder.detail')" draggable v-model="visible" width="900px">
 		<el-descriptions :column="2" border v-loading="loading">
-			<el-descriptions-item label="订单ID">{{ orderData.id }}</el-descriptions-item>
-			<el-descriptions-item label="AppId">{{ orderData.appId }}</el-descriptions-item>
-			<el-descriptions-item label="商户订单号" :span="2">{{ orderData.mchOrderNo }}</el-descriptions-item>
-			<el-descriptions-item label="平台订单号" :span="2">{{ orderData.transactionId || '-' }}</el-descriptions-item>
-			<el-descriptions-item label="订单状态">
-				<el-tag v-if="orderData.orderStatus === 'CREATE_ORDER'" type="info">创建订单</el-tag>
-				<el-tag v-else-if="orderData.orderStatus === 'PAY_SUCCESS'" type="success">支付成功</el-tag>
-				<el-tag v-else-if="orderData.orderStatus === 'PAY_FAIL'" type="danger">支付失败</el-tag>
-				<el-tag v-else-if="orderData.orderStatus === 'CANCEL_ORDER'" type="warning">取消订单</el-tag>
-				<el-tag v-else-if="orderData.orderStatus === 'PAY_TIMEOUT'" type="info">支付超时</el-tag>
+			<el-descriptions-item :label="$t('order.payOrder.orderId')">{{ orderData.id }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.appId')">{{ orderData.appId }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.mchOrderNo')" :span="2">{{ orderData.mchOrderNo }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.transactionId')" :span="2">{{ orderData.transactionId || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.orderStatus')">
+				<el-tag v-if="orderData.orderStatus === 'CREATE_ORDER'" type="info">{{ $t('order.payOrder.createOrder') }}</el-tag>
+				<el-tag v-else-if="orderData.orderStatus === 'PAY_SUCCESS'" type="success">{{ $t('order.payOrder.paySuccess') }}</el-tag>
+				<el-tag v-else-if="orderData.orderStatus === 'PAY_FAIL'" type="danger">{{ $t('order.payOrder.payFail') }}</el-tag>
+				<el-tag v-else-if="orderData.orderStatus === 'CANCEL_ORDER'" type="warning">{{ $t('order.payOrder.cancelOrder') }}</el-tag>
+				<el-tag v-else-if="orderData.orderStatus === 'PAY_TIMEOUT'" type="info">{{ $t('order.payOrder.payTimeout') }}</el-tag>
 				<el-tag v-else>{{ orderData.orderStatus }}</el-tag>
 			</el-descriptions-item>
-			<el-descriptions-item label="币种">{{ orderData.currency }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.currency')">{{ orderData.currency }}</el-descriptions-item>
 
-			<el-descriptions-item label="订单金额">
+			<el-descriptions-item :label="$t('order.payOrder.orderAmount')">
 				<span style="color: #f56c6c; font-weight: bold; font-size: 16px">¥{{ orderData.amount ? orderData.amount.toFixed(2) : '0.00' }}</span>
 			</el-descriptions-item>
-			<el-descriptions-item label="实付金额">
-				<span v-if="orderData.noticeAmount" style="color: #67c23a; font-weight: bold; font-size: 16px"
-					>¥{{ orderData.noticeAmount.toFixed(2) }}</span
-				>
+			<el-descriptions-item :label="$t('order.payOrder.paidAmount')">
+				<span v-if="orderData.noticeAmount" style="color: #67c23a; font-weight: bold; font-size: 16px">¥{{ orderData.noticeAmount.toFixed(2) }}</span>
 				<span v-else>-</span>
 			</el-descriptions-item>
 
-			<el-descriptions-item label="支付通道ID">{{ orderData.paymentChannelId }}</el-descriptions-item>
-			<el-descriptions-item label="支付通道名称">{{ orderData.paymentChannelName || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.paymentChannelId')">{{ orderData.paymentChannelId }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.paymentChannelName')">{{ orderData.paymentChannelName || '-' }}</el-descriptions-item>
 
-			<el-descriptions-item label="商户ID">{{ orderData.merchantUserId }}</el-descriptions-item>
-			<el-descriptions-item label="代理商ID">{{ orderData.agentUserId }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.merchantId')">{{ orderData.merchantUserId }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.agentId')">{{ orderData.agentUserId }}</el-descriptions-item>
 
-			<el-descriptions-item label="商户手续费类型">
-				<el-tag v-if="orderData.mFeeType === 'PERCENTAGE'" type="info">百分比</el-tag>
-				<el-tag v-else-if="orderData.mFeeType === 'FIXED'" type="warning">固定</el-tag>
-				<el-tag v-else-if="orderData.mFeeType === 'MIXED'" type="success">百分比+固定</el-tag>
+			<el-descriptions-item :label="$t('order.payOrder.merchantFeeType')">
+				<el-tag v-if="orderData.mFeeType === 'PERCENTAGE'" type="info">{{ $t('order.payOrder.feeTypePercentage') }}</el-tag>
+				<el-tag v-else-if="orderData.mFeeType === 'FIXED'" type="warning">{{ $t('order.payOrder.feeTypeFixed') }}</el-tag>
+				<el-tag v-else-if="orderData.mFeeType === 'MIXED'" type="success">{{ $t('order.payOrder.feeTypeMixed') }}</el-tag>
 				<span v-else>-</span>
 			</el-descriptions-item>
-			<el-descriptions-item label="商户手续费">
+			<el-descriptions-item :label="$t('order.payOrder.merchantFee')">
 				{{ orderData.mFee ? `¥${orderData.mFee.toFixed(2)}` : '-' }}
 			</el-descriptions-item>
 
-			<el-descriptions-item label="商户手续费比例">
+			<el-descriptions-item :label="$t('order.payOrder.merchantFeeRate')">
 				{{ orderData.mFeeRate ? `${orderData.mFeeRate}%` : '-' }}
 			</el-descriptions-item>
-			<el-descriptions-item label="商户手续费固定金额">
+			<el-descriptions-item :label="$t('order.payOrder.merchantFeeFixed')">
 				{{ orderData.mFeeEvery ? `¥${orderData.mFeeEvery.toFixed(2)}` : '-' }}
 			</el-descriptions-item>
 
-			<el-descriptions-item label="代理商手续费类型">
-				<el-tag v-if="orderData.aFeeType === 'PERCENTAGE'" type="info">百分比</el-tag>
-				<el-tag v-else-if="orderData.aFeeType === 'FIXED'" type="warning">固定</el-tag>
-				<el-tag v-else-if="orderData.aFeeType === 'MIXED'" type="success">百分比+固定</el-tag>
+			<el-descriptions-item :label="$t('order.payOrder.agentFeeType')">
+				<el-tag v-if="orderData.aFeeType === 'PERCENTAGE'" type="info">{{ $t('order.payOrder.feeTypePercentage') }}</el-tag>
+				<el-tag v-else-if="orderData.aFeeType === 'FIXED'" type="warning">{{ $t('order.payOrder.feeTypeFixed') }}</el-tag>
+				<el-tag v-else-if="orderData.aFeeType === 'MIXED'" type="success">{{ $t('order.payOrder.feeTypeMixed') }}</el-tag>
 				<span v-else>-</span>
 			</el-descriptions-item>
-			<el-descriptions-item label="代理商手续费">
+			<el-descriptions-item :label="$t('order.payOrder.agentFee')">
 				{{ orderData.aFee ? `¥${orderData.aFee.toFixed(2)}` : '-' }}
 			</el-descriptions-item>
 
-			<el-descriptions-item label="代理商手续费比例">
+			<el-descriptions-item :label="$t('order.payOrder.agentFeeRate')">
 				{{ orderData.aFeeRate ? `${orderData.aFeeRate}%` : '-' }}
 			</el-descriptions-item>
-			<el-descriptions-item label="代理商手续费固定金额">
+			<el-descriptions-item :label="$t('order.payOrder.agentFeeFixed')">
 				{{ orderData.aFeeEvery ? `¥${orderData.aFeeEvery.toFixed(2)}` : '-' }}
 			</el-descriptions-item>
 
-			<el-descriptions-item label="客户端IP">{{ orderData.clientIp || '-' }}</el-descriptions-item>
-			<el-descriptions-item label="设备">{{ orderData.device || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.clientIp')">{{ orderData.clientIp || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.device')">{{ orderData.device || '-' }}</el-descriptions-item>
 
-			<el-descriptions-item label="主题" :span="2">{{ orderData.subject || '-' }}</el-descriptions-item>
-			<el-descriptions-item label="内容" :span="2">{{ orderData.body || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.subject')" :span="2">{{ orderData.subject || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.body')" :span="2">{{ orderData.body || '-' }}</el-descriptions-item>
 
-			<el-descriptions-item label="前端跳转URL" :span="2">{{ orderData.returnUrl || '-' }}</el-descriptions-item>
-			<el-descriptions-item label="后台回调URL" :span="2">{{ orderData.notifyUrl || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.returnUrl')" :span="2">{{ orderData.returnUrl || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.notifyUrl')" :span="2">{{ orderData.notifyUrl || '-' }}</el-descriptions-item>
 
-			<el-descriptions-item label="扩展参数" :span="2">{{ orderData.extra || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.extraParams')" :span="2">{{ orderData.extra || '-' }}</el-descriptions-item>
 
-			<el-descriptions-item label="请求时间">{{ orderData.reqTime || '-' }}</el-descriptions-item>
-			<el-descriptions-item label="支付完成时间">{{ orderData.noticeDatetime || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.reqTime')">{{ orderData.reqTime || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.payCompleteTime')">{{ orderData.noticeDatetime || '-' }}</el-descriptions-item>
 
-			<el-descriptions-item label="创建时间">{{ orderData.createTime }}</el-descriptions-item>
-			<el-descriptions-item label="更新时间">{{ orderData.updateTime }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.createTime')">{{ orderData.createTime }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.updateTime')">{{ orderData.updateTime }}</el-descriptions-item>
 		</el-descriptions>
 
 		<template #footer>
 			<span class="dialog-footer">
-				<el-button @click="visible = false">关闭</el-button>
+				<el-button @click="visible = false">{{ $t('order.payOrder.close') }}</el-button>
 			</span>
 		</template>
 	</el-dialog>

+ 62 - 36
src/views/order/payOrder/index.vue

@@ -3,27 +3,47 @@
 		<div class="layout-padding-auto layout-padding-view">
 			<el-row class="ml10" v-show="showSearch">
 				<el-form :inline="true" :model="state.queryForm" @keyup.enter="getDataList" ref="queryRef">
-					<el-form-item label="商户订单号" prop="mchOrderNo">
-						<el-input placeholder="请输入商户订单号" style="max-width: 180px" v-model="state.queryForm.mchOrderNo" clearable />
+					<el-form-item :label="$t('order.payOrder.mchOrderNo')" prop="mchOrderNo">
+						<el-input
+							:placeholder="$t('order.payOrder.mchOrderNoPlaceholder')"
+							style="max-width: 180px"
+							v-model="state.queryForm.mchOrderNo"
+							clearable
+						/>
 					</el-form-item>
-					<el-form-item label="平台订单号" prop="transactionId">
-						<el-input placeholder="请输入平台订单号" style="max-width: 180px" v-model="state.queryForm.transactionId" clearable />
+					<el-form-item :label="$t('order.payOrder.transactionId')" prop="transactionId">
+						<el-input
+							:placeholder="$t('order.payOrder.transactionIdPlaceholder')"
+							style="max-width: 180px"
+							v-model="state.queryForm.transactionId"
+							clearable
+						/>
 					</el-form-item>
-					<el-form-item label="商户名称" prop="merchantName">
-						<el-input placeholder="请输入商户名称" style="max-width: 180px" v-model="state.queryForm.merchantName" clearable />
+					<el-form-item :label="$t('order.payOrder.merchantName')" prop="merchantName">
+						<el-input
+							:placeholder="$t('order.payOrder.merchantNamePlaceholder')"
+							style="max-width: 180px"
+							v-model="state.queryForm.merchantName"
+							clearable
+						/>
 					</el-form-item>
-					<el-form-item label="订单状态" prop="orderStatus">
-						<el-select v-model="state.queryForm.orderStatus" placeholder="请选择订单状态" style="max-width: 180px" clearable>
-							<el-option label="创建订单" value="CREATE_ORDER" />
-							<el-option label="支付成功" value="PAY_SUCCESS" />
-							<el-option label="支付失败" value="PAY_FAIL" />
-							<el-option label="取消订单" value="CANCEL_ORDER" />
-							<el-option label="支付超时" value="PAY_TIMEOUT" />
+					<el-form-item :label="$t('order.payOrder.orderStatus')" prop="orderStatus">
+						<el-select
+							v-model="state.queryForm.orderStatus"
+							:placeholder="$t('order.payOrder.orderStatusPlaceholder')"
+							style="max-width: 180px"
+							clearable
+						>
+							<el-option :label="$t('order.payOrder.createOrder')" value="CREATE_ORDER" />
+							<el-option :label="$t('order.payOrder.paySuccess')" value="PAY_SUCCESS" />
+							<el-option :label="$t('order.payOrder.payFail')" value="PAY_FAIL" />
+							<el-option :label="$t('order.payOrder.cancelOrder')" value="CANCEL_ORDER" />
+							<el-option :label="$t('order.payOrder.payTimeout')" value="PAY_TIMEOUT" />
 						</el-select>
 					</el-form-item>
 					<el-form-item>
-						<el-button @click="getDataList" icon="search" type="primary">查询</el-button>
-						<el-button @click="resetQuery" icon="Refresh">重置</el-button>
+						<el-button @click="getDataList" icon="search" type="primary">{{ $t('common.queryBtn') }}</el-button>
+						<el-button @click="resetQuery" icon="Refresh">{{ $t('common.resetBtn') }}</el-button>
 					</el-form-item>
 				</el-form>
 			</el-row>
@@ -43,7 +63,7 @@
 				<el-col :span="6">
 					<el-card shadow="hover">
 						<div class="statistic-item">
-							<div class="statistic-label">提交订单数</div>
+							<div class="statistic-label">{{ $t('order.payOrder.submitOrders') }}</div>
 							<div class="statistic-value">{{ statistics.numberOrders || 0 }}</div>
 						</div>
 					</el-card>
@@ -51,7 +71,7 @@
 				<el-col :span="6">
 					<el-card shadow="hover">
 						<div class="statistic-item">
-							<div class="statistic-label">订单总金额</div>
+							<div class="statistic-label">{{ $t('order.payOrder.totalOrderAmount') }}</div>
 							<div class="statistic-value">¥{{ (statistics.totalOrderAmount || 0).toFixed(2) }}</div>
 						</div>
 					</el-card>
@@ -59,7 +79,7 @@
 				<el-col :span="6">
 					<el-card shadow="hover">
 						<div class="statistic-item">
-							<div class="statistic-label">已付订单数</div>
+							<div class="statistic-label">{{ $t('order.payOrder.paidOrders') }}</div>
 							<div class="statistic-value success">{{ statistics.paidOrders || 0 }}</div>
 						</div>
 					</el-card>
@@ -67,7 +87,7 @@
 				<el-col :span="6">
 					<el-card shadow="hover">
 						<div class="statistic-item">
-							<div class="statistic-label">已付总金额</div>
+							<div class="statistic-label">{{ $t('order.payOrder.paidTotalAmount') }}</div>
 							<div class="statistic-value success">¥{{ (statistics.totalAmountPaid || 0).toFixed(2) }}</div>
 						</div>
 					</el-card>
@@ -85,53 +105,55 @@
 				:header-cell-style="tableStyle.headerCellStyle"
 			>
 				<el-table-column align="center" type="selection" width="40" />
-				<el-table-column label="商户订单号" prop="mchOrderNo" show-overflow-tooltip>
+				<el-table-column :label="$t('order.payOrder.mchOrderNo')" prop="mchOrderNo" show-overflow-tooltip>
 					<template #default="scope">
 						{{ scope.row.mchOrderNo || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="平台订单号" prop="transactionId" show-overflow-tooltip>
+				<el-table-column :label="$t('order.payOrder.transactionId')" prop="transactionId" show-overflow-tooltip>
 					<template #default="scope">
 						{{ scope.row.transactionId || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="商户名称" prop="merchantName" show-overflow-tooltip>
+				<el-table-column :label="$t('order.payOrder.merchantName')" prop="merchantName" show-overflow-tooltip>
 					<template #default="scope">
 						{{ scope.row.merchantName || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="通道名称" prop="paymentChannelName" show-overflow-tooltip>
+				<el-table-column :label="$t('order.payOrder.channelName')" prop="paymentChannelName" show-overflow-tooltip>
 					<template #default="scope">
 						{{ scope.row.paymentChannelName || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="提交金额" prop="amount" show-overflow-tooltip>
+				<el-table-column :label="$t('order.payOrder.submitAmount')" prop="amount" show-overflow-tooltip>
 					<template #default="scope">
 						<!-- 橙色 -->
 						<span style="color: #f56c6c; font-weight: bold">¥{{ scope.row.amount ? scope.row.amount.toFixed(2) : '0.00' }}</span>
 					</template>
 				</el-table-column>
-				<el-table-column label="实际金额" prop="noticeAmount" show-overflow-tooltip>
+				<el-table-column :label="$t('order.payOrder.actualAmount')" prop="noticeAmount" show-overflow-tooltip>
 					<template #default="scope">
 						<span style="color: #f56c6c; font-weight: bold">¥{{ scope.row.noticeAmount ? scope.row.noticeAmount.toFixed(2) : '0.00' }}</span>
 					</template>
 				</el-table-column>
-				<el-table-column label="订单状态" prop="orderStatus" show-overflow-tooltip>
+				<el-table-column :label="$t('order.payOrder.orderStatus')" prop="orderStatus" show-overflow-tooltip>
 					<template #default="scope">
 						<el-tag :type="orderStatusMap[scope.row.orderStatus]?.type || 'info'" size="small">
 							{{ orderStatusMap[scope.row.orderStatus]?.label || scope.row.orderStatus }}
 						</el-tag>
 					</template>
 				</el-table-column>
-				<el-table-column label="创建时间" prop="createTime" show-overflow-tooltip width="180">
+				<el-table-column :label="$t('order.payOrder.createTime')" prop="createTime" show-overflow-tooltip width="180">
 					<template #default="scope">
 						{{ scope.row.createTime || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="操作">
+				<el-table-column :label="$t('order.payOrder.operation')">
 					<template #default="scope">
 						<!-- <el-button icon="View" @click="handleView(scope.row)" text type="primary" size="small">查看</el-button> -->
-						<el-button icon="Document" @click="handleNotifyLog(scope.row)" text type="warning" size="small">回调日志</el-button>
+						<el-button icon="Document" @click="handleNotifyLog(scope.row)" text type="warning" size="small">{{
+							$t('order.payOrder.notifyLog')
+						}}</el-button>
 					</template>
 				</el-table-column>
 			</el-table>
@@ -151,14 +173,18 @@ import { useMessage } from '/@/hooks/message';
 // 引入组件
 const NotifyLogDialog = defineAsyncComponent(() => import('./notifyLog.vue'));
 
+import { useI18n } from 'vue-i18n';
+
+const { t } = useI18n();
+
 // 订单状态映射
-const orderStatusMap: Record<string, { label: string; type: any }> = {
-	CREATE_ORDER: { label: '创建订单', type: 'info' },
-	PAY_SUCCESS: { label: '支付成功', type: 'success' },
-	PAY_FAIL: { label: '支付失败', type: 'danger' },
-	CANCEL_ORDER: { label: '取消订单', type: 'warning' },
-	PAY_TIMEOUT: { label: '支付超时', type: 'info' },
-};
+const orderStatusMap = computed(() => ({
+	CREATE_ORDER: { label: t('order.payOrder.createOrder'), type: 'info' },
+	PAY_SUCCESS: { label: t('order.payOrder.paySuccess'), type: 'success' },
+	PAY_FAIL: { label: t('order.payOrder.payFail'), type: 'danger' },
+	CANCEL_ORDER: { label: t('order.payOrder.cancelOrder'), type: 'warning' },
+	PAY_TIMEOUT: { label: t('order.payOrder.payTimeout'), type: 'info' },
+}));
 
 // 定义变量内容
 const notifyLogDialogRef = ref();

+ 28 - 24
src/views/order/payOrder/notifyLog.vue

@@ -1,32 +1,32 @@
 <template>
-	<el-dialog :close-on-click-modal="false" title="回调日志" draggable v-model="visible" width="1000px">
+	<el-dialog :close-on-click-modal="false" :title="$t('order.notifyLog.title')" draggable v-model="visible" width="1000px">
 		<div v-loading="loading">
 			<!-- 回调信息概览 -->
 			<el-descriptions :column="2" border class="mb20" v-if="notifyData.id">
-				<el-descriptions-item label="订单号">{{ notifyData.orderId || '-' }}</el-descriptions-item>
-				<el-descriptions-item label="通知状态">
+				<el-descriptions-item :label="$t('order.notifyLog.orderNo')">{{ notifyData.orderId || '-' }}</el-descriptions-item>
+				<el-descriptions-item :label="$t('order.notifyLog.notifyStatus')">
 					<el-tag :type="getStatusType(notifyData.status)" size="default">
 						{{ getStatusLabel(notifyData.status) }}
 					</el-tag>
 				</el-descriptions-item>
-				<el-descriptions-item label="当前通知次数">
+				<el-descriptions-item :label="$t('order.notifyLog.currentNotifyTimes')">
 					<el-tag type="info">{{ notifyData.notifyTimes || 0 }}</el-tag>
 				</el-descriptions-item>
-				<el-descriptions-item label="最大通知次数">
+				<el-descriptions-item :label="$t('order.notifyLog.maxNotifyTimes')">
 					<el-tag type="info">{{ notifyData.maxNotifyTimes || 0 }}</el-tag>
 				</el-descriptions-item>
-				<el-descriptions-item label="最后执行时间" :span="2">{{ notifyData.lastExecuteTime || '-' }}</el-descriptions-item>
-				<el-descriptions-item label="下次通知时间" :span="2">{{ notifyData.nextNotifyTime || '-' }}</el-descriptions-item>
-				<el-descriptions-item label="通知地址" :span="2">
+				<el-descriptions-item :label="$t('order.notifyLog.lastExecuteTime')" :span="2">{{ notifyData.lastExecuteTime || '-' }}</el-descriptions-item>
+				<el-descriptions-item :label="$t('order.notifyLog.nextNotifyTime')" :span="2">{{ notifyData.nextNotifyTime || '-' }}</el-descriptions-item>
+				<el-descriptions-item :label="$t('order.notifyLog.notifyUrl')" :span="2">
 					<el-text class="notify-url" truncated>{{ notifyData.notifyUrl || '-' }}</el-text>
 				</el-descriptions-item>
-				<el-descriptions-item label="失败原因" :span="2">
+				<el-descriptions-item :label="$t('order.notifyLog.failReason')" :span="2">
 					<span style="color: #f56c6c">{{ notifyData.errorMsg || '-' }}</span>
 				</el-descriptions-item>
 			</el-descriptions>
 
 			<!-- 通知日志列表 -->
-			<el-divider content-position="left">通知日志</el-divider>
+			<el-divider content-position="left">{{ $t('order.notifyLog.notifyLogList') }}</el-divider>
 			<el-timeline v-if="notifyData.payNotifyLogs && notifyData.payNotifyLogs.length > 0">
 				<el-timeline-item
 					v-for="(log, index) in notifyData.payNotifyLogs"
@@ -38,25 +38,25 @@
 					<el-card shadow="hover">
 						<div class="log-item">
 							<div class="log-header">
-								<span class="log-title">第 {{ log.notifyTimes }} 次通知</span>
+								<span class="log-title">{{ $t('order.notifyLog.notifyTimes', { n: log.notifyTimes }) }}</span>
 								<el-tag :type="getStatusType(log.status)" size="small">
 									{{ getStatusLabel(log.status) }}
 								</el-tag>
 							</div>
 							<div class="log-content">
-								<div class="log-label">响应结果:</div>
-								<pre class="log-response">{{ log.response || '无响应' }}</pre>
+								<div class="log-label">{{ $t('order.notifyLog.responseResult') }}</div>
+								<pre class="log-response">{{ log.response || $t('order.notifyLog.noResponse') }}</pre>
 							</div>
 						</div>
 					</el-card>
 				</el-timeline-item>
 			</el-timeline>
-			<el-empty v-else description="暂无通知日志" />
+			<el-empty v-else :description="$t('order.notifyLog.noNotifyLog')" />
 		</div>
 
 		<template #footer>
 			<span class="dialog-footer">
-				<el-button @click="visible = false">关闭</el-button>
+				<el-button @click="visible = false">{{ $t('order.payOrder.close') }}</el-button>
 			</span>
 		</template>
 	</el-dialog>
@@ -66,13 +66,17 @@
 import { fetchPayNotifyLog } from '/@/api/order';
 import { useMessage } from '/@/hooks/message';
 
+import { useI18n } from 'vue-i18n';
+
+const { t } = useI18n();
+
 // 通知状态映射
-const statusMap: Record<number, { label: string; type: any }> = {
-	0: { label: '待通知', type: 'info' },
-	10: { label: '通知成功', type: 'success' },
-	20: { label: '通知失败', type: 'danger' },
-	30: { label: '通知中', type: 'warning' },
-};
+const statusMap = computed(() => ({
+	0: { label: t('order.notifyLog.pending'), type: 'info' },
+	10: { label: t('order.notifyLog.success'), type: 'success' },
+	20: { label: t('order.notifyLog.fail'), type: 'danger' },
+	30: { label: t('order.notifyLog.processing'), type: 'warning' },
+}));
 
 // 定义变量
 const visible = ref(false);
@@ -81,12 +85,12 @@ const notifyData = reactive<any>({});
 
 // 获取状态标签类型
 const getStatusType = (status: number) => {
-	return statusMap[status]?.type || 'info';
+	return (statusMap.value as any)[status]?.type || 'info';
 };
 
 // 获取状态标签文本
 const getStatusLabel = (status: number) => {
-	return statusMap[status]?.label || `未知状态(${status})`;
+	return (statusMap.value as any)[status]?.label || status;
 };
 
 // 打开弹窗
@@ -101,7 +105,7 @@ const openDialog = async (appId: string, orderId: string) => {
 		const res = await fetchPayNotifyLog(appId, orderId);
 		Object.assign(notifyData, res.data);
 	} catch (err: any) {
-		useMessage().error(err.msg || '获取回调日志失败');
+		useMessage().error(err.msg || t('order.notifyLog.fetchFailed'));
 	} finally {
 		loading.value = false;
 	}

+ 46 - 48
src/views/order/withdrawOrder/detail.vue

@@ -1,95 +1,93 @@
 <template>
-	<el-dialog :close-on-click-modal="false" title="代付订单详情" draggable v-model="visible" width="900px">
+	<el-dialog :close-on-click-modal="false" :title="$t('order.withdrawOrder.detail')" draggable v-model="visible" width="900px">
 		<el-descriptions :column="2" border v-loading="loading">
-			<el-descriptions-item label="订单ID">{{ orderData.id }}</el-descriptions-item>
-			<el-descriptions-item label="AppId">{{ orderData.appId }}</el-descriptions-item>
-			<el-descriptions-item label="商户订单号" :span="2">{{ orderData.mchOrderNo }}</el-descriptions-item>
-			<el-descriptions-item label="平台订单号" :span="2">{{ orderData.transactionId || '-' }}</el-descriptions-item>
-			<el-descriptions-item label="订单状态">
-				<el-tag v-if="orderData.orderStatus === 'CREATE_ORDER'" type="info">创建订单</el-tag>
-				<el-tag v-else-if="orderData.orderStatus === 'WITHDRAW_SUCCESS'" type="success">提现成功</el-tag>
-				<el-tag v-else-if="orderData.orderStatus === 'WITHDRAW_FAIL'" type="danger">提现失败</el-tag>
+			<el-descriptions-item :label="$t('order.payOrder.orderId')">{{ orderData.id }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.appId')">{{ orderData.appId }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.mchOrderNo')" :span="2">{{ orderData.mchOrderNo }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.transactionId')" :span="2">{{ orderData.transactionId || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.orderStatus')">
+				<el-tag v-if="orderData.orderStatus === 'CREATE_ORDER'" type="info">{{ $t('order.payOrder.createOrder') }}</el-tag>
+				<el-tag v-else-if="orderData.orderStatus === 'WITHDRAW_SUCCESS'" type="success">{{ $t('order.withdrawOrder.withdrawSuccess') }}</el-tag>
+				<el-tag v-else-if="orderData.orderStatus === 'WITHDRAW_FAIL'" type="danger">{{ $t('order.withdrawOrder.withdrawFail') }}</el-tag>
 				<el-tag v-else>{{ orderData.orderStatus }}</el-tag>
 			</el-descriptions-item>
-			<el-descriptions-item label="币种">{{ orderData.currencyType }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.withdrawOrder.currencyType')">{{ orderData.currencyType }}</el-descriptions-item>
 
-			<el-descriptions-item label="订单金额">
+			<el-descriptions-item :label="$t('order.payOrder.orderAmount')">
 				<span style="color: #f56c6c; font-weight: bold; font-size: 16px">¥{{ orderData.amount ? orderData.amount.toFixed(2) : '0.00' }}</span>
 			</el-descriptions-item>
-			<el-descriptions-item label="实付金额">
-				<span v-if="orderData.noticeAmount" style="color: #67c23a; font-weight: bold; font-size: 16px"
-					>¥{{ orderData.noticeAmount.toFixed(2) }}</span
-				>
+			<el-descriptions-item :label="$t('order.payOrder.paidAmount')">
+				<span v-if="orderData.noticeAmount" style="color: #67c23a; font-weight: bold; font-size: 16px">¥{{ orderData.noticeAmount.toFixed(2) }}</span>
 				<span v-else>-</span>
 			</el-descriptions-item>
 
-			<el-descriptions-item label="支付通道ID">{{ orderData.paymentChannelId }}</el-descriptions-item>
-			<el-descriptions-item label="通道类型ID">{{ orderData.paymentTypeId }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.paymentChannelId')">{{ orderData.paymentChannelId }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.withdrawOrder.paymentTypeId')">{{ orderData.paymentTypeId }}</el-descriptions-item>
 
-			<el-descriptions-item label="商户ID">{{ orderData.merchantUserId }}</el-descriptions-item>
-			<el-descriptions-item label="费率状态">
-				<el-tag v-if="orderData.feeStatus" type="success">成功</el-tag>
-				<el-tag v-else type="danger">失败</el-tag>
+			<el-descriptions-item :label="$t('order.payOrder.merchantId')">{{ orderData.merchantUserId }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.withdrawOrder.feeStatus')">
+				<el-tag v-if="orderData.feeStatus" type="success">{{ $t('order.withdrawOrder.feeStatusSuccess') }}</el-tag>
+				<el-tag v-else type="danger">{{ $t('order.withdrawOrder.feeStatusFail') }}</el-tag>
 			</el-descriptions-item>
 
-			<el-descriptions-item label="商户手续费类型">
-				<el-tag v-if="orderData.mFeeType === 'PERCENTAGE'" type="info">百分比</el-tag>
-				<el-tag v-else-if="orderData.mFeeType === 'FIXED'" type="warning">固定</el-tag>
-				<el-tag v-else-if="orderData.mFeeType === 'MIXED'" type="success">百分比+固定</el-tag>
+			<el-descriptions-item :label="$t('order.payOrder.merchantFeeType')">
+				<el-tag v-if="orderData.mFeeType === 'PERCENTAGE'" type="info">{{ $t('order.payOrder.feeTypePercentage') }}</el-tag>
+				<el-tag v-else-if="orderData.mFeeType === 'FIXED'" type="warning">{{ $t('order.payOrder.feeTypeFixed') }}</el-tag>
+				<el-tag v-else-if="orderData.mFeeType === 'MIXED'" type="success">{{ $t('order.payOrder.feeTypeMixed') }}</el-tag>
 				<span v-else>-</span>
 			</el-descriptions-item>
-			<el-descriptions-item label="商户手续费">
+			<el-descriptions-item :label="$t('order.payOrder.merchantFee')">
 				{{ orderData.mFee ? `¥${orderData.mFee.toFixed(2)}` : '-' }}
 			</el-descriptions-item>
 
-			<el-descriptions-item label="商户手续费比例">
+			<el-descriptions-item :label="$t('order.payOrder.merchantFeeRate')">
 				{{ orderData.mFeeRate ? `${orderData.mFeeRate}%` : '-' }}
 			</el-descriptions-item>
-			<el-descriptions-item label="商户手续费固定金额">
+			<el-descriptions-item :label="$t('order.payOrder.merchantFeeFixed')">
 				{{ orderData.mFeeEvery ? `¥${orderData.mFeeEvery.toFixed(2)}` : '-' }}
 			</el-descriptions-item>
 
-			<el-descriptions-item label="代理商手续费类型">
-				<el-tag v-if="orderData.aFeeType === 'PERCENTAGE'" type="info">百分比</el-tag>
-				<el-tag v-else-if="orderData.aFeeType === 'FIXED'" type="warning">固定</el-tag>
-				<el-tag v-else-if="orderData.aFeeType === 'MIXED'" type="success">百分比+固定</el-tag>
+			<el-descriptions-item :label="$t('order.payOrder.agentFeeType')">
+				<el-tag v-if="orderData.aFeeType === 'PERCENTAGE'" type="info">{{ $t('order.payOrder.feeTypePercentage') }}</el-tag>
+				<el-tag v-else-if="orderData.aFeeType === 'FIXED'" type="warning">{{ $t('order.payOrder.feeTypeFixed') }}</el-tag>
+				<el-tag v-else-if="orderData.aFeeType === 'MIXED'" type="success">{{ $t('order.payOrder.feeTypeMixed') }}</el-tag>
 				<span v-else>-</span>
 			</el-descriptions-item>
-			<el-descriptions-item label="代理商手续费">
+			<el-descriptions-item :label="$t('order.payOrder.agentFee')">
 				{{ orderData.aFee ? `¥${orderData.aFee.toFixed(2)}` : '-' }}
 			</el-descriptions-item>
 
-			<el-descriptions-item label="代理商手续费比例">
+			<el-descriptions-item :label="$t('order.payOrder.agentFeeRate')">
 				{{ orderData.aFeeRate ? `${orderData.aFeeRate}%` : '-' }}
 			</el-descriptions-item>
-			<el-descriptions-item label="代理商手续费固定金额">
+			<el-descriptions-item :label="$t('order.payOrder.agentFeeFixed')">
 				{{ orderData.aFeeEvery ? `¥${orderData.aFeeEvery.toFixed(2)}` : '-' }}
 			</el-descriptions-item>
 
-			<el-descriptions-item label="收款人姓名">{{ orderData.payUsername || '-' }}</el-descriptions-item>
-			<el-descriptions-item label="收款人电话">{{ orderData.payMobile || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.withdrawOrder.payeeName')">{{ orderData.payUsername || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.withdrawOrder.payeePhone')">{{ orderData.payMobile || '-' }}</el-descriptions-item>
 
-			<el-descriptions-item label="银行账号" :span="2">{{ orderData.payBankNumber || '-' }}</el-descriptions-item>
-			<el-descriptions-item label="银行名称" :span="2">{{ orderData.payBankName || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.withdrawOrder.bankAccount')" :span="2">{{ orderData.payBankNumber || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.withdrawOrder.bankName')" :span="2">{{ orderData.payBankName || '-' }}</el-descriptions-item>
 
-			<el-descriptions-item label="收款人邮箱" :span="2">{{ orderData.payEmail || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.withdrawOrder.payeeEmail')" :span="2">{{ orderData.payEmail || '-' }}</el-descriptions-item>
 
-			<el-descriptions-item label="主题" :span="2">{{ orderData.subject || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.subject')" :span="2">{{ orderData.subject || '-' }}</el-descriptions-item>
 
-			<el-descriptions-item label="后台回调URL" :span="2">{{ orderData.notifyUrl || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.notifyUrl')" :span="2">{{ orderData.notifyUrl || '-' }}</el-descriptions-item>
 
-			<el-descriptions-item label="扩展参数" :span="2">{{ orderData.payAttach || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.extraParams')" :span="2">{{ orderData.payAttach || '-' }}</el-descriptions-item>
 
-			<el-descriptions-item label="请求时间">{{ orderData.reqTime || '-' }}</el-descriptions-item>
-			<el-descriptions-item label="完成时间">{{ orderData.noticeDatetime || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.reqTime')">{{ orderData.reqTime || '-' }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.withdrawOrder.completeTime')">{{ orderData.noticeDatetime || '-' }}</el-descriptions-item>
 
-			<el-descriptions-item label="创建时间">{{ orderData.createTime }}</el-descriptions-item>
-			<el-descriptions-item label="更新时间">{{ orderData.updateTime }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.createTime')">{{ orderData.createTime }}</el-descriptions-item>
+			<el-descriptions-item :label="$t('order.payOrder.updateTime')">{{ orderData.updateTime }}</el-descriptions-item>
 		</el-descriptions>
 
 		<template #footer>
 			<span class="dialog-footer">
-				<el-button @click="visible = false">关闭</el-button>
+				<el-button @click="visible = false">{{ $t('order.payOrder.close') }}</el-button>
 			</span>
 		</template>
 	</el-dialog>

+ 54 - 28
src/views/order/withdrawOrder/index.vue

@@ -3,25 +3,45 @@
 		<div class="layout-padding-auto layout-padding-view">
 			<el-row class="ml10" v-show="showSearch">
 				<el-form :inline="true" :model="state.queryForm" @keyup.enter="getDataList" ref="queryRef">
-					<el-form-item label="商户订单号" prop="mchOrderNo">
-						<el-input placeholder="请输入商户订单号" style="max-width: 180px" v-model="state.queryForm.mchOrderNo" clearable />
+					<el-form-item :label="$t('order.payOrder.mchOrderNo')" prop="mchOrderNo">
+						<el-input
+							:placeholder="$t('order.payOrder.mchOrderNoPlaceholder')"
+							style="max-width: 180px"
+							v-model="state.queryForm.mchOrderNo"
+							clearable
+						/>
 					</el-form-item>
-					<el-form-item label="平台订单号" prop="transactionId">
-						<el-input placeholder="请输入平台订单号" style="max-width: 180px" v-model="state.queryForm.transactionId" clearable />
+					<el-form-item :label="$t('order.payOrder.transactionId')" prop="transactionId">
+						<el-input
+							:placeholder="$t('order.payOrder.transactionIdPlaceholder')"
+							style="max-width: 180px"
+							v-model="state.queryForm.transactionId"
+							clearable
+						/>
 					</el-form-item>
-					<el-form-item label="商户名称" prop="merchantName">
-						<el-input placeholder="请输入商户名称" style="max-width: 180px" v-model="state.queryForm.merchantName" clearable />
+					<el-form-item :label="$t('order.payOrder.merchantName')" prop="merchantName">
+						<el-input
+							:placeholder="$t('order.payOrder.merchantNamePlaceholder')"
+							style="max-width: 180px"
+							v-model="state.queryForm.merchantName"
+							clearable
+						/>
 					</el-form-item>
-					<el-form-item label="订单状态" prop="orderStatus">
-						<el-select v-model="state.queryForm.orderStatus" placeholder="请选择订单状态" style="max-width: 180px" clearable>
-							<el-option label="创建订单" value="CREATE_ORDER" />
-							<el-option label="提现成功" value="WITHDRAW_SUCCESS" />
-							<el-option label="提现失败" value="WITHDRAW_FAIL" />
+					<el-form-item :label="$t('order.payOrder.orderStatus')" prop="orderStatus">
+						<el-select
+							v-model="state.queryForm.orderStatus"
+							:placeholder="$t('order.payOrder.orderStatusPlaceholder')"
+							style="max-width: 180px"
+							clearable
+						>
+							<el-option :label="$t('order.payOrder.createOrder')" value="CREATE_ORDER" />
+							<el-option :label="$t('order.withdrawOrder.withdrawSuccess')" value="WITHDRAW_SUCCESS" />
+							<el-option :label="$t('order.withdrawOrder.withdrawFail')" value="WITHDRAW_FAIL" />
 						</el-select>
 					</el-form-item>
 					<el-form-item>
-						<el-button @click="getDataList" icon="search" type="primary">查询</el-button>
-						<el-button @click="resetQuery" icon="Refresh">重置</el-button>
+						<el-button @click="getDataList" icon="search" type="primary">{{ $t('common.queryBtn') }}</el-button>
+						<el-button @click="resetQuery" icon="Refresh">{{ $t('common.resetBtn') }}</el-button>
 					</el-form-item>
 				</el-form>
 			</el-row>
@@ -47,53 +67,55 @@
 				:header-cell-style="tableStyle.headerCellStyle"
 			>
 				<el-table-column align="center" type="selection" width="40" />
-				<el-table-column label="商户订单号" prop="mchOrderNo" show-overflow-tooltip>
+				<el-table-column :label="$t('order.payOrder.mchOrderNo')" prop="mchOrderNo" show-overflow-tooltip>
 					<template #default="scope">
 						{{ scope.row.mchOrderNo || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="平台订单号" prop="transactionId" show-overflow-tooltip>
+				<el-table-column :label="$t('order.payOrder.transactionId')" prop="transactionId" show-overflow-tooltip>
 					<template #default="scope">
 						{{ scope.row.transactionId || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="商户名称" prop="merchantName" show-overflow-tooltip>
+				<el-table-column :label="$t('order.payOrder.merchantName')" prop="merchantName" show-overflow-tooltip>
 					<template #default="scope">
 						{{ scope.row.merchantName || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="通道名称" prop="paymentChannelName" show-overflow-tooltip>
+				<el-table-column :label="$t('order.payOrder.channelName')" prop="paymentChannelName" show-overflow-tooltip>
 					<template #default="scope">
 						{{ scope.row.paymentChannelName || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="提交金额" prop="amount" show-overflow-tooltip>
+				<el-table-column :label="$t('order.payOrder.submitAmount')" prop="amount" show-overflow-tooltip>
 					<template #default="scope">
 						<!-- 橙色 -->
 						<span style="color: #f56c6c; font-weight: bold">¥{{ scope.row.amount ? scope.row.amount.toFixed(2) : '0.00' }}</span>
 					</template>
 				</el-table-column>
-				<el-table-column label="实际金额" prop="noticeAmount" show-overflow-tooltip>
+				<el-table-column :label="$t('order.payOrder.actualAmount')" prop="noticeAmount" show-overflow-tooltip>
 					<template #default="scope">
 						<span style="color: #f56c6c; font-weight: bold">¥{{ scope.row.noticeAmount ? scope.row.noticeAmount.toFixed(2) : '0.00' }}</span>
 					</template>
 				</el-table-column>
-				<el-table-column label="订单状态" prop="orderStatus" show-overflow-tooltip>
+				<el-table-column :label="$t('order.payOrder.orderStatus')" prop="orderStatus" show-overflow-tooltip>
 					<template #default="scope">
 						<el-tag :type="orderStatusMap[scope.row.orderStatus]?.type || 'info'" size="small">
 							{{ orderStatusMap[scope.row.orderStatus]?.label || scope.row.orderStatus }}
 						</el-tag>
 					</template>
 				</el-table-column>
-				<el-table-column label="创建时间" prop="createTime" show-overflow-tooltip width="180">
+				<el-table-column :label="$t('order.payOrder.createTime')" prop="createTime" show-overflow-tooltip width="180">
 					<template #default="scope">
 						{{ scope.row.createTime || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="操作">
+				<el-table-column :label="$t('order.payOrder.operation')">
 					<template #default="scope">
 						<!-- <el-button icon="View" @click="handleView(scope.row)" text type="primary" size="small">查看</el-button> -->
-						<el-button icon="Document" @click="handleNotifyLog(scope.row)" text type="warning" size="small">回调日志</el-button>
+						<el-button icon="Document" @click="handleNotifyLog(scope.row)" text type="warning" size="small">{{
+							$t('order.payOrder.notifyLog')
+						}}</el-button>
 					</template>
 				</el-table-column>
 			</el-table>
@@ -112,12 +134,16 @@ import { fetchWithdrawOrderList } from '/@/api/order';
 // 引入组件
 const NotifyLogDialog = defineAsyncComponent(() => import('../payOrder/notifyLog.vue'));
 
+import { useI18n } from 'vue-i18n';
+
+const { t } = useI18n();
+
 // 订单状态映射
-const orderStatusMap: Record<string, { label: string; type: any }> = {
-	CREATE_ORDER: { label: '创建订单', type: 'info' },
-	WITHDRAW_SUCCESS: { label: '提现成功', type: 'success' },
-	WITHDRAW_FAIL: { label: '提现失败', type: 'danger' },
-};
+const orderStatusMap = computed(() => ({
+	CREATE_ORDER: { label: t('order.payOrder.createOrder'), type: 'info' },
+	WITHDRAW_SUCCESS: { label: t('order.withdrawOrder.withdrawSuccess'), type: 'success' },
+	WITHDRAW_FAIL: { label: t('order.withdrawOrder.withdrawFail'), type: 'danger' },
+}));
 
 // 定义变量内容
 const notifyLogDialogRef = ref();

+ 41 - 27
src/views/payment/channel/index.vue

@@ -3,27 +3,37 @@
 		<div class="layout-padding-auto layout-padding-view">
 			<el-row class="ml10" v-show="showSearch">
 				<el-form :inline="true" :model="queryForm" @keyup.enter="handleSearch" ref="queryRef">
-					<el-form-item label="通道名称" prop="channelName">
-						<el-input placeholder="请输入通道名称" style="max-width: 180px" v-model="queryForm.channelName" clearable />
+					<el-form-item :label="$t('payment.channel.channelName')" prop="channelName">
+						<el-input
+							:placeholder="$t('payment.channel.channelNamePlaceholder')"
+							style="max-width: 180px"
+							v-model="queryForm.channelName"
+							clearable
+						/>
 					</el-form-item>
-					<el-form-item label="支付方式" prop="paymentName">
-						<el-input placeholder="请输入支付方式" style="max-width: 180px" v-model="queryForm.paymentName" clearable />
+					<el-form-item :label="$t('payment.channel.paymentName')" prop="paymentName">
+						<el-input
+							:placeholder="$t('payment.channel.paymentNamePlaceholder')"
+							style="max-width: 180px"
+							v-model="queryForm.paymentName"
+							clearable
+						/>
 					</el-form-item>
-					<el-form-item label="支付类别" prop="paymentType">
-						<el-select v-model="queryForm.paymentType" placeholder="请选择支付类别" style="max-width: 180px" clearable>
-							<el-option label="代付" value="PAY" />
-							<el-option label="代收" value="HARVEST" />
+					<el-form-item :label="$t('payment.channel.paymentType')" prop="paymentType">
+						<el-select v-model="queryForm.paymentType" :placeholder="$t('payment.channel.paymentTypePlaceholder')" style="max-width: 180px" clearable>
+							<el-option :label="$t('payment.channel.paymentTypePay')" value="PAY" />
+							<el-option :label="$t('payment.channel.paymentTypeHarvest')" value="HARVEST" />
 						</el-select>
 					</el-form-item>
 					<el-form-item>
-						<el-button @click="handleSearch" icon="search" type="primary">查询</el-button>
-						<el-button @click="resetQuery" icon="Refresh">重置</el-button>
+						<el-button @click="handleSearch" icon="search" type="primary">{{ $t('common.queryBtn') }}</el-button>
+						<el-button @click="resetQuery" icon="Refresh">{{ $t('common.resetBtn') }}</el-button>
 					</el-form-item>
 				</el-form>
 			</el-row>
 			<el-row>
 				<div class="mb8" style="width: 100%">
-					<el-button @click="loadData" class="ml10" icon="Refresh" type="primary">刷新</el-button>
+					<el-button @click="loadData" class="ml10" icon="Refresh" type="primary">{{ $t('payment.channel.refresh') }}</el-button>
 					<right-toolbar
 						@queryTable="handleSearch"
 						class="ml10"
@@ -41,34 +51,34 @@
 				:cell-style="tableStyle.cellStyle"
 				:header-cell-style="tableStyle.headerCellStyle"
 			>
-				<el-table-column label="通道名称" prop="channelName" show-overflow-tooltip align="center">
+				<el-table-column :label="$t('payment.channel.channelName')" prop="channelName" show-overflow-tooltip align="center">
 					<template #default="scope">
 						{{ scope.row.channelName || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="支付方式" prop="paymentName" show-overflow-tooltip align="center">
+				<el-table-column :label="$t('payment.channel.paymentName')" prop="paymentName" show-overflow-tooltip align="center">
 					<template #default="scope">
 						{{ scope.row.paymentName || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="支付类别" prop="paymentType" show-overflow-tooltip align="center">
+				<el-table-column :label="$t('payment.channel.paymentType')" prop="paymentType" show-overflow-tooltip align="center">
 					<template #default="scope">
 						<el-tag :type="scope.row.paymentType === 'PAY' ? 'warning' : 'info'">
 							{{ paymentTypeMap[scope.row.paymentType] || scope.row.paymentType }}
 						</el-tag>
 					</template>
 				</el-table-column>
-				<el-table-column label="代理商手续费类型" prop="afeeType" show-overflow-tooltip align="center">
+				<el-table-column :label="$t('payment.channel.agentFeeType')" prop="afeeType" show-overflow-tooltip align="center">
 					<template #default="scope">
 						{{ feeTypeMap[scope.row.afeeType] || scope.row.afeeType }}
 					</template>
 				</el-table-column>
-				<el-table-column label="代理商手续费比例" prop="afeeRate" show-overflow-tooltip align="center">
+				<el-table-column :label="$t('payment.channel.agentFeeRate')" prop="afeeRate" show-overflow-tooltip align="center">
 					<template #default="scope">
 						{{ scope.row.afeeRate ? `${scope.row.afeeRate}%` : '0%' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="代理商手续费固定金额" prop="afeeEvery" show-overflow-tooltip align="center">
+				<el-table-column :label="$t('payment.channel.agentFeeFixed')" prop="afeeEvery" show-overflow-tooltip align="center">
 					<template #default="scope">
 						<span class="amount-value">¥{{ scope.row.afeeEvery ? scope.row.afeeEvery.toFixed(2) : '0.00' }}</span>
 					</template>
@@ -82,18 +92,22 @@
 import { getMerchantRate } from '/@/api/payment/channel';
 import { useMessage } from '/@/hooks/message';
 
+import { useI18n } from 'vue-i18n';
+
+const { t } = useI18n();
+
 // 支付类别映射
-const paymentTypeMap: Record<string, string> = {
-	PAY: '代付',
-	HARVEST: '代收',
-};
+const paymentTypeMap = computed(() => ({
+	PAY: t('payment.channel.paymentTypePay'),
+	HARVEST: t('payment.channel.paymentTypeHarvest'),
+}));
 
 // 手续费类型映射
-const feeTypeMap: Record<string, string> = {
-	PERCENTAGE: '百分比',
-	FIXED: '固定金额',
-	MIXED: '混合',
-};
+const feeTypeMap = computed(() => ({
+	PERCENTAGE: t('payment.channel.feeTypePercentage'),
+	FIXED: t('payment.channel.feeTypeFixed'),
+	MIXED: t('payment.channel.feeTypeMixed'),
+}));
 
 // 定义变量
 const queryRef = ref();
@@ -156,7 +170,7 @@ const loadData = async () => {
 		const res = await getMerchantRate();
 		tableData.value = res.data || [];
 	} catch (err: any) {
-		useMessage().error(err.msg || '获取费率信息失败');
+		useMessage().error(err.msg || t('payment.channel.fetchFailed'));
 	} finally {
 		loading.value = false;
 	}

+ 35 - 24
src/views/settlement/apply/index.vue

@@ -6,40 +6,48 @@
 					<el-card shadow="hover" class="apply-card">
 						<template #header>
 							<div class="card-header">
-								<span class="card-title">申请结算</span>
+								<span class="card-title">{{ $t('settlement.apply.title') }}</span>
 								<span class="available-balance"
-									>可提现金额:<span class="balance-amount">¥{{ formatAmount(availableBalance) }}</span></span
+									>{{ $t('settlement.apply.availableAmount') }}:<span class="balance-amount">¥{{ formatAmount(availableBalance) }}</span></span
 								>
 							</div>
 						</template>
 
 						<el-form :model="formData" :rules="rules" ref="formRef" label-width="120px">
-							<el-form-item label="提现金额" prop="amount">
-								<el-input-number v-model="formData.amount" :min="0" :controls="false" placeholder="请输入提现金额" style="width: 100%" />
+							<el-form-item :label="$t('settlement.apply.withdrawAmount')" prop="amount">
+								<el-input-number
+									v-model="formData.amount"
+									:min="0"
+									:controls="false"
+									:placeholder="$t('settlement.apply.withdrawAmountPlaceholder')"
+									style="width: 100%"
+								/>
 							</el-form-item>
 
-							<el-form-item label="提现类型" prop="type">
+							<el-form-item :label="$t('settlement.apply.withdrawType')" prop="type">
 								<el-radio-group v-model="formData.type">
-									<el-radio :label="1">银行卡</el-radio>
-									<el-radio :label="2">USDT</el-radio>
+									<el-radio :label="1">{{ $t('settlement.apply.bankCard') }}</el-radio>
+									<el-radio :label="2">{{ $t('settlement.apply.usdt') }}</el-radio>
 								</el-radio-group>
 							</el-form-item>
 
-							<el-form-item label="银行名称" prop="bankName" v-if="formData.type === 1">
-								<el-input v-model="formData.bankName" placeholder="请输入银行名称" clearable />
+							<el-form-item :label="$t('settlement.apply.bankName')" prop="bankName" v-if="formData.type === 1">
+								<el-input v-model="formData.bankName" :placeholder="$t('settlement.apply.bankNamePlaceholder')" clearable />
 							</el-form-item>
 
-							<el-form-item label="银行卡账号" prop="bankAccount">
-								<el-input v-model="formData.bankAccount" placeholder="请输入银行卡账号/USDT地址" clearable />
+							<el-form-item :label="$t('settlement.apply.bankAccount')" prop="bankAccount">
+								<el-input v-model="formData.bankAccount" :placeholder="$t('settlement.apply.bankAccountPlaceholder')" clearable />
 							</el-form-item>
 
-							<el-form-item label="真实姓名" prop="realName">
-								<el-input v-model="formData.realName" placeholder="请输入真实姓名" clearable />
+							<el-form-item :label="$t('settlement.apply.realName')" prop="realName">
+								<el-input v-model="formData.realName" :placeholder="$t('settlement.apply.realNamePlaceholder')" clearable />
 							</el-form-item>
 
 							<el-form-item>
-								<el-button type="primary" @click="handleSubmit" :loading="loading" size="large" style="width: 120px"> 提交申请 </el-button>
-								<el-button @click="handleReset" size="large" style="width: 120px">重置</el-button>
+								<el-button type="primary" @click="handleSubmit" :loading="loading" size="large" style="width: 120px">{{
+									$t('settlement.apply.submit')
+								}}</el-button>
+								<el-button @click="handleReset" size="large" style="width: 120px">{{ $t('common.resetBtn') }}</el-button>
 							</el-form-item>
 						</el-form>
 					</el-card>
@@ -52,6 +60,9 @@
 <script lang="ts" name="settlementApply" setup>
 import { applyWithdraw, getAgentBalance } from '/@/api/settlement';
 import { useMessage } from '/@/hooks/message';
+import { useI18n } from 'vue-i18n';
+
+const { t } = useI18n();
 
 // 定义变量
 const formRef = ref();
@@ -66,13 +77,13 @@ const formData = ref({
 });
 
 // 表单验证规则
-const rules = {
-	amount: [{ required: true, message: '请输入提现金额', trigger: 'blur' }],
-	type: [{ required: true, message: '请选择提现类型', trigger: 'change' }],
-	bankName: [{ required: true, message: '请输入银行名称', trigger: 'blur' }],
-	bankAccount: [{ required: true, message: '请输入银行卡账号/USDT地址', trigger: 'blur' }],
-	realName: [{ required: true, message: '请输入真实姓名', trigger: 'blur' }],
-};
+const rules = computed(() => ({
+	amount: [{ required: true, message: t('settlement.apply.withdrawAmountRequired'), trigger: 'blur' }],
+	type: [{ required: true, message: t('settlement.apply.withdrawTypeRequired'), trigger: 'change' }],
+	bankName: [{ required: true, message: t('settlement.apply.bankNameRequired'), trigger: 'blur' }],
+	bankAccount: [{ required: true, message: t('settlement.apply.bankAccountRequired'), trigger: 'blur' }],
+	realName: [{ required: true, message: t('settlement.apply.realNameRequired'), trigger: 'blur' }],
+}));
 
 // 提交申请
 const handleSubmit = async () => {
@@ -81,7 +92,7 @@ const handleSubmit = async () => {
 
 		// 验证提现金额不能超过可提现金额
 		if (formData.value.amount && formData.value.amount > availableBalance.value) {
-			useMessage().error(`提现金额不能超过可提现金额 ¥${formatAmount(availableBalance.value)}`);
+			useMessage().error(`${t('settlement.apply.withdrawAmountExceed')} ¥${formatAmount(availableBalance.value)}`);
 			return;
 		}
 
@@ -100,7 +111,7 @@ const handleSubmit = async () => {
 		}
 
 		await applyWithdraw(submitData);
-		useMessage().success('申请提交成功');
+		useMessage().success(t('settlement.apply.submitSuccess'));
 		handleReset();
 	} catch (err: any) {
 		if (err.msg) {

+ 70 - 52
src/views/settlement/fundFlow/index.vue

@@ -16,49 +16,64 @@
 			<!-- 搜索表单 -->
 			<el-row class="ml10" v-show="showSearch">
 				<el-form :inline="true" :model="state.queryForm" @keyup.enter="getDataList" ref="queryRef">
-					<el-form-item label="订单号" prop="query">
-						<el-input placeholder="请输入订单号" style="max-width: 180px" v-model="state.queryForm.query" clearable />
+					<el-form-item :label="$t('settlement.fundFlow.orderNo')" prop="query">
+						<el-input
+							:placeholder="$t('settlement.fundFlow.orderNoPlaceholder')"
+							style="max-width: 180px"
+							v-model="state.queryForm.query"
+							clearable
+						/>
 					</el-form-item>
-					<el-form-item label="订单类型" prop="orderFlowType">
-						<el-select v-model="state.queryForm.orderFlowType" placeholder="请选择订单类型" style="max-width: 180px" clearable>
-							<el-option label="支付订单" value="PAY" />
-							<el-option label="提现订单" value="WITHDRAW" />
+					<el-form-item :label="$t('settlement.fundFlow.orderType')" prop="orderFlowType">
+						<el-select
+							v-model="state.queryForm.orderFlowType"
+							:placeholder="$t('settlement.fundFlow.orderTypePlaceholder')"
+							style="max-width: 180px"
+							clearable
+						>
+							<el-option :label="$t('settlement.fundFlow.payOrder')" value="PAY" />
+							<el-option :label="$t('settlement.fundFlow.withdrawOrder')" value="WITHDRAW" />
 						</el-select>
 					</el-form-item>
-					<el-form-item label="操作钱包类型" prop="walletType">
-						<el-select v-model="state.queryForm.walletType" placeholder="请选择钱包类型" style="max-width: 180px" clearable>
-							<el-option label="总金额" value="TOTAL" />
-							<el-option label="可用金额" value="USE" />
-							<el-option label="冻结金额" value="FREEZE" />
-							<el-option label="提现金额" value="WITHDRAW" />
-							<el-option label="提现总金额" value="WITHDRAW_TOTAL" />
+					<el-form-item :label="$t('settlement.fundFlow.walletType')" prop="walletType">
+						<el-select
+							v-model="state.queryForm.walletType"
+							:placeholder="$t('settlement.fundFlow.walletTypePlaceholder')"
+							style="max-width: 180px"
+							clearable
+						>
+							<el-option :label="$t('settlement.fundFlow.walletTotal')" value="TOTAL" />
+							<el-option :label="$t('settlement.fundFlow.walletUse')" value="USE" />
+							<el-option :label="$t('settlement.fundFlow.walletFreeze')" value="FREEZE" />
+							<el-option :label="$t('settlement.fundFlow.walletWithdraw')" value="WITHDRAW" />
+							<el-option :label="$t('settlement.fundFlow.walletWithdrawTotal')" value="WITHDRAW_TOTAL" />
 						</el-select>
 					</el-form-item>
-					<el-form-item label="订单创建时间" prop="orderCreateTime">
+					<el-form-item :label="$t('settlement.fundFlow.orderCreateTime')" prop="orderCreateTime">
 						<el-date-picker
 							v-model="state.queryForm.orderCreateTime"
 							type="datetimerange"
-							range-separator="至"
-							start-placeholder="开始时间"
-							end-placeholder="结束时间"
+							:range-separator="$t('settlement.fundFlow.to')"
+							:start-placeholder="$t('settlement.fundFlow.startTime')"
+							:end-placeholder="$t('settlement.fundFlow.endTime')"
 							style="max-width: 360px"
 							clearable
 						/>
 					</el-form-item>
-					<el-form-item label="支付时间" prop="payTime">
+					<el-form-item :label="$t('settlement.fundFlow.payTime')" prop="payTime">
 						<el-date-picker
 							v-model="state.queryForm.payTime"
 							type="datetimerange"
-							range-separator="至"
-							start-placeholder="开始时间"
-							end-placeholder="结束时间"
+							:range-separator="$t('settlement.fundFlow.to')"
+							:start-placeholder="$t('settlement.fundFlow.startTime')"
+							:end-placeholder="$t('settlement.fundFlow.endTime')"
 							style="max-width: 360px"
 							clearable
 						/>
 					</el-form-item>
 					<el-form-item>
-						<el-button @click="getDataList" icon="search" type="primary">查询</el-button>
-						<el-button @click="resetQuery" icon="Refresh">重置</el-button>
+						<el-button @click="getDataList" icon="search" type="primary">{{ $t('common.queryBtn') }}</el-button>
+						<el-button @click="resetQuery" icon="Refresh">{{ $t('common.resetBtn') }}</el-button>
 					</el-form-item>
 				</el-form>
 			</el-row>
@@ -85,51 +100,51 @@
 				:header-cell-style="tableStyle.headerCellStyle"
 			>
 				<el-table-column align="center" type="selection" width="40" />
-				<el-table-column label="变更前余额" prop="beforeAmount" show-overflow-tooltip>
+				<el-table-column :label="$t('settlement.fundFlow.beforeAmount')" prop="beforeAmount" show-overflow-tooltip>
 					<template #default="scope">
 						<span>¥{{ scope.row.beforeAmount ? scope.row.beforeAmount.toFixed(2) : '0.00' }}</span>
 					</template>
 				</el-table-column>
-				<el-table-column label="变更金额" prop="operationAmount" show-overflow-tooltip>
+				<el-table-column :label="$t('settlement.fundFlow.changeAmount')" prop="operationAmount" show-overflow-tooltip>
 					<template #default="scope">
 						<span :class="scope.row.amountType === 'ADD' ? 'amount-add' : 'amount-sub'">
 							{{ scope.row.amountType === 'ADD' ? '+' : '-' }} ¥{{ scope.row.operationAmount ? scope.row.operationAmount.toFixed(2) : '0.00' }}
 						</span>
 					</template>
 				</el-table-column>
-				<el-table-column label="变更后余额" prop="afterAmount" show-overflow-tooltip>
+				<el-table-column :label="$t('settlement.fundFlow.afterAmount')" prop="afterAmount" show-overflow-tooltip>
 					<template #default="scope">
 						<span>¥{{ scope.row.afterAmount ? scope.row.afterAmount.toFixed(2) : '0.00' }}</span>
 					</template>
 				</el-table-column>
-				<el-table-column label="订单类型" prop="orderType" show-overflow-tooltip align="center">
+				<el-table-column :label="$t('settlement.fundFlow.orderType')" prop="orderType" show-overflow-tooltip align="center">
 					<template #default="scope">
-						<el-tag :type="orderTypeMap[scope.row.orderType]?.type || 'info'" size="small">
-							{{ orderTypeMap[scope.row.orderType]?.label || '--' }}
+						<el-tag :type="orderTypeMap[scope.row.orderType as keyof typeof orderTypeMap]?.type || 'info'" size="small">
+							{{ orderTypeMap[scope.row.orderType as keyof typeof orderTypeMap]?.label || '--' }}
 						</el-tag>
 					</template>
 				</el-table-column>
-				<el-table-column label="操作钱包类型" prop="walletType" show-overflow-tooltip align="center">
+				<el-table-column :label="$t('settlement.fundFlow.walletType')" prop="walletType" show-overflow-tooltip align="center">
 					<template #default="scope">
-						{{ walletTypeMap[scope.row.walletType]?.label || '--' }}
+						{{ walletTypeMap[scope.row.walletType as keyof typeof walletTypeMap]?.label || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="业务订单" prop="orderNo" show-overflow-tooltip width="200">
+				<el-table-column :label="$t('settlement.fundFlow.businessOrder')" prop="orderNo" show-overflow-tooltip width="200">
 					<template #default="scope">
 						{{ scope.row.orderNo || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="订单金额" prop="orderAmount" show-overflow-tooltip>
+				<el-table-column :label="$t('settlement.fundFlow.orderAmount')" prop="orderAmount" show-overflow-tooltip>
 					<template #default="scope">
 						<span class="amount-value">¥{{ scope.row.orderAmount ? scope.row.orderAmount.toFixed(2) : '0.00' }}</span>
 					</template>
 				</el-table-column>
-				<!-- <el-table-column label="手续费" prop="feeAmount" show-overflow-tooltip>
+				<!-- <el-table-column :label="$t('settlement.fundFlow.fee')" prop="feeAmount" show-overflow-tooltip>
 					<template #default="scope">
 						<span class="amount-value">¥{{ calculateFee(scope.row) }}</span>
 					</template>
 				</el-table-column> -->
-				<el-table-column label="创建时间" prop="payTime" show-overflow-tooltip width="180">
+				<el-table-column :label="$t('settlement.fundFlow.createTime')" prop="payTime" show-overflow-tooltip width="180">
 					<template #default="scope">
 						{{ scope.row.payTime || scope.row.orderCreateTime || '--' }}
 					</template>
@@ -143,14 +158,17 @@
 <script lang="ts" name="settlementFundFlow" setup>
 import { BasicTableProps, useTable } from '/@/hooks/table';
 import { fetchFundFlowList, getAgentBalance } from '/@/api/settlement';
+import { useI18n } from 'vue-i18n';
+
+const { t } = useI18n();
 
 // 余额卡片配置
-const balanceCards = [
-	{ key: 'availableAmount', label: '可用余额' },
-	{ key: 'totalAmount', label: '总金额' },
-	{ key: 'freezeAmount', label: '总冻结金额' },
-	{ key: 'withdrawnAmount', label: '总提现金额' },
-];
+const balanceCards = computed(() => [
+	{ key: 'availableAmount', label: t('settlement.fundFlow.availableBalance') },
+	{ key: 'totalAmount', label: t('settlement.fundFlow.totalAmount') },
+	{ key: 'freezeAmount', label: t('settlement.fundFlow.totalFreezeAmount') },
+	{ key: 'withdrawnAmount', label: t('settlement.fundFlow.totalWithdrawAmount') },
+]);
 
 // 余额数据
 const balanceData = ref({
@@ -162,19 +180,19 @@ const balanceData = ref({
 });
 
 // 订单类型映射
-const orderTypeMap: Record<string, { label: string; type: any }> = {
-	PAY: { label: '支付订单', type: 'success' },
-	WITHDRAW: { label: '提现订单', type: 'warning' },
-};
+const orderTypeMap = computed(() => ({
+	PAY: { label: t('settlement.fundFlow.payOrder'), type: 'success' },
+	WITHDRAW: { label: t('settlement.fundFlow.withdrawOrder'), type: 'warning' },
+}));
 
 // 钱包类型映射
-const walletTypeMap: Record<string, { label: string; type: any }> = {
-	TOTAL: { label: '总金额', type: 'primary' },
-	USE: { label: '可用金额', type: 'success' },
-	FREEZE: { label: '冻结金额', type: 'warning' },
-	WITHDRAW: { label: '提现金额', type: 'danger' },
-	WITHDRAW_TOTAL: { label: '提现总金额', type: 'info' },
-};
+const walletTypeMap = computed(() => ({
+	TOTAL: { label: t('settlement.fundFlow.walletTotal'), type: 'primary' },
+	USE: { label: t('settlement.fundFlow.walletUse'), type: 'success' },
+	FREEZE: { label: t('settlement.fundFlow.walletFreeze'), type: 'warning' },
+	WITHDRAW: { label: t('settlement.fundFlow.walletWithdraw'), type: 'danger' },
+	WITHDRAW_TOTAL: { label: t('settlement.fundFlow.walletWithdrawTotal'), type: 'info' },
+}));
 
 // 定义变量内容
 const queryRef = ref();

+ 48 - 30
src/views/settlement/record/index.vue

@@ -3,22 +3,37 @@
 		<div class="layout-padding-auto layout-padding-view">
 			<el-row class="ml10" v-show="showSearch">
 				<el-form :inline="true" :model="state.queryForm" @keyup.enter="getDataList" ref="queryRef">
-					<el-form-item label="真实姓名" prop="realName">
-						<el-input placeholder="请输入真实姓名" style="max-width: 180px" v-model="state.queryForm.realName" clearable />
+					<el-form-item :label="$t('settlement.record.realName')" prop="realName">
+						<el-input
+							:placeholder="$t('settlement.record.realNamePlaceholder')"
+							style="max-width: 180px"
+							v-model="state.queryForm.realName"
+							clearable
+						/>
 					</el-form-item>
-					<el-form-item label="银行卡账号" prop="bankAccount">
-						<el-input placeholder="请输入银行卡账号" style="max-width: 180px" v-model="state.queryForm.bankAccount" clearable />
+					<el-form-item :label="$t('settlement.record.bankAccount')" prop="bankAccount">
+						<el-input
+							:placeholder="$t('settlement.record.bankAccountPlaceholder')"
+							style="max-width: 180px"
+							v-model="state.queryForm.bankAccount"
+							clearable
+						/>
 					</el-form-item>
-					<el-form-item label="审核状态" prop="auditStatus">
-						<el-select v-model="state.queryForm.auditStatus" placeholder="请选择审核状态" style="max-width: 180px" clearable>
-							<el-option label="待审核" :value="0" />
-							<el-option label="通过" :value="1" />
-							<el-option label="拒绝" :value="2" />
+					<el-form-item :label="$t('settlement.record.auditStatus')" prop="auditStatus">
+						<el-select
+							v-model="state.queryForm.auditStatus"
+							:placeholder="$t('settlement.record.auditStatusPlaceholder')"
+							style="max-width: 180px"
+							clearable
+						>
+							<el-option :label="$t('settlement.record.pending')" :value="0" />
+							<el-option :label="$t('settlement.record.approved')" :value="1" />
+							<el-option :label="$t('settlement.record.rejected')" :value="2" />
 						</el-select>
 					</el-form-item>
 					<el-form-item>
-						<el-button @click="getDataList" icon="search" type="primary">查询</el-button>
-						<el-button @click="resetQuery" icon="Refresh">重置</el-button>
+						<el-button @click="getDataList" icon="search" type="primary">{{ $t('common.queryBtn') }}</el-button>
+						<el-button @click="resetQuery" icon="Refresh">{{ $t('common.resetBtn') }}</el-button>
 					</el-form-item>
 				</el-form>
 			</el-row>
@@ -44,54 +59,54 @@
 				:header-cell-style="tableStyle.headerCellStyle"
 			>
 				<el-table-column align="center" type="selection" width="40" />
-				<el-table-column label="代理名称" prop="agentName" show-overflow-tooltip>
+				<el-table-column :label="$t('settlement.record.agentName')" prop="agentName" show-overflow-tooltip>
 					<template #default="scope">
 						{{ scope.row.agentName || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="提现金额" prop="amount" show-overflow-tooltip>
+				<el-table-column :label="$t('settlement.record.withdrawAmount')" prop="amount" show-overflow-tooltip>
 					<template #default="scope">
 						<span class="amount-value">¥{{ scope.row.amount ? scope.row.amount.toFixed(2) : '0.00' }}</span>
 					</template>
 				</el-table-column>
-				<el-table-column label="提现类型" prop="type" show-overflow-tooltip align="center">
+				<el-table-column :label="$t('settlement.record.withdrawType')" prop="type" show-overflow-tooltip align="center">
 					<template #default="scope">
 						{{ typeMap[scope.row.type] || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="银行名称" prop="bankName" show-overflow-tooltip>
+				<el-table-column :label="$t('settlement.record.bankName')" prop="bankName" show-overflow-tooltip>
 					<template #default="scope">
 						{{ scope.row.bankName || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="银行卡账号" prop="bankAccount" show-overflow-tooltip>
+				<el-table-column :label="$t('settlement.record.bankAccount')" prop="bankAccount" show-overflow-tooltip>
 					<template #default="scope">
 						{{ scope.row.bankAccount || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="真实姓名" prop="realName" show-overflow-tooltip>
+				<el-table-column :label="$t('settlement.record.realName')" prop="realName" show-overflow-tooltip>
 					<template #default="scope">
 						{{ scope.row.realName || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="审核状态" prop="auditStatus" show-overflow-tooltip align="center">
+				<el-table-column :label="$t('settlement.record.auditStatus')" prop="auditStatus" show-overflow-tooltip align="center">
 					<template #default="scope">
 						<el-tag :type="auditStatusMap[scope.row.auditStatus]?.type || 'info'" size="small">
 							{{ auditStatusMap[scope.row.auditStatus]?.label || '--' }}
 						</el-tag>
 					</template>
 				</el-table-column>
-				<el-table-column label="拒绝原因" prop="failReason" show-overflow-tooltip>
+				<el-table-column :label="$t('settlement.record.rejectReason')" prop="failReason" show-overflow-tooltip>
 					<template #default="scope">
 						{{ scope.row.failReason || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="申请时间" prop="applyTime" show-overflow-tooltip width="180">
+				<el-table-column :label="$t('settlement.record.applyTime')" prop="applyTime" show-overflow-tooltip width="180">
 					<template #default="scope">
 						{{ scope.row.applyTime || '--' }}
 					</template>
 				</el-table-column>
-				<el-table-column label="创建时间" prop="createdTime" show-overflow-tooltip width="180">
+				<el-table-column :label="$t('settlement.record.createTime')" prop="createdTime" show-overflow-tooltip width="180">
 					<template #default="scope">
 						{{ scope.row.createdTime || '--' }}
 					</template>
@@ -105,19 +120,22 @@
 <script lang="ts" name="settlementRecord" setup>
 import { BasicTableProps, useTable } from '/@/hooks/table';
 import { fetchWithdrawList } from '/@/api/settlement';
+import { useI18n } from 'vue-i18n';
+
+const { t } = useI18n();
 
 // 提现类型映射
-const typeMap: Record<number, string> = {
-	1: '银行卡',
-	2: 'USDT',
-};
+const typeMap = computed(() => ({
+	1: t('settlement.record.bankCard'),
+	2: t('settlement.record.usdt'),
+}));
 
 // 审核状态映射
-const auditStatusMap: Record<number, { label: string; type: any }> = {
-	0: { label: '待审核', type: 'info' },
-	1: { label: '通过', type: 'success' },
-	2: { label: '拒绝', type: 'danger' },
-};
+const auditStatusMap = computed(() => ({
+	0: { label: t('settlement.record.pending'), type: 'info' },
+	1: { label: t('settlement.record.approved'), type: 'success' },
+	2: { label: t('settlement.record.rejected'), type: 'danger' },
+}));
 
 // 定义变量内容
 const queryRef = ref();