mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-04 00:10:25 +08:00
feat: i18n
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
"@element-plus/icons-vue": "^2.3.1",
|
||||||
"@vueuse/core": "^11.1.0",
|
"@vueuse/core": "^11.2.0",
|
||||||
"asciinema-player": "^3.8.1",
|
"asciinema-player": "^3.8.1",
|
||||||
"axios": "^1.6.2",
|
"axios": "^1.6.2",
|
||||||
"clipboard": "^2.0.11",
|
"clipboard": "^2.0.11",
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"echarts": "^5.5.1",
|
"echarts": "^5.5.1",
|
||||||
"element-plus": "^2.8.6",
|
"element-plus": "^2.8.8",
|
||||||
"js-base64": "^3.7.7",
|
"js-base64": "^3.7.7",
|
||||||
"jsencrypt": "^3.3.2",
|
"jsencrypt": "^3.3.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
"monaco-sql-languages": "^0.12.2",
|
"monaco-sql-languages": "^0.12.2",
|
||||||
"monaco-themes": "^0.4.4",
|
"monaco-themes": "^0.4.4",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"pinia": "^2.2.5",
|
"pinia": "^2.2.6",
|
||||||
"qrcode.vue": "^3.5.1",
|
"qrcode.vue": "^3.5.1",
|
||||||
"screenfull": "^6.0.2",
|
"screenfull": "^6.0.2",
|
||||||
"sortablejs": "^1.15.3",
|
"sortablejs": "^1.15.3",
|
||||||
@@ -36,7 +36,8 @@
|
|||||||
"sql-formatter": "^15.4.5",
|
"sql-formatter": "^15.4.5",
|
||||||
"trzsz": "^1.1.5",
|
"trzsz": "^1.1.5",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
"vue": "^3.5.12",
|
"vue": "^3.5.13",
|
||||||
|
"vue-i18n": "^10.0.4",
|
||||||
"vue-router": "^4.4.5",
|
"vue-router": "^4.4.5",
|
||||||
"xterm": "^5.3.0",
|
"xterm": "^5.3.0",
|
||||||
"xterm-addon-fit": "^0.8.0",
|
"xterm-addon-fit": "^0.8.0",
|
||||||
@@ -51,16 +52,16 @@
|
|||||||
"@types/sortablejs": "^1.15.8",
|
"@types/sortablejs": "^1.15.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
||||||
"@typescript-eslint/parser": "^6.7.4",
|
"@typescript-eslint/parser": "^6.7.4",
|
||||||
"@vitejs/plugin-vue": "^5.1.4",
|
"@vitejs/plugin-vue": "^5.2.0",
|
||||||
"@vue/compiler-sfc": "^3.5.12",
|
"@vue/compiler-sfc": "^3.5.13",
|
||||||
"code-inspector-plugin": "^0.4.5",
|
"code-inspector-plugin": "^0.4.5",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"eslint": "^8.35.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-plugin-vue": "^9.28.0",
|
"eslint-plugin-vue": "^9.28.0",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"sass": "^1.80.5",
|
"sass": "^1.80.6",
|
||||||
"typescript": "^5.6.3",
|
"typescript": "^5.6.3",
|
||||||
"vite": "^5.4.10",
|
"vite": "^5.4.11",
|
||||||
"vue-eslint-parser": "^9.4.3"
|
"vue-eslint-parser": "^9.4.3"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<el-config-provider :size="getGlobalComponentSize" :locale="getGlobalI18n">
|
||||||
<div class="h100">
|
<div class="h100">
|
||||||
<el-watermark
|
<el-watermark
|
||||||
:zIndex="10000000"
|
:zIndex="10000000"
|
||||||
@@ -15,10 +16,11 @@
|
|||||||
<LockScreen v-if="themeConfig.isLockScreen" />
|
<LockScreen v-if="themeConfig.isLockScreen" />
|
||||||
<Setings ref="setingsRef" v-show="themeConfig.lockScreenTime !== 0" />
|
<Setings ref="setingsRef" v-show="themeConfig.lockScreenTime !== 0" />
|
||||||
</div>
|
</div>
|
||||||
|
</el-config-provider>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="app">
|
<script setup lang="ts" name="app">
|
||||||
import { ref, onMounted, onUnmounted, nextTick, watch } from 'vue';
|
import { ref, onMounted, onUnmounted, nextTick, watch, computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useThemeConfig } from '@/store/themeConfig';
|
import { useThemeConfig } from '@/store/themeConfig';
|
||||||
@@ -26,6 +28,10 @@ import LockScreen from '@/layout/lockScreen/index.vue';
|
|||||||
import Setings from '@/layout/navBars/breadcrumb/setings.vue';
|
import Setings from '@/layout/navBars/breadcrumb/setings.vue';
|
||||||
import mittBus from '@/common/utils/mitt';
|
import mittBus from '@/common/utils/mitt';
|
||||||
import { useIntervalFn } from '@vueuse/core';
|
import { useIntervalFn } from '@vueuse/core';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import EnumValue from './common/Enum';
|
||||||
|
import { I18nEnum } from './common/commonEnum';
|
||||||
|
import { saveThemeConfig } from './common/utils/storage';
|
||||||
|
|
||||||
const setingsRef = ref();
|
const setingsRef = ref();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@@ -33,6 +39,9 @@ const route = useRoute();
|
|||||||
const themeConfigStores = useThemeConfig();
|
const themeConfigStores = useThemeConfig();
|
||||||
const { themeConfig } = storeToRefs(themeConfigStores);
|
const { themeConfig } = storeToRefs(themeConfigStores);
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const { locale, t } = useI18n();
|
||||||
|
|
||||||
// 布局配置弹窗打开
|
// 布局配置弹窗打开
|
||||||
const openSetingsDrawer = () => {
|
const openSetingsDrawer = () => {
|
||||||
setingsRef.value.openDrawer();
|
setingsRef.value.openDrawer();
|
||||||
@@ -67,6 +76,31 @@ watch(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => themeConfig.value.globalI18n,
|
||||||
|
(val) => {
|
||||||
|
locale.value = val;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
themeConfig,
|
||||||
|
(val) => {
|
||||||
|
saveThemeConfig(val);
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 获取全局组件大小
|
||||||
|
const getGlobalComponentSize = computed(() => {
|
||||||
|
return themeConfig.value.globalComponentSize;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取全局 i18n
|
||||||
|
const getGlobalI18n = computed(() => {
|
||||||
|
return EnumValue.getEnumByValue(I18nEnum, locale.value)?.extra.el;
|
||||||
|
});
|
||||||
|
|
||||||
// 刷新水印时间
|
// 刷新水印时间
|
||||||
const { pause, resume } = useIntervalFn(() => {
|
const { pause, resume } = useIntervalFn(() => {
|
||||||
if (!themeConfig.value.isWatermark) {
|
if (!themeConfig.value.isWatermark) {
|
||||||
@@ -96,7 +130,7 @@ watch(
|
|||||||
() => route.path,
|
() => route.path,
|
||||||
() => {
|
() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
document.title = `${route.meta.title} - ${themeConfig.value.globalTitle}` || themeConfig.value.globalTitle;
|
document.title = `${t((route.meta.title as string) || '')} - ${themeConfig.value.globalTitle}` || themeConfig.value.globalTitle;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -5,6 +5,20 @@
|
|||||||
"css_prefix_text": "icon-",
|
"css_prefix_text": "icon-",
|
||||||
"description": "",
|
"description": "",
|
||||||
"glyphs": [
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "2967035",
|
||||||
|
"name": "符号-英文",
|
||||||
|
"font_class": "fuhao-yingwen",
|
||||||
|
"unicode": "e712",
|
||||||
|
"unicode_decimal": 59154
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26283783",
|
||||||
|
"name": "符号-中文",
|
||||||
|
"font_class": "fuhao-zhongwen",
|
||||||
|
"unicode": "e603",
|
||||||
|
"unicode_decimal": 58883
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"icon_id": "23957582",
|
"icon_id": "23957582",
|
||||||
"name": "MongoDB",
|
"name": "MongoDB",
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
import EnumValue from './Enum';
|
import EnumValue from './Enum';
|
||||||
|
// element plus 自带国际化
|
||||||
|
import zhcnLocale from 'element-plus/es/locale/lang/zh-cn';
|
||||||
|
import enLocale from 'element-plus/es/locale/lang/en';
|
||||||
|
|
||||||
|
// i18n
|
||||||
|
export const I18nEnum = {
|
||||||
|
ZhCn: EnumValue.of('zh-cn', '简体中文').setExtra({ icon: 'iconfont icon-fuhao-zhongwen', el: zhcnLocale }),
|
||||||
|
En: EnumValue.of('en', 'English').setExtra({ icon: 'iconfont icon-fuhao-yingwen', el: enLocale }),
|
||||||
|
};
|
||||||
|
|
||||||
// 资源类型
|
// 资源类型
|
||||||
export const ResourceTypeEnum = {
|
export const ResourceTypeEnum = {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export default {
|
|||||||
otpVerify: (param: any) => request.post('/auth/accounts/otp-verify', param),
|
otpVerify: (param: any) => request.post('/auth/accounts/otp-verify', param),
|
||||||
getPublicKey: () => request.get('/common/public-key'),
|
getPublicKey: () => request.get('/common/public-key'),
|
||||||
getConfigValue: (params: any) => request.get('/sys/configs/value', params),
|
getConfigValue: (params: any) => request.get('/sys/configs/value', params),
|
||||||
|
getServerConf: () => request.get('/sys/configs/server'),
|
||||||
oauth2LoginConfig: () => request.get('/auth/oauth2-config'),
|
oauth2LoginConfig: () => request.get('/auth/oauth2-config'),
|
||||||
changePwd: (param: any) => request.post('/sys/accounts/change-pwd', param),
|
changePwd: (param: any) => request.post('/sys/accounts/change-pwd', param),
|
||||||
captcha: () => request.get('/sys/captcha'),
|
captcha: () => request.get('/sys/captcha'),
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
import { i18n } from '@/i18n';
|
||||||
|
|
||||||
export const AccountUsernamePattern = {
|
export const AccountUsernamePattern = {
|
||||||
pattern: /^[a-zA-Z0-9_]{5,20}$/g,
|
pattern: /^[a-zA-Z0-9_]{5,16}$/g,
|
||||||
message: '只允许输入5-20位大小写字母、数字、_-.:',
|
message: i18n.global.t('system.account.usernamePatternErrMsg'),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ResourceCodePattern = {
|
export const ResourceCodePattern = {
|
||||||
pattern: /^[a-zA-Z0-9_\-.:]{1,32}$/g,
|
pattern: /^[a-zA-Z0-9_\-.:]{1,32}$/g,
|
||||||
message: '只允许输入1-32位大小写字母、数字、_-.:',
|
message: i18n.global.t('system.menu.resourceCodePatternErrMsg'),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -73,6 +73,15 @@ export async function getMachineConfig(): Promise<any> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取系统服务启动配置
|
||||||
|
*
|
||||||
|
* @returns 配置信息
|
||||||
|
*/
|
||||||
|
export async function getServerConf(): Promise<any> {
|
||||||
|
return openApi.getServerConf();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取系统配置值
|
* 获取系统配置值
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
import { getLocal } from '@/common/utils/storage';
|
|
||||||
|
|
||||||
// 全局组件大小
|
|
||||||
export const globalComponentSize = getLocal('themeConfig')?.globalComponentSize;
|
|
||||||
@@ -69,7 +69,7 @@ export function convertToBytes(sizeStr: string) {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function formatTime(time: number, unit: string = 's') {
|
export function formatTime(time: number, unit: string = 's') {
|
||||||
const units = {
|
const units: any = {
|
||||||
y: 31536000,
|
y: 31536000,
|
||||||
M: 2592000,
|
M: 2592000,
|
||||||
d: 86400,
|
d: 86400,
|
||||||
|
|||||||
@@ -177,3 +177,40 @@ export function isPrefixSubsequence(prefix: string, targetTemplate: string) {
|
|||||||
// 如果prefix的所有字符都被找到,返回true
|
// 如果prefix的所有字符都被找到,返回true
|
||||||
return i === prefix.length;
|
return i === prefix.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成随机密码
|
||||||
|
* @param length 密码长度
|
||||||
|
*/
|
||||||
|
export function randomPassword(length = 10) {
|
||||||
|
const lowerCase = 'abcdefghijklmnopqrstuvwxyz';
|
||||||
|
const upperCase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||||
|
const numbers = '0123456789';
|
||||||
|
const specialChars = '!@#$%^&*()-_=+[]{}|;:,.<>?';
|
||||||
|
|
||||||
|
// 确保每个类别至少包含一个字符
|
||||||
|
let password = [getRandomChar(lowerCase), getRandomChar(upperCase), getRandomChar(numbers), getRandomChar(specialChars)];
|
||||||
|
|
||||||
|
// 剩余字符从所有字符集中随机选择
|
||||||
|
const allChars = lowerCase + upperCase + numbers + specialChars;
|
||||||
|
for (let i = 4; i < length; i++) {
|
||||||
|
password.push(getRandomChar(allChars));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打乱数组顺序以增加随机性
|
||||||
|
shuffleArray(password);
|
||||||
|
|
||||||
|
return password.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRandomChar(charSet: string) {
|
||||||
|
const randomIndex = Math.floor(Math.random() * charSet.length);
|
||||||
|
return charSet[randomIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
function shuffleArray(array: string[]) {
|
||||||
|
for (let i = array.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
[array[i], array[j]] = [array[j], array[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
:is="`el-option`"
|
:is="`el-option`"
|
||||||
v-for="(col, index) in item.options"
|
v-for="(col, index) in item.options"
|
||||||
:key="index"
|
:key="index"
|
||||||
:label="col[fieldNames.label]"
|
:label="$t(col[fieldNames.label])"
|
||||||
:value="col[fieldNames.value]"
|
:value="col[fieldNames.value]"
|
||||||
></component>
|
></component>
|
||||||
</template>
|
</template>
|
||||||
@@ -28,6 +28,9 @@
|
|||||||
<script setup lang="ts" name="SearchFormItem">
|
<script setup lang="ts" name="SearchFormItem">
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { SearchItem } from '../index';
|
import { SearchItem } from '../index';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
interface SearchFormItemProps {
|
interface SearchFormItemProps {
|
||||||
item: SearchItem;
|
item: SearchItem;
|
||||||
@@ -70,7 +73,7 @@ const handleEvents = computed(() => {
|
|||||||
// 处理默认 placeholder
|
// 处理默认 placeholder
|
||||||
const placeholder = computed(() => {
|
const placeholder = computed(() => {
|
||||||
const search = props.item;
|
const search = props.item;
|
||||||
const label = search.label;
|
const label = t(search.label);
|
||||||
if (['datetimerange', 'daterange', 'monthrange'].includes(search?.props?.type) || search?.props?.isRange) {
|
if (['datetimerange', 'daterange', 'monthrange'].includes(search?.props?.type) || search?.props?.isRange) {
|
||||||
return {
|
return {
|
||||||
rangeSeparator: search?.props?.rangeSeparator ?? '至',
|
rangeSeparator: search?.props?.rangeSeparator ?? '至',
|
||||||
@@ -78,7 +81,9 @@ const placeholder = computed(() => {
|
|||||||
endPlaceholder: search?.props?.endPlaceholder ?? '结束时间',
|
endPlaceholder: search?.props?.endPlaceholder ?? '结束时间',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const placeholder = search?.props?.placeholder ?? (search?.type?.includes('input') ? `请输入${label}` : `请选择${label}`);
|
|
||||||
return { placeholder };
|
const placeholder =
|
||||||
|
search?.props?.placeholder ?? (search?.type?.includes('input') ? t('common.pleaseInput', { label }) : t('common.pleaseSelect', { label }));
|
||||||
|
return { placeholder: t(placeholder) };
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
@click="onCurrentContextmenuClick(v)"
|
@click="onCurrentContextmenuClick(v)"
|
||||||
>
|
>
|
||||||
<SvgIcon :name="v.icon" />
|
<SvgIcon :name="v.icon" />
|
||||||
<span>{{ v.txt }}</span>
|
<span>{{ $t(v.txt) }}</span>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -1,43 +1,43 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="crontab">
|
<div class="crontab">
|
||||||
<el-tabs v-model="state.activeName" @tab-change="changeTab(state.activeName)" type="border-card">
|
<el-tabs v-model="state.activeName" @tab-change="changeTab(state.activeName)" type="border-card">
|
||||||
<el-tab-pane label="秒" name="second" v-if="shouldHide('second')">
|
<el-tab-pane :label="$t('components.crontab.second')" name="second" v-if="shouldHide('second')">
|
||||||
<CrontabSecond :cron="crontabValueObj" ref="secondRef" />
|
<CrontabSecond :cron="crontabValueObj" ref="secondRef" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="分钟" name="min" v-if="shouldHide('min')">
|
<el-tab-pane :label="$t('components.crontab.minute')" name="min" v-if="shouldHide('min')">
|
||||||
<CrontabMin :cron="crontabValueObj" ref="minRef" />
|
<CrontabMin :cron="crontabValueObj" ref="minRef" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="小时" name="hour" v-if="shouldHide('hour')">
|
<el-tab-pane :label="$t('components.crontab.hour')" name="hour" v-if="shouldHide('hour')">
|
||||||
<CrontabHour :cron="crontabValueObj" ref="hourRef" />
|
<CrontabHour :cron="crontabValueObj" ref="hourRef" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="日" name="day" v-if="shouldHide('day')">
|
<el-tab-pane :label="$t('components.crontab.day')" name="day" v-if="shouldHide('day')">
|
||||||
<CrontabDay :cron="crontabValueObj" ref="dayRef" />
|
<CrontabDay :cron="crontabValueObj" ref="dayRef" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="月" name="mouth" v-if="shouldHide('mouth')">
|
<el-tab-pane :label="$t('components.crontab.month')" name="mouth" v-if="shouldHide('mouth')">
|
||||||
<CrontabMouth :cron="crontabValueObj" ref="mouthRef" />
|
<CrontabMouth :cron="crontabValueObj" ref="mouthRef" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="周" name="week" v-if="shouldHide('week')">
|
<el-tab-pane :label="$t('components.crontab.week')" name="week" v-if="shouldHide('week')">
|
||||||
<CrontabWeek :cron="crontabValueObj" ref="weekRef" />
|
<CrontabWeek :cron="crontabValueObj" ref="weekRef" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="年" name="year" v-if="shouldHide('year')">
|
<el-tab-pane :label="$t('components.crontab.year')" name="year" v-if="shouldHide('year')">
|
||||||
<CrontabYear :cron="crontabValueObj" ref="yearRef" />
|
<CrontabYear :cron="crontabValueObj" ref="yearRef" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
|
|
||||||
<div class="popup-main">
|
<div class="popup-main">
|
||||||
<div class="popup-result">
|
<div class="popup-result">
|
||||||
<p class="title">时间表达式</p>
|
<p class="title">{{ $t('components.crontab.timeExpression') }}</p>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th v-for="item of tabTitles" width="40" :key="item">{{ item }}</th>
|
<th v-for="item of tabTitles" width="40" :key="item">{{ item }}</th>
|
||||||
<th>crontab完整表达式</th>
|
<th>{{ $t('components.crontab.crontabCompleteExpression') }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -73,9 +73,9 @@
|
|||||||
<CrontabResult :ex="crontabValueString"></CrontabResult>
|
<CrontabResult :ex="crontabValueString"></CrontabResult>
|
||||||
|
|
||||||
<div class="pop_btn">
|
<div class="pop_btn">
|
||||||
<el-button size="small" @click="hidePopup">取消</el-button>
|
<el-button size="small" @click="hidePopup">{{ $t('common.cancel') }}</el-button>
|
||||||
<el-button size="small" type="warning" @click="clearCron">重置</el-button>
|
<el-button size="small" type="warning" @click="clearCron">{{ $t('common.reset') }}</el-button>
|
||||||
<el-button size="small" type="primary" @click="submitFill">确定</el-button>
|
<el-button size="small" type="primary" @click="submitFill">{{ $t('common.confirm') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,42 +1,45 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form size="small">
|
<el-form size="small">
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="1"> 日,允许的通配符[, - * / L M] </el-radio>
|
<el-radio v-model="radioValue" :label="1"> {{ $t('components.crontab.day') }},{{ $t('components.crontab.dayCrontype1') }} </el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="2"> 不指定 </el-radio>
|
<el-radio v-model="radioValue" :label="2"> {{ $t('components.crontab.crontype2') }} </el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="3">
|
<el-radio v-model="radioValue" :label="3">
|
||||||
周期从
|
{{ $t('components.crontab.crontype3') }}
|
||||||
<el-input-number v-model="cycle01" :min="0" :max="31" /> - <el-input-number v-model="cycle02" :min="0" :max="31" /> 日
|
<el-input-number v-model="cycle01" :min="0" :max="31" /> - <el-input-number v-model="cycle02" :min="0" :max="31" />
|
||||||
|
{{ $t('components.crontab.day') }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="4">
|
<el-radio v-model="radioValue" :label="4">
|
||||||
从
|
{{ $t('components.crontab.crontypeFrom') }}
|
||||||
<el-input-number v-model="average01" :min="0" :max="31" /> 号开始,每 <el-input-number v-model="average02" :min="0" :max="31" /> 日执行一次
|
<el-input-number v-model="average01" :min="0" :max="31" /> {{ $t('components.crontab.crontypeStartDay') }},
|
||||||
|
{{ $t('components.crontab.crontypeEvery') }} <el-input-number v-model="average02" :min="0" :max="31" />
|
||||||
|
{{ $t('components.crontab.crontypeExecDay') }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<!-- <el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="5">
|
<el-radio v-model="radioValue" :label="5">
|
||||||
每月
|
每月
|
||||||
<el-input-number v-model="workday" :min="0" :max="31" /> 号最近的那个工作日
|
<el-input-number v-model="workday" :min="0" :max="31" /> 号最近的那个工作日
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item> -->
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="6"> 本月最后一天 </el-radio>
|
<el-radio v-model="radioValue" :label="6"> {{ $t('components.crontab.monthLastDay') }} </el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<div class="flex-align-center w100">
|
<div class="flex-align-center w100">
|
||||||
<el-radio v-model="radioValue" :label="7" class="mr5"> 指定 </el-radio>
|
<el-radio v-model="radioValue" :label="7" class="mr5"> {{ $t('components.crontab.appoint') }} </el-radio>
|
||||||
<el-select @click="radioValue = 7" class="w100" clearable v-model="checkboxList" placeholder="可多选" multiple>
|
<el-select @click="radioValue = 7" class="w100" clearable v-model="checkboxList" multiple>
|
||||||
<el-option v-for="item in 31" :key="item" :value="`${item}`">{{ item }}</el-option>
|
<el-option v-for="item in 31" :key="item" :value="`${item}`">{{ item }}</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,27 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form size="small">
|
<el-form size="small">
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="1"> 小时,允许的通配符[, - * /] </el-radio>
|
<el-radio v-model="radioValue" :label="1"> {{ $t('components.crontab.hour') }},{{ $t('components.crontab.hourCronType1') }} </el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="2">
|
<el-radio v-model="radioValue" :label="2">
|
||||||
周期从
|
{{ $t('components.crontab.crontype3') }}
|
||||||
<el-input-number v-model="cycle01" :min="0" :max="60" /> - <el-input-number v-model="cycle02" :min="0" :max="60" /> 小时
|
<el-input-number v-model="cycle01" :min="0" :max="60" /> - <el-input-number v-model="cycle02" :min="0" :max="60" />
|
||||||
|
{{ $t('components.crontab.hour') }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="3">
|
<el-radio v-model="radioValue" :label="3">
|
||||||
从
|
{{ $t('components.crontab.crontypeFrom') }}
|
||||||
<el-input-number v-model="average01" :min="0" :max="60" /> 小时开始,每 <el-input-number v-model="average02" :min="0" :max="60" /> 小时执行一次
|
<el-input-number v-model="average01" :min="0" :max="60" /> {{ $t('components.crontab.crontypeStartHour') }},
|
||||||
|
{{ $t('components.crontab.crontypeEvery') }} <el-input-number v-model="average02" :min="0" :max="60" />
|
||||||
|
{{ $t('components.crontab.crontypeExecHour') }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<div class="flex-align-center w100">
|
<div class="flex-align-center w100">
|
||||||
<el-radio v-model="radioValue" :label="4" class="mr5"> 指定 </el-radio>
|
<el-radio v-model="radioValue" :label="4" class="mr5"> {{ $t('components.crontab.appoint') }} </el-radio>
|
||||||
<el-select @click="radioValue = 4" class="w100" clearable v-model="checkboxList" placeholder="可多选" multiple>
|
<el-select @click="radioValue = 4" class="w100" clearable v-model="checkboxList" multiple>
|
||||||
<el-option v-for="item in 60" :key="item" :value="`${item - 1}`">{{ item - 1 }}</el-option>
|
<el-option v-for="item in 60" :key="item" :value="`${item - 1}`">{{ item - 1 }}</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-input v-model="cron" placeholder="可点击左边按钮配置">
|
<el-input v-model="cron" :placeholder="$t('components.crontab.crontabInputPlaceholder')">
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<el-button @click="showCron = true" icon="Pointer"></el-button>
|
<el-button @click="showCron = true" icon="Pointer"></el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
<el-dialog title="生成 cron" v-model="showCron" width="600px">
|
<el-dialog :title="$t('components.crontab.crontabTitle')" v-model="showCron" width="660px">
|
||||||
<Crontab :expression="cron" @hide="showCron = false" @fill="(ex: any) => (cron = ex)" />
|
<Crontab :expression="cron" @hide="showCron = false" @fill="(ex: any) => (cron = ex)" />
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,27 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form size="small">
|
<el-form size="small">
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="1"> 分钟,允许的通配符[, - * /] </el-radio>
|
<el-radio v-model="radioValue" :label="1"> {{ $t('components.crontab.minute') }},{{ $t('components.crontab.hourCronType1') }} </el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="2">
|
<el-radio v-model="radioValue" :label="2">
|
||||||
周期从
|
{{ $t('components.crontab.crontype3') }}
|
||||||
<el-input-number v-model="cycle01" :min="0" :max="60" /> - <el-input-number v-model="cycle02" :min="0" :max="60" /> 分钟
|
<el-input-number v-model="cycle01" :min="0" :max="60" /> - <el-input-number v-model="cycle02" :min="0" :max="60" />
|
||||||
|
{{ $t('components.crontab.minute') }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="3">
|
<el-radio v-model="radioValue" :label="3">
|
||||||
从
|
{{ $t('components.crontab.crontypeFrom') }}
|
||||||
<el-input-number v-model="average01" :min="0" :max="60" /> 分钟开始,每 <el-input-number v-model="average02" :min="0" :max="60" /> 分钟执行一次
|
<el-input-number v-model="average01" :min="0" :max="60" /> {{ $t('components.crontab.crontypeStartMin') }},
|
||||||
|
{{ $t('components.crontab.crontypeEvery') }} <el-input-number v-model="average02" :min="0" :max="60" />
|
||||||
|
{{ $t('components.crontab.crontypeExecMin') }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<div class="flex-align-center w100">
|
<div class="flex-align-center w100">
|
||||||
<el-radio v-model="radioValue" :label="4" class="mr5"> 指定 </el-radio>
|
<el-radio v-model="radioValue" :label="4" class="mr5"> {{ $t('components.crontab.appoint') }} </el-radio>
|
||||||
<el-select @click="radioValue = 4" class="w100" clearable v-model="checkboxList" placeholder="可多选" multiple>
|
<el-select @click="radioValue = 4" class="w100" clearable v-model="checkboxList" multiple>
|
||||||
<el-option v-for="item in 60" :key="item" :value="`${item - 1}`">{{ item - 1 }}</el-option>
|
<el-option v-for="item in 60" :key="item" :value="`${item - 1}`">{{ item - 1 }}</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,27 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form size="small">
|
<el-form size="small">
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="1"> 月,允许的通配符[, - * /] </el-radio>
|
<el-radio v-model="radioValue" :label="1"> {{ $t('components.crontab.month') }},{{ $t('components.crontab.hourCronType1') }} </el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="2">
|
<el-radio v-model="radioValue" :label="2">
|
||||||
周期从
|
{{ $t('components.crontab.crontype3') }}
|
||||||
<el-input-number v-model="cycle01" :min="1" :max="12" /> - <el-input-number v-model="cycle02" :min="1" :max="12" /> 月
|
<el-input-number v-model="cycle01" :min="1" :max="12" /> - <el-input-number v-model="cycle02" :min="1" :max="12" />
|
||||||
|
{{ $t('components.crontab.month') }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="3">
|
<el-radio v-model="radioValue" :label="3">
|
||||||
从
|
{{ $t('components.crontab.crontypeFrom') }}
|
||||||
<el-input-number v-model="average01" :min="1" :max="12" /> 月开始,每 <el-input-number v-model="average02" :min="1" :max="12" /> 月月执行一次
|
<el-input-number v-model="average01" :min="1" :max="12" /> {{ $t('components.crontab.crontypeStartMonth') }},
|
||||||
|
{{ $t('components.crontab.crontypeEvery') }}
|
||||||
|
<el-input-number v-model="average02" :min="1" :max="12" /> {{ $t('components.crontab.crontypeExecMonth') }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<div class="flex-align-center w100">
|
<div class="flex-align-center w100">
|
||||||
<el-radio v-model="radioValue" :label="4" class="mr5"> 指定 </el-radio>
|
<el-radio v-model="radioValue" :label="4" class="mr5"> {{ $t('components.crontab.appoint') }} </el-radio>
|
||||||
<el-select @click="radioValue = 4" class="w100" clearable v-model="checkboxList" placeholder="可多选" multiple>
|
<el-select @click="radioValue = 4" class="w100" clearable v-model="checkboxList" multiple>
|
||||||
<el-option v-for="item in 12" :key="item" :value="`${item}`">{{ item }}</el-option>
|
<el-option v-for="item in 12" :key="item" :value="`${item}`">{{ item }}</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="popup-result">
|
<div class="popup-result">
|
||||||
<p class="title">最近5次运行时间</p>
|
<p class="title">{{ $t('components.crontab.last5runTimes') }}</p>
|
||||||
<ul class="popup-result-scroll">
|
<ul class="popup-result-scroll">
|
||||||
<template v-if="isShow">
|
<template v-if="isShow">
|
||||||
<li v-for="item in resultList" :key="item">{{ item }}</li>
|
<li v-for="item in resultList" :key="item">{{ item }}</li>
|
||||||
</template>
|
</template>
|
||||||
<li v-else>计算结果中...</li>
|
<li v-else>{{ $t('components.crontab.calculationing') }}...</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,27 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form size="small">
|
<el-form size="small">
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="1"> 秒,允许的通配符[, - * /] </el-radio>
|
<el-radio v-model="radioValue" :label="1"> {{ $t('components.crontab.second') }},{{ $t('components.crontab.hourCronType1') }} </el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="2">
|
<el-radio v-model="radioValue" :label="2">
|
||||||
周期从
|
{{ $t('components.crontab.crontype3') }}
|
||||||
<el-input-number v-model="cycle01" :min="0" :max="60" /> - <el-input-number v-model="cycle02" :min="0" :max="60" /> 秒
|
<el-input-number v-model="cycle01" :min="0" :max="60" /> - <el-input-number v-model="cycle02" :min="0" :max="60" />
|
||||||
|
{{ $t('components.crontab.second') }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="3">
|
<el-radio v-model="radioValue" :label="3">
|
||||||
从
|
{{ $t('components.crontab.crontypeFrom') }}
|
||||||
<el-input-number v-model="average01" :min="0" :max="60" /> 秒开始,每 <el-input-number v-model="average02" :min="0" :max="60" /> 秒执行一次
|
<el-input-number v-model="average01" :min="0" :max="60" /> {{ $t('components.crontab.crontypeStartSecond') }},
|
||||||
|
{{ $t('components.crontab.crontypeEvery') }}<el-input-number v-model="average02" :min="0" :max="60" />
|
||||||
|
{{ $t('components.crontab.crontypeExecSecond') }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<div class="flex-align-center w100">
|
<div class="flex-align-center w100">
|
||||||
<el-radio v-model="radioValue" :label="4" class="mr5"> 指定 </el-radio>
|
<el-radio v-model="radioValue" :label="4" class="mr5"> {{ $t('components.crontab.appoint') }} </el-radio>
|
||||||
<el-select @click="radioValue = 4" class="w100" clearable v-model="checkboxList" placeholder="可多选" multiple>
|
<el-select @click="radioValue = 4" class="w100" clearable v-model="checkboxList" multiple>
|
||||||
<el-option v-for="item in 60" :key="item" :value="`${item - 1}`">{{ item - 1 }}</el-option>
|
<el-option v-for="item in 60" :key="item" :value="`${item - 1}`">{{ item - 1 }}</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form size="small">
|
<el-form size="small">
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="1"> 周,允许的通配符[, - * / L #] </el-radio>
|
<el-radio v-model="radioValue" :label="1"> {{ $t('components.crontab.weekCronType1') }} </el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="2"> 不指定 </el-radio>
|
<el-radio v-model="radioValue" :label="2"> {{ $t('components.crontab.crontype2') }} </el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="3">
|
<el-radio v-model="radioValue" :label="3">
|
||||||
周期从星期
|
{{ $t('components.crontab.crontype3') }}
|
||||||
<el-input-number v-model="cycle01" :min="1" :max="7" /> -
|
<el-input-number v-model="cycle01" :min="1" :max="7" /> -
|
||||||
<el-input-number v-model="cycle02" :min="1" :max="7" />
|
<el-input-number v-model="cycle02" :min="1" :max="7" />
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<!-- <el-form-item>
|
||||||
<el-radio v-model="radioValue" :label="4">
|
<el-radio v-model="radioValue" :label="4">
|
||||||
第
|
第
|
||||||
<el-input-number v-model="average01" :min="1" :max="4" /> 周的星期
|
<el-input-number v-model="average01" :min="1" :max="4" /> 周的星期
|
||||||
@@ -29,13 +29,13 @@
|
|||||||
本月最后一个星期
|
本月最后一个星期
|
||||||
<el-input-number v-model="weekday" :min="1" :max="7" />
|
<el-input-number v-model="weekday" :min="1" :max="7" />
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item> -->
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<div class="flex-align-center w100">
|
<div class="flex-align-center w100">
|
||||||
<el-radio v-model="radioValue" :label="6" class="mr5"> 指定 </el-radio>
|
<el-radio v-model="radioValue" :label="6" class="mr5"> {{ $t('components.crontab.appoint') }} </el-radio>
|
||||||
<el-select @click="radioValue = 6" class="w100" clearable v-model="checkboxList" placeholder="可多选" multiple>
|
<el-select @click="radioValue = 6" class="w100" clearable v-model="checkboxList" multiple>
|
||||||
<el-option v-for="(item, index) of weekList" :label="item" :key="index" :value="`${index + 1}`">{{ item }}</el-option>
|
<el-option v-for="(item, index) of weekList" :label="item" :key="index" :value="`${index + 1}`">{{ $t(item) }}</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -56,7 +56,15 @@ const state = reactive({
|
|||||||
average01: 1,
|
average01: 1,
|
||||||
average02: 1,
|
average02: 1,
|
||||||
checkboxList: [] as any,
|
checkboxList: [] as any,
|
||||||
weekList: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
|
weekList: [
|
||||||
|
'components.crontab.monday',
|
||||||
|
'components.crontab.tuesday',
|
||||||
|
'components.crontab.wednesday',
|
||||||
|
'components.crontab.thursday',
|
||||||
|
'components.crontab.friday',
|
||||||
|
'components.crontab.saturday',
|
||||||
|
'components.crontab.sunday',
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const { radioValue, cycle01, cycle02, average01, average02, checkboxList, weekday, weekList } = toRefs(state);
|
const { radioValue, cycle01, cycle02, average01, average02, checkboxList, weekday, weekList } = toRefs(state);
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form size="small">
|
<el-form size="small">
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio :label="1" v-model="radioValue"> 不填,允许的通配符[, - * /] </el-radio>
|
<el-radio :label="1" v-model="radioValue"> {{ $t('components.crontab.hourCronType1') }} </el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio :label="2" v-model="radioValue"> 每年 </el-radio>
|
<el-radio :label="2" v-model="radioValue"> {{ $t('components.crontab.yearly') }} </el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio :label="3" v-model="radioValue">
|
<el-radio :label="3" v-model="radioValue">
|
||||||
周期从
|
{{ $t('components.crontab.crontype3') }}
|
||||||
<el-input-number v-model="cycle01" :min="fullYear" /> -
|
<el-input-number v-model="cycle01" :min="fullYear" /> -
|
||||||
<el-input-number v-model="cycle02" :min="fullYear" />
|
<el-input-number v-model="cycle02" :min="fullYear" />
|
||||||
</el-radio>
|
</el-radio>
|
||||||
@@ -18,15 +18,17 @@
|
|||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio :label="4" v-model="radioValue">
|
<el-radio :label="4" v-model="radioValue">
|
||||||
从
|
{{ $t('components.crontab.crontypeFrom') }}
|
||||||
<el-input-number v-model="average01" :min="fullYear" /> 年开始,每 <el-input-number v-model="average02" :min="fullYear" /> 年执行一次
|
<el-input-number v-model="average01" :min="fullYear" /> {{ $t('components.crontab.crontypeStartYear') }},
|
||||||
|
{{ $t('components.crontab.crontypeEvery') }}
|
||||||
|
<el-input-number v-model="average02" :min="fullYear" /> {{ $t('components.crontab.crontypeExecYear') }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<div class="flex-align-center w100">
|
<div class="flex-align-center w100">
|
||||||
<el-radio v-model="radioValue" :label="5" class="mr5"> 指定 </el-radio>
|
<el-radio v-model="radioValue" :label="5" class="mr5"> {{ $t('components.crontab.appoint') }} </el-radio>
|
||||||
<el-select @click="radioValue = 5" class="w100" clearable v-model="checkboxList" placeholder="可多选" multiple>
|
<el-select @click="radioValue = 5" class="w100" clearable v-model="checkboxList" multiple>
|
||||||
<el-option v-for="item in 9" :key="item" :value="`${item - 1 + fullYear}`" :label="item - 1 + fullYear" />
|
<el-option v-for="item in 9" :key="item" :value="`${item - 1 + fullYear}`" :label="item - 1 + fullYear" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="dynamic-form">
|
<div class="dynamic-form">
|
||||||
<el-form v-bind="$attrs" ref="formRef" :model="modelValue" label-width="auto">
|
<el-form v-bind="$attrs" ref="formRef" :model="modelValue" label-width="auto">
|
||||||
<el-form-item v-for="item in props.formItems as any" :key="item.name" :prop="item.model" :label="item.name" :required="item.required ?? true">
|
<el-form-item v-for="item in props.formItems as any" :key="item.name" :prop="item.model" :label="$t(item.name)" :required="item.required ?? true">
|
||||||
<el-input v-if="!item.options" v-model="modelValue[item.model]" :placeholder="item.placeholder" autocomplete="off" clearable></el-input>
|
<el-input v-if="!item.options" v-model="modelValue[item.model]" :placeholder="$t(item.placeholder)" autocomplete="off" clearable></el-input>
|
||||||
|
|
||||||
<el-select v-else v-model="modelValue[item.model]" :placeholder="item.placeholder" filterable autocomplete="off" clearable style="width: 100%">
|
<el-select
|
||||||
|
v-else
|
||||||
|
v-model="modelValue[item.model]"
|
||||||
|
:placeholder="$t(item.placeholder)"
|
||||||
|
filterable
|
||||||
|
autocomplete="off"
|
||||||
|
clearable
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
<el-option v-for="option in item.options.split(',')" :key="option" :label="option" :value="option" />
|
<el-option v-for="option in item.options.split(',')" :key="option" :label="option" :value="option" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<span>
|
<span>
|
||||||
<slot name="btns">
|
<slot name="btns">
|
||||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
<el-button @click="dialogVisible = false">{{ $t('common.cancel') }}</el-button>
|
||||||
<el-button type="primary" @click="confirm">确 定</el-button>
|
<el-button type="primary" @click="confirm">{{ $t('common.confirm') }}</el-button>
|
||||||
</slot>
|
</slot>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,41 +1,41 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="dynamic-form-edit w100">
|
<div class="dynamic-form-edit w100">
|
||||||
<el-table :data="formItems" stripe class="w100" empty-text="暂无表单项">
|
<el-table :data="formItems" stripe class="w100">
|
||||||
<el-table-column prop="name" label="model" min-width="100px">
|
<el-table-column prop="name" label="model" min-width="100px">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-button class="ml0" type="primary" circle size="small" icon="Plus" @click="addItem()"> </el-button>
|
<el-button class="ml0" type="primary" circle size="small" icon="Plus" @click="addItem()"> </el-button>
|
||||||
<span class="ml10">model</span>
|
<span class="ml10">model field</span>
|
||||||
</template>
|
</template>
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-input v-model="scope.row['model']" placeholder="字段model" clearable> </el-input>
|
<el-input v-model="scope.row['model']" :placeholder="$t('components.df.fieldModelPlaceholder')" clearable> </el-input>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column prop="name" label="label" min-width="100px">
|
<el-table-column prop="name" :label="$t('components.df.fieldLabel')" min-width="100px">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-input v-model="scope.row['name']" placeholder="字段title" clearable> </el-input>
|
<el-input v-model="scope.row['name']" clearable> </el-input>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column prop="placeholder" label="字段说明" min-width="140px">
|
<el-table-column prop="placeholder" :label="$t('components.df.fieldPlaceholder')" min-width="140px">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-input v-model="scope.row['placeholder']" placeholder="字段说明" clearable> </el-input>
|
<el-input v-model="scope.row['placeholder']" clearable> </el-input>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column prop="options" label="可选值" min-width="140px">
|
<el-table-column prop="options" :label="$t('components.df.optionalValues')" min-width="140px">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-input v-model="scope.row['options']" placeholder="可选值 ,分割" clearable> </el-input>
|
<el-input v-model="scope.row['options']" :placeholder="$t('components.df.optionalValuesPlaceholder')" clearable> </el-input>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column prop="required" label="必填" min-width="40px">
|
<el-table-column prop="required" :label="$t('components.df.required')" min-width="65px">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-checkbox v-model="scope.row['required']" />
|
<el-checkbox v-model="scope.row['required']" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column label="操作" wdith="20px">
|
<el-table-column :label="$t('common.operation')" wdith="20px">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button type="danger" @click="deleteItem(scope.$index)" icon="delete" plain></el-button>
|
<el-button type="danger" @click="deleteItem(scope.$index)" icon="delete" plain></el-button>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-select v-bind="$attrs" v-model="modelValue">
|
<el-select v-bind="$attrs" v-model="modelValue">
|
||||||
<el-option v-for="item in props.enums" :key="item.value" :label="item.label" :value="item.value"> </el-option>
|
<el-option v-for="item in props.enums" :key="item.value" :label="$t(item.label)" :value="item.value"> </el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-tag :disable-transitions="true" v-bind="$attrs" :type="type" :color="color" effect="plain">{{ enumLabel }}</el-tag>
|
<el-tag :disable-transitions="true" v-bind="$attrs" :type="type" :color="color" effect="plain">{{ $t(enumLabel) }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
<div>
|
<div>
|
||||||
<transition name="el-zoom-in-top">
|
<transition name="el-zoom-in-top">
|
||||||
<!-- 查询表单 -->
|
<!-- 查询表单 -->
|
||||||
<SearchForm v-if="isShowSearch" :items="tableSearchItems" v-model="queryForm" :search="search" :reset="reset" :search-col="searchCol">
|
<SearchForm v-if="isShowSearch" :items="tableSearchItems" v-model="queryForm" :search="search"
|
||||||
|
:reset="reset" :search-col="searchCol">
|
||||||
<!-- 遍历父组件传入的 solts 透传给子组件 -->
|
<!-- 遍历父组件传入的 solts 透传给子组件 -->
|
||||||
<template v-for="(_, key) in useSlots()" v-slot:[key]>
|
<template v-for="(_, key) in useSlots()" v-slot:[key]>
|
||||||
<slot :name="key"></slot>
|
<slot :name="key"></slot>
|
||||||
@@ -27,54 +28,45 @@
|
|||||||
<SvgIcon :size="16" name="CaretBottom" class="mr4 mt6 simple-search-form-btn" />
|
<SvgIcon :size="16" name="CaretBottom" class="mr4 mt6 simple-search-form-btn" />
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item
|
<el-dropdown-item v-for="searchItem in searchItems"
|
||||||
v-for="searchItem in searchItems"
|
:key="searchItem.prop" @click="changeSimpleFormItem(searchItem)">
|
||||||
:key="searchItem.prop"
|
{{ $t(searchItem.label) }}
|
||||||
@click="changeSimpleFormItem(searchItem)"
|
|
||||||
>
|
|
||||||
{{ searchItem.label }}
|
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
|
|
||||||
<div class="simple-search-form-label mt5">
|
<div class="simple-search-form-label mt5">
|
||||||
<el-text truncated tag="b">{{ `${nowSearchItem?.label} : ` }}</el-text>
|
<el-text truncated tag="b">{{ `${$t(nowSearchItem?.label)} : ` }}</el-text>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-form-item style="width: 200px" :key="nowSearchItem.prop">
|
<el-form-item style="width: 200px" :key="nowSearchItem.prop">
|
||||||
<SearchFormItem
|
<SearchFormItem @keyup.enter.native="searchFormItemKeyUpEnter"
|
||||||
@keyup.enter.native="searchFormItemKeyUpEnter"
|
v-if="!nowSearchItem.slot" :item="nowSearchItem"
|
||||||
v-if="!nowSearchItem.slot"
|
v-model="queryForm[nowSearchItem.prop]" />
|
||||||
:item="nowSearchItem"
|
|
||||||
v-model="queryForm[nowSearchItem.prop]"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<slot @keyup.enter.native="searchFormItemKeyUpEnter" v-else :name="nowSearchItem.slot"></slot>
|
<slot @keyup.enter.native="searchFormItemKeyUpEnter" v-else
|
||||||
|
:name="nowSearchItem.slot">
|
||||||
|
</slot>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<el-button v-if="showToolButton('search') && searchItems?.length" icon="Search" circle @click="search" />
|
<el-button v-if="showToolButton('search') && searchItems?.length" icon="Search"
|
||||||
|
circle @click="search" />
|
||||||
|
|
||||||
<!-- <el-button v-if="showToolButton('refresh')" icon="Refresh" circle @click="execQuery()" /> -->
|
<!-- <el-button v-if="showToolButton('refresh')" icon="Refresh" circle @click="execQuery()" /> -->
|
||||||
|
|
||||||
<el-button
|
<el-button v-if="showToolButton('search') && searchItems?.length > 1"
|
||||||
v-if="showToolButton('search') && searchItems?.length > 1"
|
:icon="isShowSearch ? 'ArrowDown' : 'ArrowUp'" circle
|
||||||
:icon="isShowSearch ? 'ArrowDown' : 'ArrowUp'"
|
@click="isShowSearch = !isShowSearch" />
|
||||||
circle
|
|
||||||
@click="isShowSearch = !isShowSearch"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<el-popover
|
<el-popover placement="bottom" title="表格配置"
|
||||||
placement="bottom"
|
popper-style="max-height: 550px; overflow: auto; max-width: 450px" width="auto"
|
||||||
title="表格配置"
|
trigger="click">
|
||||||
popper-style="max-height: 550px; overflow: auto; max-width: 450px"
|
|
||||||
width="auto"
|
|
||||||
trigger="click"
|
|
||||||
>
|
|
||||||
<div v-for="(item, index) in tableColumns" :key="index">
|
<div v-for="(item, index) in tableColumns" :key="index">
|
||||||
<el-checkbox v-model="item.show" :label="item.label" :true-value="true" :false-value="false" />
|
<el-checkbox v-model="item.show" :label="item.label" :true-value="true"
|
||||||
|
:false-value="false" />
|
||||||
</div>
|
</div>
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button icon="Operation" circle :size="props.size"></el-button>
|
<el-button icon="Operation" circle :size="props.size"></el-button>
|
||||||
@@ -86,33 +78,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-table
|
<el-table ref="tableRef" v-bind="$attrs" :max-height="tableMaxHeight"
|
||||||
ref="tableRef"
|
@selection-change="handleSelectionChange" :data="tableData" highlight-current-row
|
||||||
v-bind="$attrs"
|
v-loading="loading" :size="props.size as any" :border="border">
|
||||||
:max-height="tableMaxHeight"
|
|
||||||
@selection-change="handleSelectionChange"
|
|
||||||
:data="tableData"
|
|
||||||
highlight-current-row
|
|
||||||
v-loading="loading"
|
|
||||||
:size="props.size as any"
|
|
||||||
:border="border"
|
|
||||||
>
|
|
||||||
<el-table-column v-if="props.showSelection" :selectable="selectable" type="selection" width="40" />
|
<el-table-column v-if="props.showSelection" :selectable="selectable" type="selection" width="40" />
|
||||||
|
|
||||||
<template v-for="(item, index) in tableColumns">
|
<template v-for="(item, index) in tableColumns">
|
||||||
<el-table-column
|
<el-table-column :key="index" v-if="item.show" :prop="item.prop" :label="$t(item.label)"
|
||||||
:key="index"
|
:fixed="item.fixed" :align="item.align" :show-overflow-tooltip="item.showOverflowTooltip"
|
||||||
v-if="item.show"
|
:min-width="item.minWidth" :sortable="item.sortable || false" :type="item.type"
|
||||||
:prop="item.prop"
|
:width="item.width">
|
||||||
:label="item.label"
|
|
||||||
:fixed="item.fixed"
|
|
||||||
:align="item.align"
|
|
||||||
:show-overflow-tooltip="item.showOverflowTooltip"
|
|
||||||
:min-width="item.minWidth"
|
|
||||||
:sortable="item.sortable || false"
|
|
||||||
:type="item.type"
|
|
||||||
:width="item.width"
|
|
||||||
>
|
|
||||||
<!-- 插槽:预留功能 -->
|
<!-- 插槽:预留功能 -->
|
||||||
<template #default="scope" v-if="item.slot">
|
<template #default="scope" v-if="item.slot">
|
||||||
<slot :name="item.slotName ? item.slotName : item.prop" :data="scope.row"></slot>
|
<slot :name="item.slotName ? item.slotName : item.prop" :data="scope.row"></slot>
|
||||||
@@ -120,29 +95,21 @@
|
|||||||
|
|
||||||
<!-- 枚举类型使用tab展示 -->
|
<!-- 枚举类型使用tab展示 -->
|
||||||
<template #default="scope" v-else-if="item.type == 'tag'">
|
<template #default="scope" v-else-if="item.type == 'tag'">
|
||||||
<enum-tag :size="props.size" :enums="item.typeParam" :value="item.getValueByData(scope.row)"></enum-tag>
|
<enum-tag :size="props.size" :enums="item.typeParam"
|
||||||
|
:value="item.getValueByData(scope.row)"></enum-tag>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #default="scope" v-else>
|
<template #default="scope" v-else>
|
||||||
<!-- 配置了美化文本按钮以及文本内容大于指定长度,则显示美化按钮 -->
|
<!-- 配置了美化文本按钮以及文本内容大于指定长度,则显示美化按钮 -->
|
||||||
<el-popover
|
<el-popover v-if="item.isBeautify && item.getValueByData(scope.row)?.length > 35"
|
||||||
v-if="item.isBeautify && item.getValueByData(scope.row)?.length > 35"
|
effect="light" trigger="click" placement="top" width="600px">
|
||||||
effect="light"
|
|
||||||
trigger="click"
|
|
||||||
placement="top"
|
|
||||||
width="600px"
|
|
||||||
>
|
|
||||||
<template #default>
|
<template #default>
|
||||||
<el-input :autosize="{ minRows: 3, maxRows: 15 }" disabled v-model="formatVal" type="textarea" />
|
<el-input :autosize="{ minRows: 3, maxRows: 15 }" disabled v-model="formatVal"
|
||||||
|
type="textarea" />
|
||||||
</template>
|
</template>
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-link
|
<el-link @click="formatText(item.getValueByData(scope.row))" :underline="false"
|
||||||
@click="formatText(item.getValueByData(scope.row))"
|
type="success" icon="MagicStick" class="mr5"></el-link>
|
||||||
:underline="false"
|
|
||||||
type="success"
|
|
||||||
icon="MagicStick"
|
|
||||||
class="mr5"
|
|
||||||
></el-link>
|
|
||||||
</template>
|
</template>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
|
|
||||||
@@ -154,17 +121,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-row v-if="props.pageable" class="mt20" type="flex" justify="end">
|
<el-row v-if="props.pageable" class="mt20" type="flex" justify="end">
|
||||||
<el-pagination
|
<el-pagination :small="props.size == 'small'" @current-change="pageNumChange"
|
||||||
:small="props.size == 'small'"
|
@size-change="pageSizeChange" style="text-align: right" layout="prev, pager, next, total, sizes"
|
||||||
@current-change="pageNumChange"
|
:total="total" v-model:current-page="queryForm.pageNum" v-model:page-size="queryForm.pageSize"
|
||||||
@size-change="pageSizeChange"
|
:page-sizes="pageSizes" />
|
||||||
style="text-align: right"
|
|
||||||
layout="prev, pager, next, total, sizes"
|
|
||||||
:total="total"
|
|
||||||
v-model:current-page="queryForm.pageNum"
|
|
||||||
v-model:page-size="queryForm.pageSize"
|
|
||||||
:page-sizes="pageSizes"
|
|
||||||
/>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -185,6 +145,7 @@ import SvgIcon from '@/components/svgIcon/index.vue';
|
|||||||
import { usePageTable } from '@/hooks/usePageTable';
|
import { usePageTable } from '@/hooks/usePageTable';
|
||||||
import { ElTable } from 'element-plus';
|
import { ElTable } from 'element-plus';
|
||||||
|
|
||||||
|
|
||||||
const emit = defineEmits(['update:selectionData', 'pageSizeChange', 'pageNumChange']);
|
const emit = defineEmits(['update:selectionData', 'pageSizeChange', 'pageNumChange']);
|
||||||
|
|
||||||
export interface PageTableProps {
|
export interface PageTableProps {
|
||||||
@@ -377,6 +338,7 @@ defineExpose({
|
|||||||
// 表格 header 样式
|
// 表格 header 样式
|
||||||
.table-header {
|
.table-header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.header-button-lf {
|
.header-button-lf {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
@@ -445,7 +407,7 @@ defineExpose({
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// 设置 el-table 中 header 文字不换行,并省略
|
// 设置 el-table 中 header 文字不换行,并省略
|
||||||
.el-table__header .el-table__cell > .cell {
|
.el-table__header .el-table__cell>.cell {
|
||||||
// white-space: nowrap;
|
// white-space: nowrap;
|
||||||
white-space: wrap;
|
white-space: wrap;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import EnumValue from '@/common/Enum';
|
|||||||
import { formatDate } from '@/common/utils/format';
|
import { formatDate } from '@/common/utils/format';
|
||||||
import { getValueByPath } from '@/common/utils/object';
|
import { getValueByPath } from '@/common/utils/object';
|
||||||
import { getTextWidth } from '@/common/utils/string';
|
import { getTextWidth } from '@/common/utils/string';
|
||||||
|
import { i18n } from '@/i18n';
|
||||||
|
|
||||||
export class TableColumn {
|
export class TableColumn {
|
||||||
/**
|
/**
|
||||||
@@ -183,7 +184,7 @@ export class TableColumn {
|
|||||||
*/
|
*/
|
||||||
isEnum(enums: any): TableColumn {
|
isEnum(enums: any): TableColumn {
|
||||||
this.setFormatFunc((data: any, prop: string) => {
|
this.setFormatFunc((data: any, prop: string) => {
|
||||||
return EnumValue.getLabelByValue(enums, getValueByPath(data, prop));
|
return i18n.global.t(EnumValue.getLabelByValue(enums, getValueByPath(data, prop)));
|
||||||
});
|
});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -243,7 +244,7 @@ export class TableColumn {
|
|||||||
// 需要加上表格的内间距等,视情况加
|
// 需要加上表格的内间距等,视情况加
|
||||||
const contentWidth: number = getTextWidth(maxWidthText) + 30;
|
const contentWidth: number = getTextWidth(maxWidthText) + 30;
|
||||||
// 获取label的宽度,取较大的宽度
|
// 获取label的宽度,取较大的宽度
|
||||||
const columnWidth: number = getTextWidth(label) + 60;
|
const columnWidth: number = getTextWidth(i18n.global.t(label)) + 60;
|
||||||
const flexWidth: number = contentWidth > columnWidth ? contentWidth : columnWidth;
|
const flexWidth: number = contentWidth > columnWidth ? contentWidth : columnWidth;
|
||||||
// 设置上限与累加需要额外增加的宽度
|
// 设置上限与累加需要额外增加的宽度
|
||||||
this.minWidth = (flexWidth > 400 ? 400 : flexWidth) + this.addWidth;
|
this.minWidth = (flexWidth > 400 ? 400 : flexWidth) + this.addWidth;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<el-input v-model="state.modelValue" type="textarea" :rows="20" />
|
<el-input v-model="state.modelValue" type="textarea" :rows="20" />
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button type="primary" @click="onsubmit">确 定</el-button>
|
<el-button type="primary" @click="onsubmit">{{ $t('common.confirm') }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ import { TerminalStatus } from './common';
|
|||||||
import { useEventListener } from '@vueuse/core';
|
import { useEventListener } from '@vueuse/core';
|
||||||
import themes from './themes';
|
import themes from './themes';
|
||||||
import { TrzszFilter } from 'trzsz';
|
import { TrzszFilter } from 'trzsz';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
// mounted时,是否执行init方法
|
// mounted时,是否执行init方法
|
||||||
@@ -166,7 +169,7 @@ function initSocket() {
|
|||||||
|
|
||||||
// 监听socket错误信息
|
// 监听socket错误信息
|
||||||
socket.onerror = (e: Event) => {
|
socket.onerror = (e: Event) => {
|
||||||
term.writeln('\r\n\x1b[31m提示: 连接错误...');
|
term.writeln(`\r\n\x1b[31m${t('components.terminal.connErrMsg')}`);
|
||||||
state.status = TerminalStatus.Error;
|
state.status = TerminalStatus.Error;
|
||||||
console.log('连接错误', e);
|
console.log('连接错误', e);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="terminal-dialog-container" v-for="openTerminal of terminals" :key="openTerminal.terminalId">
|
<div class="terminal-dialog-container" v-for="openTerminal of terminals" :key="openTerminal.terminalId">
|
||||||
<el-dialog
|
<el-dialog
|
||||||
title="SSH终端"
|
title="SSH Terminal"
|
||||||
v-model="openTerminal.visible"
|
v-model="openTerminal.visible"
|
||||||
top="32px"
|
top="32px"
|
||||||
class="terminal-dialog"
|
class="terminal-dialog"
|
||||||
@@ -26,11 +26,13 @@
|
|||||||
|
|
||||||
<!-- 右侧 -->
|
<!-- 右侧 -->
|
||||||
<div class="title-right-fixed">
|
<div class="title-right-fixed">
|
||||||
<el-popconfirm @confirm="reConnect(openTerminal.terminalId)" title="确认重新连接?">
|
<el-popconfirm @confirm="reConnect(openTerminal.terminalId)" :title="$t('components.terminal.connConfirm')">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<div class="mr15 pointer">
|
<div class="mr15 pointer">
|
||||||
<el-tag v-if="openTerminal.status == TerminalStatus.Connected" type="success" effect="light" round> 已连接 </el-tag>
|
<el-tag v-if="openTerminal.status == TerminalStatus.Connected" type="success" effect="light" round>
|
||||||
<el-tag v-else type="danger" effect="light" round> 未连接 </el-tag>
|
{{ $t('components.terminal.connected') }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-else type="danger" effect="light" round> {{ $t('components.terminal.notConn') }} </el-tag>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-popconfirm>
|
</el-popconfirm>
|
||||||
@@ -39,8 +41,8 @@
|
|||||||
<template #reference>
|
<template #reference>
|
||||||
<SvgIcon name="QuestionFilled" :size="20" class="pointer-icon mr10" />
|
<SvgIcon name="QuestionFilled" :size="20" class="pointer-icon mr10" />
|
||||||
</template>
|
</template>
|
||||||
<div>ctrl | command + f (搜索)</div>
|
<div>ctrl | command + f ({{ $t('components.terminal.search') }})</div>
|
||||||
<div class="mt5">点击连接状态可重连</div>
|
<div class="mt5">{{ $t('components.terminal.reConnTips') }}</div>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
|
|
||||||
<SvgIcon
|
<SvgIcon
|
||||||
@@ -49,12 +51,24 @@
|
|||||||
@click="minimize(openTerminal.terminalId)"
|
@click="minimize(openTerminal.terminalId)"
|
||||||
:size="20"
|
:size="20"
|
||||||
class="pointer-icon mr10"
|
class="pointer-icon mr10"
|
||||||
title="最小化"
|
:title="$t('components.terminal.minimize')"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SvgIcon name="FullScreen" @click="handlerFullScreen(openTerminal)" :size="20" class="pointer-icon mr10" title="全屏|退出全屏" />
|
<SvgIcon
|
||||||
|
name="FullScreen"
|
||||||
|
@click="handlerFullScreen(openTerminal)"
|
||||||
|
:size="20"
|
||||||
|
class="pointer-icon mr10"
|
||||||
|
:title="$t('components.terminal.fullScreenTitle')"
|
||||||
|
/>
|
||||||
|
|
||||||
<SvgIcon name="Close" class="pointer-icon" @click="close(openTerminal.terminalId)" title="关闭" :size="20" />
|
<SvgIcon
|
||||||
|
name="Close"
|
||||||
|
class="pointer-icon"
|
||||||
|
@click="close(openTerminal.terminalId)"
|
||||||
|
:title="$t('components.terminal.close')"
|
||||||
|
:size="20"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import EnumTag from '@/components/enumtag/EnumTag.vue';
|
|||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '日志',
|
default: 'Log',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="search-card" v-show="search.visible" @keydown.esc="closeSearch">
|
<div id="search-card" v-show="search.visible" @keydown.esc="closeSearch">
|
||||||
<el-card title="搜索" size="small">
|
<el-card :title="$t('components.terminal.search')" size="small">
|
||||||
<!-- 搜索框 -->
|
<!-- 搜索框 -->
|
||||||
<el-input
|
<el-input
|
||||||
class="search-input"
|
class="search-input"
|
||||||
ref="searchInputRef"
|
ref="searchInputRef"
|
||||||
placeholder="请输入查找内容,回车搜索"
|
:placeholder="$t('components.terminal.serachPlaceholder')"
|
||||||
v-model="search.value"
|
v-model="search.value"
|
||||||
@keyup.enter.native="searchKeywords(true)"
|
@keyup.enter.native="searchKeywords(true)"
|
||||||
clearable
|
clearable
|
||||||
@@ -15,24 +15,30 @@
|
|||||||
<div class="search-options">
|
<div class="search-options">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-checkbox class="usn" v-model="search.regex"> 正则匹配 </el-checkbox>
|
<el-checkbox class="usn" v-model="search.regex"> {{ $t('components.terminal.regexMatch') }} </el-checkbox>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-checkbox class="usn" v-model="search.words"> 单词全匹配 </el-checkbox>
|
<el-checkbox class="usn" v-model="search.words"> {{ $t('components.terminal.fullWordMatching') }} </el-checkbox>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-checkbox class="usn" v-model="search.matchCase"> 区分大小写 </el-checkbox>
|
<el-checkbox class="usn" v-model="search.matchCase"> {{ $t('components.terminal.caseSensitive') }} </el-checkbox>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-checkbox class="usn" v-model="search.incremental"> 增量查找 </el-checkbox>
|
<el-checkbox class="usn" v-model="search.incremental"> {{ $t('components.terminal.incrementalSearch') }} </el-checkbox>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
<!-- 按钮 -->
|
<!-- 按钮 -->
|
||||||
<div class="search-buttons">
|
<div class="search-buttons">
|
||||||
<el-button class="terminal-search-button search-button-prev" type="primary" size="small" @click="searchKeywords(false)"> 上一个 </el-button>
|
<el-button class="terminal-search-button search-button-prev" type="primary" size="small" @click="searchKeywords(false)">
|
||||||
<el-button class="terminal-search-button search-button-next" type="primary" size="small" @click="searchKeywords(true)"> 下一个 </el-button>
|
{{ $t('components.terminal.previous') }}}}
|
||||||
<el-button class="terminal-search-button search-button-next" type="primary" size="small" @click="closeSearch"> 关闭 </el-button>
|
</el-button>
|
||||||
|
<el-button class="terminal-search-button search-button-next" type="primary" size="small" @click="searchKeywords(true)">
|
||||||
|
{{ $t('components.terminal.next') }}}}
|
||||||
|
</el-button>
|
||||||
|
<el-button class="terminal-search-button search-button-next" type="primary" size="small" @click="closeSearch">
|
||||||
|
{{ $t('components.terminal.close') }}
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
@@ -41,6 +47,9 @@
|
|||||||
import { ref, toRefs, nextTick, reactive } from 'vue';
|
import { ref, toRefs, nextTick, reactive } from 'vue';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { SearchAddon, ISearchOptions } from 'xterm-addon-search';
|
import { SearchAddon, ISearchOptions } from 'xterm-addon-search';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
searchAddon: {
|
searchAddon: {
|
||||||
@@ -101,7 +110,7 @@ function searchKeywords(direction: any) {
|
|||||||
res = props.searchAddon?.findPrevious(state.search.value, getSearchOptions(option));
|
res = props.searchAddon?.findPrevious(state.search.value, getSearchOptions(option));
|
||||||
}
|
}
|
||||||
if (!res) {
|
if (!res) {
|
||||||
ElMessage.info('未查询到匹配项');
|
ElMessage.info(t('components.terminal.noMatchMsg'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export enum TerminalStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const TerminalStatusEnum = {
|
export const TerminalStatusEnum = {
|
||||||
Error: EnumValue.of(TerminalStatus.Error, '连接出错').setExtra({ iconColor: 'var(--el-color-error)' }),
|
Error: EnumValue.of(TerminalStatus.Error, 'components.terminal.connError').setExtra({ iconColor: 'var(--el-color-error)' }),
|
||||||
NoConnected: EnumValue.of(TerminalStatus.NoConnected, '未连接').setExtra({ iconColor: 'var(--el-color-primary)' }),
|
NoConnected: EnumValue.of(TerminalStatus.NoConnected, 'components.terminal.notConn').setExtra({ iconColor: 'var(--el-color-primary)' }),
|
||||||
Connected: EnumValue.of(TerminalStatus.Connected, '连接成功').setExtra({ iconColor: 'var(--el-color-success)' }),
|
Connected: EnumValue.of(TerminalStatus.Connected, 'components.terminal.connSuccess').setExtra({ iconColor: 'var(--el-color-success)' }),
|
||||||
Disconnected: EnumValue.of(TerminalStatus.Disconnected, '连接失败').setExtra({ iconColor: 'var(--el-color-error)' }),
|
Disconnected: EnumValue.of(TerminalStatus.Disconnected, 'components.terminal.connFail').setExtra({ iconColor: 'var(--el-color-error)' }),
|
||||||
};
|
};
|
||||||
|
|||||||
94
frontend/src/hooks/useI18n.ts
Normal file
94
frontend/src/hooks/useI18n.ts
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
import { i18n } from '@/i18n';
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rule message 提示输入字段名
|
||||||
|
* @param label 字段名称key
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function useI18nPleaseInput(labelI18nKey: string) {
|
||||||
|
const t = i18n.global.t;
|
||||||
|
return t('common.pleaseInput', { label: t(labelI18nKey) });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rule message 提示选择字段名
|
||||||
|
* @param label 字段名称key
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function useI18nPleaseSelect(labelI18nKey: string) {
|
||||||
|
const t = i18n.global.t;
|
||||||
|
return t('common.pleaseSelect', { label: t(labelI18nKey) });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提示确认删除
|
||||||
|
* @param name 删除对象名称
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export async function useI18nDeleteConfirm(name: string = '') {
|
||||||
|
return useI18nConfirm('common.deleteConfirm', { name });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提示确认信息
|
||||||
|
* @param i18nKey i18n msg key
|
||||||
|
* @param value i18n msg value
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export async function useI18nConfirm(i18nKey: string = '', value = {}) {
|
||||||
|
const t = i18n.global.t;
|
||||||
|
return ElMessageBox.confirm(t(i18nKey, value), t('common.hint'), {
|
||||||
|
confirmButtonText: t('common.confirm'),
|
||||||
|
cancelButtonText: t('common.cancel'),
|
||||||
|
type: 'warning',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单校验
|
||||||
|
* @param formRef 表单ref
|
||||||
|
* @param callback 校验通过回调
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export async function useI18nFormValidate(formRef: any) {
|
||||||
|
const t = i18n.global.t;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await formRef.value.validate();
|
||||||
|
return true;
|
||||||
|
} catch (e: any) {
|
||||||
|
ElMessage.error(t('common.formValidationError'));
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useI18nCreateTitle(i18nKey: string) {
|
||||||
|
const t = i18n.global.t;
|
||||||
|
return t('common.createTitle', { name: t(i18nKey) });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useI18nEditTitle(i18nKey: string) {
|
||||||
|
const t = i18n.global.t;
|
||||||
|
return t('common.editTitle', { name: t(i18nKey) });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useI18nDetailTitle(i18nKey: string) {
|
||||||
|
const t = i18n.global.t;
|
||||||
|
return t('common.detailTitle', { name: t(i18nKey) });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useI18nOperateSuccessMsg() {
|
||||||
|
const t = i18n.global.t;
|
||||||
|
ElMessage.success(t('common.operateSuccess'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useI18nSaveSuccessMsg() {
|
||||||
|
const t = i18n.global.t;
|
||||||
|
ElMessage.success(t('common.saveSuccess'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useI18nDeleteSuccessMsg() {
|
||||||
|
const t = i18n.global.t;
|
||||||
|
ElMessage.success(t('common.deleteSuccess'));
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import config from '@/common/config';
|
|||||||
import { unref } from 'vue';
|
import { unref } from 'vue';
|
||||||
import { URL_401 } from '@/router/staticRouter';
|
import { URL_401 } from '@/router/staticRouter';
|
||||||
import openApi from '@/common/openApi';
|
import openApi from '@/common/openApi';
|
||||||
|
import { useThemeConfig } from '@/store/themeConfig';
|
||||||
|
|
||||||
const baseUrl: string = config.baseApiUrl;
|
const baseUrl: string = config.baseApiUrl;
|
||||||
|
|
||||||
@@ -27,7 +28,11 @@ const useCustomFetch = createFetch({
|
|||||||
headers.set('Authorization', token);
|
headers.set('Authorization', token);
|
||||||
headers.set('ClientId', getClientId());
|
headers.set('ClientId', getClientId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const themeConfig = useThemeConfig().themeConfig;
|
||||||
|
|
||||||
headers.set('Content-Type', 'application/json');
|
headers.set('Content-Type', 'application/json');
|
||||||
|
headers.set('Accept-Language', themeConfig?.globalI18n);
|
||||||
options.headers = headers;
|
options.headers = headers;
|
||||||
|
|
||||||
return { options };
|
return { options };
|
||||||
@@ -89,7 +94,7 @@ export function useApiFetch<T>(api: Api, params: any = null, reqOptions: Request
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
execute: async function () {
|
execute: async function () {
|
||||||
return execUaf(uaf);
|
return execCustomFetch(uaf);
|
||||||
},
|
},
|
||||||
isFetching: uaf.isFetching,
|
isFetching: uaf.isFetching,
|
||||||
data: uaf.data,
|
data: uaf.data,
|
||||||
@@ -100,7 +105,7 @@ export function useApiFetch<T>(api: Api, params: any = null, reqOptions: Request
|
|||||||
let refreshingToken = false;
|
let refreshingToken = false;
|
||||||
let queue: any[] = [];
|
let queue: any[] = [];
|
||||||
|
|
||||||
async function execUaf(uaf: any) {
|
async function execCustomFetch(uaf: any) {
|
||||||
try {
|
try {
|
||||||
await uaf.execute(true);
|
await uaf.execute(true);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
@@ -146,7 +151,7 @@ async function execUaf(uaf: any) {
|
|||||||
// 请求加入队列等待, 防止并发多次请求refreshToken
|
// 请求加入队列等待, 防止并发多次请求refreshToken
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
queue.push(() => {
|
queue.push(() => {
|
||||||
resolve(execUaf(uaf));
|
resolve(execCustomFetch(uaf));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -170,7 +175,7 @@ async function execUaf(uaf: any) {
|
|||||||
queue = [];
|
queue = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
await execUaf(uaf);
|
await execCustomFetch(uaf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
445
frontend/src/i18n/en/common.ts
Normal file
445
frontend/src/i18n/en/common.ts
Normal file
@@ -0,0 +1,445 @@
|
|||||||
|
// 定义内容
|
||||||
|
export default {
|
||||||
|
common: {
|
||||||
|
create: 'Create',
|
||||||
|
edit: 'Edit',
|
||||||
|
delete: 'Delete',
|
||||||
|
detail: 'Details',
|
||||||
|
add: 'Add',
|
||||||
|
save: 'Save',
|
||||||
|
remove: 'Remove',
|
||||||
|
confirm: 'Confirm',
|
||||||
|
cancel: 'Cancel',
|
||||||
|
submit: 'Submit',
|
||||||
|
operation: 'Operations',
|
||||||
|
name: 'Name',
|
||||||
|
code: 'Code',
|
||||||
|
remark: 'Remark',
|
||||||
|
status: 'Status',
|
||||||
|
username: 'Username',
|
||||||
|
role: 'Role',
|
||||||
|
msg: 'Message',
|
||||||
|
type: 'Type',
|
||||||
|
time: 'Time',
|
||||||
|
account: 'Account',
|
||||||
|
password: 'Password',
|
||||||
|
createTime: 'Create Time',
|
||||||
|
creator: 'Creator',
|
||||||
|
updateTime: 'Update Time',
|
||||||
|
modifier: 'Modifier',
|
||||||
|
keyword: 'Keyword',
|
||||||
|
path: 'Path',
|
||||||
|
tag: 'Tag',
|
||||||
|
more: 'More',
|
||||||
|
enable: 'Enable',
|
||||||
|
disable: 'Disable',
|
||||||
|
hint: 'Hint',
|
||||||
|
yes: 'Yes',
|
||||||
|
no: 'No',
|
||||||
|
refresh: 'Refresh',
|
||||||
|
basic: 'Basic',
|
||||||
|
other: 'Other',
|
||||||
|
reset: 'Reset',
|
||||||
|
success: 'Success',
|
||||||
|
fail: 'Fail',
|
||||||
|
previousStep: 'Previous Step',
|
||||||
|
nextStep: 'Next Step',
|
||||||
|
copy: 'Copy',
|
||||||
|
pleaseInput: 'Please enter {label}',
|
||||||
|
pleaseSelect: 'Please select {label}',
|
||||||
|
formValidationError: 'Please fill in the form information correctly',
|
||||||
|
createTitle: 'Create {name}',
|
||||||
|
editTitle: 'Edit {name}',
|
||||||
|
detailTitle: '{name} Details',
|
||||||
|
deleteConfirm: 'This operation will delete [{name}]. Do you want to continue?',
|
||||||
|
saveSuccess: 'save successfully',
|
||||||
|
deleteSuccess: 'delete successfully',
|
||||||
|
operateSuccess: 'operate successfully',
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
user: {
|
||||||
|
title0: 'Component size',
|
||||||
|
langSwitch: 'Language switching',
|
||||||
|
menuSearch: 'Menu search',
|
||||||
|
layoutConf: 'Layout configuration',
|
||||||
|
news: 'news',
|
||||||
|
fullScreenOn: 'Full screen on',
|
||||||
|
fullScreenOff: 'Full screen off',
|
||||||
|
dropdownLarge: 'large',
|
||||||
|
dropdownDefault: 'default',
|
||||||
|
dropdownSmall: 'small',
|
||||||
|
index: 'Home Page',
|
||||||
|
personalCenter: 'Personal Center',
|
||||||
|
logout: 'Log out',
|
||||||
|
dropdown6: 'Code warehouse',
|
||||||
|
searchPlaceholder: 'Menu search',
|
||||||
|
newTitle: 'Notice',
|
||||||
|
newBtn: 'All read',
|
||||||
|
newGo: 'Go to the notification center',
|
||||||
|
newDesc: 'No notice',
|
||||||
|
logOutTitle: 'Tips',
|
||||||
|
logOutMessage: 'This operation will log out. Do you want to continue?',
|
||||||
|
logOutExit: 'Exiting',
|
||||||
|
logoutSuccess: 'Safe exit successful!',
|
||||||
|
},
|
||||||
|
tagsView: {
|
||||||
|
refresh: 'Refresh',
|
||||||
|
close: 'Close',
|
||||||
|
closeOther: 'Close Other',
|
||||||
|
closeAll: 'Close All',
|
||||||
|
fullscreen: 'Fullscreen',
|
||||||
|
closeFullscreen: 'Close Fullscreen',
|
||||||
|
},
|
||||||
|
notFound: {
|
||||||
|
title: 'Wrong address input, please re-enter the address~',
|
||||||
|
msg: 'You can check the web address first, and then re-enter or give us feedback.',
|
||||||
|
backHomepage: 'Back to home page',
|
||||||
|
},
|
||||||
|
noAccess: {
|
||||||
|
title: 'You are not authorized to operate~',
|
||||||
|
loginAgain: 'Login again',
|
||||||
|
},
|
||||||
|
config: {
|
||||||
|
configTitle: 'Layout configuration',
|
||||||
|
terminalTheme: 'Terminal Themes',
|
||||||
|
theme: 'Theme',
|
||||||
|
custom: 'Custom',
|
||||||
|
fontColor: 'Font Color',
|
||||||
|
backgroundColor: 'Background Color',
|
||||||
|
cursorColor: 'Cursor Color',
|
||||||
|
fontSize: 'Font Size',
|
||||||
|
fontWeight: 'Font Weight',
|
||||||
|
editorSetting: 'Editor Settings',
|
||||||
|
globalSetting: 'Global Settings',
|
||||||
|
pagesize: 'Page Size',
|
||||||
|
globalTheme: 'Global Themes',
|
||||||
|
twoTopTitle: 'top bar set up',
|
||||||
|
|
||||||
|
menuSetting: 'Menu set up',
|
||||||
|
menuBar: 'Menu background',
|
||||||
|
menuBarFontColor: 'Menu default font color',
|
||||||
|
menuBarActiveColor: 'Menu Highlight Color',
|
||||||
|
isMenuBarColorGradual: 'Menu gradient',
|
||||||
|
|
||||||
|
twoColumnsTitle: 'Columns set up',
|
||||||
|
twoTopBar: 'Top bar background',
|
||||||
|
twoTopBarColor: 'Top bar default font color',
|
||||||
|
twoIsTopBarColorGradual: 'Top bar gradient',
|
||||||
|
|
||||||
|
twoColumnsMenuBar: 'Column menu background',
|
||||||
|
twoColumnsMenuBarColor: 'Default font color bar menu',
|
||||||
|
twoIsColumnsMenuBarColorGradual: 'Column gradient',
|
||||||
|
twoIsColumnsMenuHoverPreload: 'Column Menu Hover Preload',
|
||||||
|
|
||||||
|
interfaceSetting: 'Interface settings',
|
||||||
|
isCollapse: 'Menu horizontal collapse',
|
||||||
|
isUniqueOpened: 'Menu accordion',
|
||||||
|
isFixedHeader: 'Fixed header',
|
||||||
|
isClassicSplitMenu: 'Classic layout split menu',
|
||||||
|
isLockScreen: 'Open the lock screen',
|
||||||
|
lockScreenTime: 'screen locking(s/s)',
|
||||||
|
interfaceDisplay: 'Interface display',
|
||||||
|
isShowLogo: 'Sidebar logo',
|
||||||
|
isBreadcrumb: 'Open breadcrumb',
|
||||||
|
isBreadcrumbIcon: 'Open breadcrumb icon',
|
||||||
|
isTagsview: 'Open tagsview',
|
||||||
|
isTagsviewIcon: 'Open tagsview Icon',
|
||||||
|
isCacheTagsView: 'Enable tagsview cache',
|
||||||
|
isSortableTagsView: 'Enable tagsview drag',
|
||||||
|
isShareTagsView: 'Enable tagsview sharing',
|
||||||
|
isFooter: 'Open footer',
|
||||||
|
isGrayscale: 'Grey model',
|
||||||
|
isInvert: 'Color weak mode',
|
||||||
|
isDark: 'Dark Mode',
|
||||||
|
isWartermark: 'Turn on watermark',
|
||||||
|
wartermarkText: 'Watermark copy',
|
||||||
|
otherSetting: 'Other settings',
|
||||||
|
tagsStyle: 'Tagsview style',
|
||||||
|
animation: 'Page animation',
|
||||||
|
columnsAsideStyle: 'Column style',
|
||||||
|
columnsAsideLayout: 'Column layout',
|
||||||
|
layoutSwitch: 'Layout switch',
|
||||||
|
defaults: 'One',
|
||||||
|
classic: 'Two',
|
||||||
|
transverse: 'Three',
|
||||||
|
columns: 'Four',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
staticRoutes: {
|
||||||
|
signIn: 'signIn',
|
||||||
|
notFound: 'notFound',
|
||||||
|
noPower: 'noPower',
|
||||||
|
},
|
||||||
|
upgrade: {
|
||||||
|
title: 'New version',
|
||||||
|
msg: 'The new version is available, please update it now! Dont worry, the update is fast!',
|
||||||
|
desc: 'Prompt: Update will restore the default configuration',
|
||||||
|
btnOne: 'Cruel refusal',
|
||||||
|
btnTwo: 'Update now',
|
||||||
|
btnTwoLoading: 'Updating',
|
||||||
|
},
|
||||||
|
menu: {
|
||||||
|
index: 'Home Page',
|
||||||
|
personalCenter: 'Personal Center',
|
||||||
|
|
||||||
|
tag: 'Tag',
|
||||||
|
tagTree: 'Tag Tree',
|
||||||
|
tagSave: 'Save Tag',
|
||||||
|
tagDelete: 'Delete Tag',
|
||||||
|
authorization: 'Authorization',
|
||||||
|
authorizationBase: 'Base Permission',
|
||||||
|
authorizationSave: 'Save Authorization',
|
||||||
|
authorizationDelete: 'Delete Authorization',
|
||||||
|
team: 'Team',
|
||||||
|
teamSave: 'Save Team',
|
||||||
|
teamDelete: 'Delete Team',
|
||||||
|
teamMemberAdd: 'Add Member',
|
||||||
|
teamMemberDelete: 'Delete Member',
|
||||||
|
teamTagSave: 'Save Team Tag',
|
||||||
|
|
||||||
|
machine: 'Machine',
|
||||||
|
machineOp: 'Machine Operation',
|
||||||
|
machineOpBase: 'Base Permission',
|
||||||
|
machineList: 'Machine List',
|
||||||
|
machineBase: 'Base Permission',
|
||||||
|
machineCreate: 'Create Machine',
|
||||||
|
machineEdit: 'Edit Machine',
|
||||||
|
machineDelete: 'Delete Machine',
|
||||||
|
machineTerminal: 'Machine Terminal',
|
||||||
|
machineFileConf: 'File',
|
||||||
|
machineFileConfCreate: 'File-Add Config',
|
||||||
|
machineFileConfDelete: 'File-Delete Config',
|
||||||
|
machineFileCreate: 'File-Create',
|
||||||
|
machineFileDelete: 'File-Delete',
|
||||||
|
machineFileWrite: 'File-Write',
|
||||||
|
machineFileUpload: 'File-Upload',
|
||||||
|
machineScript: 'Script',
|
||||||
|
machineScriptSave: 'Script-Save',
|
||||||
|
machineScriptDelete: 'Script-Delete',
|
||||||
|
machineScriptRun: 'Script-Run',
|
||||||
|
machineKillprocess: 'Kill Process',
|
||||||
|
machineCronJob: 'Cron Job',
|
||||||
|
machineCronJobSvae: 'Cron Job-Save',
|
||||||
|
machineCronJobDelete: 'Cron Job-Delete',
|
||||||
|
machineSecurityConfig: 'Security Config',
|
||||||
|
machineSecurityCmdSvae: 'Cmd Config-Save',
|
||||||
|
machineSecurityCmdDelete: 'Cmd Config-Delete',
|
||||||
|
|
||||||
|
dbms: 'DBMS',
|
||||||
|
dbDataOp: 'Data Operation',
|
||||||
|
dbDataOpBase: 'Base Permission',
|
||||||
|
dbDataOpSqlScriptRun: 'SQL Script Run',
|
||||||
|
dbInstance: 'DB Instance',
|
||||||
|
dbInstanceBase: 'Base Permission',
|
||||||
|
dbInstanceSave: 'Save Instance',
|
||||||
|
dbInstanceDelete: 'Delete Instance',
|
||||||
|
dbBase: 'Db Base Permission',
|
||||||
|
dbSave: 'Save Db',
|
||||||
|
dbDelete: 'Delete Db',
|
||||||
|
dbDataSync: 'Data Sync',
|
||||||
|
dbDataSyncBase: 'Base Permission',
|
||||||
|
dbDataSyncSave: 'Save Sync Task',
|
||||||
|
dbDataSyncDelete: 'Delete Sync Task',
|
||||||
|
dbDataSyncChangeStatus: 'Enable/Disable Sync Task',
|
||||||
|
dbDataSyncLog: 'Sync Log',
|
||||||
|
dbTransfer: 'DB Transfer',
|
||||||
|
dbTransferBase: 'Base Permission',
|
||||||
|
dbTransferSave: 'Save Transfer Task',
|
||||||
|
dbTransferDelete: 'Delete Transfer Task',
|
||||||
|
dbTransferChangeStatus: 'Enable/Disable Transfer Task',
|
||||||
|
dbTransferRun: 'Run Transfer Task',
|
||||||
|
dbTransferRunLog: 'Transfer Log',
|
||||||
|
dbTransferFileShow: 'ransfer File-Show',
|
||||||
|
dbTransferFileDelete: 'Transfer File-Delete',
|
||||||
|
dbTransferFileDownload: 'Transfer File-Download',
|
||||||
|
dbTransferFileRun: 'Transfer File-Run',
|
||||||
|
|
||||||
|
redis: 'Redis',
|
||||||
|
redisDataOp: 'Data Operation',
|
||||||
|
redisDataOpBase: 'Base Permission',
|
||||||
|
redisDataOpSave: 'Save Data',
|
||||||
|
redisDataOpDelete: 'Delete Data',
|
||||||
|
redisManage: 'Redis Manage',
|
||||||
|
redisManageBase: 'Base Permission',
|
||||||
|
|
||||||
|
mongo: 'Mongo',
|
||||||
|
mongoDataOp: 'Data Operation',
|
||||||
|
mongoDataOpBase: 'Base Permission',
|
||||||
|
mongoDataOpSave: 'Save Data',
|
||||||
|
mongoDataOpDelete: 'Delete Data',
|
||||||
|
mongoManage: 'Mongo Manage',
|
||||||
|
mongoManageBase: 'Base Permission',
|
||||||
|
|
||||||
|
flow: 'Flow',
|
||||||
|
myTask: 'My Task',
|
||||||
|
myFlow: 'My Flow',
|
||||||
|
flowProcDef: 'Process Define',
|
||||||
|
flowProcDefSave: 'Save Process Define',
|
||||||
|
flowProcDefDelete: 'Delete Process Define',
|
||||||
|
|
||||||
|
system: 'System',
|
||||||
|
menuPermission: 'Menu & Permission',
|
||||||
|
menuPermissionBase: 'Base Permission',
|
||||||
|
menuPermissionAdd: 'Add Menu Permission',
|
||||||
|
menuPermissionEdit: 'Edit Menu Permission',
|
||||||
|
menuPermissionDelete: 'Delete Menu Permission',
|
||||||
|
menuPermissionEnableDisable: 'Enable/Disable Menu Permission',
|
||||||
|
account: 'Account',
|
||||||
|
accountBase: 'Base Permission',
|
||||||
|
accountAdd: 'Add Account',
|
||||||
|
accountEdit: 'Edit Account',
|
||||||
|
accountDelete: 'Delete Account',
|
||||||
|
accountEnableDisable: 'Enable/Disable Account',
|
||||||
|
accountRoleAllocation: 'Role Allocation',
|
||||||
|
role: 'Role',
|
||||||
|
roleBase: 'Base Permission',
|
||||||
|
roleAdd: 'Add Role',
|
||||||
|
roleEdit: 'Edit Role',
|
||||||
|
roleDelete: 'Delete Role',
|
||||||
|
roleMenuPermissionAllocation: 'Menu & Permission Allocation',
|
||||||
|
sysConf: 'System Config',
|
||||||
|
sysConfBase: 'Base Permission',
|
||||||
|
sysConfSave: 'Save System Config',
|
||||||
|
opLog: 'Operation Log',
|
||||||
|
opLogBase: 'Base Permission',
|
||||||
|
|
||||||
|
noPagePermission: 'No Page Permission',
|
||||||
|
authcertShowciphertext: 'Show Ciphertext',
|
||||||
|
},
|
||||||
|
home: {
|
||||||
|
personalInfo: 'Personal Information',
|
||||||
|
welcomeMsg: `Hello, {name}, no matter how bad life gets, it doesn't prevent me from getting better!`,
|
||||||
|
lastLoginIp: 'Last Login Ip',
|
||||||
|
lastLoginTime: 'Last Login Time',
|
||||||
|
msgNotify: 'Message Notification',
|
||||||
|
noOpRecord: 'No operation record',
|
||||||
|
msgTypeLogin: 'Login',
|
||||||
|
msgTypeNotify: 'Notify',
|
||||||
|
},
|
||||||
|
personal: {
|
||||||
|
updateInfo: 'Update Information',
|
||||||
|
basicInfo: 'Basic Information',
|
||||||
|
inputNewPasswordPlaceholder: 'Enter a new password',
|
||||||
|
updatePersonalInfo: 'Updating Personal Information',
|
||||||
|
accountInfo: 'Account Information',
|
||||||
|
currentStatus: 'Current Status',
|
||||||
|
boundUp: 'Bound up',
|
||||||
|
notBound: 'Not bound',
|
||||||
|
immediateBinding: 'Immediate binding',
|
||||||
|
unbundle: 'Unbundle',
|
||||||
|
updateSuccess: 'Update successfully',
|
||||||
|
bindingSuccess: 'Binding successfully',
|
||||||
|
unbundleSuccess: 'Unbundle successfully',
|
||||||
|
},
|
||||||
|
login: {
|
||||||
|
accountPasswordLogin: 'Account Password Login',
|
||||||
|
thirdPartyLogin: 'Third Party login',
|
||||||
|
ldapLogin: 'LDAP Login',
|
||||||
|
inputUsernamePlaceholder: 'Please enter your username',
|
||||||
|
inputPasswordPlaceholder: 'Please enter your password',
|
||||||
|
inputCaptchaPlaceholder: 'Please enter the verification code',
|
||||||
|
login: 'Login',
|
||||||
|
loginFailTip: 'Tip: If you fail to log in more than {loginFailCount} times, you will not be allowed to log in again for {loginFailMin} minutes',
|
||||||
|
loginSuccessTip: 'welcome back!',
|
||||||
|
changePassword: 'Change Password',
|
||||||
|
oldPassword: 'Old Password',
|
||||||
|
newPassword: 'New Password',
|
||||||
|
inputNewPasswordPlaceholder: 'Please enter a new password',
|
||||||
|
passwordRuleTip: 'Must be at least 8 characters long and contain upper/lower case + number + special symbol',
|
||||||
|
passwordChangeSuccessTip: 'The password has been changed successfully, and the new password has been filled in the login password box',
|
||||||
|
otpValidation: 'OTP validation',
|
||||||
|
qrCode: 'QR code',
|
||||||
|
enterOtpCodeTip: 'Enter the authorization code shown in the Token APP',
|
||||||
|
inputOtpCodePlaceholder: 'Please enter the OTP authorization code',
|
||||||
|
updateBasicInfo: 'Modifying basic information',
|
||||||
|
name: 'Name',
|
||||||
|
inputNamePlaceholder: 'Please enter your name',
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
df: {
|
||||||
|
fieldModelPlaceholder: 'The field associated with model',
|
||||||
|
fieldLabel: 'label',
|
||||||
|
fieldPlaceholder: 'placeholder',
|
||||||
|
optionalValues: 'Optional values',
|
||||||
|
optionalValuesPlaceholder: 'Optional values, use, split',
|
||||||
|
required: 'Required',
|
||||||
|
},
|
||||||
|
terminal: {
|
||||||
|
connError: 'Connection error',
|
||||||
|
notConn: 'Not connected',
|
||||||
|
connSuccess: 'be connected successfully',
|
||||||
|
connFail: 'connection fail',
|
||||||
|
connErrMsg: 'Tip: Connection error...',
|
||||||
|
connConfirm: 'Are you sure to reconnect?',
|
||||||
|
connected: 'Connected',
|
||||||
|
search: 'Search',
|
||||||
|
reConnTips: 'Click the connection status to reconnect',
|
||||||
|
minimize: 'Minimize',
|
||||||
|
fullScreenTitle: 'Full screen | Exits from full screen',
|
||||||
|
close: 'Close',
|
||||||
|
|
||||||
|
serachPlaceholder: 'Please enter the search content, press enter search',
|
||||||
|
regexMatch: 'Regex Match',
|
||||||
|
fullWordMatching: 'Full Word Matching',
|
||||||
|
caseSensitive: 'Case Sensitive',
|
||||||
|
incrementalSearch: 'Incremental Search',
|
||||||
|
previous: 'Previous',
|
||||||
|
next: 'Next',
|
||||||
|
noMatchMsg: 'No matching item is found',
|
||||||
|
},
|
||||||
|
crontab: {
|
||||||
|
crontabInputPlaceholder: 'Click the left button to configure',
|
||||||
|
crontabTitle: 'Generate cron',
|
||||||
|
second: 'Second',
|
||||||
|
minute: 'Minute',
|
||||||
|
hour: 'Hour',
|
||||||
|
day: 'Day',
|
||||||
|
month: 'Month',
|
||||||
|
week: 'Week',
|
||||||
|
year: 'Year',
|
||||||
|
timeExpression: 'Time Expression',
|
||||||
|
crontabCompleteExpression: 'Crontab Complete Expression',
|
||||||
|
|
||||||
|
dayCrontype1: 'Allowed wildcard [, - * / L M]',
|
||||||
|
crontype2: 'Not specify',
|
||||||
|
crontype3: 'Cycle from',
|
||||||
|
|
||||||
|
crontypeFrom: 'Starting on the',
|
||||||
|
crontypeEvery: 'It is executed every',
|
||||||
|
appoint: 'Appoint',
|
||||||
|
|
||||||
|
crontypeStartDay: 'th',
|
||||||
|
crontypeExecDay: 'days',
|
||||||
|
monthLastDay: 'Last day of the month',
|
||||||
|
|
||||||
|
hourCronType1: 'Allowed wildcard [, - * /]',
|
||||||
|
crontypeStartHour: "o 'clock",
|
||||||
|
crontypeExecHour: 'hours',
|
||||||
|
|
||||||
|
crontypeStartMin: 'minutes',
|
||||||
|
crontypeExecMin: 'minutes',
|
||||||
|
|
||||||
|
crontypeStartSecond: 'seconds',
|
||||||
|
crontypeExecSecond: 'seconds',
|
||||||
|
|
||||||
|
crontypeStartMonth: 'months',
|
||||||
|
crontypeExecMonth: 'months',
|
||||||
|
|
||||||
|
yearly: 'Yearly',
|
||||||
|
crontypeStartYear: 'years',
|
||||||
|
crontypeExecYear: 'years',
|
||||||
|
|
||||||
|
weekCronType1: 'Allowed wildcard [, - * / L #]',
|
||||||
|
monday: 'Monday',
|
||||||
|
tuesday: 'Tuesday',
|
||||||
|
wednesday: 'Wednesday',
|
||||||
|
thursday: 'Thursday',
|
||||||
|
friday: 'Friday',
|
||||||
|
saturday: 'Saturday',
|
||||||
|
sunday: 'Sunday',
|
||||||
|
|
||||||
|
last5runTimes: 'Last 5 running times',
|
||||||
|
calculationing: 'In the calculation result',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
207
frontend/src/i18n/en/db.ts
Normal file
207
frontend/src/i18n/en/db.ts
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
export default {
|
||||||
|
db: {
|
||||||
|
// db instance
|
||||||
|
dbManage: 'DB Management',
|
||||||
|
port: 'Port',
|
||||||
|
connParam: 'Connection Params',
|
||||||
|
keywordPlaceholder: 'host / name / code',
|
||||||
|
acName: 'Credential',
|
||||||
|
dbInst: 'DB Instance',
|
||||||
|
manageDbTitle: 'Manage the [{instName}] database',
|
||||||
|
sqlitePathPlaceholder: 'Please enter the absolute address of the sqlite file on the server',
|
||||||
|
connParamPlaceholder: 'Other connection parameters of the form key1=value1&key2=value2',
|
||||||
|
connSuccess: 'be connected successfully',
|
||||||
|
showDb: 'View DB',
|
||||||
|
db: 'Database',
|
||||||
|
dbFilterPlaceholder: 'DB name: Input filterable',
|
||||||
|
sqlRecord: 'SQL records',
|
||||||
|
dump: 'Export',
|
||||||
|
dumpContent: 'Export Content',
|
||||||
|
structure: 'Structure',
|
||||||
|
data: 'Data',
|
||||||
|
extName: 'Ext Name',
|
||||||
|
dbFilterPlacehoder: 'Filter by database name',
|
||||||
|
allDb: 'All DB',
|
||||||
|
dumpDb: 'Export DB',
|
||||||
|
getDbMode: 'Get DB Mode',
|
||||||
|
noDumpDbMsg: 'Add the database you want to export',
|
||||||
|
allSelect: 'check all',
|
||||||
|
selectDbPlacehoder: '',
|
||||||
|
|
||||||
|
// db
|
||||||
|
dbInstInfo: 'DB Instance Info',
|
||||||
|
newQuery: 'New Query',
|
||||||
|
locationTagTree: 'Navigate to the specified position in the left tree',
|
||||||
|
dbShowSetting: 'DB View Setting',
|
||||||
|
showFieldComments: 'Show column comment',
|
||||||
|
autoLocationTagTree: 'Automatically locate the tree nodes',
|
||||||
|
cacheTableInfo: 'Cache table information -[If not enabled, get table information in real time]',
|
||||||
|
dbName: 'DB Name',
|
||||||
|
table: 'Table',
|
||||||
|
createTable: 'Create Table',
|
||||||
|
tableOp: 'Table Operation',
|
||||||
|
copyTable: 'Copy Table',
|
||||||
|
renameTable: 'Rename',
|
||||||
|
editTable: 'Edit',
|
||||||
|
delTable: 'Delete Table',
|
||||||
|
close: 'Close',
|
||||||
|
closeOther: 'Close Other',
|
||||||
|
noDbInstMsg: 'Select the database instance and the corresponding schema',
|
||||||
|
query: 'Query',
|
||||||
|
nQuery: 'NewQuery',
|
||||||
|
renamePrompt: 'Rename table 【{db}.{tableName}】',
|
||||||
|
noChange: 'No change',
|
||||||
|
isCopyTableData: 'Do you copy data?',
|
||||||
|
execSuccess: 'Successful execution',
|
||||||
|
execFail: 'Execution failure',
|
||||||
|
sqlScriptRun: 'Run SQL Script',
|
||||||
|
saveSql: 'Save SQL',
|
||||||
|
execInfo: 'Execution info',
|
||||||
|
result: 'Result',
|
||||||
|
times: 'times',
|
||||||
|
resultSet: 'Result Set',
|
||||||
|
tableDataEmptyTextTips:
|
||||||
|
'tips: Single table query at the beginning of select * or click the default query data of the table name, double-click the data online modification',
|
||||||
|
noSelctRunSqlMsg: 'Select the sql you want to execute',
|
||||||
|
enterExecRemarkTips: 'Please enter remark',
|
||||||
|
execRemarkPlaceholder: 'Enter the remark to execute the sql',
|
||||||
|
currentSqlTabIsRunning: 'The current result set tab is being executed, please use the new TAB to execute',
|
||||||
|
sqlCannotEmpty: 'sql content cannot be empty',
|
||||||
|
enterSqlScriptNameTips: 'Please enter the SQL script name',
|
||||||
|
scriptFileUploadRunning: `'{filename}' is being uploaded for execution, please pay attention to the result notification`,
|
||||||
|
runSql: 'Run SQL',
|
||||||
|
newTabRunSql: 'NewTab Run SQL',
|
||||||
|
formatSql: 'Format SQL',
|
||||||
|
|
||||||
|
execTime: 'execution time',
|
||||||
|
oneClickCopy: 'One click copy',
|
||||||
|
asc: 'Asc',
|
||||||
|
desc: 'Desc',
|
||||||
|
fixed: 'Fixed',
|
||||||
|
cancelFiexd: 'Cancel Fixed',
|
||||||
|
formView: 'Form View',
|
||||||
|
genJson: 'Generating JSON',
|
||||||
|
exportCsv: 'Export CSV',
|
||||||
|
exportSql: 'Export SQL',
|
||||||
|
onlySelectOneData: 'Only one row can be selected',
|
||||||
|
|
||||||
|
editField: 'Edit field',
|
||||||
|
valueTypeNoMatch: 'The input does not match the type',
|
||||||
|
|
||||||
|
tableFieldConf: 'Table field Configuration',
|
||||||
|
columnFilterPlaceholder: 'Enter column name or remark filter',
|
||||||
|
selectAll: 'Select All',
|
||||||
|
submitUpdate: 'Submit changes',
|
||||||
|
cancelUpdate: 'Cancel changes',
|
||||||
|
autoCompleteColumnPlaceholder:
|
||||||
|
'Select a column or enter a SQL conditional expression and press Enter or click the query icon to filter the results. The input can be prompted by the field name',
|
||||||
|
selectColumn: 'Select Column',
|
||||||
|
columnName: 'Column Name',
|
||||||
|
homePage: 'Home Page',
|
||||||
|
previousPage: 'Previous Page',
|
||||||
|
rowsPage: 'rows/page',
|
||||||
|
rows: 'rows',
|
||||||
|
conditionInputDialogTitle: 'Enter the value of [{columnName}]',
|
||||||
|
addDataDialogTitle: 'Add `{tableName}` table data',
|
||||||
|
|
||||||
|
exportContent: 'Export Content',
|
||||||
|
selectExportTable: 'Select the table you want to export first',
|
||||||
|
tableNamePlaceholder: 'Table name: Input filterable',
|
||||||
|
comment: 'Comment',
|
||||||
|
commentPlaceholder: 'Comment: Input filterable',
|
||||||
|
dataSize: 'Data Size',
|
||||||
|
indexSize: 'Index Size',
|
||||||
|
column: 'Column',
|
||||||
|
index: 'Index',
|
||||||
|
nullable: 'Nullable',
|
||||||
|
seqInIndex: 'Sequence number',
|
||||||
|
|
||||||
|
// DbSqlExecLog
|
||||||
|
selectDbPlaceholder: 'Please select database',
|
||||||
|
restoreSql: 'Restore SQL',
|
||||||
|
stmtType: 'Statement type',
|
||||||
|
execUser: 'Executor',
|
||||||
|
execRes: 'Result',
|
||||||
|
oldValue: 'Old Value',
|
||||||
|
|
||||||
|
// db transfer
|
||||||
|
pleaseSetting: 'Please set',
|
||||||
|
log: 'Logs',
|
||||||
|
stop: 'Stop',
|
||||||
|
run: 'Run',
|
||||||
|
file: 'File',
|
||||||
|
taskName: 'Task Name',
|
||||||
|
srcDb: 'Source DB',
|
||||||
|
runState: 'Run State',
|
||||||
|
createDbTransferDialogTitle: 'Added DB transfer task (transfer does not change the source DB)',
|
||||||
|
editDbTransferDialogTitle: 'Modify the DB transfer task (transfer does not change the source DB)',
|
||||||
|
stopConfirm: 'Sure to stop?',
|
||||||
|
runConfirm: 'Sure to run?',
|
||||||
|
transferFileManage: 'Transfer file management',
|
||||||
|
dbFileType: 'DB dialect file',
|
||||||
|
targetDb: 'Target DB',
|
||||||
|
fileDbType: 'SQL Dialect',
|
||||||
|
transferFileRunDialogTitle: 'Specify the database to execute the sql file',
|
||||||
|
targetDbTypeSelectError: 'Please select [{dbType}] database',
|
||||||
|
cronAble: 'Timed transfer',
|
||||||
|
transferMode: 'Transfer Mode',
|
||||||
|
transfer2Db: 'Transfer to DB',
|
||||||
|
transfer2File: 'Transfer to File',
|
||||||
|
fileSaveDays: 'File retention days',
|
||||||
|
transferStrategy: 'Transfer Strategy',
|
||||||
|
day: 'Day',
|
||||||
|
transferFull: 'Full',
|
||||||
|
transferIncrement: 'Increment(not yet available)',
|
||||||
|
nameCase: 'Convert',
|
||||||
|
none: 'None',
|
||||||
|
lower: 'Lower',
|
||||||
|
upper: 'Upper',
|
||||||
|
dbObj: 'DB',
|
||||||
|
allTable: 'All Table',
|
||||||
|
custom: 'Custom',
|
||||||
|
noTransferTableMsg: 'Select the table you want to transfer',
|
||||||
|
|
||||||
|
// dbSync
|
||||||
|
recentState: 'Recent task status',
|
||||||
|
dbSync: 'Data Synchronism',
|
||||||
|
realTime: 'Real Time',
|
||||||
|
noRealTime: 'Non-real time',
|
||||||
|
srcDataSql: 'Source Data SQL',
|
||||||
|
targetDbTable: 'Target Db table',
|
||||||
|
pageSize: 'Page Size',
|
||||||
|
pageSizePlaceholder: 'Size of data per page queried when synchronizing data',
|
||||||
|
updateField: 'Update Field',
|
||||||
|
updateFieldTips: 'The current maximum value of this field will be included when querying the data source, with aliases such as t.reate_time',
|
||||||
|
updateFiledPlaceholder: 'The current maximum value of this field will be included when querying the data source',
|
||||||
|
updateFieldValue: 'Update Field Value',
|
||||||
|
updateFieldValueTips:
|
||||||
|
'The record updates the current value of the field, such as: current time, current date, etc., and the next time the data is queried, the value condition will be added',
|
||||||
|
updateFieldValuePlaceholder: 'Update the current maximum value of the field',
|
||||||
|
fieldValueSrc: 'Source of values',
|
||||||
|
fieldValueSrcTips:
|
||||||
|
'The field name of the updated value is taken from the query result. The default is the same as the updated field. If the query result specifies a field alias and is inconsistent with the original updated field, the field value is the current updated value',
|
||||||
|
fieldValueSrcPlaceholder: 'Update the value source',
|
||||||
|
fieldMap: 'Field Mapping',
|
||||||
|
srcField: 'Source Field',
|
||||||
|
targetField: 'Target Field',
|
||||||
|
sqlPreview: 'SQL Preview',
|
||||||
|
selectSql: 'Select SQL',
|
||||||
|
insertSql: 'Insert SQL',
|
||||||
|
keyDuplicateStrategy: 'Key Duplicate Strategy',
|
||||||
|
fieldMapError: 'There are duplicate target fields in the field map, please check',
|
||||||
|
noDataSqlMsg: 'Please enter data sql',
|
||||||
|
notSelectSql: 'sql statement error, please enter the select statement',
|
||||||
|
notOneSql: 'sql statement error, please enter a single query statement',
|
||||||
|
notColumnSql: 'No field found. Check your sql',
|
||||||
|
|
||||||
|
// enums
|
||||||
|
getDbNamesModeAuto: 'Real-time get db',
|
||||||
|
getDbNamesModeAssign: 'Specifying the db name',
|
||||||
|
|
||||||
|
ignore: 'Ignore',
|
||||||
|
replate: 'Replate',
|
||||||
|
|
||||||
|
running: 'Running',
|
||||||
|
waitRun: 'Wait Run',
|
||||||
|
},
|
||||||
|
};
|
||||||
90
frontend/src/i18n/en/flow.ts
Normal file
90
frontend/src/i18n/en/flow.ts
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
export default {
|
||||||
|
flow: {
|
||||||
|
// procdef
|
||||||
|
approvalNode: 'Approval Node',
|
||||||
|
procdef: 'Process Definition',
|
||||||
|
triggeringCondition: 'Condition',
|
||||||
|
triggeringConditionTips: 'go template syntax. If the output is 1, the approval process is triggered',
|
||||||
|
conditionPlaceholder: 'Trigger condition, return value =1, means to trigger the approval process',
|
||||||
|
conditionDefault: `{{/* DBMS- Run Sql rules The param parameter is described as follows */}}
|
||||||
|
{{/* stmtType: select / read / insert / update / delete / ddl ; */}}
|
||||||
|
{{ if eq .bizType "db_sql_exec_flow"}}
|
||||||
|
{{/* Enable process approval when select and read statements are not available */}}
|
||||||
|
{{ if and (ne .param.stmtType "select") (ne .param.stmtType "read") }}
|
||||||
|
1
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{/* Redis-Run Cmd rules; param: parameter is described as follows */}}
|
||||||
|
{{/* cmdType: read(Read cmd) / write(Write cmd); */}}
|
||||||
|
{{/* cmd: get/set/hset... */}}
|
||||||
|
{{ if eq .bizType "redis_run_cmd_flow"}}
|
||||||
|
{{ if eq .param.cmdType "write" }}
|
||||||
|
1
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}`,
|
||||||
|
nodeName: 'Node Name',
|
||||||
|
nodeNameTips: 'Click the specified node to drag and drop sort',
|
||||||
|
auditor: 'Auditor',
|
||||||
|
tasksNotEmpty: 'Please improve the task of the approval node',
|
||||||
|
tasksNoComplete: 'Please complete the task information of the {index} th approval node',
|
||||||
|
// procdef status enum
|
||||||
|
enable: 'Enable',
|
||||||
|
disable: 'Disable',
|
||||||
|
|
||||||
|
// procinst
|
||||||
|
startProcess: 'Start Process',
|
||||||
|
cancelProcessConfirm: 'Confirm canceling the process?',
|
||||||
|
bizType: 'Business Type',
|
||||||
|
bizKey: 'Business Key',
|
||||||
|
initiator: 'Initiator',
|
||||||
|
procdefName: 'Process Name',
|
||||||
|
bizStatus: 'Business Status',
|
||||||
|
startingTime: 'Starting Time',
|
||||||
|
endTime: 'End Time',
|
||||||
|
duration: 'Duration',
|
||||||
|
proc: 'Process',
|
||||||
|
bizInfo: 'Business Information',
|
||||||
|
approvalNodeNotExist: 'There is no approval node',
|
||||||
|
resourceNotExistFlow: 'This resource does not require an approval operation',
|
||||||
|
procinstFormError: 'Please fill in the information correctly',
|
||||||
|
procinstStartSuccess: 'Process initiated successfully',
|
||||||
|
// db run sql flow biz
|
||||||
|
runSql: 'Run SQL',
|
||||||
|
selectDbPlaceholder: 'Please select database',
|
||||||
|
// redis run cmd flow biz
|
||||||
|
runCmd: 'Rum Cmd',
|
||||||
|
selectRedisPlaceholder: 'Select the Redis instance and db',
|
||||||
|
cmdPlaceholder: `For example: SET 'key' 'value'; Multiple commands; segmentation`,
|
||||||
|
// ProcinstStatusEnum
|
||||||
|
active: 'Active',
|
||||||
|
completed: 'Completed',
|
||||||
|
suspended: 'Suspended',
|
||||||
|
terminated: 'Terminated',
|
||||||
|
cancelled: 'Cancelled',
|
||||||
|
handleResult: 'Result of handling',
|
||||||
|
runResult: 'Result of execution',
|
||||||
|
// ProcinstBizStatus
|
||||||
|
waitHandle: 'Pending',
|
||||||
|
handleSuccess: 'Success',
|
||||||
|
handleFail: 'Fail',
|
||||||
|
noHandle: 'No processing',
|
||||||
|
// ProcinstTaskStatus
|
||||||
|
waitProcess: 'Waiting',
|
||||||
|
pass: 'Pass',
|
||||||
|
reject: 'Reject',
|
||||||
|
back: 'Back',
|
||||||
|
canceled: 'Canceled',
|
||||||
|
// FlowBizType
|
||||||
|
dbSqlExec: 'DBMS-Run SQL',
|
||||||
|
redisRunCmd: 'Redis-Run Cmd',
|
||||||
|
|
||||||
|
// task
|
||||||
|
audit: 'Audit',
|
||||||
|
procinstStatus: 'Process status',
|
||||||
|
taskStatus: 'Task status',
|
||||||
|
taskName: 'Task Name',
|
||||||
|
taskBeginTime: 'Begin Time',
|
||||||
|
flowAudit: 'Approval Process',
|
||||||
|
},
|
||||||
|
};
|
||||||
134
frontend/src/i18n/en/machine.ts
Normal file
134
frontend/src/i18n/en/machine.ts
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
export default {
|
||||||
|
machine: {
|
||||||
|
keywordPlaceholder: 'ip / Name / Code',
|
||||||
|
acName: 'Credential',
|
||||||
|
runningStat: 'Running Status',
|
||||||
|
fs: 'Disk (mount point => available/total)',
|
||||||
|
memberInfo: 'Memory (available/total)',
|
||||||
|
cpuInfo: 'CPU (free)',
|
||||||
|
file: 'File',
|
||||||
|
directory: 'Directory',
|
||||||
|
folder: 'Folder',
|
||||||
|
script: 'Script',
|
||||||
|
process: 'Process',
|
||||||
|
terminalPlayback: 'Terminal Playback',
|
||||||
|
createMachine: 'Create Machine',
|
||||||
|
editMachine: 'Edit Machine',
|
||||||
|
reConnTips: 'Are you sure to reconnect?',
|
||||||
|
clickReConn: 'Click to reconnect',
|
||||||
|
port: 'Port',
|
||||||
|
sshTunnel: 'SSH Tunnel',
|
||||||
|
newOpenTabTerminalTips: 'Hold down ctrl to open a new TAB',
|
||||||
|
newTab: 'New TAB',
|
||||||
|
openTerminal: 'Open Terminal',
|
||||||
|
newTabOpenTerminal: 'Open Terminal(New TAB)',
|
||||||
|
fileManage: 'File Manage',
|
||||||
|
scriptManage: 'Script Manage',
|
||||||
|
machineState: 'Machine State',
|
||||||
|
remoteFileDesktopManage: 'Remote desktop file management', // Remote desktop file management
|
||||||
|
remoteDesktop: 'Remote Desktop',
|
||||||
|
protocol: 'Protocol',
|
||||||
|
ipAndPort: 'ip and port',
|
||||||
|
connSuccess: 'be connected successfully',
|
||||||
|
noAcErrMsg: 'Please complete the voucher account information',
|
||||||
|
|
||||||
|
// MachineRec
|
||||||
|
playback: 'Playback',
|
||||||
|
cmd: 'Command',
|
||||||
|
execCmdRecord: 'Executive command record',
|
||||||
|
execTime: 'Execution time',
|
||||||
|
operator: 'Operator',
|
||||||
|
beginTime: 'Begin Time',
|
||||||
|
endTime: 'End Time',
|
||||||
|
|
||||||
|
// MachineStats
|
||||||
|
basicInfo: 'basic information',
|
||||||
|
hostname: 'Hostname',
|
||||||
|
runTime: 'Run Time',
|
||||||
|
totalTask: 'Total Task',
|
||||||
|
runningTask: 'Running Task',
|
||||||
|
load: 'Load',
|
||||||
|
disk: 'Disk',
|
||||||
|
mountPoint: 'Mount Point',
|
||||||
|
available: 'Available',
|
||||||
|
used: 'Used',
|
||||||
|
networkCard: 'Network Card',
|
||||||
|
receive: 'Receive',
|
||||||
|
send: 'Send',
|
||||||
|
memory: 'Memory',
|
||||||
|
cpuUsageRate: 'Cpu Usage Rate',
|
||||||
|
|
||||||
|
// process
|
||||||
|
processName: 'Process Name',
|
||||||
|
selectSortType: 'Please select a sort type',
|
||||||
|
selectProcessNum: 'Please select the number of processes',
|
||||||
|
cpuDesc: 'CUP descending',
|
||||||
|
memDesc: 'Memory descending',
|
||||||
|
virtualMemory: 'Virtual Memory',
|
||||||
|
fixedMemory: 'Fixed Memory',
|
||||||
|
procState: 'process state',
|
||||||
|
startTime: 'Start Time',
|
||||||
|
procCpuRunTime: 'The actual CPU time used by the process',
|
||||||
|
killProcConfirm: 'Are you sure to terminate the process?',
|
||||||
|
kill: 'Kill',
|
||||||
|
|
||||||
|
// script
|
||||||
|
execute: 'Execute',
|
||||||
|
scriptParam: 'Script Param',
|
||||||
|
execResult: 'result of execution',
|
||||||
|
execCompleted: 'execution is completed',
|
||||||
|
scriptParamTips1: '1. You can use {{.model}} as a placeholder in the script content',
|
||||||
|
scriptParamTips2: '2. When executing the script, you can enter the corresponding form content to replace the placeholder',
|
||||||
|
scriptResultEnumResult: 'Have result',
|
||||||
|
scriptResultEnumNoResult: 'No result',
|
||||||
|
scriptResultEnumRealTime: 'Real-time',
|
||||||
|
scriptTypeEnumPrivate: 'Private',
|
||||||
|
scriptTypeEnumPublic: 'Public',
|
||||||
|
|
||||||
|
// security
|
||||||
|
cmdConfig: 'Command Config',
|
||||||
|
filterCmds: 'Filter command',
|
||||||
|
relateMachine: 'Associated machine',
|
||||||
|
newCmd: 'New Command',
|
||||||
|
cmdPlaceholder: 'Enter the command regular expression',
|
||||||
|
|
||||||
|
// cronjob
|
||||||
|
cronjob: 'Cronjob',
|
||||||
|
machineCode: 'Machine Code',
|
||||||
|
cronjobRunning: 'Running',
|
||||||
|
cronjobNoRun: 'Not Run',
|
||||||
|
cronjobRun: 'Execute',
|
||||||
|
cronJobExecStatusEnumSuccess: 'Success',
|
||||||
|
cronJobExecStatusEnumFail: 'Fail',
|
||||||
|
cronjobExecResult: 'Execute Result',
|
||||||
|
cronjobExecTime: 'Execute Time',
|
||||||
|
cronjobExecRecord: 'Record of execution',
|
||||||
|
runSuccess: 'Executed successfully',
|
||||||
|
cronjobRunState: 'Run State',
|
||||||
|
execResRecordType: 'Result record type',
|
||||||
|
cronExpression: 'Cron Expression',
|
||||||
|
|
||||||
|
// file
|
||||||
|
upload: 'Upload',
|
||||||
|
download: 'Download',
|
||||||
|
copy: 'Copy',
|
||||||
|
move: 'Move',
|
||||||
|
paste: 'Paste',
|
||||||
|
fileNameFilterPlaceholder: 'Name: Input filterable',
|
||||||
|
calculate: 'Calculate',
|
||||||
|
modificationTime: 'Modify Time',
|
||||||
|
attribute: 'Attribute',
|
||||||
|
user: 'User',
|
||||||
|
group: 'Group',
|
||||||
|
renameTips: 'rename: Double-click the file name cell and then press Ente',
|
||||||
|
fileDetail: 'File Details',
|
||||||
|
createFile: 'Create File',
|
||||||
|
pasteSuccess: 'Paste successfully',
|
||||||
|
sameDirNoPaste: 'Can not paste in the same directory',
|
||||||
|
renameSuccess: 'Rename successfully',
|
||||||
|
newFileNameNotEmpty: 'he new name cannot be empty',
|
||||||
|
fileTooLargeTips: 'The file is too large, please download and use it',
|
||||||
|
uploadSuccess: 'Upload successfully',
|
||||||
|
fileExceedsSysConf: 'The uploaded file exceeds the system configuration [{uploadMaxFileSize}]',
|
||||||
|
},
|
||||||
|
};
|
||||||
44
frontend/src/i18n/en/mongo.ts
Normal file
44
frontend/src/i18n/en/mongo.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
export default {
|
||||||
|
mongo: {
|
||||||
|
mongo: 'MongoDB',
|
||||||
|
db: 'DB',
|
||||||
|
keywordPlaceholder: 'host / name / code',
|
||||||
|
connUrl: 'Connection URL',
|
||||||
|
|
||||||
|
dbList: 'DB List',
|
||||||
|
isEmpty: 'Is Empty',
|
||||||
|
deleteDbConfirm: 'Make sure to delete the db?',
|
||||||
|
coll: 'Collection',
|
||||||
|
deleteCollConfirm: 'Are you sure to delete the collection??',
|
||||||
|
collState: 'Collection State',
|
||||||
|
createDbAndColl: 'Crate DB & Collection',
|
||||||
|
dbName: 'DB Name',
|
||||||
|
collName: 'Collection Name',
|
||||||
|
createColl: 'Create Collection',
|
||||||
|
collTitle: '`{dbName}` Collection',
|
||||||
|
|
||||||
|
template: 'Template',
|
||||||
|
cmdTemplatePlaceholder: 'Select command template',
|
||||||
|
moreCmdTips: 'Select more commands to view ',
|
||||||
|
usersInfoDesc: 'Get user information',
|
||||||
|
createUserDesc: 'Create a new user',
|
||||||
|
grantRolesToUserDesc: 'Grants additional roles to the user',
|
||||||
|
dropUserDesc: 'Drop User',
|
||||||
|
roleInfoDesc: 'Get Role Information',
|
||||||
|
createRoleDesc: 'Create Role',
|
||||||
|
runSuccess: 'Run successfully',
|
||||||
|
|
||||||
|
queryParam: 'query parameter',
|
||||||
|
queryParamPlaceholder: 'Click to enter the corresponding search conditions',
|
||||||
|
deleteDocConfirm: 'Are you sure to delete the document?',
|
||||||
|
doc: 'Document',
|
||||||
|
findParamErrMsg: 'The filter or sort field json string value is incorrect. Note: The json key requires double quotes',
|
||||||
|
docErrMsg: 'The document content is incorrect and cannot be parsed into a json object',
|
||||||
|
insertSuccess: 'Insert successfully',
|
||||||
|
insertFail: 'Insert failure',
|
||||||
|
idNotExist: 'The _id attribute for the document does not exist',
|
||||||
|
modifyFail: 'fail to modify',
|
||||||
|
deleteFail: 'fail to delete',
|
||||||
|
docParse2jsonFail: 'Parsing the document content into a json object failed',
|
||||||
|
},
|
||||||
|
};
|
||||||
66
frontend/src/i18n/en/redis.ts
Normal file
66
frontend/src/i18n/en/redis.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
export default {
|
||||||
|
redis: {
|
||||||
|
standaloneInfo: 'Standalone',
|
||||||
|
clusterInfo: 'Cluster',
|
||||||
|
node: 'Node',
|
||||||
|
clusterIpTips:
|
||||||
|
'p:port1@port2 :port1 indicates the port through which the redis server communicates with clients, and port2 indicates the port through which nodes in the cluster communicate',
|
||||||
|
masterSlaveRelationTips: `If the node is slave and the master node is known, it is the ID of the master node. Otherwise, the symbol '-'`,
|
||||||
|
configEpochTips:
|
||||||
|
'The epoch value of a node (or the epoch value of its primary node if the node is a slave node). Each time a node fails to switch, a new, unique, increasing epoch is created.',
|
||||||
|
keywordPlaceholder: 'host / name / code',
|
||||||
|
hostTips: `Enter host:port; The sentinel mode is mastername=sentinelhost:port. If the cluster or sentinels need multiple nodes, they can be separated by ','`,
|
||||||
|
nodePassword: 'Node Password',
|
||||||
|
sentinelHostErr: 'Sentinel model host for: mastername = sentinelhost: sentinelport mode',
|
||||||
|
delimiter: 'Delimiter',
|
||||||
|
keyMatchTips: 'match supports * obfuscated key, enter search',
|
||||||
|
loadMore: 'Load More',
|
||||||
|
addKey: 'Adding key',
|
||||||
|
newTabOpen: 'New tab opens',
|
||||||
|
redisSelectErr: 'Select redis first',
|
||||||
|
flushDbTips: 'Make sure to clear all keys of the [{db}] library?',
|
||||||
|
keyNotEmpty: 'The Key cannot be empty',
|
||||||
|
|
||||||
|
// info
|
||||||
|
redisInfoTitle: 'Redis server information',
|
||||||
|
version: 'Version',
|
||||||
|
port: 'Port',
|
||||||
|
mode: 'Mode',
|
||||||
|
os: 'os',
|
||||||
|
uptimeDays: 'Uptime in days',
|
||||||
|
execPath: 'Executable',
|
||||||
|
confFile: 'Config file',
|
||||||
|
clusterEnable: 'Cluster enabled',
|
||||||
|
nodeCount: 'Node count',
|
||||||
|
clientConn: 'Client Connection',
|
||||||
|
connectedNum: 'Connected clients',
|
||||||
|
blockedClientNum: 'Blocked clients',
|
||||||
|
sysCpu: 'used_cpu_sys',
|
||||||
|
userCpu: 'used_cpu_user',
|
||||||
|
sysChildCpu: 'used_cpu_sys_children',
|
||||||
|
userChildCpu: 'used_cpu_user_children',
|
||||||
|
keyCount: 'Key Count',
|
||||||
|
countInfo: 'Count',
|
||||||
|
totalCmdProcess: 'total_commands_processed',
|
||||||
|
curQps: 'instantaneous_ops_per_sec',
|
||||||
|
expiredKeys: 'expired_keys',
|
||||||
|
netInputBytes: 'total_net_input_bytes',
|
||||||
|
netOutputBytes: 'total_net_output_bytes',
|
||||||
|
persistence: 'Persistence',
|
||||||
|
aofEnable: 'aof_enabled',
|
||||||
|
loadingPersistence: 'loading',
|
||||||
|
availableMemory: 'Available',
|
||||||
|
usedMemory: 'Used',
|
||||||
|
|
||||||
|
renameTips: 'Click to rename',
|
||||||
|
ttlPlaceholder: 'Unit (seconds); negative values are permanent',
|
||||||
|
ttlTips: 'Click Change the expiration time',
|
||||||
|
settingSuccess: 'successfully set',
|
||||||
|
permanent: 'Permanent',
|
||||||
|
persistenceConfirm: 'Decide to persist the key?',
|
||||||
|
|
||||||
|
addNewLine: 'Adding new rows',
|
||||||
|
filterPlaceholder: 'Keyword Enter search',
|
||||||
|
deleteConfirm: 'Sure to delete?',
|
||||||
|
},
|
||||||
|
};
|
||||||
212
frontend/src/i18n/en/system.ts
Normal file
212
frontend/src/i18n/en/system.ts
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
export default {
|
||||||
|
system: {
|
||||||
|
menu: {
|
||||||
|
filterPlaceholder: 'Input keyword filter (right click operation)',
|
||||||
|
opTips: 'Red and orange fonts indicate disabled status (right click on the resource to operate)',
|
||||||
|
info: 'Information',
|
||||||
|
menu: 'Menu',
|
||||||
|
permission: 'Permission',
|
||||||
|
icon: 'Icon',
|
||||||
|
routerName: 'Router Name',
|
||||||
|
componentPath: 'Component Path',
|
||||||
|
isCache: 'Cache or not',
|
||||||
|
isHide: 'Whether to hide',
|
||||||
|
tagIsDelete: 'Tag cannot be deleted',
|
||||||
|
externalLink: 'External Link',
|
||||||
|
yes: 'Yes',
|
||||||
|
no: 'No',
|
||||||
|
addSubResource: 'Adding subresources',
|
||||||
|
enable: 'Enable',
|
||||||
|
disable: 'Disable',
|
||||||
|
tips: 'Tips',
|
||||||
|
addTopMenu: 'Add a top-level menu',
|
||||||
|
addChildrenMenuTitle: 'Adds `{parentName}` subresources',
|
||||||
|
updateMenu: 'Change `{name}`',
|
||||||
|
success: 'Success',
|
||||||
|
menuCodeTips: `The menu type is the access path (if the menu path does not begin with '/', the access address will automatically concatenate the parent menu path), otherwise it is the unique code of the resource`,
|
||||||
|
menuCodePlaceholder: `A menu that does not begin with '/' will automatically concatenate the parent menu path`,
|
||||||
|
routerNameTips: 'For component caching to work, match the vue component name, such as ResourceLis',
|
||||||
|
componentPathTips: 'Access path components, such as: ` system/resource/ResourceList `, default in ` views ` directory',
|
||||||
|
isCacheTips: `If yes is selected, it will be 'keepalive' cached (reentering the page without refreshing the page and requesting data again), and needs the route name to match the vue component name`,
|
||||||
|
isHideTips:
|
||||||
|
'Select Hide and the route will not appear in the menu bar, but it will still be accessible. Disabled will not be able to access and operate',
|
||||||
|
externalLinkTips: 'Inline: displayed as an iframe, external link: opened in a new TAB',
|
||||||
|
inline: 'Embedded',
|
||||||
|
linkAddress: 'Link Address',
|
||||||
|
linkPlaceholder: 'External/embedded links (http://xxx.com)',
|
||||||
|
menuNameRuleMsg: 'Please enter a resource name',
|
||||||
|
routeNameNotEmpty: 'Route names cannot be empty',
|
||||||
|
resourceCodePatternErrMsg: 'Only 1-32 uppercase letters, numbers, and -.: characters are allowed',
|
||||||
|
assignedRole: 'Assigned Role',
|
||||||
|
},
|
||||||
|
account: {
|
||||||
|
roleAllocation: 'Role Allocation',
|
||||||
|
resetOtp: 'Reset OTP',
|
||||||
|
roleName: 'Role Name',
|
||||||
|
assigner: 'Assigner',
|
||||||
|
allocateTime: 'Allocate Time',
|
||||||
|
name: 'Name',
|
||||||
|
lastLoginTime: 'Last Login Time',
|
||||||
|
usernamePlacholder: '5-16 uppercase letters, numbers, -.: characters',
|
||||||
|
random: 'Random',
|
||||||
|
usernamePatternErrMsg: 'Only 5-16 uppercase letters, numbers, and -.: characters are allowed',
|
||||||
|
accountSearchPlaceholder: 'Enter account fuzzy search and select',
|
||||||
|
accountInfo: 'Account Information',
|
||||||
|
allocateRoleTitle: 'Allocate the `{name}` role',
|
||||||
|
allocated: 'Allocated',
|
||||||
|
undistributed: 'Undistributed',
|
||||||
|
menuAndPermission: 'Menu & Permission',
|
||||||
|
remove: 'Remove',
|
||||||
|
allocation: 'Allocation',
|
||||||
|
roleCode: 'Role Code',
|
||||||
|
roleStatus: 'Role Status',
|
||||||
|
userMenuTitle: '`{name}` menus and permissions',
|
||||||
|
statusEnable: 'Enable',
|
||||||
|
statusDisable: 'Disable',
|
||||||
|
},
|
||||||
|
role: {
|
||||||
|
permissionDetail: 'Permission',
|
||||||
|
permissionAllocate: 'Permission Alloctate',
|
||||||
|
userManage: 'User',
|
||||||
|
roleName: 'Role Name',
|
||||||
|
roleCode: 'Role Code',
|
||||||
|
rolePermissionTitle: '`{name}` menus and permissions',
|
||||||
|
roleCodePlaceholder: 'COMMON begins with the role shared by all accounts',
|
||||||
|
statusEnable: 'Enable',
|
||||||
|
statusDisable: 'Disable',
|
||||||
|
allocateMenuTitle: 'Allocate permissions to `{roleName}`',
|
||||||
|
allocateAccountTitle: 'Account associated with `{roleName}`',
|
||||||
|
addAccount: 'Adding an account',
|
||||||
|
userStatus: 'User Status',
|
||||||
|
assigner: 'Assigner',
|
||||||
|
allocateTime: 'Allocate Time',
|
||||||
|
permissionInfo: 'Permission assignment information',
|
||||||
|
},
|
||||||
|
sysconf: {
|
||||||
|
confItem: 'Config Item',
|
||||||
|
confKey: ' Config Key',
|
||||||
|
permission: 'Permission',
|
||||||
|
permissionPlaceholder: 'Please enter account fuzzy search and select',
|
||||||
|
conf: 'Config',
|
||||||
|
confItemSetting: 'Config Item Setting',
|
||||||
|
confValue: 'Config Value',
|
||||||
|
|
||||||
|
fileConf: 'File Config',
|
||||||
|
fileConfRemark: 'System file config',
|
||||||
|
basePath: 'Base path',
|
||||||
|
baesPathPlaceholder: 'The default is ./file in the directory corresponding to the executable file',
|
||||||
|
|
||||||
|
dbmsConf: 'DBMS Config',
|
||||||
|
dbmsConfRemark: 'DBMS Config',
|
||||||
|
recordQuerySql: 'Record Query Sql',
|
||||||
|
recordQuerySqlPlaceholder: 'Whether to record queries sql',
|
||||||
|
maxResultSet: 'Max Result Set',
|
||||||
|
maxResultSetPlaceholder: 'Maximum number of result sets allowed for sql queries. Note: 0= no limit',
|
||||||
|
sqlExecLimt: 'sql execution time limit',
|
||||||
|
sqlExecLimtPlaceholder: 'After that time (in seconds), the execution is aborted',
|
||||||
|
|
||||||
|
machineConf: 'Machine Config',
|
||||||
|
machineConfRemark: 'Machine related configuration, such as the number of days terminal operation records are kept',
|
||||||
|
uploadMaxFileSize: 'Upload file size limit',
|
||||||
|
uploadMaxFileSizePlaceholder: 'Maximum file size allowed to upload (1MB, 2GB, etc.)',
|
||||||
|
termOpSaveDays: 'Terminal records the retention time',
|
||||||
|
termOpSaveDaysPlaceholder: 'Unit day, after which the terminal operation record will be deleted',
|
||||||
|
guacdHost: 'guacd server ip',
|
||||||
|
guacdHostPlaceholder: 'guacd server ip, default 127.0.0.1',
|
||||||
|
guacdPort: 'guacd server port',
|
||||||
|
guacdPortPlaceholder: 'guacd server port, default 4822',
|
||||||
|
guacdFilePath: 'guacd server file path',
|
||||||
|
guacdFilePathPlaceholder: 'guacd serves the file storage location for mounting the RDP folder',
|
||||||
|
|
||||||
|
systemConf: 'System-wide styling',
|
||||||
|
systemConfRemark: 'Configuration of system icon, title, watermark information, etc',
|
||||||
|
logoIcon: 'Logo Icon',
|
||||||
|
logoIconPlaceholder: 'System logo icon (base64 encoded, svg format recommended, no more than 10k)',
|
||||||
|
title: 'Menu bar title',
|
||||||
|
titlePlaceholder: 'System menu bar title display',
|
||||||
|
viceTitle: 'Login page title',
|
||||||
|
viceTitlePlaceholder: 'The login page title is displayed',
|
||||||
|
useWatermark: 'Watermarking',
|
||||||
|
useWatermarkPlaceholder: 'Whether system watermarking is enabled',
|
||||||
|
watermarkContent: 'Watermark information',
|
||||||
|
watermarkContentPlaceholder: 'Watermark supplementary information, such as company name, etc',
|
||||||
|
|
||||||
|
ldapLoginConf: 'LDAP Login Config',
|
||||||
|
ldapLoginConfRemark: 'LDAP Login Config',
|
||||||
|
ldapEnable: 'Enable',
|
||||||
|
dapEnablePlaceholder: 'Whether ldap login is enabled',
|
||||||
|
host: 'host',
|
||||||
|
port: 'port',
|
||||||
|
bindDN: 'bindDN',
|
||||||
|
bindDnPlaceholder: 'admin account for the LDAP service, for example: "cn=admin,dc=example,dc=com"',
|
||||||
|
bindPwd: 'bindPwd',
|
||||||
|
bindPwdPlaceholder: 'The administrator password for the LDAP service',
|
||||||
|
baseDN: 'baseDN',
|
||||||
|
baseDnPlaceholder: 'The user\'s base DN, for example: "ou=users,dc=example,dc=com"',
|
||||||
|
userFilter: 'userFilter',
|
||||||
|
userFilerPlaceholder: 'How to filter users, such as "(uid=%s), (&(objectClass=organizationalPerson)(uid=%s))"',
|
||||||
|
uidMap: 'uidMap',
|
||||||
|
uidMapPlaceholder: 'Mapping between user id and LDAP field name, such as: cn',
|
||||||
|
udnMap: 'udnMap',
|
||||||
|
udnMapPlaceholder: 'mapping between user name (dispalyName) and LDAP field name, such as displayName',
|
||||||
|
emailMap: 'emailMap',
|
||||||
|
emailMapPlaceholder: 'Mapping between user email and LDAP field name',
|
||||||
|
skipTlsVerfify: 'skipTlsVerfify',
|
||||||
|
skipTlsVerfifyPlaceholder: 'Whether the client skips TLS certificate validation',
|
||||||
|
securityProtocol: 'security protocol',
|
||||||
|
securityProtocolPlaceholder: 'Security protocol (Null does not use security protocol), such as StartTLS, LDAPS',
|
||||||
|
|
||||||
|
oauth2LoginConf: 'OAuth2 Login Config',
|
||||||
|
oauth2LoginConfRemark: 'OAuth2 Login Config',
|
||||||
|
oauth2Enable: 'Enable',
|
||||||
|
oauth2EnablePlaceholder: 'Whether oauth2 login is enabled or not',
|
||||||
|
name: 'Name',
|
||||||
|
namePlaceholder: 'oauth2 name',
|
||||||
|
clientId: 'Client ID',
|
||||||
|
clientIdPlaceholder: 'oauth2 Client ID',
|
||||||
|
clientSecret: 'Client Secret',
|
||||||
|
clientSecretPlaceholder: 'oauth2 Client Secret',
|
||||||
|
authorizationUrl: 'Authorization URL',
|
||||||
|
authorizationUrlPlaceholder: 'oauth2 Authorization url',
|
||||||
|
accessTokenUrl: 'Access Token URL',
|
||||||
|
accessTokenUrlPlaceholder: 'oauth2 gets the token url',
|
||||||
|
redirectUrl: 'Redirect URL',
|
||||||
|
redirectUrlPlaceholder: 'This system url',
|
||||||
|
scope: 'Scopes',
|
||||||
|
scopePlaceholder: 'oauth2 Scopes',
|
||||||
|
resourceUrl: 'Resource URL',
|
||||||
|
resourceUrlPlaceholder: 'Get the user information resource url',
|
||||||
|
userId: 'User ID',
|
||||||
|
userIdPlaceholder: 'User unique identification field The format is type:fieldPath(string:username)',
|
||||||
|
autoRegister: 'Automatic registration',
|
||||||
|
|
||||||
|
accountLoginConf: 'Login Security Settings',
|
||||||
|
accountLoginConfRemark: 'Account Login Security Settings',
|
||||||
|
useCaptcha: 'Login verification code',
|
||||||
|
useCaptchaPlaceholder: 'Whether to enable the login CAPTCHA',
|
||||||
|
useOtp: 'OTP',
|
||||||
|
useOtpPlaceholder: 'Whether two-factor (OTP) validation is enabled',
|
||||||
|
otpIssuer: 'OTP Issuer',
|
||||||
|
loginFailCount: 'Number of login failures',
|
||||||
|
loginFailCountPlaceholder: 'Disable login after n failed login attempts',
|
||||||
|
loginFainMin: 'Prohibited login time',
|
||||||
|
loginFailMinPlaceholder: 'After a specified number of login failures, re-login is prohibited within m minutes',
|
||||||
|
},
|
||||||
|
syslog: {
|
||||||
|
operator: 'Operator',
|
||||||
|
operatorPlaceholder: 'Please enter and select an account number',
|
||||||
|
operatingResult: 'Operating Result',
|
||||||
|
description: 'Description',
|
||||||
|
operatingTime: 'Operating Time',
|
||||||
|
operatingInfo: 'Operating Information',
|
||||||
|
result: 'Result',
|
||||||
|
response: 'Response',
|
||||||
|
resultSuccess: 'Success',
|
||||||
|
resultFail: 'Fail',
|
||||||
|
resultRunning: 'Running',
|
||||||
|
},
|
||||||
|
oauth: {
|
||||||
|
authSuccess: 'Authorization succeeded',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
55
frontend/src/i18n/en/tag.ts
Normal file
55
frontend/src/i18n/en/tag.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
export default {
|
||||||
|
tag: {
|
||||||
|
relateTag: 'Relate Tag',
|
||||||
|
keywordFilterPlaceholder: 'keyword filter',
|
||||||
|
nameFilterPlaceholder: 'Keyword filtering (right-click node operation)',
|
||||||
|
tagFilterPlaceholder: 'Enter the keyword -> Search for expanded node information',
|
||||||
|
tagTips1: '1. Used to group assets',
|
||||||
|
tagTips2: '2. Can be allocated in team management for resource isolation',
|
||||||
|
tagTips3: '3. Team members who own a parent tag have access to resources that manipulate their own or child tag associations',
|
||||||
|
machine: 'Machine',
|
||||||
|
db: 'Db',
|
||||||
|
code: 'Code',
|
||||||
|
createSubTag: 'Creating child tags',
|
||||||
|
createSubTagTitle: 'Creates a child tag for {codePath}',
|
||||||
|
rootTag: 'Root Tag',
|
||||||
|
selectTagPlaceholder: 'Select the associated tag',
|
||||||
|
},
|
||||||
|
team: {
|
||||||
|
team: 'Team',
|
||||||
|
member: 'Member',
|
||||||
|
addMember: 'Adding members',
|
||||||
|
teamMember: '[{teamName}] Member information',
|
||||||
|
selectAccountTips: 'Please select your account first',
|
||||||
|
joinTime: 'Join Date',
|
||||||
|
accountName: 'Account Name',
|
||||||
|
assigner: 'Assigner',
|
||||||
|
allocateTag: 'Assigned tags',
|
||||||
|
validity: 'Validity Date',
|
||||||
|
effectiveStartTime: 'Effective Start Time',
|
||||||
|
effectiveEndTime: 'Effective End Time',
|
||||||
|
},
|
||||||
|
// authcert
|
||||||
|
ac: {
|
||||||
|
namePlaceholder: 'Please enter a credential name (globally unique)',
|
||||||
|
privateKeyPlaceholder: 'Please copy the contents of the private key file here',
|
||||||
|
privateKeyPwd: 'Secret key passphrase',
|
||||||
|
resourceCode: 'Resource Code',
|
||||||
|
credentialName: 'Credential Name',
|
||||||
|
resourceType: 'Resource Type',
|
||||||
|
credentialType: 'Credential Type',
|
||||||
|
ciphertextType: 'Ciphertext Type',
|
||||||
|
privateKey: 'Private Key',
|
||||||
|
ac: 'Credential',
|
||||||
|
testConn: 'Test Connection',
|
||||||
|
usernameExist: 'The username already exists in the account list',
|
||||||
|
publicAc: 'Public credentials',
|
||||||
|
acTypeEnumPublic: 'Public credentials',
|
||||||
|
acTypeEnumPrivate: 'Ordinary certificate',
|
||||||
|
acTypeEnumPrivileged: 'Privilege credentials',
|
||||||
|
acTypeEnumPrivateDefault: 'Default credentials',
|
||||||
|
ciphertextTypeEnumPassword: 'Password',
|
||||||
|
ciphertextTypeEnumPrivateKey: 'Private key',
|
||||||
|
ciphertextTypeEnumPublic: 'Public credentials',
|
||||||
|
},
|
||||||
|
};
|
||||||
56
frontend/src/i18n/index.ts
Normal file
56
frontend/src/i18n/index.ts
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
// 定义语言国际化内容
|
||||||
|
/**
|
||||||
|
* 说明:
|
||||||
|
* 注意国际化定义的字段,不要与原有的定义字段相同。
|
||||||
|
* /src/i18n/(zh-cn、en...)/module.ts 下的 ts 为各模块国际化内容。
|
||||||
|
*/
|
||||||
|
import { createI18n } from 'vue-i18n';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { useThemeConfig } from '@/store/themeConfig';
|
||||||
|
import pinia from '@/store';
|
||||||
|
import { I18nEnum } from '@/common/commonEnum';
|
||||||
|
|
||||||
|
const modules: Record<string, any> = import.meta.glob('./**/*.ts', { eager: true });
|
||||||
|
|
||||||
|
// 读取 pinia 默认语言
|
||||||
|
const { themeConfig } = storeToRefs(useThemeConfig(pinia));
|
||||||
|
|
||||||
|
function initI18n() {
|
||||||
|
// 定义变量内容
|
||||||
|
const messages: any = {};
|
||||||
|
const itemizeMap = new Map<string, any[]>();
|
||||||
|
|
||||||
|
// 对自动引入的 modules 进行分类 en-us、zh-cn
|
||||||
|
// https://vitejs.cn/vite3-cn/guide/features.html#glob-import
|
||||||
|
for (const path in modules) {
|
||||||
|
const parts = path.split('/');
|
||||||
|
const i18n = parts[1];
|
||||||
|
|
||||||
|
const msgs = modules[path].default;
|
||||||
|
if (itemizeMap.get(i18n)) {
|
||||||
|
itemizeMap.get(i18n)?.push(modules[path].default);
|
||||||
|
} else {
|
||||||
|
itemizeMap.set(i18n, [msgs]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理最终格式
|
||||||
|
itemizeMap.forEach((value, key) => {
|
||||||
|
messages[key] = Object.assign({}, ...value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// https://vue-i18n.intlify.dev/guide/essentials/fallback.html#explicit-fallback-with-one-locale
|
||||||
|
return createI18n({
|
||||||
|
legacy: false,
|
||||||
|
silentTranslationWarn: true,
|
||||||
|
missingWarn: false,
|
||||||
|
silentFallbackWarn: true,
|
||||||
|
fallbackWarn: false,
|
||||||
|
locale: themeConfig.value.globalI18n,
|
||||||
|
fallbackLocale: I18nEnum.ZhCn.value,
|
||||||
|
messages,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出语言国际化
|
||||||
|
export const i18n = initI18n();
|
||||||
453
frontend/src/i18n/zh-cn/common.ts
Normal file
453
frontend/src/i18n/zh-cn/common.ts
Normal file
@@ -0,0 +1,453 @@
|
|||||||
|
// 定义内容
|
||||||
|
export default {
|
||||||
|
common: {
|
||||||
|
create: '创建',
|
||||||
|
edit: '编辑',
|
||||||
|
delete: '删除',
|
||||||
|
detail: '详情',
|
||||||
|
add: '添加',
|
||||||
|
save: '保存',
|
||||||
|
remove: '移除',
|
||||||
|
confirm: '确定',
|
||||||
|
cancel: '取消',
|
||||||
|
submit: '提交',
|
||||||
|
operation: '操作',
|
||||||
|
name: '名称',
|
||||||
|
code: '编号',
|
||||||
|
remark: '备注',
|
||||||
|
status: '状态',
|
||||||
|
username: '用户名',
|
||||||
|
role: '角色',
|
||||||
|
msg: '消息',
|
||||||
|
type: '类型',
|
||||||
|
time: '时间',
|
||||||
|
account: '账号',
|
||||||
|
password: '密码',
|
||||||
|
createTime: '创建时间',
|
||||||
|
creator: '创建者',
|
||||||
|
updateTime: '更新时间',
|
||||||
|
modifier: '修改者',
|
||||||
|
keyword: '关键字',
|
||||||
|
path: '路径',
|
||||||
|
tag: '标签',
|
||||||
|
more: '更多',
|
||||||
|
enable: '启用',
|
||||||
|
disable: '禁用',
|
||||||
|
hint: '提示',
|
||||||
|
yes: '是',
|
||||||
|
no: '否',
|
||||||
|
refresh: '刷新',
|
||||||
|
basic: '基本',
|
||||||
|
other: '其他',
|
||||||
|
reset: '重置',
|
||||||
|
success: '成功',
|
||||||
|
fail: '失败',
|
||||||
|
previousStep: '上一步',
|
||||||
|
nextStep: '下一步',
|
||||||
|
copy: '复制',
|
||||||
|
pleaseInput: '请输入{label}',
|
||||||
|
pleaseSelect: '请选择{label}',
|
||||||
|
formValidationError: '请正确填写表单信息',
|
||||||
|
createTitle: '创建{name}',
|
||||||
|
editTitle: '编辑{name}',
|
||||||
|
detailTitle: '{name}详情',
|
||||||
|
deleteConfirm: '此操作将删除【{name}】, 是否继续?',
|
||||||
|
saveSuccess: '保存成功',
|
||||||
|
deleteSuccess: '删除成功',
|
||||||
|
operateSuccess: '操作成功',
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
user: {
|
||||||
|
title0: '组件大小',
|
||||||
|
langSwitch: '语言切换',
|
||||||
|
menuSearch: '菜单搜索',
|
||||||
|
layoutConf: '布局配置',
|
||||||
|
news: '消息',
|
||||||
|
fullScreenOn: '开全屏',
|
||||||
|
fullScreenOff: '关全屏',
|
||||||
|
dropdownLarge: '大型',
|
||||||
|
dropdownDefault: '默认',
|
||||||
|
dropdownSmall: '小型',
|
||||||
|
index: '首页',
|
||||||
|
personalCenter: '个人中心',
|
||||||
|
logout: '退出登录',
|
||||||
|
searchPlaceholder: '菜单搜索',
|
||||||
|
newTitle: '通知',
|
||||||
|
newBtn: '全部已读',
|
||||||
|
newGo: '前往通知中心',
|
||||||
|
newDesc: '暂无通知',
|
||||||
|
logOutTitle: '提示',
|
||||||
|
logOutMessage: '此操作将退出登录, 是否继续?',
|
||||||
|
logOutExit: '退出中',
|
||||||
|
logoutSuccess: '安全退出成功!',
|
||||||
|
},
|
||||||
|
tagsView: {
|
||||||
|
refresh: '刷新',
|
||||||
|
close: '关闭',
|
||||||
|
closeOther: '关闭其它',
|
||||||
|
closeAll: '全部关闭',
|
||||||
|
fullscreen: '当前页全屏',
|
||||||
|
closeFullscreen: '关闭全屏',
|
||||||
|
},
|
||||||
|
notFound: {
|
||||||
|
title: '地址输入错误,请重新输入地址~',
|
||||||
|
msg: '您可以先检查网址,然后重新输入或给我们反馈问题。',
|
||||||
|
backHomepage: '返回首页',
|
||||||
|
},
|
||||||
|
noAccess: {
|
||||||
|
title: '您未被授权,没有操作权限~',
|
||||||
|
loginAgain: '重新登录',
|
||||||
|
},
|
||||||
|
config: {
|
||||||
|
configTitle: '布局配置',
|
||||||
|
terminalTheme: '终端主题',
|
||||||
|
theme: '主题',
|
||||||
|
custom: '自定义',
|
||||||
|
fontColor: '字体颜色',
|
||||||
|
backgroundColor: '背景颜色',
|
||||||
|
cursorColor: '光标颜色',
|
||||||
|
fontSize: '字体大小',
|
||||||
|
fontWeight: '字体粗细',
|
||||||
|
editorSetting: 'Editor 设置',
|
||||||
|
globalSetting: '全局设置',
|
||||||
|
pagesize: '分页size',
|
||||||
|
globalTheme: '全局主题',
|
||||||
|
|
||||||
|
// 菜单设置
|
||||||
|
menuSetting: '菜单设置',
|
||||||
|
menuBar: '菜单背景',
|
||||||
|
menuBarFontColor: '菜单默认字体颜色',
|
||||||
|
menuBarActiveColor: '菜单高亮背景色',
|
||||||
|
isMenuBarColorGradual: '菜单背景渐变',
|
||||||
|
|
||||||
|
// 顶栏设置
|
||||||
|
topTitle: '顶栏设置',
|
||||||
|
twoColumnsTitle: '分栏设置',
|
||||||
|
twoTopBar: '顶栏背景',
|
||||||
|
twoTopBarColor: '顶栏默认字体颜色',
|
||||||
|
twoIsTopBarColorGradual: '顶栏背景渐变',
|
||||||
|
|
||||||
|
twoColumnsMenuBar: '分栏菜单背景',
|
||||||
|
twoColumnsMenuBarColor: '分栏菜单默认字体颜色',
|
||||||
|
twoIsColumnsMenuBarColorGradual: '分栏菜单背景渐变',
|
||||||
|
twoIsColumnsMenuHoverPreload: '分栏菜单鼠标悬停预加载',
|
||||||
|
|
||||||
|
// 界面设置
|
||||||
|
interfaceSetting: '界面设置',
|
||||||
|
isCollapse: '菜单水平折叠',
|
||||||
|
isUniqueOpened: '菜单手风琴',
|
||||||
|
isFixedHeader: '固定 Header',
|
||||||
|
isClassicSplitMenu: '经典布局分割菜单',
|
||||||
|
isLockScreen: '开启锁屏',
|
||||||
|
lockScreenTime: '自动锁屏(s/秒)',
|
||||||
|
interfaceDisplay: '界面显示',
|
||||||
|
isShowLogo: '侧边栏 Logo',
|
||||||
|
isBreadcrumb: '开启 Breadcrumb',
|
||||||
|
isBreadcrumbIcon: '开启 Breadcrumb 图标',
|
||||||
|
isTagsview: '开启 Tagsview',
|
||||||
|
isTagsviewIcon: '开启 Tagsview 图标',
|
||||||
|
isCacheTagsView: '开启 TagsView 缓存',
|
||||||
|
isSortableTagsView: '开启 TagsView 拖拽',
|
||||||
|
// IsShareTagsView: '开启 TagsView 共用',
|
||||||
|
isFooter: '开启 Footer',
|
||||||
|
isGrayscale: '灰色模式',
|
||||||
|
isInvert: '色弱模式',
|
||||||
|
isDark: '深色模式',
|
||||||
|
// IsWartermark: '开启水印',
|
||||||
|
// WartermarkText: '水印文案',
|
||||||
|
|
||||||
|
// 其他设置
|
||||||
|
otherSetting: '其它设置',
|
||||||
|
tagsStyle: 'Tagsview 风格',
|
||||||
|
animation: '主页面切换动画',
|
||||||
|
columnsAsideStyle: '分栏高亮风格',
|
||||||
|
// fiveColumnsAsideLayout: '分栏布局风格',
|
||||||
|
|
||||||
|
layoutSwitch: '布局切换',
|
||||||
|
defaults: '默认',
|
||||||
|
classic: '经典',
|
||||||
|
transverse: '横向',
|
||||||
|
columns: '分栏',
|
||||||
|
// tipText: '点击下方按钮,复制布局配置去 `src/stores/themeConfig.ts` 中修改。',
|
||||||
|
// copyText: '一键复制配置',
|
||||||
|
// resetText: '一键恢复默认',
|
||||||
|
// copyTextSuccess: '复制成功!',
|
||||||
|
// copyTextError: '复制失败!',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
staticRoutes: {
|
||||||
|
signIn: '登录',
|
||||||
|
notFound: '找不到此页面',
|
||||||
|
noPower: '没有权限',
|
||||||
|
},
|
||||||
|
upgrade: {
|
||||||
|
title: '新版本升级',
|
||||||
|
msg: '新版本来啦,马上更新尝鲜吧!不用担心,更新很快的哦!',
|
||||||
|
desc: '提示:更新会还原默认配置',
|
||||||
|
btnOne: '残忍拒绝',
|
||||||
|
btnTwo: '马上更新',
|
||||||
|
btnTwoLoading: '更新中',
|
||||||
|
},
|
||||||
|
menu: {
|
||||||
|
index: '首页',
|
||||||
|
personalCenter: '个人中心',
|
||||||
|
|
||||||
|
tag: '标签管理',
|
||||||
|
tagTree: '标签树',
|
||||||
|
tagSave: '保存标签',
|
||||||
|
tagDelete: '删除标签',
|
||||||
|
authorization: '授权凭证',
|
||||||
|
authorizationBase: '基础权限',
|
||||||
|
authorizationSave: '保存权限',
|
||||||
|
authorizationDelete: '删除权限',
|
||||||
|
team: '团队管理',
|
||||||
|
teamSave: '保存团队',
|
||||||
|
teamDelete: '删除团队',
|
||||||
|
teamMemberAdd: '添加成员',
|
||||||
|
teamMemberDelete: '删除成员',
|
||||||
|
teamTagSave: '保存团队标签',
|
||||||
|
|
||||||
|
machine: '机器管理',
|
||||||
|
machineOp: '机器操作',
|
||||||
|
machineOpBase: '基本权限',
|
||||||
|
machineList: '机器列表',
|
||||||
|
machineBase: '基本权限',
|
||||||
|
machineCreate: '创建机器',
|
||||||
|
machineEdit: '编辑机器',
|
||||||
|
machineDelete: '删除机器',
|
||||||
|
machineTerminal: '机器终端',
|
||||||
|
machineFileConf: '文件管理',
|
||||||
|
machineFileConfCreate: '文件-添加配置',
|
||||||
|
machineFileConfDelete: '文件-删除配置',
|
||||||
|
machineFileCreate: '文件-创建',
|
||||||
|
machineFileDelete: '文件-删除',
|
||||||
|
machineFileWrite: '文件-写入',
|
||||||
|
machineFileUpload: '文件-上传',
|
||||||
|
machineScript: '脚本管理',
|
||||||
|
machineScriptSave: '脚本-保存',
|
||||||
|
machineScriptDelete: '脚本-删除',
|
||||||
|
machineScriptRun: '脚本-执行',
|
||||||
|
machineKillprocess: '终止进程',
|
||||||
|
machineCronJob: '计划任务',
|
||||||
|
machineCronJobSvae: '计划任务-保存',
|
||||||
|
machineCronJobDelete: '计划任务-删除',
|
||||||
|
machineSecurityConfig: '安全配置',
|
||||||
|
machineSecurityCmdSvae: '命令配置-保存',
|
||||||
|
machineSecurityCmdDelete: '命令配置-删除',
|
||||||
|
|
||||||
|
dbms: 'DBMS',
|
||||||
|
dbDataOp: '数据操作',
|
||||||
|
dbDataOpBase: '基本权限',
|
||||||
|
dbDataOpSqlScriptRun: 'SQL脚本执行',
|
||||||
|
dbInstance: '数据库实例',
|
||||||
|
dbInstanceBase: '基本权限',
|
||||||
|
dbInstanceSave: '保存实例',
|
||||||
|
dbInstanceDelete: '删除实例',
|
||||||
|
dbBase: '数据库基本权限',
|
||||||
|
dbSave: '保存数据库',
|
||||||
|
dbDelete: '删除数据库',
|
||||||
|
dbDataSync: '数据同步',
|
||||||
|
dbDataSyncBase: '基本权限',
|
||||||
|
dbDataSyncSave: '保存同步',
|
||||||
|
dbDataSyncDelete: '删除同步',
|
||||||
|
dbDataSyncChangeStatus: '启用停用',
|
||||||
|
dbDataSyncLog: '同步日志',
|
||||||
|
dbTransfer: '数据库迁移',
|
||||||
|
dbTransferBase: '基本权限',
|
||||||
|
dbTransferSave: '保存迁移任务',
|
||||||
|
dbTransferDelete: '删除迁移任务',
|
||||||
|
dbTransferChangeStatus: '启用停用',
|
||||||
|
dbTransferRun: '执行迁移任务',
|
||||||
|
dbTransferRunLog: '迁移日志查看',
|
||||||
|
dbTransferFileShow: '迁移文件-查看',
|
||||||
|
dbTransferFileDelete: '迁移文件-删除',
|
||||||
|
dbTransferFileDownload: '迁移文件-下载',
|
||||||
|
dbTransferFileRun: '迁移文件-执行',
|
||||||
|
|
||||||
|
redis: 'Redis',
|
||||||
|
redisDataOp: '数据操作',
|
||||||
|
redisDataOpBase: '基本权限',
|
||||||
|
redisDataOpSave: '数据保存',
|
||||||
|
redisDataOpDelete: '数据删除',
|
||||||
|
redisManage: 'Redis管理',
|
||||||
|
redisManageBase: '基本权限',
|
||||||
|
|
||||||
|
mongo: 'Mongo',
|
||||||
|
mongoDataOp: '数据操作',
|
||||||
|
mongoDataOpBase: '基本权限',
|
||||||
|
mongoDataOpSave: '数据保存',
|
||||||
|
mongoDataOpDelete: '数据删除',
|
||||||
|
mongoManage: 'Mongo管理',
|
||||||
|
mongoManageBase: '基本权限',
|
||||||
|
|
||||||
|
flow: '工单流程',
|
||||||
|
myTask: '我的任务',
|
||||||
|
myFlow: '我的流程',
|
||||||
|
flowProcDef: '流程定义',
|
||||||
|
flowProcDefSave: '保存流程定义',
|
||||||
|
flowProcDefDelete: '删除流程定义',
|
||||||
|
|
||||||
|
system: '系统管理',
|
||||||
|
menuPermission: '菜单权限',
|
||||||
|
menuPermissionBase: '基本权限',
|
||||||
|
menuPermissionAdd: '添加菜单权限',
|
||||||
|
menuPermissionEdit: '编辑菜单权限',
|
||||||
|
menuPermissionDelete: '删除菜单权限',
|
||||||
|
menuPermissionEnableDisable: '启用/禁用菜单权限',
|
||||||
|
account: '账号管理',
|
||||||
|
accountBase: '基本权限',
|
||||||
|
accountAdd: '添加账号',
|
||||||
|
accountEdit: '编辑账号',
|
||||||
|
accountDelete: '删除账号',
|
||||||
|
accountEnableDisable: '启用/禁用账号',
|
||||||
|
accountRoleAllocation: '角色分配',
|
||||||
|
role: '角色管理',
|
||||||
|
roleBase: '基本权限',
|
||||||
|
roleAdd: '添加角色',
|
||||||
|
roleEdit: '编辑角色',
|
||||||
|
roleDelete: '删除角色',
|
||||||
|
roleMenuPermissionAllocation: '菜单权限分配',
|
||||||
|
sysConf: '系统配置',
|
||||||
|
sysConfBase: '基本权限',
|
||||||
|
sysConfSave: '保存配置',
|
||||||
|
opLog: '操作日志',
|
||||||
|
opLogBase: '基本权限',
|
||||||
|
|
||||||
|
noPagePermission: '无页面权限',
|
||||||
|
authcertShowciphertext: '授权凭证密文查看',
|
||||||
|
},
|
||||||
|
home: {
|
||||||
|
personalInfo: '个人信息',
|
||||||
|
welcomeMsg: '您好, {name},生活变的再糟糕,也不妨碍我变得更好!',
|
||||||
|
lastLoginIp: '上次登录IP',
|
||||||
|
lastLoginTime: '上次登录时间',
|
||||||
|
msgNotify: '消息通知',
|
||||||
|
noOpRecord: '暂无操作记录',
|
||||||
|
msgTypeLogin: '登录',
|
||||||
|
msgTypeNotify: '通知',
|
||||||
|
},
|
||||||
|
personal: {
|
||||||
|
updateInfo: '更新信息',
|
||||||
|
basicInfo: '基本信息',
|
||||||
|
inputNewPasswordPlaceholder: '请输入新密码',
|
||||||
|
updatePersonalInfo: '更新个人信息',
|
||||||
|
accountInfo: '账号信息',
|
||||||
|
currentStatus: '当前状态',
|
||||||
|
boundUp: '已绑定',
|
||||||
|
notBound: '未绑定',
|
||||||
|
immediateBinding: '立即绑定',
|
||||||
|
unbundle: '解绑',
|
||||||
|
updateSuccess: '更新成功',
|
||||||
|
bindingSuccess: '绑定成功',
|
||||||
|
unbundleSuccess: '解绑成功',
|
||||||
|
},
|
||||||
|
login: {
|
||||||
|
accountPasswordLogin: '账号密码登录',
|
||||||
|
thirdPartyLogin: '第三方登录',
|
||||||
|
ldapLogin: 'LDAP 登录',
|
||||||
|
inputUsernamePlaceholder: '请输入用户名',
|
||||||
|
inputPasswordPlaceholder: '请输入密码',
|
||||||
|
inputCaptchaPlaceholder: '请输入验证码',
|
||||||
|
login: '登 录',
|
||||||
|
loginFailTip: '提示:登录失败超过{loginFailCount}次后将被限制{loginFailMin}分钟内不可再次登录',
|
||||||
|
loginSuccessTip: '欢迎回来!',
|
||||||
|
changePassword: '修改密码',
|
||||||
|
oldPassword: '旧密码',
|
||||||
|
newPassword: '新密码',
|
||||||
|
passwordRuleTip: '须为8位以上且包含字⺟⼤⼩写+数字+特殊符号',
|
||||||
|
passwordChangeSuccessTip: '密码修改成功, 新密码已填充至登录密码框',
|
||||||
|
otpValidation: 'OTP校验',
|
||||||
|
qrCode: '二维码',
|
||||||
|
enterOtpCodeTip: '请输入令牌APP中显示的授权码',
|
||||||
|
updateBasicInfo: '修改基本信息',
|
||||||
|
name: '姓名',
|
||||||
|
inputNamePlaceholder: '请输入姓名',
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
df: {
|
||||||
|
fieldModelPlaceholder: 'model关联的字段',
|
||||||
|
fieldLabel: 'label',
|
||||||
|
fieldPlaceholder: 'placeholder',
|
||||||
|
optionalValues: '可选值',
|
||||||
|
optionalValuesPlaceholder: '可选值 ,分割',
|
||||||
|
required: '必填',
|
||||||
|
},
|
||||||
|
terminal: {
|
||||||
|
connError: '连接出错',
|
||||||
|
notConn: '未连接',
|
||||||
|
connSuccess: '连接成功',
|
||||||
|
connFail: '连接失败',
|
||||||
|
connErrMsg: '提示: 连接错误...',
|
||||||
|
connConfirm: '确认重新连接?',
|
||||||
|
connected: '已连接',
|
||||||
|
search: '搜索',
|
||||||
|
reConnTips: '点击连接状态可重连',
|
||||||
|
minimize: '最小化',
|
||||||
|
fullScreenTitle: '全屏|退出全屏',
|
||||||
|
close: '关闭',
|
||||||
|
|
||||||
|
serachPlaceholder: '请输入查找内容,回车搜索',
|
||||||
|
regexMatch: '正则匹配',
|
||||||
|
fullWordMatching: '单词全匹配',
|
||||||
|
caseSensitive: '区分大小写',
|
||||||
|
incrementalSearch: '增量查找',
|
||||||
|
previous: '上一个',
|
||||||
|
next: '下一个',
|
||||||
|
noMatchMsg: '未查询到匹配项',
|
||||||
|
},
|
||||||
|
crontab: {
|
||||||
|
crontabInputPlaceholder: '可点击左边按钮配置',
|
||||||
|
crontabTitle: '生成 cron',
|
||||||
|
second: '秒',
|
||||||
|
minute: '分钟',
|
||||||
|
hour: '小时',
|
||||||
|
day: '日',
|
||||||
|
month: '月',
|
||||||
|
week: '周',
|
||||||
|
year: '年',
|
||||||
|
timeExpression: '时间表达式',
|
||||||
|
crontabCompleteExpression: 'crontab完整表达式',
|
||||||
|
|
||||||
|
dayCrontype1: '允许的通配符[, - * / L M]',
|
||||||
|
crontype2: '不指定',
|
||||||
|
crontype3: '周期从',
|
||||||
|
|
||||||
|
crontypeFrom: '从',
|
||||||
|
crontypeEvery: '每',
|
||||||
|
appoint: '指定',
|
||||||
|
|
||||||
|
crontypeStartDay: '号开始',
|
||||||
|
crontypeExecDay: '日执行一次',
|
||||||
|
monthLastDay: '本月最后一天',
|
||||||
|
|
||||||
|
hourCronType1: '允许的通配符[, - * /]',
|
||||||
|
crontypeStartHour: '小时开始',
|
||||||
|
crontypeExecHour: '小时执行一次',
|
||||||
|
|
||||||
|
crontypeStartMin: '分钟开始',
|
||||||
|
crontypeExecMin: '分钟执行一次',
|
||||||
|
|
||||||
|
crontypeStartSecond: '秒开始',
|
||||||
|
crontypeExecSecond: '秒执行一次',
|
||||||
|
|
||||||
|
crontypeStartMonth: '月开始',
|
||||||
|
crontypeExecMonth: '月执行一次',
|
||||||
|
|
||||||
|
yearly: '每年',
|
||||||
|
crontypeStartYear: '年开始',
|
||||||
|
crontypeExecYear: '年执行一次',
|
||||||
|
|
||||||
|
weekCronType1: '允许的通配符[, - * / L #]',
|
||||||
|
monday: '周一',
|
||||||
|
tuesday: '周二',
|
||||||
|
wednesday: '周三',
|
||||||
|
thursday: '周四',
|
||||||
|
friday: '周五',
|
||||||
|
saturday: '周六',
|
||||||
|
sunday: '周日',
|
||||||
|
|
||||||
|
last5runTimes: '最近5次运行时间',
|
||||||
|
calculationing: '计算结果中',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
203
frontend/src/i18n/zh-cn/db.ts
Normal file
203
frontend/src/i18n/zh-cn/db.ts
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
export default {
|
||||||
|
db: {
|
||||||
|
// db instance
|
||||||
|
dbManage: '库管理',
|
||||||
|
port: '端口',
|
||||||
|
connParam: '连接参数',
|
||||||
|
keywordPlaceholder: 'host / 名称 / 编号',
|
||||||
|
acName: '授权凭证',
|
||||||
|
dbInst: '数据库实例',
|
||||||
|
manageDbTitle: '管理【{instName}】数据库',
|
||||||
|
sqlitePathPlaceholder: '请输入sqlite文件在服务器的绝对地址',
|
||||||
|
connParamPlaceholder: '其他连接参数,形如: key1=value1&key2=value2',
|
||||||
|
connSuccess: '连接成功',
|
||||||
|
showDb: '查看库',
|
||||||
|
db: '数据库',
|
||||||
|
dbFilterPlaceholder: '库名: 输入可过滤',
|
||||||
|
sqlRecord: 'SQL记录',
|
||||||
|
dump: '导出',
|
||||||
|
dumpContent: '导出内容',
|
||||||
|
structure: '结构',
|
||||||
|
data: '数据',
|
||||||
|
extName: '扩展名',
|
||||||
|
dbFilterPlacehoder: '按数据库名称筛选',
|
||||||
|
allDb: '全部数据库',
|
||||||
|
dumpDb: '导出数据库',
|
||||||
|
getDbMode: '获库方式',
|
||||||
|
noDumpDbMsg: '请添加要导出的数据库',
|
||||||
|
allSelect: '全选',
|
||||||
|
selectDbPlacehoder: '获库方式为‘指定库名’时,可选择',
|
||||||
|
|
||||||
|
// db
|
||||||
|
dbInstInfo: '数据库实例信息',
|
||||||
|
newQuery: '新建查询',
|
||||||
|
locationTagTree: '定位至左侧树的指定位置',
|
||||||
|
dbShowSetting: '数据库展示配置',
|
||||||
|
showFieldComments: '显示字段备注',
|
||||||
|
autoLocationTagTree: '自动定位树节点',
|
||||||
|
cacheTableInfo: '缓存表信息-[不开启则实时获取表信息]',
|
||||||
|
dbName: '库名',
|
||||||
|
table: '表',
|
||||||
|
createTable: '创建表',
|
||||||
|
tableOp: '表操作',
|
||||||
|
copyTable: '复制表',
|
||||||
|
renameTable: '重命名',
|
||||||
|
editTable: '编辑表',
|
||||||
|
delTable: '删除表',
|
||||||
|
close: '关闭',
|
||||||
|
closeOther: '关闭其他',
|
||||||
|
noDbInstMsg: '请选择数据库实例及对应的schema',
|
||||||
|
query: '查询',
|
||||||
|
nQuery: '新查询',
|
||||||
|
renamePrompt: '重命名表【{db}.{tableName}】',
|
||||||
|
noChange: '无更改',
|
||||||
|
isCopyTableData: '是否复制数据?',
|
||||||
|
execSuccess: '执行成功',
|
||||||
|
execFail: '执行失败',
|
||||||
|
sqlScriptRun: 'SQL脚本执行',
|
||||||
|
saveSql: '保存SQL',
|
||||||
|
execInfo: '执行信息',
|
||||||
|
result: '结果',
|
||||||
|
times: '耗时',
|
||||||
|
resultSet: '结果集',
|
||||||
|
tableDataEmptyTextTips: 'tips: select *开头的单表查询或点击表名默认查询的数据,可双击数据在线修改',
|
||||||
|
noSelctRunSqlMsg: '请选中需要执行的sql',
|
||||||
|
enterExecRemarkTips: '请输入备注',
|
||||||
|
execRemarkPlaceholder: '输入执行该sql的备注信息',
|
||||||
|
currentSqlTabIsRunning: '当前结果集tab正在执行, 请使用新标签执行',
|
||||||
|
sqlCannotEmpty: 'sql内容不能为空',
|
||||||
|
enterSqlScriptNameTips: '请输入SQL脚本名',
|
||||||
|
scriptFileUploadRunning: `'{filename}' 正在上传执行, 请关注结果通知`,
|
||||||
|
runSql: '执行SQL',
|
||||||
|
newTabRunSql: '新标签执行SQL',
|
||||||
|
formatSql: '格式化SQL',
|
||||||
|
|
||||||
|
execTime: '执行时间',
|
||||||
|
oneClickCopy: '一键复制',
|
||||||
|
asc: '升序',
|
||||||
|
desc: '降序',
|
||||||
|
fixed: '固定',
|
||||||
|
cancelFiexd: '取消固定',
|
||||||
|
formView: '表单视图',
|
||||||
|
genJson: '生成JSON',
|
||||||
|
exportCsv: '导出CSV',
|
||||||
|
exportSql: '导出SQL',
|
||||||
|
onlySelectOneData: '只能选择一行数据',
|
||||||
|
|
||||||
|
editField: '编辑字段',
|
||||||
|
valueTypeNoMatch: '输入内容与类型不匹配',
|
||||||
|
|
||||||
|
tableFieldConf: '表格字段配置',
|
||||||
|
columnFilterPlaceholder: '输入列名或备注过滤',
|
||||||
|
selectAll: '选择所有',
|
||||||
|
submitUpdate: '提交修改',
|
||||||
|
cancelUpdate: '取消修改',
|
||||||
|
autoCompleteColumnPlaceholder: '选择列 或 输入SQL条件表达式后回车或点击查询图标过滤结果, 输入时可根据字段名提示',
|
||||||
|
selectColumn: '选择列',
|
||||||
|
columnName: '列名',
|
||||||
|
homePage: '首页',
|
||||||
|
previousPage: '上一页',
|
||||||
|
rowsPage: '条/页',
|
||||||
|
rows: '条',
|
||||||
|
conditionInputDialogTitle: '请输入 [{columnName}] 的值',
|
||||||
|
addDataDialogTitle: '添加`{tableName}`表数据',
|
||||||
|
|
||||||
|
exportContent: '导出内容',
|
||||||
|
selectExportTable: '请先选择要导出的表',
|
||||||
|
tableNamePlaceholder: '表名: 输入可过滤',
|
||||||
|
comment: '备注',
|
||||||
|
commentPlaceholder: '备注: 输入可过滤',
|
||||||
|
dataSize: '数据大小',
|
||||||
|
indexSize: '索引大小',
|
||||||
|
column: '列',
|
||||||
|
index: '索引',
|
||||||
|
nullable: '是否可为空',
|
||||||
|
seqInIndex: '列序列号',
|
||||||
|
|
||||||
|
// DbSqlExecLog
|
||||||
|
selectDbPlaceholder: '请选择数据库',
|
||||||
|
restoreSql: '还原SQL',
|
||||||
|
stmtType: '操作类型',
|
||||||
|
execUser: '执行人',
|
||||||
|
execRes: '执行结果',
|
||||||
|
oldValue: '原值',
|
||||||
|
|
||||||
|
// db transfer
|
||||||
|
pleaseSetting: '请设置',
|
||||||
|
log: '日志',
|
||||||
|
stop: '停止',
|
||||||
|
run: '运行',
|
||||||
|
file: '文件',
|
||||||
|
taskName: '任务名',
|
||||||
|
srcDb: '源库',
|
||||||
|
runState: '运行状态',
|
||||||
|
createDbTransferDialogTitle: '新增数据库迁移任务(迁移不会对源库造成修改)',
|
||||||
|
editDbTransferDialogTitle: '修改数据库迁移任务(迁移不会对源库造成修改)',
|
||||||
|
stopConfirm: '确定停止?',
|
||||||
|
runConfirm: '确定运行?',
|
||||||
|
transferFileManage: '迁移文件管理',
|
||||||
|
dbFileType: '文件数据库类型',
|
||||||
|
targetDb: '目标数据库',
|
||||||
|
fileDbType: 'sql语言',
|
||||||
|
transferFileRunDialogTitle: '指定数据库执行sql文件',
|
||||||
|
targetDbTypeSelectError: '请选择[{dbType}]数据库',
|
||||||
|
cronAble: '定时迁移',
|
||||||
|
transferMode: '迁移方式',
|
||||||
|
transfer2Db: '迁移到数据库',
|
||||||
|
transfer2File: '迁移到文件',
|
||||||
|
fileSaveDays: '文件保留天数',
|
||||||
|
transferStrategy: '迁移策略',
|
||||||
|
day: '天',
|
||||||
|
transferFull: '全量',
|
||||||
|
transferIncrement: '增量(暂不可用)',
|
||||||
|
nameCase: '转换表、字段名',
|
||||||
|
none: '无',
|
||||||
|
lower: '小写',
|
||||||
|
upper: '大写',
|
||||||
|
dbObj: '数据库对象',
|
||||||
|
allTable: '全部表',
|
||||||
|
custom: '自定义',
|
||||||
|
noTransferTableMsg: '请选择需要迁移的表',
|
||||||
|
|
||||||
|
// dbSync
|
||||||
|
recentState: '最近任务状态',
|
||||||
|
dbSync: '数据同步',
|
||||||
|
realTime: '实时',
|
||||||
|
noRealTime: '非实时',
|
||||||
|
srcDataSql: '源数据sql',
|
||||||
|
targetDbTable: '目标库表',
|
||||||
|
pageSize: '分页大小',
|
||||||
|
pageSizePlaceholder: '同步数据时查询的每页数据大小',
|
||||||
|
updateField: '更新字段',
|
||||||
|
updateFieldTips: '查询数据源的时候会带上这个字段当前最大值,支持带别名,如:t.create_time',
|
||||||
|
updateFiledPlaceholder: '查询数据源的时候会带上这个字段当前最大值',
|
||||||
|
updateFieldValue: '更新值',
|
||||||
|
updateFieldValueTips: '记录更新字段当前值,如:当前时间,当前日期等,下次查询数据时会带上该值条件',
|
||||||
|
updateFieldValuePlaceholder: '更新字段当前最大值',
|
||||||
|
fieldValueSrc: '值来源',
|
||||||
|
fieldValueSrcTips: '从查询结果中取更新值的字段名,默认同更新字段,如果查询结果指定了字段别名且与原更新字段不一致,则取这个字段值为当前更新值',
|
||||||
|
fieldValueSrcPlaceholder: '更新值来源',
|
||||||
|
fieldMap: '字段映射',
|
||||||
|
srcField: '源字段',
|
||||||
|
targetField: '目标字段',
|
||||||
|
sqlPreview: 'sql预览',
|
||||||
|
selectSql: '查询sql',
|
||||||
|
insertSql: '插入sql',
|
||||||
|
keyDuplicateStrategy: '键冲突策略',
|
||||||
|
fieldMapError: '字段映射中存在重复的目标字段,请检查',
|
||||||
|
noDataSqlMsg: '请输入数据sql',
|
||||||
|
notSelectSql: 'sql语句错误,请输入select语句',
|
||||||
|
notOneSql: 'sql语句错误,请输入单条查询语句',
|
||||||
|
notColumnSql: '没有查询到字段,请检查sql',
|
||||||
|
|
||||||
|
// enums
|
||||||
|
getDbNamesModeAuto: '实时获取',
|
||||||
|
getDbNamesModeAssign: '指定库名',
|
||||||
|
|
||||||
|
ignore: '忽略',
|
||||||
|
replate: '替换',
|
||||||
|
|
||||||
|
running: '运行中',
|
||||||
|
waitRun: '待运行',
|
||||||
|
},
|
||||||
|
};
|
||||||
90
frontend/src/i18n/zh-cn/flow.ts
Normal file
90
frontend/src/i18n/zh-cn/flow.ts
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
export default {
|
||||||
|
flow: {
|
||||||
|
// procdef
|
||||||
|
approvalNode: '审批节点',
|
||||||
|
procdef: '流程定义',
|
||||||
|
triggeringCondition: '触发条件',
|
||||||
|
triggeringConditionTips: 'go template语法。若输出结果为1,则表示触发该审批流程',
|
||||||
|
conditionPlaceholder: '触发条件, 返回值=1, 则表示触发该审批流程',
|
||||||
|
conditionDefault: `{{/* DBMS-执行sql规则; param参数描述如下 */}}
|
||||||
|
{{/* stmtType: select / read / insert / update / delete / ddl ; */}}
|
||||||
|
{{ if eq .bizType "db_sql_exec_flow"}}
|
||||||
|
{{/* 不是select和read语句时,开启流程审批 */}}
|
||||||
|
{{ if and (ne .param.stmtType "select") (ne .param.stmtType "read") }}
|
||||||
|
1
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{/* Redis-执行命令规则; param参数描述如下 */}}
|
||||||
|
{{/* cmdType: read(读命令) / write(写命令); */}}
|
||||||
|
{{/* cmd: get/set/hset...等 */}}
|
||||||
|
{{ if eq .bizType "redis_run_cmd_flow"}}
|
||||||
|
{{ if eq .param.cmdType "write" }}
|
||||||
|
1
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}`,
|
||||||
|
nodeName: '节点名称',
|
||||||
|
nodeNameTips: '点击指定节点可进行拖拽排序',
|
||||||
|
auditor: '审核人员',
|
||||||
|
tasksNotEmpty: '请完善审批节点任务',
|
||||||
|
tasksNoComplete: '请完善第{index}个审批节点任务信息',
|
||||||
|
// procdef status enum
|
||||||
|
enable: '启用',
|
||||||
|
disable: '禁用',
|
||||||
|
|
||||||
|
// procinst
|
||||||
|
startProcess: '发起流程',
|
||||||
|
cancelProcessConfirm: '确认取消该流程?',
|
||||||
|
bizType: '业务类型',
|
||||||
|
bizKey: '业务Key',
|
||||||
|
initiator: '发起人',
|
||||||
|
procdefName: '流程名',
|
||||||
|
bizStatus: '业务状态',
|
||||||
|
startingTime: '发起时间',
|
||||||
|
endTime: '结束时间',
|
||||||
|
duration: '持续时间',
|
||||||
|
proc: '流程',
|
||||||
|
bizInfo: '业务信息',
|
||||||
|
approvalNodeNotExist: '不存在审批节点',
|
||||||
|
resourceNotExistFlow: '该资源无需审批操作',
|
||||||
|
procinstFormError: '请正确填写信息',
|
||||||
|
procinstStartSuccess: '流程发起成功',
|
||||||
|
// db run sql flow biz
|
||||||
|
runSql: '执行SQL',
|
||||||
|
selectDbPlaceholder: '请选择数据库',
|
||||||
|
// redis run cmd flow biz
|
||||||
|
runCmd: '执行Cmd',
|
||||||
|
selectRedisPlaceholder: '请选择Redis实例与库',
|
||||||
|
cmdPlaceholder: `如: SET 'key' 'value'; 多条命令;分割`,
|
||||||
|
// ProcinstStatusEnum
|
||||||
|
active: '执行中',
|
||||||
|
completed: '完成',
|
||||||
|
suspended: '挂起',
|
||||||
|
terminated: '终止',
|
||||||
|
cancelled: '取消',
|
||||||
|
handleResult: '处理结果',
|
||||||
|
runResult: '执行结果',
|
||||||
|
// ProcinstBizStatus
|
||||||
|
waitHandle: '待处理',
|
||||||
|
handleSuccess: '处理成功',
|
||||||
|
handleFail: '处理失败',
|
||||||
|
noHandle: '不处理',
|
||||||
|
// ProcinstTaskStatus
|
||||||
|
waitProcess: '待处理',
|
||||||
|
pass: '通过',
|
||||||
|
reject: '拒绝',
|
||||||
|
back: '回退',
|
||||||
|
canceled: '取消',
|
||||||
|
// FlowBizType
|
||||||
|
dbSqlExec: 'DBMS-执行SQL',
|
||||||
|
redisRunCmd: 'Redis-执行命令',
|
||||||
|
|
||||||
|
// task
|
||||||
|
audit: '审核',
|
||||||
|
procinstStatus: '流程状态',
|
||||||
|
taskStatus: '任务状态',
|
||||||
|
taskName: '当前节点',
|
||||||
|
taskBeginTime: '开始时间',
|
||||||
|
flowAudit: '流程审批',
|
||||||
|
},
|
||||||
|
};
|
||||||
135
frontend/src/i18n/zh-cn/machine.ts
Normal file
135
frontend/src/i18n/zh-cn/machine.ts
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
export default {
|
||||||
|
machine: {
|
||||||
|
keywordPlaceholder: 'ip / 名称 / 编号',
|
||||||
|
acName: '授权凭证',
|
||||||
|
runningStat: '运行状态',
|
||||||
|
fs: '磁盘(挂载点=>可用/总)',
|
||||||
|
remark: '备注',
|
||||||
|
memberInfo: '内存(可用/总)',
|
||||||
|
cpuInfo: 'CPU(空闲)',
|
||||||
|
file: '文件',
|
||||||
|
directory: '目录',
|
||||||
|
folder: '文件夹',
|
||||||
|
script: '脚本',
|
||||||
|
process: '进程',
|
||||||
|
terminalPlayback: '终端回放',
|
||||||
|
createMachine: '添加机器',
|
||||||
|
editMachine: '编辑机器',
|
||||||
|
reConnTips: '确认重新连接?',
|
||||||
|
clickReConn: '点击重连',
|
||||||
|
port: '端口',
|
||||||
|
sshTunnel: 'SSH隧道',
|
||||||
|
newOpenTabTerminalTips: '按住ctrl则为新标签打开',
|
||||||
|
newTab: '新窗口',
|
||||||
|
openTerminal: '打开终端',
|
||||||
|
newTabOpenTerminal: '打开终端(新窗口)',
|
||||||
|
fileManage: '文件管理',
|
||||||
|
scriptManage: '脚本管理',
|
||||||
|
machineState: '机器状态',
|
||||||
|
remoteFileDesktopManage: '远程桌面文件管理', // Remote desktop file management
|
||||||
|
remoteDesktop: '远程桌面',
|
||||||
|
protocol: '协议',
|
||||||
|
ipAndPort: 'ip和port',
|
||||||
|
connSuccess: '连接成功',
|
||||||
|
noAcErrMsg: '请完善授权凭证账号信息',
|
||||||
|
|
||||||
|
// MachineRec
|
||||||
|
playback: '回放',
|
||||||
|
cmd: '命令',
|
||||||
|
execCmdRecord: '执行命令记录', //Executive command record
|
||||||
|
execTime: '执行时间', // execution time
|
||||||
|
operator: '操作人',
|
||||||
|
beginTime: '开始时间',
|
||||||
|
endTime: '结束时间',
|
||||||
|
|
||||||
|
// MachineStats
|
||||||
|
basicInfo: '基本信息', // basic information
|
||||||
|
hostname: '主机名',
|
||||||
|
runTime: '运行时间',
|
||||||
|
totalTask: '总任务',
|
||||||
|
runningTask: '运行中任务',
|
||||||
|
load: '负载',
|
||||||
|
disk: '磁盘',
|
||||||
|
mountPoint: '挂载点',
|
||||||
|
available: '可使用',
|
||||||
|
used: '已使用',
|
||||||
|
networkCard: '网卡',
|
||||||
|
receive: '接收',
|
||||||
|
send: '发送',
|
||||||
|
memory: '内存',
|
||||||
|
cpuUsageRate: 'CPU使用率',
|
||||||
|
|
||||||
|
// process
|
||||||
|
processName: '进程名',
|
||||||
|
selectSortType: '请选择排序类型',
|
||||||
|
selectProcessNum: '请选择进程个数',
|
||||||
|
cpuDesc: 'CUP降序',
|
||||||
|
memDesc: '内存降序',
|
||||||
|
virtualMemory: '虚拟内存',
|
||||||
|
fixedMemory: '固定内存',
|
||||||
|
procState: '进程状态',
|
||||||
|
startTime: '启动时间',
|
||||||
|
procCpuRunTime: '该进程实际使用CPU运作的时间',
|
||||||
|
killProcConfirm: '确定终止该进程?',
|
||||||
|
kill: '终止',
|
||||||
|
|
||||||
|
// script
|
||||||
|
execute: '执行',
|
||||||
|
scriptParam: '脚本参数',
|
||||||
|
execResult: '执行结果',
|
||||||
|
execCompleted: '执行完成', // execution is completed
|
||||||
|
scriptParamTips1: '1. 脚本内容中可使用{{.model}}作为占位符',
|
||||||
|
scriptParamTips2: '2. 执行脚本时可输入对应表单内容对占位符进行替换后执行',
|
||||||
|
scriptResultEnumResult: '有结果',
|
||||||
|
scriptResultEnumNoResult: '无结果',
|
||||||
|
scriptResultEnumRealTime: '实时交互',
|
||||||
|
scriptTypeEnumPrivate: '私有',
|
||||||
|
scriptTypeEnumPublic: '公共',
|
||||||
|
|
||||||
|
// security
|
||||||
|
cmdConfig: '命令配置',
|
||||||
|
filterCmds: '过滤命令',
|
||||||
|
relateMachine: '关联机器',
|
||||||
|
newCmd: '新建命令',
|
||||||
|
cmdPlaceholder: '请输入命令正则表达式',
|
||||||
|
|
||||||
|
// cronjob
|
||||||
|
cronjob: '计划任务',
|
||||||
|
machineCode: '机器编号',
|
||||||
|
cronjobRunning: '运行中',
|
||||||
|
cronjobNoRun: '未运行',
|
||||||
|
cronjobRun: '执行',
|
||||||
|
cronJobExecStatusEnumSuccess: '成功',
|
||||||
|
cronJobExecStatusEnumFail: '失败',
|
||||||
|
cronjobExecResult: '执行结果',
|
||||||
|
cronjobExecTime: '执行时间',
|
||||||
|
cronjobExecRecord: '执行记录',
|
||||||
|
runSuccess: '执行成功',
|
||||||
|
cronjobRunState: '运行状态',
|
||||||
|
execResRecordType: '结果记录类型',
|
||||||
|
cronExpression: 'cron表达式',
|
||||||
|
|
||||||
|
// file
|
||||||
|
upload: '上传',
|
||||||
|
download: '下载',
|
||||||
|
copy: '复制',
|
||||||
|
move: '移动',
|
||||||
|
paste: '粘贴',
|
||||||
|
fileNameFilterPlaceholder: '名称: 输入可过滤',
|
||||||
|
calculate: '计算',
|
||||||
|
modificationTime: '修改时间',
|
||||||
|
attribute: '属性',
|
||||||
|
user: '用户',
|
||||||
|
group: '组',
|
||||||
|
renameTips: 'rename: 双击文件名单元格修改后回车',
|
||||||
|
fileDetail: '文件详情',
|
||||||
|
createFile: '新建文件',
|
||||||
|
pasteSuccess: '粘贴成功',
|
||||||
|
sameDirNoPaste: '同目录下不能粘贴',
|
||||||
|
renameSuccess: '重命名成功',
|
||||||
|
newFileNameNotEmpty: '新名称不能为空',
|
||||||
|
fileTooLargeTips: '文件太大, 请下载使用',
|
||||||
|
uploadSuccess: '上传成功',
|
||||||
|
fileExceedsSysConf: '上传的文件超过系统配置的【{uploadMaxFileSize}】',
|
||||||
|
},
|
||||||
|
};
|
||||||
44
frontend/src/i18n/zh-cn/mongo.ts
Normal file
44
frontend/src/i18n/zh-cn/mongo.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
export default {
|
||||||
|
mongo: {
|
||||||
|
mongo: 'MongoDB',
|
||||||
|
db: '数据库',
|
||||||
|
keywordPlaceholder: 'host / 名称 / 编号',
|
||||||
|
connUrl: '连接url',
|
||||||
|
|
||||||
|
dbList: '数据库列表',
|
||||||
|
isEmpty: '是否为空',
|
||||||
|
deleteDbConfirm: '确定删除该库?',
|
||||||
|
coll: '集合',
|
||||||
|
deleteCollConfirm: '确定删除该集合?',
|
||||||
|
collState: '集合状态',
|
||||||
|
createDbAndColl: '新建库&集合',
|
||||||
|
dbName: '库名',
|
||||||
|
collName: '集合名',
|
||||||
|
createColl: '新建集合',
|
||||||
|
collTitle: '`{dbName}` 集合',
|
||||||
|
|
||||||
|
template: '模板',
|
||||||
|
cmdTemplatePlaceholder: '选择命令模板',
|
||||||
|
moreCmdTips: '更多命令查看',
|
||||||
|
usersInfoDesc: '获取用户信息',
|
||||||
|
createUserDesc: '创建新用户',
|
||||||
|
grantRolesToUserDesc: '授予对用户的额外角色',
|
||||||
|
dropUserDesc: '删除用户',
|
||||||
|
roleInfoDesc: '获取角色信息',
|
||||||
|
createRoleDesc: '创建角色',
|
||||||
|
runSuccess: '执行成功',
|
||||||
|
|
||||||
|
queryParam: '查询参数',
|
||||||
|
queryParamPlaceholder: '点击输入相应查询条件',
|
||||||
|
deleteDocConfirm: '确定删除该文档?',
|
||||||
|
doc: '文档',
|
||||||
|
findParamErrMsg: 'filter或sort字段json字符串值错误。注意: json key需双引号',
|
||||||
|
docErrMsg: '文档内容错误,无法解析为json对象',
|
||||||
|
insertSuccess: '新增成功',
|
||||||
|
insertFail: '新增失败',
|
||||||
|
idNotExist: '文档的_id属性不存在',
|
||||||
|
modifyFail: '修改失败',
|
||||||
|
deleteFail: '删除失败',
|
||||||
|
docParse2jsonFail: '文档内容解析为json对象失败',
|
||||||
|
},
|
||||||
|
};
|
||||||
64
frontend/src/i18n/zh-cn/redis.ts
Normal file
64
frontend/src/i18n/zh-cn/redis.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
export default {
|
||||||
|
redis: {
|
||||||
|
standaloneInfo: '单机信息',
|
||||||
|
clusterInfo: '集群信息',
|
||||||
|
node: '节点',
|
||||||
|
clusterIpTips: 'ip:port1@port2:port1指redis服务器与客户端通信的端口,port2则是集群内部节点间通信的端口',
|
||||||
|
masterSlaveRelationTips: `如果节点是slave,并且已知master节点,则为master节点ID;否则为符号'-'`,
|
||||||
|
configEpochTips: '节点的epoch值(如果该节点是从节点,则为其主节点的epoch值)。每当节点发生失败切换时,都会创建一个新的,独特的,递增的epoch。',
|
||||||
|
keywordPlaceholder: 'host / 名称 / 编号',
|
||||||
|
hostTips: `请输入host:port;sentinel模式为: mastername=sentinelhost:port,若集群或哨兵需设多个节点可使用','分割`,
|
||||||
|
nodePassword: '节点密码',
|
||||||
|
sentinelHostErr: 'sentinel模式host需为: mastername=sentinelhost:sentinelport模式',
|
||||||
|
delimiter: '分隔符',
|
||||||
|
keyMatchTips: 'match 支持*模糊key, 回车搜索',
|
||||||
|
loadMore: '加载更多',
|
||||||
|
addKey: '新增key',
|
||||||
|
newTabOpen: '新tab打开',
|
||||||
|
redisSelectErr: '请先选择redis',
|
||||||
|
flushDbTips: '确定清空[{db}]库的所有key?',
|
||||||
|
keyNotEmpty: 'Key不能为空',
|
||||||
|
|
||||||
|
// info
|
||||||
|
redisInfoTitle: 'Redis服务器信息',
|
||||||
|
version: '版本',
|
||||||
|
port: '端口',
|
||||||
|
mode: '模式',
|
||||||
|
os: '操作系统',
|
||||||
|
uptimeDays: '运行天数',
|
||||||
|
execPath: '可执行文件路径',
|
||||||
|
confFile: '配置文件路径',
|
||||||
|
clusterEnable: '是否启用集群模式',
|
||||||
|
nodeCount: '节点总数',
|
||||||
|
clientConn: '客户端连接',
|
||||||
|
connectedNum: '已连接客户端数',
|
||||||
|
blockedClientNum: '正在等待阻塞命令客户端数',
|
||||||
|
sysCpu: '系统CPU',
|
||||||
|
userCpu: '用户CPU',
|
||||||
|
sysChildCpu: '后台系统CPU',
|
||||||
|
userChildCpu: '后台用户CPU',
|
||||||
|
keyCount: '键值统计',
|
||||||
|
countInfo: '统计信息',
|
||||||
|
totalCmdProcess: '总处理命令数',
|
||||||
|
curQps: '当前qps',
|
||||||
|
expiredKeys: '过期key的总数量',
|
||||||
|
netInputBytes: '网络入口流量字节数',
|
||||||
|
netOutputBytes: '网络出口流量字节数',
|
||||||
|
persistence: '持久化',
|
||||||
|
aofEnable: '是否启用aof',
|
||||||
|
loadingPersistence: '是否正在载入持久化文件',
|
||||||
|
availableMemory: '可用内存',
|
||||||
|
usedMemory: '已用内存',
|
||||||
|
|
||||||
|
renameTips: '点击重命名',
|
||||||
|
ttlPlaceholder: '单位(秒),负数永久',
|
||||||
|
ttlTips: '点击修改过期时间',
|
||||||
|
settingSuccess: '设置成功',
|
||||||
|
permanent: '永久',
|
||||||
|
persistenceConfirm: '确定持久化该key?',
|
||||||
|
|
||||||
|
addNewLine: '添加新行',
|
||||||
|
filterPlaceholder: '关键词回车搜索',
|
||||||
|
deleteConfirm: '确定删除?',
|
||||||
|
},
|
||||||
|
};
|
||||||
210
frontend/src/i18n/zh-cn/system.ts
Normal file
210
frontend/src/i18n/zh-cn/system.ts
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
export default {
|
||||||
|
system: {
|
||||||
|
menu: {
|
||||||
|
filterPlaceholder: '输入关键字过滤(右击操作)',
|
||||||
|
opTips: '红色、橙色字体表示禁用状态 (右击资源进行操作)',
|
||||||
|
info: '资源信息',
|
||||||
|
menu: '菜单',
|
||||||
|
permission: '权限',
|
||||||
|
icon: '图标',
|
||||||
|
routerName: '路由名',
|
||||||
|
componentPath: '组件路径',
|
||||||
|
isCache: '是否缓存',
|
||||||
|
isHide: '是否隐藏',
|
||||||
|
tagIsDelete: 'tag不可删除',
|
||||||
|
externalLink: '外链',
|
||||||
|
yes: '是',
|
||||||
|
no: '否',
|
||||||
|
addSubResource: '添加子资源',
|
||||||
|
enable: '启用',
|
||||||
|
disable: '禁用',
|
||||||
|
tips: '提示',
|
||||||
|
addTopMenu: '添加顶级菜单',
|
||||||
|
addChildrenMenuTitle: '添加`{parentName}`的子资源',
|
||||||
|
updateMenu: '修改`{name}`',
|
||||||
|
success: '成功',
|
||||||
|
menuCodeTips: `菜单类型则为访问路径(若菜单路径不以'/'开头则访问地址会自动拼接父菜单路径)、否则为资源唯一编码`,
|
||||||
|
menuCodePlaceholder: `菜单不以'/'开头则自动拼接父菜单路径`,
|
||||||
|
routerNameTips: '与vue的组件名一致才可使组件缓存生效,如ResourceLis',
|
||||||
|
componentPathTips: '访问的组件路径,如:`system/resource/ResourceList`,默认在`views`目录下',
|
||||||
|
isCacheTips: '选择是则会被`keep-alive`缓存(重新进入页面不会刷新页面及重新请求数据),需要路由名与vue的组件名一致',
|
||||||
|
isHideTips: '选择隐藏则路由将不会出现在菜单栏中,但仍然可以访问。禁用则不可访问与操作',
|
||||||
|
externalLinkTips: '内嵌: 以iframe展示、外链: 新标签打开',
|
||||||
|
inline: '内嵌',
|
||||||
|
linkAddress: '链接地址',
|
||||||
|
linkPlaceholder: '外链/内嵌的链接地址(http://xxx.com)',
|
||||||
|
menuNameRuleMsg: '请输入资源名称',
|
||||||
|
routeNameNotEmpty: '路由名不能为空',
|
||||||
|
resourceCodePatternErrMsg: '只允许输入1-32位大小写字母、数字、_-.:',
|
||||||
|
assignedRole: '已分配角色',
|
||||||
|
},
|
||||||
|
account: {
|
||||||
|
roleAllocation: '角色分配',
|
||||||
|
resetOtp: '重置OTP',
|
||||||
|
assigner: '分配者',
|
||||||
|
allocateTime: '分配时间',
|
||||||
|
name: '姓名',
|
||||||
|
lastLoginTime: '最后登录时间',
|
||||||
|
deleteAccountConfirm: '确定删除【{name}】的账号?',
|
||||||
|
usernamePlacholder: '5-16位大小写字母、数字、_-.:',
|
||||||
|
random: '随机',
|
||||||
|
usernamePatternErrMsg: '只允许输入5-16位大小写字母、数字、_-.:',
|
||||||
|
accountSearchPlaceholder: '输入账号模糊搜索并选择',
|
||||||
|
accountInfo: '账号信息',
|
||||||
|
allocateRoleTitle: '分配 `{name}` 的角色',
|
||||||
|
allocated: '已分配',
|
||||||
|
undistributed: '未分配',
|
||||||
|
menuAndPermission: '菜单&权限',
|
||||||
|
remove: '移除',
|
||||||
|
allocation: '分配',
|
||||||
|
roleStatus: '角色状态',
|
||||||
|
userMenuTitle: '`{name}` 的菜单&权限',
|
||||||
|
statusEnable: '启用',
|
||||||
|
statusDisable: '禁用',
|
||||||
|
},
|
||||||
|
role: {
|
||||||
|
permissionDetail: '权限详情',
|
||||||
|
permissionAllocate: '权限分配',
|
||||||
|
userManage: '用户管理',
|
||||||
|
roleName: '角色名',
|
||||||
|
roleCode: '角色编码',
|
||||||
|
rolePermissionTitle: '`{name} 的菜单&权限`',
|
||||||
|
roleCodePlaceholder: 'COMMON开头则为所有账号共有角色',
|
||||||
|
statusEnable: '启用',
|
||||||
|
statusDisable: '禁用',
|
||||||
|
allocateMenuTitle: '分配 `{roleName}` 的菜单&权限',
|
||||||
|
allocateAccountTitle: '`{roleName}` 关联的账号',
|
||||||
|
addAccount: '添加账号',
|
||||||
|
userStatus: '用户状态',
|
||||||
|
assigner: '分配者',
|
||||||
|
allocateTime: '分配时间',
|
||||||
|
permissionInfo: '权限分配信息',
|
||||||
|
},
|
||||||
|
sysconf: {
|
||||||
|
confItem: '配置项',
|
||||||
|
confKey: '配置key',
|
||||||
|
permission: '权限',
|
||||||
|
permissionPlaceholder: '请输入账号模糊搜索并选择',
|
||||||
|
conf: '配置',
|
||||||
|
confItemSetting: '配置项设置',
|
||||||
|
confValue: '配置值',
|
||||||
|
|
||||||
|
fileConf: '文件配置',
|
||||||
|
fileConfRemark: '系统文件配置',
|
||||||
|
basePath: '基础路径',
|
||||||
|
baesPathPlaceholder: '默认为可执行文件对应目录下./file',
|
||||||
|
|
||||||
|
dbmsConf: 'DBMS配置',
|
||||||
|
dbmsConfRemark: '数据库相关配置',
|
||||||
|
recordQuerySql: '记录查询sql',
|
||||||
|
recordQuerySqlPlaceholder: '是否记录查询类sql',
|
||||||
|
maxResultSet: '最大结果集',
|
||||||
|
maxResultSetPlaceholder: '允许sql查询的最大结果集数。注: 0=不限制',
|
||||||
|
sqlExecLimt: 'sql执行时间限制',
|
||||||
|
sqlExecLimtPlaceholder: '超过该时间(单位:秒),执行将被取消',
|
||||||
|
|
||||||
|
machineConf: '机器相关配置',
|
||||||
|
machineConfRemark: '机器相关配置,如终端操作记录保存天数等',
|
||||||
|
uploadMaxFileSize: '上传文件大小限制',
|
||||||
|
uploadMaxFileSizePlaceholder: '允许上传的最大文件大小(1MB、2GB等)',
|
||||||
|
termOpSaveDays: '终端记录保存时间',
|
||||||
|
termOpSaveDaysPlaceholder: '单位天,超过该时间,将删除终端操作记录',
|
||||||
|
guacdHost: 'guacd服务ip',
|
||||||
|
guacdHostPlaceholder: 'guacd服务ip,默认 127.0.0.1',
|
||||||
|
guacdPort: 'guacd服务端口',
|
||||||
|
guacdPortPlaceholder: 'guacd服务端口,默认 4822',
|
||||||
|
guacdFilePath: 'guacd服务文件存储位置',
|
||||||
|
guacdFilePathPlaceholder: 'guacd服务文件存储位置,用于挂载RDP文件夹',
|
||||||
|
|
||||||
|
systemConf: '系统全局样式设置',
|
||||||
|
systemConfRemark: '系统icon、标题、水印信息等配置',
|
||||||
|
logoIcon: 'logo图标',
|
||||||
|
logoIconPlaceholder: '系统logo图标(base64编码, 建议svg格式,不超过10k)',
|
||||||
|
title: '菜单栏标题',
|
||||||
|
titlePlaceholder: '系统菜单栏标题展示',
|
||||||
|
viceTitle: '登录页标题',
|
||||||
|
viceTitlePlaceholder: '登录页标题展示',
|
||||||
|
useWatermark: '是否启用水印',
|
||||||
|
useWatermarkTips: '是否启用系统水印',
|
||||||
|
watermarkContent: '水印补充信息',
|
||||||
|
watermarkContentPlaceholder: '水印补充信息,如公司名称等',
|
||||||
|
|
||||||
|
ldapLoginConf: 'LDAP登录配置',
|
||||||
|
ldapLoginConfRemark: 'ldap登录相关配置',
|
||||||
|
ldapEnable: '是否启用',
|
||||||
|
dapEnablePlaceholder: '是否启用ldap登录',
|
||||||
|
host: 'host',
|
||||||
|
port: 'port',
|
||||||
|
bindDN: 'bindDN',
|
||||||
|
bindDnPlaceholder: 'LDAP服务的管理员账号,如: "cn=admin,dc=example,dc=com"',
|
||||||
|
bindPwd: 'bindPwd',
|
||||||
|
bindPwdPlaceholder: 'LDAP服务的管理员密码',
|
||||||
|
baseDN: 'baseDN',
|
||||||
|
baseDnPlaceholder: '用户所在的 base DN, 如: "ou=users,dc=example,dc=com"',
|
||||||
|
userFilter: 'userFilter',
|
||||||
|
userFilerPlaceholder: '过滤用户的方式, 如: "(uid=%s)、(&(objectClass=organizationalPerson)(uid=%s))"',
|
||||||
|
uidMap: 'uidMap',
|
||||||
|
uidMapPlaceholder: '用户id和 LDAP 字段名之间的映射关系,如: cn',
|
||||||
|
udnMap: 'udnMap',
|
||||||
|
udnMapPlaceholder: '用户姓名(dispalyName)和 LDAP 字段名之间的映射关系,如: displayName',
|
||||||
|
emailMap: 'emailMap',
|
||||||
|
emailMapPlaceholder: '用户email和 LDAP 字段名之间的映射关系',
|
||||||
|
skipTlsVerfify: 'skipTlsVerfify',
|
||||||
|
skipTlsVerfifyPlaceholder: '客户端是否跳过 TLS 证书验证',
|
||||||
|
securityProtocol: '安全协议',
|
||||||
|
securityProtocolPlaceholder: '安全协议(为Null不使用安全协议),如: StartTLS, LDAPS',
|
||||||
|
|
||||||
|
oauth2LoginConf: 'OAuth2登录配置',
|
||||||
|
oauth2LoginConfRemark: 'oauth2登录相关配置信息',
|
||||||
|
oauth2Enable: '是否启用',
|
||||||
|
oauth2EnablePlaceholder: '是否启用oauth2登录',
|
||||||
|
name: '名称',
|
||||||
|
namePlaceholder: 'oauth2名称',
|
||||||
|
clientId: 'Client ID',
|
||||||
|
clientIdPlaceholder: 'oauth2 Client ID',
|
||||||
|
clientSecret: 'Client Secret',
|
||||||
|
clientSecretPlaceholder: 'oauth2 Client Secret',
|
||||||
|
authorizationUrl: 'Authorization URL',
|
||||||
|
authorizationUrlPlaceholder: 'oauth2 授权地址',
|
||||||
|
accessTokenUrl: 'Access Token URL',
|
||||||
|
accessTokenUrlPlaceholder: 'oauth2 获取token地址',
|
||||||
|
redirectUrl: 'Redirect URL',
|
||||||
|
redirectUrlPlaceholder: '本系统地址',
|
||||||
|
scope: 'Scopes',
|
||||||
|
scopePlaceholder: 'oauth2 Scopes',
|
||||||
|
resourceUrl: 'Resource URL',
|
||||||
|
resourceUrlPlaceholder: '获取用户信息资源地址',
|
||||||
|
userId: 'User ID',
|
||||||
|
userIdPlaceholder: '用户唯一标识字段;格式为type:fieldPath(string:username)',
|
||||||
|
autoRegister: '是否自动注册',
|
||||||
|
|
||||||
|
accountLoginConf: '账号登录安全设置',
|
||||||
|
accountLoginConfRemark: '系统账号登录相关安全设置',
|
||||||
|
useCaptcha: '登录验证码',
|
||||||
|
useCaptchaPlaceholder: '是否启用登录验证码',
|
||||||
|
useOtp: '是否启用OTP',
|
||||||
|
useOtpPlaceholder: '是否启用双因素(OTP)校验',
|
||||||
|
otpIssuer: 'OTP签发人',
|
||||||
|
loginFailCount: '允许登录失败次数',
|
||||||
|
loginFailCountPlaceholder: '登录失败n次后禁止登录',
|
||||||
|
loginFainMin: '登录失败禁止登录时间',
|
||||||
|
loginFailMinPlaceholder: '登录失败指定次数后禁止m分钟内再次登录',
|
||||||
|
},
|
||||||
|
syslog: {
|
||||||
|
operator: '操作人',
|
||||||
|
operatorPlaceholder: '请输入并选择账号',
|
||||||
|
operatingResult: '操作结果',
|
||||||
|
description: '描述',
|
||||||
|
operatingTime: '操作时间',
|
||||||
|
operatingInfo: '操作信息',
|
||||||
|
result: '结果',
|
||||||
|
response: '响应信息',
|
||||||
|
resultSuccess: '成功',
|
||||||
|
resultFail: '失败',
|
||||||
|
resultRunning: '执行中',
|
||||||
|
},
|
||||||
|
oauth: {
|
||||||
|
authSuccess: '授权认证成功',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
56
frontend/src/i18n/zh-cn/tag.ts
Normal file
56
frontend/src/i18n/zh-cn/tag.ts
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
export default {
|
||||||
|
tag: {
|
||||||
|
relateTag: '关联标签',
|
||||||
|
keywordFilterPlaceholder: '关键字过滤',
|
||||||
|
nameFilterPlaceholder: '关键字过滤(右击节点操作)',
|
||||||
|
tagFilterPlaceholder: '输入关键字->搜索已展开节点信息',
|
||||||
|
tagTips1: '1. 用于将资产进行归类',
|
||||||
|
tagTips2: '2. 可在团队管理中进行分配,用于资源隔离',
|
||||||
|
tagTips3: '3. 拥有父标签的团队成员可访问操作其自身或子标签关联的资源',
|
||||||
|
machine: '机器',
|
||||||
|
db: '数据库',
|
||||||
|
code: '编号',
|
||||||
|
createSubTag: '创建子标签',
|
||||||
|
createSubTagTitle: '创建【{codePath}】的子标签',
|
||||||
|
rootTag: '根标签',
|
||||||
|
selectTagPlaceholder: '请选择关联标签',
|
||||||
|
},
|
||||||
|
team: {
|
||||||
|
team: '团队',
|
||||||
|
member: '成员',
|
||||||
|
addMember: '添加成员',
|
||||||
|
teamMember: '【{teamName}】成员信息',
|
||||||
|
selectAccountTips: '请先选择账号',
|
||||||
|
joinTime: '加入时间',
|
||||||
|
accountName: '姓名',
|
||||||
|
assigner: '分配人',
|
||||||
|
allocateTag: '分配标签',
|
||||||
|
validity: '有效期',
|
||||||
|
effectiveStartTime: '生效开始时间',
|
||||||
|
effectiveEndTime: '生效结束时间',
|
||||||
|
},
|
||||||
|
// authcert
|
||||||
|
ac: {
|
||||||
|
namePlaceholder: '请输入凭证名 (全局唯一)',
|
||||||
|
privateKeyPlaceholder: '请将私钥文件内容拷贝至此',
|
||||||
|
privateKeyPwd: '秘钥密码',
|
||||||
|
resourceCode: '资源编号',
|
||||||
|
credentialName: '凭证名称',
|
||||||
|
resourceType: '资源类型',
|
||||||
|
credentialType: '凭证类型',
|
||||||
|
ciphertextType: '密文类型',
|
||||||
|
privateKey: '秘钥',
|
||||||
|
ac: '授权凭证',
|
||||||
|
testConn: '测试连接',
|
||||||
|
connSuccess: '连接成功',
|
||||||
|
usernameExist: '该用户名已存在于该账号列表中',
|
||||||
|
publicAc: '公共凭证',
|
||||||
|
acTypeEnumPublic: '公共凭证',
|
||||||
|
acTypeEnumPrivate: '普通凭证',
|
||||||
|
acTypeEnumPrivileged: '特权凭证',
|
||||||
|
acTypeEnumPrivateDefault: '默认凭证',
|
||||||
|
ciphertextTypeEnumPassword: '密码',
|
||||||
|
ciphertextTypeEnumPrivateKey: '秘钥',
|
||||||
|
ciphertextTypeEnumPublic: '公共凭证',
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -2,29 +2,25 @@
|
|||||||
<div class="layout-columns-aside">
|
<div class="layout-columns-aside">
|
||||||
<el-scrollbar>
|
<el-scrollbar>
|
||||||
<ul>
|
<ul>
|
||||||
<li
|
<li v-for="(v, k) in state.columnsAsideList" :key="k" @click="onColumnsAsideMenuClick(v, k)" :ref="(el) => {
|
||||||
v-for="(v, k) in state.columnsAsideList"
|
|
||||||
:key="k"
|
|
||||||
@click="onColumnsAsideMenuClick(v, k)"
|
|
||||||
:ref="
|
|
||||||
(el) => {
|
|
||||||
if (el) columnsAsideOffsetTopRefs[k] = el;
|
if (el) columnsAsideOffsetTopRefs[k] = el;
|
||||||
}
|
}
|
||||||
"
|
" :class="{ 'layout-columns-active': state.liIndex === k }" :title="$t(v.meta.title)">
|
||||||
:class="{ 'layout-columns-active': state.liIndex === k }"
|
<div class="layout-columns-aside-li-box"
|
||||||
:title="v.meta.title"
|
v-if="!v.meta.link || (v.meta.link && v.meta.linkType == 1)">
|
||||||
>
|
|
||||||
<div class="layout-columns-aside-li-box" v-if="!v.meta.link || (v.meta.link && v.meta.linkType == 1)">
|
|
||||||
<i :class="v.meta.icon"></i>
|
<i :class="v.meta.icon"></i>
|
||||||
<div class="layout-columns-aside-li-box-title font12">
|
<div class="layout-columns-aside-li-box-title font12">
|
||||||
{{ v.meta.title && v.meta.title.length >= 4 ? v.meta.title.substr(0, 4) : v.meta.title }}
|
{{ $t(v.meta.title) && $t(v.meta.title).length >= 4 ? $t(v.meta.title).substr(0, 4) :
|
||||||
|
$t(v.meta.title) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-columns-aside-li-box" v-else>
|
<div class="layout-columns-aside-li-box" v-else>
|
||||||
<a :href="v.meta.link" target="_blank">
|
<a :href="v.meta.link" target="_blank">
|
||||||
<i :class="v.meta.icon"></i>
|
<i :class="v.meta.icon"></i>
|
||||||
<div class="layout-columns-aside-li-box-title font12">
|
<div class="layout-columns-aside-li-box-title font12">
|
||||||
{{ v.meta.title && v.meta.title.length >= 4 ? v.meta.title.substr(0, 4) : v.meta.title }}
|
{{ $t(v.meta.title) && $t(v.meta.title).length >= 4 ? $t(v.meta.title).substr(0, 4) :
|
||||||
|
$t(v.meta.title)
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,11 +6,11 @@
|
|||||||
<el-breadcrumb-item v-for="(v, k) in state.breadcrumbList" :key="v.meta.title">
|
<el-breadcrumb-item v-for="(v, k) in state.breadcrumbList" :key="v.meta.title">
|
||||||
<span v-if="k === state.breadcrumbList.length - 1" class="layout-navbars-breadcrumb-span">
|
<span v-if="k === state.breadcrumbList.length - 1" class="layout-navbars-breadcrumb-span">
|
||||||
<SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" />
|
<SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" />
|
||||||
{{ v.meta.title }}
|
{{ $t(v.meta.title) }}
|
||||||
</span>
|
</span>
|
||||||
<a v-else @click.prevent="onBreadcrumbClick(v)">
|
<a v-else @click.prevent="onBreadcrumbClick(v)">
|
||||||
<SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" />
|
<SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" />
|
||||||
{{ v.meta.title }}
|
{{ $t(v.meta.title) }}
|
||||||
</a>
|
</a>
|
||||||
</el-breadcrumb-item>
|
</el-breadcrumb-item>
|
||||||
</transition-group>
|
</transition-group>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<el-autocomplete
|
<el-autocomplete
|
||||||
v-model="state.menuQuery"
|
v-model="state.menuQuery"
|
||||||
:fetch-suggestions="menuSearch"
|
:fetch-suggestions="menuSearch"
|
||||||
placeholder="菜单搜索"
|
:placeholder="$t('layout.user.searchPlaceholder')"
|
||||||
prefix-icon="el-icon-search"
|
prefix-icon="el-icon-search"
|
||||||
ref="layoutMenuAutocompleteRef"
|
ref="layoutMenuAutocompleteRef"
|
||||||
@select="onHandleSelect"
|
@select="onHandleSelect"
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
</el-icon>
|
</el-icon>
|
||||||
</template>
|
</template>
|
||||||
<template #default="{ item }">
|
<template #default="{ item }">
|
||||||
<div><SvgIcon :name="item.meta.icon" class="mr5" />{{ item.meta.title }}</div>
|
<div><SvgIcon :name="item.meta.icon" class="mr5" />{{ $t(item.meta.title) }}</div>
|
||||||
</template>
|
</template>
|
||||||
</el-autocomplete>
|
</el-autocomplete>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@@ -27,6 +27,9 @@
|
|||||||
import { reactive, ref, nextTick } from 'vue';
|
import { reactive, ref, nextTick } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useRoutesList } from '@/store/routesList';
|
import { useRoutesList } from '@/store/routesList';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const layoutMenuAutocompleteRef: any = ref(null);
|
const layoutMenuAutocompleteRef: any = ref(null);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -50,16 +53,18 @@ const openSearch = () => {
|
|||||||
const closeSearch = () => {
|
const closeSearch = () => {
|
||||||
state.isShowSearch = false;
|
state.isShowSearch = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 菜单搜索数据过滤
|
// 菜单搜索数据过滤
|
||||||
const menuSearch = (queryString: any, cb: any) => {
|
const menuSearch = (queryString: any, cb: any) => {
|
||||||
let results = queryString ? state.tagsViewList.filter(createFilter(queryString)) : state.tagsViewList;
|
let results = queryString ? state.tagsViewList.filter(createFilter(t(queryString))) : state.tagsViewList;
|
||||||
cb(results);
|
cb(results);
|
||||||
};
|
};
|
||||||
// 菜单搜索过滤
|
// 菜单搜索过滤
|
||||||
const createFilter = (queryString: any) => {
|
const createFilter = (queryString: any) => {
|
||||||
return (restaurant: any) => {
|
return (restaurant: any) => {
|
||||||
return (
|
return (
|
||||||
restaurant.path.toLowerCase().indexOf(queryString.toLowerCase()) > -1 || restaurant.meta.title.toLowerCase().indexOf(queryString.toLowerCase()) > -1
|
t(restaurant.path).toLowerCase().indexOf(queryString.toLowerCase()) > -1 ||
|
||||||
|
t(restaurant.meta.title).toLowerCase().indexOf(queryString.toLowerCase()) > -1
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="layout-breadcrumb-seting">
|
<div class="layout-breadcrumb-seting">
|
||||||
<el-drawer title="布局设置" v-model="themeConfig.isDrawer" direction="rtl" destroy-on-close size="240px" @close="onDrawerClose">
|
<el-drawer :title="$t('layout.config.configTitle')" v-model="themeConfig.isDrawer" direction="rtl" destroy-on-close size="240px" @close="onDrawerClose">
|
||||||
<el-scrollbar class="layout-breadcrumb-seting-bar">
|
<el-scrollbar class="layout-breadcrumb-seting-bar">
|
||||||
<!-- ssh终端主题 -->
|
<!-- ssh终端主题 -->
|
||||||
<el-divider content-position="left">终端主题</el-divider>
|
<el-divider content-position="left">{{ $t('layout.config.terminalTheme') }}</el-divider>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex">
|
<div class="layout-breadcrumb-seting-bar-flex">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">主题</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('layout.config.theme') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-select @change="setLocalThemeConfig" v-model="themeConfig.terminalTheme" size="small" style="width: 140px">
|
<el-select v-model="themeConfig.terminalTheme" size="small" style="width: 140px">
|
||||||
<el-option v-for="(_, k) in themes" :key="k" :label="k" :value="k"> </el-option>
|
<el-option v-for="(_, k) in themes" :key="k" :label="k" :value="k"> </el-option>
|
||||||
<el-option label="自定义" value="custom"> </el-option>
|
<el-option :label="$t('layout.config.custom')" value="custom"> </el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="themeConfig.terminalTheme == 'custom'">
|
<template v-if="themeConfig.terminalTheme == 'custom'">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt10">
|
<div class="layout-breadcrumb-seting-bar-flex mt10">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">字体颜色</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('layout.config.fontColor') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-color-picker v-model="themeConfig.terminalForeground" size="small" @change="onColorPickerChange('terminalForeground')">
|
<el-color-picker v-model="themeConfig.terminalForeground" size="small" @change="onColorPickerChange('terminalForeground')">
|
||||||
</el-color-picker>
|
</el-color-picker>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex">
|
<div class="layout-breadcrumb-seting-bar-flex">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">背景颜色</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('layout.config.backgroundColor') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-color-picker v-model="themeConfig.terminalBackground" size="small" @change="onColorPickerChange('terminalBackground')">
|
<el-color-picker v-model="themeConfig.terminalBackground" size="small" @change="onColorPickerChange('terminalBackground')">
|
||||||
</el-color-picker>
|
</el-color-picker>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex">
|
<div class="layout-breadcrumb-seting-bar-flex">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">cursor颜色</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('layout.config.cursorColor') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-color-picker v-model="themeConfig.terminalCursor" size="small" @change="onColorPickerChange('terminalCursor')">
|
<el-color-picker v-model="themeConfig.terminalCursor" size="small" @change="onColorPickerChange('terminalCursor')">
|
||||||
</el-color-picker>
|
</el-color-picker>
|
||||||
@@ -38,35 +38,27 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt10">
|
<div class="layout-breadcrumb-seting-bar-flex mt10">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">字体大小</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('layout.config.fontSize') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-input-number
|
<el-input-number v-model="themeConfig.terminalFontSize" controls-position="right" :min="12" :max="24" size="small" style="width: 90px">
|
||||||
v-model="themeConfig.terminalFontSize"
|
|
||||||
controls-position="right"
|
|
||||||
:min="12"
|
|
||||||
:max="24"
|
|
||||||
@change="setLocalThemeConfig"
|
|
||||||
size="small"
|
|
||||||
style="width: 90px"
|
|
||||||
>
|
|
||||||
</el-input-number>
|
</el-input-number>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt10">
|
<div class="layout-breadcrumb-seting-bar-flex mt10">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">字体粗细</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('layout.config.fontWeight') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-select @change="setLocalThemeConfig" v-model="themeConfig.terminalFontWeight" size="small" style="width: 90px">
|
<el-select v-model="themeConfig.terminalFontWeight" size="small" style="width: 90px">
|
||||||
<el-option label="normal" value="normal"> </el-option>
|
<el-option label="normal" value="normal"> </el-option>
|
||||||
<el-option label="bold" value="bold"> </el-option>
|
<el-option label="bold" value="bold"> </el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-divider content-position="left">editor 设置</el-divider>
|
<el-divider content-position="left">{{ $t('layout.config.editorSetting') }}</el-divider>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex">
|
<div class="layout-breadcrumb-seting-bar-flex">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">主题</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('layout.config.theme') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-select @change="setLocalThemeConfig" v-model="themeConfig.editorTheme" size="small" style="width: 130px">
|
<el-select v-model="themeConfig.editorTheme" size="small" style="width: 130px">
|
||||||
<el-option label="vs" value="vs"> </el-option>
|
<el-option label="vs" value="vs"> </el-option>
|
||||||
<el-option label="vs-dark" value="vs-dark"> </el-option>
|
<el-option label="vs-dark" value="vs-dark"> </el-option>
|
||||||
<el-option label="SolarizedLight" value="SolarizedLight"> </el-option>
|
<el-option label="SolarizedLight" value="SolarizedLight"> </el-option>
|
||||||
@@ -75,16 +67,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 全局设置 -->
|
<!-- 全局设置 -->
|
||||||
<el-divider content-position="left">全局设置</el-divider>
|
<el-divider content-position="left">{{ $t('layout.config.globalSetting') }}</el-divider>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">分页size</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('layout.config.pagesize') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-input-number
|
<el-input-number
|
||||||
v-model="themeConfig.defaultListPageSize"
|
v-model="themeConfig.defaultListPageSize"
|
||||||
controls-position="right"
|
controls-position="right"
|
||||||
:min="10"
|
:min="10"
|
||||||
:max="50"
|
:max="50"
|
||||||
@change="setLocalThemeConfig"
|
|
||||||
size="small"
|
size="small"
|
||||||
style="width: 90px"
|
style="width: 90px"
|
||||||
>
|
>
|
||||||
@@ -93,7 +84,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 全局主题 -->
|
<!-- 全局主题 -->
|
||||||
<el-divider content-position="left">全局主题</el-divider>
|
<el-divider content-position="left">{{ $t('layout.config.globalTheme') }}</el-divider>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex">
|
<div class="layout-breadcrumb-seting-bar-flex">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">primary</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">primary</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
@@ -125,129 +116,156 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 菜单 / 顶栏 -->
|
<!-- 菜单 -->
|
||||||
<el-divider content-position="left">菜单 / 顶栏</el-divider>
|
<el-divider content-position="left">{{ $t('layout.config.menuSetting') }}</el-divider>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex">
|
<div class="layout-breadcrumb-seting-bar-flex">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">顶栏背景</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('layout.config.menuBar') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
|
||||||
<el-color-picker v-model="themeConfig.topBar" size="small" @change="onBgColorPickerChange('topBar')"> </el-color-picker>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex">
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">菜单背景</div>
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-color-picker v-model="themeConfig.menuBar" size="small" @change="onBgColorPickerChange('menuBar')"> </el-color-picker>
|
<el-color-picker v-model="themeConfig.menuBar" size="small" @change="onBgColorPickerChange('menuBar')"> </el-color-picker>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex">
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex-label">
|
||||||
|
{{ $t('layout.config.menuBarFontColor') }}
|
||||||
|
</div>
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
|
<el-color-picker v-model="themeConfig.menuBarColor" size="small" @change="onBgColorPickerChange('menuBarColor')"> </el-color-picker>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex mt14">
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex-label">
|
||||||
|
{{ $t('layout.config.menuBarActiveColor') }}
|
||||||
|
</div>
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
|
<el-switch v-model="themeConfig.isMenuBarColorHighlight" @change="onMenuBarHighlightChange"></el-switch>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex mt14">
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex-label">
|
||||||
|
{{ $t('layout.config.isMenuBarColorGradual') }}
|
||||||
|
</div>
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
|
<el-switch v-model="themeConfig.isMenuBarColorGradual" @change="onMenuBarGradualChange"></el-switch>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- <div class="layout-breadcrumb-seting-bar-flex">
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex-label">顶栏背景</div>
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
|
<el-color-picker v-model="themeConfig.topBar" size="small"
|
||||||
|
@change="onBgColorPickerChange('topBar')">
|
||||||
|
</el-color-picker>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex">
|
<div class="layout-breadcrumb-seting-bar-flex">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">分栏菜单背景</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">分栏菜单背景</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-color-picker v-model="themeConfig.columnsMenuBar" size="small" @change="onBgColorPickerChange('columnsMenuBar')"> </el-color-picker>
|
<el-color-picker v-model="themeConfig.columnsMenuBar" size="small"
|
||||||
|
@change="onBgColorPickerChange('columnsMenuBar')"> </el-color-picker>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex">
|
<div class="layout-breadcrumb-seting-bar-flex">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">顶栏默认字体颜色</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">顶栏默认字体颜色</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-color-picker v-model="themeConfig.topBarColor" size="small" @change="onBgColorPickerChange('topBarColor')"> </el-color-picker>
|
<el-color-picker v-model="themeConfig.topBarColor" size="small"
|
||||||
</div>
|
@change="onBgColorPickerChange('topBarColor')">
|
||||||
</div>
|
</el-color-picker>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex">
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">菜单默认字体颜色</div>
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
|
||||||
<el-color-picker v-model="themeConfig.menuBarColor" size="small" @change="onBgColorPickerChange('menuBarColor')"> </el-color-picker>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex">
|
<div class="layout-breadcrumb-seting-bar-flex">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">分栏菜单默认字体颜色</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">分栏菜单默认字体颜色</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-color-picker v-model="themeConfig.columnsMenuBarColor" size="small" @change="onBgColorPickerChange('columnsMenuBarColor')">
|
<el-color-picker v-model="themeConfig.columnsMenuBarColor" size="small"
|
||||||
|
@change="onBgColorPickerChange('columnsMenuBarColor')">
|
||||||
</el-color-picker>
|
</el-color-picker>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt10">
|
<div class="layout-breadcrumb-seting-bar-flex mt10">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">顶栏背景渐变</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">顶栏背景渐变</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-switch v-model="themeConfig.isTopBarColorGradual" @change="onTopBarGradualChange"></el-switch>
|
<el-switch v-model="themeConfig.isTopBarColorGradual"
|
||||||
</div>
|
@change="onTopBarGradualChange"></el-switch>
|
||||||
</div>
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt14">
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">菜单背景渐变</div>
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
|
||||||
<el-switch v-model="themeConfig.isMenuBarColorGradual" @change="onMenuBarGradualChange"></el-switch>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt14">
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">分栏菜单背景渐变</div>
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
|
||||||
<el-switch v-model="themeConfig.isColumnsMenuBarColorGradual" @change="onColumnsMenuBarGradualChange"></el-switch>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt14">
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">菜单字体背景高亮</div>
|
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
|
||||||
<el-switch v-model="themeConfig.isMenuBarColorHighlight" @change="onMenuBarHighlightChange"></el-switch>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex mt14">
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex-label">分栏菜单背景渐变</div>
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
|
<el-switch v-model="themeConfig.isColumnsMenuBarColorGradual"
|
||||||
|
@change="onColumnsMenuBarGradualChange"></el-switch>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
<!-- 界面设置 -->
|
<!-- 界面设置 -->
|
||||||
<el-divider content-position="left">界面设置</el-divider>
|
<el-divider content-position="left">{{ $t('layout.config.interfaceSetting') }}</el-divider>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex">
|
<div class="layout-breadcrumb-seting-bar-flex">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">菜单水平折叠</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">
|
||||||
|
{{ $t('layout.config.isCollapse') }}
|
||||||
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-switch v-model="themeConfig.isCollapse" @change="onThemeConfigChange"></el-switch>
|
<el-switch v-model="themeConfig.isCollapse" @change="onThemeConfigChange"></el-switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">菜单手风琴</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">
|
||||||
|
{{ $t('layout.config.isUniqueOpened') }}
|
||||||
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-switch v-model="themeConfig.isUniqueOpened" @change="setLocalThemeConfig"></el-switch>
|
<el-switch v-model="themeConfig.isUniqueOpened"></el-switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">固定 Header</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">
|
||||||
|
{{ $t('layout.config.isFixedHeader') }}
|
||||||
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-switch v-model="themeConfig.isFixedHeader" @change="onIsFixedHeaderChange"></el-switch>
|
<el-switch v-model="themeConfig.isFixedHeader" @change="onIsFixedHeaderChange"></el-switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: themeConfig.layout !== 'classic' ? 0.5 : 1 }">
|
<div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: themeConfig.layout !== 'classic' ? 0.5 : 1 }">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">经典布局分割菜单</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">
|
||||||
|
{{ $t('layout.config.isClassicSplitMenu') }}
|
||||||
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-switch v-model="themeConfig.isClassicSplitMenu" :disabled="themeConfig.layout !== 'classic'" @change="onClassicSplitMenuChange">
|
<el-switch v-model="themeConfig.isClassicSplitMenu" :disabled="themeConfig.layout !== 'classic'" @change="onClassicSplitMenuChange">
|
||||||
</el-switch>
|
</el-switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启锁屏</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">
|
||||||
|
{{ $t('layout.config.isLockScreen') }}
|
||||||
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-switch v-model="themeConfig.isLockScreen" @change="setLocalThemeConfig"></el-switch>
|
<el-switch v-model="themeConfig.isLockScreen"></el-switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt11">
|
<div class="layout-breadcrumb-seting-bar-flex mt11">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">自动锁屏(s/秒)</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">
|
||||||
|
{{ $t('layout.config.lockScreenTime') }}
|
||||||
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-input-number
|
<el-input-number v-model="themeConfig.lockScreenTime" controls-position="right" :min="0" :max="9999" size="small" style="width: 90px">
|
||||||
v-model="themeConfig.lockScreenTime"
|
|
||||||
controls-position="right"
|
|
||||||
:min="0"
|
|
||||||
:max="9999"
|
|
||||||
@change="setLocalThemeConfig"
|
|
||||||
size="small"
|
|
||||||
style="width: 90px"
|
|
||||||
>
|
|
||||||
</el-input-number>
|
</el-input-number>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 界面显示 -->
|
<!-- 界面显示 -->
|
||||||
<el-divider content-position="left">界面显示</el-divider>
|
<el-divider content-position="left">{{ $t('layout.config.interfaceDisplay') }}</el-divider>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">侧边栏 Logo</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('layout.config.isShowLogo') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-switch v-model="themeConfig.isShowLogo" @change="onIsShowLogoChange"></el-switch>
|
<el-switch v-model="themeConfig.isShowLogo" @change="onIsShowLogoChange"></el-switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: themeConfig.layout === 'transverse' ? 0.5 : 1 }">
|
<div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: themeConfig.layout === 'transverse' ? 0.5 : 1 }">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启Breadcrumb</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">
|
||||||
|
{{ $t('layout.config.isBreadcrumb') }}
|
||||||
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-switch
|
<el-switch
|
||||||
v-model="themeConfig.isBreadcrumb"
|
v-model="themeConfig.isBreadcrumb"
|
||||||
@@ -257,60 +275,68 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启Breadcrumb图标</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">
|
||||||
|
{{ $t('layout.config.isBreadcrumbIcon') }}
|
||||||
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-switch v-model="themeConfig.isBreadcrumbIcon" @change="setLocalThemeConfig"></el-switch>
|
<el-switch v-model="themeConfig.isBreadcrumbIcon"></el-switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启 Tagsview</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('layout.config.isTagsview') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-switch v-model="themeConfig.isTagsview" @change="setLocalThemeConfig"></el-switch>
|
<el-switch v-model="themeConfig.isTagsview"></el-switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启 Tagsview图标</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">
|
||||||
|
{{ $t('layout.config.isTagsviewIcon') }}
|
||||||
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-switch v-model="themeConfig.isTagsviewIcon" @change="setLocalThemeConfig"></el-switch>
|
<el-switch v-model="themeConfig.isTagsviewIcon"></el-switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启 TagsView缓存</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">
|
||||||
|
{{ $t('layout.config.isCacheTagsView') }}
|
||||||
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-switch v-model="themeConfig.isCacheTagsView" @change="setLocalThemeConfig"></el-switch>
|
<el-switch v-model="themeConfig.isCacheTagsView"></el-switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启 TagsView拖拽</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">
|
||||||
|
{{ $t('layout.config.isSortableTagsView') }}
|
||||||
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-switch v-model="themeConfig.isSortableTagsView" @change="onSortableTagsViewChange"></el-switch>
|
<el-switch v-model="themeConfig.isSortableTagsView" @change="onSortableTagsViewChange"></el-switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">开启 Footer</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('layout.config.isFooter') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-switch v-model="themeConfig.isFooter" @change="setLocalThemeConfig"></el-switch>
|
<el-switch v-model="themeConfig.isFooter"></el-switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">灰色模式</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('layout.config.isGrayscale') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-switch v-model="themeConfig.isGrayscale" @change="onAddFilterChange('grayscale')"></el-switch>
|
<el-switch v-model="themeConfig.isGrayscale" @change="onAddFilterChange('grayscale')"></el-switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">色弱模式</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('layout.config.isInvert') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-switch v-model="themeConfig.isInvert" @change="onAddFilterChange('invert')"></el-switch>
|
<el-switch v-model="themeConfig.isInvert" @change="onAddFilterChange('invert')"></el-switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 其它设置 -->
|
<!-- 其它设置 -->
|
||||||
<el-divider content-position="left">其他设置</el-divider>
|
<el-divider content-position="left">{{ $t('layout.config.otherSetting') }}</el-divider>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">Tagsview 风格</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('layout.config.tagsStyle') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-select v-model="themeConfig.tagsStyle" placeholder="请选择" size="small" style="width: 90px" @change="setLocalThemeConfig">
|
<el-select v-model="themeConfig.tagsStyle" placeholder="请选择" size="small" style="width: 90px">
|
||||||
<el-option label="风格1" value="tags-style-one"></el-option>
|
<el-option label="风格1" value="tags-style-one"></el-option>
|
||||||
<el-option label="风格2" value="tags-style-two"></el-option>
|
<el-option label="风格2" value="tags-style-two"></el-option>
|
||||||
<el-option label="风格3" value="tags-style-three"></el-option>
|
<el-option label="风格3" value="tags-style-three"></el-option>
|
||||||
@@ -318,9 +344,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
<div class="layout-breadcrumb-seting-bar-flex mt15">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">主页面切换动画</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('layout.config.animation') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-select v-model="themeConfig.animation" placeholder="请选择" size="small" style="width: 90px" @change="setLocalThemeConfig">
|
<el-select v-model="themeConfig.animation" size="small" style="width: 90px">
|
||||||
<el-option label="slide-right" value="slide-right"></el-option>
|
<el-option label="slide-right" value="slide-right"></el-option>
|
||||||
<el-option label="slide-left" value="slide-left"></el-option>
|
<el-option label="slide-left" value="slide-left"></el-option>
|
||||||
<el-option label="opacitys" value="opacitys"></el-option>
|
<el-option label="opacitys" value="opacitys"></el-option>
|
||||||
@@ -328,9 +354,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt15 mb28">
|
<div class="layout-breadcrumb-seting-bar-flex mt15 mb28">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">分栏高亮风格</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">
|
||||||
|
{{ $t('layout.config.columnsAsideStyle') }}
|
||||||
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
<el-select v-model="themeConfig.columnsAsideStyle" placeholder="请选择" size="small" style="width: 90px" @change="setLocalThemeConfig">
|
<el-select v-model="themeConfig.columnsAsideStyle" placeholder="请选择" size="small" style="width: 90px">
|
||||||
<el-option label="圆角" value="columns-round"></el-option>
|
<el-option label="圆角" value="columns-round"></el-option>
|
||||||
<el-option label="卡片" value="columns-card"></el-option>
|
<el-option label="卡片" value="columns-card"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
@@ -338,7 +366,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 布局切换 -->
|
<!-- 布局切换 -->
|
||||||
<el-divider content-position="left">布局切换</el-divider>
|
<el-divider content-position="left">{{ $t('layout.config.layoutSwitch') }}</el-divider>
|
||||||
<div class="layout-drawer-content-flex">
|
<div class="layout-drawer-content-flex">
|
||||||
<!-- defaults 布局 -->
|
<!-- defaults 布局 -->
|
||||||
<div class="layout-drawer-content-item" @click="onSetLayout('defaults')">
|
<div class="layout-drawer-content-item" @click="onSetLayout('defaults')">
|
||||||
@@ -351,7 +379,7 @@
|
|||||||
</section>
|
</section>
|
||||||
<div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': themeConfig.layout === 'defaults' }">
|
<div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': themeConfig.layout === 'defaults' }">
|
||||||
<div class="layout-tips-box">
|
<div class="layout-tips-box">
|
||||||
<p class="layout-tips-txt">默认</p>
|
<p class="layout-tips-txt">{{ $t('layout.config.defaults') }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -368,7 +396,7 @@
|
|||||||
</section>
|
</section>
|
||||||
<div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': themeConfig.layout === 'classic' }">
|
<div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': themeConfig.layout === 'classic' }">
|
||||||
<div class="layout-tips-box">
|
<div class="layout-tips-box">
|
||||||
<p class="layout-tips-txt">经典</p>
|
<p class="layout-tips-txt">{{ $t('layout.config.classic') }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -384,7 +412,7 @@
|
|||||||
</section>
|
</section>
|
||||||
<div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': themeConfig.layout === 'transverse' }">
|
<div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': themeConfig.layout === 'transverse' }">
|
||||||
<div class="layout-tips-box">
|
<div class="layout-tips-box">
|
||||||
<p class="layout-tips-txt">横向</p>
|
<p class="layout-tips-txt">{{ $t('layout.config.transverse') }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -400,7 +428,7 @@
|
|||||||
</section>
|
</section>
|
||||||
<div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': themeConfig.layout === 'columns' }">
|
<div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': themeConfig.layout === 'columns' }">
|
||||||
<div class="layout-tips-box">
|
<div class="layout-tips-box">
|
||||||
<p class="layout-tips-txt">分栏</p>
|
<p class="layout-tips-txt">{{ $t('layout.config.columns') }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -429,12 +457,12 @@ import ClipboardJS from 'clipboard';
|
|||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useThemeConfig } from '@/store/themeConfig';
|
import { useThemeConfig } from '@/store/themeConfig';
|
||||||
import { getLightColor } from '@/common/utils/theme';
|
import { getLightColor } from '@/common/utils/theme';
|
||||||
import { setLocal, getLocal, removeLocal } from '@/common/utils/storage';
|
import { setLocal, getLocal } from '@/common/utils/storage';
|
||||||
import mittBus from '@/common/utils/mitt';
|
import mittBus from '@/common/utils/mitt';
|
||||||
import themes from '@/components/terminal/themes';
|
import themes from '@/components/terminal/themes';
|
||||||
|
|
||||||
const copyConfigBtnRef = ref();
|
const copyConfigBtnRef = ref();
|
||||||
const { themeConfig } = storeToRefs(useThemeConfig());
|
const { themeConfig } = storeToRefs(useThemeConfig()) as any;
|
||||||
|
|
||||||
// 1、全局主题
|
// 1、全局主题
|
||||||
const onColorPickerChange = (color: string) => {
|
const onColorPickerChange = (color: string) => {
|
||||||
@@ -475,7 +503,7 @@ const setGraduaFun = (el: string, bool: boolean, color: string) => {
|
|||||||
if (!els) return false;
|
if (!els) return false;
|
||||||
if (bool) els.setAttribute('style', `background-image:linear-gradient(to bottom left , ${color}, ${getLightColor(color, 0.6)})`);
|
if (bool) els.setAttribute('style', `background-image:linear-gradient(to bottom left , ${color}, ${getLightColor(color, 0.6)})`);
|
||||||
else els.setAttribute('style', `background-image:${color}`);
|
else els.setAttribute('style', `background-image:${color}`);
|
||||||
setLocalThemeConfig();
|
|
||||||
const elNavbars: any = document.querySelector('.layout-navbars-breadcrumb-index');
|
const elNavbars: any = document.querySelector('.layout-navbars-breadcrumb-index');
|
||||||
const elAside: any = document.querySelector('.layout-container .el-aside');
|
const elAside: any = document.querySelector('.layout-container .el-aside');
|
||||||
const elColumns: any = document.querySelector('.layout-container .layout-columns-aside');
|
const elColumns: any = document.querySelector('.layout-container .layout-columns-aside');
|
||||||
@@ -498,7 +526,6 @@ const onMenuBarHighlightChange = () => {
|
|||||||
} else {
|
} else {
|
||||||
elActive.setAttribute('id', ``);
|
elActive.setAttribute('id', ``);
|
||||||
}
|
}
|
||||||
setLocalThemeConfig();
|
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -510,30 +537,26 @@ const onThemeConfigChange = () => {
|
|||||||
// 3、界面设置 --> 固定 Header
|
// 3、界面设置 --> 固定 Header
|
||||||
const onIsFixedHeaderChange = () => {
|
const onIsFixedHeaderChange = () => {
|
||||||
themeConfig.value.isFixedHeaderChange = themeConfig.value.isFixedHeader ? false : true;
|
themeConfig.value.isFixedHeaderChange = themeConfig.value.isFixedHeader ? false : true;
|
||||||
setLocalThemeConfig();
|
|
||||||
};
|
};
|
||||||
// 3、界面设置 --> 经典布局分割菜单
|
// 3、界面设置 --> 经典布局分割菜单
|
||||||
const onClassicSplitMenuChange = () => {
|
const onClassicSplitMenuChange = () => {
|
||||||
themeConfig.value.isBreadcrumb = false;
|
themeConfig.value.isBreadcrumb = false;
|
||||||
setLocalThemeConfig();
|
|
||||||
mittBus.emit('getBreadcrumbIndexSetFilterRoutes');
|
mittBus.emit('getBreadcrumbIndexSetFilterRoutes');
|
||||||
};
|
};
|
||||||
// 4、界面显示 --> 侧边栏 Logo
|
// 4、界面显示 --> 侧边栏 Logo
|
||||||
const onIsShowLogoChange = () => {
|
const onIsShowLogoChange = () => {
|
||||||
themeConfig.value.isShowLogoChange = themeConfig.value.isShowLogo ? false : true;
|
themeConfig.value.isShowLogoChange = themeConfig.value.isShowLogo ? false : true;
|
||||||
setLocalThemeConfig();
|
|
||||||
};
|
};
|
||||||
// 4、界面显示 --> 面包屑 Breadcrumb
|
// 4、界面显示 --> 面包屑 Breadcrumb
|
||||||
const onIsBreadcrumbChange = () => {
|
const onIsBreadcrumbChange = () => {
|
||||||
if (themeConfig.value.layout === 'classic') {
|
if (themeConfig.value.layout === 'classic') {
|
||||||
themeConfig.value.isClassicSplitMenu = false;
|
themeConfig.value.isClassicSplitMenu = false;
|
||||||
}
|
}
|
||||||
setLocalThemeConfig();
|
|
||||||
};
|
};
|
||||||
// 4、界面显示 --> 开启 TagsView 拖拽
|
// 4、界面显示 --> 开启 TagsView 拖拽
|
||||||
const onSortableTagsViewChange = () => {
|
const onSortableTagsViewChange = () => {
|
||||||
mittBus.emit('openOrCloseSortable');
|
mittBus.emit('openOrCloseSortable');
|
||||||
setLocalThemeConfig();
|
|
||||||
};
|
};
|
||||||
// 4、界面显示 --> 暗模式/灰色模式/色弱模式
|
// 4、界面显示 --> 暗模式/灰色模式/色弱模式
|
||||||
const onAddFilterChange = (attr: string) => {
|
const onAddFilterChange = (attr: string) => {
|
||||||
@@ -545,7 +568,7 @@ const onAddFilterChange = (attr: string) => {
|
|||||||
const cssAttr = attr === 'grayscale' ? `grayscale(${themeConfig.value.isGrayscale ? 1 : 0})` : `invert(${themeConfig.value.isInvert ? '80%' : '0%'})`;
|
const cssAttr = attr === 'grayscale' ? `grayscale(${themeConfig.value.isGrayscale ? 1 : 0})` : `invert(${themeConfig.value.isInvert ? '80%' : '0%'})`;
|
||||||
const appEle: any = document.querySelector('#app');
|
const appEle: any = document.querySelector('#app');
|
||||||
appEle.setAttribute('style', `filter: ${cssAttr}`);
|
appEle.setAttribute('style', `filter: ${cssAttr}`);
|
||||||
setLocalThemeConfig();
|
|
||||||
setLocal('appFilterStyle', appEle.style.cssText);
|
setLocal('appFilterStyle', appEle.style.cssText);
|
||||||
};
|
};
|
||||||
// 5、布局切换
|
// 5、布局切换
|
||||||
@@ -603,7 +626,6 @@ const onDrawerClose = () => {
|
|||||||
themeConfig.value.isFixedHeaderChange = false;
|
themeConfig.value.isFixedHeaderChange = false;
|
||||||
themeConfig.value.isShowLogoChange = false;
|
themeConfig.value.isShowLogoChange = false;
|
||||||
themeConfig.value.isDrawer = false;
|
themeConfig.value.isDrawer = false;
|
||||||
setLocalThemeConfig();
|
|
||||||
};
|
};
|
||||||
// 布局配置弹窗打开
|
// 布局配置弹窗打开
|
||||||
const openDrawer = () => {
|
const openDrawer = () => {
|
||||||
@@ -613,16 +635,12 @@ const openDrawer = () => {
|
|||||||
onCopyConfigClick(copyConfigBtnRef.value?.$el);
|
onCopyConfigClick(copyConfigBtnRef.value?.$el);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 触发 store 布局配置更新
|
// 触发 store 布局配置更新
|
||||||
const setDispatchThemeConfig = () => {
|
const setDispatchThemeConfig = () => {
|
||||||
setLocalThemeConfig();
|
|
||||||
setLocalThemeConfigStyle();
|
setLocalThemeConfigStyle();
|
||||||
};
|
};
|
||||||
// 存储布局配置
|
|
||||||
const setLocalThemeConfig = () => {
|
|
||||||
removeLocal('themeConfig');
|
|
||||||
setLocal('themeConfig', themeConfig.value);
|
|
||||||
};
|
|
||||||
// 存储布局配置全局主题样式(html根标签)
|
// 存储布局配置全局主题样式(html根标签)
|
||||||
const setLocalThemeConfigStyle = () => {
|
const setLocalThemeConfigStyle = () => {
|
||||||
setLocal('themeConfigStyle', document.documentElement.style.cssText);
|
setLocal('themeConfigStyle', document.documentElement.style.cssText);
|
||||||
|
|||||||
@@ -23,24 +23,32 @@
|
|||||||
<el-dropdown-item command="small" :disabled="state.disabledSize === 'small'">小型</el-dropdown-item>
|
<el-dropdown-item command="small" :disabled="state.disabledSize === 'small'">小型</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown> -->
|
</el-dropdown> -->
|
||||||
|
|
||||||
|
<el-dropdown :show-timeout="70" :hide-timeout="50" trigger="click" @command="onLanguageChange">
|
||||||
|
<div class="layout-navbars-breadcrumb-user-icon">
|
||||||
|
<SvgIcon :size="16" :name="EnumValue.getEnumByValue(I18nEnum, themeConfig.globalI18n)?.extra.icon" :title="$t('layout.user.langSwitch')" />
|
||||||
|
</div>
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item v-for="item in I18nEnum" :key="item.value" :command="item.value" :disabled="themeConfig.globalI18n === item.value">
|
||||||
|
{{ item.label }}
|
||||||
|
</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
|
||||||
<div class="layout-navbars-breadcrumb-user-icon" @click="onSearchClick">
|
<div class="layout-navbars-breadcrumb-user-icon" @click="onSearchClick">
|
||||||
<el-icon title="菜单搜索">
|
<SvgIcon name="search" :title="$t('layout.user.menuSearch')" />
|
||||||
<search />
|
|
||||||
</el-icon>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-navbars-breadcrumb-user-icon" @click="onLayoutSetingClick">
|
<div class="layout-navbars-breadcrumb-user-icon" @click="onLayoutSetingClick">
|
||||||
<el-icon title="布局设置">
|
<SvgIcon name="setting" :title="$t('layout.user.layoutConf')" />
|
||||||
<setting />
|
|
||||||
</el-icon>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-navbars-breadcrumb-user-icon">
|
<div class="layout-navbars-breadcrumb-user-icon">
|
||||||
<el-popover placement="bottom" trigger="click" :visible="state.isShowUserNewsPopover" :width="300" popper-class="el-popover-pupop-user-news">
|
<el-popover placement="bottom" trigger="click" :visible="state.isShowUserNewsPopover" :width="300" popper-class="el-popover-pupop-user-news">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-badge :is-dot="false" @click="state.isShowUserNewsPopover = !state.isShowUserNewsPopover">
|
<el-badge :is-dot="false" @click="state.isShowUserNewsPopover = !state.isShowUserNewsPopover">
|
||||||
<el-icon title="消息">
|
<SvgIcon name="bell" :title="$t('layout.user.news')" />
|
||||||
<bell />
|
|
||||||
</el-icon>
|
|
||||||
</el-badge>
|
</el-badge>
|
||||||
</template>
|
</template>
|
||||||
<transition name="el-zoom-in-top">
|
<transition name="el-zoom-in-top">
|
||||||
@@ -49,12 +57,8 @@
|
|||||||
</el-popover>
|
</el-popover>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-navbars-breadcrumb-user-icon mr10" @click="onScreenfullClick">
|
<div class="layout-navbars-breadcrumb-user-icon mr10" @click="onScreenfullClick">
|
||||||
<el-icon v-if="!state.isScreenfull" title="关全屏">
|
<SvgIcon v-if="!state.isScreenfull" name="full-screen" :title="$t('layout.user.fullScreenOff')" />
|
||||||
<full-screen />
|
<SvgIcon v-else name="crop" />
|
||||||
</el-icon>
|
|
||||||
<el-icon v-else title="开全屏">
|
|
||||||
<crop />
|
|
||||||
</el-icon>
|
|
||||||
</div>
|
</div>
|
||||||
<el-dropdown trigger="click" :show-timeout="70" :hide-timeout="50" @command="onHandleCommandClick">
|
<el-dropdown trigger="click" :show-timeout="70" :hide-timeout="50" @command="onHandleCommandClick">
|
||||||
<span class="layout-navbars-breadcrumb-user-link" style="cursor: pointer">
|
<span class="layout-navbars-breadcrumb-user-link" style="cursor: pointer">
|
||||||
@@ -64,9 +68,9 @@
|
|||||||
</span>
|
</span>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item command="/home">首页</el-dropdown-item>
|
<el-dropdown-item command="/home">{{ $t('layout.user.index') }}</el-dropdown-item>
|
||||||
<el-dropdown-item command="/personal">个人中心</el-dropdown-item>
|
<el-dropdown-item command="/personal">{{ $t('layout.user.personalCenter') }}</el-dropdown-item>
|
||||||
<el-dropdown-item divided command="logOut">退出登录</el-dropdown-item>
|
<el-dropdown-item divided command="logOut">{{ $t('layout.user.logout') }}</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
@@ -88,20 +92,23 @@ import UserNews from '@/layout/navBars/breadcrumb/userNews.vue';
|
|||||||
import SearchMenu from '@/layout/navBars/breadcrumb/search.vue';
|
import SearchMenu from '@/layout/navBars/breadcrumb/search.vue';
|
||||||
import mittBus from '@/common/utils/mitt';
|
import mittBus from '@/common/utils/mitt';
|
||||||
import openApi from '@/common/openApi';
|
import openApi from '@/common/openApi';
|
||||||
import { saveThemeConfig, getThemeConfig } from '@/common/utils/storage';
|
import { getThemeConfig } from '@/common/utils/storage';
|
||||||
import { useDark, usePreferredDark } from '@vueuse/core';
|
import { useDark, usePreferredDark } from '@vueuse/core';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { I18nEnum } from '@/common/commonEnum';
|
||||||
|
import EnumValue from '@/common/Enum';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const searchRef = ref();
|
const searchRef = ref();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
isScreenfull: false,
|
isScreenfull: false,
|
||||||
isShowUserNewsPopover: false,
|
isShowUserNewsPopover: false,
|
||||||
disabledI18n: 'zh-cn',
|
|
||||||
disabledSize: '',
|
disabledSize: '',
|
||||||
});
|
});
|
||||||
const { userInfo } = storeToRefs(useUserInfo());
|
const { userInfo } = storeToRefs(useUserInfo());
|
||||||
const themeConfigStore = useThemeConfig();
|
const themeConfigStore = useThemeConfig();
|
||||||
const { themeConfig } = storeToRefs(themeConfigStore);
|
const { themeConfig } = storeToRefs(themeConfigStore);
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
// 设置分割样式
|
// 设置分割样式
|
||||||
const layoutUserFlexNum = computed(() => {
|
const layoutUserFlexNum = computed(() => {
|
||||||
@@ -111,6 +118,16 @@ const layoutUserFlexNum = computed(() => {
|
|||||||
else num = '';
|
else num = '';
|
||||||
return num;
|
return num;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 页面加载时
|
||||||
|
onMounted(() => {
|
||||||
|
const themeConfig = getThemeConfig();
|
||||||
|
if (themeConfig) {
|
||||||
|
initComponentSize();
|
||||||
|
isDark.value = themeConfig.isDark;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 全屏点击时
|
// 全屏点击时
|
||||||
const onScreenfullClick = () => {
|
const onScreenfullClick = () => {
|
||||||
if (!screenfull.isEnabled) {
|
if (!screenfull.isEnabled) {
|
||||||
@@ -130,16 +147,16 @@ const onHandleCommandClick = (path: string) => {
|
|||||||
ElMessageBox({
|
ElMessageBox({
|
||||||
closeOnClickModal: false,
|
closeOnClickModal: false,
|
||||||
closeOnPressEscape: false,
|
closeOnPressEscape: false,
|
||||||
title: '提示',
|
title: t('layout.user.logOutTitle'),
|
||||||
message: '此操作将退出登录, 是否继续?',
|
message: t('layout.user.logOutMessage'),
|
||||||
showCancelButton: true,
|
showCancelButton: true,
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: t('common.confirm'),
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: t('common.cancel'),
|
||||||
beforeClose: async (action, instance, done) => {
|
beforeClose: async (action, instance, done) => {
|
||||||
if (action === 'confirm') {
|
if (action === 'confirm') {
|
||||||
await openApi.logout();
|
await openApi.logout();
|
||||||
instance.confirmButtonLoading = true;
|
instance.confirmButtonLoading = true;
|
||||||
instance.confirmButtonText = '退出中';
|
instance.confirmButtonText = t('layout.user.logOutExit');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
done();
|
done();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -156,7 +173,7 @@ const onHandleCommandClick = (path: string) => {
|
|||||||
resetRoute(); // 删除/重置路由
|
resetRoute(); // 删除/重置路由
|
||||||
router.push('/login');
|
router.push('/login');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
ElMessage.success('安全退出成功!');
|
ElMessage.success(t('layout.user.logoutSuccess'));
|
||||||
}, 300);
|
}, 300);
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
@@ -175,7 +192,6 @@ watch(preDark, (newValue) => {
|
|||||||
|
|
||||||
const switchDark = () => {
|
const switchDark = () => {
|
||||||
themeConfigStore.switchDark(isDark.value);
|
themeConfigStore.switchDark(isDark.value);
|
||||||
saveThemeConfig(themeConfig.value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// // 菜单搜索点击
|
// // 菜单搜索点击
|
||||||
@@ -211,14 +227,10 @@ const initComponentSize = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 页面加载时
|
// 语言切换
|
||||||
onMounted(() => {
|
const onLanguageChange = (lang: string) => {
|
||||||
const themeConfig = getThemeConfig();
|
themeConfig.value.globalI18n = lang;
|
||||||
if (themeConfig) {
|
};
|
||||||
initComponentSize();
|
|
||||||
isDark.value = themeConfig.isDark;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="layout-navbars-breadcrumb-user-news">
|
<div class="layout-navbars-breadcrumb-user-news">
|
||||||
<div class="head-box">
|
<div class="head-box">
|
||||||
<div class="head-box-title">通知</div>
|
<div class="head-box-title">{{ $t('layout.user.newTitle') }}</div>
|
||||||
<div class="head-box-btn" v-if="newsList.length > 0" @click="onAllReadClick">全部已读</div>
|
<div class="head-box-btn" v-if="newsList.length > 0" @click="onAllReadClick">{{ $t('layout.user.newBtn') }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content-box">
|
<div class="content-box">
|
||||||
<template v-if="newsList.length > 0">
|
<template v-if="newsList.length > 0">
|
||||||
@@ -14,9 +14,9 @@
|
|||||||
<div class="content-box-time">{{ v.time }}</div>
|
<div class="content-box-time">{{ v.time }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-empty description="暂无通知" v-else></el-empty>
|
<el-empty :description="$t('layout.user.newDesc')" v-else></el-empty>
|
||||||
</div>
|
</div>
|
||||||
<div class="foot-box" @click="toMsgCenter" v-if="newsList.length > 0">前往通知中心</div>
|
<div class="foot-box" @click="toMsgCenter" v-if="newsList.length > 0">{{ $t('layout.user.newGo') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -59,33 +59,41 @@ export default {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
.head-box-btn {
|
.head-box-btn {
|
||||||
color: var(--el-color-primary);
|
color: var(--el-color-primary);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-box {
|
.content-box {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|
||||||
.content-box-item {
|
.content-box-item {
|
||||||
padding-top: 12px;
|
padding-top: 12px;
|
||||||
|
|
||||||
&:last-of-type {
|
&:last-of-type {
|
||||||
padding-bottom: 12px;
|
padding-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-box-msg {
|
.content-box-msg {
|
||||||
color: #999999;
|
color: #999999;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-box-time {
|
.content-box-time {
|
||||||
color: #999999;
|
color: #999999;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.foot-box {
|
.foot-box {
|
||||||
height: 35px;
|
height: 35px;
|
||||||
color: var(--el-color-primary);
|
color: var(--el-color-primary);
|
||||||
@@ -96,10 +104,12 @@ export default {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-top: 1px solid #ebeef5;
|
border-top: 1px solid #ebeef5;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep(.el-empty__description p) {
|
::v-deep(.el-empty__description p) {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
>
|
>
|
||||||
<SvgIcon name="iconfont icon-tag-view-active" class="layout-navbars-tagsview-ul-li-iconfont font14" v-if="isActive(v)" />
|
<SvgIcon name="iconfont icon-tag-view-active" class="layout-navbars-tagsview-ul-li-iconfont font14" v-if="isActive(v)" />
|
||||||
<SvgIcon :name="v.icon" class="layout-navbars-tagsview-ul-li-iconfont" v-if="!isActive(v) && themeConfig.isTagsviewIcon" />
|
<SvgIcon :name="v.icon" class="layout-navbars-tagsview-ul-li-iconfont" v-if="!isActive(v) && themeConfig.isTagsviewIcon" />
|
||||||
<span>{{ v.title }}</span>
|
<span>{{ $t(v.title) }}</span>
|
||||||
<template v-if="isActive(v)">
|
<template v-if="isActive(v)">
|
||||||
<SvgIcon
|
<SvgIcon
|
||||||
name="RefreshRight"
|
name="RefreshRight"
|
||||||
@@ -74,7 +74,7 @@ const route = useRoute();
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const contextmenuItems = [
|
const contextmenuItems = [
|
||||||
new ContextmenuItem(0, '刷新').withIcon('RefreshRight').withOnClick((data: any) => {
|
new ContextmenuItem(0, 'layout.tagsView.refresh').withIcon('RefreshRight').withOnClick((data: any) => {
|
||||||
// path为fullPath
|
// path为fullPath
|
||||||
let { path } = data;
|
let { path } = data;
|
||||||
let currentTag = tagsViews.value.find((v: any) => v.path === path);
|
let currentTag = tagsViews.value.find((v: any) => v.path === path);
|
||||||
@@ -82,18 +82,18 @@ const contextmenuItems = [
|
|||||||
router.push({ path, query: currentTag?.query });
|
router.push({ path, query: currentTag?.query });
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new ContextmenuItem(1, '关闭').withIcon('Close').withOnClick((data: any) => closeCurrentTagsView(data.path)),
|
new ContextmenuItem(1, 'layout.tagsView.close').withIcon('Close').withOnClick((data: any) => closeCurrentTagsView(data.path)),
|
||||||
|
|
||||||
new ContextmenuItem(2, '关闭其他').withIcon('CircleClose').withOnClick((data: any) => {
|
new ContextmenuItem(2, 'layout.tagsView.closeOther').withIcon('CircleClose').withOnClick((data: any) => {
|
||||||
let { path } = data;
|
let { path } = data;
|
||||||
let currentTag = tagsViews.value.find((v: any) => v.path === path);
|
let currentTag = tagsViews.value.find((v: any) => v.path === path);
|
||||||
router.push({ path, query: currentTag?.query });
|
router.push({ path, query: currentTag?.query });
|
||||||
closeOtherTagsView(path);
|
closeOtherTagsView(path);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new ContextmenuItem(3, '关闭所有').withIcon('FolderDelete').withOnClick((data: any) => closeAllTagsView(data.path)),
|
new ContextmenuItem(3, 'layout.tagsView.closeAll').withIcon('FolderDelete').withOnClick((data: any) => closeAllTagsView(data.path)),
|
||||||
|
|
||||||
new ContextmenuItem(4, '当前页全屏').withIcon('full-screen').withOnClick((data: any) => openCurrenFullscreen(data.path)),
|
new ContextmenuItem(4, 'layout.tagsView.fullscreen').withIcon('full-screen').withOnClick((data: any) => openCurrenFullscreen(data.path)),
|
||||||
];
|
];
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
|
|||||||
@@ -6,19 +6,19 @@
|
|||||||
<el-sub-menu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path">
|
<el-sub-menu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path">
|
||||||
<template #title>
|
<template #title>
|
||||||
<SvgIcon :name="val.meta.icon" />
|
<SvgIcon :name="val.meta.icon" />
|
||||||
<span>{{ val.meta.title }}</span>
|
<span>{{ $t(val.meta.title) }}</span>
|
||||||
</template>
|
</template>
|
||||||
<SubItem :chil="val.children" />
|
<SubItem :chil="val.children" />
|
||||||
</el-sub-menu>
|
</el-sub-menu>
|
||||||
<el-menu-item :index="val.path" :key="val?.path" v-else>
|
<el-menu-item :index="val.path" :key="val?.path" v-else>
|
||||||
<template #title v-if="!val.meta.link || (val.meta.link && val.meta.linkType == 1)">
|
<template #title v-if="!val.meta.link || (val.meta.link && val.meta.linkType == 1)">
|
||||||
<SvgIcon :name="val.meta.icon" />
|
<SvgIcon :name="val.meta.icon" />
|
||||||
{{ val.meta.title }}
|
{{ $t(val.meta.title) }}
|
||||||
</template>
|
</template>
|
||||||
<template #title v-else>
|
<template #title v-else>
|
||||||
<a :href="val.meta.link" target="_blank">
|
<a :href="val.meta.link" target="_blank">
|
||||||
<SvgIcon :name="val.meta.icon" />
|
<SvgIcon :name="val.meta.icon" />
|
||||||
{{ val.meta.title }}
|
{{ $t(val.meta.title) }}
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
@@ -57,8 +57,7 @@ const menuLists = computed(() => {
|
|||||||
// 设置横向滚动条可以鼠标滚轮滚动
|
// 设置横向滚动条可以鼠标滚轮滚动
|
||||||
const onElMenuHorizontalScroll = (e: any) => {
|
const onElMenuHorizontalScroll = (e: any) => {
|
||||||
const eventDelta = e.wheelDelta || -e.deltaY * 40;
|
const eventDelta = e.wheelDelta || -e.deltaY * 40;
|
||||||
proxy.$refs.elMenuHorizontalScrollRef.$refs.wrapRef.scrollLeft =
|
proxy.$refs.elMenuHorizontalScrollRef.$refs.wrapRef.scrollLeft = proxy.$refs.elMenuHorizontalScrollRef.$refs.wrapRef.scrollLeft + eventDelta / 4;
|
||||||
proxy.$refs.elMenuHorizontalScrollRef.$refs.wrapRef.scrollLeft + eventDelta / 4;
|
|
||||||
};
|
};
|
||||||
// 初始化数据,页面刷新时,滚动条滚动到对应位置
|
// 初始化数据,页面刷新时,滚动条滚动到对应位置
|
||||||
const initElMenuOffsetLeft = () => {
|
const initElMenuOffsetLeft = () => {
|
||||||
|
|||||||
@@ -3,19 +3,19 @@
|
|||||||
<el-sub-menu :index="val.path" :key="val.path" v-if="val.children && val.children.length > 0">
|
<el-sub-menu :index="val.path" :key="val.path" v-if="val.children && val.children.length > 0">
|
||||||
<template #title>
|
<template #title>
|
||||||
<SvgIcon :name="val.meta.icon" />
|
<SvgIcon :name="val.meta.icon" />
|
||||||
<span>{{ val.meta.title }}</span>
|
<span>{{ $t(val.meta.title) }}</span>
|
||||||
</template>
|
</template>
|
||||||
<sub-item :chil="val.children" />
|
<sub-item :chil="val.children" />
|
||||||
</el-sub-menu>
|
</el-sub-menu>
|
||||||
<el-menu-item :index="val.path" :key="val?.path" v-else>
|
<el-menu-item :index="val.path" :key="val?.path" v-else>
|
||||||
<template v-if="!val.meta.link || (val.meta.link && val.meta.linkType == 1)">
|
<template v-if="!val.meta.link || (val.meta.link && val.meta.linkType == 1)">
|
||||||
<SvgIcon :name="val.meta.icon" />
|
<SvgIcon :name="val.meta.icon" />
|
||||||
<span>{{ val.meta.title }}</span>
|
<span>{{ $t(val.meta.title) }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a :href="val.meta.link" target="_blank">
|
<a :href="val.meta.link" target="_blank">
|
||||||
<SvgIcon :name="val.meta.icon" />
|
<SvgIcon :name="val.meta.icon" />
|
||||||
{{ val.meta.title }}
|
{{ $t(val.meta.title) }}
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
|||||||
@@ -11,17 +11,17 @@
|
|||||||
<el-sub-menu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path">
|
<el-sub-menu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path">
|
||||||
<template #title>
|
<template #title>
|
||||||
<SvgIcon :name="val.meta.icon" />
|
<SvgIcon :name="val.meta.icon" />
|
||||||
<span>{{ val.meta.title }}</span>
|
<span>{{ $t(val.meta.title) }}</span>
|
||||||
</template>
|
</template>
|
||||||
<SubItem :chil="val.children" />
|
<SubItem :chil="val.children" />
|
||||||
</el-sub-menu>
|
</el-sub-menu>
|
||||||
<el-menu-item :index="val.path" :key="val?.path" v-else>
|
<el-menu-item :index="val.path" :key="val?.path" v-else>
|
||||||
<SvgIcon :name="val.meta.icon" />
|
<SvgIcon :name="val.meta.icon" />
|
||||||
<template #title v-if="!val.meta.link || (val.meta.link && val.meta.linkType == 1)">
|
<template #title v-if="!val.meta.link || (val.meta.link && val.meta.linkType == 1)">
|
||||||
<span>{{ val.meta.title }}</span>
|
<span>{{ $t(val.meta.title) }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template #title v-else>
|
<template #title v-else>
|
||||||
<a :href="val.meta.link" target="_blank">{{ val.meta.title }}</a></template
|
<a :href="val.meta.link" target="_blank">{{ $t(val.meta.title) }}</a></template
|
||||||
>
|
>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="layout-view-bg-white flex layout-view-link">
|
<div class="layout-view-bg-white flex layout-view-link">
|
||||||
<a :href="currentRouteMeta.link" target="_blank" class="flex-margin">{{ currentRouteMeta.title }}:{{ currentRouteMeta.link }}</a>
|
<a :href="currentRouteMeta.link" target="_blank" class="flex-margin"> {{ $t(currentRouteMeta.title) }}:{{ currentRouteMeta.link }} </a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -4,27 +4,27 @@ import App from '@/App.vue';
|
|||||||
import router from './router';
|
import router from './router';
|
||||||
import pinia from '@/store/index';
|
import pinia from '@/store/index';
|
||||||
import { directive } from '@/directive/index';
|
import { directive } from '@/directive/index';
|
||||||
import { globalComponentSize } from '@/common/utils/componentSize';
|
|
||||||
import { registElSvgIcon } from '@/common/utils/svgIcons';
|
import { registElSvgIcon } from '@/common/utils/svgIcons';
|
||||||
|
|
||||||
import ElementPlus from 'element-plus';
|
import ElementPlus from 'element-plus';
|
||||||
import 'element-plus/dist/index.css';
|
import 'element-plus/dist/index.css';
|
||||||
import 'element-plus/theme-chalk/dark/css-vars.css';
|
import 'element-plus/theme-chalk/dark/css-vars.css';
|
||||||
import zhCn from 'element-plus/es/locale/lang/zh-cn';
|
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { i18n } from '@/i18n/index';
|
||||||
|
|
||||||
import 'splitpanes/dist/splitpanes.css';
|
import 'splitpanes/dist/splitpanes.css';
|
||||||
|
|
||||||
import '@/theme/index.scss';
|
import '@/theme/index.scss';
|
||||||
import '@/assets/font/font.css';
|
import '@/assets/font/font.css';
|
||||||
import '@/assets/iconfont/iconfont.js';
|
import '@/assets/iconfont/iconfont.js';
|
||||||
|
import { getThemeConfig } from './common/utils/storage';
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
registElSvgIcon(app);
|
registElSvgIcon(app);
|
||||||
directive(app);
|
directive(app);
|
||||||
|
|
||||||
app.use(pinia).use(router).use(ElementPlus, { size: globalComponentSize, locale: zhCn }).mount('#app');
|
app.use(pinia).use(router).use(i18n).use(ElementPlus, { size: getThemeConfig()?.globalComponentSize }).mount('#app');
|
||||||
|
|
||||||
// 屏蔽警告信息
|
// 屏蔽警告信息
|
||||||
app.config.warnHandler = () => null;
|
app.config.warnHandler = () => null;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export const staticRoutes: Array<RouteRecordRaw> = [
|
|||||||
name: 'login',
|
name: 'login',
|
||||||
component: () => import('@/views/login/index.vue'),
|
component: () => import('@/views/login/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '登录',
|
title: 'staticRoutes.signIn',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -40,7 +40,7 @@ export const staticRoutes: Array<RouteRecordRaw> = [
|
|||||||
name: 'oauth2Callback',
|
name: 'oauth2Callback',
|
||||||
component: () => import('@/views/oauth/Oauth2Callback.vue'),
|
component: () => import('@/views/oauth/Oauth2Callback.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'oauth2回调',
|
title: 'oauth2 callback',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -49,7 +49,7 @@ export const staticRoutes: Array<RouteRecordRaw> = [
|
|||||||
component: () => import('@/views/ops/machine/SshTerminalPage.vue'),
|
component: () => import('@/views/ops/machine/SshTerminalPage.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
// 将路径 'xxx?name=名字' 里的name字段值替换到title里
|
// 将路径 'xxx?name=名字' 里的name字段值替换到title里
|
||||||
title: '终端 | {name}',
|
title: 'terminal | {name}',
|
||||||
// 是否根据query对标题名进行参数替换,即最终显示为‘终端_机器名’
|
// 是否根据query对标题名进行参数替换,即最终显示为‘终端_机器名’
|
||||||
titleRename: true,
|
titleRename: true,
|
||||||
},
|
},
|
||||||
@@ -60,7 +60,7 @@ export const staticRoutes: Array<RouteRecordRaw> = [
|
|||||||
component: () => import('@/views/ops/machine/RdpTerminalPage.vue'),
|
component: () => import('@/views/ops/machine/RdpTerminalPage.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
// 将路径 'xxx?name=名字' 里的name字段值替换到title里
|
// 将路径 'xxx?name=名字' 里的name字段值替换到title里
|
||||||
title: '终端 | {name}',
|
title: 'terminal | {name}',
|
||||||
// 是否根据query对标题名进行参数替换,即最终显示为‘终端_机器名’
|
// 是否根据query对标题名进行参数替换,即最终显示为‘终端_机器名’
|
||||||
titleRename: true,
|
titleRename: true,
|
||||||
},
|
},
|
||||||
@@ -74,7 +74,7 @@ export const errorRoutes: Array<RouteRecordRaw> = [
|
|||||||
name: 'notFound',
|
name: 'notFound',
|
||||||
component: () => import('@/views/error/404.vue'),
|
component: () => import('@/views/error/404.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '找不到此页面',
|
title: 'staticRoutes.notFound',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -82,7 +82,7 @@ export const errorRoutes: Array<RouteRecordRaw> = [
|
|||||||
name: 'noPower',
|
name: 'noPower',
|
||||||
component: () => import('@/views/error/401.vue'),
|
component: () => import('@/views/error/401.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '没有权限',
|
title: 'staticRoutes.noPower',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Resolve refresh page, route warnings
|
// Resolve refresh page, route warnings
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { formatDate } from '@/common/utils/format';
|
import { formatDate } from '@/common/utils/format';
|
||||||
import { useUserInfo } from '@/store/userInfo';
|
import { useUserInfo } from '@/store/userInfo';
|
||||||
import { getSysStyleConfig } from '@/common/sysconfig';
|
import { getServerConf, getSysStyleConfig } from '@/common/sysconfig';
|
||||||
import { getLocal, getThemeConfig } from '@/common/utils/storage';
|
import { getLocal, getThemeConfig } from '@/common/utils/storage';
|
||||||
|
|
||||||
// 系统默认logo图标,对应于@/assets/image/logo.svg
|
// 系统默认logo图标,对应于@/assets/image/logo.svg
|
||||||
@@ -154,9 +154,14 @@ export const useThemeConfig = defineStore('themeConfig', {
|
|||||||
initThemeConfig() {
|
initThemeConfig() {
|
||||||
// 获取缓存中的布局配置
|
// 获取缓存中的布局配置
|
||||||
const tc = getThemeConfig();
|
const tc = getThemeConfig();
|
||||||
|
|
||||||
if (tc) {
|
if (tc) {
|
||||||
this.themeConfig = tc;
|
this.themeConfig = tc;
|
||||||
document.documentElement.style.cssText = getLocal('themeConfigStyle');
|
document.documentElement.style.cssText = getLocal('themeConfigStyle');
|
||||||
|
} else {
|
||||||
|
getServerConf().then((res) => {
|
||||||
|
this.themeConfig.globalI18n = res.i18n;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据后台系统配置初始化
|
// 根据后台系统配置初始化
|
||||||
|
|||||||
@@ -4,10 +4,12 @@
|
|||||||
<div class="left">
|
<div class="left">
|
||||||
<div class="left-item">
|
<div class="left-item">
|
||||||
<div class="left-item-animation left-item-num">401</div>
|
<div class="left-item-animation left-item-num">401</div>
|
||||||
<div class="left-item-animation left-item-title">您未被授权或登录超时,没有操作权限</div>
|
<div class="left-item-animation left-item-title">{{ $t('layout.noAccess.title') }}</div>
|
||||||
<div class="left-item-animation left-item-msg"></div>
|
<div class="left-item-animation left-item-msg"></div>
|
||||||
<div class="left-item-animation left-item-btn">
|
<div class="left-item-animation left-item-btn">
|
||||||
<el-button type="primary" round @click="onSetAuth">重新登录</el-button>
|
<el-button type="primary" round @click="onSetAuth">
|
||||||
|
{{ $t('layout.noAccess.loginAgain') }}
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -46,16 +48,19 @@ export default {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: var(--bg-main-color);
|
background-color: var(--bg-main-color);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
.error-flex {
|
.error-flex {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 350px;
|
height: 350px;
|
||||||
width: 900px;
|
width: 900px;
|
||||||
|
|
||||||
.left {
|
.left {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
.left-item {
|
.left-item {
|
||||||
.left-item-animation {
|
.left-item-animation {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@@ -63,33 +68,39 @@ export default {
|
|||||||
animation-duration: 0.5s;
|
animation-duration: 0.5s;
|
||||||
animation-fill-mode: forwards;
|
animation-fill-mode: forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-item-num {
|
.left-item-num {
|
||||||
color: #d6e0f6;
|
color: #d6e0f6;
|
||||||
font-size: 55px;
|
font-size: 55px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-item-title {
|
.left-item-title {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
// color: #333333;
|
// color: #333333;
|
||||||
margin: 15px 0 5px 0;
|
margin: 15px 0 5px 0;
|
||||||
animation-delay: 0.1s;
|
animation-delay: 0.1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-item-msg {
|
.left-item-msg {
|
||||||
color: #c0bebe;
|
color: #c0bebe;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
animation-delay: 0.2s;
|
animation-delay: 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-item-btn {
|
.left-item-btn {
|
||||||
animation-delay: 0.2s;
|
animation-delay: 0.2s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.right {
|
.right {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
animation-name: error-img;
|
animation-name: error-img;
|
||||||
animation-duration: 2s;
|
animation-duration: 2s;
|
||||||
animation-fill-mode: forwards;
|
animation-fill-mode: forwards;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -4,10 +4,12 @@
|
|||||||
<div class="left">
|
<div class="left">
|
||||||
<div class="left-item">
|
<div class="left-item">
|
||||||
<div class="left-item-animation left-item-num">404</div>
|
<div class="left-item-animation left-item-num">404</div>
|
||||||
<div class="left-item-animation left-item-title">地址输入有误,请重新输入地址~</div>
|
<div class="left-item-animation left-item-title">{{ $t('layout.notFound.title') }}</div>
|
||||||
<div class="left-item-animation left-item-msg">您可以先检查网址,然后重新输入</div>
|
<div class="left-item-animation left-item-msg">{{ $t('layout.notFound.msg') }}</div>
|
||||||
<div class="left-item-animation left-item-btn">
|
<div class="left-item-animation left-item-btn">
|
||||||
<el-button type="primary" round @click="onGoHome">返回首页</el-button>
|
<el-button type="primary" round @click="onGoHome">
|
||||||
|
{{ $t('layout.notFound.backHomepage') }}
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -39,16 +41,19 @@ export default {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: var(--bg-main-color);
|
background-color: var(--bg-main-color);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
.error-flex {
|
.error-flex {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 350px;
|
height: 350px;
|
||||||
width: 900px;
|
width: 900px;
|
||||||
|
|
||||||
.left {
|
.left {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
.left-item {
|
.left-item {
|
||||||
.left-item-animation {
|
.left-item-animation {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@@ -56,33 +61,39 @@ export default {
|
|||||||
animation-duration: 0.5s;
|
animation-duration: 0.5s;
|
||||||
animation-fill-mode: forwards;
|
animation-fill-mode: forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-item-num {
|
.left-item-num {
|
||||||
color: #d6e0f6;
|
color: #d6e0f6;
|
||||||
font-size: 55px;
|
font-size: 55px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-item-title {
|
.left-item-title {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
// color: #333333;
|
// color: #333333;
|
||||||
margin: 15px 0 5px 0;
|
margin: 15px 0 5px 0;
|
||||||
animation-delay: 0.1s;
|
animation-delay: 0.1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-item-msg {
|
.left-item-msg {
|
||||||
color: #c0bebe;
|
color: #c0bebe;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
animation-delay: 0.2s;
|
animation-delay: 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-item-btn {
|
.left-item-btn {
|
||||||
animation-delay: 0.2s;
|
animation-delay: 0.2s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.right {
|
.right {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
animation-name: error-img;
|
animation-name: error-img;
|
||||||
animation-duration: 2s;
|
animation-duration: 2s;
|
||||||
animation-fill-mode: forwards;
|
animation-fill-mode: forwards;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -6,15 +6,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-form :model="form" ref="formRef" :rules="rules" label-width="auto">
|
<el-form :model="form" ref="formRef" :rules="rules" label-width="auto">
|
||||||
<el-form-item prop="bizType" label="业务类型">
|
<el-form-item prop="bizType" :label="$t('flow.bizType')">
|
||||||
<EnumSelect v-model="form.bizType" :enums="FlowBizType" placeholder="请选择业务类型" />
|
<EnumSelect v-model="form.bizType" :enums="FlowBizType" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item prop="remark" label="备注">
|
<el-form-item prop="remark" :label="$t('common.remark')">
|
||||||
<el-input v-model.trim="form.remark" type="textarea" placeholder="备注" auto-complete="off" clearable></el-input>
|
<el-input v-model.trim="form.remark" type="textarea" auto-complete="off" clearable></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-divider content-position="left">业务信息</el-divider>
|
<el-divider content-position="left">{{ $t('flow.bizInfo') }}</el-divider>
|
||||||
<component
|
<component
|
||||||
ref="bizFormRef"
|
ref="bizFormRef"
|
||||||
v-if="form.bizType"
|
v-if="form.bizType"
|
||||||
@@ -26,17 +26,18 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<span v-if="flowProcdef || !state.form.procdefId">
|
<span v-if="flowProcdef || !state.form.procdefId">
|
||||||
<el-divider content-position="left">审批节点</el-divider>
|
<el-divider content-position="left">{{ $t('flow.approvalNode') }}</el-divider>
|
||||||
|
|
||||||
<ProcdefTasks v-if="flowProcdef" :procdef="flowProcdef" />
|
<ProcdefTasks v-if="flowProcdef" :procdef="flowProcdef" />
|
||||||
|
|
||||||
<el-result v-if="!state.form.procdefId" icon="error" title="不存在审批节点" sub-title="该资源无需审批操作"> </el-result>
|
<el-result v-if="!state.form.procdefId" icon="error" :title="$t('flow.approvalNodeNotExist')" :sub-title="$t('flow.resourceNotExistFlow')">
|
||||||
|
</el-result>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div>
|
<div>
|
||||||
<el-button @click="cancel()">取 消</el-button>
|
<el-button @click="cancel()">{{ $t('common.cancel') }}</el-button>
|
||||||
<el-button type="primary" :loading="saveBtnLoading" @click="btnOk" :disabled="!state.form.procdefId">确 定</el-button>
|
<el-button type="primary" :loading="saveBtnLoading" @click="btnOk" :disabled="!state.form.procdefId">{{ $t('common.confirm') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
@@ -52,9 +53,13 @@ import { FlowBizType } from './enums';
|
|||||||
import EnumSelect from '@/components/enumselect/EnumSelect.vue';
|
import EnumSelect from '@/components/enumselect/EnumSelect.vue';
|
||||||
import ProcdefTasks from './components/ProcdefTasks.vue';
|
import ProcdefTasks from './components/ProcdefTasks.vue';
|
||||||
import RedisRunCmdFlowBizForm from './flowbiz/redis/RedisRunCmdFlowBizForm.vue';
|
import RedisRunCmdFlowBizForm from './flowbiz/redis/RedisRunCmdFlowBizForm.vue';
|
||||||
|
import { useI18nPleaseInput, useI18nPleaseSelect } from '@/hooks/useI18n';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
const DbSqlExecFlowBizForm = defineAsyncComponent(() => import('./flowbiz/dbms/DbSqlExecFlowBizForm.vue'));
|
const DbSqlExecFlowBizForm = defineAsyncComponent(() => import('./flowbiz/dbms/DbSqlExecFlowBizForm.vue'));
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -79,14 +84,14 @@ const rules = {
|
|||||||
bizType: [
|
bizType: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请选择流程业务类型',
|
message: useI18nPleaseSelect('flow.bizType'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
remark: [
|
remark: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入申请备注',
|
message: useI18nPleaseInput('common.remark'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -125,12 +130,12 @@ const btnOk = async () => {
|
|||||||
await formRef.value.validate();
|
await formRef.value.validate();
|
||||||
await bizFormRef.value.validateBizForm();
|
await bizFormRef.value.validateBizForm();
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
ElMessage.error('请正确填写信息');
|
ElMessage.error(t('flow.procinstFormError'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
await procinstStart();
|
await procinstStart();
|
||||||
ElMessage.success('流程发起成功');
|
ElMessage.success(t('flow.procinstStartSuccess'));
|
||||||
emit('val-change', state.form);
|
emit('val-change', state.form);
|
||||||
//重置表单域
|
//重置表单域
|
||||||
cancel();
|
cancel();
|
||||||
|
|||||||
@@ -6,24 +6,20 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-form :model="form" ref="formRef" :rules="rules" label-width="auto">
|
<el-form :model="form" ref="formRef" :rules="rules" label-width="auto">
|
||||||
<el-form-item prop="name" label="名称">
|
<el-form-item prop="name" :label="$t('common.name')">
|
||||||
<el-input v-model.trim="form.name" placeholder="请输入流程名称" auto-complete="off" clearable></el-input>
|
<el-input v-model.trim="form.name" auto-complete="off" clearable></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="defKey" label="key">
|
<el-form-item prop="defKey" label="Key">
|
||||||
<el-input :disabled="form.id" v-model.trim="form.defKey" placeholder="请输入流程key" auto-complete="off" clearable></el-input>
|
<el-input :disabled="form.id" v-model.trim="form.defKey" auto-complete="off" clearable></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="status" label="状态">
|
<el-form-item prop="status" :label="$t('common.status')">
|
||||||
<el-select v-model="form.status" placeholder="请选择状态">
|
<EnumSelect :enums="ProcdefStatus" v-model="form.status" />
|
||||||
<el-option v-for="item in ProcdefStatus" :key="item.value" :label="item.label" :value="item.value"> </el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="condition" label="触发条件">
|
<el-form-item prop="condition" :label="$t('flow.triggeringCondition')">
|
||||||
<template #label>
|
<template #label>
|
||||||
触发条件
|
{{ $t('flow.triggeringCondition') }}
|
||||||
<el-tooltip content="go template语法。若输出结果为1,则表示触发该审批流程" placement="top">
|
<el-tooltip :content="$t('flow.triggeringConditionTips')" placement="top">
|
||||||
<el-icon>
|
<SvgIcon name="question-filled" />
|
||||||
<question-filled />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -31,42 +27,46 @@
|
|||||||
v-model="form.condition"
|
v-model="form.condition"
|
||||||
:rows="10"
|
:rows="10"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
placeholder="触发条件, 返回值=1, 则表示触发该审批流程"
|
:placeholder="$t('flow.conditionPlaceholder')"
|
||||||
auto-complete="off"
|
auto-complete="off"
|
||||||
clearable
|
clearable
|
||||||
></el-input>
|
></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="remark" label="备注">
|
<el-form-item prop="remark" :label="$t('common.remark')">
|
||||||
<el-input v-model.trim="form.remark" placeholder="备注" auto-complete="off" clearable></el-input>
|
<el-input v-model.trim="form.remark" auto-complete="off" clearable></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item ref="tagSelectRef" prop="codePaths" label="关联资源">
|
<el-form-item ref="tagSelectRef" prop="codePaths" :label="$t('tag.relateTag')">
|
||||||
<tag-tree-check height="300px" v-model="form.codePaths" :tag-type="[TagResourceTypeEnum.DbName.value, TagResourceTypeEnum.Redis.value]" />
|
<tag-tree-check height="300px" v-model="form.codePaths" :tag-type="[TagResourceTypeEnum.DbName.value, TagResourceTypeEnum.Redis.value]" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-divider content-position="left">审批节点</el-divider>
|
<el-divider content-position="left">{{ $t('flow.approvalNode') }}</el-divider>
|
||||||
|
|
||||||
<el-table ref="taskTableRef" :data="tasks" row-key="taskKey" stripe style="width: 100%">
|
<el-table ref="taskTableRef" :data="tasks" row-key="taskKey" stripe style="width: 100%">
|
||||||
<el-table-column prop="name" label="名称" min-width="100px">
|
<el-table-column prop="name" min-width="100px">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-button class="ml0" type="primary" circle size="small" icon="Plus" @click="addTask()"> </el-button>
|
<el-button class="ml0" type="primary" circle size="small" icon="Plus" @click="addTask()"> </el-button>
|
||||||
<span class="ml10">节点名称</span>
|
<span class="ml10">{{ $t('flow.nodeName') }}<span class="ml5" style="color: red">*</span></span>
|
||||||
<el-tooltip content="点击指定节点可进行拖拽排序" placement="top">
|
<el-tooltip :content="$t('flow.nodeNameTips')" placement="top">
|
||||||
<el-icon class="ml5">
|
<SvgIcon class="ml5" name="question-filled" />
|
||||||
<question-filled />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-input v-model="scope.row.name"> </el-input>
|
<el-input v-model="scope.row.name"> </el-input>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="userId" label="审核人员" min-width="150px" show-overflow-tooltip>
|
|
||||||
|
<el-table-column prop="userId" min-width="150px" show-overflow-tooltip>
|
||||||
|
<template #header>
|
||||||
|
<span class="ml10">{{ $t('flow.auditor') }}<span class="ml5" style="color: red">*</span></span>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<AccountSelectFormItem v-model="scope.row.userId" label="" />
|
<AccountSelectFormItem v-model="scope.row.userId" label="" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="60px">
|
|
||||||
|
<el-table-column :label="$t('common.operation')" width="110px">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-link @click="deleteTask(scope.$index)" class="ml5" type="danger" icon="delete" plain></el-link>
|
<el-link @click="deleteTask(scope.$index)" class="ml5" type="danger" icon="delete" plain></el-link>
|
||||||
</template>
|
</template>
|
||||||
@@ -76,8 +76,8 @@
|
|||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div>
|
<div>
|
||||||
<el-button @click="cancel()">取 消</el-button>
|
<el-button @click="cancel()">{{ $t('common.cancel') }}</el-button>
|
||||||
<el-button type="primary" :loading="saveBtnLoading" @click="btnOk">确 定</el-button>
|
<el-button type="primary" :loading="saveBtnLoading" @click="btnOk">{{ $t('common.confirm') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
@@ -95,6 +95,11 @@ import { randomUuid } from '../../common/utils/string';
|
|||||||
import { ProcdefStatus } from './enums';
|
import { ProcdefStatus } from './enums';
|
||||||
import TagTreeCheck from '../ops/component/TagTreeCheck.vue';
|
import TagTreeCheck from '../ops/component/TagTreeCheck.vue';
|
||||||
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
||||||
|
import EnumSelect from '@/components/enumselect/EnumSelect.vue';
|
||||||
|
import { useI18nFormValidate, useI18nPleaseInput, useI18nSaveSuccessMsg } from '@/hooks/useI18n';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
@@ -117,14 +122,14 @@ const rules = {
|
|||||||
name: [
|
name: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入流程名称',
|
message: useI18nPleaseInput('common.name'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
defKey: [
|
defKey: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入流程key',
|
message: useI18nPleaseInput('Key'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -161,23 +166,7 @@ watch(props, (newValue: any) => {
|
|||||||
state.tasks = tasks;
|
state.tasks = tasks;
|
||||||
} else {
|
} else {
|
||||||
state.form = { status: ProcdefStatus.Enable.value } as any;
|
state.form = { status: ProcdefStatus.Enable.value } as any;
|
||||||
state.form.condition = `{{/* DBMS-执行sql规则; param参数描述如下 */}}
|
state.form.condition = t('flow.conditionDefault');
|
||||||
{{/* stmtType: select / read / insert / update / delete / ddl ; */}}
|
|
||||||
{{ if eq .bizType "db_sql_exec_flow"}}
|
|
||||||
{{/* 不是select和read语句时,开启流程审批 */}}
|
|
||||||
{{ if and (ne .param.stmtType "select") (ne .param.stmtType "read") }}
|
|
||||||
1
|
|
||||||
{{ end }}
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
{{/* Redis-执行命令规则; param参数描述如下 */}}
|
|
||||||
{{/* cmdType: read(读命令) / write(写命令); */}}
|
|
||||||
{{/* cmd: get/set/hset...等 */}}
|
|
||||||
{{ if eq .bizType "redis_run_cmd_flow"}}
|
|
||||||
{{ if eq .param.cmdType "write" }}
|
|
||||||
1
|
|
||||||
{{ end }}
|
|
||||||
{{ end }}`;
|
|
||||||
state.tasks = [];
|
state.tasks = [];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -205,13 +194,7 @@ const deleteTask = (idx: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const btnOk = async () => {
|
const btnOk = async () => {
|
||||||
try {
|
await useI18nFormValidate(formRef);
|
||||||
await formRef.value.validate();
|
|
||||||
} catch (e: any) {
|
|
||||||
ElMessage.error('请正确填写信息');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkRes = checkTasks();
|
const checkRes = checkTasks();
|
||||||
if (checkRes.err) {
|
if (checkRes.err) {
|
||||||
ElMessage.error(checkRes.err);
|
ElMessage.error(checkRes.err);
|
||||||
@@ -220,7 +203,7 @@ const btnOk = async () => {
|
|||||||
|
|
||||||
state.form.tasks = JSON.stringify(checkRes.tasks);
|
state.form.tasks = JSON.stringify(checkRes.tasks);
|
||||||
await saveFlowDefExec();
|
await saveFlowDefExec();
|
||||||
ElMessage.success('操作成功');
|
useI18nSaveSuccessMsg();
|
||||||
emit('val-change', state.form);
|
emit('val-change', state.form);
|
||||||
//重置表单域
|
//重置表单域
|
||||||
formRef.value.resetFields();
|
formRef.value.resetFields();
|
||||||
@@ -229,14 +212,14 @@ const btnOk = async () => {
|
|||||||
|
|
||||||
const checkTasks = () => {
|
const checkTasks = () => {
|
||||||
if (state.tasks?.length == 0) {
|
if (state.tasks?.length == 0) {
|
||||||
return { err: '请完善审批节点任务' };
|
return { err: t('flow.tasksNotEmpty') };
|
||||||
}
|
}
|
||||||
|
|
||||||
const tasks = [];
|
const tasks = [];
|
||||||
for (let i = 0; i < state.tasks.length; i++) {
|
for (let i = 0; i < state.tasks.length; i++) {
|
||||||
const task = { ...state.tasks[i] };
|
const task = { ...state.tasks[i] };
|
||||||
if (!task.name || !task.userId) {
|
if (!task.name || !task.userId) {
|
||||||
return { err: `请完善第${i + 1}个审批节点任务信息` };
|
return { err: t('flow.tasksNoComplete', { index: i + 1 }) };
|
||||||
}
|
}
|
||||||
// 转为字符串(方便后续万一需要调整啥的)
|
// 转为字符串(方便后续万一需要调整啥的)
|
||||||
task.userId = `${task.userId}`;
|
task.userId = `${task.userId}`;
|
||||||
|
|||||||
@@ -10,8 +10,10 @@
|
|||||||
:columns="columns"
|
:columns="columns"
|
||||||
>
|
>
|
||||||
<template #tableHeader>
|
<template #tableHeader>
|
||||||
<el-button v-auth="perms.save" type="primary" icon="plus" @click="editFlowDef(false)">添加</el-button>
|
<el-button v-auth="perms.save" type="primary" icon="plus" @click="editFlowDef(false)">{{ $t('common.create') }}</el-button>
|
||||||
<el-button v-auth="perms.del" :disabled="state.selectionData.length < 1" @click="deleteProcdef()" type="danger" icon="delete">删除</el-button>
|
<el-button v-auth="perms.del" :disabled="state.selectionData.length < 1" @click="deleteProcdef()" type="danger" icon="delete">
|
||||||
|
{{ $t('common.delete') }}
|
||||||
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #tasks="{ data }">
|
<template #tasks="{ data }">
|
||||||
@@ -23,7 +25,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #action="{ data }">
|
<template #action="{ data }">
|
||||||
<el-button link v-if="actionBtns[perms.save]" @click="editFlowDef(data)" type="primary">编辑</el-button>
|
<el-button link v-if="actionBtns[perms.save]" @click="editFlowDef(data)" type="primary">{{ $t('common.edit') }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
</page-table>
|
</page-table>
|
||||||
|
|
||||||
@@ -38,7 +40,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, toRefs, reactive, onMounted, Ref } from 'vue';
|
import { ref, toRefs, reactive, onMounted, Ref } from 'vue';
|
||||||
import { procdefApi } from './api';
|
import { procdefApi } from './api';
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
||||||
import PageTable from '@/components/pagetable/PageTable.vue';
|
import PageTable from '@/components/pagetable/PageTable.vue';
|
||||||
import { TableColumn } from '@/components/pagetable';
|
import { TableColumn } from '@/components/pagetable';
|
||||||
import { hasPerms } from '@/components/auth/auth';
|
import { hasPerms } from '@/components/auth/auth';
|
||||||
@@ -47,27 +48,31 @@ import ProcdefEdit from './ProcdefEdit.vue';
|
|||||||
import ProcdefTasks from './components/ProcdefTasks.vue';
|
import ProcdefTasks from './components/ProcdefTasks.vue';
|
||||||
import { ProcdefStatus } from './enums';
|
import { ProcdefStatus } from './enums';
|
||||||
import TagCodePath from '../ops/component/TagCodePath.vue';
|
import TagCodePath from '../ops/component/TagCodePath.vue';
|
||||||
|
import { useI18nCreateTitle, useI18nDeleteConfirm, useI18nDeleteSuccessMsg, useI18nEditTitle } from '@/hooks/useI18n';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const perms = {
|
const perms = {
|
||||||
save: 'flow:procdef:save',
|
save: 'flow:procdef:save',
|
||||||
del: 'flow:procdef:del',
|
del: 'flow:procdef:del',
|
||||||
};
|
};
|
||||||
|
|
||||||
const searchItems = [SearchItem.input('name', '名称'), SearchItem.input('defKey', 'key')];
|
const searchItems = [SearchItem.input('name', 'common.name'), SearchItem.input('defKey', 'key')];
|
||||||
const columns = [
|
const columns = [
|
||||||
TableColumn.new('name', '名称'),
|
TableColumn.new('name', 'common.name'),
|
||||||
TableColumn.new('defKey', 'key'),
|
TableColumn.new('defKey', 'Key'),
|
||||||
TableColumn.new('status', '状态').typeTag(ProcdefStatus),
|
TableColumn.new('status', 'common.status').typeTag(ProcdefStatus),
|
||||||
TableColumn.new('remark', '备注'),
|
TableColumn.new('remark', 'common.remark'),
|
||||||
TableColumn.new('tasks', '审批节点').isSlot().alignCenter().setMinWidth(60),
|
TableColumn.new('tasks', 'flow.approvalNode').isSlot().alignCenter().setMinWidth(60),
|
||||||
TableColumn.new('codePaths', '关联资源').isSlot().setMinWidth('250px'),
|
TableColumn.new('codePaths', 'tag.relateTag').isSlot().setMinWidth('250px'),
|
||||||
TableColumn.new('creator', '创建账号'),
|
TableColumn.new('creator', 'common.creator'),
|
||||||
TableColumn.new('createTime', '创建时间').isTime(),
|
TableColumn.new('createTime', 'common.createTime').isTime(),
|
||||||
];
|
];
|
||||||
|
|
||||||
// 该用户拥有的的操作列按钮权限
|
// 该用户拥有的的操作列按钮权限
|
||||||
const actionBtns: any = hasPerms([perms.save, perms.del]);
|
const actionBtns: any = hasPerms([perms.save, perms.del]);
|
||||||
const actionColumn = TableColumn.new('action', '操作').isSlot().fixedRight().setMinWidth(160).noShowOverflowTooltip().alignCenter();
|
const actionColumn = TableColumn.new('action', 'common.operation').isSlot().fixedRight().setMinWidth(160).noShowOverflowTooltip().alignCenter();
|
||||||
|
|
||||||
const pageTableRef: Ref<any> = ref(null);
|
const pageTableRef: Ref<any> = ref(null);
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
@@ -84,7 +89,7 @@ const state = reactive({
|
|||||||
pageSize: 0,
|
pageSize: 0,
|
||||||
},
|
},
|
||||||
flowDefEditor: {
|
flowDefEditor: {
|
||||||
title: '新建流程定义',
|
title: '',
|
||||||
visible: false,
|
visible: false,
|
||||||
data: null as any,
|
data: null as any,
|
||||||
},
|
},
|
||||||
@@ -109,17 +114,17 @@ const search = async () => {
|
|||||||
|
|
||||||
const showProcdefTasks = (procdef: any) => {
|
const showProcdefTasks = (procdef: any) => {
|
||||||
state.flowTasksDialog.tasks = procdef.tasks;
|
state.flowTasksDialog.tasks = procdef.tasks;
|
||||||
state.flowTasksDialog.title = procdef.name + '-审批节点';
|
state.flowTasksDialog.title = procdef.name + ' - ' + t('flow.approvalNode');
|
||||||
state.flowTasksDialog.visible = true;
|
state.flowTasksDialog.visible = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const editFlowDef = (data: any) => {
|
const editFlowDef = (data: any) => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
state.flowDefEditor.data = null;
|
state.flowDefEditor.data = null;
|
||||||
state.flowDefEditor.title = '新建流程定义';
|
state.flowDefEditor.title = useI18nCreateTitle('flow.procdef');
|
||||||
} else {
|
} else {
|
||||||
state.flowDefEditor.data = data;
|
state.flowDefEditor.data = data;
|
||||||
state.flowDefEditor.title = '编辑流程定义';
|
state.flowDefEditor.title = useI18nEditTitle('flow.procdef');
|
||||||
}
|
}
|
||||||
state.flowDefEditor.visible = true;
|
state.flowDefEditor.visible = true;
|
||||||
};
|
};
|
||||||
@@ -131,13 +136,9 @@ const valChange = () => {
|
|||||||
|
|
||||||
const deleteProcdef = async () => {
|
const deleteProcdef = async () => {
|
||||||
try {
|
try {
|
||||||
await ElMessageBox.confirm(`确定删除【${state.selectionData.map((x: any) => x.name).join(', ')}】的流程定义?`, '提示', {
|
await useI18nDeleteConfirm(state.selectionData.map((x: any) => x.name).join(', '));
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning',
|
|
||||||
});
|
|
||||||
await procdefApi.del.request({ id: state.selectionData.map((x: any) => x.id).join(',') });
|
await procdefApi.del.request({ id: state.selectionData.map((x: any) => x.id).join(',') });
|
||||||
ElMessage.success('删除成功');
|
useI18nDeleteSuccessMsg();
|
||||||
search();
|
search();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -8,29 +8,28 @@
|
|||||||
<div>
|
<div>
|
||||||
<el-divider content-position="left">流程信息</el-divider>
|
<el-divider content-position="left">流程信息</el-divider>
|
||||||
<el-descriptions :column="3" border>
|
<el-descriptions :column="3" border>
|
||||||
<el-descriptions-item label="流程名">{{ procinst.procdefName }}</el-descriptions-item>
|
<el-descriptions-item :span="1" label="流程名">{{ procinst.procdefName }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="业务">
|
<el-descriptions-item :span="1" label="业务">
|
||||||
<enum-tag :enums="FlowBizType" :value="procinst.bizType"></enum-tag>
|
<enum-tag :enums="FlowBizType" :value="procinst.bizType"></enum-tag>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="发起人">
|
<el-descriptions-item :span="1" label="发起人">
|
||||||
<AccountInfo :account-id="procinst.creatorId" :username="procinst.creator" />
|
<AccountInfo :account-id="procinst.creatorId" :username="procinst.creator" />
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
|
||||||
<el-descriptions-item label="流程状态">
|
<el-descriptions-item :span="1" label="流程状态">
|
||||||
<enum-tag :enums="ProcinstStatus" :value="procinst.status"></enum-tag>
|
<enum-tag :enums="ProcinstStatus" :value="procinst.status"></enum-tag>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="业务状态">
|
<el-descriptions-item :span="1" label="业务状态">
|
||||||
<enum-tag :enums="ProcinstBizStatus" :value="procinst.bizStatus"></enum-tag>
|
<enum-tag :enums="ProcinstBizStatus" :value="procinst.bizStatus"></enum-tag>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :span="1" label="发起时间">{{ formatDate(procinst.createTime) }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="发起时间">{{ formatDate(procinst.createTime) }}</el-descriptions-item>
|
|
||||||
|
|
||||||
<div v-if="procinst.duration">
|
<div v-if="procinst.duration">
|
||||||
<el-descriptions-item label="结束时间">{{ formatDate(procinst.endTime) }}</el-descriptions-item>
|
<el-descriptions-item :span="1.5" label="结束时间">{{ formatDate(procinst.endTime) }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="持续时间">{{ formatTime(procinst.duration) }}</el-descriptions-item>
|
<el-descriptions-item :span="1.5" label="持续时间">{{ formatTime(procinst.duration) }}</el-descriptions-item>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-descriptions-item label="备注">
|
<el-descriptions-item :span="3" label="备注">
|
||||||
{{ procinst.remark }}
|
{{ procinst.remark }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
|
|||||||
@@ -9,20 +9,20 @@
|
|||||||
:columns="columns"
|
:columns="columns"
|
||||||
>
|
>
|
||||||
<template #tableHeader>
|
<template #tableHeader>
|
||||||
<el-button type="primary" icon="plus" @click="startProcInst()">发起流程</el-button>
|
<el-button type="primary" icon="plus" @click="startProcInst()">{{ $t('flow.startProcess') }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #action="{ data }">
|
<template #action="{ data }">
|
||||||
<el-button link @click="showProcinst(data)" type="primary">查看</el-button>
|
<el-button link @click="showProcinst(data)" type="primary">{{ $t('common.detail') }}</el-button>
|
||||||
|
|
||||||
<el-popconfirm
|
<el-popconfirm
|
||||||
v-if="data.status == ProcinstStatus.Active.value || data.status == ProcinstStatus.Suspended.value"
|
v-if="data.status == ProcinstStatus.Active.value || data.status == ProcinstStatus.Suspended.value"
|
||||||
title="确认取消该流程?"
|
:title="$t('flow.cancelProcessConfirm')"
|
||||||
width="160"
|
width="160"
|
||||||
@confirm="procinstCancel(data)"
|
@confirm="procinstCancel(data)"
|
||||||
>
|
>
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button link type="warning">取消</el-button>
|
<el-button link type="warning">{{ $t('common.cancel') }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-popconfirm>
|
</el-popconfirm>
|
||||||
</template>
|
</template>
|
||||||
@@ -49,35 +49,37 @@ import { TableColumn } from '@/components/pagetable';
|
|||||||
import { SearchItem } from '@/components/SearchForm';
|
import { SearchItem } from '@/components/SearchForm';
|
||||||
import ProcinstDetail from './ProcinstDetail.vue';
|
import ProcinstDetail from './ProcinstDetail.vue';
|
||||||
import { FlowBizType, ProcinstBizStatus, ProcinstStatus } from './enums';
|
import { FlowBizType, ProcinstBizStatus, ProcinstStatus } from './enums';
|
||||||
import { ElMessage } from 'element-plus';
|
|
||||||
import { formatTime } from '@/common/utils/format';
|
import { formatTime } from '@/common/utils/format';
|
||||||
import ProcInstEdit from './ProcInstEdit.vue';
|
import ProcInstEdit from './ProcInstEdit.vue';
|
||||||
|
import { useI18nDetailTitle, useI18nOperateSuccessMsg } from '@/hooks/useI18n';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const searchItems = [
|
const searchItems = [
|
||||||
SearchItem.select('status', '流程状态').withEnum(ProcinstStatus),
|
SearchItem.select('status', 'common.status').withEnum(ProcinstStatus),
|
||||||
SearchItem.select('bizType', '业务类型').withEnum(FlowBizType),
|
SearchItem.select('bizType', 'flow.bizType').withEnum(FlowBizType),
|
||||||
SearchItem.input('bizKey', '业务key'),
|
SearchItem.input('bizKey', 'flow.bizKey'),
|
||||||
];
|
];
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
TableColumn.new('bizType', '业务').typeTag(FlowBizType),
|
TableColumn.new('bizType', 'flow.bizType').typeTag(FlowBizType),
|
||||||
TableColumn.new('remark', '备注'),
|
TableColumn.new('remark', 'common.remark'),
|
||||||
TableColumn.new('creator', '发起人'),
|
TableColumn.new('creator', 'flow.initiator'),
|
||||||
TableColumn.new('bizKey', '业务key'),
|
TableColumn.new('bizKey', 'flow.bizKey'),
|
||||||
TableColumn.new('procdefName', '流程名'),
|
TableColumn.new('procdefName', 'flow.procdefName'),
|
||||||
TableColumn.new('status', '流程状态').typeTag(ProcinstStatus),
|
TableColumn.new('status', 'common.status').setAddWidth(8).typeTag(ProcinstStatus),
|
||||||
TableColumn.new('bizStatus', '业务状态').typeTag(ProcinstBizStatus),
|
TableColumn.new('bizStatus', 'flow.bizStatus').typeTag(ProcinstBizStatus),
|
||||||
TableColumn.new('createTime', '发起时间').isTime(),
|
TableColumn.new('createTime', 'flow.startingTime').isTime(),
|
||||||
TableColumn.new('endTime', '结束时间').isTime(),
|
TableColumn.new('endTime', 'flow.endTime').isTime(),
|
||||||
TableColumn.new('duration', '持续时间').setFormatFunc((data: any, prop: string) => {
|
TableColumn.new('duration', 'flow.duration').setFormatFunc((data: any, prop: string) => {
|
||||||
const duration = data[prop];
|
const duration = data[prop];
|
||||||
if (!duration) {
|
if (!duration) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return formatTime(duration);
|
return formatTime(duration);
|
||||||
}),
|
}),
|
||||||
// TableColumn.new('bizHandleRes', '业务处理结果'),
|
TableColumn.new('action', 'common.operation').isSlot().fixedRight().setMinWidth(160).noShowOverflowTooltip().alignCenter(),
|
||||||
TableColumn.new('action', '操作').isSlot().fixedRight().setMinWidth(160).noShowOverflowTooltip().alignCenter(),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const pageTableRef: Ref<any> = ref(null);
|
const pageTableRef: Ref<any> = ref(null);
|
||||||
@@ -96,13 +98,13 @@ const state = reactive({
|
|||||||
pageSize: 0,
|
pageSize: 0,
|
||||||
},
|
},
|
||||||
procinstDetail: {
|
procinstDetail: {
|
||||||
title: '查看流程',
|
title: '',
|
||||||
visible: false,
|
visible: false,
|
||||||
procinstId: 0,
|
procinstId: 0,
|
||||||
instTaskId: 0,
|
instTaskId: 0,
|
||||||
},
|
},
|
||||||
procinstEdit: {
|
procinstEdit: {
|
||||||
title: '发起流程',
|
title: '',
|
||||||
visible: false,
|
visible: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -115,17 +117,18 @@ const search = async () => {
|
|||||||
|
|
||||||
const procinstCancel = async (data: any) => {
|
const procinstCancel = async (data: any) => {
|
||||||
await procinstApi.cancel.request({ id: data.id });
|
await procinstApi.cancel.request({ id: data.id });
|
||||||
ElMessage.success('操作成功');
|
useI18nOperateSuccessMsg();
|
||||||
search();
|
search();
|
||||||
};
|
};
|
||||||
|
|
||||||
const showProcinst = (data: any) => {
|
const showProcinst = (data: any) => {
|
||||||
state.procinstDetail.procinstId = data.id;
|
state.procinstDetail.procinstId = data.id;
|
||||||
state.procinstDetail.title = '流程查看';
|
state.procinstDetail.title = useI18nDetailTitle('flow.proc');
|
||||||
state.procinstDetail.visible = true;
|
state.procinstDetail.visible = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const startProcInst = () => {
|
const startProcInst = () => {
|
||||||
|
state.procinstEdit.title = t('flow.startProcess');
|
||||||
state.procinstEdit.visible = true;
|
state.procinstEdit.visible = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #action="{ data }">
|
<template #action="{ data }">
|
||||||
<el-button link @click="showProcinst(data, false)" type="primary">查看</el-button>
|
<el-button link @click="showProcinst(data, false)" type="primary">{{ $t('common.detail') }}</el-button>
|
||||||
<el-button v-if="data.status == ProcinstTaskStatus.Process.value" link @click="showProcinst(data, true)" type="primary">审核</el-button>
|
<el-button v-if="data.status == ProcinstTaskStatus.Process.value" link @click="showProcinst(data, true)" type="primary">
|
||||||
|
{{ $t('flow.audit') }}
|
||||||
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</page-table>
|
</page-table>
|
||||||
|
|
||||||
@@ -38,28 +40,35 @@ import { SearchItem } from '@/components/SearchForm';
|
|||||||
import ProcinstDetail from './ProcinstDetail.vue';
|
import ProcinstDetail from './ProcinstDetail.vue';
|
||||||
import { FlowBizType, ProcinstStatus, ProcinstTaskStatus } from './enums';
|
import { FlowBizType, ProcinstStatus, ProcinstTaskStatus } from './enums';
|
||||||
import { formatTime } from '@/common/utils/format';
|
import { formatTime } from '@/common/utils/format';
|
||||||
|
import { useI18nDetailTitle } from '@/hooks/useI18n';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
const searchItems = [SearchItem.select('status', '任务状态').withEnum(ProcinstTaskStatus), SearchItem.select('bizType', '业务类型').withEnum(FlowBizType)];
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const searchItems = [
|
||||||
|
SearchItem.select('status', 'common.status').withEnum(ProcinstTaskStatus),
|
||||||
|
SearchItem.select('bizType', 'flow.bizType').withEnum(FlowBizType),
|
||||||
|
];
|
||||||
const columns = [
|
const columns = [
|
||||||
TableColumn.new('procinst.bizType', '业务').typeTag(FlowBizType),
|
TableColumn.new('procinst.bizType', 'flow.bizType').typeTag(FlowBizType),
|
||||||
TableColumn.new('procinst.remark', '备注'),
|
TableColumn.new('procinst.remark', 'common.remark'),
|
||||||
TableColumn.new('procinst.creator', '发起人'),
|
TableColumn.new('procinst.creator', 'flow.initiator'),
|
||||||
TableColumn.new('procinst.status', '流程状态').typeTag(ProcinstStatus),
|
TableColumn.new('procinst.status', 'flow.procinstStatus').typeTag(ProcinstStatus),
|
||||||
TableColumn.new('status', '任务状态').typeTag(ProcinstTaskStatus),
|
TableColumn.new('status', 'flow.taskStatus').typeTag(ProcinstTaskStatus),
|
||||||
TableColumn.new('procinst.bizKey', '业务key'),
|
TableColumn.new('procinst.bizKey', 'flow.bizKey'),
|
||||||
TableColumn.new('procinst.procdefName', '流程名'),
|
TableColumn.new('procinst.procdefName', 'flow.procdefName'),
|
||||||
TableColumn.new('taskName', '当前节点'),
|
TableColumn.new('taskName', 'flow.taskName'),
|
||||||
TableColumn.new('procinst.createTime', '发起时间').isTime(),
|
TableColumn.new('procinst.createTime', 'flow.startingTime').isTime(),
|
||||||
TableColumn.new('createTime', '开始时间').isTime(),
|
TableColumn.new('createTime', 'flow.taskBeginTime').isTime(),
|
||||||
TableColumn.new('endTime', '结束时间').isTime(),
|
TableColumn.new('endTime', 'flow.endTime').isTime(),
|
||||||
TableColumn.new('duration', '持续时间').setFormatFunc((data: any, prop: string) => {
|
TableColumn.new('duration', 'flow.duration').setFormatFunc((data: any, prop: string) => {
|
||||||
const duration = data[prop];
|
const duration = data[prop];
|
||||||
if (!duration) {
|
if (!duration) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return formatTime(duration);
|
return formatTime(duration);
|
||||||
}),
|
}),
|
||||||
TableColumn.new('action', '操作').isSlot().fixedRight().setMinWidth(160).noShowOverflowTooltip().alignCenter(),
|
TableColumn.new('action', 'common.operation').isSlot().fixedRight().setMinWidth(160).noShowOverflowTooltip().alignCenter(),
|
||||||
];
|
];
|
||||||
|
|
||||||
const pageTableRef: Ref<any> = ref(null);
|
const pageTableRef: Ref<any> = ref(null);
|
||||||
@@ -78,7 +87,7 @@ const state = reactive({
|
|||||||
pageSize: 0,
|
pageSize: 0,
|
||||||
},
|
},
|
||||||
procinstDetail: {
|
procinstDetail: {
|
||||||
title: '查看流程',
|
title: '',
|
||||||
visible: false,
|
visible: false,
|
||||||
procinstId: 0,
|
procinstId: 0,
|
||||||
instTaskId: 0,
|
instTaskId: 0,
|
||||||
@@ -95,10 +104,10 @@ const showProcinst = (data: any, audit: boolean) => {
|
|||||||
state.procinstDetail.procinstId = data.procinstId;
|
state.procinstDetail.procinstId = data.procinstId;
|
||||||
if (!audit) {
|
if (!audit) {
|
||||||
state.procinstDetail.instTaskId = 0;
|
state.procinstDetail.instTaskId = 0;
|
||||||
state.procinstDetail.title = '流程查看';
|
state.procinstDetail.title = useI18nDetailTitle('flow.proc');
|
||||||
} else {
|
} else {
|
||||||
state.procinstDetail.instTaskId = data.id;
|
state.procinstDetail.instTaskId = data.id;
|
||||||
state.procinstDetail.title = '流程审批';
|
state.procinstDetail.title = t('flow.flowAudit');
|
||||||
}
|
}
|
||||||
state.procinstDetail.visible = true;
|
state.procinstDetail.visible = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
import { EnumValue } from '@/common/Enum';
|
import { EnumValue } from '@/common/Enum';
|
||||||
|
|
||||||
export const ProcdefStatus = {
|
export const ProcdefStatus = {
|
||||||
Enable: EnumValue.of(1, '启用').setTagType('success'),
|
Enable: EnumValue.of(1, 'flow.enable').setTagType('success'),
|
||||||
Disable: EnumValue.of(-1, '禁用').setTagType('warning'),
|
Disable: EnumValue.of(-1, 'flow.disable').setTagType('warning'),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ProcinstStatus = {
|
export const ProcinstStatus = {
|
||||||
Active: EnumValue.of(1, '执行中').setTagType('primary'),
|
Active: EnumValue.of(1, 'flow.active').setTagType('primary'),
|
||||||
Completed: EnumValue.of(2, '完成').setTagType('success'),
|
Completed: EnumValue.of(2, 'flow.completed').setTagType('success'),
|
||||||
Suspended: EnumValue.of(-1, '挂起').setTagType('warning'),
|
Suspended: EnumValue.of(-1, 'flow.suspended').setTagType('warning'),
|
||||||
Terminated: EnumValue.of(-2, '终止').setTagType('danger'),
|
Terminated: EnumValue.of(-2, 'flow.terminated').setTagType('danger'),
|
||||||
Cancelled: EnumValue.of(-3, '取消').setTagType('warning'),
|
Cancelled: EnumValue.of(-3, 'flow.cancelled').setTagType('warning'),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ProcinstBizStatus = {
|
export const ProcinstBizStatus = {
|
||||||
Wait: EnumValue.of(1, '待处理').setTagType('primary'),
|
Wait: EnumValue.of(1, 'flow.waitHandle').setTagType('primary'),
|
||||||
Success: EnumValue.of(2, '处理成功').setTagType('success'),
|
Success: EnumValue.of(2, 'flow.handleSuccess').setTagType('success'),
|
||||||
Fail: EnumValue.of(-2, '处理失败').setTagType('danger'),
|
Fail: EnumValue.of(-2, 'flow.handleFail').setTagType('danger'),
|
||||||
No: EnumValue.of(-1, '不处理').setTagType('warning'),
|
No: EnumValue.of(-1, 'flow.noHandle').setTagType('warning'),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ProcinstTaskStatus = {
|
export const ProcinstTaskStatus = {
|
||||||
Process: EnumValue.of(1, '待处理').setTagType('primary'),
|
Process: EnumValue.of(1, 'flow.waitProcess').setTagType('primary'),
|
||||||
Pass: EnumValue.of(2, '通过').setTagType('success'),
|
Pass: EnumValue.of(2, 'flow.pass').setTagType('success'),
|
||||||
Reject: EnumValue.of(-1, '拒绝').setTagType('danger'),
|
Reject: EnumValue.of(-1, 'flow.reject').setTagType('danger'),
|
||||||
Back: EnumValue.of(-2, '驳回').setTagType('warning'),
|
Back: EnumValue.of(-2, 'flow.back').setTagType('warning'),
|
||||||
Canceled: EnumValue.of(-3, '取消').setTagType('warning'),
|
Canceled: EnumValue.of(-3, 'flow.canceled').setTagType('warning'),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FlowBizType = {
|
export const FlowBizType = {
|
||||||
DbSqlExec: EnumValue.of('db_sql_exec_flow', 'DBMS-执行SQL').setTagType('warning'),
|
DbSqlExec: EnumValue.of('db_sql_exec_flow', 'flow.dbSqlExec').setTagType('warning'),
|
||||||
RedisRunWriteCmd: EnumValue.of('redis_run_cmd_flow', 'Redis-执行命令').setTagType('danger'),
|
RedisRunWriteCmd: EnumValue.of('redis_run_cmd_flow', 'flow.redisRunCmd').setTagType('danger'),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-descriptions :column="3" border>
|
<el-descriptions :column="3" border>
|
||||||
<el-descriptions-item :span="3" label="标签"><TagCodePath :path="db.codePaths" /></el-descriptions-item>
|
<el-descriptions-item :span="3" :label="$t('common.tag')"><TagCodePath :path="db.codePaths" /></el-descriptions-item>
|
||||||
|
|
||||||
<el-descriptions-item :span="1" label="名称">{{ db?.name }}</el-descriptions-item>
|
<el-descriptions-item :span="1" :label="$t('common.name')">{{ db?.name }}</el-descriptions-item>
|
||||||
<el-descriptions-item :span="1" label="主机">
|
<el-descriptions-item :span="1" label="Host">
|
||||||
<SvgIcon :name="getDbDialect(db?.type).getInfo().icon" :size="20" />
|
<SvgIcon :name="getDbDialect(db?.type).getInfo().icon" :size="20" />
|
||||||
{{ `${db?.host}:${db?.port}` }}
|
{{ `${db?.host}:${db?.port}` }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item :span="1" label="数据库">{{ dbName }}</el-descriptions-item>
|
<el-descriptions-item :span="1" :label="$t('tag.db')">{{ dbName }}</el-descriptions-item>
|
||||||
|
|
||||||
<el-descriptions-item label="执行SQL">
|
<el-descriptions-item :label="$t('flow.runSql')">
|
||||||
<monaco-editor height="300px" language="sql" v-model="sql" :options="{ readOnly: true }" />
|
<monaco-editor height="300px" language="sql" v-model="sql" :options="{ readOnly: true }" />
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
|
|
||||||
<div v-if="runRes && runRes.length > 0">
|
<div v-if="runRes && runRes.length > 0">
|
||||||
<el-divider content-position="left">处理结果</el-divider>
|
<el-divider content-position="left">{{ $t('flow.handleResult') }}</el-divider>
|
||||||
<el-table :data="runRes" :max-height="400">
|
<el-table :data="runRes" :max-height="400">
|
||||||
<el-table-column prop="sql" label="SQL" show-overflow-tooltip />
|
<el-table-column prop="sql" label="SQL" show-overflow-tooltip />
|
||||||
|
|
||||||
<el-table-column prop="res" label="执行结果" :min-width="30" show-overflow-tooltip>
|
<el-table-column prop="res" :label="$t('flow.runResult')" :min-width="30" show-overflow-tooltip>
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-popover placement="top" :width="400" trigger="hover">
|
<el-popover placement="top" :width="400" trigger="hover">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form :model="bizForm" ref="formRef" :rules="rules" label-width="auto">
|
<el-form :model="bizForm" ref="formRef" :rules="rules" label-width="auto">
|
||||||
<el-form-item prop="dbId" label="数据库" required>
|
<el-form-item prop="dbId" :label="$t('tag.db')" required>
|
||||||
<db-select-tree
|
<db-select-tree
|
||||||
placeholder="请选择数据库"
|
:placeholder="$t('flow.selectDbPlaceholder')"
|
||||||
v-model:db-id="bizForm.dbId"
|
v-model:db-id="bizForm.dbId"
|
||||||
v-model:db-name="bizForm.dbName"
|
v-model:db-name="bizForm.dbName"
|
||||||
v-model:db-type="dbType"
|
v-model:db-type="dbType"
|
||||||
@@ -24,19 +24,23 @@ import DbSelectTree from '@/views/ops/db/component/DbSelectTree.vue';
|
|||||||
import MonacoEditor from '@/components/monaco/MonacoEditor.vue';
|
import MonacoEditor from '@/components/monaco/MonacoEditor.vue';
|
||||||
import { registerDbCompletionItemProvider } from '@/views/ops/db/db';
|
import { registerDbCompletionItemProvider } from '@/views/ops/db/db';
|
||||||
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useI18nPleaseInput } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const rules = {
|
const rules = {
|
||||||
dbId: [
|
dbId: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请选择数据库',
|
message: t('flow.selectDbPlaceholder'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
sql: [
|
sql: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入执行SQL',
|
message: useI18nPleaseInput('flow.runSql'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-descriptions :column="3" border>
|
<el-descriptions :column="3" border>
|
||||||
<el-descriptions-item :span="3" label="标签"><TagCodePath :path="redis.codePaths" /></el-descriptions-item>
|
<el-descriptions-item :span="3" :label="$t('common.tag')"><TagCodePath :path="redis.codePaths" /></el-descriptions-item>
|
||||||
|
|
||||||
<el-descriptions-item :span="2" label="编号">{{ redis?.code }}</el-descriptions-item>
|
<el-descriptions-item :span="2" :label="$t('common.code')">{{ redis?.code }}</el-descriptions-item>
|
||||||
<el-descriptions-item :span="1" label="名称">{{ redis?.name }}</el-descriptions-item>
|
<el-descriptions-item :span="1" :label="$t('common.name')">{{ redis?.name }}</el-descriptions-item>
|
||||||
|
|
||||||
<el-descriptions-item :span="1" label="主机">{{ `${redis?.host}` }}</el-descriptions-item>
|
<el-descriptions-item :span="1" label="Host">{{ `${redis?.host}` }}</el-descriptions-item>
|
||||||
<el-descriptions-item :span="1" label="库">{{ state.db }}</el-descriptions-item>
|
<el-descriptions-item :span="1" label="DB">{{ state.db }}</el-descriptions-item>
|
||||||
<el-descriptions-item :span="1" label="mode">
|
<el-descriptions-item :span="1" label="mode">
|
||||||
{{ redis.mode }}
|
{{ redis.mode }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
|
||||||
<el-descriptions-item :span="3" label="执行Cmd">
|
<el-descriptions-item :span="3" :label="$t('flow.runCmd')">
|
||||||
<el-input type="textarea" disabled v-model="cmd" rows="5" />
|
<el-input type="textarea" disabled v-model="cmd" rows="5" />
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
|
|
||||||
<div v-if="runRes && runRes.length > 0">
|
<div v-if="runRes && runRes.length > 0">
|
||||||
<el-divider content-position="left">处理结果</el-divider>
|
<el-divider content-position="left">{{ $t('flow.handleResult') }}</el-divider>
|
||||||
<el-table :data="runRes" :max-height="400">
|
<el-table :data="runRes" :max-height="400">
|
||||||
<el-table-column prop="cmd" label="命令" show-overflow-tooltip />
|
<el-table-column prop="cmd" label="Cmd" show-overflow-tooltip />
|
||||||
<el-table-column prop="res" label="执行结果" :min-width="50" show-overflow-tooltip> </el-table-column>
|
<el-table-column prop="res" :label="$t('flow.runResult')" :min-width="50" show-overflow-tooltip> </el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form :model="bizForm" ref="formRef" :rules="rules" label-width="auto">
|
<el-form :model="bizForm" ref="formRef" :rules="rules" label-width="auto">
|
||||||
<el-form-item prop="id" label="库" required>
|
<el-form-item prop="id" label="DB" required>
|
||||||
<TagTreeResourceSelect
|
<TagTreeResourceSelect
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
v-model="selectRedis"
|
v-model="selectRedis"
|
||||||
@change="changeRedis"
|
@change="changeRedis"
|
||||||
:resource-type="TagResourceTypeEnum.Redis.value"
|
:resource-type="TagResourceTypeEnum.Redis.value"
|
||||||
:tag-path-node-type="NodeTypeTagPath"
|
:tag-path-node-type="NodeTypeTagPath"
|
||||||
placeholder="请选择Redis实例与库"
|
:placeholder="$t('flow.selectRedisPlaceholder')"
|
||||||
>
|
>
|
||||||
</TagTreeResourceSelect>
|
</TagTreeResourceSelect>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item prop="cmd" label="CMD" required>
|
<el-form-item prop="cmd" label="CMD" required>
|
||||||
<el-input type="textarea" v-model="bizForm.cmd" placeholder="如: SET 'key' 'value'; 多条命令;分割" :rows="5" />
|
<el-input type="textarea" v-model="bizForm.cmd" :placeholder="$t('flow.cmdPlaceholder')" :rows="5" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
@@ -25,19 +25,23 @@ import TagTreeResourceSelect from '@/views/ops/component/TagTreeResourceSelect.v
|
|||||||
import { NodeType, TagTreeNode } from '@/views/ops/component/tag';
|
import { NodeType, TagTreeNode } from '@/views/ops/component/tag';
|
||||||
import { redisApi } from '@/views/ops/redis/api';
|
import { redisApi } from '@/views/ops/redis/api';
|
||||||
import { sleep } from '@/common/utils/loading';
|
import { sleep } from '@/common/utils/loading';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useI18nPleaseInput } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const rules = {
|
const rules = {
|
||||||
id: [
|
id: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请选择Redis实例',
|
message: t('flow.selectRedisPlaceholder'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
cmd: [
|
cmd: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入执行CMD',
|
message: useI18nPleaseInput('flow.runCmd'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<el-row :gutter="15">
|
<el-row :gutter="15">
|
||||||
<!-- 个人信息 -->
|
<!-- 个人信息 -->
|
||||||
<el-col :xs="24" :sm="16">
|
<el-col :xs="24" :sm="16">
|
||||||
<el-card shadow="hover" header="个人信息">
|
<el-card shadow="hover" :header="$t('home.personalInfo')">
|
||||||
<div class="personal-user">
|
<div class="personal-user">
|
||||||
<div class="personal-user-left">
|
<div class="personal-user-left">
|
||||||
<el-upload
|
<el-upload
|
||||||
@@ -20,17 +20,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="personal-user-right">
|
<div class="personal-user-right">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="24" class="personal-title mb18"
|
<el-col :span="24" class="personal-title mb18">
|
||||||
>{{ currentTime }},{{ userInfo.name }},生活变的再糟糕,也不妨碍我变得更好!
|
{{ $t('home.welcomeMsg', { name: userInfo.name }) }}
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :xs="24" :sm="12" class="personal-item mb6">
|
<el-col :xs="24" :sm="12" class="personal-item mb6">
|
||||||
<div class="personal-item-label">用户名:</div>
|
<div class="personal-item-label">{{ $t('common.username') }}:</div>
|
||||||
<div class="personal-item-value">{{ userInfo.username }}</div>
|
<div class="personal-item-value">{{ userInfo.username }}</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="24" :sm="12" class="personal-item mb6">
|
<el-col :xs="24" :sm="12" class="personal-item mb6">
|
||||||
<div class="personal-item-label">角色:</div>
|
<div class="personal-item-label">{{ $t('common.role') }}:</div>
|
||||||
<div class="personal-item-value">{{ roleInfo }}</div>
|
<div class="personal-item-value">{{ roleInfo }}</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -38,11 +38,11 @@
|
|||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :xs="24" :sm="12" class="personal-item mb6">
|
<el-col :xs="24" :sm="12" class="personal-item mb6">
|
||||||
<div class="personal-item-label">上次登录IP:</div>
|
<div class="personal-item-label">{{ $t('home.lastLoginIp') }}:</div>
|
||||||
<div class="personal-item-value">{{ userInfo.lastLoginIp }}</div>
|
<div class="personal-item-value">{{ userInfo.lastLoginIp }}</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="24" :sm="12" class="personal-item mb6">
|
<el-col :xs="24" :sm="12" class="personal-item mb6">
|
||||||
<div class="personal-item-label">上次登录时间:</div>
|
<div class="personal-item-label">{{ $t('home.lastLoginTime') }}:</div>
|
||||||
<div class="personal-item-value">{{ formatDate(userInfo.lastLoginTime) }}</div>
|
<div class="personal-item-value">{{ formatDate(userInfo.lastLoginTime) }}</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -57,13 +57,13 @@
|
|||||||
<el-col :xs="24" :sm="8" class="pl15 personal-info">
|
<el-col :xs="24" :sm="8" class="pl15 personal-info">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<template #header>
|
<template #header>
|
||||||
<span>消息通知</span>
|
<span>{{ $t('home.msgNotify') }}</span>
|
||||||
<span @click="showMsgs" class="personal-info-more">更多</span>
|
<span @click="showMsgs" class="personal-info-more">{{ $t('common.more') }}</span>
|
||||||
</template>
|
</template>
|
||||||
<div class="personal-info-box">
|
<div class="personal-info-box">
|
||||||
<ul class="personal-info-ul">
|
<ul class="personal-info-ul">
|
||||||
<li v-for="(v, k) in state.msgs as any" :key="k" class="personal-info-li">
|
<li v-for="(v, k) in state.msgs as any" :key="k" class="personal-info-li">
|
||||||
<a class="personal-info-li-title">{{ `[${getMsgTypeDesc(v.type)}] ${v.msg}` }}</a>
|
<a class="personal-info-li-title">{{ `[${$t(EnumValue.getLabelByValue(MsgTypeEnum, v.type))}] ${v.msg}` }}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -89,7 +89,13 @@
|
|||||||
</template>
|
</template>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :sm="24">
|
<el-col :sm="24">
|
||||||
<el-table :data="state.machine.opLogs" :height="state.resourceOpTableHeight" stripe size="small" empty-text="暂无操作记录">
|
<el-table
|
||||||
|
:data="state.machine.opLogs"
|
||||||
|
:height="state.resourceOpTableHeight"
|
||||||
|
stripe
|
||||||
|
size="small"
|
||||||
|
:empty-text="$t('home.noOpRecord')"
|
||||||
|
>
|
||||||
<el-table-column prop="createTime" show-overflow-tooltip width="135">
|
<el-table-column prop="createTime" show-overflow-tooltip width="135">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ formatDate(scope.row.createTime) }}
|
{{ formatDate(scope.row.createTime) }}
|
||||||
@@ -123,7 +129,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :sm="24">
|
<el-col :sm="24">
|
||||||
<el-table :data="state.db.opLogs" :height="state.resourceOpTableHeight" stripe size="small" empty-text="暂无操作记录">
|
<el-table :data="state.db.opLogs" :height="state.resourceOpTableHeight" stripe size="small" :empty-text="$t('home.noOpRecord')">
|
||||||
<el-table-column prop="createTime" show-overflow-tooltip min-width="135">
|
<el-table-column prop="createTime" show-overflow-tooltip min-width="135">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ formatDate(scope.row.createTime) }}
|
{{ formatDate(scope.row.createTime) }}
|
||||||
@@ -164,7 +170,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :sm="24">
|
<el-col :sm="24">
|
||||||
<el-table :data="state.redis.opLogs" :height="state.resourceOpTableHeight" stripe size="small" empty-text="暂无操作记录">
|
<el-table :data="state.redis.opLogs" :height="state.resourceOpTableHeight" stripe size="small" :empty-text="$t('home.noOpRecord')">
|
||||||
<el-table-column prop="createTime" show-overflow-tooltip min-width="135">
|
<el-table-column prop="createTime" show-overflow-tooltip min-width="135">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ formatDate(scope.row.createTime) }}
|
{{ formatDate(scope.row.createTime) }}
|
||||||
@@ -203,7 +209,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :sm="24">
|
<el-col :sm="24">
|
||||||
<el-table :data="state.mongo.opLogs" :height="state.resourceOpTableHeight" stripe size="small" empty-text="暂无操作记录">
|
<el-table :data="state.mongo.opLogs" :height="state.resourceOpTableHeight" stripe size="small" :empty-text="$t('home.noOpRecord')">
|
||||||
<el-table-column prop="createTime" show-overflow-tooltip min-width="135">
|
<el-table-column prop="createTime" show-overflow-tooltip min-width="135">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ formatDate(scope.row.createTime) }}
|
{{ formatDate(scope.row.createTime) }}
|
||||||
@@ -226,15 +232,15 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-dialog width="900px" title="消息" v-model="msgDialog.visible">
|
<el-dialog width="900px" :title="$t('common.msg')" v-model="msgDialog.visible">
|
||||||
<el-table border :data="msgDialog.msgs.list" size="small">
|
<el-table border :data="msgDialog.msgs.list" size="small">
|
||||||
<el-table-column property="type" label="类型" width="60">
|
<el-table-column property="type" :label="$t('common.type')" width="60">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ getMsgTypeDesc(scope.row.type) }}
|
{{ $t(EnumValue.getLabelByValue(MsgTypeEnum, scope.row.type)) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column property="msg" label="消息"></el-table-column>
|
<el-table-column property="msg" :label="$t('common.msg')"></el-table-column>
|
||||||
<el-table-column property="createTime" label="时间" width="150">
|
<el-table-column property="createTime" :label="$t('common.time')" width="150">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ formatDate(scope.row.createTime) }}
|
{{ formatDate(scope.row.createTime) }}
|
||||||
</template>
|
</template>
|
||||||
@@ -274,6 +280,8 @@ import { getAllTagInfoByCodePaths } from '../ops/component/tag';
|
|||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { getFileUrl, getUploadFileUrl } from '@/common/request';
|
import { getFileUrl, getUploadFileUrl } from '@/common/request';
|
||||||
import { saveUser } from '@/common/utils/storage';
|
import { saveUser } from '@/common/utils/storage';
|
||||||
|
import EnumValue from '../../common/Enum';
|
||||||
|
import { MsgTypeEnum } from './enums';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { userInfo } = storeToRefs(useUserInfo());
|
const { userInfo } = storeToRefs(useUserInfo());
|
||||||
@@ -352,15 +360,6 @@ const searchMsg = async () => {
|
|||||||
state.msgDialog.msgs = await getMsgs();
|
state.msgDialog.msgs = await getMsgs();
|
||||||
};
|
};
|
||||||
|
|
||||||
const getMsgTypeDesc = (type: number) => {
|
|
||||||
if (type == 1) {
|
|
||||||
return '登录';
|
|
||||||
}
|
|
||||||
if (type == 2) {
|
|
||||||
return '通知';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getAccountInfo = async () => {
|
const getAccountInfo = async () => {
|
||||||
state.accountInfo = await personApi.accountInfo.request();
|
state.accountInfo = await personApi.accountInfo.request();
|
||||||
};
|
};
|
||||||
|
|||||||
6
frontend/src/views/home/enums.ts
Normal file
6
frontend/src/views/home/enums.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { EnumValue } from '@/common/Enum';
|
||||||
|
|
||||||
|
export const MsgTypeEnum = {
|
||||||
|
Login: EnumValue.of(1, 'home.msgTypeLogin'),
|
||||||
|
Notify: EnumValue.of(2, 'home.msgTypeNotify'),
|
||||||
|
};
|
||||||
@@ -2,12 +2,20 @@
|
|||||||
<div>
|
<div>
|
||||||
<el-form ref="loginFormRef" :model="loginForm" :rules="rules" class="login-content-form" size="large">
|
<el-form ref="loginFormRef" :model="loginForm" :rules="rules" class="login-content-form" size="large">
|
||||||
<el-form-item prop="username">
|
<el-form-item prop="username">
|
||||||
<el-input type="text" placeholder="请输入用户名" prefix-icon="user" v-model="loginForm.username" clearable autocomplete="off"> </el-input>
|
<el-input
|
||||||
|
type="text"
|
||||||
|
:placeholder="$t('login.inputUsernamePlaceholder')"
|
||||||
|
prefix-icon="user"
|
||||||
|
v-model="loginForm.username"
|
||||||
|
clearable
|
||||||
|
autocomplete="off"
|
||||||
|
>
|
||||||
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="password">
|
<el-form-item prop="password">
|
||||||
<el-input
|
<el-input
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="请输入密码"
|
:placeholder="$t('login.inputPasswordPlaceholder')"
|
||||||
prefix-icon="lock"
|
prefix-icon="lock"
|
||||||
v-model="loginForm.password"
|
v-model="loginForm.password"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
@@ -22,7 +30,7 @@
|
|||||||
<el-input
|
<el-input
|
||||||
type="text"
|
type="text"
|
||||||
maxlength="6"
|
maxlength="6"
|
||||||
placeholder="请输入验证码"
|
:placeholder="$t('login.inputCaptchaPlaceholder')"
|
||||||
prefix-icon="position"
|
prefix-icon="position"
|
||||||
v-model="loginForm.captcha"
|
v-model="loginForm.captcha"
|
||||||
clearable
|
clearable
|
||||||
@@ -38,30 +46,35 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="ldapEnabled" prop="ldapLogin">
|
<el-form-item v-if="ldapEnabled" prop="ldapLogin">
|
||||||
<el-checkbox v-model="loginForm.ldapLogin" label="LDAP 登录" size="small" />
|
<el-checkbox v-model="loginForm.ldapLogin" :label="$t('login.ldapLogin')" size="small" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<span v-if="showLoginFailTips" style="color: #f56c6c; font-size: 12px">
|
<span v-if="showLoginFailTips" style="color: #f56c6c; font-size: 12px">
|
||||||
提示:登录失败超过{{ accountLoginSecurity.loginFailCount }}次后将被限制{{ accountLoginSecurity.loginFailMin }}分钟内不可再次登录
|
{{
|
||||||
|
$t('login.loginFailTip', {
|
||||||
|
loginFailCount: accountLoginSecurity.loginFailCount,
|
||||||
|
loginFailMin: accountLoginSecurity.loginFailMin,
|
||||||
|
})
|
||||||
|
}}
|
||||||
</span>
|
</span>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" class="login-content-submit" round @click="login" :loading="loading.signIn">
|
<el-button type="primary" class="login-content-submit" round @click="login" :loading="loading.signIn">
|
||||||
<span>登 录</span>
|
<span>{{ $t('login.login') }}</span>
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<el-dialog title="修改密码" v-model="changePwdDialog.visible" :close-on-click-modal="false" width="450px" :destroy-on-close="true">
|
<el-dialog :title="$t('login.changePassword')" v-model="changePwdDialog.visible" :close-on-click-modal="false" width="450px" :destroy-on-close="true">
|
||||||
<el-form :model="changePwdDialog.form" :rules="changePwdDialog.rules" ref="changePwdFormRef" label-width="auto">
|
<el-form :model="changePwdDialog.form" :rules="changePwdDialog.rules" ref="changePwdFormRef" label-width="auto">
|
||||||
<el-form-item prop="username" label="用户名" required>
|
<el-form-item prop="username" :label="$t('common.username')" required>
|
||||||
<el-input v-model.trim="changePwdDialog.form.username" disabled></el-input>
|
<el-input v-model.trim="changePwdDialog.form.username" disabled></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="oldPassword" label="旧密码" required>
|
<el-form-item prop="oldPassword" :label="$t('login.oldPassword')" required>
|
||||||
<el-input v-model.trim="changePwdDialog.form.oldPassword" autocomplete="new-password" type="password"></el-input>
|
<el-input v-model.trim="changePwdDialog.form.oldPassword" autocomplete="new-password" type="password"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="newPassword" label="新密码" required>
|
<el-form-item prop="newPassword" :label="$t('login.newPassword')" required>
|
||||||
<el-input
|
<el-input
|
||||||
v-model.trim="changePwdDialog.form.newPassword"
|
v-model.trim="changePwdDialog.form.newPassword"
|
||||||
placeholder="须为8位以上且包含字⺟⼤⼩写+数字+特殊符号"
|
:placeholder="$t('login.passwordRuleTip')"
|
||||||
type="password"
|
type="password"
|
||||||
autocomplete="new-password"
|
autocomplete="new-password"
|
||||||
></el-input>
|
></el-input>
|
||||||
@@ -70,14 +83,16 @@
|
|||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="cancelChangePwd">取 消</el-button>
|
<el-button @click="cancelChangePwd">{{ $t('common.cancel') }}</el-button>
|
||||||
<el-button @click="changePwd" type="primary" :loading="loading.changePwd">确 定</el-button>
|
<el-button @click="changePwd" type="primary" :loading="loading.changePwd">
|
||||||
|
{{ $t('common.confirm') }}
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
title="OTP校验"
|
:title="$t('login.otpValidation')"
|
||||||
v-model="otpDialog.visible"
|
v-model="otpDialog.visible"
|
||||||
@close="loading.signIn = false"
|
@close="loading.signIn = false"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
@@ -85,7 +100,7 @@
|
|||||||
:destroy-on-close="true"
|
:destroy-on-close="true"
|
||||||
>
|
>
|
||||||
<el-form ref="otpFormRef" :model="otpDialog.form" :rules="otpDialog.rules" @submit.native.prevent label-width="auto">
|
<el-form ref="otpFormRef" :model="otpDialog.form" :rules="otpDialog.rules" @submit.native.prevent label-width="auto">
|
||||||
<el-form-item v-if="otpDialog.otpUrl" label="二维码">
|
<el-form-item v-if="otpDialog.otpUrl" :label="$t('login.qrCode')">
|
||||||
<qrcode-vue :value="otpDialog.otpUrl" :size="200" level="H" />
|
<qrcode-vue :value="otpDialog.otpUrl" :size="200" level="H" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
@@ -96,31 +111,35 @@
|
|||||||
v-model.trim="otpDialog.form.code"
|
v-model.trim="otpDialog.form.code"
|
||||||
clearable
|
clearable
|
||||||
@keyup.enter="otpVerify"
|
@keyup.enter="otpVerify"
|
||||||
placeholder="请输入令牌APP中显示的授权码"
|
:placeholder="$t('login.enterOtpCodeTip')"
|
||||||
></el-input>
|
></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="otpVerify" type="primary" :loading="loading.otpConfirm">确 定</el-button>
|
<el-button @click="otpVerify" type="primary" :loading="loading.otpConfirm">
|
||||||
|
{{ $t('common.confirm') }}
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog title="修改基本信息" v-model="baseInfoDialog.visible" :close-on-click-modal="false" width="450px" :destroy-on-close="true">
|
<el-dialog :title="$t('updateBasicInfo')" v-model="baseInfoDialog.visible" :close-on-click-modal="false" width="450px" :destroy-on-close="true">
|
||||||
<el-form :model="baseInfoDialog.form" :rules="baseInfoDialog.rules" ref="baseInfoFormRef" label-width="auto">
|
<el-form :model="baseInfoDialog.form" :rules="baseInfoDialog.rules" ref="baseInfoFormRef" label-width="auto">
|
||||||
<el-form-item prop="username" label="用户名" required>
|
<el-form-item prop="username" :label="$t('common.username')" required>
|
||||||
<el-input v-model.trim="baseInfoDialog.form.username"></el-input>
|
<el-input v-model.trim="baseInfoDialog.form.username"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="name" label="姓名" required>
|
<el-form-item prop="name" :label="$t('login.name')" required>
|
||||||
<el-input v-model.trim="baseInfoDialog.form.name"></el-input>
|
<el-input v-model.trim="baseInfoDialog.form.name"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="updateUserInfo()" type="primary" :loading="loading.updateUserConfirm">确 定</el-button>
|
<el-button @click="updateUserInfo()" type="primary" :loading="loading.updateUserConfirm">
|
||||||
|
{{ $t('common.confirm') }}
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@@ -145,11 +164,14 @@ import { AccountUsernamePattern } from '@/common/pattern';
|
|||||||
import { getToken } from '@/common/utils/storage';
|
import { getToken } from '@/common/utils/storage';
|
||||||
import { useThemeConfig } from '@/store/themeConfig';
|
import { useThemeConfig } from '@/store/themeConfig';
|
||||||
import { getFileUrl } from '@/common/request';
|
import { getFileUrl } from '@/common/request';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const rules = {
|
const rules = {
|
||||||
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
|
username: [{ required: true, message: t('login.inputUsernamePlaceholder'), trigger: 'blur' }],
|
||||||
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
|
password: [{ required: true, message: t('login.inputPasswordPlaceholder'), trigger: 'blur' }],
|
||||||
captcha: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
|
captcha: [{ required: true, message: t('login.inputCaptchaPlaceholder'), trigger: 'blur' }],
|
||||||
};
|
};
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
@@ -189,10 +211,10 @@ const state = reactive({
|
|||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
newPassword: [
|
newPassword: [
|
||||||
{ required: true, message: '请输入新密码', trigger: 'blur' },
|
{ required: true, message: t('login.inputNewPasswordPlaceholder'), trigger: 'blur' },
|
||||||
{
|
{
|
||||||
pattern: /^(?=.*[A-Za-z])(?=.*\d)(?=.*[`~!@#$%^&*()_+<>?:"{},.\/\\;'[\]])[A-Za-z\d`~!@#$%^&*()_+<>?:"{},.\/\\;'[\]]{8,}$/,
|
pattern: /^(?=.*[A-Za-z])(?=.*\d)(?=.*[`~!@#$%^&*()_+<>?:"{},.\/\\;'[\]])[A-Za-z\d`~!@#$%^&*()_+<>?:"{},.\/\\;'[\]]{8,}$/,
|
||||||
message: '须为8位以上且包含字⺟⼤⼩写+数字+特殊符号',
|
message: t('login.passwordRuleTip'),
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -206,7 +228,7 @@ const state = reactive({
|
|||||||
otpToken: '',
|
otpToken: '',
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
code: [{ required: true, message: '请输入OTP授权码', trigger: 'blur' }],
|
code: [{ required: true, message: t('login.inputOtpCodePlaceholder'), trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
baseInfoDialog: {
|
baseInfoDialog: {
|
||||||
@@ -217,14 +239,14 @@ const state = reactive({
|
|||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
username: [
|
username: [
|
||||||
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
{ required: true, message: t('login.inputUsernamePlaceholder'), trigger: 'blur' },
|
||||||
{
|
{
|
||||||
pattern: AccountUsernamePattern.pattern,
|
pattern: AccountUsernamePattern.pattern,
|
||||||
message: AccountUsernamePattern.message,
|
message: AccountUsernamePattern.message,
|
||||||
trigger: ['blur'],
|
trigger: ['blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
|
name: [{ required: true, message: t('login.inputNamePlaceholder'), trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
loading: {
|
loading: {
|
||||||
@@ -424,7 +446,7 @@ const toIndex = async () => {
|
|||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
// 关闭 loading
|
// 关闭 loading
|
||||||
state.loading.signIn = true;
|
state.loading.signIn = true;
|
||||||
ElMessage.success(`${currentTimeInfo},欢迎回来!`);
|
ElMessage.success(t('login.loginSuccessTip'));
|
||||||
// 水印设置用户信息
|
// 水印设置用户信息
|
||||||
storesThemeConfig.setWatermarkUser();
|
storesThemeConfig.setWatermarkUser();
|
||||||
}, 300);
|
}, 300);
|
||||||
@@ -444,7 +466,7 @@ const changePwd = async () => {
|
|||||||
changePwdReq.oldPassword = await RsaEncrypt(form.oldPassword);
|
changePwdReq.oldPassword = await RsaEncrypt(form.oldPassword);
|
||||||
changePwdReq.newPassword = await RsaEncrypt(form.newPassword);
|
changePwdReq.newPassword = await RsaEncrypt(form.newPassword);
|
||||||
await openApi.changePwd(changePwdReq);
|
await openApi.changePwd(changePwdReq);
|
||||||
ElMessage.success('密码修改成功, 新密码已填充至登录密码框');
|
ElMessage.success(t('login.passwordChangeSuccessTip'));
|
||||||
state.loginForm.password = state.changePwdDialog.form.newPassword;
|
state.loginForm.password = state.changePwdDialog.form.newPassword;
|
||||||
state.changePwdDialog.visible = false;
|
state.changePwdDialog.visible = false;
|
||||||
getCaptcha();
|
getCaptcha();
|
||||||
|
|||||||
@@ -22,13 +22,13 @@
|
|||||||
<div class="login-right-warp-main-form">
|
<div class="login-right-warp-main-form">
|
||||||
<div v-if="!state.isScan">
|
<div v-if="!state.isScan">
|
||||||
<el-tabs v-model="state.tabsActiveName">
|
<el-tabs v-model="state.tabsActiveName">
|
||||||
<el-tab-pane label="账号密码登录" name="account">
|
<el-tab-pane :label="$t('login.accountPasswordLogin')" name="account">
|
||||||
<Account ref="loginForm" />
|
<Account ref="loginForm" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt20" v-show="state.oauth2LoginConfig.enable">
|
<div class="mt20" v-show="state.oauth2LoginConfig.enable">
|
||||||
<el-button link size="small">第三方登录: </el-button>
|
<el-button link size="small">{{ $t('login.thirdPartyLogin') }}: </el-button>
|
||||||
<el-tooltip :content="state.oauth2LoginConfig.name" placement="top-start">
|
<el-tooltip :content="state.oauth2LoginConfig.name" placement="top-start">
|
||||||
<el-button link size="small" type="primary" @click="oauth2Login">
|
<el-button link size="small" type="primary" @click="oauth2Login">
|
||||||
<el-icon :size="18">
|
<el-icon :size="18">
|
||||||
@@ -52,6 +52,7 @@ import loginBgSplitImg from '@/assets/image/login-bg-split.svg';
|
|||||||
import openApi from '@/common/openApi';
|
import openApi from '@/common/openApi';
|
||||||
import config from '@/common/config';
|
import config from '@/common/config';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
// 引入组件
|
// 引入组件
|
||||||
const Account = defineAsyncComponent(() => import('./component/AccountLogin.vue'));
|
const Account = defineAsyncComponent(() => import('./component/AccountLogin.vue'));
|
||||||
@@ -61,18 +62,20 @@ const loginForm = ref<{ loginResDeal: (data: any) => void } | null>(null);
|
|||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
const storesThemeConfig = useThemeConfig();
|
const storesThemeConfig = useThemeConfig();
|
||||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||||
|
const { locale } = useI18n();
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
tabsActiveName: 'account',
|
tabsActiveName: 'account',
|
||||||
isScan: false,
|
isScan: false,
|
||||||
oauth2LoginConfig: {
|
oauth2LoginConfig: {
|
||||||
name: 'OAuth2登录',
|
name: 'OAuth2 Login',
|
||||||
enable: false,
|
enable: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
storesThemeConfig.setWatermarkUser(true);
|
storesThemeConfig.setWatermarkUser(true);
|
||||||
|
locale.value = themeConfig.value.globalI18n;
|
||||||
state.oauth2LoginConfig = await openApi.oauth2LoginConfig();
|
state.oauth2LoginConfig = await openApi.oauth2LoginConfig();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -104,11 +107,13 @@ const oauth2Login = () => {
|
|||||||
.login-container {
|
.login-container {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: var(--bg-main-color);
|
background: var(--bg-main-color);
|
||||||
|
|
||||||
.login-left {
|
.login-left {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: rgba(211, 239, 255, 1);
|
background-color: rgba(211, 239, 255, 1);
|
||||||
margin-right: 100px;
|
margin-right: 100px;
|
||||||
|
|
||||||
.login-left-logo {
|
.login-left-logo {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -117,24 +122,29 @@ const oauth2Login = () => {
|
|||||||
left: 80px;
|
left: 80px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
animation: logoAnimation 0.3s ease;
|
animation: logoAnimation 0.3s ease;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 52px;
|
width: 52px;
|
||||||
height: 52px;
|
height: 52px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-left-logo-text {
|
.login-left-logo-text {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
color: #26a59a;
|
color: #26a59a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-left-logo-text-msg {
|
.login-left-logo-text-msg {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #32a99e;
|
color: #32a99e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-left-img {
|
.login-left-img {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
@@ -142,20 +152,24 @@ const oauth2Login = () => {
|
|||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 52%;
|
height: 52%;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
animation: error-num 0.6s ease;
|
animation: error-num 0.6s ease;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-left-waves {
|
.login-left-waves {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: -100px;
|
right: -100px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-right {
|
.login-right {
|
||||||
width: 700px;
|
width: 700px;
|
||||||
|
|
||||||
.login-right-warp {
|
.login-right-warp {
|
||||||
border: 1px solid var(--el-color-primary-light-3);
|
border: 1px solid var(--el-color-primary-light-3);
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
@@ -164,12 +178,14 @@ const oauth2Login = () => {
|
|||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: var(--bg-main-color);
|
background-color: var(--bg-main-color);
|
||||||
|
|
||||||
.login-right-warp-one,
|
.login-right-warp-one,
|
||||||
.login-right-warp-two {
|
.login-right-warp-two {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: block;
|
display: block;
|
||||||
width: inherit;
|
width: inherit;
|
||||||
height: inherit;
|
height: inherit;
|
||||||
|
|
||||||
&::before,
|
&::before,
|
||||||
&::after {
|
&::after {
|
||||||
content: '';
|
content: '';
|
||||||
@@ -177,6 +193,7 @@ const oauth2Login = () => {
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-right-warp-one {
|
.login-right-warp-one {
|
||||||
&::before {
|
&::before {
|
||||||
filter: hue-rotate(0deg);
|
filter: hue-rotate(0deg);
|
||||||
@@ -187,6 +204,7 @@ const oauth2Login = () => {
|
|||||||
background: linear-gradient(90deg, transparent, var(--el-color-primary));
|
background: linear-gradient(90deg, transparent, var(--el-color-primary));
|
||||||
animation: loginLeft 3s linear infinite;
|
animation: loginLeft 3s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
filter: hue-rotate(60deg);
|
filter: hue-rotate(60deg);
|
||||||
top: -100%;
|
top: -100%;
|
||||||
@@ -198,6 +216,7 @@ const oauth2Login = () => {
|
|||||||
animation-delay: 0.7s;
|
animation-delay: 0.7s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-right-warp-two {
|
.login-right-warp-two {
|
||||||
&::before {
|
&::before {
|
||||||
filter: hue-rotate(120deg);
|
filter: hue-rotate(120deg);
|
||||||
@@ -209,6 +228,7 @@ const oauth2Login = () => {
|
|||||||
animation: loginRight 3s linear infinite;
|
animation: loginRight 3s linear infinite;
|
||||||
animation-delay: 1.4s;
|
animation-delay: 1.4s;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
filter: hue-rotate(300deg);
|
filter: hue-rotate(300deg);
|
||||||
bottom: -100%;
|
bottom: -100%;
|
||||||
@@ -220,10 +240,12 @@ const oauth2Login = () => {
|
|||||||
animation-delay: 2.1s;
|
animation-delay: 2.1s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-right-warp-mian {
|
.login-right-warp-mian {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.login-right-warp-main-title {
|
.login-right-warp-main-title {
|
||||||
height: 110px;
|
height: 110px;
|
||||||
line-height: 110px;
|
line-height: 110px;
|
||||||
@@ -234,9 +256,11 @@ const oauth2Login = () => {
|
|||||||
animation-delay: 0.3s;
|
animation-delay: 0.3s;
|
||||||
color: var(--el-text-color-primary);
|
color: var(--el-text-color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-right-warp-main-form {
|
.login-right-warp-main-form {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 0 50px 50px;
|
padding: 0 50px 50px;
|
||||||
|
|
||||||
.login-content-main-sacn {
|
.login-content-main-sacn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
@@ -247,6 +271,7 @@ const oauth2Login = () => {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all ease 0.3s;
|
transition: all ease 0.3s;
|
||||||
color: var(--el-color-primary);
|
color: var(--el-color-primary);
|
||||||
|
|
||||||
&-delta {
|
&-delta {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 35px;
|
width: 35px;
|
||||||
@@ -257,11 +282,13 @@ const oauth2Login = () => {
|
|||||||
background: var(--el-color-white);
|
background: var(--el-color-white);
|
||||||
transform: rotate(-45deg);
|
transform: rotate(-45deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transition: all ease 0.3s;
|
transition: all ease 0.3s;
|
||||||
color: var(--el-color-primary) !important;
|
color: var(--el-color-primary) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
i {
|
i {
|
||||||
width: 47px;
|
width: 47px;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
|
|||||||
@@ -7,9 +7,12 @@ import { onMounted } from 'vue';
|
|||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import openApi from '@/common/openApi';
|
import openApi from '@/common/openApi';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
const queryParam = route.query;
|
const queryParam = route.query;
|
||||||
@@ -26,7 +29,7 @@ onMounted(async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const res: any = await openApi.oauth2Callback(queryParam);
|
const res: any = await openApi.oauth2Callback(queryParam);
|
||||||
ElMessage.success('授权认证成功');
|
ElMessage.success(t('system.oauth.authSuccess'));
|
||||||
top?.opener.postMessage(res);
|
top?.opener.postMessage(res);
|
||||||
window.close();
|
window.close();
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="auth-cert-edit">
|
<div class="auth-cert-edit">
|
||||||
<el-dialog :title="props.title" v-model="dialogVisible" :show-close="false" width="500px" :destroy-on-close="true" :close-on-click-modal="false">
|
<el-dialog :title="props.title" v-model="dialogVisible" :show-close="false" width="600px" :destroy-on-close="true" :close-on-click-modal="false">
|
||||||
<el-form ref="acForm" :model="state.form" label-width="auto" :rules="rules">
|
<el-form ref="acForm" :model="state.form" label-width="auto" :rules="rules">
|
||||||
<el-form-item prop="type" label="凭证类型" required>
|
<el-form-item prop="type" :label="$t('ac.credentialType')" required>
|
||||||
<el-select @change="changeType" v-model="form.type" placeholder="请选择凭证类型">
|
<el-select @change="changeType" v-model="form.type">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in AuthCertTypeEnum"
|
v-for="item in AuthCertTypeEnum"
|
||||||
:key="item.value"
|
:key="item.value"
|
||||||
:label="item.label"
|
:label="$t(item.label)"
|
||||||
:value="item.value"
|
:value="item.value"
|
||||||
v-show="!props.disableType?.includes(item.value)"
|
v-show="!props.disableType?.includes(item.value)"
|
||||||
>
|
>
|
||||||
@@ -15,12 +15,12 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item prop="ciphertextType" label="密文类型" required>
|
<el-form-item prop="ciphertextType" :label="$t('ac.ciphertextType')" required>
|
||||||
<el-select v-model="form.ciphertextType" placeholder="请选择密文类型" @change="changeCiphertextType">
|
<el-select v-model="form.ciphertextType" @change="changeCiphertextType">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in AuthCertCiphertextTypeEnum"
|
v-for="item in AuthCertCiphertextTypeEnum"
|
||||||
:key="item.value"
|
:key="item.value"
|
||||||
:label="item.label"
|
:label="$t(item.label)"
|
||||||
:value="item.value"
|
:value="item.value"
|
||||||
v-show="!props.disableCiphertextType?.includes(item.value)"
|
v-show="!props.disableCiphertextType?.includes(item.value)"
|
||||||
:disabled="item.value == AuthCertCiphertextTypeEnum.Public.value && form.type == AuthCertTypeEnum.Public.value"
|
:disabled="item.value == AuthCertCiphertextTypeEnum.Public.value && form.type == AuthCertTypeEnum.Public.value"
|
||||||
@@ -30,45 +30,45 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<template v-if="showResourceEdit">
|
<template v-if="showResourceEdit">
|
||||||
<el-form-item prop="type" label="资源类型" required>
|
<el-form-item prop="type" :label="$t('ac.resourceType')" required>
|
||||||
<el-select :disabled="form.id" v-model="form.resourceType" placeholder="请选择资源类型">
|
<el-select :disabled="form.id" v-model="form.resourceType">
|
||||||
<el-option
|
<el-option
|
||||||
:key="TagResourceTypeEnum.Machine.value"
|
:key="TagResourceTypeEnum.Machine.value"
|
||||||
:label="TagResourceTypeEnum.Machine.label"
|
:label="$t(TagResourceTypeEnum.Machine.label)"
|
||||||
:value="TagResourceTypeEnum.Machine.value"
|
:value="TagResourceTypeEnum.Machine.value"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<el-option :key="TagResourceTypeEnum.Db.value" :label="TagResourceTypeEnum.Db.label" :value="TagResourceTypeEnum.Db.value" />
|
<el-option :key="TagResourceTypeEnum.Db.value" :label="TagResourceTypeEnum.Db.label" :value="TagResourceTypeEnum.Db.value" />
|
||||||
<el-option
|
<el-option
|
||||||
:key="TagResourceTypeEnum.Redis.value"
|
:key="TagResourceTypeEnum.Redis.value"
|
||||||
:label="TagResourceTypeEnum.Redis.label"
|
:label="$t(TagResourceTypeEnum.Redis.label)"
|
||||||
:value="TagResourceTypeEnum.Redis.value"
|
:value="TagResourceTypeEnum.Redis.value"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="resourceCode" label="资源编号" required>
|
<el-form-item prop="resourceCode" :label="$t('ac.resourceCode')" required>
|
||||||
<el-input :disabled="form.id" v-model="form.resourceCode" placeholder="请输入资源编号"></el-input>
|
<el-input :disabled="form.id" v-model="form.resourceCode"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-form-item v-if="form.type == AuthCertTypeEnum.Public.value" prop="name" label="名称" required>
|
<el-form-item v-if="form.type == AuthCertTypeEnum.Public.value" prop="name" :label="$t('common.name')" required>
|
||||||
<el-input :disabled="form.id" v-model="form.name" placeholder="请输入凭证名 (全局唯一)"></el-input>
|
<el-input :disabled="form.id" v-model="form.name" :placeholder="$t('ac.namePlaceholder')"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<template v-if="form.ciphertextType != AuthCertCiphertextTypeEnum.Public.value">
|
<template v-if="form.ciphertextType != AuthCertCiphertextTypeEnum.Public.value">
|
||||||
<el-form-item prop="username" label="用户名">
|
<el-form-item prop="username" :label="$t('common.username')">
|
||||||
<el-input v-model="form.username"></el-input>
|
<el-input v-model="form.username"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item v-if="form.ciphertextType == AuthCertCiphertextTypeEnum.Password.value" prop="ciphertext" label="密码">
|
<el-form-item v-if="form.ciphertextType == AuthCertCiphertextTypeEnum.Password.value" prop="ciphertext" :label="$t('common.password')">
|
||||||
<el-input type="password" show-password clearable v-model.trim="form.ciphertext" placeholder="请输入密码" autocomplete="new-password">
|
<el-input type="password" show-password clearable v-model.trim="form.ciphertext" autocomplete="new-password">
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<SvgIcon v-if="form.id" v-auth="'authcert:showciphertext'" @click="getCiphertext" name="search" />
|
<SvgIcon v-if="form.id" v-auth="'authcert:showciphertext'" @click="getCiphertext" name="search" />
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item v-if="form.ciphertextType == AuthCertCiphertextTypeEnum.PrivateKey.value" prop="ciphertext" label="秘钥">
|
<el-form-item v-if="form.ciphertextType == AuthCertCiphertextTypeEnum.PrivateKey.value" prop="ciphertext" :label="$t('ac.privateKey')">
|
||||||
<div class="w100" style="position: relative">
|
<div class="w100" style="position: relative">
|
||||||
<SvgIcon
|
<SvgIcon
|
||||||
v-if="form.id"
|
v-if="form.id"
|
||||||
@@ -77,17 +77,17 @@
|
|||||||
name="search"
|
name="search"
|
||||||
style="position: absolute; top: 5px; right: 5px; cursor: pointer; z-index: 1"
|
style="position: absolute; top: 5px; right: 5px; cursor: pointer; z-index: 1"
|
||||||
/>
|
/>
|
||||||
<el-input type="textarea" :rows="5" v-model="form.ciphertext" placeholder="请将私钥文件内容拷贝至此"> </el-input>
|
<el-input type="textarea" :rows="5" v-model="form.ciphertext" :placeholder="$t('ac.privateKeyPlaceholder')"> </el-input>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item v-if="form.ciphertextType == AuthCertCiphertextTypeEnum.PrivateKey.value" prop="passphrase" label="秘钥密码">
|
<el-form-item v-if="form.ciphertextType == AuthCertCiphertextTypeEnum.PrivateKey.value" prop="passphrase" :label="$t('ac.privateKeyPwd')">
|
||||||
<el-input type="password" show-password v-model="form.extra.passphrase"> </el-input>
|
<el-input type="password" show-password v-model="form.extra.passphrase"> </el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<el-form-item label="公共凭证">
|
<el-form-item :label="$t('ac.publicAc')">
|
||||||
<el-select default-first-option filterable v-model="form.ciphertext" @change="changePublicAuthCert">
|
<el-select default-first-option filterable v-model="form.ciphertext" @change="changePublicAuthCert">
|
||||||
<el-option v-for="item in state.publicAuthCerts" :key="item.name" :label="item.name" :value="item.name">
|
<el-option v-for="item in state.publicAuthCerts" :key="item.name" :label="item.name" :value="item.name">
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
@@ -102,14 +102,14 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-form-item label="备注">
|
<el-form-item :label="$t('common.remark')">
|
||||||
<el-input v-model="form.remark" type="textarea" :rows="2"></el-input>
|
<el-input v-model="form.remark" type="textarea" :rows="2"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="cancelEdit">取 消</el-button>
|
<el-button @click="cancelEdit">{{ $t('common.cancel') }}</el-button>
|
||||||
<el-button type="primary" :loading="btnLoading" @click="btnOk">确 定</el-button>
|
<el-button type="primary" :loading="btnLoading" @click="btnOk">{{ $t('common.confirm') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@@ -123,11 +123,14 @@ import EnumTag from '@/components/enumtag/EnumTag.vue';
|
|||||||
import { resourceAuthCertApi } from '../tag/api';
|
import { resourceAuthCertApi } from '../tag/api';
|
||||||
import { ResourceCodePattern } from '@/common/pattern';
|
import { ResourceCodePattern } from '@/common/pattern';
|
||||||
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '凭证保存',
|
default: '',
|
||||||
},
|
},
|
||||||
authCert: {
|
authCert: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -162,7 +165,7 @@ const rules = {
|
|||||||
name: [
|
name: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入凭证名',
|
message: t('common.pleaseInput', { label: t('common.name') }),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -174,7 +177,7 @@ const rules = {
|
|||||||
resourceCode: [
|
resourceCode: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入资源编号',
|
message: t('common.pleaseInput', { label: t('ac.resourceCode') }),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="auth-cert-manage">
|
<div class="auth-cert-manage">
|
||||||
<el-table :data="authCerts" max-height="180" stripe size="small">
|
<el-table :data="authCerts" :max-height="180" stripe size="small">
|
||||||
<el-table-column min-wdith="120px">
|
<el-table-column min-wdith="120px">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-button v-auth="'authcert:save'" class="ml0" type="primary" circle size="small" icon="Plus" @click="edit(null)"> </el-button>
|
<el-button v-auth="'authcert:save'" class="ml0" type="primary" circle size="small" icon="Plus" @click="edit(null)"> </el-button>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<el-button class="ml1" v-auth="'authcert:del'" type="danger" @click="deleteRow(scope.$index)" icon="delete" link></el-button>
|
<el-button class="ml1" v-auth="'authcert:del'" type="danger" @click="deleteRow(scope.$index)" icon="delete" link></el-button>
|
||||||
|
|
||||||
<el-button
|
<el-button
|
||||||
title="测试连接"
|
:title="$t('ac.testConn')"
|
||||||
:loading="props.testConnBtnLoading && scope.$index == state.idx"
|
:loading="props.testConnBtnLoading && scope.$index == state.idx"
|
||||||
:disabled="props.testConnBtnLoading"
|
:disabled="props.testConnBtnLoading"
|
||||||
class="ml1"
|
class="ml1"
|
||||||
@@ -22,19 +22,18 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<!-- <el-table-column prop="name" label="名称" show-overflow-tooltip min-width="100px"> </el-table-column> -->
|
<el-table-column prop="username" :label="$t('common.username')" min-width="120px" show-overflow-tooltip> </el-table-column>
|
||||||
<el-table-column prop="username" label="用户名" min-width="120px" show-overflow-tooltip> </el-table-column>
|
<el-table-column prop="ciphertextType" :label="$t('ac.ciphertextType')" width="100px">
|
||||||
<el-table-column prop="ciphertextType" label="密文类型" width="100px">
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<EnumTag :value="scope.row.ciphertextType" :enums="AuthCertCiphertextTypeEnum" />
|
<EnumTag :value="scope.row.ciphertextType" :enums="AuthCertCiphertextTypeEnum" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="type" label="凭证类型" width="100px">
|
<el-table-column prop="type" :label="$t('ac.credentialType')" width="100px">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<EnumTag :value="scope.row.type" :enums="AuthCertTypeEnum" />
|
<EnumTag :value="scope.row.type" :enums="AuthCertTypeEnum" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="remark" label="备注" show-overflow-tooltip width="120px"> </el-table-column>
|
<el-table-column prop="remark" :label="$t('common.remark')" show-overflow-tooltip width="120px"> </el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<ResourceAuthCertEdit
|
<ResourceAuthCertEdit
|
||||||
@@ -55,6 +54,9 @@ import { resourceAuthCertApi } from '../tag/api';
|
|||||||
import EnumTag from '@/components/enumtag/EnumTag.vue';
|
import EnumTag from '@/components/enumtag/EnumTag.vue';
|
||||||
import ResourceAuthCertEdit from './ResourceAuthCertEdit.vue';
|
import ResourceAuthCertEdit from './ResourceAuthCertEdit.vue';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
resourceType: { type: Number },
|
resourceType: { type: Number },
|
||||||
@@ -117,17 +119,6 @@ const cancelEdit = () => {
|
|||||||
|
|
||||||
const btnOk = async (authCert: any) => {
|
const btnOk = async (authCert: any) => {
|
||||||
const isEdit = authCert.id;
|
const isEdit = authCert.id;
|
||||||
// if (!isEdit) {
|
|
||||||
// const res = await resourceAuthCertApi.listByQuery.request({
|
|
||||||
// name: authCert.name,
|
|
||||||
// pageNum: 1,
|
|
||||||
// pageSize: 100,
|
|
||||||
// });
|
|
||||||
// if (res.total) {
|
|
||||||
// ElMessage.error('该授权凭证名称已存在');
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (isEdit || state.idx >= 0) {
|
if (isEdit || state.idx >= 0) {
|
||||||
authCerts.value[state.idx] = authCert;
|
authCerts.value[state.idx] = authCert;
|
||||||
@@ -136,7 +127,7 @@ const btnOk = async (authCert: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (authCerts.value?.filter((x: any) => x.username == authCert.username).length > 0) {
|
if (authCerts.value?.filter((x: any) => x.username == authCert.username).length > 0) {
|
||||||
ElMessage.error('该用户名已存在于该账号列表中');
|
ElMessage.error(t('ac.usernameExist'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
v-model="sshTunnelMachineId"
|
v-model="sshTunnelMachineId"
|
||||||
@clear="clear"
|
@clear="clear"
|
||||||
placeholder="请选择SSH隧道机器"
|
placeholder="SSH tunnel machine"
|
||||||
clearable
|
clearable
|
||||||
>
|
>
|
||||||
<el-option v-for="item in sshTunnelMachineList" :key="item.id" :label="`${item.ip}:${item.port} [${item.name}]`" :value="item.id"> </el-option>
|
<el-option v-for="item in sshTunnelMachineList" :key="item.id" :label="`${item.ip}:${item.port} [${item.name}]`" :value="item.id"> </el-option>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="display: inline-flex; justify-content: center; align-items: center; cursor: pointer; vertical-align: middle">
|
<div style="display: inline-flex; justify-content: center; align-items: center; cursor: pointer; vertical-align: middle">
|
||||||
<el-popover :show-after="500" @show="showTagInfo" placement="top-start" title="标签信息" :width="300" trigger="hover">
|
<el-popover :show-after="500" @show="showTagInfo" placement="top-start" :title="$t('common.tag')" :width="300" trigger="hover">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<InfoFilled />
|
<InfoFilled />
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="card pd5">
|
<div class="card pd5">
|
||||||
<el-input v-model="filterText" placeholder="输入关键字->搜索已展开节点信息" clearable size="small" class="mb5 w100" />
|
<el-input v-model="filterText" :placeholder="$t('tag.tagFilterPlaceholder')" clearable size="small" class="mb5 w100" />
|
||||||
<el-scrollbar class="tag-tree">
|
<el-scrollbar class="tag-tree">
|
||||||
<el-tree
|
<el-tree
|
||||||
ref="treeRef"
|
ref="treeRef"
|
||||||
@@ -26,11 +26,11 @@
|
|||||||
<slot v-else :node="node" :data="data" name="prefix"></slot>
|
<slot v-else :node="node" :data="data" name="prefix"></slot>
|
||||||
|
|
||||||
<span class="ml3" :title="data.labelRemark">
|
<span class="ml3" :title="data.labelRemark">
|
||||||
<slot name="label" :data="data" v-if="!data.disabled"> {{ data.label }}</slot>
|
<slot name="label" :data="data" v-if="!data.disabled"> {{ $t(data.label) }}</slot>
|
||||||
<!-- 禁用状态 -->
|
<!-- 禁用状态 -->
|
||||||
<slot name="disabledLabel" :data="data" v-else>
|
<slot name="disabledLabel" :data="data" v-else>
|
||||||
<el-link type="danger" disabled :underline="false">
|
<el-link type="danger" disabled :underline="false">
|
||||||
{{ `${data.label}` }}
|
{{ `${$t(data.label)}` }}
|
||||||
</el-link>
|
</el-link>
|
||||||
</slot>
|
</slot>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w100 tag-tree-check">
|
<div class="w100 tag-tree-check">
|
||||||
<el-input v-model="filterTag" @input="onFilterValChanged" clearable placeholder="输入关键字过滤" size="small" />
|
<el-input v-model="filterTag" @input="onFilterValChanged" clearable :placeholder="$t('tag.keywordFilterPlaceholder')" size="small" />
|
||||||
<div class="mt3" style="border: 1px solid var(--el-border-color)">
|
<div class="mt3" style="border: 1px solid var(--el-border-color)">
|
||||||
<el-scrollbar :style="{ height: props.height }">
|
<el-scrollbar :style="{ height: props.height }">
|
||||||
<el-tree
|
<el-tree
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
v-model="state.selectTags"
|
v-model="state.selectTags"
|
||||||
@change="changeTag"
|
@change="changeTag"
|
||||||
:data="tags"
|
:data="tags"
|
||||||
placeholder="请选择关联标签"
|
:placeholder="$t('tag.selectTagPlaceholder')"
|
||||||
:default-expanded-keys="defaultExpandedKeys"
|
:default-expanded-keys="defaultExpandedKeys"
|
||||||
show-checkbox
|
show-checkbox
|
||||||
node-key="codePath"
|
node-key="codePath"
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ export class NodeType {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function getTagPathSearchItem(resourceType: number) {
|
export function getTagPathSearchItem(resourceType: number) {
|
||||||
return SearchItem.select('tagPath', '标签').withOptionsApi(
|
return SearchItem.select('tagPath', 'common.tag').withOptionsApi(
|
||||||
OptionsApi.new(tagApi.getResourceTagPaths, {resourceType}).withConvertFn((res: any) => {
|
OptionsApi.new(tagApi.getResourceTagPaths, {resourceType}).withConvertFn((res: any) => {
|
||||||
return res.map((x: any) => {
|
return res.map((x: any) => {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -10,12 +10,12 @@
|
|||||||
width="38%"
|
width="38%"
|
||||||
>
|
>
|
||||||
<el-form :model="form" ref="dbForm" :rules="rules" label-width="auto">
|
<el-form :model="form" ref="dbForm" :rules="rules" label-width="auto">
|
||||||
<el-form-item prop="name" label="名称" required>
|
<el-form-item prop="name" :label="$t('common.name')" required>
|
||||||
<el-input v-model.trim="form.name" placeholder="请输入数据库别名" auto-complete="off"></el-input>
|
<el-input v-model.trim="form.name" auto-complete="off"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item prop="authCertName" label="授权凭证" required>
|
<el-form-item prop="authCertName" :label="$t('db.acName')" required>
|
||||||
<el-select v-model="form.authCertName" placeholder="请选择授权凭证" filterable>
|
<el-select v-model="form.authCertName" filterable>
|
||||||
<el-option v-for="item in state.authCerts" :key="item.id" :label="`${item.name}`" :value="item.name">
|
<el-option v-for="item in state.authCerts" :key="item.id" :label="`${item.name}`" :value="item.name">
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
|
|
||||||
@@ -31,13 +31,11 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item prop="getDatabaseMode" label="获库方式" required>
|
<el-form-item prop="getDatabaseMode" :label="$t('db.getDbMode')" required>
|
||||||
<el-select v-model="form.getDatabaseMode" @change="onChangeGetDatabaseMode" placeholder="请选择库名获取方式">
|
<EnumSelect :enums="DbGetDbNamesMode" v-model="form.getDatabaseMode" @change="onChangeGetDatabaseMode" />
|
||||||
<el-option v-for="item in DbGetDbNamesMode" :key="item.value" :label="item.label" :value="item.value"> </el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item prop="database" label="数据库名">
|
<el-form-item prop="database" label="DB">
|
||||||
<el-select
|
<el-select
|
||||||
:disabled="form.getDatabaseMode == DbGetDbNamesMode.Auto.value || !form.authCertName"
|
:disabled="form.getDatabaseMode == DbGetDbNamesMode.Auto.value || !form.authCertName"
|
||||||
v-model="dbNamesSelected"
|
v-model="dbNamesSelected"
|
||||||
@@ -48,26 +46,28 @@
|
|||||||
filterable
|
filterable
|
||||||
:filter-method="filterDbNames"
|
:filter-method="filterDbNames"
|
||||||
allow-create
|
allow-create
|
||||||
placeholder="获库方式为‘指定库名’时,可选择"
|
:placeholder="$t('db.selectDbPlacehoder')"
|
||||||
@focus="getAllDatabase(form.authCertName)"
|
@focus="getAllDatabase(form.authCertName)"
|
||||||
:loading="state.loadingDbNames"
|
:loading="state.loadingDbNames"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-checkbox v-model="checkAllDbNames" :indeterminate="indeterminateDbNames" @change="handleCheckAll"> 全选 </el-checkbox>
|
<el-checkbox v-model="checkAllDbNames" :indeterminate="indeterminateDbNames" @change="handleCheckAll">
|
||||||
|
{{ $t('db.allSelect') }}
|
||||||
|
</el-checkbox>
|
||||||
</template>
|
</template>
|
||||||
<el-option v-for="db in state.dbNamesFiltered" :key="db" :label="db" :value="db" />
|
<el-option v-for="db in state.dbNamesFiltered" :key="db" :label="db" :value="db" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item prop="remark" label="备注">
|
<el-form-item prop="remark" :label="$t('common.remark')">
|
||||||
<el-input v-model.trim="form.remark" auto-complete="off" type="textarea"></el-input>
|
<el-input v-model.trim="form.remark" auto-complete="off" type="textarea"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="cancel()">取 消</el-button>
|
<el-button @click="cancel()">{{ $t('common.cancel') }}</el-button>
|
||||||
<el-button type="primary" @click="btnOk">确 定</el-button>
|
<el-button type="primary" @click="btnOk">{{ $t('common.confirm') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@@ -77,7 +77,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { toRefs, reactive, watch, ref } from 'vue';
|
import { toRefs, reactive, watch, ref } from 'vue';
|
||||||
import { dbApi } from './api';
|
import { dbApi } from './api';
|
||||||
import { ElMessage } from 'element-plus';
|
|
||||||
import type { CheckboxValueType } from 'element-plus';
|
import type { CheckboxValueType } from 'element-plus';
|
||||||
import { DbType } from '@/views/ops/db/dialect';
|
import { DbType } from '@/views/ops/db/dialect';
|
||||||
|
|
||||||
@@ -86,6 +85,8 @@ import { AuthCertCiphertextTypeEnum } from '../tag/enums';
|
|||||||
import { resourceAuthCertApi } from '../tag/api';
|
import { resourceAuthCertApi } from '../tag/api';
|
||||||
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
||||||
import { DbGetDbNamesMode } from './enums';
|
import { DbGetDbNamesMode } from './enums';
|
||||||
|
import EnumSelect from '@/components/enumselect/EnumSelect.vue';
|
||||||
|
import { useI18nFormValidate, useI18nPleaseInput, useI18nPleaseSelect } from '@/hooks/useI18n';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
visible: {
|
visible: {
|
||||||
@@ -106,39 +107,31 @@ const props = defineProps({
|
|||||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change', 'confirm']);
|
const emit = defineEmits(['update:visible', 'cancel', 'val-change', 'confirm']);
|
||||||
|
|
||||||
const rules = {
|
const rules = {
|
||||||
tagId: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: '请选择标签',
|
|
||||||
trigger: ['change', 'blur'],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
instanceId: [
|
instanceId: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请选择数据库实例',
|
message: useI18nPleaseSelect('db.dbInst'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
name: [
|
name: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入别名',
|
message: useI18nPleaseInput('common.name'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
authCertName: [
|
authCertName: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请选择授权凭证',
|
message: useI18nPleaseSelect('db.acName'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
getDatabaseMode: [
|
getDatabaseMode: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请选择库名获取方式',
|
message: useI18nPleaseSelect('db.getDbMode'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -237,13 +230,7 @@ const open = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const btnOk = async () => {
|
const btnOk = async () => {
|
||||||
try {
|
await useI18nFormValidate(dbForm);
|
||||||
await dbForm.value.validate();
|
|
||||||
} catch (e: any) {
|
|
||||||
ElMessage.error('请正确填写信息');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit('confirm', state.form);
|
emit('confirm', state.form);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -46,12 +46,12 @@
|
|||||||
<template #database="{ data }">
|
<template #database="{ data }">
|
||||||
<el-popover placement="bottom" :width="200" trigger="click">
|
<el-popover placement="bottom" :width="200" trigger="click">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button @click="getDbNames(data)" type="primary" link>查看库</el-button>
|
<el-button @click="getDbNames(data)" type="primary" link>{{ $t('db.showDb') }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
<el-table :data="filterDbs" v-loading="state.loadingDbNames" size="small">
|
<el-table :data="filterDbs" v-loading="state.loadingDbNames" size="small">
|
||||||
<el-table-column prop="dbName" label="数据库">
|
<el-table-column prop="dbName" :label="$t('db.db')">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-input v-model="state.dbNameSearch" size="small" placeholder="库名: 输入可过滤" clearable />
|
<el-input v-model="state.dbNameSearch" size="small" :placeholder="$t('db.dbFilterPlaceholder')" clearable />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -63,24 +63,24 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #action="{ data }">
|
<template #action="{ data }">
|
||||||
<el-button v-auth="perms.saveDb" @click="editDb(data)" type="primary" link>编辑</el-button>
|
<el-button v-auth="perms.saveDb" @click="editDb(data)" type="primary" link>{{ $t('common.edit') }}</el-button>
|
||||||
|
|
||||||
<el-divider direction="vertical" border-style="dashed" />
|
<el-divider direction="vertical" border-style="dashed" />
|
||||||
|
|
||||||
<el-button type="primary" @click="onShowSqlExec(data)" link>SQL记录</el-button>
|
<el-button type="primary" @click="onShowSqlExec(data)" link>{{ $t('db.sqlRecord') }}</el-button>
|
||||||
|
|
||||||
<el-divider direction="vertical" border-style="dashed" />
|
<el-divider direction="vertical" border-style="dashed" />
|
||||||
|
|
||||||
<el-dropdown @command="handleMoreActionCommand">
|
<el-dropdown @command="handleMoreActionCommand">
|
||||||
<span class="el-dropdown-link-more">
|
<span class="el-dropdown-link-more">
|
||||||
更多
|
{{ $t('common.more') }}
|
||||||
<el-icon class="el-icon--right">
|
<el-icon class="el-icon--right">
|
||||||
<arrow-down />
|
<arrow-down />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</span>
|
</span>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item :command="{ type: 'dumpDb', data }"> 导出 </el-dropdown-item>
|
<el-dropdown-item :command="{ type: 'dumpDb', data }"> {{ $t('db.dump') }} </el-dropdown-item>
|
||||||
<!-- <el-dropdown-item
|
<!-- <el-dropdown-item
|
||||||
:command="{ type: 'backupDb', data }"
|
:command="{ type: 'backupDb', data }"
|
||||||
v-if="actionBtns[perms.backupDb] && supportAction('backupDb', data.type)"
|
v-if="actionBtns[perms.backupDb] && supportAction('backupDb', data.type)"
|
||||||
@@ -106,18 +106,18 @@
|
|||||||
</page-table>
|
</page-table>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
|
|
||||||
<el-dialog width="750px" :title="`${exportDialog.db} 数据库导出`" v-model="exportDialog.visible">
|
<el-dialog width="750px" :title="`${exportDialog.db} DB Dump`" v-model="exportDialog.visible">
|
||||||
<el-row justify="space-between">
|
<el-row justify="space-between">
|
||||||
<el-col :span="9">
|
<el-col :span="9">
|
||||||
<el-form-item label="导出内容: ">
|
<el-form-item :label="$t('db.dumpContent')">
|
||||||
<el-checkbox-group v-model="exportDialog.contents" :min="1">
|
<el-checkbox-group v-model="exportDialog.contents" :min="1">
|
||||||
<el-checkbox label="结构" value="结构" />
|
<el-checkbox :label="$t('db.structure')" value="结构" />
|
||||||
<el-checkbox label="数据" value="数据" />
|
<el-checkbox :label="$t('db.data')" value="数据" />
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="9">
|
<el-col :span="9">
|
||||||
<el-form-item label="扩展名: ">
|
<el-form-item :label="$t('db.extName')">
|
||||||
<el-radio-group v-model="exportDialog.extName">
|
<el-radio-group v-model="exportDialog.extName">
|
||||||
<el-radio label="sql" value="sql" />
|
<el-radio label="sql" value="sql" />
|
||||||
<el-radio label="gzip" value="gzip" />
|
<el-radio label="gzip" value="gzip" />
|
||||||
@@ -130,8 +130,8 @@
|
|||||||
<el-transfer
|
<el-transfer
|
||||||
v-model="exportDialog.value"
|
v-model="exportDialog.value"
|
||||||
filterable
|
filterable
|
||||||
filter-placeholder="按数据库名称筛选"
|
:filter-placeholder="$t('db.dbFilterPlacehoder')"
|
||||||
:titles="['全部数据库', '导出数据库']"
|
:titles="[$t('db.allDb'), $t('db.dumpDb')]"
|
||||||
:data="exportDialog.data"
|
:data="exportDialog.data"
|
||||||
max-height="300"
|
max-height="300"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -140,15 +140,15 @@
|
|||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="exportDialog.visible = false">取消</el-button>
|
<el-button @click="exportDialog.visible = false">{{ $t('common.cancel') }}</el-button>
|
||||||
<el-button @click="dumpDbs()" type="primary">确定</el-button>
|
<el-button @click="dumpDbs()" type="primary">{{ $t('common.confirm') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
width="90%"
|
width="90%"
|
||||||
:title="`${sqlExecLogDialog.title} - SQL执行记录`"
|
:title="`${sqlExecLogDialog.title} - SQL`"
|
||||||
:before-close="onBeforeCloseSqlExecDialog"
|
:before-close="onBeforeCloseSqlExecDialog"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
v-model="sqlExecLogDialog.visible"
|
v-model="sqlExecLogDialog.visible"
|
||||||
@@ -157,7 +157,7 @@
|
|||||||
<db-sql-exec-log :db-id="sqlExecLogDialog.dbId" :dbs="sqlExecLogDialog.dbs" />
|
<db-sql-exec-log :db-id="sqlExecLogDialog.dbId" :dbs="sqlExecLogDialog.dbs" />
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog
|
<!-- <el-dialog
|
||||||
width="80%"
|
width="80%"
|
||||||
:title="`${dbBackupDialog.title} - 数据库备份`"
|
:title="`${dbBackupDialog.title} - 数据库备份`"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
@@ -185,7 +185,7 @@
|
|||||||
v-model="dbRestoreDialog.visible"
|
v-model="dbRestoreDialog.visible"
|
||||||
>
|
>
|
||||||
<db-restore-list :dbId="dbRestoreDialog.dbId" :dbNames="dbRestoreDialog.dbs" />
|
<db-restore-list :dbId="dbRestoreDialog.dbId" :dbNames="dbRestoreDialog.dbs" />
|
||||||
</el-dialog>
|
</el-dialog> -->
|
||||||
|
|
||||||
<db-edit
|
<db-edit
|
||||||
@confirm="confirmEditDb"
|
@confirm="confirmEditDb"
|
||||||
@@ -210,18 +210,19 @@ import { hasPerms } from '@/components/auth/auth';
|
|||||||
import DbSqlExecLog from './DbSqlExecLog.vue';
|
import DbSqlExecLog from './DbSqlExecLog.vue';
|
||||||
import { DbType } from './dialect';
|
import { DbType } from './dialect';
|
||||||
import { getDbDialect } from './dialect/index';
|
import { getDbDialect } from './dialect/index';
|
||||||
import DbBackupList from './DbBackupList.vue';
|
|
||||||
import DbBackupHistoryList from './DbBackupHistoryList.vue';
|
|
||||||
import DbRestoreList from './DbRestoreList.vue';
|
|
||||||
import ResourceTags from '../component/ResourceTags.vue';
|
import ResourceTags from '../component/ResourceTags.vue';
|
||||||
import { sleep } from '@/common/utils/loading';
|
import { sleep } from '@/common/utils/loading';
|
||||||
import { DbGetDbNamesMode } from './enums';
|
import { DbGetDbNamesMode } from './enums';
|
||||||
import { DbInst } from './db';
|
import { DbInst } from './db';
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
import DrawerHeader from '@/components/drawer-header/DrawerHeader.vue';
|
import DrawerHeader from '@/components/drawer-header/DrawerHeader.vue';
|
||||||
|
import { useI18nCreateTitle, useI18nDeleteConfirm, useI18nDeleteSuccessMsg, useI18nEditTitle, useI18nSaveSuccessMsg } from '@/hooks/useI18n';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
const DbEdit = defineAsyncComponent(() => import('./DbEdit.vue'));
|
const DbEdit = defineAsyncComponent(() => import('./DbEdit.vue'));
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
instance: {
|
instance: {
|
||||||
type: [Object],
|
type: [Object],
|
||||||
@@ -237,13 +238,13 @@ const dialogVisible = defineModel<boolean>('visible');
|
|||||||
const emit = defineEmits(['cancel']);
|
const emit = defineEmits(['cancel']);
|
||||||
|
|
||||||
const columns = ref([
|
const columns = ref([
|
||||||
TableColumn.new('name', '名称'),
|
TableColumn.new('name', 'common.name'),
|
||||||
TableColumn.new('authCertName', '授权凭证'),
|
TableColumn.new('authCertName', 'db.acName'),
|
||||||
TableColumn.new('getDatabaseMode', '获库方式').typeTag(DbGetDbNamesMode),
|
TableColumn.new('getDatabaseMode', 'db.getDbMode').typeTag(DbGetDbNamesMode),
|
||||||
TableColumn.new('database', '库').isSlot().setMinWidth(80),
|
TableColumn.new('database', 'DB').isSlot().setMinWidth(80),
|
||||||
TableColumn.new('remark', '备注'),
|
TableColumn.new('remark', 'common.remark'),
|
||||||
TableColumn.new('code', '编号'),
|
TableColumn.new('code', 'common.code'),
|
||||||
TableColumn.new('action', '操作').isSlot().setMinWidth(210).fixedRight().alignCenter(),
|
TableColumn.new('action', 'common.operation').isSlot().setMinWidth(210).fixedRight().alignCenter(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const perms = {
|
const perms = {
|
||||||
@@ -319,7 +320,7 @@ const state = reactive({
|
|||||||
dbEditDialog: {
|
dbEditDialog: {
|
||||||
visible: false,
|
visible: false,
|
||||||
data: null as any,
|
data: null as any,
|
||||||
title: '新增数据库',
|
title: '',
|
||||||
},
|
},
|
||||||
filterDb: {
|
filterDb: {
|
||||||
param: '',
|
param: '',
|
||||||
@@ -367,14 +368,14 @@ const editDb = (data: any) => {
|
|||||||
instanceId: props.instance.id,
|
instanceId: props.instance.id,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
state.dbEditDialog.title = data ? '编辑数据库' : '新增数据库';
|
state.dbEditDialog.title = data ? useI18nEditTitle('db.db') : useI18nCreateTitle('db.db');
|
||||||
state.dbEditDialog.visible = true;
|
state.dbEditDialog.visible = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const confirmEditDb = async (db: any) => {
|
const confirmEditDb = async (db: any) => {
|
||||||
db.instanceId = props.instance.id;
|
db.instanceId = props.instance.id;
|
||||||
await dbApi.saveDb.request(db);
|
await dbApi.saveDb.request(db);
|
||||||
ElMessage.success('保存成功');
|
useI18nSaveSuccessMsg();
|
||||||
search();
|
search();
|
||||||
cancelEditDb();
|
cancelEditDb();
|
||||||
};
|
};
|
||||||
@@ -386,15 +387,11 @@ const cancelEditDb = () => {
|
|||||||
|
|
||||||
const deleteDb = async () => {
|
const deleteDb = async () => {
|
||||||
try {
|
try {
|
||||||
await ElMessageBox.confirm(`确定删除【${state.selectionData.map((x: any) => x.name).join(', ')}】库?`, '提示', {
|
await useI18nDeleteConfirm(state.selectionData.map((x: any) => x.name).join('、'));
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning',
|
|
||||||
});
|
|
||||||
for (let db of state.selectionData) {
|
for (let db of state.selectionData) {
|
||||||
await dbApi.deleteDb.request({ id: db.id });
|
await dbApi.deleteDb.request({ id: db.id });
|
||||||
}
|
}
|
||||||
ElMessage.success('删除成功');
|
useI18nDeleteSuccessMsg();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
//
|
//
|
||||||
} finally {
|
} finally {
|
||||||
@@ -480,7 +477,7 @@ const onDumpDbs = async (row: any) => {
|
|||||||
state.exportDialog.value = [];
|
state.exportDialog.value = [];
|
||||||
state.exportDialog.data = data;
|
state.exportDialog.data = data;
|
||||||
state.exportDialog.dbId = row.id;
|
state.exportDialog.dbId = row.id;
|
||||||
state.exportDialog.contents = ['结构', '数据'];
|
state.exportDialog.contents = [t('db.structure'), t('db.data')];
|
||||||
state.exportDialog.extName = 'sql';
|
state.exportDialog.extName = 'sql';
|
||||||
state.exportDialog.visible = true;
|
state.exportDialog.visible = true;
|
||||||
};
|
};
|
||||||
@@ -489,7 +486,7 @@ const onDumpDbs = async (row: any) => {
|
|||||||
* 数据库信息导出
|
* 数据库信息导出
|
||||||
*/
|
*/
|
||||||
const dumpDbs = async () => {
|
const dumpDbs = async () => {
|
||||||
isTrue(state.exportDialog.value.length > 0, '请添加要导出的数据库');
|
isTrue(state.exportDialog.value.length > 0, t('db.noDumpDbMsg'));
|
||||||
let type = 0;
|
let type = 0;
|
||||||
for (let c of state.exportDialog.contents) {
|
for (let c of state.exportDialog.contents) {
|
||||||
if (c == '结构') {
|
if (c == '结构') {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
:columns="columns"
|
:columns="columns"
|
||||||
>
|
>
|
||||||
<template #dbSelect>
|
<template #dbSelect>
|
||||||
<el-select v-model="query.db" placeholder="请选择数据库" filterable clearable>
|
<el-select v-model="query.db" :placeholder="$t('db.selectDbPlaceholder')" filterable clearable>
|
||||||
<el-option v-for="item in dbs" :key="item" :label="`${item}`" :value="item"> </el-option>
|
<el-option v-for="item in dbs" :key="item" :label="`${item}`" :value="item"> </el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
<template #action="{ data }">
|
<template #action="{ data }">
|
||||||
<el-link
|
<el-link
|
||||||
v-if="
|
v-if="
|
||||||
|
data.oldValue != '' &&
|
||||||
data.status == DbSqlExecStatusEnum.Success.value &&
|
data.status == DbSqlExecStatusEnum.Success.value &&
|
||||||
(data.type == DbSqlExecTypeEnum.Update.value || data.type == DbSqlExecTypeEnum.Delete.value)
|
(data.type == DbSqlExecTypeEnum.Update.value || data.type == DbSqlExecTypeEnum.Delete.value)
|
||||||
"
|
"
|
||||||
@@ -27,12 +28,12 @@
|
|||||||
:underline="false"
|
:underline="false"
|
||||||
@click="onShowRollbackSql(data)"
|
@click="onShowRollbackSql(data)"
|
||||||
>
|
>
|
||||||
还原SQL</el-link
|
{{ $t('db.restoreSql') }}</el-link
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
</page-table>
|
</page-table>
|
||||||
|
|
||||||
<el-dialog width="55%" :title="`还原SQL`" v-model="rollbackSqlDialog.visible">
|
<el-dialog width="55%" :title="$t('db.restoreSql')" v-model="rollbackSqlDialog.visible">
|
||||||
<el-input type="textarea" :autosize="{ minRows: 15, maxRows: 30 }" v-model="rollbackSqlDialog.sql" size="small"> </el-input>
|
<el-input type="textarea" :autosize="{ minRows: 15, maxRows: 30 }" v-model="rollbackSqlDialog.sql" size="small"> </el-input>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
@@ -58,23 +59,23 @@ const props = defineProps({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const searchItems = [
|
const searchItems = [
|
||||||
SearchItem.slot('db', '数据库', 'dbSelect'),
|
SearchItem.slot('db', 'db.db', 'dbSelect'),
|
||||||
SearchItem.input('table', '表名'),
|
SearchItem.input('table', 'db.table'),
|
||||||
SearchItem.select('type', '操作类型').withEnum(DbSqlExecTypeEnum),
|
SearchItem.select('type', 'db.stmtType').withEnum(DbSqlExecTypeEnum),
|
||||||
];
|
];
|
||||||
|
|
||||||
const columns = ref([
|
const columns = ref([
|
||||||
TableColumn.new('db', '数据库'),
|
TableColumn.new('db', 'db.db'),
|
||||||
TableColumn.new('table', '表'),
|
TableColumn.new('table', 'db.type'),
|
||||||
TableColumn.new('type', '类型').typeTag(DbSqlExecTypeEnum).setAddWidth(10),
|
TableColumn.new('type', 'db.stmtType').typeTag(DbSqlExecTypeEnum).setAddWidth(10),
|
||||||
TableColumn.new('creator', '执行人'),
|
TableColumn.new('creator', 'db.execUser'),
|
||||||
TableColumn.new('sql', 'SQL').canBeautify(),
|
TableColumn.new('sql', 'SQL').canBeautify(),
|
||||||
TableColumn.new('remark', '备注'),
|
TableColumn.new('remark', 'common.remark'),
|
||||||
TableColumn.new('status', '执行状态').typeTag(DbSqlExecStatusEnum),
|
TableColumn.new('status', 'common.status').typeTag(DbSqlExecStatusEnum),
|
||||||
TableColumn.new('res', '执行结果'),
|
TableColumn.new('res', 'db.execRes'),
|
||||||
TableColumn.new('createTime', '执行时间').isTime(),
|
TableColumn.new('createTime', 'db.execTime').isTime(),
|
||||||
TableColumn.new('oldValue', '原值').canBeautify(),
|
TableColumn.new('oldValue', 'db.oldValue').canBeautify(),
|
||||||
TableColumn.new('action', '操作').isSlot().setMinWidth(90).fixedRight().alignCenter(),
|
TableColumn.new('action', 'common.operation').isSlot().setMinWidth(90).fixedRight().alignCenter(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const pageTableRef: Ref<any> = ref(null);
|
const pageTableRef: Ref<any> = ref(null);
|
||||||
|
|||||||
@@ -1,30 +1,37 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="db-transfer-edit">
|
<div class="db-transfer-edit">
|
||||||
<el-drawer :title="title" v-model="dialogVisible" :before-close="cancel" :destroy-on-close="true" :close-on-click-modal="false" size="40%">
|
<el-drawer :title="title" v-model="dialogVisible" :before-close="cancel" :destroy-on-close="true" :close-on-click-modal="false" size="45%">
|
||||||
<template #header>
|
<template #header>
|
||||||
<DrawerHeader :header="title" :back="cancel" />
|
<DrawerHeader :header="title" :back="cancel" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-form :model="form" ref="dbForm" :rules="rules" label-width="auto">
|
<el-form :model="form" ref="dbForm" :rules="rules" label-width="auto">
|
||||||
<el-divider content-position="left">基本信息</el-divider>
|
<el-divider content-position="left">{{ $t('common.basic') }}</el-divider>
|
||||||
|
|
||||||
<el-form-item prop="taskName" label="任务名" required>
|
<el-form-item prop="taskName" :label="$t('db.taskName')" required>
|
||||||
<el-input v-model.trim="form.taskName" placeholder="请输入任务名" auto-complete="off" />
|
<el-input v-model.trim="form.taskName" auto-complete="off" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-row class="w100">
|
<el-row class="w100">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item prop="status" label="启用状态">
|
<el-form-item prop="status" :label="$t('common.status')">
|
||||||
<el-switch v-model="form.status" inline-prompt active-text="启用" inactive-text="禁用" :active-value="1" :inactive-value="-1" />
|
<el-switch
|
||||||
|
v-model="form.status"
|
||||||
|
inline-prompt
|
||||||
|
:active-text="$t('common.enable')"
|
||||||
|
:inactive-text="$t('common.disable')"
|
||||||
|
:active-value="1"
|
||||||
|
:inactive-value="-1"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item prop="cronAble" label="定时迁移" required>
|
<el-form-item prop="cronAble" :label="$t('db.cronAble')" required>
|
||||||
<el-radio-group v-model="form.cronAble">
|
<el-radio-group v-model="form.cronAble">
|
||||||
<el-radio label="是" :value="1" />
|
<el-radio :label="$t('common.yes')" :value="1" />
|
||||||
<el-radio label="否" :value="-1" />
|
<el-radio :label="$t('common.no')" :value="-1" />
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -35,9 +42,8 @@
|
|||||||
<CrontabInput v-model="form.cron" />
|
<CrontabInput v-model="form.cron" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item prop="srcDbId" label="源数据库" class="w100" required>
|
<el-form-item prop="srcDbId" :label="$t('db.srcDb')" class="w100" required>
|
||||||
<db-select-tree
|
<db-select-tree
|
||||||
placeholder="请选择源数据库"
|
|
||||||
v-model:db-id="form.srcDbId"
|
v-model:db-id="form.srcDbId"
|
||||||
v-model:inst-name="form.srcInstName"
|
v-model:inst-name="form.srcInstName"
|
||||||
v-model:db-name="form.srcDbName"
|
v-model:db-name="form.srcDbName"
|
||||||
@@ -47,18 +53,18 @@
|
|||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item prop="mode" label="迁移方式" required>
|
<el-form-item prop="mode" :label="$t('db.transferMode')" required>
|
||||||
<el-radio-group v-model="form.mode">
|
<el-radio-group v-model="form.mode">
|
||||||
<el-radio label="迁移到数据库" :value="1" />
|
<el-radio :label="$t('db.transfer2Db')" :value="1" />
|
||||||
<el-radio label="迁移到文件(自动命名)" :value="2" />
|
<el-radio :label="$t('db.transfer2File')" :value="2" />
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item v-if="form.mode === 2">
|
<el-form-item v-if="form.mode === 2">
|
||||||
<el-row class="w100">
|
<el-row class="w100">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item prop="targetFileDbType" label="文件数据库类型" :required="form.mode === 2">
|
<el-form-item prop="targetFileDbType" :label="$t('db.dbFileType')" :required="form.mode === 2">
|
||||||
<el-select v-model="form.targetFileDbType" placeholder="数据库类型" clearable filterable>
|
<el-select v-model="form.targetFileDbType" clearable filterable>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="(dbTypeAndDialect, key) in getDbDialectMap()"
|
v-for="(dbTypeAndDialect, key) in getDbDialectMap()"
|
||||||
:key="key"
|
:key="key"
|
||||||
@@ -76,10 +82,10 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="文件保留天数">
|
<el-form-item :label="$t('db.fileSaveDays')">
|
||||||
<el-input-number v-model="form.fileSaveDays" :min="-1" :max="1000">
|
<el-input-number v-model="form.fileSaveDays" :min="-1" :max="1000">
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span>天</span>
|
<span>{{ $t('db.day') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-input-number>
|
</el-input-number>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -87,16 +93,15 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item prop="strategy" label="迁移策略" required>
|
<el-form-item prop="strategy" :label="$t('db.transferStrategy')" required>
|
||||||
<el-radio-group v-model="form.strategy">
|
<el-radio-group v-model="form.strategy">
|
||||||
<el-radio label="全量" :value="1" />
|
<el-radio :label="$t('db.transferFull')" :value="1" />
|
||||||
<el-radio label="增量(暂不可用)" :value="2" disabled />
|
<el-radio :label="$t('db.transferIncrement')" :value="2" disabled />
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item v-if="form.mode == 1" prop="targetDbId" label="目标数据库" class="w100" :required="form.mode === 1">
|
<el-form-item v-if="form.mode == 1" prop="targetDbId" :label="$t('db.targetDb')" class="w100" :required="form.mode === 1">
|
||||||
<db-select-tree
|
<db-select-tree
|
||||||
placeholder="请选择目标数据库"
|
|
||||||
v-model:db-id="form.targetDbId"
|
v-model:db-id="form.targetDbId"
|
||||||
v-model:inst-name="form.targetInstName"
|
v-model:inst-name="form.targetInstName"
|
||||||
v-model:db-name="form.targetDbName"
|
v-model:db-name="form.targetDbName"
|
||||||
@@ -106,17 +111,17 @@
|
|||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item prop="nameCase" label="转换表、字段名" required>
|
<el-form-item prop="nameCase" :label="$t('db.nameCase')" required>
|
||||||
<el-radio-group v-model="form.nameCase">
|
<el-radio-group v-model="form.nameCase">
|
||||||
<el-radio label="无" :value="1" />
|
<el-radio :label="$t('db.none')" :value="1" />
|
||||||
<el-radio label="大写" :value="2" />
|
<el-radio :label="$t('db.upper')" :value="2" />
|
||||||
<el-radio label="小写" :value="3" />
|
<el-radio :label="$t('db.lower')" :value="3" />
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-divider content-position="left">数据库对象</el-divider>
|
<el-divider content-position="left">{{ $t('db.dbObj') }}</el-divider>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-input v-model="state.filterSrcTableText" placeholder="过滤表" size="small" />
|
<el-input v-model="state.filterSrcTableText" placeholder="filter table" size="small" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item class="w100">
|
<el-form-item class="w100">
|
||||||
<el-tree
|
<el-tree
|
||||||
@@ -136,8 +141,8 @@
|
|||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div>
|
<div>
|
||||||
<el-button @click="cancel()">取 消</el-button>
|
<el-button @click="cancel()">{{ $t('common.cancel') }}</el-button>
|
||||||
<el-button type="primary" :loading="saveBtnLoading" @click="btnOk">确 定</el-button>
|
<el-button type="primary" :loading="saveBtnLoading" @click="btnOk">{{ $t('common.confirm') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
@@ -154,6 +159,10 @@ import { getDbDialect, getDbDialectMap } from '@/views/ops/db/dialect';
|
|||||||
import SvgIcon from '@/components/svgIcon/index.vue';
|
import SvgIcon from '@/components/svgIcon/index.vue';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import DrawerHeader from '@/components/drawer-header/DrawerHeader.vue';
|
import DrawerHeader from '@/components/drawer-header/DrawerHeader.vue';
|
||||||
|
import { useI18nFormValidate, useI18nPleaseInput, useI18nPleaseSelect, useI18nSaveSuccessMsg } from '@/hooks/useI18n';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
@@ -173,35 +182,35 @@ const rules = {
|
|||||||
taskName: [
|
taskName: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入任务名',
|
message: useI18nPleaseInput('db.taskName'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
srcDbId: [
|
srcDbId: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请选择源库',
|
message: useI18nPleaseSelect('db.srcDb'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
targetDbId: [
|
targetDbId: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请选择目标库',
|
message: useI18nPleaseSelect('db.targetDb'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
targetFileDbType: [
|
targetFileDbType: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请选择目标文件语言类型',
|
message: useI18nPleaseSelect('db.dbFileType'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
cron: [
|
cron: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请选择cron表达式',
|
message: useI18nPleaseSelect('cron'),
|
||||||
trigger: ['change', 'blur'],
|
trigger: ['change', 'blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -262,12 +271,12 @@ const state = reactive({
|
|||||||
srcTableTree: [
|
srcTableTree: [
|
||||||
{
|
{
|
||||||
id: 'tab-check',
|
id: 'tab-check',
|
||||||
label: '表',
|
label: t('db.table'),
|
||||||
children: [
|
children: [
|
||||||
{ id: 'all', label: '全部表(*)' },
|
{ id: 'all', label: `${t('db.allTable')}(*)` },
|
||||||
{
|
{
|
||||||
id: 'table-list',
|
id: 'table-list',
|
||||||
label: '自定义',
|
label: t('db.custom'),
|
||||||
disabled: srcTableListDisabled,
|
disabled: srcTableListDisabled,
|
||||||
children: [] as any[],
|
children: [] as any[],
|
||||||
},
|
},
|
||||||
@@ -394,12 +403,7 @@ const getCheckedKeys = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const btnOk = async () => {
|
const btnOk = async () => {
|
||||||
dbForm.value.validate(async (valid: boolean) => {
|
await useI18nFormValidate(dbForm);
|
||||||
if (!valid) {
|
|
||||||
ElMessage.error('请正确填写信息');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.submitForm = await getReqForm();
|
state.submitForm = await getReqForm();
|
||||||
|
|
||||||
let checkedKeys = getCheckedKeys();
|
let checkedKeys = getCheckedKeys();
|
||||||
@@ -408,15 +412,14 @@ const btnOk = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!state.submitForm.checkedKeys) {
|
if (!state.submitForm.checkedKeys) {
|
||||||
ElMessage.error('请选择需要迁移的表');
|
ElMessage.error(t('db.noTransferTableMsg'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
await saveExec();
|
await saveExec();
|
||||||
ElMessage.success('保存成功');
|
useI18nSaveSuccessMsg();
|
||||||
emit('val-change', state.form);
|
emit('val-change', state.form);
|
||||||
cancel();
|
cancel();
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const cancel = () => {
|
const cancel = () => {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user