mirror of https://github.com/certd/certd
perf: 优化中英文翻译与切换
parent
082f47663d
commit
acaa8b1731
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<AConfigProvider :locale="locale" :theme="tokenTheme">
|
||||
<AConfigProvider :locale="antdvLocale" :theme="tokenTheme">
|
||||
<FsFormProvider>
|
||||
<contextHolder />
|
||||
<router-view />
|
||||
|
@ -8,24 +8,22 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, provide, ref } from "vue";
|
||||
import "dayjs/locale/zh-cn";
|
||||
import "dayjs/locale/en";
|
||||
import dayjs from "dayjs";
|
||||
import { usePreferences, preferences } from "/@/vben/preferences";
|
||||
import { computed, provide, ref } from "vue";
|
||||
import { preferences, usePreferences } from "/@/vben/preferences";
|
||||
import { useAntdDesignTokens } from "/@/vben/hooks";
|
||||
import { theme } from "ant-design-vue";
|
||||
import { Modal, theme } from "ant-design-vue";
|
||||
import AConfigProvider from "ant-design-vue/es/config-provider";
|
||||
import { Modal } from "ant-design-vue";
|
||||
import MaxKBChat from "/@/components/ai/index.vue";
|
||||
import { util } from "/@/utils";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import { antdvLocale } from "./locales/antdv";
|
||||
import { setI18nLanguage } from "/@/locales";
|
||||
defineOptions({
|
||||
name: "App",
|
||||
});
|
||||
|
||||
const [modal, contextHolder] = Modal.useModal();
|
||||
provide("modal", modal);
|
||||
|
||||
const locale = preferences.app.locale;
|
||||
setI18nLanguage(locale);
|
||||
|
||||
const { isDark } = usePreferences();
|
||||
const { tokens } = useAntdDesignTokens();
|
||||
|
@ -43,5 +41,4 @@ const tokenTheme = computed(() => {
|
|||
token: tokens,
|
||||
};
|
||||
});
|
||||
|
||||
</script>
|
||||
|
|
|
@ -17,95 +17,91 @@ const userStore = useUserStore();
|
|||
|
||||
const router = useRouter();
|
||||
const menus = computed(() => [
|
||||
{
|
||||
handler: () => {
|
||||
router.push("/certd/mine/user-profile");
|
||||
},
|
||||
icon: "fa-solid:book",
|
||||
text: t("certd.accountInfo"),
|
||||
},
|
||||
{
|
||||
handler: () => {
|
||||
router.push("/certd/mine/security");
|
||||
},
|
||||
icon: "fluent:shield-keyhole-16-regular",
|
||||
text: t("certd.securitySettings"),
|
||||
},
|
||||
{
|
||||
handler: () => {
|
||||
router.push("/certd/mine/user-profile");
|
||||
},
|
||||
icon: "fa-solid:book",
|
||||
text: t("certd.accountInfo"),
|
||||
},
|
||||
{
|
||||
handler: () => {
|
||||
router.push("/certd/mine/security");
|
||||
},
|
||||
icon: "fluent:shield-keyhole-16-regular",
|
||||
text: t("certd.securitySettings"),
|
||||
},
|
||||
]);
|
||||
|
||||
|
||||
const avatar = computed(() => {
|
||||
const avt = userStore.getUserInfo?.avatar;
|
||||
return avt ? `/api/basic/file/download?key=${avt}` : "";
|
||||
const avt = userStore.getUserInfo?.avatar;
|
||||
return avt ? `/api/basic/file/download?key=${avt}` : "";
|
||||
});
|
||||
|
||||
async function handleLogout() {
|
||||
await userStore.logout(true);
|
||||
await userStore.logout(true);
|
||||
}
|
||||
|
||||
const settingStore = useSettingStore();
|
||||
|
||||
const sysPublic = computed(() => {
|
||||
return settingStore.sysPublic;
|
||||
return settingStore.sysPublic;
|
||||
});
|
||||
const siteInfo = computed(() => {
|
||||
return settingStore.siteInfo;
|
||||
return settingStore.siteInfo;
|
||||
});
|
||||
|
||||
onErrorCaptured(e => {
|
||||
console.error("ErrorCaptured:", e);
|
||||
// notification.error({ message: e.message });
|
||||
//阻止错误向上传递
|
||||
return false;
|
||||
console.error("ErrorCaptured:", e);
|
||||
// notification.error({ message: e.message });
|
||||
//阻止错误向上传递
|
||||
return false;
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
await settingStore.checkUrlBound();
|
||||
await settingStore.checkUrlBound();
|
||||
});
|
||||
|
||||
function goGithub() {
|
||||
window.open("https://github.com/certd/certd");
|
||||
window.open("https://github.com/certd/certd");
|
||||
}
|
||||
const settingsStore = useSettingStore();
|
||||
const chatBox = ref();
|
||||
const openChat = (q: string) => {
|
||||
chatBox.value.openChat({ q });
|
||||
chatBox.value.openChat({ q });
|
||||
};
|
||||
provide("fn:ai.open", openChat);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BasicLayout @clear-preferences-and-logout="handleLogout">
|
||||
<template #user-dropdown>
|
||||
<UserDropdown :avatar="avatar" :menus="menus"
|
||||
:text="userStore.userInfo?.nickName || userStore.userInfo?.username" description="" tag-text=""
|
||||
@logout="handleLogout" />
|
||||
</template>
|
||||
<template #lock-screen>
|
||||
<LockScreen :avatar @to-login="handleLogout" />
|
||||
</template>
|
||||
<template #header-right-0>
|
||||
<div v-if="!settingStore.isComm"
|
||||
class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full hidden md:block">
|
||||
<tutorial-button class="flex-center header-btn" />
|
||||
</div>
|
||||
<div class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full">
|
||||
<vip-button class="flex-center header-btn" mode="nav" />
|
||||
</div>
|
||||
<div v-if="!settingStore.isComm" class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full">
|
||||
<fs-button shape="circle" type="text" icon="ion:logo-github" :text="null" @click="goGithub" />
|
||||
</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<PageFooter></PageFooter>
|
||||
<MaxKBChat v-if="settingsStore.sysPublic.aiChatEnabled !== false" ref="chatBox" />
|
||||
</template>
|
||||
</BasicLayout>
|
||||
<BasicLayout @clear-preferences-and-logout="handleLogout">
|
||||
<template #user-dropdown>
|
||||
<UserDropdown :avatar="avatar" :menus="menus" :text="userStore.userInfo?.nickName || userStore.userInfo?.username" description="" tag-text="" @logout="handleLogout" />
|
||||
</template>
|
||||
<template #lock-screen>
|
||||
<LockScreen :avatar @to-login="handleLogout" />
|
||||
</template>
|
||||
<template #header-right-0>
|
||||
<div v-if="!settingStore.isComm" class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full hidden md:block">
|
||||
<tutorial-button class="flex-center header-btn" />
|
||||
</div>
|
||||
<div class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full">
|
||||
<vip-button class="flex-center header-btn" mode="nav" />
|
||||
</div>
|
||||
<div v-if="!settingStore.isComm" class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full">
|
||||
<fs-button shape="circle" type="text" icon="ion:logo-github" :text="null" @click="goGithub" />
|
||||
</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<PageFooter></PageFooter>
|
||||
<MaxKBChat v-if="settingsStore.sysPublic.aiChatEnabled !== false" ref="chatBox" />
|
||||
</template>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
.header-btn {
|
||||
font-size: 14px;
|
||||
padding: 5px;
|
||||
font-size: 14px;
|
||||
padding: 5px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import { ref } from "vue";
|
||||
import "dayjs/locale/zh-cn";
|
||||
import "dayjs/locale/en";
|
||||
import zhCN from "ant-design-vue/es/locale/zh_CN";
|
||||
import enUS from "ant-design-vue/es/locale/en_US";
|
||||
import dayjs from "dayjs";
|
||||
export const antdvLocale = ref(zhCN);
|
||||
|
||||
export async function setAntdvLocale(value: string) {
|
||||
console.log("locale changed:", value);
|
||||
if (value.startsWith("zh")) {
|
||||
dayjs.locale("zh-cn");
|
||||
antdvLocale.value = zhCN;
|
||||
} else {
|
||||
dayjs.locale("en");
|
||||
antdvLocale.value = enUS;
|
||||
}
|
||||
}
|
|
@ -1,24 +1,24 @@
|
|||
import type { App } from "vue";
|
||||
import type { Locale } from "vue-i18n";
|
||||
|
||||
import { setAntdvLocale } from "./antdv";
|
||||
import type { ImportLocaleFn, LoadMessageFn, LocaleSetupOptions, SupportedLanguagesType } from "./typing";
|
||||
|
||||
import { unref } from "vue";
|
||||
import { createI18n } from "vue-i18n";
|
||||
import en_US from './langs/en-US/index';
|
||||
import zh_CH from './langs/zh-CN/index';
|
||||
import en_US from "./langs/en-US/index";
|
||||
import zh_CN from "./langs/zh-CN/index";
|
||||
|
||||
import { useSimpleLocale } from "/@/vben/composables";
|
||||
|
||||
const i18n = createI18n({
|
||||
globalInjection: true,
|
||||
legacy: false,
|
||||
fallbackLocale: 'en_US',
|
||||
locale: 'en_US',
|
||||
messages: {
|
||||
zh_CH: zh_CH,
|
||||
en_US: en_US
|
||||
}
|
||||
globalInjection: true,
|
||||
legacy: false,
|
||||
fallbackLocale: "en-US",
|
||||
locale: "en-US",
|
||||
messages: {
|
||||
"zh-CN": zh_CN,
|
||||
"en-US": en_US,
|
||||
},
|
||||
});
|
||||
|
||||
const modules = import.meta.glob("./langs/**/*.json");
|
||||
|
@ -33,15 +33,15 @@ let loadMessages: LoadMessageFn;
|
|||
* @param modules
|
||||
*/
|
||||
function loadLocalesMap(modules: Record<string, () => Promise<unknown>>) {
|
||||
const localesMap: Record<Locale, ImportLocaleFn> = {};
|
||||
const localesMap: Record<Locale, ImportLocaleFn> = {};
|
||||
|
||||
for (const [path, loadLocale] of Object.entries(modules)) {
|
||||
const key = path.match(/([\w-]*)\.(json)/)?.[1];
|
||||
if (key) {
|
||||
localesMap[key] = loadLocale as ImportLocaleFn;
|
||||
}
|
||||
}
|
||||
return localesMap;
|
||||
for (const [path, loadLocale] of Object.entries(modules)) {
|
||||
const key = path.match(/([\w-]*)\.(json)/)?.[1];
|
||||
if (key) {
|
||||
localesMap[key] = loadLocale as ImportLocaleFn;
|
||||
}
|
||||
}
|
||||
return localesMap;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,37 +51,37 @@ function loadLocalesMap(modules: Record<string, () => Promise<unknown>>) {
|
|||
* @returns A map of locales to their corresponding import functions
|
||||
*/
|
||||
function loadLocalesMapFromDir(regexp: RegExp, modules: Record<string, () => Promise<unknown>>): Record<Locale, ImportLocaleFn> {
|
||||
const localesRaw: Record<Locale, Record<string, () => Promise<unknown>>> = {};
|
||||
const localesMap: Record<Locale, ImportLocaleFn> = {};
|
||||
const localesRaw: Record<Locale, Record<string, () => Promise<unknown>>> = {};
|
||||
const localesMap: Record<Locale, ImportLocaleFn> = {};
|
||||
|
||||
// Iterate over the modules to extract language and file names
|
||||
for (const path in modules) {
|
||||
const match = path.match(regexp);
|
||||
if (match) {
|
||||
const [_, locale, fileName] = match;
|
||||
if (locale && fileName) {
|
||||
if (!localesRaw[locale]) {
|
||||
localesRaw[locale] = {};
|
||||
}
|
||||
if (modules[path]) {
|
||||
localesRaw[locale][fileName] = modules[path];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Iterate over the modules to extract language and file names
|
||||
for (const path in modules) {
|
||||
const match = path.match(regexp);
|
||||
if (match) {
|
||||
const [_, locale, fileName] = match;
|
||||
if (locale && fileName) {
|
||||
if (!localesRaw[locale]) {
|
||||
localesRaw[locale] = {};
|
||||
}
|
||||
if (modules[path]) {
|
||||
localesRaw[locale][fileName] = modules[path];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert raw locale data into async import functions
|
||||
for (const [locale, files] of Object.entries(localesRaw)) {
|
||||
localesMap[locale] = async () => {
|
||||
const messages: Record<string, any> = {};
|
||||
for (const [fileName, importFn] of Object.entries(files)) {
|
||||
messages[fileName] = ((await importFn()) as any)?.default;
|
||||
}
|
||||
return { default: messages };
|
||||
};
|
||||
}
|
||||
// Convert raw locale data into async import functions
|
||||
for (const [locale, files] of Object.entries(localesRaw)) {
|
||||
localesMap[locale] = async () => {
|
||||
const messages: Record<string, any> = {};
|
||||
for (const [fileName, importFn] of Object.entries(files)) {
|
||||
messages[fileName] = ((await importFn()) as any)?.default;
|
||||
}
|
||||
return { default: messages };
|
||||
};
|
||||
}
|
||||
|
||||
return localesMap;
|
||||
return localesMap;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,24 +89,26 @@ function loadLocalesMapFromDir(regexp: RegExp, modules: Record<string, () => Pro
|
|||
* @param locale
|
||||
*/
|
||||
function setI18nLanguage(locale: Locale) {
|
||||
i18n.global.locale.value = locale;
|
||||
// setAntdvLocale(locale);
|
||||
//@ts-ignore
|
||||
i18n.global.locale.value = locale;
|
||||
|
||||
document?.querySelector("html")?.setAttribute("lang", locale);
|
||||
document?.querySelector("html")?.setAttribute("lang", locale);
|
||||
}
|
||||
|
||||
async function setupI18n(app: App, options: LocaleSetupOptions = {}) {
|
||||
const { defaultLocale = "en-US" } = options;
|
||||
// app可以自行扩展一些第三方库和组件库的国际化
|
||||
loadMessages = options.loadMessages || (async () => ({}));
|
||||
app.use(i18n);
|
||||
await loadLocaleMessages(defaultLocale);
|
||||
const { defaultLocale = "en-US" } = options;
|
||||
// app可以自行扩展一些第三方库和组件库的国际化
|
||||
loadMessages = options.loadMessages || (async () => ({}));
|
||||
app.use(i18n);
|
||||
await loadLocaleMessages(defaultLocale);
|
||||
|
||||
// 在控制台打印警告
|
||||
i18n.global.setMissingHandler((locale, key) => {
|
||||
if (options.missingWarn && key.includes(".")) {
|
||||
console.warn(`[intlify] Not found '${key}' key in '${locale}' locale messages.`);
|
||||
}
|
||||
});
|
||||
// 在控制台打印警告
|
||||
i18n.global.setMissingHandler((locale, key) => {
|
||||
if (options.missingWarn && key.includes(".")) {
|
||||
console.warn(`[intlify] Not found '${key}' key in '${locale}' locale messages.`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -114,22 +116,22 @@ async function setupI18n(app: App, options: LocaleSetupOptions = {}) {
|
|||
* @param lang
|
||||
*/
|
||||
async function loadLocaleMessages(lang: SupportedLanguagesType) {
|
||||
if (unref(i18n.global.locale) === lang) {
|
||||
return setI18nLanguage(lang);
|
||||
}
|
||||
setSimpleLocale(lang);
|
||||
if (unref(i18n.global.locale) === lang) {
|
||||
return setI18nLanguage(lang);
|
||||
}
|
||||
setSimpleLocale(lang);
|
||||
|
||||
const message = await localesMap[lang]?.();
|
||||
const message = await localesMap[lang]?.();
|
||||
|
||||
if (message?.default) {
|
||||
i18n.global.setLocaleMessage(lang, message.default);
|
||||
}
|
||||
if (message?.default) {
|
||||
//@ts-ignore
|
||||
i18n.global.setLocaleMessage(lang, message.default);
|
||||
}
|
||||
|
||||
const mergeMessage = await loadMessages(lang);
|
||||
i18n.global.mergeLocaleMessage(lang, mergeMessage);
|
||||
const mergeMessage = await loadMessages(lang);
|
||||
i18n.global.mergeLocaleMessage(lang, mergeMessage);
|
||||
|
||||
return setI18nLanguage(lang);
|
||||
return setI18nLanguage(lang);
|
||||
}
|
||||
|
||||
export { i18n, loadLocaleMessages, loadLocalesMap, loadLocalesMapFromDir, setupI18n };
|
||||
export { i18n, loadLocaleMessages, loadLocalesMap, loadLocalesMapFromDir, setupI18n, setI18nLanguage };
|
||||
export default i18n;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { i18n, loadLocaleMessages, loadLocalesMap, loadLocalesMapFromDir, setupI18n } from "./i18n";
|
||||
import { i18n, loadLocaleMessages, loadLocalesMap, loadLocalesMapFromDir, setupI18n, setI18nLanguage } from "./i18n";
|
||||
|
||||
const $t = i18n.global.t;
|
||||
const $te = i18n.global.te;
|
||||
|
||||
export { $t, $te, i18n, loadLocaleMessages, loadLocalesMap, loadLocalesMapFromDir, setupI18n };
|
||||
export { $t, $te, i18n, loadLocaleMessages, loadLocalesMap, loadLocalesMapFromDir, setupI18n, setI18nLanguage };
|
||||
export { type ImportLocaleFn, type LocaleSetupOptions, type SupportedLanguagesType } from "./typing";
|
||||
// export type { CompileError } from "@intlify/core-base";
|
||||
|
||||
|
|
|
@ -1,84 +1,84 @@
|
|||
export default {
|
||||
"welcomeBack": "Welcome Back",
|
||||
"pageTitle": "Plug-and-play Admin system",
|
||||
"pageDesc": "Efficient, versatile frontend template",
|
||||
"loginSuccess": "Login Successful",
|
||||
"loginSuccessDesc": "Welcome Back",
|
||||
"loginSubtitle": "Enter your account details to manage your projects",
|
||||
"selectAccount": "Quick Select Account",
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"usernameTip": "Please enter username",
|
||||
"passwordErrorTip": "Password is incorrect",
|
||||
"passwordTip": "Please enter password",
|
||||
"verifyRequiredTip": "Please complete the verification first",
|
||||
"rememberMe": "Remember Me",
|
||||
"createAnAccount": "Create an Account",
|
||||
"createAccount": "Create Account",
|
||||
"alreadyHaveAccount": "Already have an account?",
|
||||
"accountTip": "Don't have an account?",
|
||||
"signUp": "Sign Up",
|
||||
"signUpSubtitle": "Make managing your applications simple and fun",
|
||||
"confirmPassword": "Confirm Password",
|
||||
"confirmPasswordTip": "The passwords do not match",
|
||||
"agree": "I agree to",
|
||||
"privacyPolicy": "Privacy-policy",
|
||||
"terms": "Terms",
|
||||
"agreeTip": "Please agree to the Privacy Policy and Terms",
|
||||
"goToLogin": "Login instead",
|
||||
"passwordStrength": "Use 8 or more characters with a mix of letters, numbers & symbols",
|
||||
"forgetPassword": "Forget Password?",
|
||||
"forgetPasswordSubtitle": "Enter your email and we'll send you instructions to reset your password",
|
||||
"emailTip": "Please enter email",
|
||||
"emailValidErrorTip": "The email format you entered is incorrect",
|
||||
"sendResetLink": "Send Reset Link",
|
||||
"email": "Email",
|
||||
"qrcodeSubtitle": "Scan the QR code with your phone to login",
|
||||
"qrcodePrompt": "Click 'Confirm' after scanning to complete login",
|
||||
"qrcodeLogin": "QR Code Login",
|
||||
"codeSubtitle": "Enter your phone number to start managing your project",
|
||||
"code": "Security code",
|
||||
"codeTip": "Security code required {0} characters",
|
||||
"mobile": "Mobile",
|
||||
"mobileLogin": "Mobile Login",
|
||||
"mobileTip": "Please enter mobile number",
|
||||
"mobileErrortip": "The phone number format is incorrect",
|
||||
"sendCode": "Get Security code",
|
||||
"sendText": "Resend in {0}s",
|
||||
"thirdPartyLogin": "Or continue with",
|
||||
"loginAgainTitle": "Please Log In Again",
|
||||
"loginAgainSubTitle": "Your login session has expired. Please log in again to continue.",
|
||||
"layout": {
|
||||
"center": "Align Center",
|
||||
"alignLeft": "Align Left",
|
||||
"alignRight": "Align Right"
|
||||
},
|
||||
usernamePlaceholder: 'Please enter username/email/phone number',
|
||||
passwordPlaceholder: 'Please enter your password',
|
||||
mobilePlaceholder: 'Please enter your mobile number',
|
||||
loginButton: 'Log In',
|
||||
forgotAdminPassword: 'Forgot admin password?',
|
||||
registerLink: 'Register',
|
||||
welcomeBack: "Welcome Back",
|
||||
pageTitle: "Plug-and-play Admin system",
|
||||
pageDesc: "Efficient, versatile frontend template",
|
||||
loginSuccess: "Login Successful",
|
||||
loginSuccessDesc: "Welcome Back",
|
||||
loginSubtitle: "Enter your account details to manage your projects",
|
||||
selectAccount: "Quick Select Account",
|
||||
username: "Username",
|
||||
password: "Password",
|
||||
usernameTip: "Please enter username",
|
||||
passwordErrorTip: "Password is incorrect",
|
||||
passwordTip: "Please enter password",
|
||||
verifyRequiredTip: "Please complete the verification first",
|
||||
rememberMe: "Remember Me",
|
||||
createAnAccount: "Create an Account",
|
||||
createAccount: "Create Account",
|
||||
alreadyHaveAccount: "Already have an account?",
|
||||
accountTip: "Don't have an account?",
|
||||
signUp: "Sign Up",
|
||||
signUpSubtitle: "Make managing your applications simple and fun",
|
||||
confirmPassword: "Confirm Password",
|
||||
confirmPasswordTip: "The passwords do not match",
|
||||
agree: "I agree to",
|
||||
privacyPolicy: "Privacy-policy",
|
||||
terms: "Terms",
|
||||
agreeTip: "Please agree to the Privacy Policy and Terms",
|
||||
goToLogin: "Login instead",
|
||||
passwordStrength: "Use 8 or more characters with a mix of letters, numbers & symbols",
|
||||
forgetPassword: "Forget Password?",
|
||||
forgetPasswordSubtitle: "Enter your email and we'll send you instructions to reset your password",
|
||||
emailTip: "Please enter email",
|
||||
emailValidErrorTip: "The email format you entered is incorrect",
|
||||
sendResetLink: "Send Reset Link",
|
||||
email: "Email",
|
||||
qrcodeSubtitle: "Scan the QR code with your phone to login",
|
||||
qrcodePrompt: "Click 'Confirm' after scanning to complete login",
|
||||
qrcodeLogin: "QR Code Login",
|
||||
codeSubtitle: "Enter your phone number to start managing your project",
|
||||
code: "Security code",
|
||||
codeTip: "Security code required {0} characters",
|
||||
mobile: "Mobile",
|
||||
mobileLogin: "Mobile Login",
|
||||
mobileTip: "Please enter mobile number",
|
||||
mobileErrortip: "The phone number format is incorrect",
|
||||
sendCode: "Get Security code",
|
||||
sendText: "Resend in {0}s",
|
||||
thirdPartyLogin: "Or continue with",
|
||||
loginAgainTitle: "Please Log In Again",
|
||||
loginAgainSubTitle: "Your login session has expired. Please log in again to continue.",
|
||||
layout: {
|
||||
center: "Align Center",
|
||||
alignLeft: "Align Left",
|
||||
alignRight: "Align Right",
|
||||
},
|
||||
usernamePlaceholder: "Please enter username/email/phone number",
|
||||
passwordPlaceholder: "Please enter your password",
|
||||
mobilePlaceholder: "Please enter your mobile number",
|
||||
loginButton: "Log In",
|
||||
forgotAdminPassword: "Forgot admin password?",
|
||||
registerLink: "Register",
|
||||
|
||||
smsTab: 'Login via SMS code',
|
||||
passwordTab: 'Password login',
|
||||
title: 'Change Password',
|
||||
weakPasswordWarning: 'For your account security, please change your password immediately',
|
||||
changeNow: 'Change Now',
|
||||
successMessage: 'Changed successfully',
|
||||
oldPassword: 'Old Password',
|
||||
oldPasswordRequired: 'Please enter the old password',
|
||||
newPassword: 'New Password',
|
||||
newPasswordRequired: 'Please enter the new password',
|
||||
confirmNewPassword: 'Confirm New Password',
|
||||
confirmNewPasswordRequired: 'Please confirm the new password',
|
||||
changePasswordButton: 'Change Password',
|
||||
enterPassword: "Please enter the password",
|
||||
newPasswordNotSameOld: "The new password cannot be the same as the old password",
|
||||
enterPasswordAgain: "Please enter the password again",
|
||||
passwordsNotMatch: "The two passwords do not match!",
|
||||
avatar: "Avatar",
|
||||
nickName: "Nickname",
|
||||
phoneNumber: "Phone Number",
|
||||
changePassword: "Change Password",
|
||||
}
|
||||
smsTab: "Login via SMS code",
|
||||
passwordTab: "Password login",
|
||||
title: "Change Password",
|
||||
weakPasswordWarning: "For your account security, please change your password immediately",
|
||||
changeNow: "Change Now",
|
||||
successMessage: "Changed successfully",
|
||||
oldPassword: "Old Password",
|
||||
oldPasswordRequired: "Please enter the old password",
|
||||
newPassword: "New Password",
|
||||
newPasswordRequired: "Please enter the new password",
|
||||
confirmNewPassword: "Confirm New Password",
|
||||
confirmNewPasswordRequired: "Please confirm the new password",
|
||||
changePasswordButton: "Change Password",
|
||||
enterPassword: "Please enter the password",
|
||||
newPasswordNotSameOld: "The new password cannot be the same as the old password",
|
||||
enterPasswordAgain: "Please enter the password again",
|
||||
passwordsNotMatch: "The two passwords do not match!",
|
||||
avatar: "Avatar",
|
||||
nickName: "Nickname",
|
||||
phoneNumber: "Phone Number",
|
||||
changePassword: "Change Password",
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,22 +1,22 @@
|
|||
export default {
|
||||
"back": "Back",
|
||||
"backToHome": "Back To Home",
|
||||
"login": "Login",
|
||||
"logout": "Logout",
|
||||
"prompt": "Prompt",
|
||||
"cancel": "Cancel",
|
||||
"confirm": "Confirm",
|
||||
"reset": "Reset",
|
||||
"noData": "No Data",
|
||||
"refresh": "Refresh",
|
||||
"loadingMenu": "Loading Menu",
|
||||
"query": "Search",
|
||||
"search": "Search",
|
||||
"enabled": "Enabled",
|
||||
"disabled": "Disabled",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"create": "Create",
|
||||
"yes": "Yes",
|
||||
"no": "No"
|
||||
}
|
||||
back: "Back",
|
||||
backToHome: "Back To Home",
|
||||
login: "Login",
|
||||
logout: "Logout",
|
||||
prompt: "Prompt",
|
||||
cancel: "Cancel",
|
||||
confirm: "Confirm",
|
||||
reset: "Reset",
|
||||
noData: "No Data",
|
||||
refresh: "Refresh",
|
||||
loadingMenu: "Loading Menu",
|
||||
query: "Search",
|
||||
search: "Search",
|
||||
enabled: "Enabled",
|
||||
disabled: "Disabled",
|
||||
edit: "Edit",
|
||||
delete: "Delete",
|
||||
create: "Create",
|
||||
yes: "Yes",
|
||||
no: "No",
|
||||
};
|
||||
|
|
|
@ -1,71 +1,71 @@
|
|||
export default {
|
||||
createCertPipeline: {
|
||||
title: "Create Certificate Application Pipeline",
|
||||
description: "Demonstrate how to configure a certificate application task",
|
||||
items: {
|
||||
tutorialTitle: "Tutorial Demo Content",
|
||||
tutorialDesc1: "This tutorial demonstrates how to automatically apply for a certificate and deploy it to Nginx",
|
||||
tutorialDesc2: "Only 3 steps, fully automatic application and deployment",
|
||||
createTitle: "Create Certificate Pipeline",
|
||||
createDesc: "Click to add a certificate pipeline and fill in the certificate application information",
|
||||
successTitle: "Pipeline Created Successfully",
|
||||
successDesc: "Click manual trigger to apply for the certificate",
|
||||
nextTitle: "Next, demonstrate how to automatically deploy the certificate",
|
||||
nextDesc: "If you only need to apply for a certificate, you can stop here",
|
||||
},
|
||||
},
|
||||
buttons: {
|
||||
prev: "Previous Step",
|
||||
next: "Next Step",
|
||||
},
|
||||
addDeployTask: {
|
||||
title: "Add Deployment Certificate Task",
|
||||
description: "Demonstrate deployment of certificate to Nginx",
|
||||
items: {
|
||||
addTaskTitle: "Add Certificate Deployment Task",
|
||||
addTaskDesc1: "Demonstrate automatic deployment of certificate to nginx",
|
||||
addTaskDesc2: "Our system provides numerous deployment plugins to meet your needs",
|
||||
fillParamsTitle: "Fill Task Parameters",
|
||||
fillParamsDesc1: "Fill in the certificate file path on the host",
|
||||
fillParamsDesc2: "Select SSH login authorization for the host",
|
||||
activateCertTitle: "Make New Certificate Effective",
|
||||
activateCertDesc1: "Execute restart script",
|
||||
activateCertDesc2: "Make the certificate effective",
|
||||
taskSuccessTitle: "Deployment Task Added Successfully",
|
||||
taskSuccessDesc: "Now you can run it",
|
||||
pluginsTitle: "Our System Provides Numerous Deployment Plugins",
|
||||
pluginsDesc: "You can deploy certificates to various applications and platforms according to your needs",
|
||||
},
|
||||
},
|
||||
runAndTestTask: {
|
||||
runAndTestTitle: "Run and Test",
|
||||
runAndTestDescription: "Demonstrate pipeline running, view logs, skip on success, etc.",
|
||||
runTestOnce: "Run a Test",
|
||||
clickManualTriggerToTest: "Click the manual trigger button to test the run",
|
||||
viewLogs: "View Logs",
|
||||
clickTaskToViewStatusAndLogs: "Click the task to view status and logs",
|
||||
howToTroubleshootFailure: "How to Troubleshoot Failure",
|
||||
viewErrorLogs: "View error logs",
|
||||
nginxContainerNotExistFix: "Shows nginx container not found error, fix by changing to correct nginx container name",
|
||||
executionSuccess: "Execution Success",
|
||||
retryAfterFix: "After fixing, click manual trigger again to rerun successfully",
|
||||
autoSkipAfterSuccess: "Auto Skip After Success",
|
||||
successSkipExplanation: "Successful runs will be skipped automatically, rerun only if parameters or certificates update",
|
||||
viewCertDeploymentSuccess: "View Certificate Deployment Success",
|
||||
visitNginxToSeeCert: "Visit website on nginx to see certificate deployed successfully",
|
||||
downloadCertManualDeploy: "Download Certificate for Manual Deployment",
|
||||
downloadIfNoAutoDeployPlugin: "If no deployment plugin available, download certificate for manual deployment",
|
||||
},
|
||||
scheduleAndEmailTask: {
|
||||
title: "Set Scheduled Execution and Email Notifications",
|
||||
description: "Automatic running",
|
||||
setSchedule: "Set Scheduled Execution",
|
||||
pipelineSuccessThenSchedule: "Pipeline tests succeed, then configure scheduled triggers so it runs automatically daily",
|
||||
recommendDailyRun: "Recommend configuring to run once daily; new certs requested 35 days before expiry and auto-skipped otherwise",
|
||||
setEmailNotification: "Set Email Notifications",
|
||||
suggestErrorAndRecoveryEmails: "Suggest listening for 'On Error' and 'Error to Success' to quickly troubleshoot failures (basic version requires mail server setup)",
|
||||
basicVersionNeedsMailServer: "(basic version requires configuring mail server)",
|
||||
tutorialEndTitle: "Tutorial End",
|
||||
thanksForWatching: "Thank you for watching, hope it helps you",
|
||||
}
|
||||
}
|
||||
createCertPipeline: {
|
||||
title: "Create Certificate Application Pipeline",
|
||||
description: "Demonstrate how to configure a certificate application task",
|
||||
items: {
|
||||
tutorialTitle: "Tutorial Demo Content",
|
||||
tutorialDesc1: "This tutorial demonstrates how to automatically apply for a certificate and deploy it to Nginx",
|
||||
tutorialDesc2: "Only 3 steps, fully automatic application and deployment",
|
||||
createTitle: "Create Certificate Pipeline",
|
||||
createDesc: "Click to add a certificate pipeline and fill in the certificate application information",
|
||||
successTitle: "Pipeline Created Successfully",
|
||||
successDesc: "Click manual trigger to apply for the certificate",
|
||||
nextTitle: "Next, demonstrate how to automatically deploy the certificate",
|
||||
nextDesc: "If you only need to apply for a certificate, you can stop here",
|
||||
},
|
||||
},
|
||||
buttons: {
|
||||
prev: "Previous Step",
|
||||
next: "Next Step",
|
||||
},
|
||||
addDeployTask: {
|
||||
title: "Add Deployment Certificate Task",
|
||||
description: "Demonstrate deployment of certificate to Nginx",
|
||||
items: {
|
||||
addTaskTitle: "Add Certificate Deployment Task",
|
||||
addTaskDesc1: "Demonstrate automatic deployment of certificate to nginx",
|
||||
addTaskDesc2: "Our system provides numerous deployment plugins to meet your needs",
|
||||
fillParamsTitle: "Fill Task Parameters",
|
||||
fillParamsDesc1: "Fill in the certificate file path on the host",
|
||||
fillParamsDesc2: "Select SSH login authorization for the host",
|
||||
activateCertTitle: "Make New Certificate Effective",
|
||||
activateCertDesc1: "Execute restart script",
|
||||
activateCertDesc2: "Make the certificate effective",
|
||||
taskSuccessTitle: "Deployment Task Added Successfully",
|
||||
taskSuccessDesc: "Now you can run it",
|
||||
pluginsTitle: "Our System Provides Numerous Deployment Plugins",
|
||||
pluginsDesc: "You can deploy certificates to various applications and platforms according to your needs",
|
||||
},
|
||||
},
|
||||
runAndTestTask: {
|
||||
runAndTestTitle: "Run and Test",
|
||||
runAndTestDescription: "Demonstrate pipeline running, view logs, skip on success, etc.",
|
||||
runTestOnce: "Run a Test",
|
||||
clickManualTriggerToTest: "Click the manual trigger button to test the run",
|
||||
viewLogs: "View Logs",
|
||||
clickTaskToViewStatusAndLogs: "Click the task to view status and logs",
|
||||
howToTroubleshootFailure: "How to Troubleshoot Failure",
|
||||
viewErrorLogs: "View error logs",
|
||||
nginxContainerNotExistFix: "Shows nginx container not found error, fix by changing to correct nginx container name",
|
||||
executionSuccess: "Execution Success",
|
||||
retryAfterFix: "After fixing, click manual trigger again to rerun successfully",
|
||||
autoSkipAfterSuccess: "Auto Skip After Success",
|
||||
successSkipExplanation: "Successful runs will be skipped automatically, rerun only if parameters or certificates update",
|
||||
viewCertDeploymentSuccess: "View Certificate Deployment Success",
|
||||
visitNginxToSeeCert: "Visit website on nginx to see certificate deployed successfully",
|
||||
downloadCertManualDeploy: "Download Certificate for Manual Deployment",
|
||||
downloadIfNoAutoDeployPlugin: "If no deployment plugin available, download certificate for manual deployment",
|
||||
},
|
||||
scheduleAndEmailTask: {
|
||||
title: "Set Scheduled Execution and Email Notifications",
|
||||
description: "Automatic running",
|
||||
setSchedule: "Set Scheduled Execution",
|
||||
pipelineSuccessThenSchedule: "Pipeline tests succeed, then configure scheduled triggers so it runs automatically daily",
|
||||
recommendDailyRun: "Recommend configuring to run once daily; new certs requested 35 days before expiry and auto-skipped otherwise",
|
||||
setEmailNotification: "Set Email Notifications",
|
||||
suggestErrorAndRecoveryEmails: "Suggest listening for 'On Error' and 'Error to Success' to quickly troubleshoot failures (basic version requires mail server setup)",
|
||||
basicVersionNeedsMailServer: "(basic version requires configuring mail server)",
|
||||
tutorialEndTitle: "Tutorial End",
|
||||
thanksForWatching: "Thank you for watching, hope it helps you",
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import certd from './certd';
|
||||
import authentication from './authentication';
|
||||
import vip from './vip';
|
||||
import tutorial from './tutorial';
|
||||
import preferences from './preferences';
|
||||
import ui from './ui';
|
||||
import guide from './guide';
|
||||
import common from './common';
|
||||
import certd from "./certd";
|
||||
import authentication from "./authentication";
|
||||
import vip from "./vip";
|
||||
import tutorial from "./tutorial";
|
||||
import preferences from "./preferences";
|
||||
import ui from "./ui";
|
||||
import guide from "./guide";
|
||||
import common from "./common";
|
||||
|
||||
export default {
|
||||
certd,
|
||||
authentication,
|
||||
vip,
|
||||
ui,
|
||||
tutorial,
|
||||
preferences,
|
||||
guide,
|
||||
common
|
||||
};
|
||||
certd,
|
||||
authentication,
|
||||
vip,
|
||||
ui,
|
||||
tutorial,
|
||||
preferences,
|
||||
guide,
|
||||
common,
|
||||
};
|
||||
|
|
|
@ -1,186 +1,186 @@
|
|||
export default {
|
||||
"title": "Preferences",
|
||||
"subtitle": "Customize Preferences & Preview in Real Time",
|
||||
"resetTip": "Data has changed, click to reset",
|
||||
"resetTitle": "Reset Preferences",
|
||||
"resetSuccess": "Preferences reset successfully",
|
||||
"appearance": "Appearance",
|
||||
"layout": "Layout",
|
||||
"content": "Content",
|
||||
"other": "Other",
|
||||
"wide": "Wide",
|
||||
"compact": "Fixed",
|
||||
"followSystem": "Follow System",
|
||||
"vertical": "Vertical",
|
||||
"verticalTip": "Side vertical menu mode",
|
||||
"horizontal": "Horizontal",
|
||||
"horizontalTip": "Horizontal menu mode, all menus displayed at the top",
|
||||
"twoColumn": "Two Column",
|
||||
"twoColumnTip": "Vertical Two Column Menu Mode",
|
||||
"headerSidebarNav": "Header Vertical",
|
||||
"headerSidebarNavTip": "Header Full Width, Sidebar Navigation Mode",
|
||||
"headerTwoColumn": "Header Two Column",
|
||||
"headerTwoColumnTip": "Header Navigation & Sidebar Two Column co-exists",
|
||||
"mixedMenu": "Mixed Menu",
|
||||
"mixedMenuTip": "Vertical & Horizontal Menu Co-exists",
|
||||
"fullContent": "Full Content",
|
||||
"fullContentTip": "Only display content body, hide all menus",
|
||||
"normal": "Normal",
|
||||
"plain": "Plain",
|
||||
"rounded": "Rounded",
|
||||
"copyPreferences": "Copy Preferences",
|
||||
"copyPreferencesSuccessTitle": "Copy successful",
|
||||
"copyPreferencesSuccess": "Copy successful, please override in `src/preferences.ts` under app",
|
||||
"clearAndLogout": "Clear Cache & Logout",
|
||||
"mode": "Mode",
|
||||
"general": "General",
|
||||
"language": "Language",
|
||||
"dynamicTitle": "Dynamic Title",
|
||||
"watermark": "Watermark",
|
||||
"checkUpdates": "Periodic update check",
|
||||
"position": {
|
||||
"title": "Preferences Postion",
|
||||
"header": "Header",
|
||||
"auto": "Auto",
|
||||
"fixed": "Fixed"
|
||||
},
|
||||
"sidebar": {
|
||||
"title": "Sidebar",
|
||||
"width": "Width",
|
||||
"visible": "Show Sidebar",
|
||||
"collapsed": "Collpase Menu",
|
||||
"collapsedShowTitle": "Show Menu Title",
|
||||
"autoActivateChild": "Auto Activate SubMenu",
|
||||
"autoActivateChildTip": "`Enabled` to automatically activate the submenu while click menu.",
|
||||
"expandOnHover": "Expand On Hover",
|
||||
"expandOnHoverTip": "When the mouse hovers over menu, \n `Enabled` to expand children menus \n `Disabled` to expand whole sidebar."
|
||||
},
|
||||
"tabbar": {
|
||||
"title": "Tabbar",
|
||||
"enable": "Enable Tab Bar",
|
||||
"icon": "Show Tabbar Icon",
|
||||
"showMore": "Show More Button",
|
||||
"showMaximize": "Show Maximize Button",
|
||||
"persist": "Persist Tabs",
|
||||
"maxCount": "Max Count of Tabs",
|
||||
"maxCountTip": "When the number of tabs exceeds the maximum,\nthe oldest tab will be closed.\n Set to 0 to disable count checking.",
|
||||
"draggable": "Enable Draggable Sort",
|
||||
"wheelable": "Support Mouse Wheel",
|
||||
"middleClickClose": "Close Tab when Mouse Middle Button Click",
|
||||
"wheelableTip": "When enabled, the Tabbar area responds to vertical scrolling events of the scroll wheel.",
|
||||
"styleType": {
|
||||
"title": "Tabs Style",
|
||||
"chrome": "Chrome",
|
||||
"card": "Card",
|
||||
"plain": "Plain",
|
||||
"brisk": "Brisk"
|
||||
},
|
||||
"contextMenu": {
|
||||
"reload": "Reload",
|
||||
"close": "Close",
|
||||
"pin": "Pin",
|
||||
"unpin": "Unpin",
|
||||
"closeLeft": "Close Left Tabs",
|
||||
"closeRight": "Close Right Tabs",
|
||||
"closeOther": "Close Other Tabs",
|
||||
"closeAll": "Close All Tabs",
|
||||
"openInNewWindow": "Open in New Window",
|
||||
"maximize": "Maximize",
|
||||
"restoreMaximize": "Restore"
|
||||
}
|
||||
},
|
||||
"navigationMenu": {
|
||||
"title": "Navigation Menu",
|
||||
"style": "Navigation Menu Style",
|
||||
"accordion": "Sidebar Accordion Menu",
|
||||
"split": "Navigation Menu Separation",
|
||||
"splitTip": "When enabled, the sidebar displays the top bar's submenu"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"title": "Breadcrumb",
|
||||
"home": "Show Home Button",
|
||||
"enable": "Enable Breadcrumb",
|
||||
"icon": "Show Breadcrumb Icon",
|
||||
"background": "background",
|
||||
"style": "Breadcrumb Style",
|
||||
"hideOnlyOne": "Hidden when only one"
|
||||
},
|
||||
"animation": {
|
||||
"title": "Animation",
|
||||
"loading": "Page Loading",
|
||||
"transition": "Page Transition",
|
||||
"progress": "Page Progress"
|
||||
},
|
||||
"theme": {
|
||||
"title": "Theme",
|
||||
"radius": "Radius",
|
||||
"light": "Light",
|
||||
"dark": "Dark",
|
||||
"darkSidebar": "Semi Dark Sidebar",
|
||||
"darkHeader": "Semi Dark Header",
|
||||
"weakMode": "Weak Mode",
|
||||
"grayMode": "Gray Mode",
|
||||
"builtin": {
|
||||
"title": "Built-in",
|
||||
"default": "Default",
|
||||
"violet": "Violet",
|
||||
"pink": "Pink",
|
||||
"rose": "Rose",
|
||||
"skyBlue": "Sky Blue",
|
||||
"deepBlue": "Deep Blue",
|
||||
"green": "Green",
|
||||
"deepGreen": "Deep Green",
|
||||
"orange": "Orange",
|
||||
"yellow": "Yellow",
|
||||
"zinc": "Zinc",
|
||||
"neutral": "Neutral",
|
||||
"slate": "Slate",
|
||||
"gray": "Gray",
|
||||
"custom": "Custom"
|
||||
}
|
||||
},
|
||||
"header": {
|
||||
"title": "Header",
|
||||
"visible": "Show Header",
|
||||
"modeStatic": "Static",
|
||||
"modeFixed": "Fixed",
|
||||
"modeAuto": "Auto hide & Show",
|
||||
"modeAutoScroll": "Scroll to Hide & Show",
|
||||
"menuAlign": "Menu Align",
|
||||
"menuAlignStart": "Start",
|
||||
"menuAlignEnd": "End",
|
||||
"menuAlignCenter": "Center"
|
||||
},
|
||||
"footer": {
|
||||
"title": "Footer",
|
||||
"visible": "Show Footer",
|
||||
"fixed": "Fixed at Bottom"
|
||||
},
|
||||
"copyright": {
|
||||
"title": "Copyright",
|
||||
"enable": "Enable Copyright",
|
||||
"companyName": "Company Name",
|
||||
"companySiteLink": "Company Site Link",
|
||||
"date": "Date",
|
||||
"icp": "ICP License Number",
|
||||
"icpLink": "ICP Site Link"
|
||||
},
|
||||
"shortcutKeys": {
|
||||
"title": "Shortcut Keys",
|
||||
"global": "Global",
|
||||
"search": "Global Search",
|
||||
"logout": "Logout",
|
||||
"preferences": "Preferences"
|
||||
},
|
||||
"widget": {
|
||||
"title": "Widget",
|
||||
"globalSearch": "Enable Global Search",
|
||||
"fullscreen": "Enable Fullscreen",
|
||||
"themeToggle": "Enable Theme Toggle",
|
||||
"languageToggle": "Enable Language Toggle",
|
||||
"notification": "Enable Notification",
|
||||
"sidebarToggle": "Enable Sidebar Toggle",
|
||||
"lockScreen": "Enable Lock Screen",
|
||||
"refresh": "Enable Refresh"
|
||||
}
|
||||
}
|
||||
title: "Preferences",
|
||||
subtitle: "Customize Preferences & Preview in Real Time",
|
||||
resetTip: "Data has changed, click to reset",
|
||||
resetTitle: "Reset Preferences",
|
||||
resetSuccess: "Preferences reset successfully",
|
||||
appearance: "Appearance",
|
||||
layout: "Layout",
|
||||
content: "Content",
|
||||
other: "Other",
|
||||
wide: "Wide",
|
||||
compact: "Fixed",
|
||||
followSystem: "Follow System",
|
||||
vertical: "Vertical",
|
||||
verticalTip: "Side vertical menu mode",
|
||||
horizontal: "Horizontal",
|
||||
horizontalTip: "Horizontal menu mode, all menus displayed at the top",
|
||||
twoColumn: "Two Column",
|
||||
twoColumnTip: "Vertical Two Column Menu Mode",
|
||||
headerSidebarNav: "Header Vertical",
|
||||
headerSidebarNavTip: "Header Full Width, Sidebar Navigation Mode",
|
||||
headerTwoColumn: "Header Two Column",
|
||||
headerTwoColumnTip: "Header Navigation & Sidebar Two Column co-exists",
|
||||
mixedMenu: "Mixed Menu",
|
||||
mixedMenuTip: "Vertical & Horizontal Menu Co-exists",
|
||||
fullContent: "Full Content",
|
||||
fullContentTip: "Only display content body, hide all menus",
|
||||
normal: "Normal",
|
||||
plain: "Plain",
|
||||
rounded: "Rounded",
|
||||
copyPreferences: "Copy Preferences",
|
||||
copyPreferencesSuccessTitle: "Copy successful",
|
||||
copyPreferencesSuccess: "Copy successful, please override in `src/preferences.ts` under app",
|
||||
clearAndLogout: "Clear Cache & Logout",
|
||||
mode: "Mode",
|
||||
general: "General",
|
||||
language: "Language",
|
||||
dynamicTitle: "Dynamic Title",
|
||||
watermark: "Watermark",
|
||||
checkUpdates: "Periodic update check",
|
||||
position: {
|
||||
title: "Preferences Postion",
|
||||
header: "Header",
|
||||
auto: "Auto",
|
||||
fixed: "Fixed",
|
||||
},
|
||||
sidebar: {
|
||||
title: "Sidebar",
|
||||
width: "Width",
|
||||
visible: "Show Sidebar",
|
||||
collapsed: "Collpase Menu",
|
||||
collapsedShowTitle: "Show Menu Title",
|
||||
autoActivateChild: "Auto Activate SubMenu",
|
||||
autoActivateChildTip: "`Enabled` to automatically activate the submenu while click menu.",
|
||||
expandOnHover: "Expand On Hover",
|
||||
expandOnHoverTip: "When the mouse hovers over menu, \n `Enabled` to expand children menus \n `Disabled` to expand whole sidebar.",
|
||||
},
|
||||
tabbar: {
|
||||
title: "Tabbar",
|
||||
enable: "Enable Tab Bar",
|
||||
icon: "Show Tabbar Icon",
|
||||
showMore: "Show More Button",
|
||||
showMaximize: "Show Maximize Button",
|
||||
persist: "Persist Tabs",
|
||||
maxCount: "Max Count of Tabs",
|
||||
maxCountTip: "When the number of tabs exceeds the maximum,\nthe oldest tab will be closed.\n Set to 0 to disable count checking.",
|
||||
draggable: "Enable Draggable Sort",
|
||||
wheelable: "Support Mouse Wheel",
|
||||
middleClickClose: "Close Tab when Mouse Middle Button Click",
|
||||
wheelableTip: "When enabled, the Tabbar area responds to vertical scrolling events of the scroll wheel.",
|
||||
styleType: {
|
||||
title: "Tabs Style",
|
||||
chrome: "Chrome",
|
||||
card: "Card",
|
||||
plain: "Plain",
|
||||
brisk: "Brisk",
|
||||
},
|
||||
contextMenu: {
|
||||
reload: "Reload",
|
||||
close: "Close",
|
||||
pin: "Pin",
|
||||
unpin: "Unpin",
|
||||
closeLeft: "Close Left Tabs",
|
||||
closeRight: "Close Right Tabs",
|
||||
closeOther: "Close Other Tabs",
|
||||
closeAll: "Close All Tabs",
|
||||
openInNewWindow: "Open in New Window",
|
||||
maximize: "Maximize",
|
||||
restoreMaximize: "Restore",
|
||||
},
|
||||
},
|
||||
navigationMenu: {
|
||||
title: "Navigation Menu",
|
||||
style: "Navigation Menu Style",
|
||||
accordion: "Sidebar Accordion Menu",
|
||||
split: "Navigation Menu Separation",
|
||||
splitTip: "When enabled, the sidebar displays the top bar's submenu",
|
||||
},
|
||||
breadcrumb: {
|
||||
title: "Breadcrumb",
|
||||
home: "Show Home Button",
|
||||
enable: "Enable Breadcrumb",
|
||||
icon: "Show Breadcrumb Icon",
|
||||
background: "background",
|
||||
style: "Breadcrumb Style",
|
||||
hideOnlyOne: "Hidden when only one",
|
||||
},
|
||||
animation: {
|
||||
title: "Animation",
|
||||
loading: "Page Loading",
|
||||
transition: "Page Transition",
|
||||
progress: "Page Progress",
|
||||
},
|
||||
theme: {
|
||||
title: "Theme",
|
||||
radius: "Radius",
|
||||
light: "Light",
|
||||
dark: "Dark",
|
||||
darkSidebar: "Semi Dark Sidebar",
|
||||
darkHeader: "Semi Dark Header",
|
||||
weakMode: "Weak Mode",
|
||||
grayMode: "Gray Mode",
|
||||
builtin: {
|
||||
title: "Built-in",
|
||||
default: "Default",
|
||||
violet: "Violet",
|
||||
pink: "Pink",
|
||||
rose: "Rose",
|
||||
skyBlue: "Sky Blue",
|
||||
deepBlue: "Deep Blue",
|
||||
green: "Green",
|
||||
deepGreen: "Deep Green",
|
||||
orange: "Orange",
|
||||
yellow: "Yellow",
|
||||
zinc: "Zinc",
|
||||
neutral: "Neutral",
|
||||
slate: "Slate",
|
||||
gray: "Gray",
|
||||
custom: "Custom",
|
||||
},
|
||||
},
|
||||
header: {
|
||||
title: "Header",
|
||||
visible: "Show Header",
|
||||
modeStatic: "Static",
|
||||
modeFixed: "Fixed",
|
||||
modeAuto: "Auto hide & Show",
|
||||
modeAutoScroll: "Scroll to Hide & Show",
|
||||
menuAlign: "Menu Align",
|
||||
menuAlignStart: "Start",
|
||||
menuAlignEnd: "End",
|
||||
menuAlignCenter: "Center",
|
||||
},
|
||||
footer: {
|
||||
title: "Footer",
|
||||
visible: "Show Footer",
|
||||
fixed: "Fixed at Bottom",
|
||||
},
|
||||
copyright: {
|
||||
title: "Copyright",
|
||||
enable: "Enable Copyright",
|
||||
companyName: "Company Name",
|
||||
companySiteLink: "Company Site Link",
|
||||
date: "Date",
|
||||
icp: "ICP License Number",
|
||||
icpLink: "ICP Site Link",
|
||||
},
|
||||
shortcutKeys: {
|
||||
title: "Shortcut Keys",
|
||||
global: "Global",
|
||||
search: "Global Search",
|
||||
logout: "Logout",
|
||||
preferences: "Preferences",
|
||||
},
|
||||
widget: {
|
||||
title: "Widget",
|
||||
globalSearch: "Enable Global Search",
|
||||
fullscreen: "Enable Fullscreen",
|
||||
themeToggle: "Enable Theme Toggle",
|
||||
languageToggle: "Enable Language Toggle",
|
||||
notification: "Enable Notification",
|
||||
sidebarToggle: "Enable Sidebar Toggle",
|
||||
lockScreen: "Enable Lock Screen",
|
||||
refresh: "Enable Refresh",
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export default {
|
||||
title: 'Tutorial',
|
||||
}
|
||||
title: "Tutorial",
|
||||
};
|
||||
|
|
|
@ -1,104 +1,104 @@
|
|||
export default {
|
||||
"formRules": {
|
||||
"required": "Please enter {0}",
|
||||
"selectRequired": "Please select {0}",
|
||||
"minLength": "{0} must be at least {1} characters",
|
||||
"maxLength": "{0} can be at most {1} characters",
|
||||
"length": "{0} must be {1} characters long",
|
||||
"alreadyExists": "{0} `{1}` already exists",
|
||||
"startWith": "{0} must start with `{1}`",
|
||||
"invalidURL": "Please input a valid URL"
|
||||
},
|
||||
"actionTitle": {
|
||||
"edit": "Modify {0}",
|
||||
"create": "Create {0}",
|
||||
"delete": "Delete {0}",
|
||||
"view": "View {0}"
|
||||
},
|
||||
"actionMessage": {
|
||||
"deleteConfirm": "Are you sure to delete {0}?",
|
||||
"deleting": "Deleting {0} ...",
|
||||
"deleteSuccess": "{0} deleted successfully",
|
||||
"operationSuccess": "Operation succeeded",
|
||||
"operationFailed": "Operation failed"
|
||||
},
|
||||
"placeholder": {
|
||||
"input": "Please enter",
|
||||
"select": "Please select"
|
||||
},
|
||||
"captcha": {
|
||||
"title": "Please complete the security verification",
|
||||
"sliderSuccessText": "Passed",
|
||||
"sliderDefaultText": "Slider and drag",
|
||||
"alt": "Supports img tag src attribute value",
|
||||
"sliderRotateDefaultTip": "Click picture to refresh",
|
||||
"sliderRotateFailTip": "Validation failed",
|
||||
"sliderRotateSuccessTip": "Validation successful, time {0} seconds",
|
||||
"refreshAriaLabel": "Refresh captcha",
|
||||
"confirmAriaLabel": "Confirm selection",
|
||||
"confirm": "Confirm",
|
||||
"pointAriaLabel": "Click point",
|
||||
"clickInOrder": "Please click in order"
|
||||
},
|
||||
"iconPicker": {
|
||||
"placeholder": "Select an icon",
|
||||
"search": "Search icon..."
|
||||
},
|
||||
"jsonViewer": {
|
||||
"copy": "Copy",
|
||||
"copied": "Copied"
|
||||
},
|
||||
"fallback": {
|
||||
"pageNotFound": "Oops! Page Not Found",
|
||||
"pageNotFoundDesc": "Sorry, we couldn't find the page you were looking for.",
|
||||
"forbidden": "Oops! Access Denied",
|
||||
"forbiddenDesc": "Sorry, but you don't have permission to access this page.",
|
||||
"internalError": "Oops! Something Went Wrong",
|
||||
"internalErrorDesc": "Sorry, but the server encountered an error.",
|
||||
"offline": "Offline Page",
|
||||
"offlineError": "Oops! Network Error",
|
||||
"offlineErrorDesc": "Sorry, can't connect to the internet. Check your connection.",
|
||||
"comingSoon": "Coming Soon",
|
||||
"http": {
|
||||
"requestTimeout": "The request timed out. Please try again later.",
|
||||
"networkError": "A network error occurred. Please check your internet connection and try again.",
|
||||
"badRequest": "Bad Request. Please check your input and try again.",
|
||||
"unauthorized": "Unauthorized. Please log in to continue.",
|
||||
"forbidden": "Forbidden. You do not have permission to access this resource.",
|
||||
"notFound": "Not Found. The requested resource could not be found.",
|
||||
"internalServerError": "Internal Server Error. Something went wrong on our end. Please try again later."
|
||||
}
|
||||
},
|
||||
"widgets": {
|
||||
"document": "Document",
|
||||
"qa": "Q&A",
|
||||
"setting": "Settings",
|
||||
"logoutTip": "Do you want to logout?",
|
||||
"viewAll": "View All Messages",
|
||||
"notifications": "Notifications",
|
||||
"markAllAsRead": "Make All as Read",
|
||||
"clearNotifications": "Clear",
|
||||
"checkUpdatesTitle": "New Version Available",
|
||||
"checkUpdatesDescription": "Click to refresh and get the latest version",
|
||||
"search": {
|
||||
"title": "Search",
|
||||
"searchNavigate": "Search Navigation",
|
||||
"select": "Select",
|
||||
"navigate": "Navigate",
|
||||
"close": "Close",
|
||||
"noResults": "No Search Results Found",
|
||||
"noRecent": "No Search History",
|
||||
"recent": "Search History"
|
||||
},
|
||||
"lockScreen": {
|
||||
"title": "Lock Screen",
|
||||
"screenButton": "Locking",
|
||||
"password": "Password",
|
||||
"placeholder": "Please enter password",
|
||||
"unlock": "Click to unlock",
|
||||
"errorPasswordTip": "Password error, please re-enter",
|
||||
"backToLogin": "Back to login",
|
||||
"entry": "Enter the system"
|
||||
}
|
||||
}
|
||||
}
|
||||
formRules: {
|
||||
required: "Please enter {0}",
|
||||
selectRequired: "Please select {0}",
|
||||
minLength: "{0} must be at least {1} characters",
|
||||
maxLength: "{0} can be at most {1} characters",
|
||||
length: "{0} must be {1} characters long",
|
||||
alreadyExists: "{0} `{1}` already exists",
|
||||
startWith: "{0} must start with `{1}`",
|
||||
invalidURL: "Please input a valid URL",
|
||||
},
|
||||
actionTitle: {
|
||||
edit: "Modify {0}",
|
||||
create: "Create {0}",
|
||||
delete: "Delete {0}",
|
||||
view: "View {0}",
|
||||
},
|
||||
actionMessage: {
|
||||
deleteConfirm: "Are you sure to delete {0}?",
|
||||
deleting: "Deleting {0} ...",
|
||||
deleteSuccess: "{0} deleted successfully",
|
||||
operationSuccess: "Operation succeeded",
|
||||
operationFailed: "Operation failed",
|
||||
},
|
||||
placeholder: {
|
||||
input: "Please enter",
|
||||
select: "Please select",
|
||||
},
|
||||
captcha: {
|
||||
title: "Please complete the security verification",
|
||||
sliderSuccessText: "Passed",
|
||||
sliderDefaultText: "Slider and drag",
|
||||
alt: "Supports img tag src attribute value",
|
||||
sliderRotateDefaultTip: "Click picture to refresh",
|
||||
sliderRotateFailTip: "Validation failed",
|
||||
sliderRotateSuccessTip: "Validation successful, time {0} seconds",
|
||||
refreshAriaLabel: "Refresh captcha",
|
||||
confirmAriaLabel: "Confirm selection",
|
||||
confirm: "Confirm",
|
||||
pointAriaLabel: "Click point",
|
||||
clickInOrder: "Please click in order",
|
||||
},
|
||||
iconPicker: {
|
||||
placeholder: "Select an icon",
|
||||
search: "Search icon...",
|
||||
},
|
||||
jsonViewer: {
|
||||
copy: "Copy",
|
||||
copied: "Copied",
|
||||
},
|
||||
fallback: {
|
||||
pageNotFound: "Oops! Page Not Found",
|
||||
pageNotFoundDesc: "Sorry, we couldn't find the page you were looking for.",
|
||||
forbidden: "Oops! Access Denied",
|
||||
forbiddenDesc: "Sorry, but you don't have permission to access this page.",
|
||||
internalError: "Oops! Something Went Wrong",
|
||||
internalErrorDesc: "Sorry, but the server encountered an error.",
|
||||
offline: "Offline Page",
|
||||
offlineError: "Oops! Network Error",
|
||||
offlineErrorDesc: "Sorry, can't connect to the internet. Check your connection.",
|
||||
comingSoon: "Coming Soon",
|
||||
http: {
|
||||
requestTimeout: "The request timed out. Please try again later.",
|
||||
networkError: "A network error occurred. Please check your internet connection and try again.",
|
||||
badRequest: "Bad Request. Please check your input and try again.",
|
||||
unauthorized: "Unauthorized. Please log in to continue.",
|
||||
forbidden: "Forbidden. You do not have permission to access this resource.",
|
||||
notFound: "Not Found. The requested resource could not be found.",
|
||||
internalServerError: "Internal Server Error. Something went wrong on our end. Please try again later.",
|
||||
},
|
||||
},
|
||||
widgets: {
|
||||
document: "Document",
|
||||
qa: "Q&A",
|
||||
setting: "Settings",
|
||||
logoutTip: "Do you want to logout?",
|
||||
viewAll: "View All Messages",
|
||||
notifications: "Notifications",
|
||||
markAllAsRead: "Make All as Read",
|
||||
clearNotifications: "Clear",
|
||||
checkUpdatesTitle: "New Version Available",
|
||||
checkUpdatesDescription: "Click to refresh and get the latest version",
|
||||
search: {
|
||||
title: "Search",
|
||||
searchNavigate: "Search Navigation",
|
||||
select: "Select",
|
||||
navigate: "Navigate",
|
||||
close: "Close",
|
||||
noResults: "No Search Results Found",
|
||||
noRecent: "No Search History",
|
||||
recent: "Search History",
|
||||
},
|
||||
lockScreen: {
|
||||
title: "Lock Screen",
|
||||
screenButton: "Locking",
|
||||
password: "Password",
|
||||
placeholder: "Please enter password",
|
||||
unlock: "Click to unlock",
|
||||
errorPasswordTip: "Password error, please re-enter",
|
||||
backToLogin: "Back to login",
|
||||
entry: "Enter the system",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,86 +1,86 @@
|
|||
export default {
|
||||
comm: {
|
||||
name: "{vipLabel} Activated",
|
||||
title: "Expires on: {expire}",
|
||||
nav: "{vipLabel}",
|
||||
},
|
||||
plus: {
|
||||
name: "Pro Features",
|
||||
title: "Upgrade to Pro for commercial license",
|
||||
},
|
||||
free: {
|
||||
comm: {
|
||||
name: "Pro Features",
|
||||
title: "Upgrade to Pro for commercial license",
|
||||
},
|
||||
button: {
|
||||
name: "Advanced Features",
|
||||
title: "Upgrade to Advanced for more VIP privileges",
|
||||
},
|
||||
nav: {
|
||||
name: "Basic Version",
|
||||
title: "Upgrade to Advanced for more VIP privileges",
|
||||
},
|
||||
},
|
||||
enterCode: "Please enter the activation code",
|
||||
successTitle: "Activation Successful",
|
||||
successContent: "You have successfully activated {vipLabel}, valid until: {expireDate}",
|
||||
bindAccountTitle: "Bind Your Account",
|
||||
bindAccountContent: "Binding your account helps prevent license loss. Strongly recommended.",
|
||||
congratulations_vip_trial: 'Congratulations, you have received a Pro version {duration} days trial',
|
||||
trial_modal_title: '7-day Pro version trial acquisition',
|
||||
trial_modal_ok_text: 'Get now',
|
||||
trial_modal_thanks: 'Thank you for supporting the open source project',
|
||||
trial_modal_click_confirm: 'Click confirm to get a 7-day Pro version trial',
|
||||
get_7_day_pro_trial: "7-day professional version trial",
|
||||
star_now: "Star Now",
|
||||
please_help_star: "Could you please help by starring? Thanks a lot!",
|
||||
admin_only_operation: "Admin operation only",
|
||||
enter_activation_code: "Please enter the activation code",
|
||||
activate_pro_business: "Activate Professional/Business Edition",
|
||||
renew_business: "Renew Business Edition",
|
||||
renew_pro_upgrade_business: "Renew Professional Edition / Upgrade to Business Edition",
|
||||
basic_edition: "Basic Edition",
|
||||
community_free_version: "Community Free Version",
|
||||
unlimited_certificate_application: "Unlimited certificate applications",
|
||||
unlimited_domain_count: "Unlimited domain count",
|
||||
unlimited_certificate_pipelines: "Unlimited certificate pipelines",
|
||||
common_deployment_plugins: "Common host, cloud platform, CDN, Baota, 1Panel deployment plugins",
|
||||
email_webhook_notifications: "Email, webhook notification methods",
|
||||
comm: {
|
||||
name: "{vipLabel} Activated",
|
||||
title: "Expires on: {expire}",
|
||||
nav: "{vipLabel}",
|
||||
},
|
||||
plus: {
|
||||
name: "Pro Features",
|
||||
title: "Upgrade to Pro for commercial license",
|
||||
},
|
||||
free: {
|
||||
comm: {
|
||||
name: "Pro Features",
|
||||
title: "Upgrade to Pro for commercial license",
|
||||
},
|
||||
button: {
|
||||
name: "Advanced Features",
|
||||
title: "Upgrade to Advanced for more VIP privileges",
|
||||
},
|
||||
nav: {
|
||||
name: "Basic Version",
|
||||
title: "Upgrade to Advanced for more VIP privileges",
|
||||
},
|
||||
},
|
||||
enterCode: "Please enter the activation code",
|
||||
successTitle: "Activation Successful",
|
||||
successContent: "You have successfully activated {vipLabel}, valid until: {expireDate}",
|
||||
bindAccountTitle: "Bind Your Account",
|
||||
bindAccountContent: "Binding your account helps prevent license loss. Strongly recommended.",
|
||||
congratulations_vip_trial: "Congratulations, you have received a Pro version {duration} days trial",
|
||||
trial_modal_title: "7-day Pro version trial acquisition",
|
||||
trial_modal_ok_text: "Get now",
|
||||
trial_modal_thanks: "Thank you for supporting the open source project",
|
||||
trial_modal_click_confirm: "Click confirm to get a 7-day Pro version trial",
|
||||
get_7_day_pro_trial: "7-day professional version trial",
|
||||
star_now: "Star Now",
|
||||
please_help_star: "Could you please help by starring? Thanks a lot!",
|
||||
admin_only_operation: "Admin operation only",
|
||||
enter_activation_code: "Please enter the activation code",
|
||||
activate_pro_business: "Activate Professional/Business Edition",
|
||||
renew_business: "Renew Business Edition",
|
||||
renew_pro_upgrade_business: "Renew Professional Edition / Upgrade to Business Edition",
|
||||
basic_edition: "Basic Edition",
|
||||
community_free_version: "Community Free Version",
|
||||
unlimited_certificate_application: "Unlimited certificate applications",
|
||||
unlimited_domain_count: "Unlimited domain count",
|
||||
unlimited_certificate_pipelines: "Unlimited certificate pipelines",
|
||||
common_deployment_plugins: "Common host, cloud platform, CDN, Baota, 1Panel deployment plugins",
|
||||
email_webhook_notifications: "Email, webhook notification methods",
|
||||
|
||||
professional_edition: "Professional Edition",
|
||||
open_source_support: "Open source requires your sponsorship support",
|
||||
vip_group_priority: "Access to VIP group, your requests will have priority",
|
||||
unlimited_site_certificate_monitoring: "Unlimited site certificate monitoring",
|
||||
more_notification_methods: "More notification methods",
|
||||
plugins_fully_open: "All plugins open, including Synology and more",
|
||||
click_to_get_7_day_trial: "Click to get 7-day trial",
|
||||
years: "years",
|
||||
afdian_support_vip: 'Get a one-year professional activation code after supporting "VIP membership" on Afdian, open source needs your support',
|
||||
get_after_support: "Get after sponsoring",
|
||||
professional_edition: "Professional Edition",
|
||||
open_source_support: "Open source requires your sponsorship support",
|
||||
vip_group_priority: "Access to VIP group, your requests will have priority",
|
||||
unlimited_site_certificate_monitoring: "Unlimited site certificate monitoring",
|
||||
more_notification_methods: "More notification methods",
|
||||
plugins_fully_open: "All plugins open, including Synology and more",
|
||||
click_to_get_7_day_trial: "Click to get 7-day trial",
|
||||
years: "years",
|
||||
afdian_support_vip: 'Get a one-year professional activation code after supporting "VIP membership" on Afdian, open source needs your support',
|
||||
get_after_support: "Get after sponsoring",
|
||||
|
||||
business_edition: "Business Edition",
|
||||
commercial_license: "Commercial license, allowed for external operation",
|
||||
all_pro_privileges: "All professional edition privileges",
|
||||
allow_commercial_use_modify_logo_title: "Allows commercial use, can modify logo and title",
|
||||
data_statistics: "Data statistics",
|
||||
plugin_management: "Plugin management",
|
||||
unlimited_multi_users: "Unlimited multi-users",
|
||||
support_user_payment: "Supports user payments",
|
||||
contact_author_for_trial: "Please contact the author for trial",
|
||||
activate: "Activate",
|
||||
get_pro_code_after_support: 'Get a one-year professional activation code after supporting "VIP membership" on Afdian',
|
||||
business_contact_author: "Business edition please contact the author directly",
|
||||
year: "year",
|
||||
freee: "Free",
|
||||
renew: "Renew",
|
||||
activate_immediately: "Activate Immediately",
|
||||
current: "Current",
|
||||
activated_expire_time: " activated, expiration date: ",
|
||||
site_id: "Site ID",
|
||||
invite_code_optional: "Invite code [optional], can get extra 30 days for Professional / 15 days for Business",
|
||||
no_activation_code: "No activation code?",
|
||||
activation_code_one_use: "Activation code can only be used once. To change site, please ",
|
||||
bind_account: "bind account",
|
||||
transfer_vip: ' then "Transfer VIP"',
|
||||
}
|
||||
business_edition: "Business Edition",
|
||||
commercial_license: "Commercial license, allowed for external operation",
|
||||
all_pro_privileges: "All professional edition privileges",
|
||||
allow_commercial_use_modify_logo_title: "Allows commercial use, can modify logo and title",
|
||||
data_statistics: "Data statistics",
|
||||
plugin_management: "Plugin management",
|
||||
unlimited_multi_users: "Unlimited multi-users",
|
||||
support_user_payment: "Supports user payments",
|
||||
contact_author_for_trial: "Please contact the author for trial",
|
||||
activate: "Activate",
|
||||
get_pro_code_after_support: 'Get a one-year professional activation code after supporting "VIP membership" on Afdian',
|
||||
business_contact_author: "Business edition please contact the author directly",
|
||||
year: "year",
|
||||
freee: "Free",
|
||||
renew: "Renew",
|
||||
activate_immediately: "Activate Immediately",
|
||||
current: "Current",
|
||||
activated_expire_time: " activated, expiration date: ",
|
||||
site_id: "Site ID",
|
||||
invite_code_optional: "Invite code [optional], can get extra 30 days for Professional / 15 days for Business",
|
||||
no_activation_code: "No activation code?",
|
||||
activation_code_one_use: "Activation code can only be used once. To change site, please ",
|
||||
bind_account: "bind account",
|
||||
transfer_vip: ' then "Transfer VIP"',
|
||||
};
|
||||
|
|
|
@ -1,85 +1,85 @@
|
|||
export default {
|
||||
"welcomeBack": "欢迎回来",
|
||||
"pageTitle": "开箱即用的大型中后台管理系统",
|
||||
"pageDesc": "工程化、高性能、跨组件库的前端模版",
|
||||
"loginSuccess": "登录成功",
|
||||
"loginSuccessDesc": "欢迎回来",
|
||||
"loginSubtitle": "请输入您的帐户信息以开始管理您的项目",
|
||||
"selectAccount": "快速选择账号",
|
||||
"username": "账号",
|
||||
"password": "密码",
|
||||
"usernameTip": "请输入用户名",
|
||||
"passwordTip": "请输入密码",
|
||||
"verifyRequiredTip": "请先完成验证",
|
||||
"passwordErrorTip": "密码错误",
|
||||
"rememberMe": "记住账号",
|
||||
"createAnAccount": "创建一个账号",
|
||||
"createAccount": "创建账号",
|
||||
"alreadyHaveAccount": "已经有账号了?",
|
||||
"accountTip": "还没有账号?",
|
||||
"signUp": "注册",
|
||||
"signUpSubtitle": "让您的应用程序管理变得简单而有趣",
|
||||
"confirmPassword": "确认密码",
|
||||
"confirmPasswordTip": "两次输入的密码不一致",
|
||||
"agree": "我同意",
|
||||
"privacyPolicy": "隐私政策",
|
||||
"terms": "条款",
|
||||
"agreeTip": "请同意隐私政策和条款",
|
||||
"goToLogin": "去登录",
|
||||
"passwordStrength": "使用 8 个或更多字符,混合字母、数字和符号",
|
||||
"forgetPassword": "忘记密码?",
|
||||
"forgetPasswordSubtitle": "输入您的电子邮件,我们将向您发送重置密码的连接",
|
||||
"emailTip": "请输入邮箱",
|
||||
"emailValidErrorTip": "你输入的邮箱格式不正确",
|
||||
"sendResetLink": "发送重置链接",
|
||||
"email": "邮箱",
|
||||
"qrcodeSubtitle": "请用手机扫描二维码登录",
|
||||
"qrcodePrompt": "扫码后点击 '确认',即可完成登录",
|
||||
"qrcodeLogin": "扫码登录",
|
||||
"codeSubtitle": "请输入您的手机号码以开始管理您的项目",
|
||||
"code": "验证码",
|
||||
"codeTip": "请输入{0}位验证码",
|
||||
"mobile": "手机号码",
|
||||
"mobileTip": "请输入手机号",
|
||||
"mobileErrortip": "手机号码格式错误",
|
||||
"mobileLogin": "手机号登录",
|
||||
"sendCode": "获取验证码",
|
||||
"sendText": "{0}秒后重新获取",
|
||||
"thirdPartyLogin": "其他登录方式",
|
||||
"loginAgainTitle": "重新登录",
|
||||
"loginAgainSubTitle": "您的登录状态已过期,请重新登录以继续。",
|
||||
"layout": {
|
||||
"center": "居中",
|
||||
"alignLeft": "居左",
|
||||
"alignRight": "居右"
|
||||
},
|
||||
usernamePlaceholder: '请输入用户名/邮箱/手机号',
|
||||
passwordPlaceholder: '请输入密码',
|
||||
mobilePlaceholder: '请输入手机号',
|
||||
loginButton: '登录',
|
||||
forgotAdminPassword: '忘记管理员密码?',
|
||||
registerLink: '注册',
|
||||
welcomeBack: "欢迎回来",
|
||||
pageTitle: "开箱即用的大型中后台管理系统",
|
||||
pageDesc: "工程化、高性能、跨组件库的前端模版",
|
||||
loginSuccess: "登录成功",
|
||||
loginSuccessDesc: "欢迎回来",
|
||||
loginSubtitle: "请输入您的帐户信息以开始管理您的项目",
|
||||
selectAccount: "快速选择账号",
|
||||
username: "账号",
|
||||
password: "密码",
|
||||
usernameTip: "请输入用户名",
|
||||
passwordTip: "请输入密码",
|
||||
verifyRequiredTip: "请先完成验证",
|
||||
passwordErrorTip: "密码错误",
|
||||
rememberMe: "记住账号",
|
||||
createAnAccount: "创建一个账号",
|
||||
createAccount: "创建账号",
|
||||
alreadyHaveAccount: "已经有账号了?",
|
||||
accountTip: "还没有账号?",
|
||||
signUp: "注册",
|
||||
signUpSubtitle: "让您的应用程序管理变得简单而有趣",
|
||||
confirmPassword: "确认密码",
|
||||
confirmPasswordTip: "两次输入的密码不一致",
|
||||
agree: "我同意",
|
||||
privacyPolicy: "隐私政策",
|
||||
terms: "条款",
|
||||
agreeTip: "请同意隐私政策和条款",
|
||||
goToLogin: "去登录",
|
||||
passwordStrength: "使用 8 个或更多字符,混合字母、数字和符号",
|
||||
forgetPassword: "忘记密码?",
|
||||
forgetPasswordSubtitle: "输入您的电子邮件,我们将向您发送重置密码的连接",
|
||||
emailTip: "请输入邮箱",
|
||||
emailValidErrorTip: "你输入的邮箱格式不正确",
|
||||
sendResetLink: "发送重置链接",
|
||||
email: "邮箱",
|
||||
qrcodeSubtitle: "请用手机扫描二维码登录",
|
||||
qrcodePrompt: "扫码后点击 '确认',即可完成登录",
|
||||
qrcodeLogin: "扫码登录",
|
||||
codeSubtitle: "请输入您的手机号码以开始管理您的项目",
|
||||
code: "验证码",
|
||||
codeTip: "请输入{0}位验证码",
|
||||
mobile: "手机号码",
|
||||
mobileTip: "请输入手机号",
|
||||
mobileErrortip: "手机号码格式错误",
|
||||
mobileLogin: "手机号登录",
|
||||
sendCode: "获取验证码",
|
||||
sendText: "{0}秒后重新获取",
|
||||
thirdPartyLogin: "其他登录方式",
|
||||
loginAgainTitle: "重新登录",
|
||||
loginAgainSubTitle: "您的登录状态已过期,请重新登录以继续。",
|
||||
layout: {
|
||||
center: "居中",
|
||||
alignLeft: "居左",
|
||||
alignRight: "居右",
|
||||
},
|
||||
usernamePlaceholder: "请输入用户名/邮箱/手机号",
|
||||
passwordPlaceholder: "请输入密码",
|
||||
mobilePlaceholder: "请输入手机号",
|
||||
loginButton: "登录",
|
||||
forgotAdminPassword: "忘记管理员密码?",
|
||||
registerLink: "注册",
|
||||
|
||||
smsTab: '短信验证码登录',
|
||||
passwordTab: '密码登录',
|
||||
smsTab: "短信验证码登录",
|
||||
passwordTab: "密码登录",
|
||||
|
||||
title: '修改密码',
|
||||
weakPasswordWarning: '为了您的账户安全,请立即修改密码',
|
||||
changeNow: '立即修改',
|
||||
successMessage: '修改成功',
|
||||
oldPassword: '旧密码',
|
||||
oldPasswordRequired: '请输入旧密码',
|
||||
newPassword: '新密码',
|
||||
newPasswordRequired: '请输入新密码',
|
||||
confirmNewPassword: '确认新密码',
|
||||
confirmNewPasswordRequired: '请输入确认密码',
|
||||
changePasswordButton: '修改密码',
|
||||
enterPassword: "请输入密码",
|
||||
newPasswordNotSameOld: "新密码不能和旧密码相同",
|
||||
enterPasswordAgain: "请再次输入密码",
|
||||
passwordsNotMatch: "两次输入密码不一致!",
|
||||
avatar: "头像",
|
||||
nickName: "昵称",
|
||||
phoneNumber: "手机号",
|
||||
changePassword: "修改密码",
|
||||
}
|
||||
title: "修改密码",
|
||||
weakPasswordWarning: "为了您的账户安全,请立即修改密码",
|
||||
changeNow: "立即修改",
|
||||
successMessage: "修改成功",
|
||||
oldPassword: "旧密码",
|
||||
oldPasswordRequired: "请输入旧密码",
|
||||
newPassword: "新密码",
|
||||
newPasswordRequired: "请输入新密码",
|
||||
confirmNewPassword: "确认新密码",
|
||||
confirmNewPasswordRequired: "请输入确认密码",
|
||||
changePasswordButton: "修改密码",
|
||||
enterPassword: "请输入密码",
|
||||
newPasswordNotSameOld: "新密码不能和旧密码相同",
|
||||
enterPasswordAgain: "请再次输入密码",
|
||||
passwordsNotMatch: "两次输入密码不一致!",
|
||||
avatar: "头像",
|
||||
nickName: "昵称",
|
||||
phoneNumber: "手机号",
|
||||
changePassword: "修改密码",
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,22 +1,22 @@
|
|||
export default {
|
||||
"back": "返回",
|
||||
"backToHome": "返回首页",
|
||||
"login": "登录",
|
||||
"logout": "退出登录",
|
||||
"prompt": "提示",
|
||||
"cancel": "取消",
|
||||
"confirm": "确认",
|
||||
"reset": "重置",
|
||||
"noData": "暂无数据",
|
||||
"refresh": "刷新",
|
||||
"loadingMenu": "加载菜单中",
|
||||
"query": "查询",
|
||||
"search": "搜索",
|
||||
"enabled": "已启用",
|
||||
"disabled": "已禁用",
|
||||
"edit": "修改",
|
||||
"delete": "删除",
|
||||
"create": "新增",
|
||||
"yes": "是",
|
||||
"no": "否"
|
||||
}
|
||||
back: "返回",
|
||||
backToHome: "返回首页",
|
||||
login: "登录",
|
||||
logout: "退出登录",
|
||||
prompt: "提示",
|
||||
cancel: "取消",
|
||||
confirm: "确认",
|
||||
reset: "重置",
|
||||
noData: "暂无数据",
|
||||
refresh: "刷新",
|
||||
loadingMenu: "加载菜单中",
|
||||
query: "查询",
|
||||
search: "搜索",
|
||||
enabled: "已启用",
|
||||
disabled: "已禁用",
|
||||
edit: "修改",
|
||||
delete: "删除",
|
||||
create: "新增",
|
||||
yes: "是",
|
||||
no: "否",
|
||||
};
|
||||
|
|
|
@ -1,71 +1,71 @@
|
|||
export default {
|
||||
createCertPipeline: {
|
||||
title: "创建证书申请流水线",
|
||||
description: "演示证书申请任务如何配置",
|
||||
items: {
|
||||
tutorialTitle: "教程演示内容",
|
||||
tutorialDesc1: "本教程演示如何自动申请证书并部署到Nginx上",
|
||||
tutorialDesc2: "仅需3步,全自动申请部署证书",
|
||||
createTitle: "创建证书流水线",
|
||||
createDesc: "点击添加证书流水线,填写证书申请信息",
|
||||
successTitle: "流水线创建成功",
|
||||
successDesc: "点击手动触发即可申请证书",
|
||||
nextTitle: "接下来演示如何自动部署证书",
|
||||
nextDesc: "如果您只需要申请证书,那么到这一步就可以了",
|
||||
},
|
||||
},
|
||||
buttons: {
|
||||
prev: "上一步",
|
||||
next: "下一步",
|
||||
},
|
||||
addDeployTask: {
|
||||
title: "添加部署证书任务",
|
||||
description: "这里演示部署证书到Nginx",
|
||||
items: {
|
||||
addTaskTitle: "添加证书部署任务",
|
||||
addTaskDesc1: "这里演示自动部署证书到nginx",
|
||||
addTaskDesc2: "本系统提供海量部署插件,满足您的各种部署需求",
|
||||
fillParamsTitle: "填写任务参数",
|
||||
fillParamsDesc1: "填写主机上证书文件的路径",
|
||||
fillParamsDesc2: "选择主机ssh登录授权",
|
||||
activateCertTitle: "让新证书生效",
|
||||
activateCertDesc1: "执行重启脚本",
|
||||
activateCertDesc2: "让证书生效",
|
||||
taskSuccessTitle: "部署任务添加成功",
|
||||
taskSuccessDesc: "现在可以运行",
|
||||
pluginsTitle: "本系统提供茫茫多的部署插件",
|
||||
pluginsDesc: "您可以根据自身需求将证书部署到各种应用和平台",
|
||||
},
|
||||
},
|
||||
runAndTestTask: {
|
||||
runAndTestTitle: "运行与测试",
|
||||
runAndTestDescription: "演示流水线运行,查看日志,成功后跳过等",
|
||||
runTestOnce: "运行测试一下",
|
||||
clickManualTriggerToTest: "点击手动触发按钮,即可测试运行",
|
||||
viewLogs: "查看日志",
|
||||
clickTaskToViewStatusAndLogs: "点击任务可以查看状态和日志",
|
||||
howToTroubleshootFailure: "执行失败如何排查",
|
||||
viewErrorLogs: "查看错误日志",
|
||||
nginxContainerNotExistFix: "这里报的是nginx容器不存在,修改命令,改成正确的nginx容器名称即可",
|
||||
executionSuccess: "执行成功",
|
||||
retryAfterFix: "修改正确后,重新点击手动触发,重新运行一次,执行成功",
|
||||
autoSkipAfterSuccess: "成功后自动跳过",
|
||||
successSkipExplanation: "可以看到成功过的将会自动跳过,不会重复执行,只有当参数变更或者证书更新了,才会重新运行",
|
||||
viewCertDeploymentSuccess: "查看证书部署成功",
|
||||
visitNginxToSeeCert: "访问nginx上的网站,可以看到证书已经部署成功",
|
||||
downloadCertManualDeploy: "还可以下载证书,手动部署",
|
||||
downloadIfNoAutoDeployPlugin: "如果还没有好用的部署插件,没办法自动部署,你还可以下载证书,手动部署",
|
||||
},
|
||||
scheduleAndEmailTask: {
|
||||
title: "设置定时执行和邮件通知",
|
||||
description: "自动运行",
|
||||
setSchedule: "设置定时执行",
|
||||
pipelineSuccessThenSchedule: "流水线测试成功,接下来配置定时触发,以后每天定时执行就不用管了",
|
||||
recommendDailyRun: "推荐配置每天运行一次,在到期前35天才会重新申请新证书并部署,没到期前会自动跳过,不会重复申请。",
|
||||
setEmailNotification: "设置邮件通知",
|
||||
suggestErrorAndRecoveryEmails: "建议选择监听'错误时'和'错误转成功'两种即可,在意外失败时可以尽快去排查问题,(基础版需要配置邮件服务器)",
|
||||
basicVersionNeedsMailServer: "(基础版需要配置邮件服务器)",
|
||||
tutorialEndTitle: "教程结束",
|
||||
thanksForWatching: "感谢观看,希望对你有所帮助",
|
||||
}
|
||||
}
|
||||
createCertPipeline: {
|
||||
title: "创建证书申请流水线",
|
||||
description: "演示证书申请任务如何配置",
|
||||
items: {
|
||||
tutorialTitle: "教程演示内容",
|
||||
tutorialDesc1: "本教程演示如何自动申请证书并部署到Nginx上",
|
||||
tutorialDesc2: "仅需3步,全自动申请部署证书",
|
||||
createTitle: "创建证书流水线",
|
||||
createDesc: "点击添加证书流水线,填写证书申请信息",
|
||||
successTitle: "流水线创建成功",
|
||||
successDesc: "点击手动触发即可申请证书",
|
||||
nextTitle: "接下来演示如何自动部署证书",
|
||||
nextDesc: "如果您只需要申请证书,那么到这一步就可以了",
|
||||
},
|
||||
},
|
||||
buttons: {
|
||||
prev: "上一步",
|
||||
next: "下一步",
|
||||
},
|
||||
addDeployTask: {
|
||||
title: "添加部署证书任务",
|
||||
description: "这里演示部署证书到Nginx",
|
||||
items: {
|
||||
addTaskTitle: "添加证书部署任务",
|
||||
addTaskDesc1: "这里演示自动部署证书到nginx",
|
||||
addTaskDesc2: "本系统提供海量部署插件,满足您的各种部署需求",
|
||||
fillParamsTitle: "填写任务参数",
|
||||
fillParamsDesc1: "填写主机上证书文件的路径",
|
||||
fillParamsDesc2: "选择主机ssh登录授权",
|
||||
activateCertTitle: "让新证书生效",
|
||||
activateCertDesc1: "执行重启脚本",
|
||||
activateCertDesc2: "让证书生效",
|
||||
taskSuccessTitle: "部署任务添加成功",
|
||||
taskSuccessDesc: "现在可以运行",
|
||||
pluginsTitle: "本系统提供茫茫多的部署插件",
|
||||
pluginsDesc: "您可以根据自身需求将证书部署到各种应用和平台",
|
||||
},
|
||||
},
|
||||
runAndTestTask: {
|
||||
runAndTestTitle: "运行与测试",
|
||||
runAndTestDescription: "演示流水线运行,查看日志,成功后跳过等",
|
||||
runTestOnce: "运行测试一下",
|
||||
clickManualTriggerToTest: "点击手动触发按钮,即可测试运行",
|
||||
viewLogs: "查看日志",
|
||||
clickTaskToViewStatusAndLogs: "点击任务可以查看状态和日志",
|
||||
howToTroubleshootFailure: "执行失败如何排查",
|
||||
viewErrorLogs: "查看错误日志",
|
||||
nginxContainerNotExistFix: "这里报的是nginx容器不存在,修改命令,改成正确的nginx容器名称即可",
|
||||
executionSuccess: "执行成功",
|
||||
retryAfterFix: "修改正确后,重新点击手动触发,重新运行一次,执行成功",
|
||||
autoSkipAfterSuccess: "成功后自动跳过",
|
||||
successSkipExplanation: "可以看到成功过的将会自动跳过,不会重复执行,只有当参数变更或者证书更新了,才会重新运行",
|
||||
viewCertDeploymentSuccess: "查看证书部署成功",
|
||||
visitNginxToSeeCert: "访问nginx上的网站,可以看到证书已经部署成功",
|
||||
downloadCertManualDeploy: "还可以下载证书,手动部署",
|
||||
downloadIfNoAutoDeployPlugin: "如果还没有好用的部署插件,没办法自动部署,你还可以下载证书,手动部署",
|
||||
},
|
||||
scheduleAndEmailTask: {
|
||||
title: "设置定时执行和邮件通知",
|
||||
description: "自动运行",
|
||||
setSchedule: "设置定时执行",
|
||||
pipelineSuccessThenSchedule: "流水线测试成功,接下来配置定时触发,以后每天定时执行就不用管了",
|
||||
recommendDailyRun: "推荐配置每天运行一次,在到期前35天才会重新申请新证书并部署,没到期前会自动跳过,不会重复申请。",
|
||||
setEmailNotification: "设置邮件通知",
|
||||
suggestErrorAndRecoveryEmails: "建议选择监听'错误时'和'错误转成功'两种即可,在意外失败时可以尽快去排查问题,(基础版需要配置邮件服务器)",
|
||||
basicVersionNeedsMailServer: "(基础版需要配置邮件服务器)",
|
||||
tutorialEndTitle: "教程结束",
|
||||
thanksForWatching: "感谢观看,希望对你有所帮助",
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import certd from './certd';
|
||||
import authentication from './authentication';
|
||||
import vip from './vip';
|
||||
import tutorial from './tutorial';
|
||||
import preferences from './preferences';
|
||||
import ui from './ui';
|
||||
import guide from './guide';
|
||||
import common from './common';
|
||||
import certd from "./certd";
|
||||
import authentication from "./authentication";
|
||||
import vip from "./vip";
|
||||
import tutorial from "./tutorial";
|
||||
import preferences from "./preferences";
|
||||
import ui from "./ui";
|
||||
import guide from "./guide";
|
||||
import common from "./common";
|
||||
|
||||
export default {
|
||||
certd,
|
||||
authentication,
|
||||
vip,
|
||||
ui,
|
||||
tutorial,
|
||||
preferences,
|
||||
guide,
|
||||
common
|
||||
};
|
||||
certd,
|
||||
authentication,
|
||||
vip,
|
||||
ui,
|
||||
tutorial,
|
||||
preferences,
|
||||
guide,
|
||||
common,
|
||||
};
|
||||
|
|
|
@ -1,186 +1,186 @@
|
|||
export default {
|
||||
"title": "偏好设置",
|
||||
"subtitle": "自定义偏好设置 & 实时预览",
|
||||
"resetTitle": "重置偏好设置",
|
||||
"resetTip": "数据有变化,点击可进行重置",
|
||||
"resetSuccess": "重置偏好设置成功",
|
||||
"appearance": "外观",
|
||||
"layout": "布局",
|
||||
"content": "内容",
|
||||
"other": "其它",
|
||||
"wide": "流式",
|
||||
"compact": "定宽",
|
||||
"followSystem": "跟随系统",
|
||||
"vertical": "垂直",
|
||||
"verticalTip": "侧边垂直菜单模式",
|
||||
"horizontal": "水平",
|
||||
"horizontalTip": "水平菜单模式,菜单全部显示在顶部",
|
||||
"twoColumn": "双列菜单",
|
||||
"twoColumnTip": "垂直双列菜单模式",
|
||||
"headerSidebarNav": "侧边导航",
|
||||
"headerSidebarNavTip": "顶部通栏,侧边导航模式",
|
||||
"headerTwoColumn": "混合双列",
|
||||
"headerTwoColumnTip": "双列、水平菜单共存模式",
|
||||
"mixedMenu": "混合垂直",
|
||||
"mixedMenuTip": "垂直水平菜单共存",
|
||||
"fullContent": "内容全屏",
|
||||
"fullContentTip": "不显示任何菜单,只显示内容主体",
|
||||
"normal": "常规",
|
||||
"plain": "朴素",
|
||||
"rounded": "圆润",
|
||||
"copyPreferences": "复制偏好设置",
|
||||
"copyPreferencesSuccessTitle": "复制成功",
|
||||
"copyPreferencesSuccess": "复制成功,请在 app 下的 `src/preferences.ts`内进行覆盖",
|
||||
"clearAndLogout": "清空缓存 & 退出登录",
|
||||
"mode": "模式",
|
||||
"general": "通用",
|
||||
"language": "语言",
|
||||
"dynamicTitle": "动态标题",
|
||||
"watermark": "水印",
|
||||
"checkUpdates": "定时检查更新",
|
||||
"position": {
|
||||
"title": "偏好设置位置",
|
||||
"header": "顶栏",
|
||||
"auto": "自动",
|
||||
"fixed": "固定"
|
||||
},
|
||||
"sidebar": {
|
||||
"title": "侧边栏",
|
||||
"width": "宽度",
|
||||
"visible": "显示侧边栏",
|
||||
"collapsed": "折叠菜单",
|
||||
"collapsedShowTitle": "折叠显示菜单名",
|
||||
"autoActivateChild": "自动激活子菜单",
|
||||
"autoActivateChildTip": "点击顶层菜单时,自动激活第一个子菜单或者上一次激活的子菜单",
|
||||
"expandOnHover": "鼠标悬停展开",
|
||||
"expandOnHoverTip": "鼠标在折叠区域悬浮时,`启用`则展开当前子菜单,`禁用`则展开整个侧边栏"
|
||||
},
|
||||
"tabbar": {
|
||||
"title": "标签栏",
|
||||
"enable": "启用标签栏",
|
||||
"icon": "显示标签栏图标",
|
||||
"showMore": "显示更多按钮",
|
||||
"showMaximize": "显示最大化按钮",
|
||||
"persist": "持久化标签页",
|
||||
"maxCount": "最大标签数",
|
||||
"maxCountTip": "每次打开新的标签时如果超过最大标签数,\n会自动关闭一个最先打开的标签\n设置为 0 则不限制",
|
||||
"draggable": "启动拖拽排序",
|
||||
"wheelable": "启用纵向滚轮响应",
|
||||
"middleClickClose": "点击鼠标中键关闭标签页",
|
||||
"wheelableTip": "开启后,标签栏区域可以响应滚轮的纵向滚动事件。\n关闭时,只能响应系统的横向滚动事件(需要按下Shift再滚动滚轮)",
|
||||
"styleType": {
|
||||
"title": "标签页风格",
|
||||
"chrome": "谷歌",
|
||||
"card": "卡片",
|
||||
"plain": "朴素",
|
||||
"brisk": "轻快"
|
||||
},
|
||||
"contextMenu": {
|
||||
"reload": "重新加载",
|
||||
"close": "关闭",
|
||||
"pin": "固定",
|
||||
"unpin": "取消固定",
|
||||
"closeLeft": "关闭左侧标签页",
|
||||
"closeRight": "关闭右侧标签页",
|
||||
"closeOther": "关闭其它标签页",
|
||||
"closeAll": "关闭全部标签页",
|
||||
"openInNewWindow": "在新窗口打开",
|
||||
"maximize": "最大化",
|
||||
"restoreMaximize": "还原"
|
||||
}
|
||||
},
|
||||
"navigationMenu": {
|
||||
"title": "导航菜单",
|
||||
"style": "导航菜单风格",
|
||||
"accordion": "侧边导航菜单手风琴模式",
|
||||
"split": "导航菜单分离",
|
||||
"splitTip": "开启时,侧边栏显示顶栏对应菜单的子菜单"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"title": "面包屑导航",
|
||||
"enable": "开启面包屑导航",
|
||||
"icon": "显示面包屑图标",
|
||||
"home": "显示首页按钮",
|
||||
"style": "面包屑风格",
|
||||
"hideOnlyOne": "仅有一个时隐藏",
|
||||
"background": "背景"
|
||||
},
|
||||
"animation": {
|
||||
"title": "动画",
|
||||
"loading": "页面切换 Loading",
|
||||
"transition": "页面切换动画",
|
||||
"progress": "页面切换进度条"
|
||||
},
|
||||
"theme": {
|
||||
"title": "主题",
|
||||
"radius": "圆角",
|
||||
"light": "浅色",
|
||||
"dark": "深色",
|
||||
"darkSidebar": "深色侧边栏",
|
||||
"darkHeader": "深色顶栏",
|
||||
"weakMode": "色弱模式",
|
||||
"grayMode": "灰色模式",
|
||||
"builtin": {
|
||||
"title": "内置主题",
|
||||
"default": "默认",
|
||||
"violet": "紫罗兰",
|
||||
"pink": "樱花粉",
|
||||
"rose": "玫瑰红",
|
||||
"skyBlue": "天蓝色",
|
||||
"deepBlue": "深蓝色",
|
||||
"green": "浅绿色",
|
||||
"deepGreen": "深绿色",
|
||||
"orange": "橙黄色",
|
||||
"yellow": "柠檬黄",
|
||||
"zinc": "锌色灰",
|
||||
"neutral": "中性色",
|
||||
"slate": "石板灰",
|
||||
"gray": "中灰色",
|
||||
"custom": "自定义"
|
||||
}
|
||||
},
|
||||
"header": {
|
||||
"title": "顶栏",
|
||||
"modeStatic": "静止",
|
||||
"modeFixed": "固定",
|
||||
"modeAuto": "自动隐藏和显示",
|
||||
"modeAutoScroll": "滚动隐藏和显示",
|
||||
"visible": "显示顶栏",
|
||||
"menuAlign": "菜单位置",
|
||||
"menuAlignStart": "左侧",
|
||||
"menuAlignEnd": "右侧",
|
||||
"menuAlignCenter": "居中"
|
||||
},
|
||||
"footer": {
|
||||
"title": "底栏",
|
||||
"visible": "显示底栏",
|
||||
"fixed": "固定在底部"
|
||||
},
|
||||
"copyright": {
|
||||
"title": "版权",
|
||||
"enable": "启用版权",
|
||||
"companyName": "公司名",
|
||||
"companySiteLink": "公司主页",
|
||||
"date": "日期",
|
||||
"icp": "ICP 备案号",
|
||||
"icpLink": "ICP 网站链接"
|
||||
},
|
||||
"shortcutKeys": {
|
||||
"title": "快捷键",
|
||||
"global": "全局",
|
||||
"search": "全局搜索",
|
||||
"logout": "退出登录",
|
||||
"preferences": "偏好设置"
|
||||
},
|
||||
"widget": {
|
||||
"title": "小部件",
|
||||
"globalSearch": "启用全局搜索",
|
||||
"fullscreen": "启用全屏",
|
||||
"themeToggle": "启用主题切换",
|
||||
"languageToggle": "启用语言切换",
|
||||
"notification": "启用通知",
|
||||
"sidebarToggle": "启用侧边栏切换",
|
||||
"lockScreen": "启用锁屏",
|
||||
"refresh": "启用刷新"
|
||||
}
|
||||
}
|
||||
title: "偏好设置",
|
||||
subtitle: "自定义偏好设置 & 实时预览",
|
||||
resetTitle: "重置偏好设置",
|
||||
resetTip: "数据有变化,点击可进行重置",
|
||||
resetSuccess: "重置偏好设置成功",
|
||||
appearance: "外观",
|
||||
layout: "布局",
|
||||
content: "内容",
|
||||
other: "其它",
|
||||
wide: "流式",
|
||||
compact: "定宽",
|
||||
followSystem: "跟随系统",
|
||||
vertical: "垂直",
|
||||
verticalTip: "侧边垂直菜单模式",
|
||||
horizontal: "水平",
|
||||
horizontalTip: "水平菜单模式,菜单全部显示在顶部",
|
||||
twoColumn: "双列菜单",
|
||||
twoColumnTip: "垂直双列菜单模式",
|
||||
headerSidebarNav: "侧边导航",
|
||||
headerSidebarNavTip: "顶部通栏,侧边导航模式",
|
||||
headerTwoColumn: "混合双列",
|
||||
headerTwoColumnTip: "双列、水平菜单共存模式",
|
||||
mixedMenu: "混合垂直",
|
||||
mixedMenuTip: "垂直水平菜单共存",
|
||||
fullContent: "内容全屏",
|
||||
fullContentTip: "不显示任何菜单,只显示内容主体",
|
||||
normal: "常规",
|
||||
plain: "朴素",
|
||||
rounded: "圆润",
|
||||
copyPreferences: "复制偏好设置",
|
||||
copyPreferencesSuccessTitle: "复制成功",
|
||||
copyPreferencesSuccess: "复制成功,请在 app 下的 `src/preferences.ts`内进行覆盖",
|
||||
clearAndLogout: "清空缓存 & 退出登录",
|
||||
mode: "模式",
|
||||
general: "通用",
|
||||
language: "语言",
|
||||
dynamicTitle: "动态标题",
|
||||
watermark: "水印",
|
||||
checkUpdates: "定时检查更新",
|
||||
position: {
|
||||
title: "偏好设置位置",
|
||||
header: "顶栏",
|
||||
auto: "自动",
|
||||
fixed: "固定",
|
||||
},
|
||||
sidebar: {
|
||||
title: "侧边栏",
|
||||
width: "宽度",
|
||||
visible: "显示侧边栏",
|
||||
collapsed: "折叠菜单",
|
||||
collapsedShowTitle: "折叠显示菜单名",
|
||||
autoActivateChild: "自动激活子菜单",
|
||||
autoActivateChildTip: "点击顶层菜单时,自动激活第一个子菜单或者上一次激活的子菜单",
|
||||
expandOnHover: "鼠标悬停展开",
|
||||
expandOnHoverTip: "鼠标在折叠区域悬浮时,`启用`则展开当前子菜单,`禁用`则展开整个侧边栏",
|
||||
},
|
||||
tabbar: {
|
||||
title: "标签栏",
|
||||
enable: "启用标签栏",
|
||||
icon: "显示标签栏图标",
|
||||
showMore: "显示更多按钮",
|
||||
showMaximize: "显示最大化按钮",
|
||||
persist: "持久化标签页",
|
||||
maxCount: "最大标签数",
|
||||
maxCountTip: "每次打开新的标签时如果超过最大标签数,\n会自动关闭一个最先打开的标签\n设置为 0 则不限制",
|
||||
draggable: "启动拖拽排序",
|
||||
wheelable: "启用纵向滚轮响应",
|
||||
middleClickClose: "点击鼠标中键关闭标签页",
|
||||
wheelableTip: "开启后,标签栏区域可以响应滚轮的纵向滚动事件。\n关闭时,只能响应系统的横向滚动事件(需要按下Shift再滚动滚轮)",
|
||||
styleType: {
|
||||
title: "标签页风格",
|
||||
chrome: "谷歌",
|
||||
card: "卡片",
|
||||
plain: "朴素",
|
||||
brisk: "轻快",
|
||||
},
|
||||
contextMenu: {
|
||||
reload: "重新加载",
|
||||
close: "关闭",
|
||||
pin: "固定",
|
||||
unpin: "取消固定",
|
||||
closeLeft: "关闭左侧标签页",
|
||||
closeRight: "关闭右侧标签页",
|
||||
closeOther: "关闭其它标签页",
|
||||
closeAll: "关闭全部标签页",
|
||||
openInNewWindow: "在新窗口打开",
|
||||
maximize: "最大化",
|
||||
restoreMaximize: "还原",
|
||||
},
|
||||
},
|
||||
navigationMenu: {
|
||||
title: "导航菜单",
|
||||
style: "导航菜单风格",
|
||||
accordion: "侧边导航菜单手风琴模式",
|
||||
split: "导航菜单分离",
|
||||
splitTip: "开启时,侧边栏显示顶栏对应菜单的子菜单",
|
||||
},
|
||||
breadcrumb: {
|
||||
title: "面包屑导航",
|
||||
enable: "开启面包屑导航",
|
||||
icon: "显示面包屑图标",
|
||||
home: "显示首页按钮",
|
||||
style: "面包屑风格",
|
||||
hideOnlyOne: "仅有一个时隐藏",
|
||||
background: "背景",
|
||||
},
|
||||
animation: {
|
||||
title: "动画",
|
||||
loading: "页面切换 Loading",
|
||||
transition: "页面切换动画",
|
||||
progress: "页面切换进度条",
|
||||
},
|
||||
theme: {
|
||||
title: "主题",
|
||||
radius: "圆角",
|
||||
light: "浅色",
|
||||
dark: "深色",
|
||||
darkSidebar: "深色侧边栏",
|
||||
darkHeader: "深色顶栏",
|
||||
weakMode: "色弱模式",
|
||||
grayMode: "灰色模式",
|
||||
builtin: {
|
||||
title: "内置主题",
|
||||
default: "默认",
|
||||
violet: "紫罗兰",
|
||||
pink: "樱花粉",
|
||||
rose: "玫瑰红",
|
||||
skyBlue: "天蓝色",
|
||||
deepBlue: "深蓝色",
|
||||
green: "浅绿色",
|
||||
deepGreen: "深绿色",
|
||||
orange: "橙黄色",
|
||||
yellow: "柠檬黄",
|
||||
zinc: "锌色灰",
|
||||
neutral: "中性色",
|
||||
slate: "石板灰",
|
||||
gray: "中灰色",
|
||||
custom: "自定义",
|
||||
},
|
||||
},
|
||||
header: {
|
||||
title: "顶栏",
|
||||
modeStatic: "静止",
|
||||
modeFixed: "固定",
|
||||
modeAuto: "自动隐藏和显示",
|
||||
modeAutoScroll: "滚动隐藏和显示",
|
||||
visible: "显示顶栏",
|
||||
menuAlign: "菜单位置",
|
||||
menuAlignStart: "左侧",
|
||||
menuAlignEnd: "右侧",
|
||||
menuAlignCenter: "居中",
|
||||
},
|
||||
footer: {
|
||||
title: "底栏",
|
||||
visible: "显示底栏",
|
||||
fixed: "固定在底部",
|
||||
},
|
||||
copyright: {
|
||||
title: "版权",
|
||||
enable: "启用版权",
|
||||
companyName: "公司名",
|
||||
companySiteLink: "公司主页",
|
||||
date: "日期",
|
||||
icp: "ICP 备案号",
|
||||
icpLink: "ICP 网站链接",
|
||||
},
|
||||
shortcutKeys: {
|
||||
title: "快捷键",
|
||||
global: "全局",
|
||||
search: "全局搜索",
|
||||
logout: "退出登录",
|
||||
preferences: "偏好设置",
|
||||
},
|
||||
widget: {
|
||||
title: "小部件",
|
||||
globalSearch: "启用全局搜索",
|
||||
fullscreen: "启用全屏",
|
||||
themeToggle: "启用主题切换",
|
||||
languageToggle: "启用语言切换",
|
||||
notification: "启用通知",
|
||||
sidebarToggle: "启用侧边栏切换",
|
||||
lockScreen: "启用锁屏",
|
||||
refresh: "启用刷新",
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export default {
|
||||
title: '使用教程',
|
||||
}
|
||||
title: "使用教程",
|
||||
};
|
||||
|
|
|
@ -1,104 +1,104 @@
|
|||
export default {
|
||||
"formRules": {
|
||||
"required": "请输入{0}",
|
||||
"selectRequired": "请选择{0}",
|
||||
"minLength": "{0}至少{1}个字符",
|
||||
"maxLength": "{0}最多{1}个字符",
|
||||
"length": "{0}长度必须为{1}个字符",
|
||||
"alreadyExists": "{0} `{1}` 已存在",
|
||||
"startWith": "{0}必须以 {1} 开头",
|
||||
"invalidURL": "请输入有效的链接"
|
||||
},
|
||||
"actionTitle": {
|
||||
"edit": "修改{0}",
|
||||
"create": "新增{0}",
|
||||
"delete": "删除{0}",
|
||||
"view": "查看{0}"
|
||||
},
|
||||
"actionMessage": {
|
||||
"deleteConfirm": "确定删除 {0} 吗?",
|
||||
"deleting": "正在删除 {0} ...",
|
||||
"deleteSuccess": "{0} 删除成功",
|
||||
"operationSuccess": "操作成功",
|
||||
"operationFailed": "操作失败"
|
||||
},
|
||||
"placeholder": {
|
||||
"input": "请输入",
|
||||
"select": "请选择"
|
||||
},
|
||||
"captcha": {
|
||||
"title": "请完成安全验证",
|
||||
"sliderSuccessText": "验证通过",
|
||||
"sliderDefaultText": "请按住滑块拖动",
|
||||
"sliderRotateDefaultTip": "点击图片可刷新",
|
||||
"sliderRotateFailTip": "验证失败",
|
||||
"sliderRotateSuccessTip": "验证成功,耗时{0}秒",
|
||||
"alt": "支持img标签src属性值",
|
||||
"refreshAriaLabel": "刷新验证码",
|
||||
"confirmAriaLabel": "确认选择",
|
||||
"confirm": "确认",
|
||||
"pointAriaLabel": "点击点",
|
||||
"clickInOrder": "请依次点击"
|
||||
},
|
||||
"iconPicker": {
|
||||
"placeholder": "选择一个图标",
|
||||
"search": "搜索图标..."
|
||||
},
|
||||
"jsonViewer": {
|
||||
"copy": "复制",
|
||||
"copied": "已复制"
|
||||
},
|
||||
"fallback": {
|
||||
"pageNotFound": "哎呀!未找到页面",
|
||||
"pageNotFoundDesc": "抱歉,我们无法找到您要找的页面。",
|
||||
"forbidden": "哎呀!访问被拒绝",
|
||||
"forbiddenDesc": "抱歉,您没有权限访问此页面。",
|
||||
"internalError": "哎呀!出错了",
|
||||
"internalErrorDesc": "抱歉,服务器遇到错误。",
|
||||
"offline": "离线页面",
|
||||
"offlineError": "哎呀!网络错误",
|
||||
"offlineErrorDesc": "抱歉,无法连接到互联网,请检查您的网络连接并重试。",
|
||||
"comingSoon": "即将推出",
|
||||
"http": {
|
||||
"requestTimeout": "请求超时,请稍后再试。",
|
||||
"networkError": "网络异常,请检查您的网络连接后重试。",
|
||||
"badRequest": "请求错误。请检查您的输入并重试。",
|
||||
"unauthorized": "登录认证过期,请重新登录后继续。",
|
||||
"forbidden": "禁止访问, 您没有权限访问此资源。",
|
||||
"notFound": "未找到, 请求的资源不存在。",
|
||||
"internalServerError": "内部服务器错误,请稍后再试。"
|
||||
}
|
||||
},
|
||||
"widgets": {
|
||||
"document": "文档",
|
||||
"qa": "问题 & 帮助",
|
||||
"setting": "设置",
|
||||
"logoutTip": "是否退出登录?",
|
||||
"viewAll": "查看所有消息",
|
||||
"notifications": "通知",
|
||||
"markAllAsRead": "全部标记为已读",
|
||||
"clearNotifications": "清空",
|
||||
"checkUpdatesTitle": "新版本可用",
|
||||
"checkUpdatesDescription": "点击刷新以获取最新版本",
|
||||
"search": {
|
||||
"title": "搜索",
|
||||
"searchNavigate": "搜索导航菜单",
|
||||
"select": "选择",
|
||||
"navigate": "导航",
|
||||
"close": "关闭",
|
||||
"noResults": "未找到搜索结果",
|
||||
"noRecent": "没有搜索历史",
|
||||
"recent": "搜索历史"
|
||||
},
|
||||
"lockScreen": {
|
||||
"title": "锁定屏幕",
|
||||
"screenButton": "锁定",
|
||||
"password": "密码",
|
||||
"placeholder": "请输入锁屏密码",
|
||||
"unlock": "点击解锁",
|
||||
"errorPasswordTip": "密码错误,请重新输入",
|
||||
"backToLogin": "返回登录",
|
||||
"entry": "进入系统"
|
||||
}
|
||||
}
|
||||
}
|
||||
formRules: {
|
||||
required: "请输入{0}",
|
||||
selectRequired: "请选择{0}",
|
||||
minLength: "{0}至少{1}个字符",
|
||||
maxLength: "{0}最多{1}个字符",
|
||||
length: "{0}长度必须为{1}个字符",
|
||||
alreadyExists: "{0} `{1}` 已存在",
|
||||
startWith: "{0}必须以 {1} 开头",
|
||||
invalidURL: "请输入有效的链接",
|
||||
},
|
||||
actionTitle: {
|
||||
edit: "修改{0}",
|
||||
create: "新增{0}",
|
||||
delete: "删除{0}",
|
||||
view: "查看{0}",
|
||||
},
|
||||
actionMessage: {
|
||||
deleteConfirm: "确定删除 {0} 吗?",
|
||||
deleting: "正在删除 {0} ...",
|
||||
deleteSuccess: "{0} 删除成功",
|
||||
operationSuccess: "操作成功",
|
||||
operationFailed: "操作失败",
|
||||
},
|
||||
placeholder: {
|
||||
input: "请输入",
|
||||
select: "请选择",
|
||||
},
|
||||
captcha: {
|
||||
title: "请完成安全验证",
|
||||
sliderSuccessText: "验证通过",
|
||||
sliderDefaultText: "请按住滑块拖动",
|
||||
sliderRotateDefaultTip: "点击图片可刷新",
|
||||
sliderRotateFailTip: "验证失败",
|
||||
sliderRotateSuccessTip: "验证成功,耗时{0}秒",
|
||||
alt: "支持img标签src属性值",
|
||||
refreshAriaLabel: "刷新验证码",
|
||||
confirmAriaLabel: "确认选择",
|
||||
confirm: "确认",
|
||||
pointAriaLabel: "点击点",
|
||||
clickInOrder: "请依次点击",
|
||||
},
|
||||
iconPicker: {
|
||||
placeholder: "选择一个图标",
|
||||
search: "搜索图标...",
|
||||
},
|
||||
jsonViewer: {
|
||||
copy: "复制",
|
||||
copied: "已复制",
|
||||
},
|
||||
fallback: {
|
||||
pageNotFound: "哎呀!未找到页面",
|
||||
pageNotFoundDesc: "抱歉,我们无法找到您要找的页面。",
|
||||
forbidden: "哎呀!访问被拒绝",
|
||||
forbiddenDesc: "抱歉,您没有权限访问此页面。",
|
||||
internalError: "哎呀!出错了",
|
||||
internalErrorDesc: "抱歉,服务器遇到错误。",
|
||||
offline: "离线页面",
|
||||
offlineError: "哎呀!网络错误",
|
||||
offlineErrorDesc: "抱歉,无法连接到互联网,请检查您的网络连接并重试。",
|
||||
comingSoon: "即将推出",
|
||||
http: {
|
||||
requestTimeout: "请求超时,请稍后再试。",
|
||||
networkError: "网络异常,请检查您的网络连接后重试。",
|
||||
badRequest: "请求错误。请检查您的输入并重试。",
|
||||
unauthorized: "登录认证过期,请重新登录后继续。",
|
||||
forbidden: "禁止访问, 您没有权限访问此资源。",
|
||||
notFound: "未找到, 请求的资源不存在。",
|
||||
internalServerError: "内部服务器错误,请稍后再试。",
|
||||
},
|
||||
},
|
||||
widgets: {
|
||||
document: "文档",
|
||||
qa: "问题 & 帮助",
|
||||
setting: "设置",
|
||||
logoutTip: "是否退出登录?",
|
||||
viewAll: "查看所有消息",
|
||||
notifications: "通知",
|
||||
markAllAsRead: "全部标记为已读",
|
||||
clearNotifications: "清空",
|
||||
checkUpdatesTitle: "新版本可用",
|
||||
checkUpdatesDescription: "点击刷新以获取最新版本",
|
||||
search: {
|
||||
title: "搜索",
|
||||
searchNavigate: "搜索导航菜单",
|
||||
select: "选择",
|
||||
navigate: "导航",
|
||||
close: "关闭",
|
||||
noResults: "未找到搜索结果",
|
||||
noRecent: "没有搜索历史",
|
||||
recent: "搜索历史",
|
||||
},
|
||||
lockScreen: {
|
||||
title: "锁定屏幕",
|
||||
screenButton: "锁定",
|
||||
password: "密码",
|
||||
placeholder: "请输入锁屏密码",
|
||||
unlock: "点击解锁",
|
||||
errorPasswordTip: "密码错误,请重新输入",
|
||||
backToLogin: "返回登录",
|
||||
entry: "进入系统",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,86 +1,86 @@
|
|||
export default {
|
||||
comm: {
|
||||
name: "{vipLabel}已开通",
|
||||
title: "到期时间:{expire}",
|
||||
nav: "{vipLabel}",
|
||||
},
|
||||
plus: {
|
||||
name: "商业版功能",
|
||||
title: "升级商业版,获取商业授权",
|
||||
},
|
||||
free: {
|
||||
comm: {
|
||||
name: "商业版功能",
|
||||
title: "升级商业版,获取商业授权",
|
||||
},
|
||||
button: {
|
||||
name: "专业版功能",
|
||||
title: "升级专业版,享受更多VIP特权",
|
||||
},
|
||||
nav: {
|
||||
name: "基础版",
|
||||
title: "升级专业版,享受更多VIP特权",
|
||||
},
|
||||
},
|
||||
enterCode: "请输入激活码",
|
||||
successTitle: "激活成功",
|
||||
successContent: "您已成功激活{vipLabel},有效期至:{expireDate}",
|
||||
bindAccountTitle: "是否绑定袖手账号",
|
||||
bindAccountContent: "绑定账号后,可以避免License丢失,强烈建议绑定",
|
||||
congratulations_vip_trial: '恭喜,您已获得专业版{duration}天试用',
|
||||
trial_modal_title: '7天专业版试用获取',
|
||||
trial_modal_ok_text: '立即获取',
|
||||
trial_modal_thanks: '感谢您对开源项目的支持',
|
||||
trial_modal_click_confirm: '点击确认,即可获取7天专业版试用',
|
||||
get_7_day_pro_trial: "7天专业版试用获取",
|
||||
star_now: "立即去Star",
|
||||
please_help_star: "可以先请您帮忙点个star吗?感谢感谢",
|
||||
admin_only_operation: "仅限管理员操作",
|
||||
enter_activation_code: "请输入激活码",
|
||||
activate_pro_business: "激活专业版/商业版",
|
||||
renew_business: "续期商业版",
|
||||
renew_pro_upgrade_business: "续期专业版/升级商业版",
|
||||
basic_edition: "基础版",
|
||||
community_free_version: "社区免费版",
|
||||
unlimited_certificate_application: "证书申请无限制",
|
||||
unlimited_domain_count: "域名数量无限制",
|
||||
unlimited_certificate_pipelines: "证书流水线数量无限制",
|
||||
common_deployment_plugins: "常用的主机、云平台、cdn、宝塔、1Panel等部署插件",
|
||||
email_webhook_notifications: "邮件、webhook通知方式",
|
||||
comm: {
|
||||
name: "{vipLabel}已开通",
|
||||
title: "到期时间:{expire}",
|
||||
nav: "{vipLabel}",
|
||||
},
|
||||
plus: {
|
||||
name: "商业版功能",
|
||||
title: "升级商业版,获取商业授权",
|
||||
},
|
||||
free: {
|
||||
comm: {
|
||||
name: "商业版功能",
|
||||
title: "升级商业版,获取商业授权",
|
||||
},
|
||||
button: {
|
||||
name: "专业版功能",
|
||||
title: "升级专业版,享受更多VIP特权",
|
||||
},
|
||||
nav: {
|
||||
name: "基础版",
|
||||
title: "升级专业版,享受更多VIP特权",
|
||||
},
|
||||
},
|
||||
enterCode: "请输入激活码",
|
||||
successTitle: "激活成功",
|
||||
successContent: "您已成功激活{vipLabel},有效期至:{expireDate}",
|
||||
bindAccountTitle: "是否绑定袖手账号",
|
||||
bindAccountContent: "绑定账号后,可以避免License丢失,强烈建议绑定",
|
||||
congratulations_vip_trial: "恭喜,您已获得专业版{duration}天试用",
|
||||
trial_modal_title: "7天专业版试用获取",
|
||||
trial_modal_ok_text: "立即获取",
|
||||
trial_modal_thanks: "感谢您对开源项目的支持",
|
||||
trial_modal_click_confirm: "点击确认,即可获取7天专业版试用",
|
||||
get_7_day_pro_trial: "7天专业版试用获取",
|
||||
star_now: "立即去Star",
|
||||
please_help_star: "可以先请您帮忙点个star吗?感谢感谢",
|
||||
admin_only_operation: "仅限管理员操作",
|
||||
enter_activation_code: "请输入激活码",
|
||||
activate_pro_business: "激活专业版/商业版",
|
||||
renew_business: "续期商业版",
|
||||
renew_pro_upgrade_business: "续期专业版/升级商业版",
|
||||
basic_edition: "基础版",
|
||||
community_free_version: "社区免费版",
|
||||
unlimited_certificate_application: "证书申请无限制",
|
||||
unlimited_domain_count: "域名数量无限制",
|
||||
unlimited_certificate_pipelines: "证书流水线数量无限制",
|
||||
common_deployment_plugins: "常用的主机、云平台、cdn、宝塔、1Panel等部署插件",
|
||||
email_webhook_notifications: "邮件、webhook通知方式",
|
||||
|
||||
professional_edition: "专业版",
|
||||
open_source_support: "开源需要您的赞助支持",
|
||||
vip_group_priority: "可加VIP群,您的需求将优先实现",
|
||||
unlimited_site_certificate_monitoring: "站点证书监控无限制",
|
||||
more_notification_methods: "更多通知方式",
|
||||
plugins_fully_open: "插件全开放,群辉等更多插件",
|
||||
click_to_get_7_day_trial: "点击获取7天试用",
|
||||
years: "年",
|
||||
afdian_support_vip: '爱发电赞助“VIP会员”后获取一年期专业版激活码,开源需要您的支持',
|
||||
get_after_support: "爱发电赞助后获取",
|
||||
professional_edition: "专业版",
|
||||
open_source_support: "开源需要您的赞助支持",
|
||||
vip_group_priority: "可加VIP群,您的需求将优先实现",
|
||||
unlimited_site_certificate_monitoring: "站点证书监控无限制",
|
||||
more_notification_methods: "更多通知方式",
|
||||
plugins_fully_open: "插件全开放,群辉等更多插件",
|
||||
click_to_get_7_day_trial: "点击获取7天试用",
|
||||
years: "年",
|
||||
afdian_support_vip: "爱发电赞助“VIP会员”后获取一年期专业版激活码,开源需要您的支持",
|
||||
get_after_support: "爱发电赞助后获取",
|
||||
|
||||
business_edition: "商业版",
|
||||
commercial_license: "商业授权,可对外运营",
|
||||
all_pro_privileges: "拥有专业版所有特权",
|
||||
allow_commercial_use_modify_logo_title: "允许商用,可修改logo、标题",
|
||||
data_statistics: "数据统计",
|
||||
plugin_management: "插件管理",
|
||||
unlimited_multi_users: "多用户无限制",
|
||||
support_user_payment: "支持用户支付",
|
||||
contact_author_for_trial: "请联系作者获取试用",
|
||||
activate: "激活",
|
||||
get_pro_code_after_support: '爱发电赞助“VIP会员”后获取一年期专业版激活码',
|
||||
business_contact_author: "商业版请直接联系作者",
|
||||
year: "年",
|
||||
freee: "免费",
|
||||
renew: "续期",
|
||||
activate_immediately: "立刻激活",
|
||||
current: "当前",
|
||||
activated_expire_time: "已激活,到期时间:",
|
||||
site_id: "站点ID",
|
||||
invite_code_optional: "邀请码【选填】,可额外获得专业版30天/商业版15天时长",
|
||||
no_activation_code: "没有激活码?",
|
||||
activation_code_one_use: "激活码使用过一次之后,不可再次使用,如果要更换站点,请",
|
||||
bind_account: "绑定账号",
|
||||
transfer_vip: ',然后"转移VIP"即可',
|
||||
}
|
||||
business_edition: "商业版",
|
||||
commercial_license: "商业授权,可对外运营",
|
||||
all_pro_privileges: "拥有专业版所有特权",
|
||||
allow_commercial_use_modify_logo_title: "允许商用,可修改logo、标题",
|
||||
data_statistics: "数据统计",
|
||||
plugin_management: "插件管理",
|
||||
unlimited_multi_users: "多用户无限制",
|
||||
support_user_payment: "支持用户支付",
|
||||
contact_author_for_trial: "请联系作者获取试用",
|
||||
activate: "激活",
|
||||
get_pro_code_after_support: "爱发电赞助“VIP会员”后获取一年期专业版激活码",
|
||||
business_contact_author: "商业版请直接联系作者",
|
||||
year: "年",
|
||||
freee: "免费",
|
||||
renew: "续期",
|
||||
activate_immediately: "立刻激活",
|
||||
current: "当前",
|
||||
activated_expire_time: "已激活,到期时间:",
|
||||
site_id: "站点ID",
|
||||
invite_code_optional: "邀请码【选填】,可额外获得专业版30天/商业版15天时长",
|
||||
no_activation_code: "没有激活码?",
|
||||
activation_code_one_use: "激活码使用过一次之后,不可再次使用,如果要更换站点,请",
|
||||
bind_account: "绑定账号",
|
||||
transfer_vip: ',然后"转移VIP"即可',
|
||||
};
|
||||
|
|
|
@ -12,7 +12,7 @@ async function generateAccess(options: GenerateMenuAndRoutesOptions) {
|
|||
|
||||
const layoutMap: ComponentRecordType = {
|
||||
BasicLayout,
|
||||
IFrameView
|
||||
IFrameView,
|
||||
} as any;
|
||||
|
||||
return await generateAccessible(preferences.app.accessMode, {
|
||||
|
@ -28,7 +28,7 @@ async function generateAccess(options: GenerateMenuAndRoutesOptions) {
|
|||
forbiddenComponent,
|
||||
// 如果 route.meta.menuVisibleWithForbidden = true
|
||||
layoutMap,
|
||||
pageMap
|
||||
pageMap,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,44 +1,44 @@
|
|||
import LayoutBasic from "/@/layout/layout-basic.vue";
|
||||
|
||||
import type { RouteRecordRaw } from "vue-router";
|
||||
import i18n from '/@/locales/i18n';
|
||||
import i18n from "/@/locales/i18n";
|
||||
|
||||
import { mergeRouteModules } from "/@/vben/utils";
|
||||
const dynamicRouteFiles = import.meta.glob("./modules/**/*.ts*", {
|
||||
eager: true,
|
||||
eager: true,
|
||||
});
|
||||
|
||||
/** 动态路由 */
|
||||
const dynamicRoutes: RouteRecordRaw[] = mergeRouteModules(dynamicRouteFiles);
|
||||
export const frameworkResource = [
|
||||
{
|
||||
title: i18n.global.t("certd.framework.title"),
|
||||
name: "root",
|
||||
path: "/",
|
||||
redirect: "/index",
|
||||
component: LayoutBasic,
|
||||
meta: {
|
||||
icon: "ion:accessibility",
|
||||
hideInBreadcrumb: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: i18n.global.t("certd.framework.home"),
|
||||
name: "index",
|
||||
path: "/index",
|
||||
component: "/framework/home/index.vue",
|
||||
meta: {
|
||||
fixedAside: true,
|
||||
showOnHeader: false,
|
||||
icon: "ion:home-outline",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
// @ts-ignore
|
||||
{
|
||||
title: "certd.framework.title",
|
||||
name: "root",
|
||||
path: "/",
|
||||
redirect: "/index",
|
||||
component: LayoutBasic,
|
||||
meta: {
|
||||
icon: "ion:accessibility",
|
||||
hideInBreadcrumb: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: "certd.framework.home",
|
||||
name: "index",
|
||||
path: "/index",
|
||||
component: "/framework/home/index.vue",
|
||||
meta: {
|
||||
fixedAside: true,
|
||||
showOnHeader: false,
|
||||
icon: "ion:home-outline",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
// @ts-ignore
|
||||
|
||||
...dynamicRoutes,
|
||||
],
|
||||
},
|
||||
...dynamicRoutes,
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
console.assert(frameworkResource.length === 1, "frameworkResource数组长度只能为1,你只能配置framework路由的子路由");
|
||||
|
|
|
@ -1,36 +1,35 @@
|
|||
import i18n from '/@/locales/i18n';
|
||||
import i18n from "/@/locales/i18n";
|
||||
|
||||
export const headerResource = [
|
||||
{
|
||||
title: i18n.global.t("certd.helpDoc"),
|
||||
path: "https://certd.docmirror.cn",
|
||||
meta: {
|
||||
icon: "ion:document-text-outline"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.source"),
|
||||
name: "source",
|
||||
key: "source",
|
||||
meta: {
|
||||
icon: "ion:git-branch-outline"
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: i18n.global.t("certd.github"),
|
||||
path: "https://github.com/certd/certd",
|
||||
meta: {
|
||||
icon: "ion:logo-github"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.gitee"),
|
||||
path: "https://gitee.com/certd/certd",
|
||||
meta: {
|
||||
icon: "ion:logo-octocat"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
{
|
||||
title: "certd.helpDoc",
|
||||
path: "https://certd.docmirror.cn",
|
||||
meta: {
|
||||
icon: "ion:document-text-outline",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.source",
|
||||
name: "source",
|
||||
key: "source",
|
||||
meta: {
|
||||
icon: "ion:git-branch-outline",
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: "certd.github",
|
||||
path: "https://github.com/certd/certd",
|
||||
meta: {
|
||||
icon: "ion:logo-github",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.gitee",
|
||||
path: "https://gitee.com/certd/certd",
|
||||
meta: {
|
||||
icon: "ion:logo-octocat",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -2,25 +2,25 @@ import { IFrameView } from "/@/vben/layouts";
|
|||
import { useSettingStore } from "/@/store/settings";
|
||||
import { computed } from "vue";
|
||||
import TutorialButton from "/@/components/tutorial/index.vue";
|
||||
import i18n from '/@/locales/i18n';
|
||||
import i18n from "/@/locales/i18n";
|
||||
|
||||
export const aboutResource = [
|
||||
{
|
||||
title: i18n.global.t("certd.dashboard.helpDoc"),
|
||||
name: "document",
|
||||
path: "/about/doc",
|
||||
component: IFrameView,
|
||||
meta: {
|
||||
icon: "lucide:book-open-text",
|
||||
link: "https://certd.docmirror.cn",
|
||||
title: i18n.global.t("certd.dashboard.helpDoc"),
|
||||
order: 9999,
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return !settingStore.isComm;
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.dashboard.helpDoc",
|
||||
name: "document",
|
||||
path: "/about/doc",
|
||||
component: IFrameView,
|
||||
meta: {
|
||||
icon: "lucide:book-open-text",
|
||||
link: "https://certd.docmirror.cn",
|
||||
title: "certd.dashboard.helpDoc",
|
||||
order: 9999,
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return !settingStore.isComm;
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export default aboutResource;
|
||||
|
|
|
@ -1,256 +1,255 @@
|
|||
import { useSettingStore } from "/@/store/settings";
|
||||
import aboutResource from "/@/router/source/modules/about";
|
||||
import i18n from '/@/locales/i18n';
|
||||
import i18n from "/@/locales/i18n";
|
||||
|
||||
export const certdResources = [
|
||||
{
|
||||
title: i18n.global.t("certd.title"),
|
||||
name: "CertdRoot",
|
||||
path: "/certd",
|
||||
redirect: "/certd/pipeline",
|
||||
meta: {
|
||||
icon: "ion:key-outline",
|
||||
auth: true,
|
||||
order: 0,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: i18n.global.t("certd.pipeline"),
|
||||
name: "PipelineManager",
|
||||
path: "/certd/pipeline",
|
||||
component: "/certd/pipeline/index.vue",
|
||||
meta: {
|
||||
icon: "ion:analytics-sharp",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.pipelineEdit"),
|
||||
name: "PipelineEdit",
|
||||
path: "/certd/pipeline/detail",
|
||||
component: "/certd/pipeline/detail.vue",
|
||||
meta: {
|
||||
isMenu: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.history"),
|
||||
name: "PipelineHistory",
|
||||
path: "/certd/history",
|
||||
component: "/certd/history/index.vue",
|
||||
meta: {
|
||||
icon: "ion:timer-outline",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.certStore"),
|
||||
name: "CertStore",
|
||||
path: "/certd/monitor/cert",
|
||||
component: "/certd/monitor/cert/index.vue",
|
||||
meta: {
|
||||
icon: "ion:shield-checkmark-outline",
|
||||
auth: true,
|
||||
isMenu: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.siteMonitor"),
|
||||
name: "SiteCertMonitor",
|
||||
path: "/certd/monitor/site",
|
||||
component: "/certd/monitor/site/index.vue",
|
||||
meta: {
|
||||
icon: "ion:videocam-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.settings"),
|
||||
name: "MineSetting",
|
||||
path: "/certd/setting",
|
||||
redirect: "/certd/access",
|
||||
meta: {
|
||||
icon: "ion:settings-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: i18n.global.t("certd.accessManager"),
|
||||
name: "AccessManager",
|
||||
path: "/certd/access",
|
||||
component: "/certd/access/index.vue",
|
||||
meta: {
|
||||
icon: "ion:disc-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.cnameRecord"),
|
||||
name: "CnameRecord",
|
||||
path: "/certd/cname/record",
|
||||
component: "/certd/cname/record/index.vue",
|
||||
meta: {
|
||||
icon: "ion:link-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.subDomain"),
|
||||
name: "SubDomain",
|
||||
path: "/certd/pipeline/subDomain",
|
||||
component: "/certd/pipeline/sub-domain/index.vue",
|
||||
meta: {
|
||||
icon: "material-symbols:approval-delegation-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.pipelineGroup"),
|
||||
name: "PipelineGroupManager",
|
||||
path: "/certd/pipeline/group",
|
||||
component: "/certd/pipeline/group/index.vue",
|
||||
meta: {
|
||||
icon: "mdi:format-list-group",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.openKey"),
|
||||
name: "OpenKey",
|
||||
path: "/certd/open/openkey",
|
||||
component: "/certd/open/openkey/index.vue",
|
||||
meta: {
|
||||
icon: "hugeicons:api",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.notification"),
|
||||
name: "NotificationManager",
|
||||
path: "/certd/notification",
|
||||
component: "/certd/notification/index.vue",
|
||||
meta: {
|
||||
icon: "ion:megaphone-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.siteMonitorSetting"),
|
||||
name: "SiteMonitorSetting",
|
||||
path: "/certd/monitor/setting",
|
||||
component: "/certd/monitor/site/setting/index.vue",
|
||||
meta: {
|
||||
icon: "ion:videocam-outline",
|
||||
auth: true,
|
||||
isMenu: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.userSecurity"),
|
||||
name: "UserSecurity",
|
||||
path: "/certd/mine/security",
|
||||
component: "/certd/mine/security/index.vue",
|
||||
meta: {
|
||||
icon: "fluent:shield-keyhole-16-regular",
|
||||
auth: true,
|
||||
isMenu: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.userProfile"),
|
||||
name: "UserProfile",
|
||||
path: "/certd/mine/user-profile",
|
||||
component: "/certd/mine/user-profile.vue",
|
||||
meta: {
|
||||
icon: "ion:person-outline",
|
||||
auth: true,
|
||||
isMenu: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.suite"),
|
||||
name: "SuiteProduct",
|
||||
path: "/certd/suite",
|
||||
redirect: "/certd/suite/mine",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm && settingStore.isSuiteEnabled;
|
||||
},
|
||||
icon: "ion:cart-outline",
|
||||
auth: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: i18n.global.t("certd.mySuite"),
|
||||
name: "MySuite",
|
||||
path: "/certd/suite/mine",
|
||||
component: "/certd/suite/mine/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:gift-outline",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.suiteBuy"),
|
||||
name: "SuiteProductBuy",
|
||||
path: "/certd/suite/buy",
|
||||
component: "/certd/suite/buy.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:cart-outline",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.myTrade"),
|
||||
name: "MyTrade",
|
||||
path: "/certd/trade",
|
||||
component: "/certd/trade/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:bag-check-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t("certd.paymentReturn"),
|
||||
name: "PaymentReturn",
|
||||
path: "/certd/payment/return/:type",
|
||||
component: "/certd/payment/return.vue",
|
||||
meta: {
|
||||
icon: "ant-design:pay-circle-outlined",
|
||||
auth: false,
|
||||
isMenu: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "certd.title",
|
||||
name: "CertdRoot",
|
||||
path: "/certd",
|
||||
redirect: "/certd/pipeline",
|
||||
meta: {
|
||||
icon: "ion:key-outline",
|
||||
auth: true,
|
||||
order: 0,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: "certd.pipeline",
|
||||
name: "PipelineManager",
|
||||
path: "/certd/pipeline",
|
||||
component: "/certd/pipeline/index.vue",
|
||||
meta: {
|
||||
icon: "ion:analytics-sharp",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.pipelineEdit",
|
||||
name: "PipelineEdit",
|
||||
path: "/certd/pipeline/detail",
|
||||
component: "/certd/pipeline/detail.vue",
|
||||
meta: {
|
||||
isMenu: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.history",
|
||||
name: "PipelineHistory",
|
||||
path: "/certd/history",
|
||||
component: "/certd/history/index.vue",
|
||||
meta: {
|
||||
icon: "ion:timer-outline",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.certStore",
|
||||
name: "CertStore",
|
||||
path: "/certd/monitor/cert",
|
||||
component: "/certd/monitor/cert/index.vue",
|
||||
meta: {
|
||||
icon: "ion:shield-checkmark-outline",
|
||||
auth: true,
|
||||
isMenu: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.siteMonitor",
|
||||
name: "SiteCertMonitor",
|
||||
path: "/certd/monitor/site",
|
||||
component: "/certd/monitor/site/index.vue",
|
||||
meta: {
|
||||
icon: "ion:videocam-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.settings",
|
||||
name: "MineSetting",
|
||||
path: "/certd/setting",
|
||||
redirect: "/certd/access",
|
||||
meta: {
|
||||
icon: "ion:settings-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: "certd.accessManager",
|
||||
name: "AccessManager",
|
||||
path: "/certd/access",
|
||||
component: "/certd/access/index.vue",
|
||||
meta: {
|
||||
icon: "ion:disc-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.cnameRecord",
|
||||
name: "CnameRecord",
|
||||
path: "/certd/cname/record",
|
||||
component: "/certd/cname/record/index.vue",
|
||||
meta: {
|
||||
icon: "ion:link-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.subDomain",
|
||||
name: "SubDomain",
|
||||
path: "/certd/pipeline/subDomain",
|
||||
component: "/certd/pipeline/sub-domain/index.vue",
|
||||
meta: {
|
||||
icon: "material-symbols:approval-delegation-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.pipelineGroup",
|
||||
name: "PipelineGroupManager",
|
||||
path: "/certd/pipeline/group",
|
||||
component: "/certd/pipeline/group/index.vue",
|
||||
meta: {
|
||||
icon: "mdi:format-list-group",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.openKey",
|
||||
name: "OpenKey",
|
||||
path: "/certd/open/openkey",
|
||||
component: "/certd/open/openkey/index.vue",
|
||||
meta: {
|
||||
icon: "hugeicons:api",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.notification",
|
||||
name: "NotificationManager",
|
||||
path: "/certd/notification",
|
||||
component: "/certd/notification/index.vue",
|
||||
meta: {
|
||||
icon: "ion:megaphone-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.siteMonitorSetting",
|
||||
name: "SiteMonitorSetting",
|
||||
path: "/certd/monitor/setting",
|
||||
component: "/certd/monitor/site/setting/index.vue",
|
||||
meta: {
|
||||
icon: "ion:videocam-outline",
|
||||
auth: true,
|
||||
isMenu: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.userSecurity",
|
||||
name: "UserSecurity",
|
||||
path: "/certd/mine/security",
|
||||
component: "/certd/mine/security/index.vue",
|
||||
meta: {
|
||||
icon: "fluent:shield-keyhole-16-regular",
|
||||
auth: true,
|
||||
isMenu: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.userProfile",
|
||||
name: "UserProfile",
|
||||
path: "/certd/mine/user-profile",
|
||||
component: "/certd/mine/user-profile.vue",
|
||||
meta: {
|
||||
icon: "ion:person-outline",
|
||||
auth: true,
|
||||
isMenu: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "certd.suite",
|
||||
name: "SuiteProduct",
|
||||
path: "/certd/suite",
|
||||
redirect: "/certd/suite/mine",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm && settingStore.isSuiteEnabled;
|
||||
},
|
||||
icon: "ion:cart-outline",
|
||||
auth: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: "certd.mySuite",
|
||||
name: "MySuite",
|
||||
path: "/certd/suite/mine",
|
||||
component: "/certd/suite/mine/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:gift-outline",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.suiteBuy",
|
||||
name: "SuiteProductBuy",
|
||||
path: "/certd/suite/buy",
|
||||
component: "/certd/suite/buy.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:cart-outline",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.myTrade",
|
||||
name: "MyTrade",
|
||||
path: "/certd/trade",
|
||||
component: "/certd/trade/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:bag-check-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.paymentReturn",
|
||||
name: "PaymentReturn",
|
||||
path: "/certd/payment/return/:type",
|
||||
component: "/certd/payment/return.vue",
|
||||
meta: {
|
||||
icon: "ant-design:pay-circle-outlined",
|
||||
auth: false,
|
||||
isMenu: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
export default certdResources;
|
||||
|
|
|
@ -1,256 +1,256 @@
|
|||
import LayoutPass from "/@/layout/layout-pass.vue";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import aboutResource from "/@/router/source/modules/about";
|
||||
import i18n from '/@/locales/i18n';
|
||||
import i18n from "/@/locales/i18n";
|
||||
|
||||
export const sysResources = [
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.sysRoot'),
|
||||
name: "SysRoot",
|
||||
path: "/sys",
|
||||
redirect: "/sys/settings",
|
||||
meta: {
|
||||
icon: "ion:settings-outline",
|
||||
permission: "sys:settings:view",
|
||||
order: 10,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.sysConsole'),
|
||||
name: "SysConsole",
|
||||
path: "/sys/console",
|
||||
component: "/sys/console/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:speedometer-outline",
|
||||
permission: "sys:auth:user:view",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.sysRoot",
|
||||
name: "SysRoot",
|
||||
path: "/sys",
|
||||
redirect: "/sys/settings",
|
||||
meta: {
|
||||
icon: "ion:settings-outline",
|
||||
permission: "sys:settings:view",
|
||||
order: 10,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: "certd.sysResources.sysConsole",
|
||||
name: "SysConsole",
|
||||
path: "/sys/console",
|
||||
component: "/sys/console/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:speedometer-outline",
|
||||
permission: "sys:auth:user:view",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.sysSettings'),
|
||||
name: "SysSettings",
|
||||
path: "/sys/settings",
|
||||
component: "/sys/settings/index.vue",
|
||||
meta: {
|
||||
icon: "ion:settings-outline",
|
||||
permission: "sys:settings:view",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.cnameSetting'),
|
||||
name: "CnameSetting",
|
||||
path: "/sys/cname/provider",
|
||||
component: "/sys/cname/provider/index.vue",
|
||||
meta: {
|
||||
icon: "ion:earth-outline",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.emailSetting'),
|
||||
name: "EmailSetting",
|
||||
path: "/sys/settings/email",
|
||||
component: "/sys/settings/email/index.vue",
|
||||
meta: {
|
||||
permission: "sys:settings:view",
|
||||
icon: "ion:mail-outline",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.siteSetting'),
|
||||
name: "SiteSetting",
|
||||
path: "/sys/site",
|
||||
component: "/sys/site/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:document-text-outline",
|
||||
permission: "sys:settings:view",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.headerMenus'),
|
||||
name: "HeaderMenus",
|
||||
path: "/sys/settings/header-menus",
|
||||
component: "/sys/settings/header-menus/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:menu",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.sysAccess'),
|
||||
name: "SysAccess",
|
||||
path: "/sys/access",
|
||||
component: "/sys/access/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:disc-outline",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.sysPlugin'),
|
||||
name: "SysPlugin",
|
||||
path: "/sys/plugin",
|
||||
component: "/sys/plugin/index.vue",
|
||||
meta: {
|
||||
icon: "ion:extension-puzzle-outline",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.sysPluginEdit'),
|
||||
name: "SysPluginEdit",
|
||||
path: "/sys/plugin/edit",
|
||||
component: "/sys/plugin/edit.vue",
|
||||
meta: {
|
||||
isMenu: false,
|
||||
icon: "ion:extension-puzzle",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.sysPluginConfig'),
|
||||
name: "SysPluginConfig",
|
||||
path: "/sys/plugin/config",
|
||||
component: "/sys/plugin/config.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:extension-puzzle",
|
||||
permission: "sys:settings:view",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.accountBind'),
|
||||
name: "AccountBind",
|
||||
path: "/sys/account",
|
||||
component: "/sys/account/index.vue",
|
||||
meta: {
|
||||
icon: "ion:golf-outline",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.permissionManager'),
|
||||
name: "PermissionManager",
|
||||
path: "/sys/authority/permission",
|
||||
component: "/sys/authority/permission/index.vue",
|
||||
meta: {
|
||||
icon: "ion:list-outline",
|
||||
permission: "sys:auth:per:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.roleManager'),
|
||||
name: "RoleManager",
|
||||
path: "/sys/authority/role",
|
||||
component: "/sys/authority/role/index.vue",
|
||||
meta: {
|
||||
icon: "ion:people-outline",
|
||||
permission: "sys:auth:role:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.userManager'),
|
||||
name: "UserManager",
|
||||
path: "/sys/authority/user",
|
||||
component: "/sys/authority/user/index.vue",
|
||||
meta: {
|
||||
icon: "ion:person-outline",
|
||||
permission: "sys:auth:user:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.sysSettings",
|
||||
name: "SysSettings",
|
||||
path: "/sys/settings",
|
||||
component: "/sys/settings/index.vue",
|
||||
meta: {
|
||||
icon: "ion:settings-outline",
|
||||
permission: "sys:settings:view",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.cnameSetting",
|
||||
name: "CnameSetting",
|
||||
path: "/sys/cname/provider",
|
||||
component: "/sys/cname/provider/index.vue",
|
||||
meta: {
|
||||
icon: "ion:earth-outline",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.emailSetting",
|
||||
name: "EmailSetting",
|
||||
path: "/sys/settings/email",
|
||||
component: "/sys/settings/email/index.vue",
|
||||
meta: {
|
||||
permission: "sys:settings:view",
|
||||
icon: "ion:mail-outline",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.siteSetting",
|
||||
name: "SiteSetting",
|
||||
path: "/sys/site",
|
||||
component: "/sys/site/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:document-text-outline",
|
||||
permission: "sys:settings:view",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.headerMenus",
|
||||
name: "HeaderMenus",
|
||||
path: "/sys/settings/header-menus",
|
||||
component: "/sys/settings/header-menus/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:menu",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.sysAccess",
|
||||
name: "SysAccess",
|
||||
path: "/sys/access",
|
||||
component: "/sys/access/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:disc-outline",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.sysPlugin",
|
||||
name: "SysPlugin",
|
||||
path: "/sys/plugin",
|
||||
component: "/sys/plugin/index.vue",
|
||||
meta: {
|
||||
icon: "ion:extension-puzzle-outline",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.sysPluginEdit",
|
||||
name: "SysPluginEdit",
|
||||
path: "/sys/plugin/edit",
|
||||
component: "/sys/plugin/edit.vue",
|
||||
meta: {
|
||||
isMenu: false,
|
||||
icon: "ion:extension-puzzle",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.sysPluginConfig",
|
||||
name: "SysPluginConfig",
|
||||
path: "/sys/plugin/config",
|
||||
component: "/sys/plugin/config.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:extension-puzzle",
|
||||
permission: "sys:settings:view",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.accountBind",
|
||||
name: "AccountBind",
|
||||
path: "/sys/account",
|
||||
component: "/sys/account/index.vue",
|
||||
meta: {
|
||||
icon: "ion:golf-outline",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.permissionManager",
|
||||
name: "PermissionManager",
|
||||
path: "/sys/authority/permission",
|
||||
component: "/sys/authority/permission/index.vue",
|
||||
meta: {
|
||||
icon: "ion:list-outline",
|
||||
permission: "sys:auth:per:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.roleManager",
|
||||
name: "RoleManager",
|
||||
path: "/sys/authority/role",
|
||||
component: "/sys/authority/role/index.vue",
|
||||
meta: {
|
||||
icon: "ion:people-outline",
|
||||
permission: "sys:auth:role:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.userManager",
|
||||
name: "UserManager",
|
||||
path: "/sys/authority/user",
|
||||
component: "/sys/authority/user/index.vue",
|
||||
meta: {
|
||||
icon: "ion:person-outline",
|
||||
permission: "sys:auth:user:view",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.suiteManager'),
|
||||
name: "SuiteManager",
|
||||
path: "/sys/suite",
|
||||
redirect: "/sys/suite/setting",
|
||||
meta: {
|
||||
icon: "ion:cart-outline",
|
||||
permission: "sys:settings:edit",
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
keepAlive: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.suiteSetting'),
|
||||
name: "SuiteSetting",
|
||||
path: "/sys/suite/setting",
|
||||
component: "/sys/suite/setting/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:cart",
|
||||
permission: "sys:settings:edit",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.orderManager'),
|
||||
name: "OrderManager",
|
||||
path: "/sys/suite/trade",
|
||||
component: "/sys/suite/trade/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:bag-check",
|
||||
permission: "sys:settings:edit",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18n.global.t('certd.sysResources.userSuites'),
|
||||
name: "UserSuites",
|
||||
path: "/sys/suite/user-suite",
|
||||
component: "/sys/suite/user-suite/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:gift-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.suiteManager",
|
||||
name: "SuiteManager",
|
||||
path: "/sys/suite",
|
||||
redirect: "/sys/suite/setting",
|
||||
meta: {
|
||||
icon: "ion:cart-outline",
|
||||
permission: "sys:settings:edit",
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
keepAlive: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: "certd.sysResources.suiteSetting",
|
||||
name: "SuiteSetting",
|
||||
path: "/sys/suite/setting",
|
||||
component: "/sys/suite/setting/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:cart",
|
||||
permission: "sys:settings:edit",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.orderManager",
|
||||
name: "OrderManager",
|
||||
path: "/sys/suite/trade",
|
||||
component: "/sys/suite/trade/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:bag-check",
|
||||
permission: "sys:settings:edit",
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.userSuites",
|
||||
name: "UserSuites",
|
||||
path: "/sys/suite/user-suite",
|
||||
component: "/sys/suite/user-suite/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:gift-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default sysResources;
|
||||
|
|
|
@ -10,21 +10,21 @@ export const outsideResource = [
|
|||
children: [
|
||||
{
|
||||
meta: {
|
||||
title: "登录"
|
||||
title: "登录",
|
||||
},
|
||||
name: "login",
|
||||
path: "/login",
|
||||
component: "/framework/login/index.vue"
|
||||
component: "/framework/login/index.vue",
|
||||
},
|
||||
{
|
||||
meta: {
|
||||
title: "注册"
|
||||
title: "注册",
|
||||
},
|
||||
name: "register",
|
||||
path: "/register",
|
||||
component: "/framework/register/index.vue"
|
||||
}
|
||||
]
|
||||
component: "/framework/register/index.vue",
|
||||
},
|
||||
],
|
||||
},
|
||||
...errorPage
|
||||
...errorPage,
|
||||
];
|
||||
|
|
|
@ -1,161 +1,163 @@
|
|||
import { defineStore } from "pinia";
|
||||
import * as api from "./api.plugin";
|
||||
import { DynamicType, FormItemProps } from "@fast-crud/fast-crud";
|
||||
|
||||
import { i18n } from "/src/locales/i18n";
|
||||
interface PluginState {
|
||||
group?: PluginGroups;
|
||||
group?: PluginGroups;
|
||||
}
|
||||
|
||||
export type PluginGroup = {
|
||||
key: string;
|
||||
title: string;
|
||||
desc?: string;
|
||||
order: number;
|
||||
icon: string;
|
||||
plugins: any[];
|
||||
key: string;
|
||||
title: string;
|
||||
desc?: string;
|
||||
order: number;
|
||||
icon: string;
|
||||
plugins: any[];
|
||||
};
|
||||
|
||||
export type PluginDefine = {
|
||||
name: string;
|
||||
title: string;
|
||||
desc?: string;
|
||||
shortcut: any;
|
||||
input: {
|
||||
[key: string]: DynamicType<FormItemProps>;
|
||||
};
|
||||
output: {
|
||||
[key: string]: any;
|
||||
};
|
||||
name: string;
|
||||
title: string;
|
||||
desc?: string;
|
||||
shortcut: any;
|
||||
input: {
|
||||
[key: string]: DynamicType<FormItemProps>;
|
||||
};
|
||||
output: {
|
||||
[key: string]: any;
|
||||
};
|
||||
};
|
||||
|
||||
export class PluginGroups {
|
||||
groups!: { [key: string]: PluginGroup };
|
||||
map!: { [key: string]: PluginDefine };
|
||||
constructor(groups: { [key: string]: PluginGroup }) {
|
||||
this.groups = groups;
|
||||
this.initGroup(groups);
|
||||
this.initMap();
|
||||
}
|
||||
groups!: { [key: string]: PluginGroup };
|
||||
map!: { [key: string]: PluginDefine };
|
||||
t: any;
|
||||
constructor(groups: { [key: string]: PluginGroup }) {
|
||||
this.groups = groups;
|
||||
this.t = i18n.global.t;
|
||||
this.initGroup(groups);
|
||||
this.initMap();
|
||||
}
|
||||
|
||||
private initGroup(groups: { [p: string]: PluginGroup }) {
|
||||
const all: PluginGroup = {
|
||||
key: "all",
|
||||
title: t('certd.all'),
|
||||
order: 0,
|
||||
plugins: [],
|
||||
icon: "material-symbols:border-all-rounded",
|
||||
};
|
||||
for (const key in groups) {
|
||||
all.plugins.push(...groups[key].plugins);
|
||||
}
|
||||
this.groups = {
|
||||
all,
|
||||
...groups,
|
||||
};
|
||||
}
|
||||
private initGroup(groups: { [p: string]: PluginGroup }) {
|
||||
const all: PluginGroup = {
|
||||
key: "all",
|
||||
title: this.t("certd.all"),
|
||||
order: 0,
|
||||
plugins: [],
|
||||
icon: "material-symbols:border-all-rounded",
|
||||
};
|
||||
for (const key in groups) {
|
||||
all.plugins.push(...groups[key].plugins);
|
||||
}
|
||||
this.groups = {
|
||||
all,
|
||||
...groups,
|
||||
};
|
||||
}
|
||||
|
||||
initMap() {
|
||||
const map: { [key: string]: PluginDefine } = {};
|
||||
for (const key in this.groups) {
|
||||
const group = this.groups[key];
|
||||
for (const plugin of group.plugins) {
|
||||
map[plugin.name] = plugin;
|
||||
}
|
||||
}
|
||||
this.map = map;
|
||||
}
|
||||
initMap() {
|
||||
const map: { [key: string]: PluginDefine } = {};
|
||||
for (const key in this.groups) {
|
||||
const group = this.groups[key];
|
||||
for (const plugin of group.plugins) {
|
||||
map[plugin.name] = plugin;
|
||||
}
|
||||
}
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
getGroups() {
|
||||
return this.groups;
|
||||
}
|
||||
getGroups() {
|
||||
return this.groups;
|
||||
}
|
||||
|
||||
get(name: string) {
|
||||
return this.map[name];
|
||||
}
|
||||
get(name: string) {
|
||||
return this.map[name];
|
||||
}
|
||||
|
||||
getPreStepOutputOptions({ pipeline, currentStageIndex, currentTaskIndex, currentStepIndex, currentTask }: any) {
|
||||
const steps = this.collectionPreStepOutputs({
|
||||
pipeline,
|
||||
currentStageIndex,
|
||||
currentTaskIndex,
|
||||
currentStepIndex,
|
||||
currentTask,
|
||||
});
|
||||
const options: any[] = [];
|
||||
for (const step of steps) {
|
||||
const stepDefine = this.get(step.type);
|
||||
for (const key in stepDefine?.output) {
|
||||
options.push({
|
||||
value: `step.${step.id}.${key}`,
|
||||
label: `${stepDefine.output[key].title}【from:${step.title}】`,
|
||||
type: step.type,
|
||||
});
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
getPreStepOutputOptions({ pipeline, currentStageIndex, currentTaskIndex, currentStepIndex, currentTask }: any) {
|
||||
const steps = this.collectionPreStepOutputs({
|
||||
pipeline,
|
||||
currentStageIndex,
|
||||
currentTaskIndex,
|
||||
currentStepIndex,
|
||||
currentTask,
|
||||
});
|
||||
const options: any[] = [];
|
||||
for (const step of steps) {
|
||||
const stepDefine = this.get(step.type);
|
||||
for (const key in stepDefine?.output) {
|
||||
options.push({
|
||||
value: `step.${step.id}.${key}`,
|
||||
label: `${stepDefine.output[key].title}【from:${step.title}】`,
|
||||
type: step.type,
|
||||
});
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
collectionPreStepOutputs({ pipeline, currentStageIndex, currentTaskIndex, currentStepIndex, currentTask }: any) {
|
||||
const steps: any[] = [];
|
||||
// 开始放step
|
||||
for (let i = 0; i < currentStageIndex; i++) {
|
||||
const stage = pipeline.stages[i];
|
||||
for (const task of stage.tasks) {
|
||||
for (const step of task.steps) {
|
||||
steps.push(step);
|
||||
}
|
||||
}
|
||||
}
|
||||
//当前阶段之前的task
|
||||
const currentStage = pipeline.stages[currentStageIndex];
|
||||
for (let i = 0; i < currentTaskIndex; i++) {
|
||||
const task = currentStage.tasks[i];
|
||||
for (const step of task.steps) {
|
||||
steps.push(step);
|
||||
}
|
||||
}
|
||||
//放当前任务下的step
|
||||
for (let i = 0; i < currentStepIndex; i++) {
|
||||
const step = currentTask.steps[i];
|
||||
steps.push(step);
|
||||
}
|
||||
return steps;
|
||||
}
|
||||
collectionPreStepOutputs({ pipeline, currentStageIndex, currentTaskIndex, currentStepIndex, currentTask }: any) {
|
||||
const steps: any[] = [];
|
||||
// 开始放step
|
||||
for (let i = 0; i < currentStageIndex; i++) {
|
||||
const stage = pipeline.stages[i];
|
||||
for (const task of stage.tasks) {
|
||||
for (const step of task.steps) {
|
||||
steps.push(step);
|
||||
}
|
||||
}
|
||||
}
|
||||
//当前阶段之前的task
|
||||
const currentStage = pipeline.stages[currentStageIndex];
|
||||
for (let i = 0; i < currentTaskIndex; i++) {
|
||||
const task = currentStage.tasks[i];
|
||||
for (const step of task.steps) {
|
||||
steps.push(step);
|
||||
}
|
||||
}
|
||||
//放当前任务下的step
|
||||
for (let i = 0; i < currentStepIndex; i++) {
|
||||
const step = currentTask.steps[i];
|
||||
steps.push(step);
|
||||
}
|
||||
return steps;
|
||||
}
|
||||
}
|
||||
|
||||
export const usePluginStore = defineStore({
|
||||
id: "app.plugin",
|
||||
state: (): PluginState => ({
|
||||
group: null,
|
||||
}),
|
||||
actions: {
|
||||
async reload() {
|
||||
const groups = await api.GetGroups({});
|
||||
this.group = new PluginGroups(groups);
|
||||
},
|
||||
async init() {
|
||||
if (!this.group) {
|
||||
await this.reload();
|
||||
}
|
||||
return this.group;
|
||||
},
|
||||
async getGroups(): Promise<PluginGroups> {
|
||||
await this.init();
|
||||
return this.group as PluginGroups;
|
||||
},
|
||||
async clear() {
|
||||
this.group = null;
|
||||
},
|
||||
async getList(): Promise<PluginDefine[]> {
|
||||
await this.init();
|
||||
return this.group.groups.all.plugins;
|
||||
},
|
||||
async getPluginDefine(name: string): Promise<PluginDefine> {
|
||||
await this.init();
|
||||
return this.group.get(name);
|
||||
},
|
||||
async getPluginConfig(query: any) {
|
||||
return await api.GetPluginConfig(query);
|
||||
},
|
||||
},
|
||||
id: "app.plugin",
|
||||
state: (): PluginState => ({
|
||||
group: null,
|
||||
}),
|
||||
actions: {
|
||||
async reload() {
|
||||
const groups = await api.GetGroups({});
|
||||
this.group = new PluginGroups(groups);
|
||||
},
|
||||
async init() {
|
||||
if (!this.group) {
|
||||
await this.reload();
|
||||
}
|
||||
return this.group;
|
||||
},
|
||||
async getGroups(): Promise<PluginGroups> {
|
||||
await this.init();
|
||||
return this.group as PluginGroups;
|
||||
},
|
||||
async clear() {
|
||||
this.group = null;
|
||||
},
|
||||
async getList(): Promise<PluginDefine[]> {
|
||||
await this.init();
|
||||
return this.group.groups.all.plugins;
|
||||
},
|
||||
async getPluginDefine(name: string): Promise<PluginDefine> {
|
||||
await this.init();
|
||||
return this.group.get(name);
|
||||
},
|
||||
async getPluginConfig(query: any) {
|
||||
return await api.GetPluginConfig(query);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import type { VbenFormSchema } from '/@/vben/form-ui';
|
||||
import type { VbenFormSchema } from "/@/vben/form-ui";
|
||||
|
||||
import { computed, reactive } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { computed, reactive } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
import { $t } from '/@/locales';
|
||||
import { $t } from "/@/locales";
|
||||
|
||||
import { useVbenForm } from '/@/vben/form-ui';
|
||||
import { VbenButton } from '/@/vben/shadcn-ui';
|
||||
import { useVbenForm } from "/@/vben/form-ui";
|
||||
import { VbenButton } from "/@/vben/shadcn-ui";
|
||||
|
||||
import Title from './auth-title.vue';
|
||||
import Title from "./auth-title.vue";
|
||||
|
||||
interface Props {
|
||||
formSchema: VbenFormSchema[];
|
||||
|
@ -36,15 +36,15 @@ interface Props {
|
|||
}
|
||||
|
||||
defineOptions({
|
||||
name: 'ForgetPassword',
|
||||
name: "ForgetPassword",
|
||||
});
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
loading: false,
|
||||
loginPath: '/auth/login',
|
||||
submitButtonText: '',
|
||||
subTitle: '',
|
||||
title: '',
|
||||
loginPath: "/auth/login",
|
||||
submitButtonText: "",
|
||||
subTitle: "",
|
||||
title: "",
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -59,7 +59,7 @@ const [Form, formApi] = useVbenForm(
|
|||
},
|
||||
schema: computed(() => props.formSchema),
|
||||
showDefaultActions: false,
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
const router = useRouter();
|
||||
|
@ -68,7 +68,7 @@ async function handleSubmit() {
|
|||
const { valid } = await formApi.validate();
|
||||
const values = await formApi.getValues();
|
||||
if (valid) {
|
||||
emit('submit', values);
|
||||
emit("submit", values);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,12 +84,10 @@ defineExpose({
|
|||
<template>
|
||||
<div>
|
||||
<Title>
|
||||
<slot name="title">
|
||||
{{ title || $t('authentication.forgetPassword') }} 🤦🏻♂️
|
||||
</slot>
|
||||
<slot name="title"> {{ title || $t("authentication.forgetPassword") }} 🤦🏻♂️ </slot>
|
||||
<template #desc>
|
||||
<slot name="subTitle">
|
||||
{{ subTitle || $t('authentication.forgetPasswordSubtitle') }}
|
||||
{{ subTitle || $t("authentication.forgetPasswordSubtitle") }}
|
||||
</slot>
|
||||
</template>
|
||||
</Title>
|
||||
|
@ -105,11 +103,11 @@ defineExpose({
|
|||
@click="handleSubmit"
|
||||
>
|
||||
<slot name="submitButtonText">
|
||||
{{ submitButtonText || $t('authentication.sendResetLink') }}
|
||||
{{ submitButtonText || $t("authentication.sendResetLink") }}
|
||||
</slot>
|
||||
</VbenButton>
|
||||
<VbenButton class="mt-4 w-full" variant="outline" @click="goToLogin()">
|
||||
{{ $t('common.back') }}
|
||||
{{ $t("common.back") }}
|
||||
</VbenButton>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
export { default as Breadcrumb } from './breadcrumb.vue';
|
||||
export * from './check-updates';
|
||||
export { default as AuthenticationColorToggle } from './color-toggle.vue';
|
||||
export * from './global-search';
|
||||
export { default as LanguageToggle } from './language-toggle.vue';
|
||||
export { default as AuthenticationLayoutToggle } from './layout-toggle.vue';
|
||||
export * from './lock-screen';
|
||||
export * from './notification';
|
||||
export * from './preferences';
|
||||
export * from './theme-toggle';
|
||||
export * from './user-dropdown';
|
||||
export { default as Breadcrumb } from "./breadcrumb.vue";
|
||||
export * from "./check-updates";
|
||||
export { default as AuthenticationColorToggle } from "./color-toggle.vue";
|
||||
export * from "./global-search";
|
||||
export { default as LanguageToggle } from "./language-toggle.vue";
|
||||
export { default as AuthenticationLayoutToggle } from "./layout-toggle.vue";
|
||||
export * from "./lock-screen";
|
||||
export * from "./notification";
|
||||
export * from "./preferences";
|
||||
export * from "./theme-toggle";
|
||||
export * from "./user-dropdown";
|
||||
|
|
|
@ -12,25 +12,25 @@ import { preferences, updatePreferences, usePreferences } from "/@/vben/preferen
|
|||
import { VbenDropdownRadioMenu, VbenIconButton } from "/@/vben//shadcn-ui";
|
||||
|
||||
defineOptions({
|
||||
name: "AuthenticationLayoutToggle"
|
||||
name: "AuthenticationLayoutToggle",
|
||||
});
|
||||
|
||||
const menus = computed((): VbenDropdownMenuItem[] => [
|
||||
{
|
||||
icon: PanelLeft,
|
||||
label: $t("authentication.layout.alignLeft"),
|
||||
value: "panel-left"
|
||||
value: "panel-left",
|
||||
},
|
||||
{
|
||||
icon: InspectionPanel,
|
||||
label: $t("authentication.layout.center"),
|
||||
value: "panel-center"
|
||||
value: "panel-center",
|
||||
},
|
||||
{
|
||||
icon: PanelRight,
|
||||
label: $t("authentication.layout.alignRight"),
|
||||
value: "panel-right"
|
||||
}
|
||||
value: "panel-right",
|
||||
},
|
||||
]);
|
||||
|
||||
const { authPanelCenter, authPanelLeft, authPanelRight } = usePreferences();
|
||||
|
@ -38,8 +38,8 @@ const { authPanelCenter, authPanelLeft, authPanelRight } = usePreferences();
|
|||
function handleUpdate(value: string) {
|
||||
updatePreferences({
|
||||
app: {
|
||||
authPageLayout: value as AuthPageLayoutType
|
||||
}
|
||||
authPageLayout: value as AuthPageLayoutType,
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,71 +1,69 @@
|
|||
<script setup lang="ts">
|
||||
import type { SelectOption } from '/@/vben/types';
|
||||
import type { SelectOption } from "/@/vben/types";
|
||||
|
||||
import { computed } from 'vue';
|
||||
import { computed } from "vue";
|
||||
|
||||
import { $t } from '/@/locales';
|
||||
import { $t } from "/@/locales";
|
||||
|
||||
import SelectItem from '../select-item.vue';
|
||||
import SwitchItem from '../switch-item.vue';
|
||||
import SelectItem from "../select-item.vue";
|
||||
import SwitchItem from "../switch-item.vue";
|
||||
|
||||
defineOptions({
|
||||
name: 'PreferenceInterfaceControl',
|
||||
name: "PreferenceInterfaceControl",
|
||||
});
|
||||
|
||||
const widgetGlobalSearch = defineModel<boolean>('widgetGlobalSearch');
|
||||
const widgetFullscreen = defineModel<boolean>('widgetFullscreen');
|
||||
const widgetLanguageToggle = defineModel<boolean>('widgetLanguageToggle');
|
||||
const widgetNotification = defineModel<boolean>('widgetNotification');
|
||||
const widgetThemeToggle = defineModel<boolean>('widgetThemeToggle');
|
||||
const widgetSidebarToggle = defineModel<boolean>('widgetSidebarToggle');
|
||||
const widgetLockScreen = defineModel<boolean>('widgetLockScreen');
|
||||
const appPreferencesButtonPosition = defineModel<string>(
|
||||
'appPreferencesButtonPosition',
|
||||
);
|
||||
const widgetRefresh = defineModel<boolean>('widgetRefresh');
|
||||
const widgetGlobalSearch = defineModel<boolean>("widgetGlobalSearch");
|
||||
const widgetFullscreen = defineModel<boolean>("widgetFullscreen");
|
||||
const widgetLanguageToggle = defineModel<boolean>("widgetLanguageToggle");
|
||||
const widgetNotification = defineModel<boolean>("widgetNotification");
|
||||
const widgetThemeToggle = defineModel<boolean>("widgetThemeToggle");
|
||||
const widgetSidebarToggle = defineModel<boolean>("widgetSidebarToggle");
|
||||
const widgetLockScreen = defineModel<boolean>("widgetLockScreen");
|
||||
const appPreferencesButtonPosition = defineModel<string>("appPreferencesButtonPosition");
|
||||
const widgetRefresh = defineModel<boolean>("widgetRefresh");
|
||||
|
||||
const positionItems = computed((): SelectOption[] => [
|
||||
{
|
||||
label: $t('preferences.position.auto'),
|
||||
value: 'auto',
|
||||
label: $t("preferences.position.auto"),
|
||||
value: "auto",
|
||||
},
|
||||
{
|
||||
label: $t('preferences.position.header'),
|
||||
value: 'header',
|
||||
label: $t("preferences.position.header"),
|
||||
value: "header",
|
||||
},
|
||||
{
|
||||
label: $t('preferences.position.fixed'),
|
||||
value: 'fixed',
|
||||
label: $t("preferences.position.fixed"),
|
||||
value: "fixed",
|
||||
},
|
||||
]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SwitchItem v-model="widgetGlobalSearch">
|
||||
{{ $t('preferences.widget.globalSearch') }}
|
||||
{{ $t("preferences.widget.globalSearch") }}
|
||||
</SwitchItem>
|
||||
<SwitchItem v-model="widgetThemeToggle">
|
||||
{{ $t('preferences.widget.themeToggle') }}
|
||||
{{ $t("preferences.widget.themeToggle") }}
|
||||
</SwitchItem>
|
||||
<SwitchItem v-model="widgetLanguageToggle">
|
||||
{{ $t('preferences.widget.languageToggle') }}
|
||||
{{ $t("preferences.widget.languageToggle") }}
|
||||
</SwitchItem>
|
||||
<SwitchItem v-model="widgetFullscreen">
|
||||
{{ $t('preferences.widget.fullscreen') }}
|
||||
{{ $t("preferences.widget.fullscreen") }}
|
||||
</SwitchItem>
|
||||
<SwitchItem v-model="widgetNotification">
|
||||
{{ $t('preferences.widget.notification') }}
|
||||
{{ $t("preferences.widget.notification") }}
|
||||
</SwitchItem>
|
||||
<SwitchItem v-model="widgetLockScreen">
|
||||
{{ $t('preferences.widget.lockScreen') }}
|
||||
{{ $t("preferences.widget.lockScreen") }}
|
||||
</SwitchItem>
|
||||
<SwitchItem v-model="widgetSidebarToggle">
|
||||
{{ $t('preferences.widget.sidebarToggle') }}
|
||||
{{ $t("preferences.widget.sidebarToggle") }}
|
||||
</SwitchItem>
|
||||
<SwitchItem v-model="widgetRefresh">
|
||||
{{ $t('preferences.widget.refresh') }}
|
||||
{{ $t("preferences.widget.refresh") }}
|
||||
</SwitchItem>
|
||||
<SelectItem v-model="appPreferencesButtonPosition" :items="positionItems">
|
||||
{{ $t('preferences.position.title') }}
|
||||
{{ $t("preferences.position.title") }}
|
||||
</SelectItem>
|
||||
</template>
|
||||
|
|
|
@ -108,7 +108,7 @@ const defaultPreferences: Preferences = {
|
|||
widget: {
|
||||
fullscreen: true,
|
||||
globalSearch: true,
|
||||
languageToggle: false,
|
||||
languageToggle: true,
|
||||
lockScreen: true,
|
||||
notification: false,
|
||||
refresh: true,
|
||||
|
|
|
@ -1,35 +1,23 @@
|
|||
import type { Preferences } from './types';
|
||||
import type { Preferences } from "./types";
|
||||
|
||||
import { preferencesManager } from './preferences';
|
||||
import { preferencesManager } from "./preferences";
|
||||
|
||||
// 偏好设置(带有层级关系)
|
||||
const preferences: Preferences =
|
||||
preferencesManager.getPreferences.apply(preferencesManager);
|
||||
const preferences: Preferences = preferencesManager.getPreferences.apply(preferencesManager);
|
||||
|
||||
// 更新偏好设置
|
||||
const updatePreferences =
|
||||
preferencesManager.updatePreferences.bind(preferencesManager);
|
||||
const updatePreferences = preferencesManager.updatePreferences.bind(preferencesManager);
|
||||
|
||||
// 重置偏好设置
|
||||
const resetPreferences =
|
||||
preferencesManager.resetPreferences.bind(preferencesManager);
|
||||
const resetPreferences = preferencesManager.resetPreferences.bind(preferencesManager);
|
||||
|
||||
const clearPreferencesCache =
|
||||
preferencesManager.clearCache.bind(preferencesManager);
|
||||
const clearPreferencesCache = preferencesManager.clearCache.bind(preferencesManager);
|
||||
|
||||
// 初始化偏好设置
|
||||
const initPreferences =
|
||||
preferencesManager.initPreferences.bind(preferencesManager);
|
||||
const initPreferences = preferencesManager.initPreferences.bind(preferencesManager);
|
||||
|
||||
export {
|
||||
clearPreferencesCache,
|
||||
initPreferences,
|
||||
preferences,
|
||||
preferencesManager,
|
||||
resetPreferences,
|
||||
updatePreferences,
|
||||
};
|
||||
export { clearPreferencesCache, initPreferences, preferences, preferencesManager, resetPreferences, updatePreferences };
|
||||
|
||||
export * from './constants';
|
||||
export type * from './types';
|
||||
export * from './use-preferences';
|
||||
export * from "./constants";
|
||||
export type * from "./types";
|
||||
export * from "./use-preferences";
|
||||
|
|
|
@ -1,22 +1,18 @@
|
|||
import type { DeepPartial } from '/@/vben/typings';
|
||||
import type { DeepPartial } from "/@/vben/typings";
|
||||
|
||||
import type { InitialOptions, Preferences } from './types';
|
||||
import type { InitialOptions, Preferences } from "./types";
|
||||
|
||||
import { markRaw, reactive, readonly, watch } from 'vue';
|
||||
import { markRaw, reactive, readonly, watch } from "vue";
|
||||
|
||||
import { StorageManager } from '/@/vben/shared/cache';
|
||||
import { isMacOs, merge } from '/@/vben/shared/utils';
|
||||
import { StorageManager } from "/@/vben/shared/cache";
|
||||
import { isMacOs, merge } from "/@/vben/shared/utils";
|
||||
|
||||
import {
|
||||
breakpointsTailwind,
|
||||
useBreakpoints,
|
||||
useDebounceFn,
|
||||
} from '@vueuse/core';
|
||||
import { breakpointsTailwind, useBreakpoints, useDebounceFn } from "@vueuse/core";
|
||||
|
||||
import { defaultPreferences } from './config';
|
||||
import { updateCSSVariables } from './update-css-variables';
|
||||
import { defaultPreferences } from "./config";
|
||||
import { updateCSSVariables } from "./update-css-variables";
|
||||
|
||||
const STORAGE_KEY = 'preferences';
|
||||
const STORAGE_KEY = "preferences";
|
||||
const STORAGE_KEY_LOCALE = `${STORAGE_KEY}-locale`;
|
||||
const STORAGE_KEY_THEME = `${STORAGE_KEY}-theme`;
|
||||
|
||||
|
@ -33,14 +29,11 @@ class PreferenceManager {
|
|||
this.cache = new StorageManager();
|
||||
|
||||
// 避免频繁的操作缓存
|
||||
this.savePreferences = useDebounceFn(
|
||||
(preference: Preferences) => this._savePreferences(preference),
|
||||
150,
|
||||
);
|
||||
this.savePreferences = useDebounceFn((preference: Preferences) => this._savePreferences(preference), 150);
|
||||
}
|
||||
|
||||
clearCache() {
|
||||
[STORAGE_KEY, STORAGE_KEY_LOCALE, STORAGE_KEY_THEME].forEach((key) => {
|
||||
[STORAGE_KEY, STORAGE_KEY_LOCALE, STORAGE_KEY_THEME].forEach(key => {
|
||||
this.cache?.removeItem(key);
|
||||
});
|
||||
}
|
||||
|
@ -73,7 +66,7 @@ class PreferenceManager {
|
|||
{},
|
||||
// overrides,
|
||||
this.loadCachedPreferences() || {},
|
||||
this.initialPreferences,
|
||||
this.initialPreferences
|
||||
);
|
||||
|
||||
// 更新偏好设置
|
||||
|
@ -103,7 +96,7 @@ class PreferenceManager {
|
|||
// 保存重置后的偏好设置
|
||||
this.savePreferences(this.state);
|
||||
// 从存储中移除偏好设置项
|
||||
[STORAGE_KEY, STORAGE_KEY_THEME, STORAGE_KEY_LOCALE].forEach((key) => {
|
||||
[STORAGE_KEY, STORAGE_KEY_THEME, STORAGE_KEY_LOCALE].forEach(key => {
|
||||
this.cache?.removeItem(key);
|
||||
});
|
||||
this.updatePreferences(this.state);
|
||||
|
@ -145,17 +138,14 @@ class PreferenceManager {
|
|||
updateCSSVariables(this.state);
|
||||
}
|
||||
|
||||
if (
|
||||
Reflect.has(appUpdates, 'colorGrayMode') ||
|
||||
Reflect.has(appUpdates, 'colorWeakMode')
|
||||
) {
|
||||
if (Reflect.has(appUpdates, "colorGrayMode") || Reflect.has(appUpdates, "colorWeakMode")) {
|
||||
this.updateColorMode(this.state);
|
||||
}
|
||||
}
|
||||
|
||||
private initPlatform() {
|
||||
const dom = document.documentElement;
|
||||
dom.dataset.platform = isMacOs() ? 'macOs' : 'window';
|
||||
dom.dataset.platform = isMacOs() ? "macOs" : "window";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -183,25 +173,23 @@ class PreferenceManager {
|
|||
|
||||
// 监听断点,判断是否移动端
|
||||
const breakpoints = useBreakpoints(breakpointsTailwind);
|
||||
const isMobile = breakpoints.smaller('md');
|
||||
const isMobile = breakpoints.smaller("md");
|
||||
watch(
|
||||
() => isMobile.value,
|
||||
(val) => {
|
||||
val => {
|
||||
this.updatePreferences({
|
||||
app: { isMobile: val },
|
||||
});
|
||||
},
|
||||
{ immediate: true },
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 监听系统主题偏好设置变化
|
||||
window
|
||||
.matchMedia('(prefers-color-scheme: dark)')
|
||||
.addEventListener('change', ({ matches: isDark }) => {
|
||||
this.updatePreferences({
|
||||
theme: { mode: isDark ? 'dark' : 'light' },
|
||||
});
|
||||
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", ({ matches: isDark }) => {
|
||||
this.updatePreferences({
|
||||
theme: { mode: isDark ? "dark" : "light" },
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -212,14 +200,10 @@ class PreferenceManager {
|
|||
if (preference.app) {
|
||||
const { colorGrayMode, colorWeakMode } = preference.app;
|
||||
const dom = document.documentElement;
|
||||
const COLOR_WEAK = 'invert-mode';
|
||||
const COLOR_GRAY = 'grayscale-mode';
|
||||
colorWeakMode
|
||||
? dom.classList.add(COLOR_WEAK)
|
||||
: dom.classList.remove(COLOR_WEAK);
|
||||
colorGrayMode
|
||||
? dom.classList.add(COLOR_GRAY)
|
||||
: dom.classList.remove(COLOR_GRAY);
|
||||
const COLOR_WEAK = "invert-mode";
|
||||
const COLOR_GRAY = "grayscale-mode";
|
||||
colorWeakMode ? dom.classList.add(COLOR_WEAK) : dom.classList.remove(COLOR_WEAK);
|
||||
colorGrayMode ? dom.classList.add(COLOR_GRAY) : dom.classList.remove(COLOR_GRAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import type { Preferences } from './types';
|
||||
import type { Preferences } from "./types";
|
||||
|
||||
import { generatorColorVariables } from '/@/vben/shared/color';
|
||||
import { updateCSSVariables as executeUpdateCSSVariables } from '/@/vben/shared/utils';
|
||||
import { generatorColorVariables } from "/@/vben/shared/color";
|
||||
import { updateCSSVariables as executeUpdateCSSVariables } from "/@/vben/shared/utils";
|
||||
|
||||
import { BUILT_IN_THEME_PRESETS } from './constants';
|
||||
import { BUILT_IN_THEME_PRESETS } from "./constants";
|
||||
|
||||
/**
|
||||
* 更新主题的 CSS 变量以及其他 CSS 变量
|
||||
|
@ -21,13 +21,13 @@ function updateCSSVariables(preferences: Preferences) {
|
|||
const { builtinType, mode, radius } = theme;
|
||||
|
||||
// html 设置 dark 类
|
||||
if (Reflect.has(theme, 'mode')) {
|
||||
if (Reflect.has(theme, "mode")) {
|
||||
const dark = isDarkTheme(mode);
|
||||
root.classList.toggle('dark', dark);
|
||||
root.classList.toggle("dark", dark);
|
||||
}
|
||||
|
||||
// html 设置 data-theme=[builtinType]
|
||||
if (Reflect.has(theme, 'builtinType')) {
|
||||
if (Reflect.has(theme, "builtinType")) {
|
||||
const rootTheme = root.dataset.theme;
|
||||
if (rootTheme !== builtinType) {
|
||||
root.dataset.theme = builtinType;
|
||||
|
@ -35,36 +35,26 @@ function updateCSSVariables(preferences: Preferences) {
|
|||
}
|
||||
|
||||
// 获取当前的内置主题
|
||||
const currentBuiltType = [...BUILT_IN_THEME_PRESETS].find(
|
||||
(item) => item.type === builtinType,
|
||||
);
|
||||
const currentBuiltType = [...BUILT_IN_THEME_PRESETS].find(item => item.type === builtinType);
|
||||
|
||||
let builtinTypeColorPrimary: string | undefined = '';
|
||||
let builtinTypeColorPrimary: string | undefined = "";
|
||||
|
||||
if (currentBuiltType) {
|
||||
const isDark = isDarkTheme(preferences.theme.mode);
|
||||
// 设置不同主题的主要颜色
|
||||
const color = isDark
|
||||
? currentBuiltType.darkPrimaryColor || currentBuiltType.primaryColor
|
||||
: currentBuiltType.primaryColor;
|
||||
const color = isDark ? currentBuiltType.darkPrimaryColor || currentBuiltType.primaryColor : currentBuiltType.primaryColor;
|
||||
builtinTypeColorPrimary = color || currentBuiltType.color;
|
||||
}
|
||||
|
||||
// 如果内置主题颜色和自定义颜色都不存在,则不更新主题颜色
|
||||
if (
|
||||
builtinTypeColorPrimary ||
|
||||
Reflect.has(theme, 'colorPrimary') ||
|
||||
Reflect.has(theme, 'colorDestructive') ||
|
||||
Reflect.has(theme, 'colorSuccess') ||
|
||||
Reflect.has(theme, 'colorWarning')
|
||||
) {
|
||||
if (builtinTypeColorPrimary || Reflect.has(theme, "colorPrimary") || Reflect.has(theme, "colorDestructive") || Reflect.has(theme, "colorSuccess") || Reflect.has(theme, "colorWarning")) {
|
||||
// preferences.theme.colorPrimary = builtinTypeColorPrimary || colorPrimary;
|
||||
updateMainColorVariables(preferences);
|
||||
}
|
||||
|
||||
// 更新圆角
|
||||
if (Reflect.has(theme, 'radius')) {
|
||||
document.documentElement.style.setProperty('--radius', `${radius}rem`);
|
||||
if (Reflect.has(theme, "radius")) {
|
||||
document.documentElement.style.setProperty("--radius", `${radius}rem`);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,22 +66,21 @@ function updateMainColorVariables(preference: Preferences) {
|
|||
if (!preference.theme) {
|
||||
return;
|
||||
}
|
||||
const { colorDestructive, colorPrimary, colorSuccess, colorWarning } =
|
||||
preference.theme;
|
||||
const { colorDestructive, colorPrimary, colorSuccess, colorWarning } = preference.theme;
|
||||
|
||||
const colorVariables = generatorColorVariables([
|
||||
{ color: colorPrimary, name: 'primary' },
|
||||
{ alias: 'warning', color: colorWarning, name: 'yellow' },
|
||||
{ alias: 'success', color: colorSuccess, name: 'green' },
|
||||
{ alias: 'destructive', color: colorDestructive, name: 'red' },
|
||||
{ color: colorPrimary, name: "primary" },
|
||||
{ alias: "warning", color: colorWarning, name: "yellow" },
|
||||
{ alias: "success", color: colorSuccess, name: "green" },
|
||||
{ alias: "destructive", color: colorDestructive, name: "red" },
|
||||
]);
|
||||
|
||||
// 要设置的 CSS 变量映射
|
||||
const colorMappings = {
|
||||
'--green-500': '--success',
|
||||
'--primary-500': '--primary',
|
||||
'--red-500': '--destructive',
|
||||
'--yellow-500': '--warning',
|
||||
"--green-500": "--success",
|
||||
"--primary-500": "--primary",
|
||||
"--red-500": "--destructive",
|
||||
"--yellow-500": "--warning",
|
||||
};
|
||||
|
||||
// 统一处理颜色变量的更新
|
||||
|
@ -106,9 +95,9 @@ function updateMainColorVariables(preference: Preferences) {
|
|||
}
|
||||
|
||||
function isDarkTheme(theme: string) {
|
||||
let dark = theme === 'dark';
|
||||
if (theme === 'auto') {
|
||||
dark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
let dark = theme === "dark";
|
||||
if (theme === "auto") {
|
||||
dark = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||
}
|
||||
return dark;
|
||||
}
|
||||
|
|
|
@ -166,7 +166,7 @@ function usePreferences() {
|
|||
if (!enablePreferences) {
|
||||
return {
|
||||
fixed: false,
|
||||
header: false
|
||||
header: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@ function usePreferences() {
|
|||
if (preferencesButtonPosition !== "auto") {
|
||||
return {
|
||||
fixed: preferencesButtonPosition === "fixed",
|
||||
header: isHeaderPosition
|
||||
header: isHeaderPosition,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -191,7 +191,7 @@ function usePreferences() {
|
|||
|
||||
return {
|
||||
fixed,
|
||||
header: !fixed
|
||||
header: !fixed,
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -219,7 +219,7 @@ function usePreferences() {
|
|||
locale,
|
||||
preferencesButtonPosition,
|
||||
sidebarCollapsed,
|
||||
theme
|
||||
theme,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,81 +1,89 @@
|
|||
<template>
|
||||
<a-drawer v-model:open="notificationDrawerVisible" placement="right" :closable="true" width="600px"
|
||||
class="pi-notification-form" @after-open-change="notificationDrawerOnAfterVisibleChange">
|
||||
<template #title>
|
||||
<div>
|
||||
{{ t('certd.edit_notification') }}
|
||||
<a-button v-if="mode === 'edit'" @click="notificationDelete()">
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="currentNotification">
|
||||
<pi-container>
|
||||
<a-form ref="notificationFormRef" class="notification-form" :model="currentNotification"
|
||||
:label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<fs-form-item v-if="currentNotification.type === 'email'" v-model="currentNotification.type" :item="{
|
||||
title: t('certd.type'),
|
||||
key: 'type',
|
||||
value: 'email',
|
||||
component: {
|
||||
name: 'a-select',
|
||||
vModel: 'value',
|
||||
disabled: !editMode,
|
||||
options: [
|
||||
{ value: 'email', label: t('certd.email') },
|
||||
{ value: 'other', label: t('certd.other_notification_method') },
|
||||
],
|
||||
},
|
||||
rules: [{ required: true, message: t('certd.required') }],
|
||||
}" />
|
||||
<fs-form-item v-model="currentNotification.when" :item="{
|
||||
title: t('certd.trigger_time'),
|
||||
key: 'when',
|
||||
value: ['error'],
|
||||
component: {
|
||||
name: 'a-select',
|
||||
vModel: 'value',
|
||||
disabled: !editMode,
|
||||
mode: 'multiple',
|
||||
options: [
|
||||
{ value: 'start', label: t('certd.start_time') },
|
||||
{ value: 'success', label: t('certd.success_time') },
|
||||
{ value: 'turnToSuccess', label: t('certd.fail_to_success_time') },
|
||||
{ value: 'error', label: t('certd.fail_time') },
|
||||
],
|
||||
},
|
||||
helper: t('certd.helper_suggest_fail_only'),
|
||||
rules: [{ required: true, message: t('certd.required') }],
|
||||
}" />
|
||||
<pi-notification-form-email v-if="currentNotification.type === 'email'" ref="optionsRef"
|
||||
v-model:options="currentNotification.options"></pi-notification-form-email>
|
||||
<a-drawer v-model:open="notificationDrawerVisible" placement="right" :closable="true" width="600px" class="pi-notification-form" @after-open-change="notificationDrawerOnAfterVisibleChange">
|
||||
<template #title>
|
||||
<div>
|
||||
{{ t("certd.edit_notification") }}
|
||||
<a-button v-if="mode === 'edit'" @click="notificationDelete()">
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="currentNotification">
|
||||
<pi-container>
|
||||
<a-form ref="notificationFormRef" class="notification-form" :model="currentNotification" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<fs-form-item
|
||||
v-if="currentNotification.type === 'email'"
|
||||
v-model="currentNotification.type"
|
||||
:item="{
|
||||
title: t('certd.type'),
|
||||
key: 'type',
|
||||
value: 'email',
|
||||
component: {
|
||||
name: 'a-select',
|
||||
vModel: 'value',
|
||||
disabled: !editMode,
|
||||
options: [
|
||||
{ value: 'email', label: t('certd.email') },
|
||||
{ value: 'other', label: t('certd.other_notification_method') },
|
||||
],
|
||||
},
|
||||
rules: [{ required: true, message: t('certd.required') }],
|
||||
}"
|
||||
/>
|
||||
<fs-form-item
|
||||
v-model="currentNotification.when"
|
||||
:item="{
|
||||
title: t('certd.trigger_time'),
|
||||
key: 'when',
|
||||
value: ['error'],
|
||||
component: {
|
||||
name: 'a-select',
|
||||
vModel: 'value',
|
||||
disabled: !editMode,
|
||||
mode: 'multiple',
|
||||
options: [
|
||||
{ value: 'start', label: t('certd.start_time') },
|
||||
{ value: 'success', label: t('certd.success_time') },
|
||||
{ value: 'turnToSuccess', label: t('certd.fail_to_success_time') },
|
||||
{ value: 'error', label: t('certd.fail_time') },
|
||||
],
|
||||
},
|
||||
helper: t('certd.helper_suggest_fail_only'),
|
||||
rules: [{ required: true, message: t('certd.required') }],
|
||||
}"
|
||||
/>
|
||||
<pi-notification-form-email v-if="currentNotification.type === 'email'" ref="optionsRef" v-model:options="currentNotification.options"></pi-notification-form-email>
|
||||
|
||||
<fs-form-item v-else v-model="currentNotification.notificationId" :item="{
|
||||
title: t('certd.notification_config'),
|
||||
key: 'notificationId',
|
||||
component: {
|
||||
disabled: !editMode,
|
||||
name: NotificationSelector,
|
||||
onSelectedChange,
|
||||
},
|
||||
helper: t('certd.please_select_notification'),
|
||||
rules: [{ required: true, message: t('certd.required') }],
|
||||
}" />
|
||||
</a-form>
|
||||
<fs-form-item
|
||||
v-else
|
||||
v-model="currentNotification.notificationId"
|
||||
:item="{
|
||||
title: t('certd.notification_config'),
|
||||
key: 'notificationId',
|
||||
component: {
|
||||
disabled: !editMode,
|
||||
name: NotificationSelector,
|
||||
onSelectedChange,
|
||||
},
|
||||
helper: t('certd.please_select_notification'),
|
||||
rules: [{ required: true, message: t('certd.required') }],
|
||||
}"
|
||||
/>
|
||||
</a-form>
|
||||
|
||||
<template #footer>
|
||||
<a-form-item v-if="editMode" :wrapper-col="{ span: 14, offset: 4 }">
|
||||
<a-button type="primary" @click="notificationSave"> {{ t('certd.confirm') }} </a-button>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</pi-container>
|
||||
</template>
|
||||
</a-drawer>
|
||||
<template #footer>
|
||||
<a-form-item v-if="editMode" :wrapper-col="{ span: 14, offset: 4 }">
|
||||
<a-button type="primary" @click="notificationSave"> {{ t("certd.confirm") }} </a-button>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</pi-container>
|
||||
</template>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { Modal } from "ant-design-vue";
|
||||
import { ref, Ref } from "vue";
|
||||
import * as _ from "lodash-es";
|
||||
|
@ -86,157 +94,125 @@ import { useI18n } from "vue-i18n";
|
|||
|
||||
const { t } = useI18n();
|
||||
|
||||
export default {
|
||||
name: "PiNotificationForm",
|
||||
// eslint-disable-next-line vue/no-unused-components
|
||||
components: { NotificationSelector, PiNotificationFormEmail },
|
||||
props: {
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
emits: ["update"],
|
||||
setup(props: any, context: any) {
|
||||
/**
|
||||
* notification drawer
|
||||
* @returns
|
||||
*/
|
||||
function useNotificationForm() {
|
||||
const mode = ref("add");
|
||||
const callback = ref();
|
||||
const currentNotification: Ref<any> = ref({ type: undefined, when: [], options: {}, notificationId: undefined, title: "" });
|
||||
const currentPlugin = ref({});
|
||||
const notificationFormRef = ref(null);
|
||||
const notificationDrawerVisible = ref(false);
|
||||
const optionsRef = ref();
|
||||
const rules = ref({
|
||||
type: [
|
||||
{
|
||||
type: "string",
|
||||
required: true,
|
||||
message: t('certd.please_select_type'),
|
||||
},
|
||||
],
|
||||
when: [
|
||||
{
|
||||
type: "string",
|
||||
required: true,
|
||||
message: t('certd.please_select_trigger_time'),
|
||||
},
|
||||
],
|
||||
notificationId: [
|
||||
{
|
||||
type: "number",
|
||||
required: true,
|
||||
message: t('certd.please_select_notification_config'),
|
||||
},
|
||||
],
|
||||
});
|
||||
const notificationDrawerShow = () => {
|
||||
notificationDrawerVisible.value = true;
|
||||
};
|
||||
const notificationDrawerClose = () => {
|
||||
notificationDrawerVisible.value = false;
|
||||
};
|
||||
defineOptions({
|
||||
name: "PiNotificationForm",
|
||||
});
|
||||
|
||||
const notificationDrawerOnAfterVisibleChange = (val: any) => {
|
||||
console.log("notificationDrawerOnAfterVisibleChange", val);
|
||||
};
|
||||
const props = defineProps<{
|
||||
editMode: boolean;
|
||||
}>();
|
||||
|
||||
const notificationOpen = (notification: any, emit: any) => {
|
||||
callback.value = emit;
|
||||
currentNotification.value = _.cloneDeep(notification);
|
||||
console.log("currentNotificationOpen", currentNotification.value);
|
||||
notificationDrawerShow();
|
||||
};
|
||||
const emit = defineEmits(["update"]);
|
||||
|
||||
const notificationAdd = (emit: any) => {
|
||||
mode.value = "add";
|
||||
const notification = { id: nanoid(), type: "custom", when: ["error", "turnToSuccess"] };
|
||||
notificationOpen(notification, emit);
|
||||
};
|
||||
|
||||
const notificationEdit = (notification: any, emit: any) => {
|
||||
mode.value = "edit";
|
||||
notificationOpen(notification, emit);
|
||||
};
|
||||
|
||||
const notificationView = (notification: any, emit: any) => {
|
||||
mode.value = "view";
|
||||
notificationOpen(notification, emit);
|
||||
};
|
||||
|
||||
const notificationSave = async (e: any) => {
|
||||
if (optionsRef.value) {
|
||||
currentNotification.value.options = await optionsRef.value.getValue();
|
||||
}
|
||||
|
||||
console.log("currentNotificationSave", currentNotification.value);
|
||||
try {
|
||||
await notificationFormRef.value.validate();
|
||||
} catch (e) {
|
||||
console.error("表单验证失败:", e);
|
||||
return;
|
||||
}
|
||||
|
||||
callback.value("save", currentNotification.value);
|
||||
notificationDrawerClose();
|
||||
};
|
||||
|
||||
const notificationDelete = () => {
|
||||
Modal.confirm({
|
||||
title: t('certd.confirm'),
|
||||
content: t('certd.confirm_delete_trigger'),
|
||||
async onOk() {
|
||||
callback.value("delete");
|
||||
notificationDrawerClose();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const blankFn = () => {
|
||||
return {};
|
||||
};
|
||||
|
||||
function onSelectedChange(node: any) {
|
||||
currentNotification.value.title = node?.name || null;
|
||||
}
|
||||
return {
|
||||
notificationFormRef,
|
||||
onSelectedChange,
|
||||
mode,
|
||||
notificationAdd,
|
||||
notificationEdit,
|
||||
notificationView,
|
||||
notificationDrawerShow,
|
||||
notificationDrawerVisible,
|
||||
notificationDrawerOnAfterVisibleChange,
|
||||
currentNotification,
|
||||
currentPlugin,
|
||||
notificationSave,
|
||||
notificationDelete,
|
||||
rules,
|
||||
blankFn,
|
||||
optionsRef,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...useNotificationForm(),
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
NotificationSelector() {
|
||||
return NotificationSelector;
|
||||
},
|
||||
},
|
||||
/**
|
||||
* notification drawer
|
||||
* @returns
|
||||
*/
|
||||
const mode = ref("add");
|
||||
const callback = ref();
|
||||
const currentNotification: Ref<any> = ref({ type: undefined, when: [], options: {}, notificationId: undefined, title: "" });
|
||||
const currentPlugin = ref({});
|
||||
const notificationFormRef = ref(null);
|
||||
const notificationDrawerVisible = ref(false);
|
||||
const optionsRef = ref();
|
||||
const rules = ref({
|
||||
type: [
|
||||
{
|
||||
type: "string",
|
||||
required: true,
|
||||
message: t("certd.please_select_type"),
|
||||
},
|
||||
],
|
||||
when: [
|
||||
{
|
||||
type: "string",
|
||||
required: true,
|
||||
message: t("certd.please_select_trigger_time"),
|
||||
},
|
||||
],
|
||||
notificationId: [
|
||||
{
|
||||
type: "number",
|
||||
required: true,
|
||||
message: t("certd.please_select_notification_config"),
|
||||
},
|
||||
],
|
||||
});
|
||||
const notificationDrawerShow = () => {
|
||||
notificationDrawerVisible.value = true;
|
||||
};
|
||||
const notificationDrawerClose = () => {
|
||||
notificationDrawerVisible.value = false;
|
||||
};
|
||||
|
||||
const notificationDrawerOnAfterVisibleChange = (val: any) => {
|
||||
console.log("notificationDrawerOnAfterVisibleChange", val);
|
||||
};
|
||||
|
||||
const notificationOpen = (notification: any, emit: any) => {
|
||||
callback.value = emit;
|
||||
currentNotification.value = _.cloneDeep(notification);
|
||||
console.log("currentNotificationOpen", currentNotification.value);
|
||||
notificationDrawerShow();
|
||||
};
|
||||
|
||||
const notificationAdd = (emit: any) => {
|
||||
mode.value = "add";
|
||||
const notification = { id: nanoid(), type: "custom", when: ["error", "turnToSuccess"] };
|
||||
notificationOpen(notification, emit);
|
||||
};
|
||||
|
||||
const notificationEdit = (notification: any, emit: any) => {
|
||||
mode.value = "edit";
|
||||
notificationOpen(notification, emit);
|
||||
};
|
||||
|
||||
const notificationView = (notification: any, emit: any) => {
|
||||
mode.value = "view";
|
||||
notificationOpen(notification, emit);
|
||||
};
|
||||
|
||||
const notificationSave = async (e: any) => {
|
||||
if (optionsRef.value) {
|
||||
currentNotification.value.options = await optionsRef.value.getValue();
|
||||
}
|
||||
|
||||
console.log("currentNotificationSave", currentNotification.value);
|
||||
try {
|
||||
await notificationFormRef.value.validate();
|
||||
} catch (e) {
|
||||
console.error("表单验证失败:", e);
|
||||
return;
|
||||
}
|
||||
|
||||
callback.value("save", currentNotification.value);
|
||||
notificationDrawerClose();
|
||||
};
|
||||
|
||||
const notificationDelete = () => {
|
||||
Modal.confirm({
|
||||
title: t("certd.confirm"),
|
||||
content: t("certd.confirm_delete_trigger"),
|
||||
async onOk() {
|
||||
callback.value("delete");
|
||||
notificationDrawerClose();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const blankFn = () => {
|
||||
return {};
|
||||
};
|
||||
|
||||
function onSelectedChange(node: any) {
|
||||
currentNotification.value.title = node?.name || null;
|
||||
}
|
||||
|
||||
const labelCol = { span: 6 };
|
||||
const wrapperCol = { span: 16 };
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.pi-notification-form {}
|
||||
.pi-notification-form {
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,195 +1,201 @@
|
|||
<template>
|
||||
<a-drawer v-model:open="triggerDrawerVisible" placement="right" :closable="true" width="650px"
|
||||
class="pi-trigger-form" @after-open-change="triggerDrawerOnAfterVisibleChange">
|
||||
<template #title>
|
||||
<div>
|
||||
{{ t("certd.editTrigger") }}
|
||||
<a-button v-if="mode === 'edit'" @click="triggerDelete()">
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="currentTrigger">
|
||||
<pi-container>
|
||||
<a-form ref="triggerFormRef" class="trigger-form" :model="currentTrigger" :label-col="labelCol"
|
||||
:wrapper-col="wrapperCol">
|
||||
<fs-form-item v-model="currentTrigger.title" :item="{
|
||||
title: t('certd.triggerName'),
|
||||
key: 'title',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
disabled: !editMode,
|
||||
},
|
||||
rules: [{ required: true, message: t('certd.requiredField') }],
|
||||
}" />
|
||||
<a-drawer v-model:open="triggerDrawerVisible" placement="right" :closable="true" width="650px" class="pi-trigger-form" @after-open-change="triggerDrawerOnAfterVisibleChange">
|
||||
<template #title>
|
||||
<div>
|
||||
{{ t("certd.editTrigger") }}
|
||||
<a-button v-if="mode === 'edit'" @click="triggerDelete()">
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="currentTrigger">
|
||||
<pi-container>
|
||||
<a-form ref="triggerFormRef" class="trigger-form" :model="currentTrigger" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<fs-form-item
|
||||
v-model="currentTrigger.title"
|
||||
:item="{
|
||||
title: t('certd.triggerName'),
|
||||
key: 'title',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
disabled: !editMode,
|
||||
},
|
||||
rules: [{ required: true, message: t('certd.requiredField') }],
|
||||
}"
|
||||
/>
|
||||
|
||||
<fs-form-item
|
||||
v-model="currentTrigger.type"
|
||||
:item="{
|
||||
title: t('certd.type'),
|
||||
key: 'type',
|
||||
value: 'timer',
|
||||
component: {
|
||||
name: 'a-select',
|
||||
vModel: 'value',
|
||||
disabled: !editMode,
|
||||
options: [{ value: 'timer', label: t('certd.schedule') }],
|
||||
},
|
||||
rules: [{ required: true, message: t('certd.requiredField') }],
|
||||
}"
|
||||
/>
|
||||
|
||||
<fs-form-item v-model="currentTrigger.type" :item="{
|
||||
title: t('certd.type'),
|
||||
key: 'type',
|
||||
value: 'timer',
|
||||
component: {
|
||||
name: 'a-select',
|
||||
vModel: 'value',
|
||||
disabled: !editMode,
|
||||
options: [{ value: 'timer', label: t('certd.schedule') }],
|
||||
},
|
||||
rules: [{ required: true, message: t('certd.requiredField') }],
|
||||
}" />
|
||||
<fs-form-item
|
||||
v-model="currentTrigger.props.cron"
|
||||
:item="{
|
||||
title: t('certd.cronForm.title'),
|
||||
key: 'props.cron',
|
||||
component: {
|
||||
disabled: !editMode,
|
||||
name: 'cron-editor',
|
||||
vModel: 'modelValue',
|
||||
},
|
||||
helper: t('certd.cronForm.helper'),
|
||||
rules: [{ required: true, message: t('certd.cronForm.required') }],
|
||||
}"
|
||||
/>
|
||||
</a-form>
|
||||
|
||||
<fs-form-item v-model="currentTrigger.props.cron" :item="{
|
||||
title: t('certd.cronForm.title'),
|
||||
key: 'props.cron',
|
||||
component: {
|
||||
disabled: !editMode,
|
||||
name: 'cron-editor',
|
||||
vModel: 'modelValue',
|
||||
},
|
||||
helper: t('certd.cronForm.helper'),
|
||||
rules: [{ required: true, message: t('certd.cronForm.required') }],
|
||||
}" />
|
||||
</a-form>
|
||||
|
||||
<template #footer>
|
||||
<a-form-item v-if="editMode" :wrapper-col="{ span: 14, offset: 4 }">
|
||||
<a-button type="primary" @click="triggerSave"> 确定 </a-button>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</pi-container>
|
||||
</template>
|
||||
</a-drawer>
|
||||
<template #footer>
|
||||
<a-form-item v-if="editMode" :wrapper-col="{ span: 14, offset: 4 }">
|
||||
<a-button type="primary" @click="triggerSave"> 确定 </a-button>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</pi-container>
|
||||
</template>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { message, Modal } from "ant-design-vue";
|
||||
import { inject, ref } from "vue";
|
||||
import * as _ from "lodash-es";
|
||||
import { useI18n } from "/src/locales/";
|
||||
import { nanoid } from "nanoid";
|
||||
export default {
|
||||
name: "PiTriggerForm",
|
||||
props: {
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
emits: ["update"],
|
||||
setup(props, context) {
|
||||
/**
|
||||
* trigger drawer
|
||||
* @returns
|
||||
*/
|
||||
function useTriggerForm() {
|
||||
const mode = ref("add");
|
||||
const callback = ref();
|
||||
const currentTrigger = ref({ title: undefined, input: {} });
|
||||
const currentPlugin = ref({});
|
||||
const triggerFormRef = ref(null);
|
||||
const triggerDrawerVisible = ref(false);
|
||||
const rules = ref({
|
||||
name: [
|
||||
{
|
||||
type: "string",
|
||||
required: true,
|
||||
message: t("certd.enterName"),
|
||||
},
|
||||
],
|
||||
});
|
||||
name: "PiTriggerForm",
|
||||
props: {
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
emits: ["update"],
|
||||
setup(props, context) {
|
||||
/**
|
||||
* trigger drawer
|
||||
* @returns
|
||||
*/
|
||||
const { t } = useI18n();
|
||||
function useTriggerForm() {
|
||||
const mode = ref("add");
|
||||
const callback = ref();
|
||||
const currentTrigger = ref({ title: undefined, input: {} });
|
||||
const currentPlugin = ref({});
|
||||
const triggerFormRef = ref(null);
|
||||
const triggerDrawerVisible = ref(false);
|
||||
const rules = ref({
|
||||
name: [
|
||||
{
|
||||
type: "string",
|
||||
required: true,
|
||||
message: t("certd.enterName"),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const triggerDrawerShow = () => {
|
||||
triggerDrawerVisible.value = true;
|
||||
};
|
||||
const triggerDrawerClose = () => {
|
||||
triggerDrawerVisible.value = false;
|
||||
};
|
||||
|
||||
const triggerDrawerShow = () => {
|
||||
triggerDrawerVisible.value = true;
|
||||
};
|
||||
const triggerDrawerClose = () => {
|
||||
triggerDrawerVisible.value = false;
|
||||
};
|
||||
const triggerDrawerOnAfterVisibleChange = val => {
|
||||
console.log("triggerDrawerOnAfterVisibleChange", val);
|
||||
};
|
||||
|
||||
const triggerDrawerOnAfterVisibleChange = val => {
|
||||
console.log("triggerDrawerOnAfterVisibleChange", val);
|
||||
};
|
||||
const triggerOpen = (trigger, emit) => {
|
||||
callback.value = emit;
|
||||
currentTrigger.value = _.cloneDeep(trigger);
|
||||
console.log("currentTriggerOpen", currentTrigger.value);
|
||||
triggerDrawerShow();
|
||||
};
|
||||
|
||||
const triggerOpen = (trigger, emit) => {
|
||||
callback.value = emit;
|
||||
currentTrigger.value = _.cloneDeep(trigger);
|
||||
console.log("currentTriggerOpen", currentTrigger.value);
|
||||
triggerDrawerShow();
|
||||
};
|
||||
const triggerAdd = emit => {
|
||||
mode.value = "add";
|
||||
const trigger = { id: nanoid(), title: t("certd.timerTrigger"), type: "timer", props: {} };
|
||||
triggerOpen(trigger, emit);
|
||||
};
|
||||
|
||||
const triggerAdd = emit => {
|
||||
mode.value = "add";
|
||||
const trigger = { id: nanoid(), title: t("certd.timerTrigger"), type: "timer", props: {} };
|
||||
triggerOpen(trigger, emit);
|
||||
};
|
||||
const triggerEdit = (trigger, emit) => {
|
||||
mode.value = "edit";
|
||||
triggerOpen(trigger, emit);
|
||||
};
|
||||
|
||||
const triggerView = (trigger, emit) => {
|
||||
mode.value = "view";
|
||||
triggerOpen(trigger, emit);
|
||||
};
|
||||
|
||||
const triggerEdit = (trigger, emit) => {
|
||||
mode.value = "edit";
|
||||
triggerOpen(trigger, emit);
|
||||
};
|
||||
const triggerSave = async e => {
|
||||
console.log("currentTriggerSave", currentTrigger.value);
|
||||
try {
|
||||
await triggerFormRef.value.validate();
|
||||
} catch (e) {
|
||||
console.error("表单验证失败:", e);
|
||||
return;
|
||||
}
|
||||
|
||||
const triggerView = (trigger, emit) => {
|
||||
mode.value = "view";
|
||||
triggerOpen(trigger, emit);
|
||||
};
|
||||
callback.value("save", currentTrigger.value);
|
||||
triggerDrawerClose();
|
||||
};
|
||||
|
||||
const triggerSave = async e => {
|
||||
console.log("currentTriggerSave", currentTrigger.value);
|
||||
try {
|
||||
await triggerFormRef.value.validate();
|
||||
} catch (e) {
|
||||
console.error("表单验证失败:", e);
|
||||
return;
|
||||
}
|
||||
const triggerDelete = () => {
|
||||
Modal.confirm({
|
||||
title: t("certd.confirm"),
|
||||
content: t("certd.confirmDeleteTrigger"),
|
||||
async onOk() {
|
||||
callback.value("delete");
|
||||
triggerDrawerClose();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
callback.value("save", currentTrigger.value);
|
||||
triggerDrawerClose();
|
||||
};
|
||||
const blankFn = () => {
|
||||
return {};
|
||||
};
|
||||
return {
|
||||
triggerFormRef,
|
||||
mode,
|
||||
triggerAdd,
|
||||
triggerEdit,
|
||||
triggerView,
|
||||
triggerDrawerShow,
|
||||
triggerDrawerVisible,
|
||||
triggerDrawerOnAfterVisibleChange,
|
||||
currentTrigger,
|
||||
currentPlugin,
|
||||
triggerSave,
|
||||
triggerDelete,
|
||||
rules,
|
||||
blankFn,
|
||||
};
|
||||
}
|
||||
|
||||
const triggerDelete = () => {
|
||||
Modal.confirm({
|
||||
title: t("certd.confirm"),
|
||||
content: t("certd.confirmDeleteTrigger"),
|
||||
async onOk() {
|
||||
callback.value("delete");
|
||||
triggerDrawerClose();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const blankFn = () => {
|
||||
return {};
|
||||
};
|
||||
return {
|
||||
triggerFormRef,
|
||||
mode,
|
||||
triggerAdd,
|
||||
triggerEdit,
|
||||
triggerView,
|
||||
triggerDrawerShow,
|
||||
triggerDrawerVisible,
|
||||
triggerDrawerOnAfterVisibleChange,
|
||||
currentTrigger,
|
||||
currentPlugin,
|
||||
triggerSave,
|
||||
triggerDelete,
|
||||
rules,
|
||||
blankFn,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...useTriggerForm(),
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
},
|
||||
return {
|
||||
...useTriggerForm(),
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.pi-trigger-form {}
|
||||
.pi-trigger-form {
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,96 +1,86 @@
|
|||
<template>
|
||||
<div class="main login-page">
|
||||
<a-form v-if="!twoFactor.loginId" ref="formRef" class="user-layout-login" name="custom-validation"
|
||||
:model="formState" v-bind="layout" @finish="handleFinish" @finish-failed="handleFinishFailed">
|
||||
<!-- <div class="login-title">登录</div>-->
|
||||
<a-tabs v-model:active-key="formState.loginType"
|
||||
:tab-bar-style="{ textAlign: 'center', borderBottom: 'unset' }">
|
||||
<a-tab-pane key="password" :tab="$t('authentication.passwordTab')"
|
||||
:disabled="sysPublicSettings.passwordLoginEnabled !== true">
|
||||
<template v-if="formState.loginType === 'password'">
|
||||
<!-- <div class="login-title">登录</div>-->
|
||||
<a-form-item required has-feedback name="username" :rules="rules.username">
|
||||
<a-input v-model:value="formState.username"
|
||||
:placeholder="$t('authentication.usernamePlaceholder')" autocomplete="off">
|
||||
<template #prefix>
|
||||
<fs-icon icon="ion:phone-portrait-outline"></fs-icon>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item has-feedback name="password" :rules="rules.password">
|
||||
<a-input-password v-model:value="formState.password"
|
||||
:placeholder="$t('authentication.passwordPlaceholder')" autocomplete="off">
|
||||
<template #prefix>
|
||||
<fs-icon icon="ion:lock-closed-outline"></fs-icon>
|
||||
</template>
|
||||
</a-input-password>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="sms" :tab="$t('authentication.smsTab')"
|
||||
:disabled="sysPublicSettings.smsLoginEnabled !== true">
|
||||
<template v-if="formState.loginType === 'sms'">
|
||||
<a-form-item has-feedback name="mobile" :rules="rules.mobile">
|
||||
<a-input v-model:value="formState.mobile"
|
||||
:placeholder="$t('authentication.mobilePlaceholder')" autocomplete="off">
|
||||
<template #prefix>
|
||||
<fs-icon icon="ion:phone-portrait-outline"></fs-icon>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<div class="main login-page">
|
||||
<a-form v-if="!twoFactor.loginId" ref="formRef" class="user-layout-login" name="custom-validation" :model="formState" v-bind="layout" @finish="handleFinish" @finish-failed="handleFinishFailed">
|
||||
<!-- <div class="login-title">登录</div>-->
|
||||
<a-tabs v-model:active-key="formState.loginType" :tab-bar-style="{ textAlign: 'center', borderBottom: 'unset' }">
|
||||
<a-tab-pane key="password" :tab="t('authentication.passwordTab')" :disabled="sysPublicSettings.passwordLoginEnabled !== true">
|
||||
<template v-if="formState.loginType === 'password'">
|
||||
<!-- <div class="login-title">登录</div>-->
|
||||
<a-form-item required has-feedback name="username" :rules="rules.username">
|
||||
<a-input v-model:value="formState.username" :placeholder="t('authentication.usernamePlaceholder')" autocomplete="off">
|
||||
<template #prefix>
|
||||
<fs-icon icon="ion:phone-portrait-outline"></fs-icon>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item has-feedback name="password" :rules="rules.password">
|
||||
<a-input-password v-model:value="formState.password" :placeholder="t('authentication.passwordPlaceholder')" autocomplete="off">
|
||||
<template #prefix>
|
||||
<fs-icon icon="ion:lock-closed-outline"></fs-icon>
|
||||
</template>
|
||||
</a-input-password>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane v-if="sysPublicSettings.smsLoginEnabled === true" key="sms" :tab="t('authentication.smsTab')">
|
||||
<template v-if="formState.loginType === 'sms'">
|
||||
<a-form-item has-feedback name="mobile" :rules="rules.mobile">
|
||||
<a-input v-model:value="formState.mobile" :placeholder="t('authentication.mobilePlaceholder')" autocomplete="off">
|
||||
<template #prefix>
|
||||
<fs-icon icon="ion:phone-portrait-outline"></fs-icon>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item has-feedback name="imgCode">
|
||||
<image-code v-model:value="formState.imgCode"
|
||||
v-model:random-str="formState.randomStr"></image-code>
|
||||
</a-form-item>
|
||||
<a-form-item has-feedback name="imgCode">
|
||||
<image-code v-model:value="formState.imgCode" v-model:random-str="formState.randomStr"></image-code>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="smsCode" :rules="rules.smsCode">
|
||||
<sms-code v-model:value="formState.smsCode" :img-code="formState.imgCode"
|
||||
:mobile="formState.mobile" :phone-code="formState.phoneCode"
|
||||
:random-str="formState.randomStr" />
|
||||
</a-form-item>
|
||||
</template>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
<a-form-item>
|
||||
<a-button type="primary" size="large" html-type="submit" :loading="loading" class="login-button">
|
||||
{{ $t('authentication.loginButton') }}
|
||||
</a-button>
|
||||
<a-form-item name="smsCode" :rules="rules.smsCode">
|
||||
<sms-code v-model:value="formState.smsCode" :img-code="formState.imgCode" :mobile="formState.mobile" :phone-code="formState.phoneCode" :random-str="formState.randomStr" />
|
||||
</a-form-item>
|
||||
</template>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
<a-form-item>
|
||||
<a-button type="primary" size="large" html-type="submit" :loading="loading" class="login-button">
|
||||
{{ t("authentication.loginButton") }}
|
||||
</a-button>
|
||||
|
||||
<div v-if="!settingStore.isComm" class="mt-2">
|
||||
<a href="https://certd.docmirror.cn/guide/use/forgotpasswd/" target="_blank">
|
||||
{{ $t('authentication.forgotAdminPassword') }}
|
||||
</a>
|
||||
</div>
|
||||
</a-form-item>
|
||||
<div v-if="!settingStore.isComm" class="mt-2">
|
||||
<a href="https://certd.docmirror.cn/guide/use/forgotpasswd/" target="_blank">
|
||||
{{ t("authentication.forgotAdminPassword") }}
|
||||
</a>
|
||||
</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item class="user-login-other">
|
||||
<router-link v-if="hasRegisterTypeEnabled()" class="register" :to="{ name: 'register' }">
|
||||
{{ $t('authentication.registerLink') }}
|
||||
</router-link>
|
||||
</a-form-item>
|
||||
<a-form-item class="user-login-other">
|
||||
<div class="flex flex-between justify-between items-center">
|
||||
<language-toggle class="color-blue"></language-toggle>
|
||||
<router-link v-if="hasRegisterTypeEnabled()" class="register" :to="{ name: 'register' }">
|
||||
{{ t("authentication.registerLink") }}
|
||||
</router-link>
|
||||
</div>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<a-form v-else ref="twoFactorFormRef" class="user-layout-login" :model="twoFactor" v-bind="layout">
|
||||
<div class="mb-10 flex flex-center">请打开您的Authenticator APP,获取动态验证码。</div>
|
||||
<a-form-item name="verifyCode">
|
||||
<a-input ref="verifyCodeInputRef" v-model:value="twoFactor.verifyCode" placeholder="请输入动态验证码" allow-clear @keydown.enter="handleTwoFactorSubmit">
|
||||
<template #prefix>
|
||||
<fs-icon icon="ion:lock-closed-outline"></fs-icon>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<loading-button type="primary" size="large" html-type="button" class="login-button" :click="handleTwoFactorSubmit">OTP验证登录</loading-button>
|
||||
</a-form-item>
|
||||
|
||||
</a-form>
|
||||
<a-form v-else ref="twoFactorFormRef" class="user-layout-login" :model="twoFactor" v-bind="layout">
|
||||
<div class="mb-10 flex flex-center">请打开您的Authenticator APP,获取动态验证码。</div>
|
||||
<a-form-item name="verifyCode">
|
||||
<a-input ref="verifyCodeInputRef" v-model:value="twoFactor.verifyCode" placeholder="请输入动态验证码"
|
||||
allow-clear @keydown.enter="handleTwoFactorSubmit">
|
||||
<template #prefix>
|
||||
<fs-icon icon="ion:lock-closed-outline"></fs-icon>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<loading-button type="primary" size="large" html-type="button" class="login-button"
|
||||
:click="handleTwoFactorSubmit">OTP验证登录</loading-button>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item class="user-login-other">
|
||||
<a class="register" @click="twoFactor.loginId = null"> 返回 </a>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
<a-form-item class="user-login-other">
|
||||
<a class="register" @click="twoFactor.loginId = null"> 返回 </a>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, nextTick, reactive, ref, toRaw } from "vue";
|
||||
|
@ -99,126 +89,130 @@ import { useSettingStore } from "/@/store/settings";
|
|||
import { utils } from "@fast-crud/fast-crud";
|
||||
import ImageCode from "/@/views/framework/login/image-code.vue";
|
||||
import SmsCode from "/@/views/framework/login/sms-code.vue";
|
||||
import { useI18n } from "/@/locales";
|
||||
import { LanguageToggle } from "/@/vben/layouts";
|
||||
|
||||
export default defineComponent({
|
||||
name: "LoginPage",
|
||||
components: { SmsCode, ImageCode },
|
||||
setup() {
|
||||
const verifyCodeInputRef = ref();
|
||||
const loading = ref(false);
|
||||
const userStore = useUserStore();
|
||||
const settingStore = useSettingStore();
|
||||
const formRef = ref();
|
||||
const formState = reactive({
|
||||
username: "",
|
||||
phoneCode: "86",
|
||||
mobile: "",
|
||||
password: "",
|
||||
loginType: "password", //password
|
||||
imgCode: "",
|
||||
smsCode: "",
|
||||
randomStr: "",
|
||||
});
|
||||
name: "LoginPage",
|
||||
components: { LanguageToggle, SmsCode, ImageCode },
|
||||
setup() {
|
||||
const { t } = useI18n();
|
||||
const verifyCodeInputRef = ref();
|
||||
const loading = ref(false);
|
||||
const userStore = useUserStore();
|
||||
const settingStore = useSettingStore();
|
||||
const formRef = ref();
|
||||
const formState = reactive({
|
||||
username: "",
|
||||
phoneCode: "86",
|
||||
mobile: "",
|
||||
password: "",
|
||||
loginType: "password", //password
|
||||
imgCode: "",
|
||||
smsCode: "",
|
||||
randomStr: "",
|
||||
});
|
||||
|
||||
const rules = {
|
||||
mobile: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入手机号",
|
||||
},
|
||||
],
|
||||
username: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入用户名",
|
||||
},
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入登录密码",
|
||||
},
|
||||
],
|
||||
smsCode: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入短信验证码",
|
||||
},
|
||||
],
|
||||
};
|
||||
const layout = {
|
||||
labelCol: {
|
||||
span: 0,
|
||||
},
|
||||
wrapperCol: {
|
||||
span: 24,
|
||||
},
|
||||
};
|
||||
const rules = {
|
||||
mobile: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入手机号",
|
||||
},
|
||||
],
|
||||
username: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入用户名",
|
||||
},
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入登录密码",
|
||||
},
|
||||
],
|
||||
smsCode: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入短信验证码",
|
||||
},
|
||||
],
|
||||
};
|
||||
const layout = {
|
||||
labelCol: {
|
||||
span: 0,
|
||||
},
|
||||
wrapperCol: {
|
||||
span: 24,
|
||||
},
|
||||
};
|
||||
|
||||
const twoFactor = reactive({
|
||||
loginId: "",
|
||||
verifyCode: "",
|
||||
});
|
||||
const twoFactor = reactive({
|
||||
loginId: "",
|
||||
verifyCode: "",
|
||||
});
|
||||
|
||||
const handleTwoFactorSubmit = async () => {
|
||||
await userStore.loginByTwoFactor(twoFactor);
|
||||
};
|
||||
const handleTwoFactorSubmit = async () => {
|
||||
await userStore.loginByTwoFactor(twoFactor);
|
||||
};
|
||||
|
||||
const handleFinish = async (values: any) => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const loginType = formState.loginType;
|
||||
await userStore.login(loginType, toRaw(formState));
|
||||
} catch (e: any) {
|
||||
//@ts-ignore
|
||||
if (e.code === 10020) {
|
||||
//双重认证
|
||||
//@ts-ignore
|
||||
twoFactor.loginId = e.data;
|
||||
await nextTick();
|
||||
verifyCodeInputRef.value.focus();
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
const handleFinish = async (values: any) => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const loginType = formState.loginType;
|
||||
await userStore.login(loginType, toRaw(formState));
|
||||
} catch (e: any) {
|
||||
//@ts-ignore
|
||||
if (e.code === 10020) {
|
||||
//双重认证
|
||||
//@ts-ignore
|
||||
twoFactor.loginId = e.data;
|
||||
await nextTick();
|
||||
verifyCodeInputRef.value.focus();
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleFinishFailed = (errors: any) => {
|
||||
utils.logger.log(errors);
|
||||
};
|
||||
const handleFinishFailed = (errors: any) => {
|
||||
utils.logger.log(errors);
|
||||
};
|
||||
|
||||
const resetForm = () => {
|
||||
formRef.value.resetFields();
|
||||
};
|
||||
const resetForm = () => {
|
||||
formRef.value.resetFields();
|
||||
};
|
||||
|
||||
const isLoginError = ref();
|
||||
const isLoginError = ref();
|
||||
|
||||
const sysPublicSettings = settingStore.getSysPublic;
|
||||
const sysPublicSettings = settingStore.getSysPublic;
|
||||
|
||||
function hasRegisterTypeEnabled() {
|
||||
return sysPublicSettings.registerEnabled && (sysPublicSettings.usernameRegisterEnabled || sysPublicSettings.emailRegisterEnabled);
|
||||
}
|
||||
function hasRegisterTypeEnabled() {
|
||||
return sysPublicSettings.registerEnabled && (sysPublicSettings.usernameRegisterEnabled || sysPublicSettings.emailRegisterEnabled);
|
||||
}
|
||||
|
||||
return {
|
||||
loading,
|
||||
formState,
|
||||
formRef,
|
||||
rules,
|
||||
layout,
|
||||
handleFinishFailed,
|
||||
handleFinish,
|
||||
resetForm,
|
||||
isLoginError,
|
||||
sysPublicSettings,
|
||||
hasRegisterTypeEnabled,
|
||||
twoFactor,
|
||||
handleTwoFactorSubmit,
|
||||
verifyCodeInputRef,
|
||||
settingStore,
|
||||
};
|
||||
},
|
||||
return {
|
||||
t,
|
||||
loading,
|
||||
formState,
|
||||
formRef,
|
||||
rules,
|
||||
layout,
|
||||
handleFinishFailed,
|
||||
handleFinish,
|
||||
resetForm,
|
||||
isLoginError,
|
||||
sysPublicSettings,
|
||||
hasRegisterTypeEnabled,
|
||||
twoFactor,
|
||||
handleTwoFactorSubmit,
|
||||
verifyCodeInputRef,
|
||||
settingStore,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -226,83 +220,83 @@ export default defineComponent({
|
|||
@import "../../../style/theme/index.less";
|
||||
|
||||
.login-page.main {
|
||||
//margin: 20px !important;
|
||||
margin-bottom: 100px;
|
||||
//margin: 20px !important;
|
||||
margin-bottom: 100px;
|
||||
|
||||
.user-layout-login {
|
||||
//label {
|
||||
// font-size: 14px;
|
||||
//}
|
||||
.user-layout-login {
|
||||
//label {
|
||||
// font-size: 14px;
|
||||
//}
|
||||
|
||||
.login-title {
|
||||
color: @primary-color;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
margin: 20px;
|
||||
}
|
||||
.login-title {
|
||||
color: @primary-color;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.getCaptcha {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
.getCaptcha {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.image-code {
|
||||
height: 34px;
|
||||
}
|
||||
.image-code {
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
.input-right {
|
||||
width: 160px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.input-right {
|
||||
width: 160px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.forge-password {
|
||||
font-size: 14px;
|
||||
}
|
||||
.forge-password {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
button.login-button {
|
||||
padding: 0 15px;
|
||||
font-size: 16px;
|
||||
width: 100%;
|
||||
}
|
||||
button.login-button {
|
||||
padding: 0 15px;
|
||||
font-size: 16px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.user-login-other {
|
||||
text-align: left;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 30px;
|
||||
//line-height: 22px;
|
||||
.user-login-other {
|
||||
text-align: left;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 30px;
|
||||
//line-height: 22px;
|
||||
|
||||
.item-icon {
|
||||
font-size: 24px;
|
||||
color: rgba(0, 0, 0, 0.2);
|
||||
margin-left: 16px;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
.item-icon {
|
||||
font-size: 24px;
|
||||
color: rgba(0, 0, 0, 0.2);
|
||||
margin-left: 16px;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
|
||||
&:hover {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
.register {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
.register {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.fs-icon {
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
margin-right: 4px;
|
||||
}
|
||||
.fs-icon {
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.ant-input-affix-wrapper {
|
||||
line-height: 1.8 !important;
|
||||
font-size: 14px !important;
|
||||
.ant-input-affix-wrapper {
|
||||
line-height: 1.8 !important;
|
||||
font-size: 14px !important;
|
||||
|
||||
>* {
|
||||
line-height: 1.8 !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
> * {
|
||||
line-height: 1.8 !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue