!247 i18n: pages/layout and fix i18n bug

Merge pull request !247 from a20070322/task/i18n
This commit is contained in:
蒋小小 2024-05-09 07:26:06 +00:00 committed by Gitee
commit ab4cc889cc
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
46 changed files with 1025 additions and 316 deletions

View File

@ -16,9 +16,13 @@ import { useI18n } from 'vue-i18n'
*/
export const useI18nPage = <T = any>(pagePath: string) => {
const { t: $t } = useI18n()
const $tPage = $t(pagePath) as T
// $t(pagePath) as T
const $tl = (key: string, ...args: any[]) => {
const arg = [...args]
return $t(`${pagePath}.${key}`, arg) as T
}
return {
$t,
$tPage
$tl
}
}

View File

@ -15,6 +15,7 @@ import dispatch from './pages/dispatch'
import docker from './pages/docker'
import fileManager from './pages/file-manager'
import monitor from './pages/monitor'
import layout from './pages/layout'
export default {
pages: {
404: page404,
@ -23,6 +24,7 @@ export default {
dispatch,
docker,
fileManager,
monitor
monitor,
layout
}
}

View File

@ -18,7 +18,7 @@ export default {
nameLabel: 'Name:',
readWrite: 'Read/Write',
read: 'Read',
path: 'Path: {{ item.source }}(Host) => {{ item.destination }}(Container)',
path: 'Path: {source}(Host) => {destination}(Container)',
networkPort: 'Network Port',
bridgeMode: 'Bridge Mode:',
gateway: 'Gateway',
@ -33,41 +33,7 @@ export default {
edit: 'Edit',
logs: 'Logs',
forceDelete: 'Force delete',
delete: 'Delete',
name_1: 'Name',
containerId_1: 'Container ID',
imageId_1: 'Image ID',
view_1: 'View',
all_1: 'All',
running_1: 'Running',
search_1: 'Search',
seconds_1: 's seconds',
refreshCountdown_1: 'Refresh countdown',
containerName_1: 'Container Name:',
containerIdLabel_1: 'Container ID:',
image_1: 'Image:',
imageIdLabel_1: 'Image ID:',
containerNameTag_1: 'Container Name Tag',
mount_1: 'Mount',
nameLabel_1: 'Name:',
readWrite_1: 'Read/Write',
read_1: 'Read',
path_1: 'Path: {{ item.source }} (Host) => {{ item.destination }} (Container)',
networkPort_1: 'Network Port',
bridgeMode_1: 'Bridge Mode:',
gateway_1: 'Gateway',
viewLogs_1: 'Click to view logs',
enterTerminal_1: 'Enter terminal when container is running',
stop_1: 'Stop',
restart_1: 'Restart',
start_1: 'Start',
modifyAndRun_1: 'Modify container configuration and run again',
rebuild_1: 'Rebuild',
editBasicParams_1: 'Edit some basic parameters of the container',
edit_1: 'Edit',
logs_1: 'Logs',
forceDelete_1: 'Force delete',
delete_1: 'Delete'
delete: 'Delete'
},
p: {
noData: 'No data available',
@ -87,24 +53,6 @@ export default {
confirmStart: 'Are you sure you want to start the current container?',
systemPrompt: 'System Prompt',
confirm: 'Confirm',
cancel: 'Cancel',
noData_1: 'No data available',
configureContainer_1: 'Configure Container',
serialNumber_1: 'Serial Number',
containerId_1: 'Container ID',
imageId_1: 'Image ID',
status_1: 'Status',
port_1: 'Port',
tag_1: 'Tag',
command_1: 'Command',
createTime_1: 'Creation Time',
operation_1: 'Operation',
confirmDelete_1: 'Are you sure you want to delete the current container?',
confirmStop_1: 'Are you sure you want to stop the current container?',
confirmRestart_1: 'Are you sure you want to restart the current container?',
confirmStart_1: 'Are you sure you want to start the current container?',
systemPrompt_1: 'System Prompt',
confirm_1: 'Confirm',
cancel_1: 'Cancel'
cancel: 'Cancel'
}
}

View File

@ -0,0 +1,85 @@
export default {
c: {},
p: {
openSourceIsNotFree: 'Open source is not equivalent to free',
contactUsForAuthorization: 'If you modify Jpom based on secondary development',
nameCopyright: ', name, copyright, etc.',
legalRisks: 'Please contact us for authorization, otherwise there will be legal risks.',
pursueLegalAction:
'We have the right to sue all illegal income from teams or individuals who破坏open source and profit from it, and we also welcome you to provide us with clues of infringement.',
modifyCopyrightRisks: 'Unauthorized modification or deletion of copyright information has legal risks',
respectOpenSourceAgreement:
'Please respect the open source agreement and do not modify the version information without authorization, otherwise you may bear legal responsibility.',
supportOpenSource: 'Support open source',
supportUs:
'Jpom is an open source software. If you use this project and feel good about it, or want to support us to continue developing, you can support us in the following ways:',
recommendToFriends: 'Recommend or share it to your friends:',
donationSponsorship:
'Make a one-time donation sponsorship through the following QR code to buy the author a cup of coffee ☕️',
prioritySupport:
'Join our technical communication group to get priority answers to all your questions by paying a fee',
enterpriseVersion: 'Choose an enterprise version or purchase authorization:',
oneTimeDonation: 'One-time donation sponsorship',
wechatAppreciation: 'WeChat appreciation',
scanToSupport: 'Scan to support the long-term development of open source projects',
alipayTransfer: 'Alipay transfer',
scanToTransfer: 'Scan to transfer to support the long-term development of open source projects',
contactUs: 'Contact us',
notePurpose: 'Please note the purpose when contacting',
noteExample: 'Note example:',
paidCommunity: 'Paid community',
enterpriseServices: 'Enterprise services',
advertising: 'Advertising',
cooperationInquiry: 'Cooperation inquiry',
freeCommunity: 'Free community',
email: 'Email:',
wechat: 'WeChat:',
wechatQRCode: 'WeChat QR code',
openSourceLicense: 'Open source license',
softwareAcknowledgment: 'Software acknowledgment',
usedOpenSourceSoftware:
'The following open source software is used in Jpom. We sincerely thank them for making Jpom more perfect with their open source contributions',
alphabeticalOrder: 'The ranking is sorted in alphabetical order a-z',
moreRelatedDependencies: 'There are more related dependent open source components',
openSourceIsNotFree_1: 'Open source is not the same as free',
contactUsForAuthorization_1: 'If you modify Jpom based on secondary development',
nameCopyright_1: ', name, copyright, etc.',
legalRisks_1: 'Please contact us for authorization, otherwise there will be legal risks.',
pursueLegalAction_1:
'We have the right to sue all illegal income of individuals or teams who damage open source and profit from it. We also welcome anyone who can provide us with clues of infringement.',
modifyCopyrightRisks_1: 'Unauthorized modification or deletion of copyright information has legal risks',
respectOpenSourceAgreement_1:
'Please respect the open source agreement and do not modify the version information without authorization, otherwise you may bear legal responsibilities.',
supportOpenSource_1: 'Support open source',
supportUs_1:
'Jpom is an open source software. If you use this project and feel good about it, or want to support us to continue developing, you can support us in the following ways:',
recommendToFriends_1: 'Recommend or share it with your friends:',
donationSponsorship_1:
'Make a one-time donation sponsorship through the following QR code to buy the author a cup of coffee ☕️',
prioritySupport_1:
'Join our technical communication group by paying a fee to get priority answers to all your questions',
enterpriseVersion_1: 'Choose an enterprise version or purchase authorization:',
oneTimeDonation_1: 'One-time donation sponsorship',
wechatAppreciation_1: 'WeChat appreciation',
scanToSupport_1: 'Scan the QR code to support the long-term development of the open source project',
alipayTransfer_1: 'Alipay transfer',
scanToTransfer_1: 'Scan the QR code to transfer to support the long-term development of the open source project',
contactUs_1: 'Contact us',
notePurpose_1: 'Please note the purpose when contacting',
noteExample_1: 'Note example:',
paidCommunity_1: 'Paid community',
enterpriseServices_1: 'Enterprise services',
advertising_1: 'Advertising',
cooperationInquiry_1: 'Cooperation inquiry',
freeCommunity_1: 'Free community',
email_1: 'Email:',
wechat_1: 'WeChat:',
wechatQRCode_1: 'WeChat QR code',
openSourceLicense_1: 'Open source license',
softwareAcknowledgment_1: 'Software acknowledgment',
usedOpenSourceSoftware_1:
'The following open source software is used in Jpom. We sincerely thank them for their open source contributions, which make Jpom more perfect.',
alphabeticalOrder_1: 'The ranking is sorted in alphabetical order from a to z',
moreRelatedDependencies_1: 'There are more related dependent open source components'
}
}

View File

@ -0,0 +1,10 @@
export default {
c: {},
p: {
closeOthers: 'Close others',
closeLeft: 'Close left',
closeRight: 'Close right',
cannotClose: 'Cannot close',
operationSuccess: 'Operation successful'
}
}

View File

@ -0,0 +1,4 @@
export default {
c: {},
p: {}
}

View File

@ -0,0 +1,8 @@
export default {
c: {},
p: {},
projectMaintenance: {
clickToCollapseLeftMenu: 'Click to collapse the left menu bar',
projectOperation: 'Project operation'
}
}

View File

@ -0,0 +1,27 @@
import about from './about'
import contentTab from './content-tab'
import defaultBg from './default-bg'
import defaultIndex from './default-index'
import ipAccess from './ipAccess'
import loading from './loading'
import management from './management'
import myWorkspace from './my-workspace'
import overview from './overview'
import sideMenu from './side-menu'
import userHeader from './user-header'
import userLog from './user-log'
export default {
about,
contentTab,
defaultBg,
defaultIndex,
ipAccess,
loading,
management,
myWorkspace,
overview,
sideMenu,
userHeader,
userLog
}

View File

@ -0,0 +1,7 @@
export default {
c: {},
p: {
k1: 'You do not have permission to access',
k2: 'Access denied'
}
}

View File

@ -0,0 +1,4 @@
export default {
c: {},
p: {}
}

View File

@ -0,0 +1,4 @@
export default {
c: {},
p: {}
}

View File

@ -0,0 +1,12 @@
export default {
c: {},
p: {
workspaceName: 'My Workspace',
workspaceNote: 'Please enter a workspace note, or use the default name if left blank',
confirm: 'Confirm',
originalName: 'Original Name:',
sortDrag: 'Long press to drag and sort',
save: 'Save',
resetName: 'Restore Default Name'
}
}

View File

@ -0,0 +1,39 @@
export default {
c: {
unknown: 'Unknown',
operationLog: 'Operation log',
unknown_1: 'Unknown',
operationLog_1: 'Operation Log'
},
p: {
welcome: 'Welcome [',
systemUsage: '] You are using this system',
manageWorkspaces: 'You can manage {count} workspaces',
demoAccount: 'Demo account',
superuser: 'Super administrator',
admin: 'Administrator',
normalUser: 'Normal user',
refreshData: 'Refresh data',
systemInfo: 'About the system',
dataStatistics: 'Data statistics',
relatedDataStatistics: 'Current workspace related data statistics',
buildLog: 'Build log',
triggeredBuilds: 'Current workspace build records triggered by you',
notYetBuilt: 'You have not built yet',
loginLog: 'Login log',
notYetLoggedIn: 'You have not logged in yet',
allOperationLog: 'All your operation logs in the system',
notYetPerformedOperations: 'You have not performed any operations yet',
openSourceInfo: 'About open source software',
logicNode: 'Logic node',
nodeProject: 'Node project',
nodeScript: 'Node script',
projectDistribution: 'Project distribution',
terminal: 'Terminal',
script: 'Script',
localScript: 'Local script',
node: 'Node',
cluster: 'Cluster',
dynamicFile: 'Dynamic file'
}
}

View File

@ -0,0 +1,8 @@
export default {
c: {},
p: {
managementSystem: 'System management',
functionManagement: 'Function management',
invalidRouting: 'Invalid routing, unable to jump'
}
}

View File

@ -0,0 +1,117 @@
export default {
c: {
unConfigured: 'Unconfigured',
bracketRight: '】',
bracketLeft: '【',
securityManagement: 'Security Management',
operationLog: 'Operation Log',
oldPassword: 'Please enter your current password',
newPassword: 'Please enter your new password',
confirmPassword: 'Please confirm your new password',
verificationCode: 'Verification Code',
twoStepVerificationCode: 'Two-Step Verification Code',
twoStepVerificationApp: 'Two-Step Verification App',
nickname: 'Nickname',
emailAddress: 'Email Address',
emailVerificationCode: 'Email Verification Code',
dingNotificationAddress: 'DingTalk Notification Address',
enterpriseWeChatNotificationAddress: 'Enterprise WeChat Notification Address',
lightTheme: 'Light Theme',
darkTheme: 'Dark Theme',
securityReminder: 'Security Reminder',
nicknameLength: 'Nickname should be 2-10 characters long',
passwordLength: 'Password should be 6-20 characters long',
systemPrompt: 'System Prompt',
confirm: 'Confirm',
cancel: 'Cancel',
logoutSuccess: 'Logout successful'
},
p: {
workspaceName: 'Workspace Name:',
groupName: 'Group Name:',
clusterName: 'Cluster Name:',
switchWorkspace: 'Switch Workspace',
switchCluster: 'Switch Cluster',
userProfile: 'User Profile',
personalConfiguration: 'Personal Configuration',
logout: 'Logout',
switchAccount: 'Switch Account',
completeLogout: 'Complete Logout',
changePassword: 'Change Password',
originalPassword: 'Original Password',
newPassword: 'New Password',
confirmPassword: 'Confirm Password',
confirmReset: 'Confirm Reset',
twoStepVerification: 'Two-Step Verification',
prompt: 'Prompt',
mfaKey:
'This will not be displayed after binding. It is strongly recommended to save this QR code or the MFA key below.',
pleaseScanQRCodeAndBindToken:
'Please use the app to scan the QR code to bind the token, then enter the verification code to confirm the binding.',
currentStatus: 'Current Status',
opening: 'Opening',
closing: 'Closing',
qrCode: 'QR Code',
confirmBind: 'Confirm Bind',
confirmClose: 'Confirm Close',
enableMFA: 'Enable MFA',
editUserProfile: 'Edit User Profile',
temporaryToken: 'Temporary Token',
permanentToken: 'Permanent Token',
sendVerificationCode: 'Send Verification Code',
personalConfigArea: 'Personal Configuration Area',
theseConfigsOnlyEffectiveInCurrentBrowser:
'These configuration settings will only be effective in the current browser.',
clearingBrowserCacheWillRestoreDefaults: 'Clearing the browser cache will restore default settings.',
menuConfig: 'Menu Configuration',
yes: 'Yes',
no: 'No',
expandMultipleAtOnce: 'Expand Multiple at Once',
fullScreenLog: 'Full Screen Log',
fullScreen: 'Full Screen',
notFullScreen: 'Not Full Screen',
viewLogInFullScreen: 'View Log in Full Screen',
contentTheme: 'Content Theme',
followSystem: 'Follow System',
contentAreaThemeSwitch: 'Content Area Theme Switch',
menuTheme: 'Menu Theme',
leftMenuThemeSwitch: 'Left Menu Theme Switch',
compactMode: 'Compact Mode',
compact: 'Compact',
loose: 'Loose',
fontSpacingAdjustment: 'Font Spacing Adjustment',
onlyEffectiveInDarkMode: 'Only Effective in Dark Mode',
language: 'Language',
chinese: 'Chinese',
forYourAccountSecurityTheSystemRequiresTwoStepVerificationToBeEnabledToEnsureAccountSafety:
'For the security of your account, the system requires two-step verification to be enabled to ensure account safety.',
enableImmediately: 'Enable immediately',
nickname: 'Please enter a nickname',
twoStepVerificationCode: 'Please enter the two-step verification code',
verificationCode6: 'Verification code 6 is pure digits',
closeOperationGuide: 'Close the page operation guide and navigation',
openOperationGuide: 'Enable the page operation guide and navigation',
multipleMenusExpand: 'Multiple menus can be expanded at the same time',
singleMenuExpand: 'Only one menu can be expanded at a time',
autoExpandContent: 'The page content automatically expands to appear on the screen scrollbar',
fullScreen_1: 'Full screen for the page, height 100%. Partial areas can be scrolled',
scrollableContent: 'The page content will have a scrollbar',
hiddenScrollbar:
'Hide the scrollbar. Vertical scrolling reminder: scroll wheel, horizontal scrolling: Shift + scroll wheel',
logDialogFullScreen: 'The log dialog will open in full screen',
logDialogNonFullScreen: 'The log dialog will open in non-full screen',
compactMode_1: 'Enable compact mode for the page',
looseMode: 'Enable loose mode for the page',
resetOperationGuideSuccess: 'Reset the page operation guide and navigation successfully',
quitConfirmation:
'Are you sure you want to completely exit the system? Completely exiting will log you out and clear the browser cache',
switchAccountConfirmation: 'Are you sure you want to exit and switch to another account to log in?',
quitSystemConfirmation: 'Are you sure you want to exit the system?',
passwordsNotMatch: 'The two passwords do not match...',
emailAddress: 'Please enter an email address',
clusterNotConfigured: 'The cluster address has not been configured yet, and the cluster cannot be switched',
verificationCodeRequired: 'A verification code is required. It will take effect after confirmation of binding',
disableTwoStepVerificationConfirmation:
'Are you sure you want to disable two-step verification? Disabling it will affect the security of your account, and existing mfa keys will be invalidated'
}
}

View File

@ -0,0 +1,64 @@
export default {
c: {
function: 'Function',
method: 'Method',
shortcut: 'Quickly return to the first page by holding Ctrl or Alt/Option and clicking the button',
search: 'Search',
success: 'Success',
failure: 'Failure',
usage: 'Usage',
unused: 'Unused',
unknown: 'Unknown',
function_1: 'Operation function',
method_1: 'Operation method',
shortcut_1: 'Press and hold the Ctrl or Alt/Option key to click the button to quickly return to the first page',
search_1: 'Search',
success_1: 'Success',
failure_1: 'Failure',
usage_1: 'Usage',
unused_1: 'Unused',
unknown_1: 'Unknown'
},
p: {
operationLog: 'Operation Log',
defaultStatusCode: 'The default status code of 200 indicates successful execution',
partialStatusCode: 'Some operation status codes may be 0',
statusCode0: 'Most operations with a status code of 0 have no operation result or are executed asynchronously',
loginLog: 'Login Log',
username: 'Username',
loginIp: 'Login IP',
operator: 'Operator',
node: 'Node',
dataName: 'Data Name',
workspaceName: 'Workspace Name',
statusCode: 'Status Code',
operationTime: 'Operation Time',
userId: 'User ID',
userName: 'User Name',
browser: 'Browser',
successFlag: 'Success Flag',
mfaUsage: 'MFA Usage',
resultDescription: 'Result Description',
loginTime: 'Login Time',
operationLog_1: 'Operation log',
defaultStatusCode_1: 'The default status code of 200 indicates successful execution',
partialStatusCode_1: 'Some operation status codes may be 0',
statusCode0_1: 'Most operations with a status code of 0 have no operation results or are executed asynchronously',
loginLog_1: 'Login log',
username_1: 'Username',
loginIp_1: 'Login IP',
operator_1: 'Operator',
node_1: 'Node',
dataName_1: 'Data name',
workspaceName_1: 'Workspace name',
statusCode_1: 'Status code',
operationTime_1: 'Operation time',
userId_1: 'User ID',
userName_1: 'User name',
browser_1: 'Browser',
successFlag_1: 'Whether successful',
mfaUsage_1: 'Whether to use MFA',
resultDescription_1: 'Result description',
loginTime_1: 'Login time'
}
}

View File

@ -1,6 +1,6 @@
import list from './list.ts'
import log from './log.ts'
import operateLog from './operate-log.ts'
import list from './list'
import log from './log'
import operateLog from './operate-log'
export default {
list,

View File

@ -15,6 +15,7 @@ import dispatch from './pages/dispatch'
import docker from './pages/docker'
import fileManager from './pages/file-manager'
import monitor from './pages/monitor'
import layout from './pages/layout'
export default {
pages: {
404: page404,
@ -23,6 +24,7 @@ export default {
dispatch,
docker,
fileManager,
monitor
monitor,
layout
}
}

View File

@ -18,7 +18,7 @@ export default {
nameLabel: '名称:',
readWrite: '读写',
read: '读',
path: '路径:{{ item.source }}(宿主机) => {{ item.destination }}(容器)',
path: '路径:{source}(宿主机) => {destination}(容器)',
networkPort: '网络端口',
bridgeMode: '桥接模式:',
gateway: '网关',

View File

@ -0,0 +1,39 @@
export default {
c: {},
p: {
openSourceIsNotFree: '开源不等同于免费',
contactUsForAuthorization: '如果您基于 Jpom 二次开发修改了',
nameCopyright: '、名称、版权等',
legalRisks: '请找我们授权,否则会有法律风险。',
pursueLegalAction: '我们有权利追诉破坏开源并因此获利的团队个人的全部违法所得,也欢迎给我们提供侵权线索。',
modifyCopyrightRisks: '擅自修改或者删除版权信息有法律风险',
respectOpenSourceAgreement: '请尊重开源协议,不要擅自修改版本信息,否则可能承担法律责任。',
supportOpenSource: '支持开源',
supportUs: '是一款开源软件您使用这个项目并感觉良好,或是想支持我们继续开发,您可以通过如下方式支持我们:',
recommendToFriends: '并向您的朋友推荐或分享:',
donationSponsorship: '通过以下二维码进行一次性捐款赞助,请作者喝一杯咖啡☕️',
prioritySupport: '付费加入我们的技术交流群优先解答您所有疑问',
enterpriseVersion: '选择企业版本或者购买授权:',
oneTimeDonation: '一次性捐款赞助',
wechatAppreciation: '微信赞赏',
scanToSupport: '扫码赞赏支持开源项目长期发展',
alipayTransfer: '支付宝转账',
scanToTransfer: '扫码转账支持开源项目长期发展',
contactUs: '联系我们',
notePurpose: '联系时请备注来意',
noteExample: '备注示例:',
paidCommunity: '付费社群',
enterpriseServices: '企业服务',
advertising: '广告投放',
cooperationInquiry: '合作咨询',
freeCommunity: '免费社群',
email: '邮箱:',
wechat: '微信:',
wechatQRCode: '微信二维码',
openSourceLicense: '开源协议',
softwareAcknowledgment: '软件致谢',
usedOpenSourceSoftware: '中使用了如下开源软件,我们衷心感谢有了他们的开源 Jpom 才能更完善',
alphabeticalOrder: '排名按照字母 a-z 排序',
moreRelatedDependencies: '还有更多相关依赖开源组件'
}
}

View File

@ -0,0 +1,10 @@
export default {
c: {},
p: {
closeOthers: '关闭其他',
closeLeft: '关闭左侧',
closeRight: '关闭右侧',
cannotClose: '不能关闭了',
operationSuccess: '操作成功'
}
}

View File

@ -0,0 +1,4 @@
export default {
c: {},
p: {}
}

View File

@ -0,0 +1,8 @@
export default {
c: {},
p: {},
projectMaintenance: {
clickToCollapseLeftMenu: '点击可以折叠左侧菜单栏',
projectOperation: '项目运维'
}
}

View File

@ -0,0 +1,27 @@
import about from './about'
import contentTab from './content-tab'
import defaultBg from './default-bg'
import defaultIndex from './default-index'
import ipAccess from './ipAccess'
import loading from './loading'
import management from './management'
import myWorkspace from './my-workspace'
import overview from './overview'
import sideMenu from './side-menu'
import userHeader from './user-header'
import userLog from './user-log'
export default {
about,
contentTab,
defaultBg,
defaultIndex,
ipAccess,
loading,
management,
myWorkspace,
overview,
sideMenu,
userHeader,
userLog
}

View File

@ -0,0 +1,7 @@
export default {
c: {},
p: {
k1: '您没有权限访问',
k2: '禁止访问'
}
}

View File

@ -0,0 +1,4 @@
export default {
c: {},
p: {}
}

View File

@ -0,0 +1,4 @@
export default {
c: {},
p: {}
}

View File

@ -0,0 +1,12 @@
export default {
c: {},
p: {
workspaceName: '我的工作空间',
workspaceNote: '请输入工作空间备注,留空使用默认的名称',
confirm: '确定',
originalName: '原始名:',
sortDrag: '长按可以拖动排序',
save: '保存',
resetName: '恢复默认名称'
}
}

View File

@ -0,0 +1,37 @@
export default {
c: {
unknown: '未知',
operationLog: '操作日志'
},
p: {
welcome: '欢迎【',
systemUsage: '】您使用本系统',
manageWorkspaces: '可以管理{count}个工作空间',
demoAccount: '演示账号',
superuser: '超级管理员',
admin: '管理员',
normalUser: '普通用户',
refreshData: '刷新数据',
systemInfo: '关于系统',
dataStatistics: '数据统计',
relatedDataStatistics: '当前工作空间关联数据统计',
buildLog: '构建日志',
triggeredBuilds: '当前工作空间您触发的构建记录',
notYetBuilt: '您还未构建',
loginLog: '登录日志',
notYetLoggedIn: '您还未登录过',
allOperationLog: '系统中您所有操作日志',
notYetPerformedOperations: '您还未执行操作',
openSourceInfo: '关于开源软件',
logicNode: '逻辑节点',
nodeProject: '节点项目',
nodeScript: '节点脚本',
projectDistribution: '项目分发',
terminal: '终端',
script: '脚本',
localScript: '本地脚本',
node: '节点',
cluster: '集群',
dynamicFile: '动态文件'
}
}

View File

@ -0,0 +1,8 @@
export default {
c: {},
p: {
managementSystem: '系统管理',
functionManagement: '功能管理',
invalidRouting: '路由无效,无法跳转'
}
}

View File

@ -0,0 +1,112 @@
export default {
c: {
unConfigured: '未配置',
bracketRight: '】',
bracketLeft: '【',
securityManagement: '安全管理',
operationLog: '操作日志',
oldPassword: '请输入原密码',
newPassword: '请输入新密码',
confirmPassword: '请输入确认密码',
verificationCode: '验证码',
twoStepVerificationCode: '两步验证码',
twoStepVerificationApp: '两步验证应用',
nickname: '昵称',
emailAddress: '邮箱地址',
emailVerificationCode: '邮箱验证码',
dingNotificationAddress: '钉钉通知地址',
enterpriseWeChatNotificationAddress: '企业微信通知地址',
lightTheme: '浅色',
darkTheme: '深色',
securityReminder: '安全提醒',
nicknameLength: '昵称长度为2-10',
passwordLength: '密码长度为6-20',
systemPrompt: '系统提示',
confirm: '确认',
cancel: '取消',
logoutSuccess: '退出登录成功'
},
p: {
workspaceName: '工作空间名称:',
groupName: '【分组名:',
clusterName: '集群名称:',
switchWorkspace: '切换工作空间',
switchCluster: '切换集群',
userProfile: '用户资料',
personalConfiguration: '个性配置',
logout: '退出登录',
switchAccount: '切换账号',
completeLogout: '彻底退出',
changePassword: '修改密码',
originalPassword: '原密码',
newPassword: '新密码',
confirmPassword: '确认密码',
confirmReset: '确认重置',
twoStepVerification: '两步验证',
prompt: '提示',
mfaKey: '绑定成功后将不再显示,强烈建议保存此二维码或者下面的 MFA key',
pleaseScanQRCodeAndBindToken: '请使用应用扫码绑定令牌,然后输入验证码确认绑定才生效',
currentStatus: '当前状态',
opening: '开启中',
closing: '关闭中',
qrCode: '二维码',
confirmBind: '确认绑定',
confirmClose: '确认关闭',
enableMFA: '开启 MFA',
editUserProfile: '修改用户资料',
temporaryToken: '临时token',
permanentToken: '长期token',
sendVerificationCode: '发送验证码',
personalConfigArea: '个性配置区',
theseConfigsOnlyEffectiveInCurrentBrowser: '下列配置信息仅在当前浏览器生效',
clearingBrowserCacheWillRestoreDefaults: '清空浏览器缓存配置将恢复默认',
menuConfig: '菜单配置',
yes: '是',
no: '否',
expandMultipleAtOnce: '同时展开多个',
fullScreenLog: '全屏日志',
fullScreen: '全屏',
notFullScreen: '非全屏',
viewLogInFullScreen: '全屏查看日志',
contentTheme: '内容主题',
followSystem: '跟随系统',
contentAreaThemeSwitch: '内容区域主题切换',
menuTheme: '菜单主题',
leftMenuThemeSwitch: '左边菜单栏主题切换',
compactMode: '紧凑模式',
compact: '紧凑',
loose: '宽松',
fontSpacingAdjustment: '字体间距调整',
onlyEffectiveInDarkMode: '仅在深色模式生效',
language: '语言',
chinese: '中文',
forYourAccountSecurityTheSystemRequiresTwoStepVerificationToBeEnabledToEnsureAccountSafety:
'为了您的账号安全系统要求必须开启两步验证来确保账号的安全性',
enableImmediately: '立即开启',
nickname: '请输入昵称',
twoStepVerificationCode: '请输入两步验证码',
verificationCode6: '验证码 6 为纯数字',
closeOperationGuide: '关闭页面操作引导、导航',
openOperationGuide: '开启页面操作引导、导航',
multipleMenusExpand: '可以同时展开多个菜单',
singleMenuExpand: '同时只能展开一个菜单',
autoExpandContent: '页面内容自动撑开出现屏幕滚动条',
fullScreen_1: '页面全屏,高度 100%。局部区域可以滚动',
scrollableContent: '页面内容会出现滚动条',
hiddenScrollbar: '隐藏滚动条。纵向滚动方式提醒滚轮横行滚动方式Shift+滚轮',
logDialogFullScreen: '日志弹窗会全屏打开',
logDialogNonFullScreen: '日志弹窗会非全屏打开',
compactMode_1: '页面启用紧凑模式',
looseMode: '页面启用宽松模式',
resetOperationGuideSuccess: '重置页面操作引导、导航成功',
quitConfirmation: '真的要彻底退出系统么?彻底退出将退出登录和清空浏览器缓存',
switchAccountConfirmation: '真的要退出并切换账号登录么?',
quitSystemConfirmation: '真的要退出系统么?',
passwordsNotMatch: '两次密码不一致...',
emailAddress: '请输入邮箱地址',
clusterNotConfigured: '还未配置集群地址,不能切换集群',
verificationCodeRequired: '需要输入验证码,确认绑定后才生效奥',
disableTwoStepVerificationConfirmation:
'确定要关闭两步验证吗?关闭后账号安全性将受到影响,关闭后已经存在的 mfa key 将失效'
}
}

View File

@ -0,0 +1,35 @@
export default {
c: {
function: '操作功能',
method: '操作方法',
shortcut: '按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页',
search: '搜索',
success: '成功',
failure: '失败',
usage: '使用',
unused: '未使用',
unknown: '未知'
},
p: {
operationLog: '操作日志',
defaultStatusCode: '默认状态码为 200 表示执行成功',
partialStatusCode: '部分操作状态码可能为 0',
statusCode0: '状态码为 0 的操作大部分为没有操作结果或者异步执行',
loginLog: '登录日志',
username: '用户名',
loginIp: '登录IP',
operator: '操作者',
node: '节点',
dataName: '数据名称',
workspaceName: '工作空间名',
statusCode: '状态码',
operationTime: '操作时间',
userId: '用户ID',
userName: '用户名称',
browser: '浏览器',
successFlag: '是否成功',
mfaUsage: '是否使用MFA',
resultDescription: '结果描述',
loginTime: '登录时间'
}
}

View File

@ -403,7 +403,7 @@
{{ $tl('c.nameLabel') }}{{ item.name }}
<a-tag>{{ item.rw ? $tl('c.readWrite') : $tl('c.read') }}</a-tag>
</p>
<p>{{ $tl('c.path') }}</p>
<p>{{ $tl('c.path', { source: item.source, destination: item.destination }) }}</p>
<a-divider></a-divider>
</div>
</template>

View File

@ -21,7 +21,7 @@
<a-switch
v-model:checked="pruneForm.dangling"
:checked-children="$tl('p.floating')"
un-checked-children="非{{$tl('p.floating')}}"
:un-checked-children="$tl('p.nonFloating')"
/>
</a-form-item>
<a-form-item

View File

@ -21,38 +21,40 @@
<ul>
<li>
<div>
<b style="color: red">开源不等同于免费</b>如果您基于 Jpom 二次开发修改了
<b>logo名称版权等</b>请找我们授权否则会有法律风险
<div>我们有权利追诉破坏开源并因此获利的团队个人的全部违法所得也欢迎给我们提供侵权线索</div>
<b style="color: red">{{ $tl('p.openSourceIsNotFree') }}</b
>{{ $tl('p.contactUsForAuthorization') }} <b>logo{{ $tl('p.nameCopyright') }}</b
>{{ $tl('p.legalRisks') }}
<div>{{ $tl('p.pursueLegalAction') }}</div>
</div>
</li>
<li>
<div>
<b style="color: red">擅自修改或者删除版权信息有法律风险</b
>请尊重开源协议不要擅自修改版本信息否则可能承担法律责任
<b style="color: red">{{ $tl('p.modifyCopyrightRisks') }}</b
>{{ $tl('p.respectOpenSourceAgreement') }}
</div>
</li>
</ul>
</template>
</a-alert>
<a-tabs>
<a-tab-pane key="0" tab="支持开源">
<h2>Jpom 是一款开源软件您使用这个项目并感觉良好或是想支持我们继续开发您可以通过如下方式支持我们</h2>
<a-tab-pane key="0" :tab="$tl('p.supportOpenSource')">
<h2>Jpom {{ $tl('p.supportUs') }}</h2>
<ul>
<li>
Star 并向您的朋友推荐或分享 <a href="https://gitee.com/dromara/Jpom" target="_blank">Gitee</a> /
Star {{ $tl('p.recommendToFriends') }} <a href="https://gitee.com/dromara/Jpom" target="_blank">Gitee</a> /
<a href="https://github.com/dromara/Jpom" target="_blank">Github</a>
</li>
<li>通过以下二维码进行一次性捐款赞助请作者喝一杯咖啡</li>
<li>付费加入我们的技术交流群优先解答您所有疑问</li>
<li>{{ $tl('p.donationSponsorship') }}</li>
<li>{{ $tl('p.prioritySupport') }}</li>
<li>
选择企业版本或者购买授权<a href="https://jpom.top/pages/enterprise-service/" target="_blank">企业服务</a>
{{ $tl('p.enterpriseVersion')
}}<a href="https://jpom.top/pages/enterprise-service/" target="_blank">企业服务</a>
</li>
</ul>
<div></div>
<a-card style="text-align: center">
<template #title> 一次性捐款赞助 </template>
<template #title> {{ $tl('p.oneTimeDonation') }} </template>
<template #extra>
<a href="https://jpom.top/pages/praise/" target="_blank">更多说明</a>
</template>
@ -74,7 +76,8 @@
<!-- <setting-outlined key="setting" />
<edit-outlined key="edit" />
<ellipsis-outlined key="ellipsis" /> -->
<a-card-meta title="微信赞赏" description="扫码赞赏支持开源项目长期发展"> </a-card-meta>
<a-card-meta :title="$tl('p.wechatAppreciation')" :description="$tl('p.scanToSupport')">
</a-card-meta>
</template>
</a-card>
</a-col>
@ -92,7 +95,7 @@
<!-- <img alt="alipay" :src="alipayQrcorde" style="width: 90%; margin: 5%" /> -->
</template>
<template #actions>
<a-card-meta title="支付宝转账" description="扫码转账支持开源项目长期发展"> </a-card-meta>
<a-card-meta :title="$tl('p.alipayTransfer')" :description="$tl('p.scanToTransfer')"> </a-card-meta>
<!-- <setting-outlined key="setting" />
<edit-outlined key="edit" />
@ -104,16 +107,20 @@
</a-row>
</a-card>
</a-tab-pane>
<a-tab-pane key="3" tab="联系我们">
<a-tab-pane key="3" :tab="$tl('p.contactUs')">
<div>
<h2 style="display: inline">联系时请备注来意</h2>
备注示例<a-tag>付费社群</a-tag><a-tag></a-tag><a-tag>广</a-tag><a-tag></a-tag>
<a-tag>免费社群</a-tag>
<h2 style="display: inline">{{ $tl('p.notePurpose') }}</h2>
{{ $tl('p.noteExample') }}<a-tag>{{ $tl('p.paidCommunity') }}</a-tag
><a-tag>{{ $tl('p.enterpriseServices') }}</a-tag
><a-tag>{{ $tl('p.advertising') }}</a-tag
><a-tag>{{ $tl('p.cooperationInquiry') }}</a-tag>
<a-tag>{{ $tl('p.freeCommunity') }}</a-tag>
</div>
<ul>
<li>
邮箱<a-typography-paragraph
{{ $tl('p.email')
}}<a-typography-paragraph
style="display: inline"
:copyable="{ tooltip: false, text: 'bwcx_jzy@dromara.org' }"
>
@ -121,13 +128,14 @@
</a-typography-paragraph>
</li>
<li>
微信<a-typography-paragraph style="display: inline" :copyable="{ tooltip: false, text: 'jpom66' }">
{{ $tl('p.wechat')
}}<a-typography-paragraph style="display: inline" :copyable="{ tooltip: false, text: 'jpom66' }">
<a href="https://jpom.top/pages/praise/join/" target="_blank"> jpom66</a>
</a-typography-paragraph>
</li>
</ul>
<a-card title="微信二维码">
<a-card :title="$tl('p.wechatQRCode')">
<div style="text-align: center">
<a-image width="400px" :src="weixQrcodeJpom66" :preview="true"> </a-image>
</div>
@ -140,11 +148,11 @@
/> -->
</a-card>
</a-tab-pane>
<a-tab-pane key="1" tab="开源协议">
<a-tab-pane key="1" :tab="$tl('p.openSourceLicense')">
<pre style="white-space: pre-wrap">{{ licenseText }}</pre>
</a-tab-pane>
<a-tab-pane key="2" tab="软件致谢">
<h1>Jpom 中使用了如下开源软件我们衷心感谢有了他们的开源 Jpom 才能更完善</h1>
<a-tab-pane key="2" :tab="$tl('p.softwareAcknowledgment')">
<h1>Jpom {{ $tl('p.usedOpenSourceSoftware') }}</h1>
<a-list size="small" bordered :data-source="thankDependency">
<template #renderItem="{ item }">
<a-list-item>
@ -166,10 +174,10 @@
</a-list-item>
</template>
<template #header>
<div>排名按照字母 a-z 排序</div>
<div>{{ $tl('p.alphabeticalOrder') }}</div>
</template>
<template #footer>
<div>还有更多相关依赖开源组件</div>
<div>{{ $tl('p.moreRelatedDependencies') }}</div>
</template>
</a-list></a-tab-pane
>
@ -184,11 +192,14 @@ import weixinQrcorde from '@/assets/images/qrcode/weixin-small.png'
import alipayPraiseQrcorde from '@/assets/images/qrcode/alipay-praise.jpg'
import weixinPraiseQrcorde from '@/assets/images/qrcode/weixin-praise.jpg'
import weixQrcodeJpom66 from '@/assets/images/qrcode/weix-qrcode-jpom66.jpg'
import { useI18nPage } from '@/i18n/hooks/useI18nPage'
// import jpomLogo from '@/assets/images/jpom.svg'
const licenseText = ref('')
const thankDependency = ref([])
const { $tl } = useI18nPage('pages.layout.about')
// const qrCodeSize = ref(200)
onMounted(() => {

View File

@ -13,7 +13,7 @@
})
"
>
<a-button type="link" :disabled="tabList.length <= 1">关闭其他</a-button>
<a-button type="link" :disabled="tabList.length <= 1">{{ $tl('p.closeOthers') }}</a-button>
</a-menu-item>
<a-menu-item
@click="
@ -23,7 +23,7 @@
})
"
>
<a-button type="link" :disabled="tabList.length <= 1 || index === 0">关闭左侧</a-button>
<a-button type="link" :disabled="tabList.length <= 1 || index === 0">{{ $tl('p.closeLeft') }}</a-button>
</a-menu-item>
<a-menu-item
@click="
@ -34,7 +34,7 @@
"
>
<a-button type="link" :disabled="tabList.length <= 1 || index === tabList.length - 1"
>关闭右侧
>{{ $tl('p.closeRight') }}
</a-button>
</a-menu-item>
</a-menu>
@ -46,9 +46,10 @@
</a-tabs>
</template>
<script lang="ts" setup>
import { useI18nPage } from '@/i18n/hooks/useI18nPage'
import userHeader from './user-header.vue'
import { useAllMenuStore } from '@/stores/menu2'
const { $tl } = useI18nPage('pages.layout.contentTab')
const router = useRouter()
const route = useRoute()
@ -87,7 +88,7 @@ const onEdit = (key: string, action: 'remove') => {
if (action === 'remove') {
if (tabList.value.length === 1) {
$notification.warn({
message: '不能关闭了'
message: $tl('p.cannotClose')
})
return
}
@ -100,7 +101,7 @@ const onEdit = (key: string, action: 'remove') => {
// tabs
const closeTabs = (data: any) => {
$notification.success({
message: '操作成功'
message: $tl('p.operationSuccess')
})
menuStore.clearTabs(props.mode, data).then(() => {
activeTab()

View File

@ -3,7 +3,7 @@
<a-layout-sider v-model:collapsed="collapsed" :theme="menuTheme" :trigger="null" collapsible>
<a-layout-sider v-model:collapsed="collapsed" class="sider" :theme="menuTheme" :trigger="null" collapsible>
<div class="sider-content">
<a-tooltip placement="right" title="点击可以折叠左侧菜单栏">
<a-tooltip placement="right" :title="$tl('projectMaintenance.clickToCollapseLeftMenu')">
<div
class="logo"
:style="`color:${menuTheme === 'light' && theme === 'light' ? '#000' : '#fff'}`"
@ -80,7 +80,10 @@ import { checkSystem, loadingLogo } from '@/api/install'
import defaultLogo from '@/assets/images/jpom.svg'
import { useAllMenuStore } from '@/stores/menu2'
import { UserNotificationType, systemNotification } from '@/api/user/user-notification'
import { useI18nPage } from '@/i18n/hooks/useI18nPage'
// import { SpaceSize } from 'ant-design-vue/es/space'
const { $tl } = useI18nPage('pages.layout.defaultIndex')
defineProps({
mode: {
type: String,
@ -138,7 +141,7 @@ watch(
)
const collapsed = ref(false)
const subTitle = ref('项目运维')
const subTitle = ref($tl('projectMaintenance.projectOperation'))
const logoUrl = ref('')
const _appStore = appStore()

View File

@ -4,9 +4,9 @@
<a-card hoverable class="card">
<a-card-meta>
<template #description>
<a-result status="error" title="您没有权限访问">
<a-result status="error" :title="$tl('p.k1')">
<template #extra>
<a-button> 禁止访问 </a-button>
<a-button> {{ $tl('p.k2') }} </a-button>
</template>
</a-result>
</template>
@ -23,6 +23,11 @@ export default {
},
data() {
return {}
},
methods: {
$tl(key, ...args) {
return this.$t(`pages.layout.ipAccess.${key}`, ...args)
}
}
}
</script>

View File

@ -2,7 +2,7 @@
<div>
<a-row type="flex" justify="center">
<a-col :span="18">
<a-card title="我的工作空间" :bordered="true">
<a-card :title="$tl('p.workspaceName')" :bordered="true">
<Container drag-handle-selector=".move" orientation="vertical" @drop="onDrop">
<Draggable v-for="(element, index) in myWorkspaceList" :key="index">
<a-row class="item-row">
@ -10,13 +10,13 @@
<template v-if="element.edit">
<a-input-search
v-model:value="element.name"
placeholder="请输入工作空间备注,留空使用默认的名称"
enter-button="确定"
:placeholder="$tl('p.workspaceNote')"
:enter-button="$tl('p.confirm')"
@search="editOk(element)"
/>
</template>
<template v-else>
<a-tooltip :title="`原始名:${element.originalName}`">
<a-tooltip :title="`${$tl('p.originalName')}${element.originalName}`">
{{ element.name || element.originalName }}
</a-tooltip>
</template>
@ -27,7 +27,7 @@
<a-button :disabled="element.edit" type="primary" size="small" @click="edit(element)">
<template #icon><EditOutlined /></template>
</a-button>
<a-tooltip placement="left" :title="`长按可以拖动排序`" class="move">
<a-tooltip placement="left" :title="`${$tl('p.sortDrag')}`" class="move">
<MenuOutlined />
</a-tooltip>
</a-space>
@ -37,8 +37,8 @@
</Container>
<a-col style="margin-top: 10px">
<a-space>
<a-button type="primary" @click="save"> 保存 </a-button>
<a-button type="primary" @click="resetDefaultName"> 恢复默认名称 </a-button>
<a-button type="primary" @click="save"> {{ $tl('p.save') }} </a-button>
<a-button type="primary" @click="resetDefaultName"> {{ $tl('p.resetName') }} </a-button>
</a-space>
</a-col>
</a-card>
@ -65,6 +65,9 @@ export default {
this.init()
},
methods: {
$tl(key, ...args) {
return this.$t(`pages.layout.myWorkspace.${key}`, ...args)
},
onDrop(dropResult) {
this.myWorkspaceList = dropApplyDrag(this.myWorkspaceList, dropResult).map((item, index) => {
return { ...item, sort: index }

View File

@ -1,24 +1,26 @@
<template>
<div>
<a-page-header :back-icon="false">
<template #title> 欢迎{{ getUserInfo.name }}您使用本系统</template>
<template #subTitle>可以管理{{ (myWorkspaceList && myWorkspaceList.length) || 0 }}个工作空间 </template>
<template #title> {{ $tl('p.welcome') }}{{ getUserInfo.name }}{{ $tl('p.systemUsage') }}</template>
<template #subTitle>
{{ $tl('p.manageWorkspaces', { count: (myWorkspaceList && myWorkspaceList.length) || 0 }) }}
</template>
<template #tags>
<a-tag color="blue">
<template v-if="getUserInfo.demoUser">演示账号</template>
<template v-else-if="getUserInfo.superSystemUser">超级管理员</template>
<template v-else-if="getUserInfo.systemUser">管理员</template>
<template v-else>普通用户</template>
<template v-if="getUserInfo.demoUser">{{ $tl('p.demoAccount') }}</template>
<template v-else-if="getUserInfo.superSystemUser">{{ $tl('p.superuser') }}</template>
<template v-else-if="getUserInfo.systemUser">{{ $tl('p.admin') }}</template>
<template v-else>{{ $tl('p.normalUser') }}</template>
</a-tag>
</template>
<template #extra>
<a-tooltip title="刷新数据">
<a-tooltip :title="$tl('p.refreshData')">
<a-button @click="init">
<template #icon><ReloadOutlined /></template>
</a-button>
</a-tooltip>
<!-- // -->
<a-tooltip v-if="getUserInfo && (getUserInfo.systemUser || getUserInfo.demoUser)" title="关于系统">
<a-tooltip v-if="getUserInfo && (getUserInfo.systemUser || getUserInfo.demoUser)" :title="$tl('p.systemInfo')">
<a-button @click="showAbout">
<template #icon><ExclamationCircleOutlined /></template>
</a-button>
@ -31,8 +33,8 @@
<a-col :span="6">
<a-card size="small">
<template #title>
数据统计
<a-tooltip title="当前工作空间关联数据统计"><QuestionCircleOutlined /></a-tooltip>
{{ $tl('p.dataStatistics') }}
<a-tooltip :title="$tl('p.relatedDataStatistics')"><QuestionCircleOutlined /></a-tooltip>
</template>
<a-list :data-source="statNames">
<template #renderItem="{ item }">
@ -44,8 +46,8 @@
<a-col :span="6">
<a-card size="small">
<template #title>
构建日志
<a-tooltip title="当前工作空间您触发的构建记录"><QuestionCircleOutlined /></a-tooltip>
{{ $tl('p.buildLog') }}
<a-tooltip :title="$tl('p.triggeredBuilds')"><QuestionCircleOutlined /></a-tooltip>
</template>
<a-timeline v-if="buildLog && buildLog.length">
<a-timeline-item v-for="item in buildLog" :key="item.id" :color="statusColor[item.status]">
@ -65,9 +67,9 @@
<span>{{ item.buildName || '-' }}</span>
</a-col>
<a-col>
<a-tooltip :title="item.statusMsg || statusMap[item.status] || '未知'">
<a-tooltip :title="item.statusMsg || statusMap[item.status] || $tl('c.unknown')">
<a-tag :color="statusColor[item.status]" @click="handleBuildLog(item)">
{{ statusMap[item.status] || '未知' }}
{{ statusMap[item.status] || $tl('c.unknown') }}
</a-tag>
</a-tooltip>
</a-col>
@ -75,12 +77,12 @@
</a-space>
</a-timeline-item>
</a-timeline>
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" description="您还未构建" />
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" :description="$tl('p.notYetBuilt')" />
</a-card>
</a-col>
<a-col :span="6">
<a-card size="small">
<template #title> 登录日志 </template>
<template #title> {{ $tl('p.loginLog') }} </template>
<template #extra>
<a href="#" @click="handleUserlog(2)">more</a>
</template>
@ -89,20 +91,20 @@
<a-space direction="vertical" :size="1">
<div>{{ parseTime(item.createTimeMillis) }}</div>
<a-space>
<a-tag> {{ operateCodeMap[item.operateCode] || '未知' }}</a-tag>
<a-tag> {{ operateCodeMap[item.operateCode] || $tl('c.unknown') }}</a-tag>
<span> IP:{{ item.ip }}</span>
</a-space>
</a-space>
</a-timeline-item>
</a-timeline>
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" description="您还未登录过" />
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" :description="$tl('p.notYetLoggedIn')" />
</a-card>
</a-col>
<a-col :span="6">
<a-card size="small">
<template #title>
操作日志
<a-tooltip title="系统中您所有操作日志"><QuestionCircleOutlined /></a-tooltip>
{{ $tl('c.operationLog') }}
<a-tooltip :title="$tl('p.allOperationLog')"><QuestionCircleOutlined /></a-tooltip>
</template>
<template #extra>
<a href="#" @click="handleUserlog(1)">more</a>
@ -122,7 +124,7 @@
</a-space>
</a-timeline-item>
</a-timeline>
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" description="您还未执行操作" />
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" :description="$tl('p.notYetPerformedOperations')" />
</a-card>
</a-col>
</a-row>
@ -132,7 +134,7 @@
destroy-on-close
:open="viewLogVisible > 0"
:width="'90vw'"
title="操作日志"
:title="$tl('c.operationLog')"
:footer="null"
:mask-closable="false"
@cancel="viewLogVisible = 0"
@ -147,7 +149,7 @@
destroy-on-close
:open="aboutVisible > 0"
:width="'90vw'"
title="关于开源软件"
:title="$tl('p.openSourceInfo')"
:footer="null"
:mask-closable="false"
@cancel="aboutVisible = 0"
@ -193,16 +195,16 @@ export default {
viewLogVisible: 0,
// "", "", "", "", "SSH", "SSH", "", "Docker", "", ""
statNames: [
{ name: '逻辑节点', field: 'nodeCount' },
{ name: '节点项目', field: 'projectCount' },
{ name: '节点脚本', field: 'nodeScriptCount' },
{ name: '项目分发', field: 'outGivingCount' },
{ name: 'SSH终端', field: 'sshCount' },
{ name: 'SSH脚本', field: 'sshCommandCount' },
{ name: '本地脚本', field: 'scriptCount' },
{ name: 'Docker节点', field: 'dockerCount' },
{ name: 'Docker集群', field: 'dockerSwarmCount' },
{ name: '动态文件', field: 'fileCount' }
{ name: this.$tl('p.logicNode'), field: 'nodeCount' },
{ name: this.$tl('p.nodeProject'), field: 'projectCount' },
{ name: this.$tl('p.nodeScript'), field: 'nodeScriptCount' },
{ name: this.$tl('p.projectDistribution'), field: 'outGivingCount' },
{ name: `SSH${this.$tl('p.terminal')}`, field: 'sshCount' },
{ name: `SSH${this.$tl('p.script')}`, field: 'sshCommandCount' },
{ name: this.$tl('p.localScript'), field: 'scriptCount' },
{ name: `Docker${this.$tl('p.node')}`, field: 'dockerCount' },
{ name: `Docker${this.$tl('p.cluster')}`, field: 'dockerSwarmCount' },
{ name: this.$tl('p.dynamicFile'), field: 'fileCount' }
// { name: "", field: "staticFileCount" },
],
statData: {},
@ -218,6 +220,9 @@ export default {
this.init()
},
methods: {
$tl(key, ...args) {
return this.$t(`pages.layout.overview.${key}`, ...args)
},
parseTime,
init() {
//

View File

@ -13,12 +13,12 @@
<template v-if="mode === 'normal'">
<SettingOutlined :style="{ fontSize: '18px' }" />
<span>系统管理</span>
<span>{{ $tl('p.managementSystem') }}</span>
</template>
<template v-if="mode === 'management'">
<DesktopOutlined :style="{ fontSize: '18px' }" />
<span>功能管理</span>
<span>{{ $tl('p.functionManagement') }}</span>
</template>
</a-menu-item>
</a-menu>
@ -114,6 +114,9 @@ export default {
},
beforeUnmount() {},
methods: {
$tl(key, ...args) {
return this.$t(`pages.layout.sideMenu.${key}`, ...args)
},
mangerMenuClick() {
this.mangerMenuOpenkeys = []
this.$nextTick(() => {
@ -137,7 +140,7 @@ export default {
//
if (!subMenu.path) {
$notification.error({
message: '路由无效,无法跳转'
message: this.$tl('p.invalidRouting')
})
return false
}

View File

@ -5,7 +5,7 @@
<a-button v-if="mode === 'normal'" type="dashed" class="workspace jpom-workspace btn-group-item">
<div class="workspace-name">
<a-tooltip
:title="`工作空间名称:${selectWorkspace.name} 【分组名:${selectWorkspace.group || '未配置'}】`"
:title="`${$tl('p.workspaceName')}${selectWorkspace.name} ${$tl('p.groupName')}${selectWorkspace.group || $tl('c.unConfigured')}${$tl('c.bracketRight')}`"
placement="bottom"
>
<SwitcherOutlined />
@ -29,7 +29,7 @@
</a-button>
<a-button v-if="mode === 'management'" type="dashed">
<div class="workspace-name">
<a-tooltip :title="`集群名称:${selectCluster && selectCluster.name}`" placement="bottom">
<a-tooltip :title="`${$tl('p.clusterName')}${selectCluster && selectCluster.name}`" placement="bottom">
<ClusterOutlined />
{{ selectCluster && selectCluster.name }}
</a-tooltip>
@ -48,7 +48,7 @@
<template v-if="mode === 'normal'">
<a-sub-menu>
<template #title>
<a-button type="link"><RetweetOutlined />切换工作空间</a-button>
<a-button type="link"><RetweetOutlined />{{ $tl('p.switchWorkspace') }}</a-button>
</template>
<template v-if="myWorkspaceList.length == 1">
<template v-for="(item, index) in myWorkspaceList[0].children">
@ -59,16 +59,17 @@
@click="handleWorkspaceChange(item)"
>
<a-button type="link" :disabled="item.id === selectWorkspace.id">
{{ item.name || '未配置' }}
{{ item.name || $tl('c.unConfigured') }}
<template v-if="myClusterList.length > 1 && item.clusterInfoId">
{{
{{ $tl('c.bracketLeft')
}}{{
myClusterList.find((item2) => {
return item2.id === item.clusterInfoId
}) &&
myClusterList.find((item2) => {
return item2.id === item.clusterInfoId
}).name
}}
}}{{ $tl('c.bracketRight') }}
</template>
</a-button>
</a-menu-item>
@ -80,7 +81,7 @@
<a-sub-menu>
<template #title>
<a-button type="link">
{{ item1.value || '未配置' }}
{{ item1.value || $tl('c.unConfigured') }}
</a-button>
</template>
<template v-for="(item, index) in item1.children">
@ -93,14 +94,15 @@
<a-button type="link" :disabled="item.id === selectWorkspace.id">
{{ item.name }}
<template v-if="myClusterList.length > 1 && item.clusterInfoId">
{{
{{ $tl('c.bracketLeft')
}}{{
myClusterList.find((item2) => {
return item2.id === item.clusterInfoId
}) &&
myClusterList.find((item2) => {
return item2.id === item.clusterInfoId
}).name
}}
}}{{ $tl('c.bracketRight') }}
</template>
</a-button>
</a-menu-item>
@ -117,7 +119,7 @@
<template v-if="mode === 'management'">
<a-sub-menu>
<template #title>
<a-button type="link"><RetweetOutlined />切换集群</a-button>
<a-button type="link"><RetweetOutlined />{{ $tl('p.switchCluster') }}</a-button>
</template>
<template v-for="(item, index) in myClusterList">
<a-menu-item
@ -135,31 +137,31 @@
</a-sub-menu>
</template>
<a-menu-item @click="handleUpdatePwd">
<a-button type="link"> <lock-outlined />安全管理 </a-button>
<a-button type="link"> <lock-outlined />{{ $tl('c.securityManagement') }} </a-button>
</a-menu-item>
<a-menu-divider />
<a-menu-item @click="handleUpdateUser">
<a-button type="link"><profile-outlined /> 用户资料 </a-button>
<a-button type="link"><profile-outlined /> {{ $tl('p.userProfile') }} </a-button>
</a-menu-item>
<a-menu-divider />
<a-menu-item @click="handleUserlog">
<a-button type="link"><bars-outlined /> 操作日志 </a-button>
<a-button type="link"><bars-outlined /> {{ $tl('c.operationLog') }} </a-button>
</a-menu-item>
<a-menu-divider />
<a-menu-item @click="customize">
<a-button type="link"><skin-outlined /> 个性配置 </a-button>
<a-button type="link"><skin-outlined /> {{ $tl('p.personalConfiguration') }} </a-button>
</a-menu-item>
<a-menu-divider />
<a-menu-item @click="logOut">
<a-button type="link"> <logout-outlined />退出登录 </a-button>
<a-button type="link"> <logout-outlined />{{ $tl('p.logout') }} </a-button>
</a-menu-item>
<a-menu-divider />
<a-menu-item @click="logOutSwap">
<a-button type="link"> <SwapOutlined />切换账号 </a-button>
<a-button type="link"> <SwapOutlined />{{ $tl('p.switchAccount') }} </a-button>
</a-menu-item>
<a-menu-divider />
<a-menu-item @click="logOutAll">
<a-button type="link"><RestOutlined /> 彻底退出 </a-button>
<a-button type="link"><RestOutlined /> {{ $tl('p.completeLogout') }} </a-button>
</a-menu-item>
</a-menu>
</template>
@ -171,12 +173,12 @@
v-model:open="updateNameVisible"
destroy-on-close
:width="'60vw'"
title="安全管理"
:title="$tl('c.securityManagement')"
:footer="null"
:mask-closable="false"
>
<a-tabs v-model:active-key="temp.tabActiveKey" @change="tabChange">
<a-tab-pane :key="1" tab="修改密码">
<a-tab-pane :key="1" :tab="$tl('p.changePassword')">
<a-spin tip="Loading..." :spinning="confirmLoading">
<a-form
ref="pwdForm"
@ -186,34 +188,36 @@
:wrapper-col="{ span: 14 }"
@finish="handleUpdatePwdOk"
>
<a-form-item label="原密码" name="oldPwd">
<a-input-password v-model:value="temp.oldPwd" placeholder="请输入原密码" />
<a-form-item :label="$tl('p.originalPassword')" name="oldPwd">
<a-input-password v-model:value="temp.oldPwd" :placeholder="$tl('c.oldPassword')" />
</a-form-item>
<a-form-item label="新密码" name="newPwd">
<a-input-password v-model:value="temp.newPwd" placeholder="请输入新密码" />
<a-form-item :label="$tl('p.newPassword')" name="newPwd">
<a-input-password v-model:value="temp.newPwd" :placeholder="$tl('c.newPassword')" />
</a-form-item>
<a-form-item label="确认密码" name="confirmPwd">
<a-input-password v-model:value="temp.confirmPwd" placeholder="请输入确认密码" />
<a-form-item :label="$tl('p.confirmPassword')" name="confirmPwd">
<a-input-password v-model:value="temp.confirmPwd" :placeholder="$tl('c.confirmPassword')" />
</a-form-item>
<a-form-item>
<a-row type="flex" justify="center">
<a-col :span="2">
<a-button type="primary" html-type="submit" :loading="confirmLoading">确认重置</a-button>
<a-button type="primary" html-type="submit" :loading="confirmLoading">{{
$tl('p.confirmReset')
}}</a-button>
</a-col>
</a-row>
</a-form-item>
</a-form>
</a-spin>
</a-tab-pane>
<a-tab-pane :key="2" tab="两步验证">
<a-tab-pane :key="2" :tab="$tl('p.twoStepVerification')">
<a-row>
<a-col :span="24">
<a-alert v-if="temp.needVerify" type="warning">
<template #message> 提示 </template>
<template #message> {{ $tl('p.prompt') }} </template>
<template #description>
<ul style="color: red">
<li>绑定成功后将不再显示,强烈建议保存此二维码或者下面的 MFA key</li>
<li>请使用应用扫码绑定令牌,然后输入验证码确认绑定才生效</li>
<li>{{ $tl('p.mfaKey') }}</li>
<li>{{ $tl('p.pleaseScanQRCodeAndBindToken') }}</li>
</ul>
</template>
</a-alert>
@ -227,16 +231,16 @@
:wrapper-col="{ span: 14 }"
@finish="handleBindMfa"
>
<a-form-item label="当前状态" name="status">
<a-form-item :label="$tl('p.currentStatus')" name="status">
<a-switch
v-model:checked="temp.status"
checked-children="开启中"
:checked-children="$tl('p.opening')"
disabled
un-checked-children="关闭中"
:un-checked-children="$tl('p.closing')"
/>
</a-form-item>
<template v-if="temp.needVerify">
<a-form-item label="二维码">
<a-form-item :label="$tl('p.qrCode')">
<a-row>
<a-col :span="14">
<a-qrcode :value="temp.url" :status="temp.url ? 'active' : 'loading'" />
@ -256,24 +260,24 @@
</a-form-item>
</template>
<!-- 不能使用 template 包裹 否则验证不能正常启用 -->
<a-form-item v-if="temp.needVerify" label="验证码" name="twoCode">
<a-input ref="twoCode" v-model:value="temp.twoCode" placeholder="两步验证码" />
<a-form-item v-if="temp.needVerify" :label="$tl('c.verificationCode')" name="twoCode">
<a-input ref="twoCode" v-model:value="temp.twoCode" :placeholder="$tl('c.twoStepVerificationCode')" />
</a-form-item>
<a-form-item v-if="temp.needVerify">
<a-row type="flex" justify="center">
<a-col :span="2">
<a-button type="primary" html-type="submit">确认绑定</a-button>
<a-button type="primary" html-type="submit">{{ $tl('p.confirmBind') }}</a-button>
</a-col>
</a-row>
</a-form-item>
<!-- 不能使用 template 包裹 否则验证不能正常启用 -->
<a-form-item v-if="!temp.needVerify && temp.status" label="验证码" name="twoCode">
<a-input ref="twoCode" v-model:value="temp.twoCode" placeholder="两步验证码" />
<a-form-item v-if="!temp.needVerify && temp.status" :label="$tl('c.verificationCode')" name="twoCode">
<a-input ref="twoCode" v-model:value="temp.twoCode" :placeholder="$tl('c.twoStepVerificationCode')" />
</a-form-item>
<a-form-item v-if="!temp.needVerify && temp.status">
<a-row type="flex" justify="center">
<a-col :span="2">
<a-button type="primary" html-type="submit">确认关闭</a-button>
<a-button type="primary" html-type="submit">{{ $tl('p.confirmClose') }}</a-button>
</a-col>
</a-row>
</a-form-item>
@ -281,14 +285,14 @@
<a-form-item v-if="!temp.needVerify && !temp.status">
<a-row type="flex" justify="center">
<a-col :span="2">
<a-button type="primary" @click="openMfaFn">开启 MFA</a-button>
<a-button type="primary" @click="openMfaFn">{{ $tl('p.enableMFA') }}</a-button>
</a-col>
</a-row>
</a-form-item>
</a-form>
</a-col>
<a-col :span="12">
<h3 id="两步验证应用">两步验证应用</h3>
<h3 :id="$tl('c.twoStepVerificationApp')">{{ $tl('c.twoStepVerificationApp') }}</h3>
<p v-for="(html, index) in MFA_APP_TIP_ARRAY" :key="index" v-html="html" />
</a-col>
</a-row>
@ -300,12 +304,12 @@
v-model:open="updateUserVisible"
destroy-on-close
:confirm-loading="confirmLoading"
title="修改用户资料"
:title="$tl('p.editUserProfile')"
:mask-closable="false"
@ok="handleUpdateUserOk"
>
<a-form ref="userForm" :rules="rules" :model="temp" :label-col="{ span: 8 }" :wrapper-col="{ span: 15 }">
<a-form-item label="临时token" name="token">
<a-form-item :label="$tl('p.temporaryToken')" name="token">
<a-input v-model:value="temp.token" disabled placeholder="Token">
<template #suffix>
<a-typography-paragraph style="margin-bottom: 0" :copyable="{ tooltip: true, text: temp.token }">
@ -313,7 +317,7 @@
</template>
</a-input>
</a-form-item>
<a-form-item label="长期token" name="md5Token">
<a-form-item :label="$tl('p.permanentToken')" name="md5Token">
<a-input v-model:value="temp.md5Token" disabled placeholder="Token">
<template #suffix>
<a-typography-paragraph style="margin-bottom: 0" :copyable="{ tooltip: true, text: temp.md5Token }">
@ -321,35 +325,47 @@
</template>
</a-input>
</a-form-item>
<a-form-item label="昵称" name="name">
<a-input v-model:value="temp.name" placeholder="昵称" />
<a-form-item :label="$tl('c.nickname')" name="name">
<a-input v-model:value="temp.name" :placeholder="$tl('c.nickname')" />
</a-form-item>
<a-form-item label="邮箱地址" name="email">
<a-input v-model:value="temp.email" placeholder="邮箱地址" />
<a-form-item :label="$tl('c.emailAddress')" name="email">
<a-input v-model:value="temp.email" :placeholder="$tl('c.emailAddress')" />
</a-form-item>
<a-form-item v-show="showCode" label="邮箱验证码" name="code">
<a-form-item v-show="showCode" :label="$tl('c.emailVerificationCode')" name="code">
<a-row :gutter="8">
<a-col :span="15">
<a-input v-model:value="temp.code" placeholder="邮箱验证码" />
<a-input v-model:value="temp.code" :placeholder="$tl('c.emailVerificationCode')" />
</a-col>
<a-col :span="4">
<a-button type="primary" :disabled="!temp.email" @click="sendEmailCode">发送验证码</a-button>
<a-button type="primary" :disabled="!temp.email" @click="sendEmailCode">{{
$tl('p.sendVerificationCode')
}}</a-button>
</a-col>
</a-row>
</a-form-item>
<a-form-item label="钉钉通知地址" name="dingDing">
<a-input v-model:value="temp.dingDing" placeholder="钉钉通知地址" />
<a-form-item :label="$tl('c.dingNotificationAddress')" name="dingDing">
<a-input v-model:value="temp.dingDing" :placeholder="$tl('c.dingNotificationAddress')" />
</a-form-item>
<a-form-item label="企业微信通知地址" name="workWx">
<a-input v-model:value="temp.workWx" placeholder="企业微信通知地址" />
<a-form-item :label="$tl('c.enterpriseWeChatNotificationAddress')" name="workWx">
<a-input v-model:value="temp.workWx" :placeholder="$tl('c.enterpriseWeChatNotificationAddress')" />
</a-form-item>
</a-form>
</a-modal>
<!-- 个性配置区 -->
<a-modal v-model:open="customizeVisible" destroy-on-close title="个性配置区" :footer="null" :mask-closable="false">
<a-modal
v-model:open="customizeVisible"
destroy-on-close
:title="$tl('p.personalConfigArea')"
:footer="null"
:mask-closable="false"
>
<a-form :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
<a-alert banner>
<template #message> 下列配置信息仅在当前浏览器生效,清空浏览器缓存配置将恢复默认 </template>
<template #message>
{{ $tl('p.theseConfigsOnlyEffectiveInCurrentBrowser') }},{{
$tl('p.clearingBrowserCacheWillRestoreDefaults')
}}
</template>
</a-alert>
<!-- <a-form-item label="页面导航">
<a-space>
@ -367,15 +383,15 @@
</div>
</a-space>
</a-form-item> -->
<a-form-item label="菜单配置">
<a-form-item :label="$tl('p.menuConfig')">
<a-space>
<a-switch
checked-children=""
:checked-children="$tl('p.yes')"
:checked="menuMultipleFlag"
un-checked-children=""
:un-checked-children="$tl('p.no')"
@click="toggleMenuMultiple"
/>
同时展开多个
{{ $tl('p.expandMultipleAtOnce') }}
</a-space>
</a-form-item>
<!-- <a-form-item label="页面配置">
@ -400,52 +416,52 @@
/>
</a-space>
</a-form-item> -->
<a-form-item label="全屏日志">
<a-form-item :label="$tl('p.fullScreenLog')">
<a-space>
<a-switch
checked-children="全屏"
:checked-children="$tl('p.fullScreen')"
:checked="fullscreenViewLog"
un-checked-children="非全屏"
:un-checked-children="$tl('p.notFullScreen')"
@click="toggleFullscreenViewLog"
/>
全屏查看日志
{{ $tl('p.viewLogInFullScreen') }}
</a-space>
</a-form-item>
<a-form-item label="内容主题">
<a-form-item :label="$tl('p.contentTheme')">
<a-space>
<a-radio-group v-model:value="themeView" button-style="solid">
<a-radio-button value="light">浅色</a-radio-button>
<a-radio-button value="dark">深色</a-radio-button>
<a-radio-button value="auto">跟随系统</a-radio-button>
<a-radio-button value="light">{{ $tl('c.lightTheme') }}</a-radio-button>
<a-radio-button value="dark">{{ $tl('c.darkTheme') }}</a-radio-button>
<a-radio-button value="auto">{{ $tl('p.followSystem') }}</a-radio-button>
</a-radio-group>
内容区域主题切换
{{ $tl('p.contentAreaThemeSwitch') }}
</a-space>
</a-form-item>
<a-form-item label="菜单主题">
<a-form-item :label="$tl('p.menuTheme')">
<a-space>
<a-radio-group v-model:value="menuThemeView" button-style="solid">
<a-radio-button value="light">浅色</a-radio-button>
<a-radio-button value="dark">深色</a-radio-button>
<a-radio-button value="light">{{ $tl('c.lightTheme') }}</a-radio-button>
<a-radio-button value="dark">{{ $tl('c.darkTheme') }}</a-radio-button>
</a-radio-group>
左边菜单栏主题切换
{{ $tl('p.leftMenuThemeSwitch') }}
</a-space>
</a-form-item>
<a-form-item label="紧凑模式">
<a-form-item :label="$tl('p.compactMode')">
<a-space>
<a-switch
checked-children="紧凑"
:checked-children="$tl('p.compact')"
:checked="compactView"
un-checked-children="宽松"
:un-checked-children="$tl('p.loose')"
@click="toggleCompactView"
/>
字体间距调整(仅在深色模式生效)
{{ $tl('p.fontSpacingAdjustment') }}({{ $tl('p.onlyEffectiveInDarkMode') }})
</a-space>
</a-form-item>
<a-form-item v-if="!isProduction" label="语言">
<a-form-item v-if="!isProduction" :label="$tl('p.language')">
<a-space>
<a-radio-group v-model:value="locale" button-style="solid">
<a-radio-button value="zh-cn">中文</a-radio-button>
<a-radio-button value="zh-cn">{{ $tl('p.chinese') }}</a-radio-button>
<a-radio-button value="en-us">English</a-radio-button>
</a-radio-group>
</a-space>
@ -456,7 +472,7 @@
<a-modal
v-model:open="bindMfaTip"
destroy-on-close
title="安全提醒"
:title="$tl('c.securityReminder')"
:footer="null"
:mask-closable="false"
:closable="false"
@ -464,13 +480,15 @@
>
<a-space direction="vertical">
<a-alert
message="安全提醒"
description="为了您的账号安全系统要求必须开启两步验证来确保账号的安全性"
:message="$tl('c.securityReminder')"
:description="
$tl('p.forYourAccountSecurityTheSystemRequiresTwoStepVerificationToBeEnabledToEnsureAccountSafety')
"
type="error"
:closable="false"
/>
<a-row align="middle" type="flex" justify="center">
<a-button type="danger" @click="toBindMfa"> 立即开启 </a-button>
<a-button type="danger" @click="toBindMfa"> {{ $tl('p.enableImmediately') }} </a-button>
</a-row>
</a-space>
</a-modal>
@ -479,7 +497,7 @@
v-model:open="viewLogVisible"
destroy-on-close
:width="'90vw'"
title="操作日志"
:title="$tl('c.operationLog')"
:footer="null"
:mask-closable="false"
>
@ -537,31 +555,31 @@ export default {
//
rules: {
name: [
{ required: true, message: '请输入昵称', trigger: 'blur' },
{ max: 10, message: '昵称长度为2-10', trigger: 'blur' },
{ min: 2, message: '昵称长度为2-10', trigger: 'blur' }
{ required: true, message: this.$tl('p.nickname'), trigger: 'blur' },
{ max: 10, message: this.$tl('c.nicknameLength'), trigger: 'blur' },
{ min: 2, message: this.$tl('c.nicknameLength'), trigger: 'blur' }
],
oldPwd: [
{ required: true, message: '请输入原密码', trigger: 'blur' },
{ max: 20, message: '密码长度为6-20', trigger: 'blur' },
{ min: 6, message: '密码长度为6-20', trigger: 'blur' }
{ required: true, message: this.$tl('c.oldPassword'), trigger: 'blur' },
{ max: 20, message: this.$tl('c.passwordLength'), trigger: 'blur' },
{ min: 6, message: this.$tl('c.passwordLength'), trigger: 'blur' }
],
newPwd: [
{ required: true, message: '请输入新密码', trigger: 'blur' },
{ max: 20, message: '密码长度为6-20', trigger: 'blur' },
{ min: 6, message: '密码长度为6-20', trigger: 'blur' }
{ required: true, message: this.$tl('c.newPassword'), trigger: 'blur' },
{ max: 20, message: this.$tl('c.passwordLength'), trigger: 'blur' },
{ min: 6, message: this.$tl('c.passwordLength'), trigger: 'blur' }
],
confirmPwd: [
{ required: true, message: '请输入确认密码', trigger: 'blur' },
{ max: 20, message: '密码长度为6-20', trigger: 'blur' },
{ min: 6, message: '密码长度为6-20', trigger: 'blur' }
{ required: true, message: this.$tl('c.confirmPassword'), trigger: 'blur' },
{ max: 20, message: this.$tl('c.passwordLength'), trigger: 'blur' },
{ min: 6, message: this.$tl('c.passwordLength'), trigger: 'blur' }
],
email: [
// { required: true, message: "", trigger: "blur" }
],
twoCode: [
{ required: true, message: '请输入两步验证码', trigger: ['change', 'blur'] },
{ pattern: /^\d{6}$/, message: '验证码 6 为纯数字', trigger: ['change', 'blur'] }
{ required: true, message: this.$tl('p.twoStepVerificationCode'), trigger: ['change', 'blur'] },
{ pattern: /^\d{6}$/, message: this.$tl('p.verificationCode6'), trigger: ['change', 'blur'] }
]
},
MFA_APP_TIP_ARRAY,
@ -642,6 +660,9 @@ export default {
this.init()
},
methods: {
$tl(key, ...args) {
return this.$t(`pages.layout.userHeader.${key}`, ...args)
},
customize() {
this.customizeVisible = true
},
@ -699,11 +720,11 @@ export default {
.then((flag) => {
if (flag) {
$notification.success({
message: '关闭页面操作引导、导航'
message: this.$tl('p.closeOperationGuide')
})
} else {
$notification.success({
message: '开启页面操作引导、导航'
message: this.$tl('p.openOperationGuide')
})
}
})
@ -715,11 +736,11 @@ export default {
.then((flag) => {
if (flag) {
$notification.success({
message: '可以同时展开多个菜单'
message: this.$tl('p.multipleMenusExpand')
})
} else {
$notification.success({
message: '同时只能展开一个菜单'
message: this.$tl('p.singleMenuExpand')
})
}
})
@ -731,11 +752,11 @@ export default {
.then((flag) => {
if (flag) {
$notification.success({
message: '页面内容自动撑开出现屏幕滚动条'
message: this.$tl('p.autoExpandContent')
})
} else {
$notification.success({
message: '页面全屏,高度 100%。局部区域可以滚动'
message: this.$tl('p.fullScreen_1')
})
}
})
@ -747,11 +768,11 @@ export default {
.then((flag) => {
if (flag) {
$notification.success({
message: '页面内容会出现滚动条'
message: this.$tl('p.scrollableContent')
})
} else {
$notification.success({
message: '隐藏滚动条。纵向滚动方式提醒滚轮横行滚动方式Shift+滚轮'
message: this.$tl('p.hiddenScrollbar')
})
}
})
@ -763,11 +784,11 @@ export default {
.then((fullscreenViewLog) => {
if (fullscreenViewLog) {
$notification.success({
message: '日志弹窗会全屏打开'
message: this.$tl('p.logDialogFullScreen')
})
} else {
$notification.success({
message: '日志弹窗会非全屏打开'
message: this.$tl('p.logDialogNonFullScreen')
})
}
})
@ -778,11 +799,11 @@ export default {
.then((compact) => {
if (compact) {
$notification.success({
message: '页面启用紧凑模式'
message: this.$tl('p.compactMode_1')
})
} else {
$notification.success({
message: '页面启用宽松模式'
message: this.$tl('p.looseMode')
})
}
})
@ -792,24 +813,24 @@ export default {
.restGuide()
.then(() => {
$notification.success({
message: '重置页面操作引导、导航成功'
message: this.$tl('p.resetOperationGuideSuccess')
})
})
},
// 退
logOutAll() {
$confirm({
title: '系统提示',
title: this.$tl('c.systemPrompt'),
zIndex: 1009,
content: '真的要彻底退出系统么?彻底退出将退出登录和清空浏览器缓存',
okText: '确认',
cancelText: '取消',
content: this.$tl('p.quitConfirmation'),
okText: this.$tl('c.confirm'),
cancelText: this.$tl('c.cancel'),
onOk: () => {
return useUserStore()
.logOut()
.then(() => {
$notification.success({
message: '退出登录成功'
message: this.$tl('c.logoutSuccess')
})
localStorage.clear()
this.$router.replace({
@ -823,17 +844,17 @@ export default {
//
logOutSwap() {
$confirm({
title: '系统提示',
title: this.$tl('c.systemPrompt'),
zIndex: 1009,
content: '真的要退出并切换账号登录么?',
okText: '确认',
cancelText: '取消',
content: this.$tl('p.switchAccountConfirmation'),
okText: this.$tl('c.confirm'),
cancelText: this.$tl('c.cancel'),
onOk: () => {
return useUserStore()
.logOut()
.then(() => {
$notification.success({
message: '退出登录成功'
message: this.$tl('c.logoutSuccess')
})
useAppStore().changeWorkspace('')
this.$router.replace({
@ -847,17 +868,17 @@ export default {
// 退
logOut() {
$confirm({
title: '系统提示',
title: this.$tl('c.systemPrompt'),
zIndex: 1009,
content: '真的要退出系统么?',
okText: '确认',
cancelText: '取消',
content: this.$tl('p.quitSystemConfirmation'),
okText: this.$tl('c.confirm'),
cancelText: this.$tl('c.cancel'),
onOk: () => {
return useUserStore()
.logOut()
.then(() => {
$notification.success({
message: '退出登录成功'
message: this.$tl('c.logoutSuccess')
})
const query = Object.assign({}, this.$route.query)
this.$router.replace({
@ -878,7 +899,7 @@ export default {
//
if (this.temp.newPwd !== this.temp.confirmPwd) {
$notification.error({
message: '两次密码不一致...'
message: this.$tl('p.passwordsNotMatch')
})
return
}
@ -925,7 +946,7 @@ export default {
sendEmailCode() {
if (!this.temp.email) {
$notification.error({
message: '请输入邮箱地址'
message: this.$tl('p.emailAddress')
})
return
}
@ -995,7 +1016,7 @@ export default {
location.href = url
} else {
$notification.error({
message: '还未配置集群地址,不能切换集群'
message: this.$tl('p.clusterNotConfigured')
})
}
},
@ -1034,7 +1055,7 @@ export default {
$notification.info({
// placement: "",
message: '需要输入验证码,确认绑定后才生效奥'
message: this.$tl('p.verificationCodeRequired')
})
}
})
@ -1055,11 +1076,11 @@ export default {
})
} else {
$confirm({
title: '系统提示',
title: this.$tl('c.systemPrompt'),
zIndex: 1009,
content: '确定要关闭两步验证吗?关闭后账号安全性将受到影响,关闭后已经存在的 mfa key 将失效',
okText: '确认',
cancelText: '取消',
content: this.$tl('p.disableTwoStepVerificationConfirmation'),
okText: this.$tl('c.confirm'),
cancelText: this.$tl('c.cancel'),
onOk: () => {
return closeMfa({
code: this.temp.twoCode

View File

@ -1,7 +1,7 @@
<template>
<div>
<a-tabs v-model:activeKey="tabKey">
<a-tab-pane :key="1" tab="操作日志">
<a-tab-pane :key="1" :tab="$tl('p.operationLog')">
<!-- 数据表格 -->
<a-table
size="middle"
@ -36,7 +36,7 @@
}
"
allow-clear
placeholder="操作功能"
:placeholder="$tl('c.function')"
class="search-input-item"
>
<a-select-option v-for="item in classFeature" :key="item.value">{{ item.title }}</a-select-option>
@ -55,7 +55,7 @@
}
"
allow-clear
placeholder="操作方法"
:placeholder="$tl('c.method')"
class="search-input-item"
>
<a-select-option v-for="item in methodFeature" :key="item.value">{{ item.title }}</a-select-option>
@ -69,8 +69,10 @@
}
"
/>
<a-tooltip title="按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页">
<a-button type="primary" :loading="operateloading" @click="operaterloadData">搜索</a-button>
<a-tooltip :title="$tl('c.shortcut')">
<a-button type="primary" :loading="operateloading" @click="operaterloadData">{{
$tl('c.search')
}}</a-button>
</a-tooltip>
</a-space>
</template>
@ -95,7 +97,7 @@
<template v-else-if="column.dataIndex === 'optStatus'">
<a-tooltip
placement="topLeft"
:title="`默认状态码为 200 表示执行成功,部分操作状态码可能为 0,状态码为 0 的操作大部分为没有操作结果或者异步执行`"
:title="`${$tl('p.defaultStatusCode')},${$tl('p.partialStatusCode')},${$tl('p.statusCode0')}`"
>
<span>{{ text }}</span>
</a-tooltip>
@ -108,7 +110,7 @@
</template>
</a-table>
</a-tab-pane>
<a-tab-pane :key="2" tab="登录日志">
<a-tab-pane :key="2" :tab="$tl('p.loginLog')">
<a-table
size="middle"
:data-source="loginlist"
@ -130,13 +132,13 @@
<a-space>
<a-input
v-model:value="loginlistQuery['%username%']"
placeholder="用户名"
:placeholder="$tl('p.username')"
class="search-input-item"
@press-enter="loginloadData"
/>
<a-input
v-model:value="loginlistQuery['%ip%']"
placeholder="登录IP"
:placeholder="$tl('p.loginIp')"
class="search-input-item"
@press-enter="loginloadData"
/>
@ -149,21 +151,21 @@
}
"
/>
<a-tooltip title="按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页">
<a-button type="primary" :loading="loginloading" @click="loginloadData">搜索</a-button>
<a-tooltip :title="$tl('c.shortcut')">
<a-button type="primary" :loading="loginloading" @click="loginloadData">{{ $tl('c.search') }}</a-button>
</a-tooltip>
</a-space>
</template>
<template #bodyCell="{ column, text }">
<template v-if="column.dataIndex === 'success'">
<a-tooltip placement="topLeft" :title="text ? '成功' : '失败'">
<a-tag v-if="text" color="green">成功</a-tag>
<a-tag v-else color="pink">失败</a-tag>
<a-tooltip placement="topLeft" :title="text ? $tl('c.success') : $tl('c.failure')">
<a-tag v-if="text" color="green">{{ $tl('c.success') }}</a-tag>
<a-tag v-else color="pink">{{ $tl('c.failure') }}</a-tag>
</a-tooltip>
</template>
<template v-else-if="column.dataIndex === 'useMfa'">
<a-tooltip placement="topLeft" :title="text ? '使用' : '未使用'">
<a-tag>{{ text ? '使用' : '未使用' }}</a-tag>
<a-tooltip placement="topLeft" :title="text ? $tl('c.usage') : $tl('c.unused')">
<a-tag>{{ text ? $tl('c.usage') : $tl('c.unused') }}</a-tag>
</a-tooltip>
</template>
@ -174,8 +176,8 @@
</template>
<template v-else-if="column.dataIndex === 'operateCode'">
<a-tooltip placement="topLeft" :title="operateCode[text] || '未知'">
{{ operateCode[text] || '未知' }}
<a-tooltip placement="topLeft" :title="operateCode[text] || $tl('c.unknown')">
{{ operateCode[text] || $tl('c.unknown') }}
</a-tooltip>
</template>
</template>
@ -208,26 +210,26 @@ export default {
classFeatureMap: {},
operatecolumns: [
{
title: '操作者',
title: this.$tl('p.operator'),
dataIndex: 'username',
ellipsis: true
},
{ title: 'IP', dataIndex: 'ip', ellipsis: true, width: '130px' },
{
title: '节点',
title: this.$tl('p.node'),
dataIndex: 'nodeId',
width: 120,
ellipsis: true
},
{
title: '数据名称',
title: this.$tl('p.dataName'),
dataIndex: 'dataName',
/*width: 240,*/
ellipsis: true,
tooltip: true
},
{
title: '工作空间名',
title: this.$tl('p.workspaceName'),
dataIndex: 'workspaceName',
/*width: 240,*/
ellipsis: true,
@ -235,24 +237,24 @@ export default {
},
// { title: " ID", dataIndex: "dataId", /*width: 240,*/ ellipsis: true,},
{
title: '操作功能',
title: this.$tl('c.function'),
dataIndex: 'classFeature',
/*width: 240,*/
ellipsis: true
},
{
title: '操作方法',
title: this.$tl('c.method'),
dataIndex: 'methodFeature',
/*width: 240,*/
ellipsis: true
},
{
title: '状态码',
title: this.$tl('p.statusCode'),
dataIndex: 'optStatus',
width: 90
},
{
title: '操作时间',
title: this.$tl('p.operationTime'),
dataIndex: 'createTimeMillis',
sorter: true,
customRender: ({ text, item }) => {
@ -267,13 +269,13 @@ export default {
loginlistQuery: Object.assign({}, PAGE_DEFAULT_LIST_QUERY),
logincolumns: [
{
title: '用户ID',
title: this.$tl('p.userId'),
dataIndex: 'modifyUser',
ellipsis: true,
tooltip: true
},
{
title: '用户名称',
title: this.$tl('p.userName'),
dataIndex: 'username',
ellipsis: true,
tooltip: true
@ -285,31 +287,31 @@ export default {
tooltip: true
},
{
title: '浏览器',
title: this.$tl('p.browser'),
dataIndex: 'userAgent',
ellipsis: true,
tooltip: true
},
{
title: '是否成功',
title: this.$tl('p.successFlag'),
dataIndex: 'success',
ellipsis: true,
width: '100px'
},
{
title: '是否使用MFA',
title: this.$tl('p.mfaUsage'),
dataIndex: 'useMfa',
ellipsis: true,
width: '130px'
},
{
title: '结果描述',
title: this.$tl('p.resultDescription'),
dataIndex: 'operateCode',
/*width: 240,*/ ellipsis: true
},
{
title: '登录时间',
title: this.$tl('p.loginTime'),
dataIndex: 'createTimeMillis',
sorter: true,
customRender: ({ text, item }) => {
@ -347,6 +349,9 @@ export default {
})
},
methods: {
$tl(key, ...args) {
return this.$t(`pages.layout.userLog.${key}`, ...args)
},
CHANGE_PAGE,
//
operaterloadData(pointerEvent) {

View File

@ -354,7 +354,7 @@ export default {
},
methods: {
$tl(key, ...args) {
return this.$t(`pages..monitor.list.${key}`, ...args)
return this.$t(`pages.monitor.list.${key}`, ...args)
},
//
loadData(pointerEvent) {

View File

@ -175,7 +175,7 @@ export default {
},
methods: {
$tl(key, ...args) {
return this.$t(`pages..monitor.log.${key}`, ...args)
return this.$t(`pages.monitor.log.${key}`, ...args)
},
// node
loadNodeList(fn) {

View File

@ -214,7 +214,7 @@ export default {
},
methods: {
$tl(key, ...args) {
return this.$t(`pages..monitor.operateLog.${key}`, ...args)
return this.$t(`pages.monitor.operateLog.${key}`, ...args)
},
//
loadData(pointerEvent) {