i18n: pages/user

This commit is contained in:
a20070322 2024-05-21 17:32:09 +08:00
parent b320b93694
commit cbf3532417
16 changed files with 404 additions and 110 deletions

View File

@ -22,6 +22,7 @@ import script from './pages/script'
import node from './pages/node'
import ssh from './pages/ssh'
import tools from './pages/tools'
import user from './pages/user'
export default {
pages: {
404: page404,
@ -37,6 +38,7 @@ export default {
script,
node,
ssh,
tools
tools,
user
}
}

View File

@ -0,0 +1,11 @@
import notification from './notification'
import operationLog from './operation-log'
import permissionGroup from './permission-group'
import userLoginLog from './user-login-log'
export default {
notification,
operationLog,
permissionGroup,
userLoginLog
}

View File

@ -0,0 +1,21 @@
export default {
c: {},
p: {
status: 'Closed',
htmlSupport: 'Supports html format',
statusValue: 'Status',
isOpen: 'Enabled',
title: 'Title',
titleInput: 'Please enter the announcement title',
content: 'Content',
contentInput: 'Please enter the announcement content',
canClose: 'Can close',
cannotClose: 'Cannot close',
level: 'Level',
reminder: 'Reminder',
warning: 'Warning',
error: 'Error',
save: 'Save',
systemNotice: 'System Notice'
}
}

View File

@ -0,0 +1,30 @@
export default {
c: {},
p: {
operationFunction: 'Operation Function',
operationMethod: 'Operation Method',
noOperationLog: 'No Operation Log',
selectOperator: 'Select Operator',
selectNode: 'Select Node',
quickBackToFirstPage: 'Hold Ctrl or Alt/Option and click the button to quickly return to the first page',
search: 'Search',
defaultStatusCode: 'The default status code is 200, indicating successful execution',
partialOperationStatus: 'The status code for some operations may be 0',
statusWithNoResult:
'Most operations with a status code of 0 do not have operation results or are executed asynchronously',
details: 'Details',
detailInfo: 'Detailed Information',
userId: 'User ID',
userNickname: 'User Nickname',
node: 'Node',
dataName: 'Data Name',
workspaceName: 'Workspace Name',
statusCode: 'Status Code',
operationTime: 'Operation Time',
action: 'Action',
dataId: 'Data ID',
browserIdentifier: 'Browser Identifier',
requestParams: 'Request Parameters',
responseResult: 'Response Result'
}
}

View File

@ -0,0 +1,48 @@
export default {
c: {
name: 'Name',
new: 'New',
edit: 'Edit',
startTime: 'Start Time',
endTime: 'End Time',
description: 'Description',
systemTip: 'System Tip',
confirm: 'Confirm',
cancel: 'Cancel'
},
p: {
quickBack: 'Press and hold Ctrl or Alt/Option to click the button to quickly return to the first page',
search: 'Search',
delete: 'Delete',
workspace: 'Workspace',
configWorkspacePermission: 'Configure Workspace Permissions',
userRestriction: 'Restrict users to only operate corresponding functions in their corresponding workspaces',
disablePeriod: 'Disable Period',
disableControl:
'After configuration, you can control users to prohibit certain functions during certain time periods. Priority is given to the disable period',
disableReason: 'Disable Reason',
allowPeriod: 'Allow Period',
priorityDisable: 'Priority is given to the disable period',
allowOperation:
'Then judge the allowed period. After configuring the allowed period, users can only perform corresponding functions during the corresponding period',
selectableWeekdays: 'Please select the executable weekdays',
monday: 'Monday',
tuesday: 'Tuesday',
wednesday: 'Wednesday',
thursday: 'Thursday',
friday: 'Friday',
saturday: 'Saturday',
sunday: 'Sunday',
modifier: 'Modifier',
modifyTime: 'Modify Time',
operation: 'Operation',
permissionGroupName: 'Please enter the permission group name',
permission: 'Permission',
terminalUnlimited: 'Unlimited terminal commands',
selectWorkspace: 'Please select the workspace',
confirmDelete: 'Are you sure you want to delete the permission group?',
demoAccountTip: 'The account is specifically used for system demonstration',
demoAccountRestriction:
'The system will restrict many permissions for demo accounts by default. It is not recommended to use demo accounts in non-demonstration scenarios'
}
}

View File

@ -0,0 +1,22 @@
export default {
c: {},
p: {
nickname: 'User nickname',
noLoginLogs: 'No login logs',
username: 'Username',
loginIp: 'Login IP',
goToFirstPage: 'Hold Ctrl or Alt/Option key and click the button to quickly go back to the first page',
search: 'Search',
success: 'Success',
failure: 'Failure',
used: 'Used',
unused: 'Unused',
unknown: 'Unknown',
userId: 'User ID',
isSuccess: 'Is successful',
isMfaUsed: 'Is MFA used',
resultDescription: 'Result description',
loginTime: 'Login time',
browser: 'Browser'
}
}

View File

@ -22,6 +22,7 @@ import script from './pages/script'
import node from './pages/node'
import ssh from './pages/ssh'
import tools from './pages/tools'
import user from './pages/user'
export default {
pages: {
404: page404,
@ -37,6 +38,7 @@ export default {
script,
node,
ssh,
tools
tools,
user
}
}

View File

@ -0,0 +1,11 @@
import notification from './notification'
import operationLog from './operation-log'
import permissionGroup from './permission-group'
import userLoginLog from './user-login-log'
export default {
notification,
operationLog,
permissionGroup,
userLoginLog
}

View File

@ -0,0 +1,21 @@
export default {
c: {},
p: {
status: '关闭',
htmlSupport: '支持 html 格式',
statusValue: '状态',
isOpen: '开启',
title: '标题',
titleInput: '请输入公告标题',
content: '内容',
contentInput: '请输入公告内容',
canClose: '可以关闭',
cannotClose: '不能关闭',
level: '级别',
reminder: '提醒',
warning: '警告',
error: '错误',
save: '保存',
systemNotice: '系统公告'
}
}

View File

@ -0,0 +1,29 @@
export default {
c: {},
p: {
operationFunction: '操作功能',
operationMethod: '操作方法',
noOperationLog: '没有任何操作日志',
selectOperator: '请选择操作者',
selectNode: '请选择节点',
quickBackToFirstPage: '按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页',
search: '搜索',
defaultStatusCode: '默认状态码为 200 表示执行成功',
partialOperationStatus: '部分操作状态码可能为 0',
statusWithNoResult: '状态码为 0 的操作大部分为没有操作结果或者异步执行',
details: '详情',
detailInfo: '详情信息',
userId: '用户ID',
userNickname: '用户昵称',
node: '节点',
dataName: '数据名称',
workspaceName: '工作空间名',
statusCode: '状态码',
operationTime: '操作时间',
action: '操作',
dataId: '数据Id',
browserIdentifier: '浏览器标识',
requestParams: '请求参数',
responseResult: '响应结果'
}
}

View File

@ -0,0 +1,45 @@
export default {
c: {
name: '名称',
new: '新增',
edit: '编辑',
startTime: '开始时间',
endTime: '结束时间',
description: '描述',
systemTip: '系统提示',
confirm: '确认',
cancel: '取消'
},
p: {
quickBack: '按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页',
search: '搜索',
delete: '删除',
workspace: '工作空间',
configWorkspacePermission: '配置工作空间权限',
userRestriction: '用户限制用户只能对应的工作空间里面操作对应的功能',
disablePeriod: '禁用时段',
disableControl: '配置后可以控制想要在某个时间段禁止用户操作某些功能,优先判断禁用时段',
disableReason: '禁用原因',
allowPeriod: '允许时段',
priorityDisable: '优先判断禁用时段',
allowOperation: '再判断允许时段。配置允许时段后用户只能在对应的时段执行相应功能的操作',
selectableWeekdays: '请选择可以执行的星期',
monday: '周一',
tuesday: '周二',
wednesday: '周三',
thursday: '周四',
friday: '周五',
saturday: '周六',
sunday: '周日',
modifier: '修改人',
modifyTime: '修改时间',
operation: '操作',
permissionGroupName: '请输入权限组名称',
permission: '权限',
terminalUnlimited: '终端命令无限制',
selectWorkspace: '请选择工作空间',
confirmDelete: '真的要删除权限组么?',
demoAccountTip: '账号是系统特定演示使用的账号',
demoAccountRestriction: '系统默认将对 demo 账号限制很多权限。非演示场景不建议使用 demo 账号'
}
}

View File

@ -0,0 +1,22 @@
export default {
c: {},
p: {
nickname: '用户昵称',
noLoginLogs: '没有任何登录日志',
username: '用户名',
loginIp: '登录IP',
goToFirstPage: '按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页',
search: '搜索',
success: '成功',
failure: '失败',
used: '使用',
unused: '未使用',
unknown: '未知',
userId: '用户ID',
isSuccess: '是否成功',
isMfaUsed: '是否使用MFA',
resultDescription: '结果描述',
loginTime: '登录时间',
browser: '浏览器'
}
}

View File

@ -1,37 +1,48 @@
<template>
<a-form :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 16 }">
<a-form-item label="状态" name="enabled">
<a-switch v-model:checked="temp.enabled" checked-children="开启" un-checked-children="关闭" />
<a-form-item :label="$tl('p.statusValue')" name="enabled">
<a-switch
v-model:checked="temp.enabled"
:checked-children="$tl('p.isOpen')"
:un-checked-children="$tl('p.status')"
/>
</a-form-item>
<a-form-item label="标题" name="title">
<a-input v-model:value="temp.title" type="text" placeholder="请输入公告标题" />
<template #help> 支持 html 格式</template>
<a-form-item :label="$tl('p.title')" name="title">
<a-input v-model:value="temp.title" type="text" :placeholder="$tl('p.titleInput')" />
<template #help> {{ $tl('p.htmlSupport') }}</template>
</a-form-item>
<a-form-item label="内容" name="content">
<a-textarea v-model:value="temp.content" type="text" placeholder="请输入公告内容" />
<template #help> 支持 html 格式</template>
<a-form-item :label="$tl('p.content')" name="content">
<a-textarea v-model:value="temp.content" type="text" :placeholder="$tl('p.contentInput')" />
<template #help> {{ $tl('p.htmlSupport') }}</template>
</a-form-item>
<a-form-item label="关闭" name="closable">
<a-switch v-model:checked="temp.closable" checked-children="可以关闭" un-checked-children="不能关闭" />
<a-form-item :label="$tl('p.status')" name="closable">
<a-switch
v-model:checked="temp.closable"
:checked-children="$tl('p.canClose')"
:un-checked-children="$tl('p.cannotClose')"
/>
</a-form-item>
<a-form-item label="级别" name="enabled">
<a-form-item :label="$tl('p.level')" name="enabled">
<a-radio-group v-model:value="temp.level" name="radioGroup">
<a-radio value="info">提醒</a-radio>
<a-radio value="warning">警告</a-radio>
<a-radio value="error">错误</a-radio>
<a-radio value="info">{{ $tl('p.reminder') }}</a-radio>
<a-radio value="warning">{{ $tl('p.warning') }}</a-radio>
<a-radio value="error">{{ $tl('p.error') }}</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item :wrapper-col="{ span: 14, offset: 4 }">
<a-button type="primary" class="btn" @click="onSubmit()">保存</a-button>
<a-button type="primary" class="btn" @click="onSubmit()">{{ $tl('p.save') }}</a-button>
</a-form-item>
</a-form>
</template>
<script setup lang="ts">
import { UserNotificationType, getUserNotification, saveUserNotification } from '@/api/user/user-notification'
import { useI18nPage } from '@/i18n/hooks/useI18nPage'
const { $tl } = useI18nPage('pages.user.notification')
const defaultValue = {
level: 'info',
closable: true,
title: '系统公告',
title: $tl('p.systemNotice'),
enabled: false
} as UserNotificationType

View File

@ -7,7 +7,7 @@
:auto-refresh-time="30"
:active-page="activePage"
table-name="systemUserOperationLog"
empty-description="没有任何操作日志"
:empty-description="$tl('p.noOperationLog')"
:data-source="list"
:columns="columns"
:pagination="pagination"
@ -35,7 +35,7 @@
}
"
allow-clear
placeholder="请选择操作者"
:placeholder="$tl('p.selectOperator')"
class="search-input-item"
>
<a-select-option v-for="item in userList" :key="item.id">{{ item.name }}</a-select-option>
@ -54,7 +54,7 @@
}
"
allow-clear
placeholder="请选择节点"
:placeholder="$tl('p.selectNode')"
class="search-input-item"
>
<a-select-option v-for="node in nodeList" :key="node.id">{{ node.name }}</a-select-option>
@ -73,7 +73,7 @@
}
"
allow-clear
placeholder="操作功能"
:placeholder="$tl('p.operationFunction')"
class="search-input-item"
>
<a-select-option v-for="item in classFeature" :key="item.value">{{ item.title }}</a-select-option>
@ -92,14 +92,14 @@
}
"
allow-clear
placeholder="操作方法"
:placeholder="$tl('p.operationMethod')"
class="search-input-item"
>
<a-select-option v-for="item in methodFeature" :key="item.value">{{ item.title }}</a-select-option>
</a-select>
<a-range-picker :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss" @change="onchangeTime" />
<a-tooltip title="按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页">
<a-button type="primary" :loading="loading" @click="loadData">搜索</a-button>
<a-tooltip :title="$tl('p.quickBackToFirstPage')">
<a-button type="primary" :loading="loading" @click="loadData">{{ $tl('p.search') }}</a-button>
</a-tooltip>
</a-space>
</template>
@ -134,19 +134,19 @@
<template v-else-if="column.dataIndex === 'optStatus'">
<a-tooltip
placement="topLeft"
:title="`默认状态码为 200 表示执行成功,部分操作状态码可能为 0,状态码为 0 的操作大部分为没有操作结果或者异步执行`"
:title="`${$tl('p.defaultStatusCode')},${$tl('p.partialOperationStatus')},${$tl('p.statusWithNoResult')}`"
>
<span>{{ text }}</span>
</a-tooltip>
</template>
<template v-else-if="column.dataIndex === 'operation'">
<a-button size="small" type="primary" @click="handleDetail(record)">详情</a-button>
<a-button size="small" type="primary" @click="handleDetail(record)">{{ $tl('p.details') }}</a-button>
</template>
</template>
</CustomTable>
<!-- 详情区 -->
<a-modal v-model:open="detailVisible" destroy-on-close width="600px" title="详情信息" :footer="null">
<a-modal v-model:open="detailVisible" destroy-on-close width="600px" :title="$tl('p.detailInfo')" :footer="null">
<a-list item-layout="horizontal" :data-source="detailData">
<template #renderItem="{ item }">
<a-list-item>
@ -192,31 +192,31 @@ export default {
detailData: [],
columns: [
{
title: '用户ID',
title: this.$tl('p.userId'),
dataIndex: 'userId',
ellipsis: true
},
{
title: '用户昵称',
title: this.$tl('p.userNickname'),
dataIndex: 'username',
ellipsis: true
},
{ title: 'IP', dataIndex: 'ip' /*width: 130*/ },
{
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,
@ -224,24 +224,24 @@ export default {
},
// { title: " ID", dataIndex: "dataId", /*width: 240,*/ ellipsis: true, },
{
title: '操作功能',
title: this.$tl('p.operationFunction'),
dataIndex: 'classFeature',
/*width: 240,*/
ellipsis: true
},
{
title: '操作方法',
title: this.$tl('p.operationMethod'),
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, record }) => {
@ -250,7 +250,7 @@ export default {
width: '170px'
},
{
title: '操作',
title: this.$tl('p.action'),
align: 'center',
dataIndex: 'operation',
fixed: 'right',
@ -284,6 +284,9 @@ export default {
})
},
methods: {
$tl(key, ...args) {
return this.$t(`pages.user.operationLog.${key}`, ...args)
},
// node
loadNodeList() {
getNodeListAll().then((res) => {
@ -340,18 +343,18 @@ export default {
} catch (e) {
console.error(e)
}
this.detailData.push({ title: '数据Id', description: this.temp.dataId })
this.detailData.push({ title: this.$tl('p.dataId'), description: this.temp.dataId })
this.detailData.push({
title: '浏览器标识',
title: this.$tl('p.browserIdentifier'),
description: this.temp.userAgent
})
this.detailData.push({
title: '请求参数',
title: this.$tl('p.requestParams'),
json: true,
value: this.temp.reqData
})
this.detailData.push({
title: '响应结果',
title: this.$tl('p.responseResult'),
json: true,
value: this.temp.resultMsg
})

View File

@ -17,21 +17,21 @@
<a-space wrap class="search-box">
<a-input
v-model:value="listQuery['%name%']"
placeholder="名称"
:placeholder="$tl('c.name')"
class="search-input-item"
@press-enter="loadData"
/>
<a-tooltip title="按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页">
<a-button type="primary" :loading="loading" @click="loadData">搜索</a-button>
<a-tooltip :title="$tl('p.quickBack')">
<a-button type="primary" :loading="loading" @click="loadData">{{ $tl('p.search') }}</a-button>
</a-tooltip>
<a-button type="primary" @click="handleAdd">新增</a-button>
<a-button type="primary" @click="handleAdd">{{ $tl('c.new') }}</a-button>
</a-space>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'operation'">
<a-space>
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
<a-button type="primary" danger size="small" @click="handleDelete(record)">删除</a-button>
<a-button size="small" type="primary" @click="handleEdit(record)">{{ $tl('c.edit') }}</a-button>
<a-button type="primary" danger size="small" @click="handleDelete(record)">{{ $tl('p.delete') }}</a-button>
</a-space>
</template>
</template>
@ -42,19 +42,19 @@
destroy-on-close
:confirm-loading="confirmLoading"
width="60vw"
title="编辑"
:title="$tl('c.edit')"
:mask-closable="false"
@ok="handleEditUserOk"
>
<a-form ref="editForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
<a-form-item label="名称" name="name">
<a-input v-model:value="temp.name" :max-length="50" placeholder="名称" />
<a-form-item :label="$tl('c.name')" name="name">
<a-input v-model:value="temp.name" :max-length="50" :placeholder="$tl('c.name')" />
</a-form-item>
<a-form-item name="workspace">
<template #label>
<a-tooltip>
工作空间
<template #title> 配置工作空间权限,用户限制用户只能对应的工作空间里面操作对应的功能</template>
{{ $tl('p.workspace') }}
<template #title> {{ $tl('p.configWorkspacePermission') }},{{ $tl('p.userRestriction') }}</template>
<QuestionCircleOutlined v-if="!temp.id" />
</a-tooltip>
</template>
@ -63,8 +63,8 @@
<a-form-item name="prohibitExecute">
<template #label>
<a-tooltip>
禁用时段
<template #title> 配置后可以控制想要在某个时间段禁止用户操作某些功能优先判断禁用时段</template>
{{ $tl('p.disablePeriod') }}
<template #title> {{ $tl('p.disableControl') }}</template>
<QuestionCircleOutlined v-if="!temp.id" />
</a-tooltip>
</template>
@ -97,11 +97,11 @@
:show-time="{ format: 'HH:mm:ss' }"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
:placeholder="['开始时间', '结束时间']"
:placeholder="[$tl('c.startTime'), $tl('c.endTime')]"
/>
<div>
<a-input v-model:value="item.reason" placeholder="禁用原因" allow-clear />
<a-input v-model:value="item.reason" :placeholder="$tl('p.disableReason')" allow-clear />
</div>
</a-space>
@ -124,17 +124,15 @@
temp.prohibitExecuteArray.push({})
}
"
>新增
>{{ $tl('c.new') }}
</a-button>
</a-form-item-rest>
</a-form-item>
<a-form-item name="allowExecute">
<template #label>
<a-tooltip>
允许时段
<template #title>
优先判断禁用时段,再判断允许时段配置允许时段后用户只能在对应的时段执行相应功能的操作
</template>
{{ $tl('p.allowPeriod') }}
<template #title> {{ $tl('p.priorityDisable') }},{{ $tl('p.allowOperation') }} </template>
<QuestionCircleOutlined v-if="!temp.id" />
</a-tooltip>
</template>
@ -145,7 +143,7 @@
<div>
<a-select
v-model:value="item.week"
placeholder="请选择可以执行的星期"
:placeholder="$tl('p.selectableWeekdays')"
mode="multiple"
style="width: 100%"
>
@ -167,8 +165,16 @@
</div>
<div>
<a-space>
<a-time-picker v-model:value="item.startTime" placeholder="开始时间" value-format="HH:mm:ss" />
<a-time-picker v-model:value="item.endTime" placeholder="结束时间" value-format="HH:mm:ss" />
<a-time-picker
v-model:value="item.startTime"
:placeholder="$tl('c.startTime')"
value-format="HH:mm:ss"
/>
<a-time-picker
v-model:value="item.endTime"
:placeholder="$tl('c.endTime')"
value-format="HH:mm:ss"
/>
</a-space>
</div>
</a-space>
@ -191,13 +197,18 @@
temp.allowExecuteArray.push({})
}
"
>新增
>{{ $tl('c.new') }}
</a-button>
</a-form-item-rest>
</a-form-item>
<a-form-item label="描述" name="description">
<a-textarea v-model:value="temp.description" :max-length="200" :rows="5" placeholder="描述" />
<a-form-item :label="$tl('c.description')" name="description">
<a-textarea
v-model:value="temp.description"
:max-length="200"
:rows="5"
:placeholder="$tl('c.description')"
/>
</a-form-item>
</a-form>
</a-modal>
@ -226,29 +237,29 @@ export default {
methodFeature: [],
temp: {},
weeks: [
{ value: 1, name: '周一' },
{ value: 2, name: '周二' },
{ value: 3, name: '周三' },
{ value: 4, name: '周四' },
{ value: 5, name: '周五' },
{ value: 6, name: '周六' },
{ value: 7, name: '周日' }
{ value: 1, name: this.$tl('p.monday') },
{ value: 2, name: this.$tl('p.tuesday') },
{ value: 3, name: this.$tl('p.wednesday') },
{ value: 4, name: this.$tl('p.thursday') },
{ value: 5, name: this.$tl('p.friday') },
{ value: 6, name: this.$tl('p.saturday') },
{ value: 7, name: this.$tl('p.sunday') }
],
editVisible: false,
listQuery: Object.assign({}, PAGE_DEFAULT_LIST_QUERY),
columns: [
{ title: 'id', dataIndex: 'id', ellipsis: true },
{ title: '名称', dataIndex: 'name', ellipsis: true },
{ title: '描述', dataIndex: 'description', ellipsis: true },
{ title: this.$tl('c.name'), dataIndex: 'name', ellipsis: true },
{ title: this.$tl('c.description'), dataIndex: 'description', ellipsis: true },
{
title: '修改人',
title: this.$tl('p.modifier'),
dataIndex: 'modifyUser',
ellipsis: true,
width: 150
},
{
title: '修改时间',
title: this.$tl('p.modifyTime'),
dataIndex: 'modifyTimeMillis',
sorter: true,
ellipsis: true,
@ -258,7 +269,7 @@ export default {
width: 170
},
{
title: '操作',
title: this.$tl('p.operation'),
align: 'center',
dataIndex: 'operation',
@ -267,7 +278,7 @@ export default {
],
//
rules: {
name: [{ required: true, message: '请输入权限组名称', trigger: 'blur' }]
name: [{ required: true, message: this.$tl('p.permissionGroupName'), trigger: 'blur' }]
},
confirmLoading: false
}
@ -283,6 +294,9 @@ export default {
this.loadOptTypeData()
},
methods: {
$tl(key, ...args) {
return this.$t(`pages.user.permissionGroup.${key}`, ...args)
},
dayjs,
//
loadData(pointerEvent) {
@ -306,13 +320,13 @@ export default {
const children = this.methodFeature.map((item) => {
return {
key: element.id + '-' + item.value,
title: item.title + '权限',
title: item.title + this.$tl('p.permission'),
parentId: element.id
}
})
children.push({
key: element.id + '-sshCommandNotLimited',
title: 'SSH 终端命令无限制',
title: `SSH ${this.$tl('p.terminalUnlimited')}`,
parentId: element.id
})
this.workspaceList.push({
@ -401,7 +415,7 @@ export default {
delete temp.allowExecuteArray
if (!emitKeys || emitKeys.length <= 0) {
$notification.error({
message: '请选择工作空间'
message: this.$tl('p.selectWorkspace')
})
return false
}
@ -430,11 +444,11 @@ export default {
//
handleDelete(record) {
$confirm({
title: '系统提示',
title: this.$tl('c.systemTip'),
zIndex: 1009,
content: '真的要删除权限组么?',
okText: '确认',
cancelText: '取消',
content: this.$tl('p.confirmDelete'),
okText: this.$tl('c.confirm'),
cancelText: this.$tl('c.cancel'),
onOk: () => {
return deletePermissionGroup(record.id).then((res) => {
if (res.code === 200) {
@ -456,12 +470,11 @@ export default {
checkTipUserName() {
if (this.temp?.id === 'demo') {
$confirm({
title: '系统提示',
title: this.$tl('c.systemTip'),
zIndex: 1009,
content:
'demo 账号是系统特定演示使用的账号,系统默认将对 demo 账号限制很多权限。非演示场景不建议使用 demo 账号',
okText: '确认',
cancelText: '取消',
content: `demo ${this.$tl('p.demoAccountTip')},${this.$tl('p.demoAccountRestriction')}`,
okText: this.$tl('c.confirm'),
cancelText: this.$tl('c.cancel'),
onCancel: () => {
this.temp.id = ''

View File

@ -7,7 +7,7 @@
:auto-refresh-time="30"
:active-page="activePage"
table-name="systemUserLoginLog"
empty-description="没有任何登录日志"
:empty-description="$tl('p.noLoginLogs')"
:loading="loading"
:data-source="list"
:columns="columns"
@ -24,19 +24,19 @@
<a-space>
<a-input
v-model:value="listQuery['%modifyUser%']"
placeholder="用户名"
:placeholder="$tl('p.username')"
class="search-input-item"
@press-enter="loadData"
/>
<a-input
v-model:value="listQuery['%username%']"
placeholder="用户昵称"
:placeholder="$tl('p.nickname')"
class="search-input-item"
@press-enter="loadData"
/>
<a-input
v-model:value="listQuery['%ip%']"
placeholder="登录IP"
:placeholder="$tl('p.loginIp')"
class="search-input-item"
@press-enter="loadData"
/>
@ -47,8 +47,8 @@
format="YYYY-MM-DD HH:mm:ss"
@change="onChangeTime"
/>
<a-tooltip title="按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页">
<a-button type="primary" :loading="loading" @click="loadData">搜索</a-button>
<a-tooltip :title="$tl('p.goToFirstPage')">
<a-button type="primary" :loading="loading" @click="loadData">{{ $tl('p.search') }}</a-button>
</a-tooltip>
</a-space>
</template>
@ -58,16 +58,16 @@
</template>
<template v-if="column.dataIndex === 'success'">
<a-tag v-if="text" color="green">成功</a-tag>
<a-tag v-else color="pink">失败</a-tag>
<a-tag v-if="text" color="green">{{ $tl('p.success') }}</a-tag>
<a-tag v-else color="pink">{{ $tl('p.failure') }}</a-tag>
</template>
<template v-if="column.dataIndex === 'useMfa'">
<a-tag>{{ text ? '使用' : '未使用' }}</a-tag>
<a-tag>{{ text ? $tl('p.used') : $tl('p.unused') }}</a-tag>
</template>
<template v-if="column.dataIndex === 'operateCode'">
{{ operateCodeMap[text] || '未知' }}
{{ operateCodeMap[text] || $tl('p.unknown') }}
</template>
</template>
</CustomTable>
@ -79,6 +79,9 @@ import { IPageQuery } from '@/interface/common'
import { CustomColumnType } from '@/components/customTable/types'
import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY, parseTime } from '@/utils/const'
import { useI18nPage } from '@/i18n/hooks/useI18nPage'
const { $tl } = useI18nPage('pages.user.userLoginLog')
const loading = ref(false)
const list = ref([])
// const operateCode = operateCodeMap;
@ -91,36 +94,36 @@ const activePage = computed(() => {
})
const columns = ref<CustomColumnType[]>([
{ title: '用户ID', dataIndex: 'modifyUser', width: 100 },
{ title: '用户昵称', dataIndex: 'username', width: 120 },
{ title: $tl('p.userId'), dataIndex: 'modifyUser', width: 100 },
{ title: $tl('p.nickname'), dataIndex: 'username', width: 120 },
{ title: 'IP', dataIndex: 'ip', width: 120 },
{
title: '是否成功',
title: $tl('p.isSuccess'),
dataIndex: 'success',
width: 90,
align: 'center'
},
{
title: '是否使用MFA',
title: $tl('p.isMfaUsed'),
dataIndex: 'useMfa',
align: 'center',
width: 110
},
{
title: '结果描述',
title: $tl('p.resultDescription'),
dataIndex: 'operateCode',
ellipsis: true,
width: 180
},
{
title: '登录时间',
title: $tl('p.loginTime'),
dataIndex: 'createTimeMillis',
sorter: true,
customRender: ({ text, record }) => parseTime(text || record.optTime),
width: '170px'
},
{ title: '浏览器', dataIndex: 'userAgent', ellipsis: true, width: 100 }
{ title: $tl('p.browser'), dataIndex: 'userAgent', ellipsis: true, width: 100 }
])
const pagination = computed(() => {