mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-26 16:46:19 +08:00
feat: multi-language layout
This commit is contained in:
@@ -6,7 +6,7 @@ function createFakeUserList() {
|
|||||||
{
|
{
|
||||||
userId: '1',
|
userId: '1',
|
||||||
username: 'vben',
|
username: 'vben',
|
||||||
realName: 'Vben',
|
realName: 'Vben Admin',
|
||||||
desc: 'manager',
|
desc: 'manager',
|
||||||
password: '123456',
|
password: '123456',
|
||||||
token: 'fakeToken1',
|
token: 'fakeToken1',
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
import AppLocalPicker from './src/AppLocalPicker.vue';
|
import AppLocalePicker from './src/AppLocalePicker.vue';
|
||||||
import AppPageFooter from './src/AppPageFooter.vue';
|
import AppPageFooter from './src/AppPageFooter.vue';
|
||||||
import AppLogo from './src/AppLogo.vue';
|
import AppLogo from './src/AppLogo.vue';
|
||||||
import { withInstall } from '../util';
|
import { withInstall } from '../util';
|
||||||
|
|
||||||
export { AppLocalPicker, AppPageFooter, AppLogo };
|
export { AppLocalePicker, AppPageFooter, AppLogo };
|
||||||
|
|
||||||
export default withInstall(AppLocalPicker, AppPageFooter, AppLogo);
|
export default withInstall(AppLocalePicker, AppPageFooter, AppLogo);
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
:dropMenuList="localeList"
|
:dropMenuList="localeList"
|
||||||
:selectedKeys="selectedKeys"
|
:selectedKeys="selectedKeys"
|
||||||
@menuEvent="handleMenuEvent"
|
@menuEvent="handleMenuEvent"
|
||||||
|
overlayClassName="app-locale-picker-overlay"
|
||||||
>
|
>
|
||||||
<span class="app-local-picker">
|
<span class="app-local-picker">
|
||||||
<GlobalOutlined class="app-local-picker__icon" />
|
<GlobalOutlined class="app-local-picker__icon" />
|
||||||
@@ -30,8 +31,12 @@
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
|
reload: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
},
|
},
|
||||||
setup() {
|
},
|
||||||
|
setup(props) {
|
||||||
const { localeList } = useLocaleSetting();
|
const { localeList } = useLocaleSetting();
|
||||||
const selectedKeys = ref<string[]>([]);
|
const selectedKeys = ref<string[]>([]);
|
||||||
|
|
||||||
@@ -50,6 +55,7 @@
|
|||||||
function toggleLocale(lang: LocaleType | string) {
|
function toggleLocale(lang: LocaleType | string) {
|
||||||
changeLocale(lang as LocaleType);
|
changeLocale(lang as LocaleType);
|
||||||
selectedKeys.value = [lang as string];
|
selectedKeys.value = [lang as string];
|
||||||
|
props.reload && location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMenuEvent(menu: DropMenu) {
|
function handleMenuEvent(menu: DropMenu) {
|
||||||
@@ -61,7 +67,13 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less">
|
||||||
|
.app-locale-picker-overlay {
|
||||||
|
.ant-dropdown-menu-item {
|
||||||
|
min-width: 160px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.app-local-picker {
|
.app-local-picker {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
@@ -1,11 +1,12 @@
|
|||||||
|
import type { Trigger } from './types';
|
||||||
|
|
||||||
import { defineComponent, computed, unref } from 'vue';
|
import { defineComponent, computed, unref } from 'vue';
|
||||||
import { Dropdown, Menu, Divider } from 'ant-design-vue';
|
import { Dropdown, Menu } from 'ant-design-vue';
|
||||||
|
|
||||||
import Icon from '/@/components/Icon/index';
|
import Icon from '/@/components/Icon/index';
|
||||||
|
|
||||||
import { basicDropdownProps } from './props';
|
import { basicDropdownProps } from './props';
|
||||||
import { getSlot } from '/@/utils/helper/tsxHelper';
|
import { getSlot } from '/@/utils/helper/tsxHelper';
|
||||||
import { Trigger } from './types';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Dropdown',
|
name: 'Dropdown',
|
||||||
@@ -24,7 +25,7 @@ export default defineComponent({
|
|||||||
<Menu onClick={handleClickMenu} selectedKeys={props.selectedKeys}>
|
<Menu onClick={handleClickMenu} selectedKeys={props.selectedKeys}>
|
||||||
{() => (
|
{() => (
|
||||||
<>
|
<>
|
||||||
{unref(getMenuList).map((item, index) => {
|
{unref(getMenuList).map((item) => {
|
||||||
const { disabled, icon, text, divider, event } = item;
|
const { disabled, icon, text, divider, event } = item;
|
||||||
return [
|
return [
|
||||||
<Menu.Item key={`${event}`} disabled={disabled}>
|
<Menu.Item key={`${event}`} disabled={disabled}>
|
||||||
@@ -35,7 +36,8 @@ export default defineComponent({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Menu.Item>,
|
</Menu.Item>,
|
||||||
divider && <Divider key={`d-${index}`} />,
|
// @ts-ignore
|
||||||
|
divider && <Menu.Divider key={`d-${event}`} />,
|
||||||
];
|
];
|
||||||
})}
|
})}
|
||||||
</>
|
</>
|
||||||
|
@@ -13,20 +13,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// .ant-form-item-label {
|
|
||||||
// text-align: unset;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// =================================
|
// =================================
|
||||||
// ==============descriptions=======
|
// ==============descriptions=======
|
||||||
// =================================
|
// =================================
|
||||||
.ant-descriptions-bordered .ant-descriptions-item-label {
|
// .ant-descriptions-bordered .ant-descriptions-item-label {
|
||||||
background-color: @background-color-light;
|
// background-color: @background-color-light;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
// .ant-descriptions .ant-descriptions-item-content {
|
||||||
|
// color: @text-color-call-out;
|
||||||
|
// }
|
||||||
|
|
||||||
.ant-descriptions .ant-descriptions-item-content {
|
|
||||||
color: @text-color-call-out;
|
|
||||||
}
|
|
||||||
// =================================
|
// =================================
|
||||||
// ==============modal message======
|
// ==============modal message======
|
||||||
// =================================
|
// =================================
|
||||||
@@ -46,68 +43,6 @@
|
|||||||
color: @primary-color !important;
|
color: @primary-color !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-modal-mask {
|
|
||||||
background-color: rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
// =================================
|
|
||||||
// ==============menu===============
|
|
||||||
// =================================
|
|
||||||
.ant-menu-item {
|
|
||||||
&-selected {
|
|
||||||
a {
|
|
||||||
color: @primary-color;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: @primary-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// =================================
|
|
||||||
// ==============dropdown===========
|
|
||||||
// =================================
|
|
||||||
.ant-dropdown {
|
|
||||||
.ant-divider {
|
|
||||||
margin: 4px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-menu-item {
|
|
||||||
line-height: 30px;
|
|
||||||
color: @text-color-call-out;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: inherit;
|
|
||||||
background-color: @border-color-shallow-light;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// =================================
|
|
||||||
// ==============back-top===========
|
|
||||||
// =================================
|
|
||||||
.ant-back-top {
|
|
||||||
right: 50px;
|
|
||||||
bottom: 60px;
|
|
||||||
}
|
|
||||||
// =================================
|
|
||||||
// ==============calendar===========
|
|
||||||
// =================================
|
|
||||||
.ant-calendar-picker {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
// =================================
|
|
||||||
// ==============tooltip============
|
|
||||||
// =================================
|
|
||||||
|
|
||||||
.ant-tooltip {
|
|
||||||
&-inner {
|
|
||||||
padding: 6px 16px;
|
|
||||||
line-height: 20px;
|
|
||||||
color: @white;
|
|
||||||
background: @text-color-base;
|
|
||||||
border-radius: 4px;
|
|
||||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// =================================
|
// =================================
|
||||||
// ==============form===============
|
// ==============form===============
|
||||||
// =================================
|
// =================================
|
||||||
|
@@ -5,24 +5,9 @@
|
|||||||
.ant-input {
|
.ant-input {
|
||||||
&-number {
|
&-number {
|
||||||
min-width: 110px;
|
min-width: 110px;
|
||||||
border-color: @border-color-shallow-dark;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-input-affix-wrapper:hover .ant-input:not(.ant-input-disabled) {
|
|
||||||
border-color: @info-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-input-disabled,
|
|
||||||
.ant-select-disabled .ant-select-selection,
|
|
||||||
.ant-cascader-picker-label {
|
|
||||||
color: @text-color-base !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-input-disabled {
|
|
||||||
background-color: @background-color-light;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-input-affix-wrapper .ant-input-suffix {
|
.ant-input-affix-wrapper .ant-input-suffix {
|
||||||
right: 9px;
|
right: 9px;
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@white: #fff;
|
@white: #fff;
|
||||||
|
|
||||||
|
@content-bg: #f0f2f5;
|
||||||
|
|
||||||
@info-color: @primary-color;
|
@info-color: @primary-color;
|
||||||
|
|
||||||
@basic-mask-color: fade(@white, 30%);
|
@basic-mask-color: fade(@white, 30%);
|
||||||
@@ -24,7 +27,7 @@
|
|||||||
@iconify-bg-color: #5551;
|
@iconify-bg-color: #5551;
|
||||||
|
|
||||||
// =================================
|
// =================================
|
||||||
// ==============border-color============
|
// ==============border-color=======
|
||||||
// =================================
|
// =================================
|
||||||
|
|
||||||
// Dark-dark
|
// Dark-dark
|
||||||
|
@@ -54,8 +54,7 @@ input::-ms-reveal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
// font-family: 'Microsoft YaHei,微软雅黑,Arial,sans-serif,Helvetica Neue,Helvetica,Pingfang SC,Hiragino Sans GB';
|
font-family: 'BlinkMacSystemFont,segoe ui,Microsoft YaHei,Arial,sans-serif,Helvetica Neue,Helvetica,Pingfang SC,Hiragino Sans GB,Roboto,helvetica neue,Arial,noto sans,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol,noto color emoji';
|
||||||
font-family: '-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol,noto color emoji';
|
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
line-height: 1.428571429; // 20/14
|
line-height: 1.428571429; // 20/14
|
||||||
@@ -159,17 +158,3 @@ embed,
|
|||||||
object {
|
object {
|
||||||
vertical-align: baseline !important;
|
vertical-align: baseline !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-layout {
|
|
||||||
background: #f0f2f5;
|
|
||||||
|
|
||||||
// &-content {
|
|
||||||
// position: relative;
|
|
||||||
// overflow: hidden;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
@@ -16,33 +16,33 @@
|
|||||||
color: @color;
|
color: @color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 文本截断
|
// Text truncation
|
||||||
.text-truncate() {
|
.text-truncate() {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 强制不换行 */
|
/* Force no line break */
|
||||||
.word-nowrap() {
|
.word-nowrap() {
|
||||||
word-wrap: normal;
|
word-wrap: normal;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 强制换行 */
|
/* Force line break */
|
||||||
.break-all() {
|
.break-all() {
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 禁止选中
|
// Prohibit selection
|
||||||
.unselect() {
|
.unselect() {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 适用于webkit内核和移动端 */
|
/* Suitable for webkit core and mobile */
|
||||||
.ellipsis-multiple(@num: 1) {
|
.ellipsis-multiple(@num: 1) {
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@@ -1,8 +1,16 @@
|
|||||||
|
#app {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.app-svg-loading {
|
.app-svg-loading {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =================================
|
||||||
|
// ==============scrollbar==========
|
||||||
|
// =================================
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 6px;
|
width: 6px;
|
||||||
height: 6px;
|
height: 6px;
|
||||||
|
@@ -1,103 +0,0 @@
|
|||||||
@import 'var/link';
|
|
||||||
@import './mixins/reset-text.less';
|
|
||||||
@import 'color/index';
|
|
||||||
.reset() {
|
|
||||||
html,
|
|
||||||
body {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
&.color-weak {
|
|
||||||
filter: invert(80%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.gray-mode {
|
|
||||||
filter: grayscale(100%);
|
|
||||||
filter: progid:dximagetransform.microsoft.basicimage(grayscale=1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
input::-ms-clear,
|
|
||||||
input::-ms-reveal {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
.reset-text();
|
|
||||||
}
|
|
||||||
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
font-weight: 500;
|
|
||||||
color: @heading-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul,
|
|
||||||
ol {
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
list-style-type: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
vertical-align: top;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
|
||||||
border-collapse: collapse;
|
|
||||||
border-spacing: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:focus,
|
|
||||||
a:active {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
i,
|
|
||||||
em {
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
div:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: @link-color;
|
|
||||||
text-decoration: @link-decoration;
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: transparent; // remove the gray background on active links in IE 10.
|
|
||||||
outline: none;
|
|
||||||
transition: color 0.3s;
|
|
||||||
-webkit-text-decoration-skip: objects; // remove gaps in links underline in iOS 8+ and Safari 8+.
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: @link-hover-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
color: @link-active-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active,
|
|
||||||
&:hover {
|
|
||||||
text-decoration: @link-hover-decoration;
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&[disabled] {
|
|
||||||
color: @disabled-color;
|
|
||||||
pointer-events: none;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,11 +1,11 @@
|
|||||||
.transition-default() {
|
.transition-default() {
|
||||||
&-enter-active,
|
&-enter-active,
|
||||||
&-leave-active {
|
&-leave-active {
|
||||||
transition: 0.1s cubic-bezier(0.25, 0.8, 0.5, 1) !important;
|
transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-move {
|
&-move {
|
||||||
transition: transform 0.2s;
|
transition: transform 0.4s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
/* fade-slide */
|
/* fade-slide */
|
||||||
.fade-slide-leave-active,
|
.fade-slide-leave-active,
|
||||||
.fade-slide-enter-active {
|
.fade-slide-enter-active {
|
||||||
transition: all 0.2s;
|
transition: all 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade-slide-enter-from {
|
.fade-slide-enter-from {
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
//
|
//
|
||||||
@side-drag-z-index: 200;
|
@side-drag-z-index: 200;
|
||||||
|
|
||||||
@page-loading-z-index: 10000;
|
@page-loading-z-index: 10000;
|
||||||
|
|
||||||
// left-menu
|
// left-menu
|
||||||
|
@@ -19,10 +19,20 @@ export function useLocaleSetting() {
|
|||||||
// get Fallback Locales
|
// get Fallback Locales
|
||||||
const getFallbackLocale = computed((): string => unref(getLocale).fallback);
|
const getFallbackLocale = computed((): string => unref(getLocale).fallback);
|
||||||
|
|
||||||
|
const getShowLocale = computed(() => unref(getLocale).show);
|
||||||
|
|
||||||
// Set locale configuration
|
// Set locale configuration
|
||||||
function setLocale(locale: Partial<LocaleSetting>): void {
|
function setLocale(locale: Partial<LocaleSetting>): void {
|
||||||
appStore.commitProjectConfigState({ locale });
|
appStore.commitProjectConfigState({ locale });
|
||||||
}
|
}
|
||||||
|
|
||||||
return { getLocale, getLang, localeList, setLocale, getAvailableLocales, getFallbackLocale };
|
return {
|
||||||
|
getLocale,
|
||||||
|
getLang,
|
||||||
|
localeList,
|
||||||
|
setLocale,
|
||||||
|
getShowLocale,
|
||||||
|
getAvailableLocales,
|
||||||
|
getFallbackLocale,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
21
src/hooks/web/useI18n.ts
Normal file
21
src/hooks/web/useI18n.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { getI18n } from '/@/setup/i18n';
|
||||||
|
|
||||||
|
export function useI18n(namespace?: string) {
|
||||||
|
const { t, ...methods } = getI18n().global;
|
||||||
|
|
||||||
|
function getKey(key: string) {
|
||||||
|
if (!namespace) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
if (key.startsWith(namespace)) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
return `${namespace}.${key}`;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...methods,
|
||||||
|
t: (key: string, ...arg: Parameters<typeof t>) => {
|
||||||
|
return t(getKey(key), ...arg);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
@@ -65,10 +65,3 @@ export function useLocale() {
|
|||||||
antConfigLocale: antConfigLocaleRef,
|
antConfigLocale: antConfigLocaleRef,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* For non-setup setting
|
|
||||||
*/
|
|
||||||
export function useExternalI18n() {
|
|
||||||
return getI18n().global;
|
|
||||||
}
|
|
||||||
|
@@ -8,18 +8,21 @@ import { GithubFilled } from '@ant-design/icons-vue';
|
|||||||
import { DOC_URL, GITHUB_URL, SITE_URL } from '/@/settings/siteSetting';
|
import { DOC_URL, GITHUB_URL, SITE_URL } from '/@/settings/siteSetting';
|
||||||
import { openWindow } from '/@/utils';
|
import { openWindow } from '/@/utils';
|
||||||
|
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'LayoutContent',
|
name: 'LayoutContent',
|
||||||
setup() {
|
setup() {
|
||||||
|
const { t } = useI18n('layout.footer');
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return (
|
||||||
<Layout.Footer class="layout-footer">
|
<Layout.Footer class="layout-footer">
|
||||||
{() => (
|
{() => (
|
||||||
<>
|
<>
|
||||||
<div class="layout-footer__links">
|
<div class="layout-footer__links">
|
||||||
<a onClick={() => openWindow(SITE_URL)}>在线预览</a>
|
<a onClick={() => openWindow(SITE_URL)}>{t('onlinePreview')}</a>
|
||||||
<GithubFilled onClick={() => openWindow(GITHUB_URL)} class="github" />
|
<GithubFilled onClick={() => openWindow(GITHUB_URL)} class="github" />
|
||||||
<a onClick={() => openWindow(DOC_URL)}>在线文档</a>
|
<a onClick={() => openWindow(DOC_URL)}>{t('onlineDocument')}</a>
|
||||||
</div>
|
</div>
|
||||||
<div>Copyright ©2020 Vben Admin</div>
|
<div>Copyright ©2020 Vben Admin</div>
|
||||||
</>
|
</>
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import './index.less';
|
import './index.less';
|
||||||
|
|
||||||
import type { FunctionalComponent } from 'vue';
|
import type { FunctionalComponent } from 'vue';
|
||||||
|
import type { Component } from '/@/components/types';
|
||||||
|
|
||||||
import { defineComponent, unref, computed, ref, nextTick } from 'vue';
|
import { defineComponent, unref, computed, ref, nextTick } from 'vue';
|
||||||
|
|
||||||
@@ -27,6 +28,7 @@ import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
|
|||||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||||
|
import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting';
|
||||||
|
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
@@ -34,7 +36,8 @@ import { errorStore } from '/@/store/modules/error';
|
|||||||
|
|
||||||
import { PageEnum } from '/@/enums/pageEnum';
|
import { PageEnum } from '/@/enums/pageEnum';
|
||||||
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
|
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
|
||||||
import { Component } from '/@/components/types';
|
import { AppLocalePicker } from '/@/components/Application';
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
|
||||||
interface TooltipItemProps {
|
interface TooltipItemProps {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -65,9 +68,11 @@ export default defineComponent({
|
|||||||
const logoWidthRef = ref(200);
|
const logoWidthRef = ref(200);
|
||||||
const logoRef = ref<ComponentRef>(null);
|
const logoRef = ref<ComponentRef>(null);
|
||||||
const { refreshPage } = useTabs();
|
const { refreshPage } = useTabs();
|
||||||
|
const { t } = useI18n('layout.header');
|
||||||
|
|
||||||
const { getShowTopMenu, getShowHeaderTrigger, getSplit, getTopMenuAlign } = useMenuSetting();
|
const { getShowTopMenu, getShowHeaderTrigger, getSplit, getTopMenuAlign } = useMenuSetting();
|
||||||
|
|
||||||
|
const { getShowLocale } = useLocaleSetting();
|
||||||
const { getUseErrorHandle, getShowBreadCrumbIcon } = useRootSetting();
|
const { getUseErrorHandle, getShowBreadCrumbIcon } = useRootSetting();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -160,8 +165,8 @@ export default defineComponent({
|
|||||||
|
|
||||||
function renderActionDefault(Comp: Component | any, event: Fn) {
|
function renderActionDefault(Comp: Component | any, event: Fn) {
|
||||||
return (
|
return (
|
||||||
<div class={`layout-header__action-item`} onClick={event}>
|
<div class="layout-header__action-item" onClick={event}>
|
||||||
<Comp class={`layout-header__action-icon`} />
|
<Comp class="layout-header__action-icon" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -170,7 +175,7 @@ export default defineComponent({
|
|||||||
return (
|
return (
|
||||||
<div class={`layout-header__action`}>
|
<div class={`layout-header__action`}>
|
||||||
{unref(getUseErrorHandle) && (
|
{unref(getUseErrorHandle) && (
|
||||||
<TooltipItem title="错误日志">
|
<TooltipItem title={t('layout.header.tooltipErrorLog')}>
|
||||||
{() => (
|
{() => (
|
||||||
<Badge
|
<Badge
|
||||||
count={errorStore.getErrorListCountState}
|
count={errorStore.getErrorListCountState}
|
||||||
@@ -185,23 +190,31 @@ export default defineComponent({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{unref(getUseLockPage) && (
|
{unref(getUseLockPage) && (
|
||||||
<TooltipItem title="锁定屏幕">
|
<TooltipItem title={t('layout.header.tooltipLock')}>
|
||||||
{() => renderActionDefault(LockOutlined, handleLockPage)}
|
{() => renderActionDefault(LockOutlined, handleLockPage)}
|
||||||
</TooltipItem>
|
</TooltipItem>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{unref(getShowNotice) && (
|
{unref(getShowNotice) && (
|
||||||
<TooltipItem title="消息通知">{() => <NoticeAction />}</TooltipItem>
|
<TooltipItem title={t('layout.header.tooltipNotify')}>
|
||||||
|
{() => <NoticeAction />}
|
||||||
|
</TooltipItem>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{unref(getShowRedo) && (
|
{unref(getShowRedo) && (
|
||||||
<TooltipItem title="刷新">
|
<TooltipItem title={t('layout.header.tooltipRedo')}>
|
||||||
{() => renderActionDefault(RedoOutlined, refreshPage)}
|
{() => renderActionDefault(RedoOutlined, refreshPage)}
|
||||||
</TooltipItem>
|
</TooltipItem>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{unref(getShowFullScreen) && (
|
{unref(getShowFullScreen) && (
|
||||||
<TooltipItem title={unref(isFullscreenRef) ? '退出全屏' : '全屏'}>
|
<TooltipItem
|
||||||
|
title={
|
||||||
|
unref(isFullscreenRef)
|
||||||
|
? t('layout.header.tooltipExitFull')
|
||||||
|
: t('layout.header.tooltipEntryFull')
|
||||||
|
}
|
||||||
|
>
|
||||||
{() => {
|
{() => {
|
||||||
const Icon = !unref(isFullscreenRef) ? (
|
const Icon = !unref(isFullscreenRef) ? (
|
||||||
<FullscreenOutlined />
|
<FullscreenOutlined />
|
||||||
@@ -212,7 +225,14 @@ export default defineComponent({
|
|||||||
}}
|
}}
|
||||||
</TooltipItem>
|
</TooltipItem>
|
||||||
)}
|
)}
|
||||||
<UserDropdown class={`layout-header__user-dropdown`} />
|
<UserDropdown class="layout-header__user-dropdown" />
|
||||||
|
{unref(getShowLocale) && (
|
||||||
|
<AppLocalePicker
|
||||||
|
reload={true}
|
||||||
|
showText={false}
|
||||||
|
class="layout-header__action-item locale"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
// components
|
// components
|
||||||
import { Dropdown, Menu, Divider } from 'ant-design-vue';
|
import { Dropdown, Menu } from 'ant-design-vue';
|
||||||
|
|
||||||
import { defineComponent, computed, unref } from 'vue';
|
import { defineComponent, computed, unref } from 'vue';
|
||||||
|
|
||||||
@@ -16,6 +16,7 @@ import { openWindow } from '/@/utils';
|
|||||||
|
|
||||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||||
import { FunctionalComponent } from 'vue';
|
import { FunctionalComponent } from 'vue';
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
|
||||||
type MenuEvent = 'loginOut' | 'doc';
|
type MenuEvent = 'loginOut' | 'doc';
|
||||||
interface MenuItemProps {
|
interface MenuItemProps {
|
||||||
@@ -43,6 +44,7 @@ const MenuItem: FunctionalComponent<MenuItemProps> = (props) => {
|
|||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'UserDropdown',
|
name: 'UserDropdown',
|
||||||
setup() {
|
setup() {
|
||||||
|
const { t } = useI18n('layout.header');
|
||||||
const { getShowDoc } = useHeaderSetting();
|
const { getShowDoc } = useHeaderSetting();
|
||||||
|
|
||||||
const getUserInfo = computed(() => {
|
const getUserInfo = computed(() => {
|
||||||
@@ -89,9 +91,14 @@ export default defineComponent({
|
|||||||
<Menu onClick={handleMenuClick}>
|
<Menu onClick={handleMenuClick}>
|
||||||
{() => (
|
{() => (
|
||||||
<>
|
<>
|
||||||
{showDoc && <MenuItem key="doc" text="文档" icon="gg:loadbar-doc" />}
|
{showDoc && <MenuItem key="doc" text={t('dropdownItemDoc')} icon="gg:loadbar-doc" />}
|
||||||
{showDoc && <Divider />}
|
{/* @ts-ignore */}
|
||||||
<MenuItem key="loginOut" text="退出系统" icon="ant-design:poweroff-outlined" />
|
{showDoc && <Menu.Divider />}
|
||||||
|
<MenuItem
|
||||||
|
key="loginOut"
|
||||||
|
text={t('dropdownItemLoginOut')}
|
||||||
|
icon="ant-design:poweroff-outlined"
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Menu>
|
</Menu>
|
||||||
@@ -100,7 +107,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return (
|
||||||
<Dropdown placement="bottomLeft">
|
<Dropdown placement="bottomLeft" overlayClassName="app-layout-header-user-dropdown-overlay">
|
||||||
{{
|
{{
|
||||||
default: () => renderSlotsDefault(),
|
default: () => renderSlotsDefault(),
|
||||||
overlay: () => renderSlotOverlay(),
|
overlay: () => renderSlotOverlay(),
|
||||||
|
@@ -92,6 +92,11 @@
|
|||||||
&:hover {
|
&:hover {
|
||||||
background: @header-light-bg-hover-color;
|
background: @header-light-bg-hover-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.locale {
|
||||||
|
padding: 0 10px;
|
||||||
|
color: rgba(0, 0, 0, 0.65);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-icon {
|
&-icon {
|
||||||
@@ -221,3 +226,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.app-layout-header-user-dropdown-overlay {
|
||||||
|
.ant-dropdown-menu-item {
|
||||||
|
min-width: 160px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
.default-layout {
|
.default-layout {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
|
background: @content-bg;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
> .ant-layout {
|
> .ant-layout {
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
|
@@ -9,11 +9,13 @@ import headerImg from '/@/assets/images/header.jpg';
|
|||||||
|
|
||||||
import { appStore } from '/@/store/modules/app';
|
import { appStore } from '/@/store/modules/app';
|
||||||
import { userStore } from '/@/store/modules/user';
|
import { userStore } from '/@/store/modules/user';
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
|
||||||
const prefixCls = 'lock-modal';
|
const prefixCls = 'lock-modal';
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'LockModal',
|
name: 'LockModal',
|
||||||
setup(_, { attrs }) {
|
setup(_, { attrs }) {
|
||||||
|
const { t } = useI18n('layout.header');
|
||||||
const [register, { closeModal }] = useModalInner();
|
const [register, { closeModal }] = useModalInner();
|
||||||
|
|
||||||
const [registerForm, { validateFields, resetFields }] = useForm({
|
const [registerForm, { validateFields, resetFields }] = useForm({
|
||||||
@@ -21,7 +23,7 @@ export default defineComponent({
|
|||||||
schemas: [
|
schemas: [
|
||||||
{
|
{
|
||||||
field: 'password',
|
field: 'password',
|
||||||
label: '锁屏密码',
|
label: t('lockScreenPassword'),
|
||||||
component: 'InputPassword',
|
component: 'InputPassword',
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
@@ -49,7 +51,13 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<BasicModal footer={null} title="锁定屏幕" {...attrs} class={prefixCls} onRegister={register}>
|
<BasicModal
|
||||||
|
footer={null}
|
||||||
|
title={t('lockScreen')}
|
||||||
|
{...attrs}
|
||||||
|
class={prefixCls}
|
||||||
|
onRegister={register}
|
||||||
|
>
|
||||||
{() => (
|
{() => (
|
||||||
<div class={`${prefixCls}__entry`}>
|
<div class={`${prefixCls}__entry`}>
|
||||||
<div class={`${prefixCls}__header`}>
|
<div class={`${prefixCls}__header`}>
|
||||||
@@ -61,10 +69,10 @@ export default defineComponent({
|
|||||||
|
|
||||||
<div class={`${prefixCls}__footer`}>
|
<div class={`${prefixCls}__footer`}>
|
||||||
<Button type="primary" block class="mt-2" onClick={lock}>
|
<Button type="primary" block class="mt-2" onClick={lock}>
|
||||||
{() => '锁屏'}
|
{() => t('lockScreenBtn')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button block class="mt-2" onClick={lock.bind(null, false)}>
|
<Button block class="mt-2" onClick={lock.bind(null, false)}>
|
||||||
{() => ' 不设置密码锁屏'}
|
{() => t('notLockScreenPassword')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -13,6 +13,7 @@ import { useTabDropdown } from './useTabDropdown';
|
|||||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||||
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
|
||||||
const ExtraContent: FunctionalComponent = () => {
|
const ExtraContent: FunctionalComponent = () => {
|
||||||
return (
|
return (
|
||||||
@@ -56,6 +57,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
|
const { t } = useI18n('layout.multipleTab');
|
||||||
const { getShowMenu } = useMenuSetting();
|
const { getShowMenu } = useMenuSetting();
|
||||||
const { getShowHeader } = useHeaderSetting();
|
const { getShowHeader } = useHeaderSetting();
|
||||||
const { getShowQuick } = useMultipleTabSetting();
|
const { getShowQuick } = useMultipleTabSetting();
|
||||||
@@ -71,7 +73,10 @@ export default defineComponent({
|
|||||||
const { getDropMenuList, handleMenuEvent } = useTabDropdown(props as TabContentProps);
|
const { getDropMenuList, handleMenuEvent } = useTabDropdown(props as TabContentProps);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const scaleAction = getScaleAction(unref(getIsScale) ? '收起' : '展开', unref(getIsScale));
|
const scaleAction = getScaleAction(
|
||||||
|
unref(getIsScale) ? t('putAway') : t('unfold'),
|
||||||
|
unref(getIsScale)
|
||||||
|
);
|
||||||
const dropMenuList = unref(getDropMenuList) || [];
|
const dropMenuList = unref(getDropMenuList) || [];
|
||||||
|
|
||||||
const isTab = unref(getIsTab);
|
const isTab = unref(getIsTab);
|
||||||
|
@@ -2,6 +2,10 @@ import { DropMenu } from '/@/components/Dropdown/index';
|
|||||||
import { AppRouteRecordRaw } from '/@/router/types';
|
import { AppRouteRecordRaw } from '/@/router/types';
|
||||||
import type { TabItem } from '/@/store/modules/tab';
|
import type { TabItem } from '/@/store/modules/tab';
|
||||||
|
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
|
||||||
|
const { t } = useI18n('layout.multipleTab');
|
||||||
|
|
||||||
export enum TabContentEnum {
|
export enum TabContentEnum {
|
||||||
TAB_TYPE,
|
TAB_TYPE,
|
||||||
EXTRA_TYPE,
|
EXTRA_TYPE,
|
||||||
@@ -37,40 +41,40 @@ export function getActions() {
|
|||||||
const REFRESH_PAGE: DropMenu = {
|
const REFRESH_PAGE: DropMenu = {
|
||||||
icon: 'ant-design:reload-outlined',
|
icon: 'ant-design:reload-outlined',
|
||||||
event: MenuEventEnum.REFRESH_PAGE,
|
event: MenuEventEnum.REFRESH_PAGE,
|
||||||
text: '刷新',
|
text: t('redo'),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
};
|
};
|
||||||
const CLOSE_CURRENT: DropMenu = {
|
const CLOSE_CURRENT: DropMenu = {
|
||||||
icon: 'ant-design:close-outlined',
|
icon: 'ant-design:close-outlined',
|
||||||
event: MenuEventEnum.CLOSE_CURRENT,
|
event: MenuEventEnum.CLOSE_CURRENT,
|
||||||
text: '关闭',
|
text: t('close'),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
divider: true,
|
divider: true,
|
||||||
};
|
};
|
||||||
const CLOSE_LEFT: DropMenu = {
|
const CLOSE_LEFT: DropMenu = {
|
||||||
icon: 'ant-design:pic-left-outlined',
|
icon: 'ant-design:pic-left-outlined',
|
||||||
event: MenuEventEnum.CLOSE_LEFT,
|
event: MenuEventEnum.CLOSE_LEFT,
|
||||||
text: '关闭左侧',
|
text: t('closeLeft'),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
divider: false,
|
divider: false,
|
||||||
};
|
};
|
||||||
const CLOSE_RIGHT: DropMenu = {
|
const CLOSE_RIGHT: DropMenu = {
|
||||||
icon: 'ant-design:pic-right-outlined',
|
icon: 'ant-design:pic-right-outlined',
|
||||||
event: MenuEventEnum.CLOSE_RIGHT,
|
event: MenuEventEnum.CLOSE_RIGHT,
|
||||||
text: '关闭右侧',
|
text: t('closeRight'),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
divider: true,
|
divider: true,
|
||||||
};
|
};
|
||||||
const CLOSE_OTHER: DropMenu = {
|
const CLOSE_OTHER: DropMenu = {
|
||||||
icon: 'ant-design:pic-center-outlined',
|
icon: 'ant-design:pic-center-outlined',
|
||||||
event: MenuEventEnum.CLOSE_OTHER,
|
event: MenuEventEnum.CLOSE_OTHER,
|
||||||
text: '关闭其他',
|
text: t('closeOther'),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
};
|
};
|
||||||
const CLOSE_ALL: DropMenu = {
|
const CLOSE_ALL: DropMenu = {
|
||||||
icon: 'ant-design:line-outlined',
|
icon: 'ant-design:line-outlined',
|
||||||
event: MenuEventEnum.CLOSE_ALL,
|
event: MenuEventEnum.CLOSE_ALL,
|
||||||
text: '关闭全部',
|
text: t('closeAll'),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
};
|
};
|
||||||
return [REFRESH_PAGE, CLOSE_CURRENT, CLOSE_LEFT, CLOSE_RIGHT, CLOSE_OTHER, CLOSE_ALL];
|
return [REFRESH_PAGE, CLOSE_CURRENT, CLOSE_LEFT, CLOSE_RIGHT, CLOSE_OTHER, CLOSE_ALL];
|
||||||
|
@@ -18,6 +18,7 @@ import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
|||||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||||
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
||||||
import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
|
import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
|
||||||
import { updateColorWeak, updateGrayMode } from '/@/setup/theme';
|
import { updateColorWeak, updateGrayMode } from '/@/setup/theme';
|
||||||
|
|
||||||
@@ -55,6 +56,7 @@ interface ThemePickerProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { createSuccessModal, createMessage } = useMessage();
|
const { createSuccessModal, createMessage } = useMessage();
|
||||||
|
const { t } = useI18n('layout.setting');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Menu type Picker comp
|
* Menu type Picker comp
|
||||||
@@ -120,8 +122,8 @@ const FooterButton: FunctionalComponent = () => {
|
|||||||
const { isSuccessRef } = useCopyToClipboard(JSON.stringify(unref(getRootSetting), null, 2));
|
const { isSuccessRef } = useCopyToClipboard(JSON.stringify(unref(getRootSetting), null, 2));
|
||||||
unref(isSuccessRef) &&
|
unref(isSuccessRef) &&
|
||||||
createSuccessModal({
|
createSuccessModal({
|
||||||
title: '操作成功',
|
title: t('operatingTitle'),
|
||||||
content: '复制成功,请到 src/settings/projectSetting.ts 中修改配置!',
|
content: t('operatingContent'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function handleResetSetting() {
|
function handleResetSetting() {
|
||||||
@@ -131,7 +133,7 @@ const FooterButton: FunctionalComponent = () => {
|
|||||||
// updateTheme(themeColor);
|
// updateTheme(themeColor);
|
||||||
updateColorWeak(colorWeak);
|
updateColorWeak(colorWeak);
|
||||||
updateGrayMode(grayMode);
|
updateGrayMode(grayMode);
|
||||||
createMessage.success('重置成功!');
|
createMessage.success(t('resetSuccess'));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
createMessage.error(error);
|
createMessage.error(error);
|
||||||
}
|
}
|
||||||
@@ -149,7 +151,7 @@ const FooterButton: FunctionalComponent = () => {
|
|||||||
{() => (
|
{() => (
|
||||||
<>
|
<>
|
||||||
<CopyOutlined class="mr-2" />
|
<CopyOutlined class="mr-2" />
|
||||||
拷贝
|
{t('copyBtn')}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -157,7 +159,7 @@ const FooterButton: FunctionalComponent = () => {
|
|||||||
{() => (
|
{() => (
|
||||||
<>
|
<>
|
||||||
<RedoOutlined class="mr-2" />
|
<RedoOutlined class="mr-2" />
|
||||||
重置
|
{t('resetBtn')}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -165,7 +167,7 @@ const FooterButton: FunctionalComponent = () => {
|
|||||||
{() => (
|
{() => (
|
||||||
<>
|
<>
|
||||||
<RedoOutlined class="mr-2" />
|
<RedoOutlined class="mr-2" />
|
||||||
清空缓存并返回登录页
|
{t('clearBtn')}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -224,7 +226,7 @@ export default defineComponent({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MenuTypePicker />
|
<MenuTypePicker />
|
||||||
{renderSwitchItem('分割菜单', {
|
{renderSwitchItem(t('splitMenu'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.MENU_SPLIT, e);
|
baseHandler(HandlerEnum.MENU_SPLIT, e);
|
||||||
},
|
},
|
||||||
@@ -238,7 +240,7 @@ export default defineComponent({
|
|||||||
function renderTheme() {
|
function renderTheme() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Divider>{() => '顶栏主题'}</Divider>
|
<Divider>{() => t('headerTheme')}</Divider>
|
||||||
<ThemePicker
|
<ThemePicker
|
||||||
colorList={HEADER_PRESET_BG_COLOR_LIST}
|
colorList={HEADER_PRESET_BG_COLOR_LIST}
|
||||||
def={unref(getHeaderBgColor)}
|
def={unref(getHeaderBgColor)}
|
||||||
@@ -246,7 +248,7 @@ export default defineComponent({
|
|||||||
baseHandler(HandlerEnum.HEADER_THEME, e);
|
baseHandler(HandlerEnum.HEADER_THEME, e);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Divider>{() => '菜单主题'}</Divider>
|
<Divider>{() => t('sidebarTheme')}</Divider>
|
||||||
<ThemePicker
|
<ThemePicker
|
||||||
colorList={SIDE_BAR_BG_COLOR_LIST}
|
colorList={SIDE_BAR_BG_COLOR_LIST}
|
||||||
def={unref(getMenuBgColor)}
|
def={unref(getMenuBgColor)}
|
||||||
@@ -263,56 +265,56 @@ export default defineComponent({
|
|||||||
*/
|
*/
|
||||||
function renderFeatures() {
|
function renderFeatures() {
|
||||||
return [
|
return [
|
||||||
renderSwitchItem('侧边菜单拖拽', {
|
renderSwitchItem(t('menuDrag'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.MENU_HAS_DRAG, e);
|
baseHandler(HandlerEnum.MENU_HAS_DRAG, e);
|
||||||
},
|
},
|
||||||
def: unref(getCanDrag),
|
def: unref(getCanDrag),
|
||||||
disabled: !unref(getShowMenuRef),
|
disabled: !unref(getShowMenuRef),
|
||||||
}),
|
}),
|
||||||
renderSwitchItem('侧边菜单搜索', {
|
renderSwitchItem(t('menuSearch'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.MENU_SHOW_SEARCH, e);
|
baseHandler(HandlerEnum.MENU_SHOW_SEARCH, e);
|
||||||
},
|
},
|
||||||
def: unref(getShowSearch),
|
def: unref(getShowSearch),
|
||||||
disabled: !unref(getShowMenuRef),
|
disabled: !unref(getShowMenuRef),
|
||||||
}),
|
}),
|
||||||
renderSwitchItem('侧边菜单手风琴模式', {
|
renderSwitchItem(t('menuAccordion'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.MENU_ACCORDION, e);
|
baseHandler(HandlerEnum.MENU_ACCORDION, e);
|
||||||
},
|
},
|
||||||
def: unref(getAccordion),
|
def: unref(getAccordion),
|
||||||
disabled: !unref(getShowMenuRef),
|
disabled: !unref(getShowMenuRef),
|
||||||
}),
|
}),
|
||||||
renderSwitchItem('折叠菜单', {
|
renderSwitchItem(t('menuCollapse'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.MENU_COLLAPSED, e);
|
baseHandler(HandlerEnum.MENU_COLLAPSED, e);
|
||||||
},
|
},
|
||||||
def: unref(getCollapsed),
|
def: unref(getCollapsed),
|
||||||
disabled: !unref(getShowMenuRef),
|
disabled: !unref(getShowMenuRef),
|
||||||
}),
|
}),
|
||||||
renderSwitchItem('折叠菜单显示名称', {
|
renderSwitchItem(t('collapseMenuDisplayName'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.MENU_COLLAPSED_SHOW_TITLE, e);
|
baseHandler(HandlerEnum.MENU_COLLAPSED_SHOW_TITLE, e);
|
||||||
},
|
},
|
||||||
def: unref(getCollapsedShowTitle),
|
def: unref(getCollapsedShowTitle),
|
||||||
disabled: !unref(getShowMenuRef) || !unref(getCollapsed),
|
disabled: !unref(getShowMenuRef) || !unref(getCollapsed),
|
||||||
}),
|
}),
|
||||||
renderSwitchItem('固定header', {
|
renderSwitchItem(t('fixedHeader'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.HEADER_FIXED, e);
|
baseHandler(HandlerEnum.HEADER_FIXED, e);
|
||||||
},
|
},
|
||||||
def: unref(getHeaderFixed),
|
def: unref(getHeaderFixed),
|
||||||
disabled: !unref(getShowHeader),
|
disabled: !unref(getShowHeader),
|
||||||
}),
|
}),
|
||||||
renderSwitchItem('固定Siderbar', {
|
renderSwitchItem(t('fixedSideBar'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.MENU_FIXED, e);
|
baseHandler(HandlerEnum.MENU_FIXED, e);
|
||||||
},
|
},
|
||||||
def: unref(getMenuFixed),
|
def: unref(getMenuFixed),
|
||||||
disabled: !unref(getShowMenuRef),
|
disabled: !unref(getShowMenuRef),
|
||||||
}),
|
}),
|
||||||
renderSelectItem('顶部菜单布局', {
|
renderSelectItem(t('topMenuLayout'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.MENU_TOP_ALIGN, e);
|
baseHandler(HandlerEnum.MENU_TOP_ALIGN, e);
|
||||||
},
|
},
|
||||||
@@ -320,7 +322,7 @@ export default defineComponent({
|
|||||||
options: topMenuAlignOptions,
|
options: topMenuAlignOptions,
|
||||||
disabled: !unref(getShowHeader) || (!unref(getIsTopMenu) && !unref(getSplit)),
|
disabled: !unref(getShowHeader) || (!unref(getIsTopMenu) && !unref(getSplit)),
|
||||||
}),
|
}),
|
||||||
renderSelectItem('菜单折叠按钮', {
|
renderSelectItem(t('menuCollapseButton'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.MENU_TRIGGER, e);
|
baseHandler(HandlerEnum.MENU_TRIGGER, e);
|
||||||
},
|
},
|
||||||
@@ -329,7 +331,7 @@ export default defineComponent({
|
|||||||
options: menuTriggerOptions,
|
options: menuTriggerOptions,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
renderSelectItem('内容区域宽度', {
|
renderSelectItem(t('contentMode'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.CONTENT_MODE, e);
|
baseHandler(HandlerEnum.CONTENT_MODE, e);
|
||||||
},
|
},
|
||||||
@@ -337,9 +339,9 @@ export default defineComponent({
|
|||||||
options: contentModeOptions,
|
options: contentModeOptions,
|
||||||
}),
|
}),
|
||||||
<div class={`setting-drawer__cell-item`}>
|
<div class={`setting-drawer__cell-item`}>
|
||||||
<span>自动锁屏</span>
|
<span>{t('autoScreenLock')}</span>
|
||||||
<InputNumber
|
<InputNumber
|
||||||
style="width:120px"
|
style="width:126px"
|
||||||
size="small"
|
size="small"
|
||||||
min={0}
|
min={0}
|
||||||
onChange={(e: any) => {
|
onChange={(e: any) => {
|
||||||
@@ -348,16 +350,16 @@ export default defineComponent({
|
|||||||
defaultValue={appStore.getProjectConfig.lockTime}
|
defaultValue={appStore.getProjectConfig.lockTime}
|
||||||
formatter={(value: string) => {
|
formatter={(value: string) => {
|
||||||
if (parseInt(value) === 0) {
|
if (parseInt(value) === 0) {
|
||||||
return '0(不自动锁屏)';
|
return `0(${t('notAutoScreenLock')})`;
|
||||||
}
|
}
|
||||||
return `${value}分钟`;
|
return `${value}${t('minute')}`;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>,
|
</div>,
|
||||||
<div class={`setting-drawer__cell-item`}>
|
<div class={`setting-drawer__cell-item`}>
|
||||||
<span>菜单展开宽度</span>
|
<span>{t('expandedMenuWidth')}</span>
|
||||||
<InputNumber
|
<InputNumber
|
||||||
style="width:120px"
|
style="width:126px"
|
||||||
size="small"
|
size="small"
|
||||||
max={600}
|
max={600}
|
||||||
min={100}
|
min={100}
|
||||||
@@ -375,27 +377,27 @@ export default defineComponent({
|
|||||||
|
|
||||||
function renderContent() {
|
function renderContent() {
|
||||||
return [
|
return [
|
||||||
renderSwitchItem('面包屑', {
|
renderSwitchItem(t('breadcrumb'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.SHOW_BREADCRUMB, e);
|
baseHandler(HandlerEnum.SHOW_BREADCRUMB, e);
|
||||||
},
|
},
|
||||||
def: unref(getShowBreadCrumb),
|
def: unref(getShowBreadCrumb),
|
||||||
disabled: !unref(getShowHeader),
|
disabled: !unref(getShowHeader),
|
||||||
}),
|
}),
|
||||||
renderSwitchItem('面包屑图标', {
|
renderSwitchItem(t('breadcrumbIcon'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.SHOW_BREADCRUMB_ICON, e);
|
baseHandler(HandlerEnum.SHOW_BREADCRUMB_ICON, e);
|
||||||
},
|
},
|
||||||
def: unref(getShowBreadCrumbIcon),
|
def: unref(getShowBreadCrumbIcon),
|
||||||
disabled: !unref(getShowHeader),
|
disabled: !unref(getShowHeader),
|
||||||
}),
|
}),
|
||||||
renderSwitchItem('标签页', {
|
renderSwitchItem(t('tabs'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.TABS_SHOW, e);
|
baseHandler(HandlerEnum.TABS_SHOW, e);
|
||||||
},
|
},
|
||||||
def: unref(getShowMultipleTab),
|
def: unref(getShowMultipleTab),
|
||||||
}),
|
}),
|
||||||
renderSwitchItem('标签页快捷按钮', {
|
renderSwitchItem(t('tabsQuickBtn'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.TABS_SHOW_QUICK, e);
|
baseHandler(HandlerEnum.TABS_SHOW_QUICK, e);
|
||||||
},
|
},
|
||||||
@@ -403,14 +405,14 @@ export default defineComponent({
|
|||||||
disabled: !unref(getShowMultipleTab),
|
disabled: !unref(getShowMultipleTab),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
renderSwitchItem('左侧菜单', {
|
renderSwitchItem(t('sidebar'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.MENU_SHOW_SIDEBAR, e);
|
baseHandler(HandlerEnum.MENU_SHOW_SIDEBAR, e);
|
||||||
},
|
},
|
||||||
def: unref(getShowMenu),
|
def: unref(getShowMenu),
|
||||||
disabled: unref(getIsHorizontal),
|
disabled: unref(getIsHorizontal),
|
||||||
}),
|
}),
|
||||||
renderSwitchItem('顶栏', {
|
renderSwitchItem(t('header'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.HEADER_SHOW, e);
|
baseHandler(HandlerEnum.HEADER_SHOW, e);
|
||||||
},
|
},
|
||||||
@@ -422,25 +424,25 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
def: unref(getShowLogo),
|
def: unref(getShowLogo),
|
||||||
}),
|
}),
|
||||||
renderSwitchItem('页脚', {
|
renderSwitchItem(t('footer'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.SHOW_FOOTER, e);
|
baseHandler(HandlerEnum.SHOW_FOOTER, e);
|
||||||
},
|
},
|
||||||
def: unref(getShowFooter),
|
def: unref(getShowFooter),
|
||||||
}),
|
}),
|
||||||
renderSwitchItem('全屏内容', {
|
renderSwitchItem(t('fullContent'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.FULL_CONTENT, e);
|
baseHandler(HandlerEnum.FULL_CONTENT, e);
|
||||||
},
|
},
|
||||||
def: unref(getFullContent),
|
def: unref(getFullContent),
|
||||||
}),
|
}),
|
||||||
renderSwitchItem('灰色模式', {
|
renderSwitchItem(t('grayMode'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.GRAY_MODE, e);
|
baseHandler(HandlerEnum.GRAY_MODE, e);
|
||||||
},
|
},
|
||||||
def: unref(getGrayMode),
|
def: unref(getGrayMode),
|
||||||
}),
|
}),
|
||||||
renderSwitchItem('色弱模式', {
|
renderSwitchItem(t('colorWeak'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.COLOR_WEAK, e);
|
baseHandler(HandlerEnum.COLOR_WEAK, e);
|
||||||
},
|
},
|
||||||
@@ -452,13 +454,13 @@ export default defineComponent({
|
|||||||
function renderTransition() {
|
function renderTransition() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{renderSwitchItem('顶部进度条', {
|
{renderSwitchItem(t('progress'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.OPEN_PROGRESS, e);
|
baseHandler(HandlerEnum.OPEN_PROGRESS, e);
|
||||||
},
|
},
|
||||||
def: unref(getOpenNProgress),
|
def: unref(getOpenNProgress),
|
||||||
})}
|
})}
|
||||||
{renderSwitchItem('切换loading', {
|
{renderSwitchItem(t('switchLoading'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.OPEN_PAGE_LOADING, e);
|
baseHandler(HandlerEnum.OPEN_PAGE_LOADING, e);
|
||||||
},
|
},
|
||||||
@@ -466,14 +468,14 @@ export default defineComponent({
|
|||||||
disabled: !unref(getEnableTransition),
|
disabled: !unref(getEnableTransition),
|
||||||
})}
|
})}
|
||||||
|
|
||||||
{renderSwitchItem('切换动画', {
|
{renderSwitchItem(t('switchAnimation'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.OPEN_ROUTE_TRANSITION, e);
|
baseHandler(HandlerEnum.OPEN_ROUTE_TRANSITION, e);
|
||||||
},
|
},
|
||||||
def: unref(getEnableTransition),
|
def: unref(getEnableTransition),
|
||||||
})}
|
})}
|
||||||
|
|
||||||
{renderSelectItem('动画类型', {
|
{renderSelectItem(t('animationType'), {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.ROUTER_TRANSITION, e);
|
baseHandler(HandlerEnum.ROUTER_TRANSITION, e);
|
||||||
},
|
},
|
||||||
@@ -495,7 +497,7 @@ export default defineComponent({
|
|||||||
{...opt}
|
{...opt}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
size="small"
|
size="small"
|
||||||
style={{ width: '120px' }}
|
style={{ width: '126px' }}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
handler && handler(e);
|
handler && handler(e);
|
||||||
}}
|
}}
|
||||||
@@ -517,26 +519,26 @@ export default defineComponent({
|
|||||||
onChange={(e: any) => {
|
onChange={(e: any) => {
|
||||||
handler && handler(e);
|
handler && handler(e);
|
||||||
}}
|
}}
|
||||||
checkedChildren="开"
|
checkedChildren={t('on')}
|
||||||
unCheckedChildren="关"
|
unCheckedChildren={t('off')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<BasicDrawer {...attrs} title="项目配置" width={300} wrapClassName="setting-drawer">
|
<BasicDrawer {...attrs} title={t('drawerTitle')} width={330} wrapClassName="setting-drawer">
|
||||||
{{
|
{{
|
||||||
default: () => (
|
default: () => (
|
||||||
<>
|
<>
|
||||||
<Divider>{() => '导航栏模式'}</Divider>
|
<Divider>{() => t('navMode')}</Divider>
|
||||||
{renderSidebar()}
|
{renderSidebar()}
|
||||||
{renderTheme()}
|
{renderTheme()}
|
||||||
<Divider>{() => '界面功能'}</Divider>
|
<Divider>{() => t('interfaceFunction')}</Divider>
|
||||||
{renderFeatures()}
|
{renderFeatures()}
|
||||||
<Divider>{() => '界面显示'}</Divider>
|
<Divider>{() => t('interfaceDisplay')}</Divider>
|
||||||
{renderContent()}
|
{renderContent()}
|
||||||
<Divider>{() => '切换动画'}</Divider>
|
<Divider>{() => t('animation')}</Divider>
|
||||||
{renderTransition()}
|
{renderTransition()}
|
||||||
<Divider />
|
<Divider />
|
||||||
<FooterButton />
|
<FooterButton />
|
||||||
|
@@ -1,9 +1,12 @@
|
|||||||
import { ContentEnum, RouterTransitionEnum, ThemeEnum } from '/@/enums/appEnum';
|
import { ContentEnum, RouterTransitionEnum } from '/@/enums/appEnum';
|
||||||
import { MenuModeEnum, MenuTypeEnum, TopMenuAlignEnum, TriggerEnum } from '/@/enums/menuEnum';
|
import { MenuModeEnum, MenuTypeEnum, TopMenuAlignEnum, TriggerEnum } from '/@/enums/menuEnum';
|
||||||
|
|
||||||
import mixImg from '/@/assets/images/layout/menu-mix.svg';
|
import mixImg from '/@/assets/images/layout/menu-mix.svg';
|
||||||
import sidebarImg from '/@/assets/images/layout/menu-sidebar.svg';
|
import sidebarImg from '/@/assets/images/layout/menu-sidebar.svg';
|
||||||
import menuTopImg from '/@/assets/images/layout/menu-top.svg';
|
import menuTopImg from '/@/assets/images/layout/menu-top.svg';
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
|
||||||
|
const { t } = useI18n('layout.setting');
|
||||||
|
|
||||||
export enum HandlerEnum {
|
export enum HandlerEnum {
|
||||||
CHANGE_LAYOUT,
|
CHANGE_LAYOUT,
|
||||||
@@ -45,55 +48,44 @@ export enum HandlerEnum {
|
|||||||
OPEN_ROUTE_TRANSITION,
|
OPEN_ROUTE_TRANSITION,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const themeOptions = [
|
|
||||||
{
|
|
||||||
value: ThemeEnum.LIGHT,
|
|
||||||
label: '亮色',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: ThemeEnum.DARK,
|
|
||||||
label: '暗色',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const contentModeOptions = [
|
export const contentModeOptions = [
|
||||||
{
|
{
|
||||||
value: ContentEnum.FULL,
|
value: ContentEnum.FULL,
|
||||||
label: '流式',
|
label: t('contentModeFull'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: ContentEnum.FIXED,
|
value: ContentEnum.FIXED,
|
||||||
label: '定宽',
|
label: t('contentModeFixed'),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const topMenuAlignOptions = [
|
export const topMenuAlignOptions = [
|
||||||
{
|
{
|
||||||
value: TopMenuAlignEnum.CENTER,
|
value: TopMenuAlignEnum.CENTER,
|
||||||
label: '居中',
|
label: t('topMenuAlignRight'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: TopMenuAlignEnum.START,
|
value: TopMenuAlignEnum.START,
|
||||||
label: '居左',
|
label: t('topMenuAlignLeft'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: TopMenuAlignEnum.END,
|
value: TopMenuAlignEnum.END,
|
||||||
label: '居右',
|
label: t('topMenuAlignCenter'),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const menuTriggerOptions = [
|
export const menuTriggerOptions = [
|
||||||
{
|
{
|
||||||
value: TriggerEnum.NONE,
|
value: TriggerEnum.NONE,
|
||||||
label: '不显示',
|
label: t('menuTriggerNone'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: TriggerEnum.FOOTER,
|
value: TriggerEnum.FOOTER,
|
||||||
label: '底部',
|
label: t('menuTriggerBottom'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: TriggerEnum.HEADER,
|
value: TriggerEnum.HEADER,
|
||||||
label: '顶部',
|
label: t('menuTriggerTop'),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -112,20 +104,20 @@ export const routerTransitionOptions = [
|
|||||||
|
|
||||||
export const menuTypeList = [
|
export const menuTypeList = [
|
||||||
{
|
{
|
||||||
title: '左侧菜单模式',
|
title: t('menuTypeSidebar'),
|
||||||
mode: MenuModeEnum.INLINE,
|
mode: MenuModeEnum.INLINE,
|
||||||
type: MenuTypeEnum.SIDEBAR,
|
type: MenuTypeEnum.SIDEBAR,
|
||||||
src: sidebarImg,
|
src: sidebarImg,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '混合模式',
|
title: t('menuTypeMix'),
|
||||||
mode: MenuModeEnum.INLINE,
|
mode: MenuModeEnum.INLINE,
|
||||||
type: MenuTypeEnum.MIX,
|
type: MenuTypeEnum.MIX,
|
||||||
src: mixImg,
|
src: mixImg,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: '顶部菜单模式',
|
title: t('menuTypeTopMenu'),
|
||||||
mode: MenuModeEnum.HORIZONTAL,
|
mode: MenuModeEnum.HORIZONTAL,
|
||||||
type: MenuTypeEnum.TOP_MENU,
|
type: MenuTypeEnum.TOP_MENU,
|
||||||
src: menuTopImg,
|
src: menuTopImg,
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import './index.less';
|
import './index.less';
|
||||||
|
|
||||||
import { computed, defineComponent, ref, unref, watch, nextTick } from 'vue';
|
import { computed, defineComponent, ref, unref, watch, nextTick, CSSProperties } from 'vue';
|
||||||
|
|
||||||
import { Layout } from 'ant-design-vue';
|
import { Layout } from 'ant-design-vue';
|
||||||
import LayoutMenu from '../menu';
|
import LayoutMenu from '../menu';
|
||||||
@@ -91,17 +91,19 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const getHiddenDomStyle = computed(() => {
|
const getHiddenDomStyle = computed(
|
||||||
|
(): CSSProperties => {
|
||||||
const width = `${unref(getRealWidth)}px`;
|
const width = `${unref(getRealWidth)}px`;
|
||||||
return {
|
return {
|
||||||
width: width,
|
width: width,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
flex: `0 0 ${width}`,
|
flex: `0 0 ${width}`,
|
||||||
'max-width': width,
|
maxWidth: width,
|
||||||
'min-width': width,
|
minWidth: width,
|
||||||
transition: 'all 0.2s',
|
transition: 'all 0.2s',
|
||||||
};
|
};
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
function renderDefault() {
|
function renderDefault() {
|
||||||
return (
|
return (
|
||||||
|
4
src/locales/lang/en/layout/footer.ts
Normal file
4
src/locales/lang/en/layout/footer.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export default {
|
||||||
|
onlinePreview: 'Preview',
|
||||||
|
onlineDocument: 'Document',
|
||||||
|
};
|
18
src/locales/lang/en/layout/header.ts
Normal file
18
src/locales/lang/en/layout/header.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
export default {
|
||||||
|
// user dropdown
|
||||||
|
dropdownItemDoc: 'Document',
|
||||||
|
dropdownItemLoginOut: 'Login Out',
|
||||||
|
|
||||||
|
tooltipErrorLog: 'Error log',
|
||||||
|
tooltipLock: 'Lock screen',
|
||||||
|
tooltipNotify: 'Notification',
|
||||||
|
tooltipRedo: 'Refresh',
|
||||||
|
tooltipEntryFull: 'Full Screen',
|
||||||
|
tooltipExitFull: 'Exit Full Screen',
|
||||||
|
|
||||||
|
// lock
|
||||||
|
lockScreenPassword: 'Lock screen password',
|
||||||
|
lockScreen: 'Lock screen',
|
||||||
|
lockScreenBtn: 'Locking',
|
||||||
|
notLockScreenPassword: 'No password lock screen',
|
||||||
|
};
|
10
src/locales/lang/en/layout/multipleTab.ts
Normal file
10
src/locales/lang/en/layout/multipleTab.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
export default {
|
||||||
|
redo: 'Refresh',
|
||||||
|
close: 'Close',
|
||||||
|
closeLeft: 'Close Left',
|
||||||
|
closeRight: 'Close Right',
|
||||||
|
closeOther: 'Close Other',
|
||||||
|
closeAll: 'Close All',
|
||||||
|
putAway: 'PutAway',
|
||||||
|
unfold: 'Unfold',
|
||||||
|
};
|
73
src/locales/lang/en/layout/setting.ts
Normal file
73
src/locales/lang/en/layout/setting.ts
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
export default {
|
||||||
|
// content mode
|
||||||
|
contentModeFull: 'Full',
|
||||||
|
contentModeFixed: 'Fixed width',
|
||||||
|
// topMenu align
|
||||||
|
topMenuAlignLeft: 'Left',
|
||||||
|
topMenuAlignRight: 'Center',
|
||||||
|
topMenuAlignCenter: 'Right',
|
||||||
|
// menu trigger
|
||||||
|
menuTriggerNone: 'Not Show',
|
||||||
|
menuTriggerBottom: 'Bottom',
|
||||||
|
menuTriggerTop: 'Top',
|
||||||
|
// menu type
|
||||||
|
menuTypeSidebar: 'Left menu mode',
|
||||||
|
menuTypeMix: 'Mixed mode',
|
||||||
|
menuTypeTopMenu: 'Top menu mode',
|
||||||
|
|
||||||
|
on: 'On',
|
||||||
|
off: 'Off',
|
||||||
|
minute: 'Minute',
|
||||||
|
|
||||||
|
operatingTitle: 'Successful!',
|
||||||
|
operatingContent:
|
||||||
|
'The copy is successful, please go to src/settings/projectSetting.ts to modify the configuration!',
|
||||||
|
resetSuccess: 'Successfully reset!',
|
||||||
|
|
||||||
|
copyBtn: 'Copy',
|
||||||
|
resetBtn: 'Reset',
|
||||||
|
clearBtn: 'Clear cache and to the login page',
|
||||||
|
|
||||||
|
drawerTitle: 'Configuration',
|
||||||
|
|
||||||
|
navMode: 'Navigation mode',
|
||||||
|
interfaceFunction: 'Interface function',
|
||||||
|
interfaceDisplay: 'Interface display',
|
||||||
|
animation: 'Animation',
|
||||||
|
splitMenu: 'Split menu',
|
||||||
|
|
||||||
|
headerTheme: 'Header theme',
|
||||||
|
sidebarTheme: 'Menu theme',
|
||||||
|
|
||||||
|
menuDrag: 'Drag Sidebar',
|
||||||
|
menuSearch: 'Sidebar search',
|
||||||
|
menuAccordion: 'Sidebar accordion',
|
||||||
|
menuCollapse: 'Collapse menu',
|
||||||
|
collapseMenuDisplayName: 'Collapse menu display name',
|
||||||
|
topMenuLayout: 'Top menu layout',
|
||||||
|
menuCollapseButton: 'Menu collapse button',
|
||||||
|
contentMode: 'Content area width',
|
||||||
|
expandedMenuWidth: 'Expanded menu width',
|
||||||
|
|
||||||
|
breadcrumb: 'Breadcrumbs',
|
||||||
|
breadcrumbIcon: 'Breadcrumbs Icon',
|
||||||
|
tabs: 'Tabs',
|
||||||
|
tabsQuickBtn: 'Tabs quick button',
|
||||||
|
sidebar: 'Sidebar',
|
||||||
|
header: 'Header',
|
||||||
|
footer: 'Footer',
|
||||||
|
fullContent: 'Full content',
|
||||||
|
grayMode: 'Gray mode',
|
||||||
|
colorWeak: 'Color Weak Mode',
|
||||||
|
|
||||||
|
progress: 'Progress',
|
||||||
|
switchLoading: 'Switch Loading',
|
||||||
|
switchAnimation: 'Switch animation',
|
||||||
|
animationType: 'Animation type',
|
||||||
|
|
||||||
|
autoScreenLock: 'Auto screen lock',
|
||||||
|
notAutoScreenLock: 'Not auto lock',
|
||||||
|
|
||||||
|
fixedHeader: 'Fixed header',
|
||||||
|
fixedSideBar: 'Fixed Sidebar',
|
||||||
|
};
|
4
src/locales/lang/zh_CN/layout/footer.ts
Normal file
4
src/locales/lang/zh_CN/layout/footer.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export default {
|
||||||
|
onlinePreview: '在线预览',
|
||||||
|
onlineDocument: '在线文档',
|
||||||
|
};
|
19
src/locales/lang/zh_CN/layout/header.ts
Normal file
19
src/locales/lang/zh_CN/layout/header.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
export default {
|
||||||
|
// user dropdown
|
||||||
|
dropdownItemDoc: '文档',
|
||||||
|
dropdownItemLoginOut: '退出系统',
|
||||||
|
|
||||||
|
// tooltip
|
||||||
|
tooltipErrorLog: '错误日志',
|
||||||
|
tooltipLock: '锁定屏幕',
|
||||||
|
tooltipNotify: '消息通知',
|
||||||
|
tooltipRedo: '刷新',
|
||||||
|
tooltipEntryFull: '全屏',
|
||||||
|
tooltipExitFull: '退出全屏',
|
||||||
|
|
||||||
|
// lock
|
||||||
|
lockScreenPassword: '锁屏密码',
|
||||||
|
lockScreen: '锁定屏幕',
|
||||||
|
lockScreenBtn: '锁定',
|
||||||
|
notLockScreenPassword: '不设置密码锁屏',
|
||||||
|
};
|
10
src/locales/lang/zh_CN/layout/multipleTab.ts
Normal file
10
src/locales/lang/zh_CN/layout/multipleTab.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
export default {
|
||||||
|
redo: '刷新',
|
||||||
|
close: '关闭',
|
||||||
|
closeLeft: '关闭左侧',
|
||||||
|
closeRight: '关闭右侧',
|
||||||
|
closeOther: '关闭其他',
|
||||||
|
closeAll: '关闭全部',
|
||||||
|
putAway: '收起',
|
||||||
|
unfold: '展开',
|
||||||
|
};
|
72
src/locales/lang/zh_CN/layout/setting.ts
Normal file
72
src/locales/lang/zh_CN/layout/setting.ts
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
export default {
|
||||||
|
// content mode
|
||||||
|
contentModeFull: '流式',
|
||||||
|
contentModeFixed: '定宽',
|
||||||
|
// topMenu align
|
||||||
|
topMenuAlignLeft: '居左',
|
||||||
|
topMenuAlignRight: '居中',
|
||||||
|
topMenuAlignCenter: '居右',
|
||||||
|
// menu trigger
|
||||||
|
menuTriggerNone: '不显示',
|
||||||
|
menuTriggerBottom: '底部',
|
||||||
|
menuTriggerTop: '顶部',
|
||||||
|
// menu type
|
||||||
|
menuTypeSidebar: '左侧菜单模式',
|
||||||
|
menuTypeMix: '混合模式',
|
||||||
|
menuTypeTopMenu: '顶部菜单模式',
|
||||||
|
|
||||||
|
on: '开',
|
||||||
|
off: '关',
|
||||||
|
minute: '分钟',
|
||||||
|
|
||||||
|
operatingTitle: '操作成功',
|
||||||
|
operatingContent: '复制成功,请到 src/settings/projectSetting.ts 中修改配置!',
|
||||||
|
resetSuccess: '重置成功!',
|
||||||
|
|
||||||
|
copyBtn: '拷贝',
|
||||||
|
resetBtn: '重置',
|
||||||
|
clearBtn: '清空缓存并返回登录页',
|
||||||
|
|
||||||
|
drawerTitle: '项目配置',
|
||||||
|
|
||||||
|
navMode: '导航栏模式',
|
||||||
|
interfaceFunction: '界面功能',
|
||||||
|
interfaceDisplay: '界面显示',
|
||||||
|
animation: '动画',
|
||||||
|
splitMenu: '分割菜单',
|
||||||
|
|
||||||
|
headerTheme: '顶栏主题',
|
||||||
|
sidebarTheme: '菜单主题',
|
||||||
|
|
||||||
|
menuDrag: '侧边菜单拖拽',
|
||||||
|
menuSearch: '侧边菜单搜索',
|
||||||
|
menuAccordion: '侧边菜单手风琴模式',
|
||||||
|
menuCollapse: '折叠菜单',
|
||||||
|
collapseMenuDisplayName: '折叠菜单显示名称',
|
||||||
|
topMenuLayout: '顶部菜单布局',
|
||||||
|
menuCollapseButton: '菜单折叠按钮',
|
||||||
|
contentMode: '内容区域宽度',
|
||||||
|
expandedMenuWidth: '菜单展开宽度',
|
||||||
|
|
||||||
|
breadcrumb: '面包屑',
|
||||||
|
breadcrumbIcon: '面包屑图标',
|
||||||
|
tabs: '标签页',
|
||||||
|
tabsQuickBtn: '标签页快捷按钮',
|
||||||
|
sidebar: '左侧菜单',
|
||||||
|
header: '顶栏',
|
||||||
|
footer: '页脚',
|
||||||
|
fullContent: '全屏内容',
|
||||||
|
grayMode: '灰色模式',
|
||||||
|
colorWeak: '色弱模式',
|
||||||
|
|
||||||
|
progress: '顶部进度条',
|
||||||
|
switchLoading: '切换loading',
|
||||||
|
switchAnimation: '切换动画',
|
||||||
|
animationType: '动画类型',
|
||||||
|
|
||||||
|
autoScreenLock: '自动锁屏',
|
||||||
|
notAutoScreenLock: '不自动锁屏',
|
||||||
|
|
||||||
|
fixedHeader: '固定header',
|
||||||
|
fixedSideBar: '固定Sidebar',
|
||||||
|
};
|
@@ -41,6 +41,7 @@ const setting: ProjectConfig = {
|
|||||||
|
|
||||||
// locale setting
|
// locale setting
|
||||||
locale: {
|
locale: {
|
||||||
|
show: true,
|
||||||
// Locale
|
// Locale
|
||||||
lang: 'zh_CN',
|
lang: 'zh_CN',
|
||||||
// Default locale
|
// Default locale
|
||||||
|
1
src/types/config.d.ts
vendored
1
src/types/config.d.ts
vendored
@@ -51,6 +51,7 @@ export interface HeaderSetting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface LocaleSetting {
|
export interface LocaleSetting {
|
||||||
|
show: boolean;
|
||||||
// Current language
|
// Current language
|
||||||
lang: LocaleType;
|
lang: LocaleType;
|
||||||
// default language
|
// default language
|
||||||
|
@@ -1,15 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<BasicModal :width="800" :title="t('sys.errorLog.tableActionDesc')" v-bind="$attrs">
|
<BasicModal :width="800" :title="t('tableActionDesc')" v-bind="$attrs">
|
||||||
<Description :data="info" @register="register" />
|
<Description :data="info" @register="register" />
|
||||||
</BasicModal>
|
</BasicModal>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, PropType } from 'vue';
|
import { defineComponent, PropType } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
|
|
||||||
import { BasicModal } from '/@/components/Modal/index';
|
import { BasicModal } from '/@/components/Modal/index';
|
||||||
import { ErrorInfo } from '/@/store/modules/error';
|
import { ErrorInfo } from '/@/store/modules/error';
|
||||||
import { Description, useDescription } from '/@/components/Description/index';
|
import { Description, useDescription } from '/@/components/Description/index';
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
|
||||||
import { getDescSchema } from './data';
|
import { getDescSchema } from './data';
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n('sys.errorLog');
|
||||||
const [register] = useDescription({
|
const [register] = useDescription({
|
||||||
column: 2,
|
column: 2,
|
||||||
schema: getDescSchema(),
|
schema: getDescSchema(),
|
||||||
|
@@ -1,16 +1,15 @@
|
|||||||
import { Tag } from 'ant-design-vue';
|
import { Tag } from 'ant-design-vue';
|
||||||
import { BasicColumn } from '/@/components/Table/index';
|
import { BasicColumn } from '/@/components/Table/index';
|
||||||
import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
|
import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
|
||||||
import { useExternalI18n } from '/@/hooks/web/useLocale';
|
const { t } = useI18n('sys.errorLog');
|
||||||
|
|
||||||
const { t } = useExternalI18n();
|
|
||||||
|
|
||||||
export function getColumns(): BasicColumn[] {
|
export function getColumns(): BasicColumn[] {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
dataIndex: 'type',
|
dataIndex: 'type',
|
||||||
title: t('sys.errorLog.tableColumnType'),
|
title: t('tableColumnType'),
|
||||||
width: 80,
|
width: 80,
|
||||||
customRender: ({ text }) => {
|
customRender: ({ text }) => {
|
||||||
const color =
|
const color =
|
||||||
@@ -33,12 +32,12 @@ export function getColumns(): BasicColumn[] {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'time',
|
dataIndex: 'time',
|
||||||
title: t('sys.errorLog.tableColumnDate'),
|
title: t('tableColumnDate'),
|
||||||
width: 160,
|
width: 160,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'file',
|
dataIndex: 'file',
|
||||||
title: t('sys.errorLog.tableColumnFile'),
|
title: t('tableColumnFile'),
|
||||||
width: 200,
|
width: 200,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -48,12 +47,12 @@ export function getColumns(): BasicColumn[] {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'message',
|
dataIndex: 'message',
|
||||||
title: t('sys.errorLog.tableColumnMsg'),
|
title: t('tableColumnMsg'),
|
||||||
width: 300,
|
width: 300,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'stack',
|
dataIndex: 'stack',
|
||||||
title: t('sys.errorLog.tableColumnStackMsg'),
|
title: t('tableColumnStackMsg'),
|
||||||
width: 300,
|
width: 300,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
import { useModal } from '/@/components/Modal/index';
|
import { useModal } from '/@/components/Modal/index';
|
||||||
import { useMessage } from '/@/hooks/web/useMessage';
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
|
||||||
import { errorStore, ErrorInfo } from '/@/store/modules/error';
|
import { errorStore, ErrorInfo } from '/@/store/modules/error';
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
const rowInfoRef = ref<ErrorInfo>();
|
const rowInfoRef = ref<ErrorInfo>();
|
||||||
const imgListRef = ref<string[]>([]);
|
const imgListRef = ref<string[]>([]);
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n('sys.errorLog');
|
||||||
|
|
||||||
const [register, { setTableData }] = useTable({
|
const [register, { setTableData }] = useTable({
|
||||||
title: t('sys.errorLog.tableTitle'),
|
title: t('sys.errorLog.tableTitle'),
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
);
|
);
|
||||||
const { createMessage } = useMessage();
|
const { createMessage } = useMessage();
|
||||||
if (isDevMode()) {
|
if (isDevMode()) {
|
||||||
createMessage.info(t('sys.errorLog.enableMessage'));
|
createMessage.info(t('enableMessage'));
|
||||||
}
|
}
|
||||||
// 查看详情
|
// 查看详情
|
||||||
function handleDetail(row: ErrorInfo) {
|
function handleDetail(row: ErrorInfo) {
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
import './exception.less';
|
||||||
|
|
||||||
import type { PropType } from 'vue';
|
import type { PropType } from 'vue';
|
||||||
|
|
||||||
import { Result, Button } from 'ant-design-vue';
|
import { Result, Button } from 'ant-design-vue';
|
||||||
@@ -12,9 +14,8 @@ import { useRoute } from 'vue-router';
|
|||||||
|
|
||||||
import { useGo, useRedo } from '/@/hooks/web/usePage';
|
import { useGo, useRedo } from '/@/hooks/web/usePage';
|
||||||
import { PageEnum } from '/@/enums/pageEnum';
|
import { PageEnum } from '/@/enums/pageEnum';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
|
||||||
import './exception.less';
|
|
||||||
interface MapValue {
|
interface MapValue {
|
||||||
title: string;
|
title: string;
|
||||||
subTitle: string;
|
subTitle: string;
|
||||||
@@ -52,7 +53,7 @@ export default defineComponent({
|
|||||||
const { query } = useRoute();
|
const { query } = useRoute();
|
||||||
const go = useGo();
|
const go = useGo();
|
||||||
const redo = useRedo();
|
const redo = useRedo();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n('sys.exception');
|
||||||
|
|
||||||
const getStatus = computed(() => {
|
const getStatus = computed(() => {
|
||||||
const { status: routeStatus } = query;
|
const { status: routeStatus } = query;
|
||||||
@@ -66,13 +67,13 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const backLoginI18n = t('sys.exception.backLogin');
|
const backLoginI18n = t('backLogin');
|
||||||
const backHomeI18n = t('sys.exception.backHome');
|
const backHomeI18n = t('backHome');
|
||||||
|
|
||||||
unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_ACCESS, {
|
unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_ACCESS, {
|
||||||
title: '403',
|
title: '403',
|
||||||
status: `${ExceptionEnum.PAGE_NOT_ACCESS}`,
|
status: `${ExceptionEnum.PAGE_NOT_ACCESS}`,
|
||||||
subTitle: t('sys.exception.subTitle403'),
|
subTitle: t('subTitle403'),
|
||||||
btnText: props.full ? backLoginI18n : backHomeI18n,
|
btnText: props.full ? backLoginI18n : backHomeI18n,
|
||||||
handler: () => (props.full ? go(PageEnum.BASE_LOGIN) : go()),
|
handler: () => (props.full ? go(PageEnum.BASE_LOGIN) : go()),
|
||||||
});
|
});
|
||||||
@@ -80,7 +81,7 @@ export default defineComponent({
|
|||||||
unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_FOUND, {
|
unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_FOUND, {
|
||||||
title: '404',
|
title: '404',
|
||||||
status: `${ExceptionEnum.PAGE_NOT_FOUND}`,
|
status: `${ExceptionEnum.PAGE_NOT_FOUND}`,
|
||||||
subTitle: t('sys.exception.subTitle404'),
|
subTitle: t('subTitle404'),
|
||||||
btnText: props.full ? backLoginI18n : backHomeI18n,
|
btnText: props.full ? backLoginI18n : backHomeI18n,
|
||||||
handler: () => (props.full ? go(PageEnum.BASE_LOGIN) : go()),
|
handler: () => (props.full ? go(PageEnum.BASE_LOGIN) : go()),
|
||||||
});
|
});
|
||||||
@@ -88,22 +89,22 @@ export default defineComponent({
|
|||||||
unref(statusMapRef).set(ExceptionEnum.ERROR, {
|
unref(statusMapRef).set(ExceptionEnum.ERROR, {
|
||||||
title: '500',
|
title: '500',
|
||||||
status: `${ExceptionEnum.ERROR}`,
|
status: `${ExceptionEnum.ERROR}`,
|
||||||
subTitle: t('sys.exception.subTitle500'),
|
subTitle: t('subTitle500'),
|
||||||
btnText: backHomeI18n,
|
btnText: backHomeI18n,
|
||||||
handler: () => go(),
|
handler: () => go(),
|
||||||
});
|
});
|
||||||
|
|
||||||
unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_DATA, {
|
unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_DATA, {
|
||||||
title: t('sys.exception.noDataTitle'),
|
title: t('noDataTitle'),
|
||||||
subTitle: '',
|
subTitle: '',
|
||||||
btnText: t('sys.exception.redo'),
|
btnText: t('redo'),
|
||||||
handler: () => redo(),
|
handler: () => redo(),
|
||||||
icon: notDataImg,
|
icon: notDataImg,
|
||||||
});
|
});
|
||||||
|
|
||||||
unref(statusMapRef).set(ExceptionEnum.NET_WORK_ERROR, {
|
unref(statusMapRef).set(ExceptionEnum.NET_WORK_ERROR, {
|
||||||
title: t('sys.exception.networkErrorTitle'),
|
title: t('networkErrorTitle'),
|
||||||
subTitle: t('sys.exception.networkErrorSubTitle'),
|
subTitle: t('networkErrorSubTitle'),
|
||||||
btnText: 'Refresh',
|
btnText: 'Refresh',
|
||||||
handler: () => redo(),
|
handler: () => redo(),
|
||||||
icon: netWorkImg,
|
icon: netWorkImg,
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
<p class="lock-page__header-name">{{ realName }}</p>
|
<p class="lock-page__header-name">{{ realName }}</p>
|
||||||
</div>
|
</div>
|
||||||
<BasicForm @register="register" v-if="!getIsNotPwd" />
|
<BasicForm @register="register" v-if="!getIsNotPwd" />
|
||||||
<Alert v-if="errMsgRef" type="error" :message="t('sys.lock.alert')" banner />
|
<Alert v-if="errMsgRef" type="error" :message="t('alert')" banner />
|
||||||
<div class="lock-page__footer">
|
<div class="lock-page__footer">
|
||||||
<a-button type="default" class="mt-2 mr-2" @click="goLogin" v-if="!getIsNotPwd">
|
<a-button type="default" class="mt-2 mr-2" @click="goLogin" v-if="!getIsNotPwd">
|
||||||
{{ t('sys.lock.backToLogin') }}
|
{{ t('sys.lock.backToLogin') }}
|
||||||
@@ -26,8 +26,7 @@
|
|||||||
|
|
||||||
import { userStore } from '/@/store/modules/user';
|
import { userStore } from '/@/store/modules/user';
|
||||||
import { appStore } from '/@/store/modules/app';
|
import { appStore } from '/@/store/modules/app';
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'LockPage',
|
name: 'LockPage',
|
||||||
@@ -37,7 +36,7 @@
|
|||||||
const loadingRef = ref(false);
|
const loadingRef = ref(false);
|
||||||
const errMsgRef = ref(false);
|
const errMsgRef = ref(false);
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n('sys.lock');
|
||||||
const [register, { validateFields }] = useForm({
|
const [register, { validateFields }] = useForm({
|
||||||
showActionButtonGroup: false,
|
showActionButtonGroup: false,
|
||||||
schemas: [
|
schemas: [
|
||||||
@@ -47,7 +46,7 @@
|
|||||||
component: 'InputPassword',
|
component: 'InputPassword',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
style: { width: '100%' },
|
style: { width: '100%' },
|
||||||
placeholder: t('sys.lock.placeholder'),
|
placeholder: t('placeholder'),
|
||||||
},
|
},
|
||||||
rules: [{ required: true }],
|
rules: [{ required: true }],
|
||||||
},
|
},
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
<div class="login-form-wrap">
|
<div class="login-form-wrap">
|
||||||
<div class="login-form mx-6">
|
<div class="login-form mx-6">
|
||||||
<div class="login-form__content px-2 py-10">
|
<div class="login-form__content px-2 py-10">
|
||||||
<AppLocalPicker class="login-form__locale" />
|
<AppLocalePicker v-if="showLocale" class="login-form__locale" />
|
||||||
<header>
|
<header>
|
||||||
<img :src="logo" class="mr-4" />
|
<img :src="logo" class="mr-4" />
|
||||||
<h1>{{ title }}</h1>
|
<h1>{{ title }}</h1>
|
||||||
@@ -64,23 +64,23 @@
|
|||||||
import { Checkbox } from 'ant-design-vue';
|
import { Checkbox } from 'ant-design-vue';
|
||||||
|
|
||||||
import Button from '/@/components/Button/index.vue';
|
import Button from '/@/components/Button/index.vue';
|
||||||
import { AppLocalPicker } from '/@/components/Application';
|
import { AppLocalePicker } from '/@/components/Application';
|
||||||
// import { BasicDragVerify, DragVerifyActionType } from '/@/components/Verify/index';
|
// import { BasicDragVerify, DragVerifyActionType } from '/@/components/Verify/index';
|
||||||
|
|
||||||
import { userStore } from '/@/store/modules/user';
|
import { userStore } from '/@/store/modules/user';
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
|
|
||||||
// import { appStore } from '/@/store/modules/app';
|
// import { appStore } from '/@/store/modules/app';
|
||||||
import { useMessage } from '/@/hooks/web/useMessage';
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
import { useGlobSetting } from '/@/hooks/setting';
|
import { useGlobSetting, useProjectSetting } from '/@/hooks/setting';
|
||||||
import logo from '/@/assets/images/logo.png';
|
import logo from '/@/assets/images/logo.png';
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
// BasicDragVerify,
|
// BasicDragVerify,
|
||||||
AButton: Button,
|
AButton: Button,
|
||||||
ACheckbox: Checkbox,
|
ACheckbox: Checkbox,
|
||||||
AppLocalPicker,
|
AppLocalePicker,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const formRef = ref<any>(null);
|
const formRef = ref<any>(null);
|
||||||
@@ -88,8 +88,9 @@
|
|||||||
// const verifyRef = ref<RefInstanceType<DragVerifyActionType>>(null);
|
// const verifyRef = ref<RefInstanceType<DragVerifyActionType>>(null);
|
||||||
|
|
||||||
const globSetting = useGlobSetting();
|
const globSetting = useGlobSetting();
|
||||||
|
const { locale } = useProjectSetting();
|
||||||
const { notification } = useMessage();
|
const { notification } = useMessage();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n('sys.login');
|
||||||
|
|
||||||
// const openLoginVerifyRef = computed(() => appStore.getProjectConfig.openLoginVerify);
|
// const openLoginVerifyRef = computed(() => appStore.getProjectConfig.openLoginVerify);
|
||||||
|
|
||||||
@@ -103,10 +104,8 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
const formRules = reactive({
|
const formRules = reactive({
|
||||||
account: [{ required: true, message: t('sys.login.accountPlaceholder'), trigger: 'blur' }],
|
account: [{ required: true, message: t('accountPlaceholder'), trigger: 'blur' }],
|
||||||
password: [
|
password: [{ required: true, message: t('passwordPlaceholder'), trigger: 'blur' }],
|
||||||
{ required: true, message: t('sys.login.passwordPlaceholder'), trigger: 'blur' },
|
|
||||||
],
|
|
||||||
// verify: unref(openLoginVerifyRef) ? [{ required: true, message: '请通过验证码校验' }] : [],
|
// verify: unref(openLoginVerifyRef) ? [{ required: true, message: '请通过验证码校验' }] : [],
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -131,8 +130,8 @@
|
|||||||
);
|
);
|
||||||
if (userInfo) {
|
if (userInfo) {
|
||||||
notification.success({
|
notification.success({
|
||||||
message: t('sys.login.loginSuccessTitle'),
|
message: t('loginSuccessTitle'),
|
||||||
description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realName}`,
|
description: `${t('loginSuccessDesc')}: ${userInfo.realName}`,
|
||||||
duration: 3,
|
duration: 3,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -154,6 +153,7 @@
|
|||||||
title: globSetting && globSetting.title,
|
title: globSetting && globSetting.title,
|
||||||
logo,
|
logo,
|
||||||
t,
|
t,
|
||||||
|
showLocale: locale.show,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user