wip: multi-language support

This commit is contained in:
vben
2020-11-23 00:35:15 +08:00
parent b49950a390
commit 737b1b190c
59 changed files with 512 additions and 272 deletions

View File

@@ -1,13 +1,16 @@
<template>
<BasicModal :width="800" title="错误详情" v-bind="$attrs">
<BasicModal :width="800" :title="t('sys.errorLog.tableActionDesc')" v-bind="$attrs">
<Description :data="info" @register="register" />
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue';
import { useI18n } from 'vue-i18n';
import { BasicModal } from '/@/components/Modal/index';
import { ErrorInfo } from '/@/store/modules/error';
import { Description, useDescription } from '/@/components/Description/index';
import { getDescSchema } from './data';
export default defineComponent({
@@ -20,12 +23,15 @@
},
},
setup() {
const { t } = useI18n();
const [register] = useDescription({
column: 2,
schema: getDescSchema(),
});
return {
register,
useI18n,
t,
};
},
});

View File

@@ -2,11 +2,15 @@ import { Tag } from 'ant-design-vue';
import { BasicColumn } from '/@/components/Table/index';
import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
import { useExternalI18n } from '/@/hooks/web/useLocale';
const { t } = useExternalI18n();
export function getColumns(): BasicColumn[] {
return [
{
dataIndex: 'type',
title: '类型',
title: t('sys.errorLog.tableColumnType'),
width: 80,
customRender: ({ text }) => {
const color =
@@ -24,17 +28,17 @@ export function getColumns(): BasicColumn[] {
},
{
dataIndex: 'url',
title: '地址',
title: 'URL',
width: 200,
},
{
dataIndex: 'time',
title: '时间',
title: t('sys.errorLog.tableColumnDate'),
width: 160,
},
{
dataIndex: 'file',
title: '文件',
title: t('sys.errorLog.tableColumnFile'),
width: 200,
},
{
@@ -44,12 +48,12 @@ export function getColumns(): BasicColumn[] {
},
{
dataIndex: 'message',
title: '错误信息',
title: t('sys.errorLog.tableColumnMsg'),
width: 300,
},
{
dataIndex: 'stack',
title: 'stack信息',
title: t('sys.errorLog.tableColumnStackMsg'),
width: 300,
},
];

View File

@@ -6,12 +6,22 @@
<DetailModal :info="rowInfoRef" @register="registerModal" />
<BasicTable @register="register" class="error-handle-table">
<template #toolbar>
<a-button @click="fireVueError" type="primary"> 点击触发vue错误 </a-button>
<a-button @click="fireResourceError" type="primary"> 点击触发resource错误 </a-button>
<a-button @click="fireAjaxError" type="primary"> 点击触发ajax错误 </a-button>
<a-button @click="fireVueError" type="primary">
{{ t('sys.errorLog.fireVueError') }}
</a-button>
<a-button @click="fireResourceError" type="primary">
{{ t('sys.errorLog.fireResourceError') }}
</a-button>
<a-button @click="fireAjaxError" type="primary">
{{ t('sys.errorLog.fireAjaxError') }}
</a-button>
</template>
<template #action="{ record }">
<TableAction :actions="[{ label: '详情', onClick: handleDetail.bind(null, record) }]" />
<TableAction
:actions="[
{ label: t('sys.errorLog.tableActionDesc'), onClick: handleDetail.bind(null, record) },
]"
/>
</template>
</BasicTable>
</div>
@@ -21,10 +31,11 @@
import { defineComponent, watch, ref, nextTick } from 'vue';
import DetailModal from './DetailModal.vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table/index';
import { useModal } from '/@/components/Modal/index';
import { useMessage } from '/@/hooks/web/useMessage';
import { BasicTable, useTable, TableAction } from '/@/components/Table/index';
import { useI18n } from 'vue-i18n';
import { errorStore, ErrorInfo } from '/@/store/modules/error';
@@ -42,12 +53,14 @@
const rowInfoRef = ref<ErrorInfo>();
const imgListRef = ref<string[]>([]);
const { t } = useI18n();
const [register, { setTableData }] = useTable({
title: '错误日志列表',
title: t('sys.errorLog.tableTitle'),
columns: getColumns(),
actionColumn: {
width: 80,
title: '操作',
title: 'Action',
dataIndex: 'action',
slots: { customRender: 'action' },
},
@@ -67,7 +80,7 @@
);
const { createMessage } = useMessage();
if (isDevMode()) {
createMessage.info('只在`/src/settings/projectSetting.ts` 内的useErrorHandle=true时生效');
createMessage.info(t('sys.errorLog.enableMessage'));
}
// 查看详情
function handleDetail(row: ErrorInfo) {
@@ -96,6 +109,7 @@
fireAjaxError,
imgListRef,
rowInfoRef,
t,
};
},
});

View File

@@ -12,6 +12,7 @@ import { useRoute } from 'vue-router';
import { useGo, useRedo } from '/@/hooks/web/usePage';
import { PageEnum } from '/@/enums/pageEnum';
import { useI18n } from 'vue-i18n';
import './exception.less';
interface MapValue {
@@ -47,9 +48,12 @@ export default defineComponent({
},
setup(props) {
const statusMapRef = ref(new Map<string | number, MapValue>());
const { query } = useRoute();
const go = useGo();
const redo = useRedo();
const { t } = useI18n();
const getStatus = computed(() => {
const { status: routeStatus } = query;
const { status } = props;
@@ -62,41 +66,44 @@ export default defineComponent({
}
);
const backLoginI18n = t('sys.exception.backLogin');
const backHomeI18n = t('sys.exception.backHome');
unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_ACCESS, {
title: '403',
status: `${ExceptionEnum.PAGE_NOT_ACCESS}`,
subTitle: `Sorry, you don't have access to this page.!`,
btnText: props.full ? 'Back Login' : 'Back Home',
subTitle: t('sys.exception.subTitle403'),
btnText: props.full ? backLoginI18n : backHomeI18n,
handler: () => (props.full ? go(PageEnum.BASE_LOGIN) : go()),
});
unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_FOUND, {
title: '404',
status: `${ExceptionEnum.PAGE_NOT_FOUND}`,
subTitle: `Sorry, the page you visited does not exist.`,
btnText: props.full ? 'Back Login' : 'Back Home',
subTitle: t('sys.exception.subTitle404'),
btnText: props.full ? backLoginI18n : backHomeI18n,
handler: () => (props.full ? go(PageEnum.BASE_LOGIN) : go()),
});
unref(statusMapRef).set(ExceptionEnum.ERROR, {
title: '500',
status: `${ExceptionEnum.ERROR}`,
subTitle: `Sorry, the server is reporting an error.`,
btnText: 'Back Home',
subTitle: t('sys.exception.subTitle500'),
btnText: backHomeI18n,
handler: () => go(),
});
unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_DATA, {
title: 'No data on the current page',
title: t('sys.exception.noDataTitle'),
subTitle: '',
btnText: 'Refresh',
btnText: t('sys.exception.redo'),
handler: () => redo(),
icon: notDataImg,
});
unref(statusMapRef).set(ExceptionEnum.NET_WORK_ERROR, {
title: 'Network Error',
subTitle: 'SorryYour network connection has been disconnected, please check your network!',
title: t('sys.exception.networkErrorTitle'),
subTitle: t('sys.exception.networkErrorSubTitle'),
btnText: 'Refresh',
handler: () => redo(),
icon: netWorkImg,

View File

@@ -6,36 +6,38 @@
<p class="lock-page__header-name">{{ realName }}</p>
</div>
<BasicForm @register="register" v-if="!getIsNotPwd" />
<Alert v-if="errMsgRef" type="error" message="锁屏密码错误" banner />
<Alert v-if="errMsgRef" type="error" :message="t('sys.lock.alert')" banner />
<div class="lock-page__footer">
<a-button type="default" class="mt-2 mr-2" @click="goLogin" v-if="!getIsNotPwd">
返回登录
{{ t('sys.lock.backToLogin') }}
</a-button>
<a-button type="primary" class="mt-2" @click="unLock(!getIsNotPwd)" :loading="loadingRef">
进入系统
{{ t('sys.lock.entry') }}
</a-button>
</div>
</div>
</div>
</template>
<script lang="ts">
// 组件相关
import { defineComponent, ref, computed } from 'vue';
import { Alert } from 'ant-design-vue';
// hook
import { BasicForm, useForm } from '/@/components/Form';
import { userStore } from '/@/store/modules/user';
import { appStore } from '/@/store/modules/app';
import { useI18n } from 'vue-i18n';
export default defineComponent({
name: 'LockPage',
components: { Alert, BasicForm },
setup() {
// 获取配置文件
// 样式前缀
const loadingRef = ref(false);
const errMsgRef = ref(false);
const { t } = useI18n();
const [register, { validateFields }] = useForm({
showActionButtonGroup: false,
schemas: [
@@ -45,7 +47,7 @@
component: 'InputPassword',
componentProps: {
style: { width: '100%' },
placeholder: '请输入锁屏密码或者用户密码',
placeholder: t('sys.lock.placeholder'),
},
rules: [{ required: true }],
},
@@ -55,6 +57,14 @@
const { realName } = userStore.getUserInfoState || {};
return realName;
});
const getIsNotPwd = computed(() => {
if (!appStore.getLockInfo) {
return true;
}
return appStore.getLockInfo.pwd === undefined;
});
/**
* @description: unLock
*/
@@ -76,17 +86,12 @@
loadingRef.value = false;
}
}
function goLogin() {
userStore.loginOut(true);
appStore.resetLockInfo();
}
const getIsNotPwd = computed(() => {
if (!appStore.getLockInfo) {
return true;
}
return appStore.getLockInfo.pwd === undefined;
});
// 账号密码登录
return {
register,
getIsNotPwd,
@@ -95,6 +100,7 @@
unLock,
errMsgRef,
loadingRef,
t,
};
},
});

View File

@@ -4,6 +4,7 @@
<div class="login-form-wrap">
<div class="login-form mx-6">
<div class="login-form__content px-2 py-10">
<AppLocalPicker class="login-form__locale" />
<header>
<img :src="logo" class="mr-4" />
<h1>{{ title }}</h1>
@@ -29,13 +30,15 @@
<a-col :span="12">
<a-form-item>
<!-- No logic, you need to deal with it yourself -->
<a-checkbox v-model:checked="autoLogin" size="small">自动登录</a-checkbox>
<a-checkbox v-model:checked="autoLogin" size="small">{{
t('sys.login.autoLogin')
}}</a-checkbox>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item :style="{ 'text-align': 'right' }">
<!-- No logic, you need to deal with it yourself -->
<a-button type="link" size="small">忘记密码</a-button>
<a-button type="link" size="small">{{ t('sys.login.forgetPassword') }}</a-button>
</a-form-item>
</a-col>
</a-row>
@@ -47,7 +50,7 @@
:block="true"
@click="login"
:loading="formState.loading"
>{{ t('system.login.button') }}</a-button
>{{ t('sys.login.loginButton') }}</a-button
>
</a-form-item>
</a-form>
@@ -61,6 +64,7 @@
import { Checkbox } from 'ant-design-vue';
import Button from '/@/components/Button/index.vue';
import { AppLocalPicker } from '/@/components/Application';
// import { BasicDragVerify, DragVerifyActionType } from '/@/components/Verify/index';
import { userStore } from '/@/store/modules/user';
@@ -68,7 +72,7 @@
// import { appStore } from '/@/store/modules/app';
import { useMessage } from '/@/hooks/web/useMessage';
import { useSetting } from '/@/hooks/core/useSetting';
import { useGlobSetting } from '/@/settings/use';
import logo from '/@/assets/images/logo.png';
export default defineComponent({
@@ -76,14 +80,16 @@
// BasicDragVerify,
AButton: Button,
ACheckbox: Checkbox,
AppLocalPicker,
},
setup() {
const formRef = ref<any>(null);
const autoLoginRef = ref(false);
// const verifyRef = ref<RefInstanceType<DragVerifyActionType>>(null);
const { globSetting } = useSetting();
const globSetting = useGlobSetting();
const { notification } = useMessage();
const { t } = useI18n();
// const openLoginVerifyRef = computed(() => appStore.getProjectConfig.openLoginVerify);
@@ -97,8 +103,10 @@
});
const formRules = reactive({
account: [{ required: true, message: '请输入账号', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
account: [{ required: true, message: t('sys.login.accountPlaceholder'), trigger: 'blur' }],
password: [
{ required: true, message: t('sys.login.passwordPlaceholder'), trigger: 'blur' },
],
// verify: unref(openLoginVerifyRef) ? [{ required: true, message: '请通过验证码校验' }] : [],
});
@@ -123,8 +131,8 @@
);
if (userInfo) {
notification.success({
message: '登录成功',
description: `欢迎回来: ${userInfo.realName}`,
message: t('sys.login.loginSuccessTitle'),
description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realName}`,
duration: 3,
});
}
@@ -134,7 +142,6 @@
formState.loading = false;
}
}
const { t } = useI18n();
return {
formRef,
// verifyRef,
@@ -195,7 +202,14 @@
.respond-to(xlarge, { width: 540px; right:0});
}
&__locale {
position: absolute;
top: 10px;
right: 10px;
}
&__content {
position: relative;
width: 100%;
height: 100%;
border: 1px solid #999;