mirror of
https://github.com/pure-admin/pure-admin-thin.git
synced 2025-04-25 07:57:18 +08:00
feat: 修改登录界面,登录验证使用后端接口,修改侧边栏
This commit is contained in:
parent
ff27074ebd
commit
a3887dde7a
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -25,7 +25,7 @@
|
|||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": true
|
"source.fixAll.eslint": "explicit"
|
||||||
},
|
},
|
||||||
"iconify.excludes": ["el"]
|
"iconify.excludes": ["el"]
|
||||||
}
|
}
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
<h1>vue-pure-admin Lite Edition(no i18n version)</h1>
|
|
||||||
|
|
||||||
[](LICENSE)
|
|
||||||
|
|
||||||
**English** | [中文](./README.md)
|
|
||||||
|
|
||||||
## Introduce
|
|
||||||
|
|
||||||
The simplified version is based on the shelf extracted from [vue-pure-admin](https://github.com/pure-admin/vue-pure-admin), which contains main functions and is more suitable for actual project development. The packaged size is introduced globally [element-plus](https://element-plus.org) is still below `2.3MB`, and the full version of the code will be permanently synchronized. After enabling `brotli` compression and `cdn` to replace the local library mode, the package size is less than `350kb`
|
|
||||||
|
|
||||||
## Supporting Video
|
|
||||||
|
|
||||||
- [Click Watch Tutorial](https://www.bilibili.com/video/BV1kg411v7QT)
|
|
||||||
- [Click Watch UI Design](https://www.bilibili.com/video/BV17g411T7rq)
|
|
||||||
|
|
||||||
## Docs
|
|
||||||
|
|
||||||
- [documentation site](https://yiming_chang.gitee.io/pure-admin-doc)
|
|
||||||
|
|
||||||
## Preview
|
|
||||||
|
|
||||||
- [Click me to view the preview station](https://pure-admin-thin.netlify.app/#/login)
|
|
||||||
|
|
||||||
## Maintainer
|
|
||||||
|
|
||||||
[xiaoxian521](https://github.com/xiaoxian521)
|
|
||||||
|
|
||||||
## ⚠️ Attention
|
|
||||||
|
|
||||||
- The Lite version does not accept any issues and prs. If you have any questions, please go to the full version [issues](https://github.com/pure-admin/vue-pure-admin/issues/new/choose) to mention, thank you!
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
In principle, no fees and copyrights are charged, and it is commercially available, but if you need secondary open source (such as using this platform for secondary development and open source, the front-end code must be open source and free), please contact the author for permission! (Free, just take a record)
|
|
||||||
|
|
||||||
[MIT © 2020-present, pure-admin](./LICENSE)
|
|
53
README.md
53
README.md
@ -1,40 +1,47 @@
|
|||||||
<h1>vue-pure-admin精简版(非国际化版本)</h1>
|
### 前端(Vue.js)命名规范
|
||||||
|
|
||||||
[](LICENSE)
|
#### 变量命名
|
||||||
|
|
||||||
**中文** | [English](./README.en-US.md)
|
- 使用驼峰命名法(camelCase)来命名变量,首字母小写。
|
||||||
|
- 示例:`userInfo`, `selectedItem`.
|
||||||
|
|
||||||
## 介绍
|
#### 函数命名
|
||||||
|
|
||||||
精简版是基于 [vue-pure-admin](https://github.com/pure-admin/vue-pure-admin) 提炼出的架子,包含主体功能,更适合实际项目开发,打包后的大小在全局引入 [element-plus](https://element-plus.org) 的情况下仍然低于 `2.3MB`,并且会永久同步完整版的代码。开启 `brotli` 压缩和 `cdn` 替换本地库模式后,打包大小低于 `350kb`
|
- 同样使用驼峰命名法,以动词开头描述函数的操作。
|
||||||
|
- 示例:`getUserData()`, `updateUserProfile()`.
|
||||||
|
|
||||||
## 版本选择
|
#### 组件命名
|
||||||
|
|
||||||
当前是非国际化版本,如果您需要国际化版本 [请点击](https://github.com/pure-admin/pure-admin-thin/tree/i18n)
|
- 使用帕斯卡命名法(PascalCase)来命名组件,每个单词的首字母都大写。
|
||||||
|
- 示例:`UserProfile`, `ProductList`.
|
||||||
|
|
||||||
## 配套视频
|
#### 文件命名
|
||||||
|
|
||||||
- [点我查看教程](https://www.bilibili.com/video/BV1kg411v7QT)
|
- 使用帕斯卡命名法来命名 Vue 组件文件,同时在文件名中体现出组件的用途。
|
||||||
- [点我查看 UI 设计](https://www.bilibili.com/video/BV17g411T7rq)
|
- 示例:`UserProfile.vue`, `ProductList.vue`.
|
||||||
|
|
||||||
## 配套保姆级文档
|
#### 常量命名
|
||||||
|
|
||||||
- [查看文档](https://yiming_chang.gitee.io/pure-admin-doc)
|
- 常量全部大写,多个单词间使用下划线分隔。
|
||||||
|
- 示例:`MAX_ITEMS`, `API_ENDPOINTS`.
|
||||||
|
|
||||||
## 预览
|
#### CSS 类名
|
||||||
|
|
||||||
- [查看预览](https://pure-admin-thin.netlify.app/#/login)
|
- 使用连字符(kebab-case)来命名类名,保持一致。
|
||||||
|
- 示例:`user-profile`, `product-card`.
|
||||||
|
|
||||||
## 维护者
|
#### 路由命名和地址规范
|
||||||
|
|
||||||
[xiaoxian521](https://github.com/xiaoxian521)
|
- 使用小写字母和连字符(kebab-case)来命名路由地址。
|
||||||
|
- 示例:`/user-profile`.
|
||||||
|
|
||||||
## ⚠️ 注意
|
---
|
||||||
|
|
||||||
- 精简版不接受任何 `issues` 和 `pr`,如果有问题请到完整版 [issues](https://github.com/pure-admin/vue-pure-admin/issues/new/choose) 去提,谢谢!
|
### 运行命令:
|
||||||
|
|
||||||
## 许可证
|
```bash
|
||||||
|
npm install -g pnpm # 下载 pnpm
|
||||||
原则上不收取任何费用及版权,可商用,不过如需二次开源(比如用此平台二次开发并开源,要求前端代码必须开源免费)请联系作者获取许可!(免费,走个记录而已)
|
pnpm install # 下载配置项
|
||||||
|
pnpm dev # 运行
|
||||||
[MIT © 2020-present, pure-admin](./LICENSE)
|
pnpm build # 打包
|
||||||
|
```
|
||||||
|
@ -2,7 +2,7 @@ import type { Plugin } from "vite";
|
|||||||
import dayjs, { Dayjs } from "dayjs";
|
import dayjs, { Dayjs } from "dayjs";
|
||||||
import utils from "@pureadmin/utils";
|
import utils from "@pureadmin/utils";
|
||||||
import duration from "dayjs/plugin/duration";
|
import duration from "dayjs/plugin/duration";
|
||||||
import { green, blue, bold } from "picocolors";
|
import { green, bold } from "picocolors";
|
||||||
dayjs.extend(duration);
|
dayjs.extend(duration);
|
||||||
|
|
||||||
export function viteBuildInfo(): Plugin {
|
export function viteBuildInfo(): Plugin {
|
||||||
@ -17,15 +17,6 @@ export function viteBuildInfo(): Plugin {
|
|||||||
outDir = resolvedConfig.build?.outDir ?? "dist";
|
outDir = resolvedConfig.build?.outDir ?? "dist";
|
||||||
},
|
},
|
||||||
buildStart() {
|
buildStart() {
|
||||||
console.log(
|
|
||||||
bold(
|
|
||||||
green(
|
|
||||||
`👏欢迎使用${blue(
|
|
||||||
"[vue-pure-admin]"
|
|
||||||
)},如果您感觉不错,记得点击后面链接给个star哦💖 https://github.com/pure-admin/vue-pure-admin`
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
if (config.command === "build") {
|
if (config.command === "build") {
|
||||||
startTime = dayjs(new Date());
|
startTime = dayjs(new Date());
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ const permissionRouter = {
|
|||||||
path: "/permission",
|
path: "/permission",
|
||||||
meta: {
|
meta: {
|
||||||
title: "权限管理",
|
title: "权限管理",
|
||||||
icon: "lollipop",
|
icon: "informationLine",
|
||||||
rank: 10
|
rank: 10
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
|
3572
pnpm-lock.yaml
generated
3572
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"Version": "4.5.0",
|
"Version": "4.5.0",
|
||||||
"Title": "PureAdmin",
|
"Title": "Mine processing",
|
||||||
"FixedHeader": true,
|
"FixedHeader": true,
|
||||||
"HiddenSideBar": false,
|
"HiddenSideBar": false,
|
||||||
"MultiTagsCache": false,
|
"MultiTagsCache": false,
|
||||||
|
1
src/api/qa.ts
Normal file
1
src/api/qa.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
// import { http } from "@/utils/http";
|
@ -1,10 +1,19 @@
|
|||||||
import { http } from "@/utils/http";
|
import { http } from "@/utils/http";
|
||||||
|
|
||||||
type Result = {
|
// type Result = {
|
||||||
success: boolean;
|
// success: boolean;
|
||||||
data: Array<any>;
|
// data: Array<any>;
|
||||||
|
// };
|
||||||
|
|
||||||
|
type HelloMessageResult = {
|
||||||
|
message: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getAsyncRoutes = () => {
|
// mock 中的添加路由的接口,用不到注释掉了
|
||||||
return http.request<Result>("get", "/getAsyncRoutes");
|
// export const getAsyncRoutes = () => {
|
||||||
|
// return http.request<Result>("get", "/getAsyncRoutes");
|
||||||
|
// };
|
||||||
|
|
||||||
|
export const getHelloMessage = () => {
|
||||||
|
return http.request<HelloMessageResult>("get", "http://127.0.0.1:5005/hello");
|
||||||
};
|
};
|
||||||
|
@ -28,9 +28,11 @@ export type RefreshTokenResult = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 登录 */
|
/** 登录 使用后端实现,不再使用 mock 中*/
|
||||||
export const getLogin = (data?: object) => {
|
export const getLogin = (data?: object) => {
|
||||||
return http.request<UserResult>("post", "/login", { data });
|
return http.request<UserResult>("post", "http://127.0.0.1:5005/login", {
|
||||||
|
data
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 刷新token */
|
/** 刷新token */
|
||||||
|
BIN
src/assets/login/logo.jpg
Normal file
BIN
src/assets/login/logo.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
@ -1,36 +0,0 @@
|
|||||||
export default {
|
|
||||||
path: "/error",
|
|
||||||
redirect: "/error/403",
|
|
||||||
meta: {
|
|
||||||
icon: "informationLine",
|
|
||||||
title: "异常页面",
|
|
||||||
// showLink: false,
|
|
||||||
rank: 9
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: "/error/403",
|
|
||||||
name: "403",
|
|
||||||
component: () => import("@/views/error/403.vue"),
|
|
||||||
meta: {
|
|
||||||
title: "403"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/error/404",
|
|
||||||
name: "404",
|
|
||||||
component: () => import("@/views/error/404.vue"),
|
|
||||||
meta: {
|
|
||||||
title: "404"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/error/500",
|
|
||||||
name: "500",
|
|
||||||
component: () => import("@/views/error/500.vue"),
|
|
||||||
meta: {
|
|
||||||
title: "500"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
} as RouteConfigsTable;
|
|
29
src/router/modules/qa.ts
Normal file
29
src/router/modules/qa.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
export default {
|
||||||
|
path: "/qa",
|
||||||
|
redirect: "/qa/chat",
|
||||||
|
component: () => import("@/views/qa/index.vue"),
|
||||||
|
meta: {
|
||||||
|
icon: "lollipop",
|
||||||
|
title: "问答系统",
|
||||||
|
// showLink: false,
|
||||||
|
rank: 10
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/qa/chat",
|
||||||
|
name: "chat",
|
||||||
|
component: () => import("@/views/qa/chat/index.vue"),
|
||||||
|
meta: {
|
||||||
|
title: "对话"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/qa/triad",
|
||||||
|
name: "triad",
|
||||||
|
component: () => import("@/views/qa/triad/index.vue"),
|
||||||
|
meta: {
|
||||||
|
title: "三元组"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
} as RouteConfigsTable;
|
@ -16,7 +16,7 @@ import {
|
|||||||
storageSession,
|
storageSession,
|
||||||
isIncludeAllChildren
|
isIncludeAllChildren
|
||||||
} from "@pureadmin/utils";
|
} from "@pureadmin/utils";
|
||||||
import { getConfig } from "@/config";
|
// import { getConfig } from "@/config";
|
||||||
import { menuType } from "@/layout/types";
|
import { menuType } from "@/layout/types";
|
||||||
import { buildHierarchyTree } from "@/utils/tree";
|
import { buildHierarchyTree } from "@/utils/tree";
|
||||||
import { sessionKey, type DataInfo } from "@/utils/auth";
|
import { sessionKey, type DataInfo } from "@/utils/auth";
|
||||||
@ -27,7 +27,7 @@ const IFrame = () => import("@/layout/frameView.vue");
|
|||||||
const modulesRoutes = import.meta.glob("/src/views/**/*.{vue,tsx}");
|
const modulesRoutes = import.meta.glob("/src/views/**/*.{vue,tsx}");
|
||||||
|
|
||||||
// 动态路由
|
// 动态路由
|
||||||
import { getAsyncRoutes } from "@/api/routes";
|
// import { getAsyncRoutes } from "@/api/routes";
|
||||||
|
|
||||||
function handRank(routeInfo: any) {
|
function handRank(routeInfo: any) {
|
||||||
const { name, path, parentId, meta } = routeInfo;
|
const { name, path, parentId, meta } = routeInfo;
|
||||||
@ -181,34 +181,44 @@ function handleAsyncRoutes(routeList) {
|
|||||||
addPathMatch();
|
addPathMatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 初始化路由(`new Promise` 写法防止在异步请求中造成无限循环)*/
|
||||||
|
// function initRouter() {
|
||||||
|
// if (getConfig()?.CachingAsyncRoutes) {
|
||||||
|
// // 开启动态路由缓存本地sessionStorage
|
||||||
|
// const key = "async-routes";
|
||||||
|
// const asyncRouteList = storageSession().getItem(key) as any;
|
||||||
|
// if (asyncRouteList && asyncRouteList?.length > 0) {
|
||||||
|
// return new Promise(resolve => {
|
||||||
|
// handleAsyncRoutes(asyncRouteList);
|
||||||
|
// resolve(router);
|
||||||
|
// });
|
||||||
|
// } else {
|
||||||
|
// return new Promise(resolve => {
|
||||||
|
// getAsyncRoutes().then(({ data }) => {
|
||||||
|
// handleAsyncRoutes(cloneDeep(data));
|
||||||
|
// storageSession().setItem(key, data);
|
||||||
|
// resolve(router);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// return new Promise(resolve => {
|
||||||
|
// getAsyncRoutes().then(({ data }) => {
|
||||||
|
// handleAsyncRoutes(cloneDeep(data));
|
||||||
|
// resolve(router);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
/** 初始化路由(`new Promise` 写法防止在异步请求中造成无限循环)*/
|
/** 初始化路由(`new Promise` 写法防止在异步请求中造成无限循环)*/
|
||||||
function initRouter() {
|
function initRouter() {
|
||||||
if (getConfig()?.CachingAsyncRoutes) {
|
return new Promise(resolve => {
|
||||||
// 开启动态路由缓存本地sessionStorage
|
// 假设有静态路由配置
|
||||||
const key = "async-routes";
|
const staticRoutes = [];
|
||||||
const asyncRouteList = storageSession().getItem(key) as any;
|
handleAsyncRoutes(staticRoutes);
|
||||||
if (asyncRouteList && asyncRouteList?.length > 0) {
|
resolve(router);
|
||||||
return new Promise(resolve => {
|
});
|
||||||
handleAsyncRoutes(asyncRouteList);
|
|
||||||
resolve(router);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
getAsyncRoutes().then(({ data }) => {
|
|
||||||
handleAsyncRoutes(cloneDeep(data));
|
|
||||||
storageSession().setItem(key, data);
|
|
||||||
resolve(router);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
getAsyncRoutes().then(({ data }) => {
|
|
||||||
handleAsyncRoutes(cloneDeep(data));
|
|
||||||
resolve(router);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
import noAccess from "@/assets/status/403.svg?component";
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: "403"
|
|
||||||
});
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="flex justify-center items-center h-[640px]">
|
|
||||||
<noAccess />
|
|
||||||
<div class="ml-12">
|
|
||||||
<p
|
|
||||||
class="font-medium text-4xl mb-4 dark:text-white"
|
|
||||||
v-motion
|
|
||||||
:initial="{
|
|
||||||
opacity: 0,
|
|
||||||
y: 100
|
|
||||||
}"
|
|
||||||
:enter="{
|
|
||||||
opacity: 1,
|
|
||||||
y: 0,
|
|
||||||
transition: {
|
|
||||||
delay: 100
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
403
|
|
||||||
</p>
|
|
||||||
<p
|
|
||||||
class="mb-4 text-gray-500"
|
|
||||||
v-motion
|
|
||||||
:initial="{
|
|
||||||
opacity: 0,
|
|
||||||
y: 100
|
|
||||||
}"
|
|
||||||
:enter="{
|
|
||||||
opacity: 1,
|
|
||||||
y: 0,
|
|
||||||
transition: {
|
|
||||||
delay: 300
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
抱歉,你无权访问该页面
|
|
||||||
</p>
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
@click="router.push('/')"
|
|
||||||
v-motion
|
|
||||||
:initial="{
|
|
||||||
opacity: 0,
|
|
||||||
y: 100
|
|
||||||
}"
|
|
||||||
:enter="{
|
|
||||||
opacity: 1,
|
|
||||||
y: 0,
|
|
||||||
transition: {
|
|
||||||
delay: 500
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
返回首页
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
@ -1,70 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
import noExist from "@/assets/status/404.svg?component";
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: "404"
|
|
||||||
});
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="flex justify-center items-center h-[640px]">
|
|
||||||
<noExist />
|
|
||||||
<div class="ml-12">
|
|
||||||
<p
|
|
||||||
class="font-medium text-4xl mb-4 dark:text-white"
|
|
||||||
v-motion
|
|
||||||
:initial="{
|
|
||||||
opacity: 0,
|
|
||||||
y: 100
|
|
||||||
}"
|
|
||||||
:enter="{
|
|
||||||
opacity: 1,
|
|
||||||
y: 0,
|
|
||||||
transition: {
|
|
||||||
delay: 100
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
404
|
|
||||||
</p>
|
|
||||||
<p
|
|
||||||
class="mb-4 text-gray-500"
|
|
||||||
v-motion
|
|
||||||
:initial="{
|
|
||||||
opacity: 0,
|
|
||||||
y: 100
|
|
||||||
}"
|
|
||||||
:enter="{
|
|
||||||
opacity: 1,
|
|
||||||
y: 0,
|
|
||||||
transition: {
|
|
||||||
delay: 300
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
抱歉,你访问的页面不存在
|
|
||||||
</p>
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
@click="router.push('/')"
|
|
||||||
v-motion
|
|
||||||
:initial="{
|
|
||||||
opacity: 0,
|
|
||||||
y: 100
|
|
||||||
}"
|
|
||||||
:enter="{
|
|
||||||
opacity: 1,
|
|
||||||
y: 0,
|
|
||||||
transition: {
|
|
||||||
delay: 500
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
返回首页
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
@ -1,70 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
import noServer from "@/assets/status/500.svg?component";
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: "500"
|
|
||||||
});
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="flex justify-center items-center h-[640px]">
|
|
||||||
<noServer />
|
|
||||||
<div class="ml-12">
|
|
||||||
<p
|
|
||||||
class="font-medium text-4xl mb-4 dark:text-white"
|
|
||||||
v-motion
|
|
||||||
:initial="{
|
|
||||||
opacity: 0,
|
|
||||||
y: 100
|
|
||||||
}"
|
|
||||||
:enter="{
|
|
||||||
opacity: 1,
|
|
||||||
y: 0,
|
|
||||||
transition: {
|
|
||||||
delay: 100
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
500
|
|
||||||
</p>
|
|
||||||
<p
|
|
||||||
class="mb-4 text-gray-500"
|
|
||||||
v-motion
|
|
||||||
:initial="{
|
|
||||||
opacity: 0,
|
|
||||||
y: 100
|
|
||||||
}"
|
|
||||||
:enter="{
|
|
||||||
opacity: 1,
|
|
||||||
y: 0,
|
|
||||||
transition: {
|
|
||||||
delay: 300
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
抱歉,服务器出错了
|
|
||||||
</p>
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
@click="router.push('/')"
|
|
||||||
v-motion
|
|
||||||
:initial="{
|
|
||||||
opacity: 0,
|
|
||||||
y: 100
|
|
||||||
}"
|
|
||||||
:enter="{
|
|
||||||
opacity: 1,
|
|
||||||
y: 0,
|
|
||||||
transition: {
|
|
||||||
delay: 500
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
返回首页
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
@ -8,7 +8,7 @@ import type { FormInstance } from "element-plus";
|
|||||||
import { useLayout } from "@/layout/hooks/useLayout";
|
import { useLayout } from "@/layout/hooks/useLayout";
|
||||||
import { useUserStoreHook } from "@/store/modules/user";
|
import { useUserStoreHook } from "@/store/modules/user";
|
||||||
import { initRouter, getTopMenu } from "@/router/utils";
|
import { initRouter, getTopMenu } from "@/router/utils";
|
||||||
import { bg, avatar, illustration } from "./utils/static";
|
import { bg, illustration } from "./utils/static";
|
||||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||||
import { ref, reactive, toRaw, onMounted, onBeforeUnmount } from "vue";
|
import { ref, reactive, toRaw, onMounted, onBeforeUnmount } from "vue";
|
||||||
import { useDataThemeChange } from "@/layout/hooks/useDataThemeChange";
|
import { useDataThemeChange } from "@/layout/hooks/useDataThemeChange";
|
||||||
@ -33,8 +33,10 @@ dataThemeChange();
|
|||||||
const { title } = useNav();
|
const { title } = useNav();
|
||||||
|
|
||||||
const ruleForm = reactive({
|
const ruleForm = reactive({
|
||||||
username: "admin",
|
// username: "admin",
|
||||||
password: "admin123"
|
// password: "admin123"
|
||||||
|
username: "",
|
||||||
|
password: ""
|
||||||
});
|
});
|
||||||
|
|
||||||
const onLogin = async (formEl: FormInstance | undefined) => {
|
const onLogin = async (formEl: FormInstance | undefined) => {
|
||||||
@ -43,7 +45,10 @@ const onLogin = async (formEl: FormInstance | undefined) => {
|
|||||||
await formEl.validate((valid, fields) => {
|
await formEl.validate((valid, fields) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
useUserStoreHook()
|
useUserStoreHook()
|
||||||
.loginByUsername({ username: ruleForm.username, password: "admin123" })
|
.loginByUsername({
|
||||||
|
username: ruleForm.username,
|
||||||
|
password: ruleForm.password
|
||||||
|
})
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
// 获取后端路由
|
// 获取后端路由
|
||||||
@ -51,6 +56,12 @@ const onLogin = async (formEl: FormInstance | undefined) => {
|
|||||||
router.push(getTopMenu(true).path);
|
router.push(getTopMenu(true).path);
|
||||||
message("登录成功", { type: "success" });
|
message("登录成功", { type: "success" });
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
// TODO: 下面这个不能正确运行
|
||||||
|
// 弹窗显示 "登录失败",并重新返回到登录界面
|
||||||
|
alert("登录失败");
|
||||||
|
loading.value = false;
|
||||||
|
formEl.resetFields(); // 重置表单字段
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -95,7 +106,8 @@ onBeforeUnmount(() => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="login-box">
|
<div class="login-box">
|
||||||
<div class="login-form">
|
<div class="login-form">
|
||||||
<avatar class="avatar" />
|
<!-- <avatar class="avatar" /> -->
|
||||||
|
<img src="@/assets/login/logo.jpg" />
|
||||||
<Motion>
|
<Motion>
|
||||||
<h2 class="outline-none">{{ title }}</h2>
|
<h2 class="outline-none">{{ title }}</h2>
|
||||||
</Motion>
|
</Motion>
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { type CSSProperties, computed } from "vue";
|
|
||||||
import { hasAuth, getAuths } from "@/router/utils";
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: "PermissionButton"
|
|
||||||
});
|
|
||||||
|
|
||||||
const elStyle = computed((): CSSProperties => {
|
|
||||||
return {
|
|
||||||
width: "85vw",
|
|
||||||
justifyContent: "start"
|
|
||||||
};
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<el-space direction="vertical" size="large">
|
|
||||||
<el-tag :style="elStyle" size="large" effect="dark">
|
|
||||||
当前拥有的code列表:{{ getAuths() }}
|
|
||||||
</el-tag>
|
|
||||||
|
|
||||||
<el-card shadow="never" :style="elStyle">
|
|
||||||
<template #header>
|
|
||||||
<div class="card-header">组件方式判断权限</div>
|
|
||||||
</template>
|
|
||||||
<Auth value="btn_add">
|
|
||||||
<el-button type="success"> 拥有code:'btn_add' 权限可见 </el-button>
|
|
||||||
</Auth>
|
|
||||||
<Auth :value="['btn_edit']">
|
|
||||||
<el-button type="primary"> 拥有code:['btn_edit'] 权限可见 </el-button>
|
|
||||||
</Auth>
|
|
||||||
<Auth :value="['btn_add', 'btn_edit', 'btn_delete']">
|
|
||||||
<el-button type="danger">
|
|
||||||
拥有code:['btn_add', 'btn_edit', 'btn_delete'] 权限可见
|
|
||||||
</el-button>
|
|
||||||
</Auth>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<el-card shadow="never" :style="elStyle">
|
|
||||||
<template #header>
|
|
||||||
<div class="card-header">函数方式判断权限</div>
|
|
||||||
</template>
|
|
||||||
<el-button type="success" v-if="hasAuth('btn_add')">
|
|
||||||
拥有code:'btn_add' 权限可见
|
|
||||||
</el-button>
|
|
||||||
<el-button type="primary" v-if="hasAuth(['btn_edit'])">
|
|
||||||
拥有code:['btn_edit'] 权限可见
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
type="danger"
|
|
||||||
v-if="hasAuth(['btn_add', 'btn_edit', 'btn_delete'])"
|
|
||||||
>
|
|
||||||
拥有code:['btn_add', 'btn_edit', 'btn_delete'] 权限可见
|
|
||||||
</el-button>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<el-card shadow="never" :style="elStyle">
|
|
||||||
<template #header>
|
|
||||||
<div class="card-header">
|
|
||||||
指令方式判断权限(该方式不能动态修改权限)
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<el-button type="success" v-auth="'btn_add'">
|
|
||||||
拥有code:'btn_add' 权限可见
|
|
||||||
</el-button>
|
|
||||||
<el-button type="primary" v-auth="['btn_edit']">
|
|
||||||
拥有code:['btn_edit'] 权限可见
|
|
||||||
</el-button>
|
|
||||||
<el-button type="danger" v-auth="['btn_add', 'btn_edit', 'btn_delete']">
|
|
||||||
拥有code:['btn_add', 'btn_edit', 'btn_delete'] 权限可见
|
|
||||||
</el-button>
|
|
||||||
</el-card>
|
|
||||||
</el-space>
|
|
||||||
</template>
|
|
@ -1,66 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { initRouter } from "@/router/utils";
|
|
||||||
import { storageSession } from "@pureadmin/utils";
|
|
||||||
import { type CSSProperties, ref, computed } from "vue";
|
|
||||||
import { useUserStoreHook } from "@/store/modules/user";
|
|
||||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: "PermissionPage"
|
|
||||||
});
|
|
||||||
|
|
||||||
const elStyle = computed((): CSSProperties => {
|
|
||||||
return {
|
|
||||||
width: "85vw",
|
|
||||||
justifyContent: "start"
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const username = ref(useUserStoreHook()?.username);
|
|
||||||
|
|
||||||
const options = [
|
|
||||||
{
|
|
||||||
value: "admin",
|
|
||||||
label: "管理员角色"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "common",
|
|
||||||
label: "普通角色"
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
function onChange() {
|
|
||||||
useUserStoreHook()
|
|
||||||
.loginByUsername({ username: username.value, password: "admin123" })
|
|
||||||
.then(res => {
|
|
||||||
if (res.success) {
|
|
||||||
storageSession().removeItem("async-routes");
|
|
||||||
usePermissionStoreHook().clearAllCachePage();
|
|
||||||
initRouter();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<el-space direction="vertical" size="large">
|
|
||||||
<el-tag :style="elStyle" size="large" effect="dark">
|
|
||||||
模拟后台根据不同角色返回对应路由(具体参考完整版pure-admin代码)
|
|
||||||
</el-tag>
|
|
||||||
<el-card shadow="never" :style="elStyle">
|
|
||||||
<template #header>
|
|
||||||
<div class="card-header">
|
|
||||||
<span>当前角色:{{ username }}</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<el-select v-model="username" @change="onChange">
|
|
||||||
<el-option
|
|
||||||
v-for="item in options"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-card>
|
|
||||||
</el-space>
|
|
||||||
</template>
|
|
9
src/views/qa/chat/index.vue
Normal file
9
src/views/qa/chat/index.vue
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
defineOptions({
|
||||||
|
name: "QAchat"
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<h1>问答系统</h1>
|
||||||
|
</template>
|
27
src/views/qa/triad/index.vue
Normal file
27
src/views/qa/triad/index.vue
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { getHelloMessage } from "@/api/routes";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "QAtriad"
|
||||||
|
});
|
||||||
|
|
||||||
|
const message = ref(""); // 响应式变量,用于存储返回的消息
|
||||||
|
|
||||||
|
const handleClick = async () => {
|
||||||
|
try {
|
||||||
|
const response = await getHelloMessage();
|
||||||
|
message.value = response.message; // 更新消息
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching message:", error);
|
||||||
|
message.value = "Error fetching message";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<h1>三元组管理</h1>
|
||||||
|
<button @click="handleClick">获取消息</button>
|
||||||
|
<p v-if="message">{{ message }}</p>
|
||||||
|
<!-- 显示消息 -->
|
||||||
|
</template>
|
@ -5,5 +5,5 @@ defineOptions({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<h1>Pure-Admin-Thin(非国际化版本)</h1>
|
<h1>首页</h1>
|
||||||
</template>
|
</template>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user