新增 与后端对接

This commit is contained in:
小肥羊 2025-08-05 16:30:55 +08:00
parent 910a3a5837
commit ac2a6caa1e
21 changed files with 107 additions and 95 deletions

View File

@ -6,3 +6,5 @@ VITE_PUBLIC_PATH = /
# 开发环境路由历史模式Hash模式传"hash"、HTML5模式传"h5"、Hash模式带base参数传"hash,base参数"、HTML5模式带base参数传"h5,base参数"
VITE_ROUTER_HISTORY = "hash"
VITE_API_BASEURL = "http://localhost:5199/api"

View File

@ -11,7 +11,7 @@ import removeNoMatch from "vite-plugin-router-warn";
import { visualizer } from "rollup-plugin-visualizer";
import removeConsole from "vite-plugin-remove-console";
import { codeInspectorPlugin } from "code-inspector-plugin";
import { vitePluginFakeServer } from "vite-plugin-fake-server";
// import { vitePluginFakeServer } from "vite-plugin-fake-server";
export function getPluginsList(
VITE_CDN: boolean,
@ -41,12 +41,12 @@ export function getPluginsList(
*/
removeNoMatch(),
// mock支持
vitePluginFakeServer({
logger: false,
include: "mock",
infixName: false,
enableProd: true
}),
// vitePluginFakeServer({
// logger: false,
// include: "mock",
// infixName: false,
// enableProd: true
// }),
// svg组件化支持
svgLoader(),
// 自动按需加载图标

View File

@ -6,13 +6,13 @@ export default defineFakeRoute([
url: "/login",
method: "post",
response: ({ body }) => {
if (body.username === "admin") {
if (body.userName === "admin") {
return {
success: true,
data: {
avatar: "https://avatars.githubusercontent.com/u/44761321",
username: "admin",
nickname: "小铭",
userName: "admin",
nickName: "小铭",
// 一个用户可能有多个角色
roles: ["admin"],
// 按钮级别权限
@ -27,8 +27,8 @@ export default defineFakeRoute([
success: true,
data: {
avatar: "https://avatars.githubusercontent.com/u/52823142",
username: "common",
nickname: "小林",
userName: "common",
nickName: "小林",
roles: ["common"],
permissions: ["permission:btn:add", "permission:btn:edit"],
accessToken: "eyJhbGciOiJIUzUxMiJ9.common",

View File

@ -6,5 +6,5 @@ type Result = {
};
export const getAsyncRoutes = () => {
return http.request<Result>("get", "/get-async-routes");
return http.request<Result>("get", "/Menu/AdminMenu");
};

View File

@ -1,25 +1,23 @@
import { http } from "@/utils/http";
import type { Res } from "@/utils/http/types";
export type UserResult = {
success: boolean;
data: {
/** 头像 */
avatar: string;
/** 用户名 */
username: string;
/** 昵称 */
nickname: string;
/** 当前登录用户的角色 */
roles: Array<string>;
/** 按钮级别权限 */
permissions: Array<string>;
/** `token` */
accessToken: string;
/** 用于调用刷新`accessToken`的接口时所需的`token` */
refreshToken: string;
/** `accessToken`的过期时间(格式'xxxx/xx/xx xx:xx:xx' */
expires: Date;
};
/** 头像 */
avatar: string;
/** 用户名 */
userName: string;
/** 昵称 */
nickName: string;
/** 当前登录用户的角色 */
roles: Array<string>;
/** 按钮级别权限 */
permissions: Array<string>;
/** `token` */
accessToken: string;
/** 用于调用刷新`accessToken`的接口时所需的`token` */
refreshToken: string;
/** `accessToken`的过期时间(格式'xxxx/xx/xx xx:xx:xx' */
expires: Date;
};
export type RefreshTokenResult = {
@ -36,7 +34,7 @@ export type RefreshTokenResult = {
/** 登录 */
export const getLogin = (data?: object) => {
return http.request<UserResult>("post", "/login", { data });
return http.request<Res<UserResult>>("post", "/Admin/Login", { data });
};
/** 刷新`token` */

View File

@ -16,7 +16,7 @@ const {
logout,
onPanel,
pureApp,
username,
userName,
userAvatar,
avatarsStyle,
toggleSideBar
@ -50,7 +50,7 @@ const {
<el-dropdown trigger="click">
<span class="el-dropdown-link navbar-bg-hover select-none">
<img :src="userAvatar" :style="avatarsStyle" />
<p v-if="username" class="dark:text-white">{{ username }}</p>
<p v-if="userName" class="dark:text-white">{{ userName }}</p>
</span>
<template #dropdown>
<el-dropdown-menu class="logout">

View File

@ -26,7 +26,7 @@ const {
logout,
onPanel,
getLogo,
username,
userName,
userAvatar,
backTopMenu,
avatarsStyle
@ -81,7 +81,7 @@ onMounted(() => {
<el-dropdown trigger="click">
<span class="el-dropdown-link navbar-bg-hover">
<img :src="userAvatar" :style="avatarsStyle" />
<p v-if="username" class="dark:text-white">{{ username }}</p>
<p v-if="userName" class="dark:text-white">{{ userName }}</p>
</span>
<template #dropdown>
<el-dropdown-menu class="logout">

View File

@ -22,7 +22,7 @@ const {
logout,
onPanel,
resolvePath,
username,
userName,
userAvatar,
getDivStyle,
avatarsStyle
@ -101,7 +101,7 @@ watch(
<el-dropdown trigger="click">
<span class="el-dropdown-link navbar-bg-hover select-none">
<img :src="userAvatar" :style="avatarsStyle" />
<p v-if="username" class="dark:text-white">{{ username }}</p>
<p v-if="userName" class="dark:text-white">{{ userName }}</p>
</span>
<template #dropdown>
<el-dropdown-menu class="logout">

View File

@ -88,10 +88,13 @@ const expandCloseIcon = computed(() => {
const onlyOneChild: menuType = ref(null);
function hasOneShowingChild(children: menuType[] = [], parent: menuType) {
const showingChildren = children.filter((item: any) => {
onlyOneChild.value = item;
return true;
});
const showingChildren =
children == null
? []
: children.filter((item: any) => {
onlyOneChild.value = item;
return true;
});
if (showingChildren[0]?.meta?.showParent) {
return false;

View File

@ -45,14 +45,14 @@ export function useNav() {
});
/** 昵称(如果昵称为空则显示用户名) */
const username = computed(() => {
return isAllEmpty(useUserStoreHook()?.nickname)
? useUserStoreHook()?.username
: useUserStoreHook()?.nickname;
const userName = computed(() => {
return isAllEmpty(useUserStoreHook()?.nickName)
? useUserStoreHook()?.userName
: useUserStoreHook()?.nickName;
});
const avatarsStyle = computed(() => {
return username.value ? { marginRight: "10px" } : "";
return userName.value ? { marginRight: "10px" } : "";
});
const isCollapse = computed(() => {
@ -149,7 +149,7 @@ export function useNav() {
getLogo,
isCollapse,
pureApp,
username,
userName,
userAvatar,
avatarsStyle,
tooltipEffect

View File

@ -28,7 +28,6 @@ const modulesRoutes = import.meta.glob("/src/views/**/*.{vue,tsx}");
// 动态路由
import { getAsyncRoutes } from "@/api/routes";
function handRank(routeInfo: any) {
const { name, path, parentId, meta } = routeInfo;
return isAllEmpty(parentId)

View File

@ -26,6 +26,7 @@ export const usePermissionStore = defineStore("pure-permission", {
actions: {
/** 组装整体路由生成的菜单 */
handleWholeMenus(routes: any[]) {
debugger;
this.wholeMenus = filterNoPermissionTree(
filterTree(ascending(this.constantMenus.concat(routes)))
);

View File

@ -15,15 +15,16 @@ import {
} from "@/api/user";
import { useMultiTagsStoreHook } from "./multiTags";
import { type DataInfo, setToken, removeToken, userKey } from "@/utils/auth";
import type { Res } from "@/utils/http/types";
export const useUserStore = defineStore("pure-user", {
state: (): userType => ({
// 头像
avatar: storageLocal().getItem<DataInfo<number>>(userKey)?.avatar ?? "",
// 用户名
username: storageLocal().getItem<DataInfo<number>>(userKey)?.username ?? "",
userName: storageLocal().getItem<DataInfo<number>>(userKey)?.userName ?? "",
// 昵称
nickname: storageLocal().getItem<DataInfo<number>>(userKey)?.nickname ?? "",
nickName: storageLocal().getItem<DataInfo<number>>(userKey)?.nickName ?? "",
// 页面级别权限
roles: storageLocal().getItem<DataInfo<number>>(userKey)?.roles ?? [],
// 按钮级别权限
@ -40,12 +41,12 @@ export const useUserStore = defineStore("pure-user", {
this.avatar = avatar;
},
/** 存储用户名 */
SET_USERNAME(username: string) {
this.username = username;
SET_USERNAME(userName: string) {
this.userName = userName;
},
/** 存储昵称 */
SET_NICKNAME(nickname: string) {
this.nickname = nickname;
SET_NICKNAME(nickName: string) {
this.nickName = nickName;
},
/** 存储角色 */
SET_ROLES(roles: Array<string>) {
@ -65,10 +66,10 @@ export const useUserStore = defineStore("pure-user", {
},
/** 登入 */
async loginByUsername(data) {
return new Promise<UserResult>((resolve, reject) => {
return new Promise<Res<UserResult>>((resolve, reject) => {
getLogin(data)
.then(data => {
if (data?.success) setToken(data.data);
if (data?.code == 200) setToken(data.data);
resolve(data);
})
.catch(error => {
@ -78,7 +79,7 @@ export const useUserStore = defineStore("pure-user", {
},
/** 前端登出(不调用接口) */
logOut() {
this.username = "";
this.userName = "";
this.roles = [];
this.permissions = [];
removeToken();

View File

@ -38,8 +38,8 @@ export type setType = {
export type userType = {
avatar?: string;
username?: string;
nickname?: string;
userName?: string;
nickName?: string;
roles?: Array<string>;
permissions?: Array<string>;
isRemembered?: boolean;

View File

@ -12,9 +12,9 @@ export interface DataInfo<T> {
/** 头像 */
avatar?: string;
/** 用户名 */
username?: string;
userName?: string;
/** 昵称 */
nickname?: string;
nickName?: string;
/** 当前登录用户的角色 */
roles?: Array<string>;
/** 当前登录用户的按钮级别权限 */
@ -43,7 +43,7 @@ export function getToken(): DataInfo<number> {
* @description `token``token`
* `accessToken`访使`token``refreshToken``accessToken``token``refreshToken`30`accessToken`2`expires``accessToken`
* `accessToken``expires``refreshToken`key值为authorized-token的cookie里
* `avatar``username``nickname``roles``permissions``refreshToken``expires`key值为`user-info`localStorage里`multipleTabsKey`
* `avatar``userName``nickName``roles``permissions``refreshToken``expires`key值为`user-info`localStorage里`multipleTabsKey`
*/
export function setToken(data: DataInfo<Date>) {
let expires = 0;
@ -68,47 +68,47 @@ export function setToken(data: DataInfo<Date>) {
: {}
);
function setUserKey({ avatar, username, nickname, roles, permissions }) {
function setUserKey({ avatar, userName, nickName, roles, permissions }) {
useUserStoreHook().SET_AVATAR(avatar);
useUserStoreHook().SET_USERNAME(username);
useUserStoreHook().SET_NICKNAME(nickname);
useUserStoreHook().SET_USERNAME(userName);
useUserStoreHook().SET_NICKNAME(nickName);
useUserStoreHook().SET_ROLES(roles);
useUserStoreHook().SET_PERMS(permissions);
storageLocal().setItem(userKey, {
refreshToken,
expires,
avatar,
username,
nickname,
userName,
nickName,
roles,
permissions
});
}
if (data.username && data.roles) {
const { username, roles } = data;
if (data.userName && data.roles) {
const { userName, roles } = data;
setUserKey({
avatar: data?.avatar ?? "",
username,
nickname: data?.nickname ?? "",
userName,
nickName: data?.nickName ?? "",
roles,
permissions: data?.permissions ?? []
});
} else {
const avatar =
storageLocal().getItem<DataInfo<number>>(userKey)?.avatar ?? "";
const username =
storageLocal().getItem<DataInfo<number>>(userKey)?.username ?? "";
const nickname =
storageLocal().getItem<DataInfo<number>>(userKey)?.nickname ?? "";
const userName =
storageLocal().getItem<DataInfo<number>>(userKey)?.userName ?? "";
const nickName =
storageLocal().getItem<DataInfo<number>>(userKey)?.nickName ?? "";
const roles =
storageLocal().getItem<DataInfo<number>>(userKey)?.roles ?? [];
const permissions =
storageLocal().getItem<DataInfo<number>>(userKey)?.permissions ?? [];
setUserKey({
avatar,
username,
nickname,
userName,
nickName,
roles,
permissions
});

View File

@ -16,6 +16,7 @@ import { useUserStoreHook } from "@/store/modules/user";
// 相关配置请参考www.axios-js.com/zh-cn/docs/#axios-request-config-1
const defaultConfig: AxiosRequestConfig = {
baseURL: import.meta.env.VITE_API_BASEURL,
// 请求超时时间
timeout: 10000,
headers: {

View File

@ -18,6 +18,11 @@ export interface PureHttpError extends AxiosError {
isCancelRequest?: boolean;
}
export type Res<T> = {
code: number;
data: T;
message: string;
};
export interface PureHttpResponse extends AxiosResponse {
config: PureHttpRequestConfig;
}

View File

@ -2,7 +2,7 @@ import { removeToken, setToken, type DataInfo } from "./auth";
import { subBefore, getQueryMap } from "@pureadmin/utils";
/**
* http://localhost:8848/#/permission/page/index?username=sso&roles=admin&accessToken=eyJhbGciOiJIUzUxMiJ9.admin
* http://localhost:8848/#/permission/page/index?userName=sso&roles=admin&accessToken=eyJhbGciOiJIUzUxMiJ9.admin
*
*
* 1.
@ -13,7 +13,7 @@ import { subBefore, getQueryMap } from "@pureadmin/utils";
(function () {
// 获取 url 中的参数
const params = getQueryMap(location.href) as DataInfo<Date>;
const must = ["username", "roles", "accessToken"];
const must = ["userName", "roles", "accessToken"];
const mustLength = must.length;
if (Object.keys(params).length !== mustLength) return;

View File

@ -37,8 +37,8 @@ dataThemeChange(overallStyle.value);
const { title } = useNav();
const ruleForm = reactive({
username: "admin",
password: "admin123"
account: "admin",
password: "123456"
});
const onLogin = async (formEl: FormInstance | undefined) => {
@ -48,11 +48,11 @@ const onLogin = async (formEl: FormInstance | undefined) => {
loading.value = true;
useUserStoreHook()
.loginByUsername({
username: ruleForm.username,
account: ruleForm.account,
password: ruleForm.password
})
.then(res => {
if (res.success) {
if ((res.code = 200)) {
//
return initRouter().then(() => {
disabled.value = true;
@ -112,12 +112,14 @@ useEventListener(document, "keydown", ({ code }) => {
<h2 class="outline-hidden">{{ title }}</h2>
</Motion>
<el-form
<!-- <el-form
ref="ruleFormRef"
:model="ruleForm"
:rules="loginRules"
size="large"
>
> -->
<el-form ref="ruleFormRef" :model="ruleForm" size="large">
<Motion :delay="100">
<el-form-item
:rules="[
@ -127,10 +129,10 @@ useEventListener(document, "keydown", ({ code }) => {
trigger: 'blur'
}
]"
prop="username"
prop="account"
>
<el-input
v-model="ruleForm.username"
v-model="ruleForm.account"
clearable
placeholder="账号"
:prefix-icon="useRenderIcon(User)"

View File

@ -16,7 +16,7 @@ const elStyle = computed((): CSSProperties => {
};
});
const username = ref(useUserStoreHook()?.username);
const userName = ref(useUserStoreHook()?.userName);
const options = [
{
@ -31,9 +31,9 @@ const options = [
function onChange() {
useUserStoreHook()
.loginByUsername({ username: username.value, password: "admin123" })
.loginByUsername({ userName: userName.value, password: "admin123" })
.then(res => {
if (res.success) {
if (res.code === 200) {
storageLocal().removeItem("async-routes");
usePermissionStoreHook().clearAllCachePage();
initRouter();
@ -50,10 +50,10 @@ function onChange() {
<el-card shadow="never" :style="elStyle">
<template #header>
<div class="card-header">
<span>当前角色{{ username }}</span>
<span>当前角色{{ userName }}</span>
</div>
</template>
<el-select v-model="username" class="w-[160px]!" @change="onChange">
<el-select v-model="userName" class="w-[160px]!" @change="onChange">
<el-option
v-for="item in options"
:key="item.value"

2
types/global.d.ts vendored
View File

@ -136,7 +136,7 @@ declare global {
showLogo?: boolean;
showModel?: string;
menuSearchHistory?: number;
username?: string;
userName?: string;
}
/**