V001
This commit is contained in:
1 parent
d5d4a6f3bf
commit
fb1a79a3e9
27 files changed
+708
-75
No files matched your search
@@ -1,2 +1,51 @@
|
||||
<template>error 401</template>
|
||||
<script setup lang="ts"></script>
|
||||
<template>
|
||||
<ErrorPanel code="401" badge="UNAUTHORIZED · 未认证" tone="blue" title="需要登录后才能访问"
|
||||
description="你的登录状态已经失效,或者还没有登录。重新登录一次即可继续。" :reasons="reasons" :from="fromPath" hint="提示:登录后在其它设备退出登录,也会让当前设备失效。">
|
||||
<template #icon>
|
||||
<LockOutlined />
|
||||
</template>
|
||||
<template #actions>
|
||||
<a-button type="primary" size="large" block @click="goLogin">
|
||||
<template #icon><LoginOutlined /></template>
|
||||
去登录
|
||||
</a-button>
|
||||
<a-button size="large" block @click="goBack">
|
||||
<template #icon><ArrowLeftOutlined /></template>
|
||||
返回上一页
|
||||
</a-button>
|
||||
</template>
|
||||
</ErrorPanel>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { ArrowLeftOutlined, LockOutlined, LoginOutlined } from "@ant-design/icons-vue";
|
||||
import ErrorPanel from "@/components/basic/ErrorPanel.vue";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
/** 出错的地址:由守卫/拦截器跳转时用 ?from= 带过来 */
|
||||
const fromPath = computed(() =>
|
||||
typeof route.query.from === "string" ? route.query.from : ""
|
||||
);
|
||||
|
||||
const reasons = [
|
||||
"登录已过期:长时间没有操作,或访问令牌到期",
|
||||
"在其它设备或标签页退出了登录,当前设备随之失效",
|
||||
"浏览器清理了本地数据(无痕模式、清理缓存、换浏览器)",
|
||||
"管理员刚修改过你的账号信息(如密码、手机号)",
|
||||
];
|
||||
|
||||
/** 去登录:带上原地址,登录成功后能直接回到这里 */
|
||||
const goLogin = () => {
|
||||
const redirect = fromPath.value || "/dashboard";
|
||||
router.replace({ path: "/login", query: { redirect } });
|
||||
};
|
||||
|
||||
const goBack = () => {
|
||||
if (window.history.length > 1) router.back();
|
||||
else router.replace("/login");
|
||||
};
|
||||
</script>
|
||||
@@ -1,2 +1,49 @@
|
||||
<template>error 403</template>
|
||||
<script setup lang="ts"> </script>
|
||||
<template>
|
||||
<ErrorPanel code="403" badge="FORBIDDEN · 无权限" tone="amber" title="你没有这个页面的访问权限"
|
||||
description="账号是正常的,但你所在的角色/权限组没有被授予这个功能。" :reasons="reasons" :from="fromPath" hint="提示:权限由管理员分配,变更后需要重新登录才会生效。">
|
||||
<template #icon>
|
||||
<SafetyCertificateOutlined />
|
||||
</template>
|
||||
<template #actions>
|
||||
<a-button type="primary" size="large" block @click="goRelogin">
|
||||
<template #icon><LoginOutlined /></template>
|
||||
重新登录
|
||||
</a-button>
|
||||
<a-button size="large" block @click="goHome">
|
||||
<template #icon><HomeOutlined /></template>
|
||||
返回首页
|
||||
</a-button>
|
||||
</template>
|
||||
</ErrorPanel>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { HomeOutlined, LoginOutlined, SafetyCertificateOutlined } from "@ant-design/icons-vue";
|
||||
import ErrorPanel from "@/components/basic/ErrorPanel.vue";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const fromPath = computed(() =>
|
||||
typeof route.query.from === "string" ? route.query.from : ""
|
||||
);
|
||||
|
||||
const reasons = [
|
||||
"当前账号所属的角色 / 权限组没有该功能的权限",
|
||||
"该功能还没在后台授权,虽然能看到入口但打不开",
|
||||
"权限刚被调整过,浏览器里还是旧的权限数据",
|
||||
"把别人的链接发给了你,而你的账号没有对应权限",
|
||||
];
|
||||
|
||||
/** 重新登录:拿一次最新权限(权限变更后必须重登才生效) */
|
||||
const goRelogin = () => {
|
||||
router.replace({ path: "/login", query: fromPath.value ? { redirect: fromPath.value } : undefined });
|
||||
};
|
||||
|
||||
/** 回首页:首页与菜单是匿名接口,即使没权限也能正常打开 */
|
||||
const goHome = () => {
|
||||
router.replace(router.hasRoute("dashboard") ? "/dashboard" : "/");
|
||||
};
|
||||
</script>
|
||||
@@ -1,2 +1,49 @@
|
||||
<template>error 404</template>
|
||||
<script setup lang="ts"> </script>
|
||||
<template>
|
||||
<ErrorPanel code="404" badge="NOT FOUND · 找不到页面" tone="violet" title="这个页面不存在"
|
||||
description="地址可能写错了,或者对应的页面已经不在系统里。" :reasons="reasons" :from="fromPath" hint="提示:没有权限的功能不会出现在菜单里,地址直接打开也会落到这里。">
|
||||
<template #icon>
|
||||
<CompassOutlined />
|
||||
</template>
|
||||
<template #actions>
|
||||
<a-button type="primary" size="large" block @click="goHome">
|
||||
<template #icon><HomeOutlined /></template>
|
||||
返回首页
|
||||
</a-button>
|
||||
<a-button size="large" block @click="goBack">
|
||||
<template #icon><ArrowLeftOutlined /></template>
|
||||
返回上一页
|
||||
</a-button>
|
||||
</template>
|
||||
</ErrorPanel>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { ArrowLeftOutlined, CompassOutlined, HomeOutlined } from "@ant-design/icons-vue";
|
||||
import ErrorPanel from "@/components/basic/ErrorPanel.vue";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
/** 出错的地址:路由兜底跳转时用 ?from= 带过来 */
|
||||
const fromPath = computed(() =>
|
||||
typeof route.query.from === "string" ? route.query.from : ""
|
||||
);
|
||||
|
||||
const reasons = [
|
||||
"地址拼错了,或从聊天/邮件里复制时被截断",
|
||||
"该功能没有在菜单里开放(系统里查不到这条路由)",
|
||||
"页面已下线或改名,收藏夹里还是旧地址",
|
||||
"服务器刚重启、菜单还没加载出来,刷新一次即可",
|
||||
];
|
||||
|
||||
const goHome = () => {
|
||||
router.replace(router.hasRoute("dashboard") ? "/dashboard" : "/");
|
||||
};
|
||||
|
||||
const goBack = () => {
|
||||
if (window.history.length > 1) router.back();
|
||||
else router.replace(router.hasRoute("dashboard") ? "/dashboard" : "/");
|
||||
};
|
||||
</script>
|
||||
@@ -75,7 +75,7 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, computed, watch } from 'vue'
|
||||
import { useRouter } from "vue-router";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { UserOutlined, LockOutlined } from "@ant-design/icons-vue";
|
||||
import authService from "@/service/security/authService";
|
||||
import { LoginData } from "@/data/auto/loginData";
|
||||
@@ -95,8 +95,15 @@ const { t } = i18n.global;
|
||||
//const props = defineProps(['id'])
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const userLoginProfile = useLoginProfileStore();
|
||||
|
||||
/** 登录成功后的落点:路由守卫拦截时会带上 ?redirect=,没有就回首页 */
|
||||
const afterLoginPath = (): string =>
|
||||
typeof route.query.redirect === "string" && route.query.redirect
|
||||
? route.query.redirect
|
||||
: "/dashboard";
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
LoginData: {
|
||||
@@ -149,7 +156,7 @@ const handleSubmit = async () => {
|
||||
|
||||
userLoginProfile.updateLoginProfile(profile);
|
||||
|
||||
router.push({ path: "/dashboard" });
|
||||
router.push(afterLoginPath());
|
||||
} catch (error) {
|
||||
} finally {
|
||||
state.loading = false;
|
||||
@@ -281,7 +288,7 @@ const onBiometricLogin = async () => {
|
||||
// same call LoginView makes after a successful password login.
|
||||
userLoginProfile.updateLoginProfile(profile);
|
||||
|
||||
router.push({ path: "/dashboard" });
|
||||
router.push(afterLoginPath());
|
||||
} catch (err: any) {
|
||||
// Best-effort error extraction — handles ALL of:
|
||||
// 1. Axios error: err.response.data is the server body (string or object)
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(FileSearchOutlined)"
|
||||
@click.prevent="onSearch">查询</a-button>
|
||||
<a-button :disabled="isEdit" :icon="h(ClearOutlined)" @click.prevent="onReset">重置</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(FileAddOutlined)" @click.prevent="onCreate">新增</a-button>
|
||||
<a-button type="primary" v-if="canCreate" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
@click.prevent="onCreate">新增</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-main ft-page" :class="{ 'ft-readonly': !isEdit }" :style="{ height: resultH }">
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
@click.prevent="onSearch">查询</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(ClearOutlined)"
|
||||
@click.prevent="onReset">重置</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
<a-button type="primary" v-if="canCreate" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
@click.prevent="onCreate">新增</a-button>
|
||||
</a-space>
|
||||
</a-col>
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
>
|
||||
<a-button
|
||||
type="primary"
|
||||
v-if="canCreate"
|
||||
:disabled="isEdit"
|
||||
:icon="h(FileAddOutlined)"
|
||||
@click.prevent="onCreate"
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
@click.prevent="onSearch">查询</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(ClearOutlined)"
|
||||
@click.prevent="onReset">重置</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
<a-button type="primary" v-if="canCreate" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
@click.prevent="onCreate">新增</a-button>
|
||||
</a-space>
|
||||
</a-col>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
@click.prevent="onSearch">查询</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(ClearOutlined)"
|
||||
@click.prevent="onReset">重置</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
<a-button type="primary" v-if="canCreate" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
@click.prevent="onCreate">新增</a-button>
|
||||
</a-space>
|
||||
</a-col>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
@click.prevent="onSearch">查询</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(ClearOutlined)"
|
||||
@click.prevent="onReset">重置</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
<a-button type="primary" v-if="canCreate" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
@click.prevent="onCreate">新增</a-button>
|
||||
</a-space>
|
||||
</a-col>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
@click.prevent="onSearch">查询</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(ClearOutlined)"
|
||||
@click.prevent="onReset">重置</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
<a-button type="primary" v-if="canCreate" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
@click.prevent="onCreate">新增</a-button>
|
||||
</a-space>
|
||||
</a-col>
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
@click.prevent="onSearch">查询</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(ClearOutlined)"
|
||||
@click.prevent="onReset">重置</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
<a-button type="primary" v-if="canCreate" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
@click.prevent="onCreate">新增</a-button>
|
||||
</a-space>
|
||||
</a-col>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
@click.prevent="onSearch">查询</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(ClearOutlined)"
|
||||
@click.prevent="onReset">重置</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
<a-button type="primary" v-if="canCreate" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
@click.prevent="onCreate">新增</a-button>
|
||||
</a-space>
|
||||
</a-col>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
@click.prevent="onSearch">查询</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(ClearOutlined)"
|
||||
@click.prevent="onReset">重置</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
<a-button type="primary" v-if="canCreate" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
@click.prevent="onCreate">新增</a-button>
|
||||
</a-space>
|
||||
</a-col>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
@click.prevent="onSearch">查询</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(ClearOutlined)"
|
||||
@click.prevent="onReset">重置</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
<a-button type="primary" v-if="canCreate" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
@click.prevent="onCreate">新增</a-button>
|
||||
</a-space>
|
||||
</a-col>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
@click.prevent="onSearch">查询</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(ClearOutlined)"
|
||||
@click.prevent="onReset">重置</a-button>
|
||||
<a-button type="primary" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
<a-button type="primary" v-if="canCreate" :disabled="isEdit" :icon="h(FileAddOutlined)"
|
||||
@click.prevent="onCreate">新增</a-button>
|
||||
</a-space>
|
||||
</a-col>
|
||||
|
||||
Reference in new issue
Block a user