login
This commit is contained in:
@ -1,15 +1,15 @@
|
|||||||
/* eslint-env node */
|
/* eslint-env node */
|
||||||
require('@rushstack/eslint-patch/modern-module-resolution')
|
require("@rushstack/eslint-patch/modern-module-resolution");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
'extends': [
|
extends: [
|
||||||
'plugin:vue/vue3-essential',
|
"plugin:vue/vue3-essential",
|
||||||
'eslint:recommended',
|
"eslint:recommended",
|
||||||
'@vue/eslint-config-typescript',
|
"@vue/eslint-config-typescript",
|
||||||
'@vue/eslint-config-prettier'
|
"@vue/eslint-config-prettier",
|
||||||
],
|
],
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
ecmaVersion: 'latest'
|
ecmaVersion: "latest",
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
@ -1 +1 @@
|
|||||||
{}
|
{}
|
||||||
|
@ -13,8 +13,8 @@ TypeScript cannot handle type information for `.vue` imports by default, so we r
|
|||||||
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
|
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
|
||||||
|
|
||||||
1. Disable the built-in TypeScript Extension
|
1. Disable the built-in TypeScript Extension
|
||||||
1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
|
1. Run `Extensions: Show Built-in Extensions` from VSCode's command palette
|
||||||
2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
|
2. Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
|
||||||
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
|
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
|
||||||
|
|
||||||
## Customize configuration
|
## Customize configuration
|
||||||
|
5
auto-imports.d.ts
vendored
Normal file
5
auto-imports.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Generated by 'unplugin-auto-import'
|
||||||
|
export {}
|
||||||
|
declare global {
|
||||||
|
|
||||||
|
}
|
34
components.d.ts
vendored
Normal file
34
components.d.ts
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// generated by unplugin-vue-components
|
||||||
|
// We suggest you to commit this file into source control
|
||||||
|
// Read more: https://github.com/vuejs/core/pull/3399
|
||||||
|
import '@vue/runtime-core'
|
||||||
|
|
||||||
|
export {}
|
||||||
|
|
||||||
|
declare module '@vue/runtime-core' {
|
||||||
|
export interface GlobalComponents {
|
||||||
|
ElButton: typeof import('element-plus/es')['ElButton']
|
||||||
|
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
||||||
|
ElCol: typeof import('element-plus/es')['ElCol']
|
||||||
|
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
|
||||||
|
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
||||||
|
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||||
|
ElForm: typeof import('element-plus/es')['ElForm']
|
||||||
|
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||||
|
ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||||
|
ElInput: typeof import('element-plus/es')['ElInput']
|
||||||
|
ElPagination: typeof import('element-plus/es')['ElPagination']
|
||||||
|
ElRadio: typeof import('element-plus/es')['ElRadio']
|
||||||
|
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
||||||
|
ElRow: typeof import('element-plus/es')['ElRow']
|
||||||
|
ElSwitch: typeof import('element-plus/es')['ElSwitch']
|
||||||
|
ElTable: typeof import('element-plus/es')['ElTable']
|
||||||
|
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
||||||
|
ElTag: typeof import('element-plus/es')['ElTag']
|
||||||
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
}
|
||||||
|
export interface ComponentCustomProperties {
|
||||||
|
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
|
||||||
|
}
|
||||||
|
}
|
20
index.html
20
index.html
@ -1,13 +1,13 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" href="/favicon.ico">
|
<link rel="icon" href="/favicon.ico" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>生成短链接</title>
|
<title>生成短链接</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -14,13 +14,18 @@
|
|||||||
"@element-plus/icons-vue": "^2.0.10",
|
"@element-plus/icons-vue": "^2.0.10",
|
||||||
"axios": "^1.3.2",
|
"axios": "^1.3.2",
|
||||||
"element-plus": "^2.2.30",
|
"element-plus": "^2.2.30",
|
||||||
|
"js-cookie": "^3.0.1",
|
||||||
|
"js-md5": "^0.7.3",
|
||||||
|
"jsencrypt": "^3.3.1",
|
||||||
"modern-normalize": "^1.1.0",
|
"modern-normalize": "^1.1.0",
|
||||||
|
"pinia": "^2.0.30",
|
||||||
"qrcode.vue": "^3.3.3",
|
"qrcode.vue": "^3.3.3",
|
||||||
"vue": "^3.2.45",
|
"vue": "^3.2.45",
|
||||||
"vue-router": "^4.1.6"
|
"vue-router": "^4.1.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rushstack/eslint-patch": "^1.1.4",
|
"@rushstack/eslint-patch": "^1.1.4",
|
||||||
|
"@types/js-cookie": "^3.0.2",
|
||||||
"@types/node": "^18.11.12",
|
"@types/node": "^18.11.12",
|
||||||
"@vitejs/plugin-vue": "^4.0.0",
|
"@vitejs/plugin-vue": "^4.0.0",
|
||||||
"@vue/eslint-config-prettier": "^7.0.0",
|
"@vue/eslint-config-prettier": "^7.0.0",
|
||||||
@ -35,6 +40,9 @@
|
|||||||
"sass": "^1.58.0",
|
"sass": "^1.58.0",
|
||||||
"tailwindcss": "^3.2.6",
|
"tailwindcss": "^3.2.6",
|
||||||
"typescript": "~4.7.4",
|
"typescript": "~4.7.4",
|
||||||
|
"unplugin-auto-import": "^0.14.2",
|
||||||
|
"unplugin-icons": "^0.15.2",
|
||||||
|
"unplugin-vue-components": "^0.23.0",
|
||||||
"vite": "^4.0.0",
|
"vite": "^4.0.0",
|
||||||
"vue-tsc": "^1.0.12"
|
"vue-tsc": "^1.0.12"
|
||||||
}
|
}
|
||||||
|
948
pnpm-lock.yaml
generated
948
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -3,4 +3,4 @@ module.exports = {
|
|||||||
tailwindcss: {},
|
tailwindcss: {},
|
||||||
autoprefixer: {},
|
autoprefixer: {},
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
10
src/App.vue
10
src/App.vue
@ -1,13 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// export default defineComponent({
|
// @ts-ignore
|
||||||
// components: { Gen_short_link }
|
import zhCn from "element-plus/dist/locale/zh-cn.mjs";
|
||||||
//
|
|
||||||
// });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<!-- <GenShortLink class="w-full h-full"></GenShortLink>-->
|
<!-- <GenShortLink class="w-full h-full"></GenShortLink>-->
|
||||||
<RouterView />
|
<el-config-provider :locale="zhCn">
|
||||||
|
<RouterView />
|
||||||
|
</el-config-provider>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
42
src/api/login.ts
Normal file
42
src/api/login.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import request from "@/utils/request";
|
||||||
|
// @ts-ignore
|
||||||
|
import md5 from "js-md5";
|
||||||
|
|
||||||
|
// 登录方法
|
||||||
|
export function login(
|
||||||
|
username: string,
|
||||||
|
password: string,
|
||||||
|
code: string,
|
||||||
|
uuid: string
|
||||||
|
) {
|
||||||
|
const data = {
|
||||||
|
username,
|
||||||
|
password: md5(password),
|
||||||
|
code,
|
||||||
|
uuid,
|
||||||
|
};
|
||||||
|
return request({
|
||||||
|
url: "/login",
|
||||||
|
headers: {
|
||||||
|
isToken: false,
|
||||||
|
},
|
||||||
|
method: "post",
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户详细信息
|
||||||
|
export function getInfo() {
|
||||||
|
return request({
|
||||||
|
url: "/getInfo",
|
||||||
|
method: "get",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 退出方法
|
||||||
|
export function logout() {
|
||||||
|
return request({
|
||||||
|
url: "/logout",
|
||||||
|
method: "post",
|
||||||
|
});
|
||||||
|
}
|
BIN
src/assets/login-background.jpg
Normal file
BIN
src/assets/login-background.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 509 KiB |
22
src/main.ts
22
src/main.ts
@ -1,24 +1,26 @@
|
|||||||
import { createApp } from "vue";
|
import { createApp } from "vue";
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
|
import store from "./store";
|
||||||
import router from "./router";
|
import router from "./router";
|
||||||
import ElementPlus from "element-plus";
|
|
||||||
import "element-plus/dist/index.css";
|
import "element-plus/dist/index.css";
|
||||||
import "./assets/main.css";
|
import "./assets/main.css";
|
||||||
import "modern-normalize/modern-normalize.css";
|
import "modern-normalize/modern-normalize.css";
|
||||||
|
import "./permission"; // permission control
|
||||||
// import "@/assets/iconfont/iconfont.js";
|
// import "@/assets/iconfont/iconfont.js";
|
||||||
import "@/assets/iconfont/iconfont.css";
|
import "@/assets/iconfont/iconfont.css";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import zhCn from "element-plus/dist/locale/zh-cn.mjs";
|
// import zhCn from "element-plus/dist/locale/zh-cn.mjs";
|
||||||
|
//
|
||||||
import * as ElementPlusIconsVue from "@element-plus/icons-vue";
|
// import * as ElementPlusIconsVue from "@element-plus/icons-vue";
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
|
app.use(store);
|
||||||
app.use(router);
|
app.use(router);
|
||||||
app.use(ElementPlus, {
|
// app.use(ElementPlus, {
|
||||||
locale: zhCn,
|
// locale: zhCn,
|
||||||
});
|
// });
|
||||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
// for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||||
app.component(key, component);
|
// app.component(key, component);
|
||||||
}
|
// }
|
||||||
app.mount("#app");
|
app.mount("#app");
|
||||||
|
40
src/permission.ts
Normal file
40
src/permission.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { getToken } from "@/utils/auth";
|
||||||
|
import router from "@/router";
|
||||||
|
import { useUserStore } from "@/store/user";
|
||||||
|
|
||||||
|
const whiteList = ["/login"];
|
||||||
|
// const userStore = useUserStore();
|
||||||
|
router.beforeEach((to, from, next) => {
|
||||||
|
if (getToken()) {
|
||||||
|
if (to.path === "/login") {
|
||||||
|
next({ path: "/" });
|
||||||
|
// NProgress.done()
|
||||||
|
} else {
|
||||||
|
if (useUserStore().roles.length === 0) {
|
||||||
|
useUserStore()
|
||||||
|
.getInfo()
|
||||||
|
.then(() => {
|
||||||
|
next({ ...to, replace: true });
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
useUserStore()
|
||||||
|
.logOut()
|
||||||
|
.then(() => {
|
||||||
|
next({ path: "/" });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 没有token
|
||||||
|
if (whiteList.indexOf(to.path) !== -1) {
|
||||||
|
// 在免登录白名单,直接进入
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
next(`/login?redirect=${to.fullPath}`); // 否则全部重定向到登录页
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
@ -1,6 +1,7 @@
|
|||||||
import { createRouter, createWebHistory } from "vue-router";
|
import { createRouter, createWebHistory } from "vue-router";
|
||||||
import GenShortLink from "@/views/GenShortLink.vue";
|
import GenShortLink from "@/views/GenShortLink.vue";
|
||||||
import AccessRecords from "@/views/AccessRecords.vue";
|
import AccessRecords from "@/views/AccessRecords.vue";
|
||||||
|
import Login from "@/views/Login.vue";
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
@ -15,6 +16,11 @@ const router = createRouter({
|
|||||||
name: "AccessRecords",
|
name: "AccessRecords",
|
||||||
component: AccessRecords,
|
component: AccessRecords,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/login",
|
||||||
|
name: "Login",
|
||||||
|
component: Login,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
5
src/store/index.ts
Normal file
5
src/store/index.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { createPinia } from "pinia";
|
||||||
|
|
||||||
|
const store = createPinia();
|
||||||
|
|
||||||
|
export default store;
|
73
src/store/user.ts
Normal file
73
src/store/user.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import { defineStore } from "pinia";
|
||||||
|
import { getToken, removeToken, setToken } from "@/utils/auth";
|
||||||
|
import { getInfo, login, logout } from "@/api/login";
|
||||||
|
|
||||||
|
export const useUserStore = defineStore("user", {
|
||||||
|
state: () => {
|
||||||
|
return {
|
||||||
|
token: getToken(),
|
||||||
|
name: "",
|
||||||
|
avatar: "",
|
||||||
|
roles: [],
|
||||||
|
permissions: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
// 登录
|
||||||
|
login(userInfo: any) {
|
||||||
|
const username = userInfo.username.trim();
|
||||||
|
const password = userInfo.password;
|
||||||
|
const code = userInfo.code;
|
||||||
|
const uuid = userInfo.uuid;
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
login(username, password, code, uuid)
|
||||||
|
.then((res: any) => {
|
||||||
|
setToken(res.data.token);
|
||||||
|
this.token = res.data.token;
|
||||||
|
resolve(null);
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 退出系统
|
||||||
|
logOut() {
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
logout()
|
||||||
|
.then(() => {
|
||||||
|
this.token = "";
|
||||||
|
removeToken();
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, // 获取用户信息
|
||||||
|
getInfo() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
getInfo()
|
||||||
|
.then((res: any) => {
|
||||||
|
const user = res.data.user;
|
||||||
|
// const avatar = (user.avatar == "" || user.avatar == null) ? defAva : import.meta.env.VITE_APP_BASE_API + user.avatar;
|
||||||
|
|
||||||
|
if (res.data.roles && res.data.roles.length > 0) {
|
||||||
|
// 验证返回的roles是否是一个非空数组
|
||||||
|
this.roles = res.data.roles;
|
||||||
|
this.permissions = res.data.permissions;
|
||||||
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
|
this.roles = ["ROLE_DEFAULT"];
|
||||||
|
}
|
||||||
|
this.name = user.userName;
|
||||||
|
// this.avatar = avatar;
|
||||||
|
resolve(res.data);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
@ -5,4 +5,5 @@ export interface ShortLink {
|
|||||||
urlPrefix?: string;
|
urlPrefix?: string;
|
||||||
urlSuffix?: string;
|
urlSuffix?: string;
|
||||||
validityTime?: string;
|
validityTime?: string;
|
||||||
|
status?: boolean;
|
||||||
}
|
}
|
||||||
|
16
src/utils/auth.ts
Normal file
16
src/utils/auth.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// @ts-ignore
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
|
||||||
|
const TokenKey = "Admin-Token";
|
||||||
|
|
||||||
|
export function getToken() {
|
||||||
|
return Cookies.get(TokenKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setToken(token: string) {
|
||||||
|
return Cookies.set(TokenKey, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeToken() {
|
||||||
|
return Cookies.remove(TokenKey);
|
||||||
|
}
|
31
src/utils/jsencrypt.ts
Normal file
31
src/utils/jsencrypt.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// @ts-ignore
|
||||||
|
import JSEncrypt from "jsencrypt/bin/jsencrypt.min";
|
||||||
|
|
||||||
|
// 密钥对生成 http://web.chacuo.net/netrsakeypair
|
||||||
|
const publicKey =
|
||||||
|
"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n" +
|
||||||
|
"nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==";
|
||||||
|
|
||||||
|
const privateKey =
|
||||||
|
"MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n" +
|
||||||
|
"7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n" +
|
||||||
|
"PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n" +
|
||||||
|
"kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n" +
|
||||||
|
"cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n" +
|
||||||
|
"DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n" +
|
||||||
|
"YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n" +
|
||||||
|
"UP8iWi1Qw0Y=";
|
||||||
|
|
||||||
|
// 加密
|
||||||
|
export function encrypt(txt: string) {
|
||||||
|
const encryptor = new JSEncrypt();
|
||||||
|
encryptor.setPublicKey(publicKey); // 设置公钥
|
||||||
|
return encryptor.encrypt(txt); // 对数据进行加密
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解密
|
||||||
|
export function decrypt(txt: string) {
|
||||||
|
const encryptor = new JSEncrypt();
|
||||||
|
encryptor.setPrivateKey(privateKey); // 设置私钥
|
||||||
|
return encryptor.decrypt(txt); // 对数据进行解密
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import axios, { type AxiosRequestConfig, type AxiosResponse } from "axios";
|
import axios from "axios";
|
||||||
import { ElMessage, ElNotification } from "element-plus";
|
import { ElMessage, ElNotification } from "element-plus";
|
||||||
import { errorCode } from "@/utils/errorCode";
|
import { errorCode } from "@/utils/errorCode";
|
||||||
|
import { getToken } from "@/utils/auth";
|
||||||
// 创建axios实例
|
// 创建axios实例
|
||||||
|
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
@ -11,6 +12,17 @@ const service = axios.create({
|
|||||||
timeout: 100000,
|
timeout: 100000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
service.interceptors.request.use((config) => {
|
||||||
|
// 是否需要设置 token
|
||||||
|
const isToken = (config.headers || {}).isToken === false;
|
||||||
|
|
||||||
|
if (getToken() && !isToken) {
|
||||||
|
config.headers["Authorization"] = "Bearer " + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
});
|
||||||
service.interceptors.response.use(
|
service.interceptors.response.use(
|
||||||
(res) => {
|
(res) => {
|
||||||
// 未设置状态码则默认成功状态
|
// 未设置状态码则默认成功状态
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app-container">
|
<div id="app-container">
|
||||||
<el-button size="small" @click="back" type="primary" plain icon="back"
|
<el-button size="small" @click="back" type="primary" plain :icon="BackIcon"
|
||||||
>返回</el-button
|
>返回
|
||||||
>
|
</el-button>
|
||||||
<el-form
|
<el-form
|
||||||
class="query-form"
|
class="query-form"
|
||||||
inline
|
inline
|
||||||
@ -27,20 +27,47 @@
|
|||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="search" @click="handleSearch"
|
<el-button type="primary" :icon="Search" @click="handleSearch"
|
||||||
>搜索
|
>搜索
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" icon="refresh" @click="resetQuery"
|
<el-button type="primary" :icon="Refresh" @click="resetQuery"
|
||||||
>重置
|
>重置
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-table :data="logList" v-loading>
|
<el-table :data="logList" v-loading>
|
||||||
<el-table-column label="访问时间" prop="visitTime"></el-table-column>
|
<el-table-column
|
||||||
<el-table-column label="访问IP" prop="visitIp"></el-table-column>
|
label="访问后缀"
|
||||||
<el-table-column label="访问地区" prop="visitAddress"></el-table-column>
|
prop="urlSuffix"
|
||||||
<el-table-column label="访问设备" prop="visitDevice"></el-table-column>
|
align="center"
|
||||||
<el-table-column label="访问后缀" prop="urlSuffix"></el-table-column>
|
></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
label="访问时间"
|
||||||
|
prop="visitTime"
|
||||||
|
align="center"
|
||||||
|
></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
label="访问IP"
|
||||||
|
prop="visitIp"
|
||||||
|
align="center"
|
||||||
|
></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
label="访问地区"
|
||||||
|
prop="visitAddress"
|
||||||
|
align="center"
|
||||||
|
></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
label="访问设备"
|
||||||
|
prop="visitDevice"
|
||||||
|
align="center"
|
||||||
|
></el-table-column>
|
||||||
|
<el-table-column label="访问结果" width="80" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag v-if="row.visitType === '0'" type="success">成功</el-tag>
|
||||||
|
<el-tag v-else-if="row.visitType === '1'" type="danger">失败</el-tag>
|
||||||
|
<el-tag v-else type="warning">未知</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<div class="pagination">
|
<div class="pagination">
|
||||||
<el-pagination
|
<el-pagination
|
||||||
@ -59,6 +86,7 @@
|
|||||||
import { reactive, ref, toRefs } from "vue";
|
import { reactive, ref, toRefs } from "vue";
|
||||||
import { listLogList } from "@/api/shortlink";
|
import { listLogList } from "@/api/shortlink";
|
||||||
import type { LogListParams } from "@/types/LogListParams";
|
import type { LogListParams } from "@/types/LogListParams";
|
||||||
|
import { Back as BackIcon, Refresh, Search } from "@element-plus/icons-vue";
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
<div id="app-container" class="p-3">
|
<div id="app-container" class="p-3">
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button @click="handleAdd" type="primary" size="small" icon="plus"
|
<el-button @click="handleAdd" type="primary" size="small" :icon="Plus"
|
||||||
>新增
|
>新增
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button
|
<el-button
|
||||||
icon="delete"
|
:icon="Delete"
|
||||||
@click="handleDelete()"
|
@click="handleDelete()"
|
||||||
type="danger"
|
type="danger"
|
||||||
size="small"
|
size="small"
|
||||||
@ -89,6 +89,13 @@
|
|||||||
label="过期时间"
|
label="过期时间"
|
||||||
prop="validityTime"
|
prop="validityTime"
|
||||||
></el-table-column>
|
></el-table-column>
|
||||||
|
<el-table-column label="状态" width="80" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag v-if="row.status === '0'" type="success">启用</el-tag>
|
||||||
|
<el-tag v-else-if="row.status === '1'" type="danger">禁用</el-tag>
|
||||||
|
<el-tag v-else type="warning">未知</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column align="center" label="操作">
|
<el-table-column align="center" label="操作">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button
|
<el-button
|
||||||
@ -143,14 +150,33 @@
|
|||||||
></el-input>
|
></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="有效期" prop="validityTime">
|
<el-form-item ref="validityTimeRef" label="有效期" prop="validityTime">
|
||||||
|
<el-radio-group
|
||||||
|
:style="{ marginRight: '10px' }"
|
||||||
|
v-model="isPermanent"
|
||||||
|
@change="changePermanent"
|
||||||
|
>
|
||||||
|
<el-radio :label="true">永久</el-radio>
|
||||||
|
<el-radio :label="false">自定义</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
|
v-if="!isPermanent"
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
v-model="form.validityTime"
|
v-model="form.validityTime"
|
||||||
type="datetime"
|
type="datetime"
|
||||||
placeholder="请选择过期时间"
|
placeholder="请选择过期时间"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="状态" prop="status">
|
||||||
|
<el-switch
|
||||||
|
v-model="form.status"
|
||||||
|
inactive-value="1"
|
||||||
|
active-value="0"
|
||||||
|
inactive-text="禁用"
|
||||||
|
active-text="启用"
|
||||||
|
></el-switch>
|
||||||
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
@ -191,11 +217,13 @@ import {
|
|||||||
import { reactive, ref, toRefs } from "vue";
|
import { reactive, ref, toRefs } from "vue";
|
||||||
import { ElMessage, ElMessageBox } from "element-plus";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
import type { ShortLink } from "@/types/ShortLink";
|
import type { ShortLink } from "@/types/ShortLink";
|
||||||
|
import { CopyDocument, Delete, Plus } from "@element-plus/icons-vue";
|
||||||
|
|
||||||
import QrcodeVue from "qrcode.vue";
|
import QrcodeVue from "qrcode.vue";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
|
|
||||||
const qrcodeRef = ref();
|
const qrcodeRef = ref();
|
||||||
|
const isPermanent = ref(false);
|
||||||
const shortLinkList = ref<ShortLink[]>([]);
|
const shortLinkList = ref<ShortLink[]>([]);
|
||||||
const showEditDialog = ref(false);
|
const showEditDialog = ref(false);
|
||||||
const editDialogTitle = ref<string>("");
|
const editDialogTitle = ref<string>("");
|
||||||
@ -245,8 +273,13 @@ const data = reactive<{
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const { form, queryParams, rules } = toRefs(data);
|
const { form, queryParams, rules } = toRefs(data);
|
||||||
|
const validityTimeRef = ref();
|
||||||
|
const changePermanent = (status: boolean) => {
|
||||||
|
if (status) validityTimeRef.value.clearValidate();
|
||||||
|
};
|
||||||
const total = ref<number>(0);
|
const total = ref<number>(0);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
const resp = await listShortLink(queryParams.value);
|
const resp = await listShortLink(queryParams.value);
|
||||||
shortLinkList.value = resp.data.rows;
|
shortLinkList.value = resp.data.rows;
|
||||||
@ -327,6 +360,10 @@ const handleDelete = (id?: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const submitForm = async () => {
|
const submitForm = async () => {
|
||||||
|
if (isPermanent.value) {
|
||||||
|
form.value.validityTime = "2099-12-12 23:59:59";
|
||||||
|
}
|
||||||
|
await formRef.value.validate();
|
||||||
if (form.value.id) {
|
if (form.value.id) {
|
||||||
await updateShortLink(form.value);
|
await updateShortLink(form.value);
|
||||||
ElMessage.success("短链接修改成功");
|
ElMessage.success("短链接修改成功");
|
||||||
|
283
src/views/Login.vue
Normal file
283
src/views/Login.vue
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
<template>
|
||||||
|
<div class="login">
|
||||||
|
<el-form
|
||||||
|
ref="loginRef"
|
||||||
|
:model="loginForm"
|
||||||
|
:rules="loginRules"
|
||||||
|
class="login-form"
|
||||||
|
>
|
||||||
|
<h3 class="title">短链接生成</h3>
|
||||||
|
<el-form-item prop="username">
|
||||||
|
<el-input
|
||||||
|
v-model="loginForm.username"
|
||||||
|
type="text"
|
||||||
|
size="large"
|
||||||
|
auto-complete="off"
|
||||||
|
placeholder="账号"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<el-icon>
|
||||||
|
<User />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="password">
|
||||||
|
<el-input
|
||||||
|
v-model="loginForm.password"
|
||||||
|
type="password"
|
||||||
|
size="large"
|
||||||
|
auto-complete="off"
|
||||||
|
placeholder="密码"
|
||||||
|
@keyup.enter="handleLogin"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<el-icon>
|
||||||
|
<Lock />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- <el-form-item prop="code" v-if="captchaEnabled">-->
|
||||||
|
<!-- <el-input-->
|
||||||
|
<!-- v-model="loginForm.code"-->
|
||||||
|
<!-- size="large"-->
|
||||||
|
<!-- auto-complete="off"-->
|
||||||
|
<!-- placeholder="验证码"-->
|
||||||
|
<!-- style="width: 63%"-->
|
||||||
|
<!-- @keyup.enter="handleLogin"-->
|
||||||
|
<!-- >-->
|
||||||
|
<!-- <template #prefix>-->
|
||||||
|
<!-- <svg-icon-->
|
||||||
|
<!-- icon-class="validCode"-->
|
||||||
|
<!-- class="el-input__icon input-icon"-->
|
||||||
|
<!-- />-->
|
||||||
|
<!-- </template>-->
|
||||||
|
<!-- </el-input>-->
|
||||||
|
<!-- <div class="login-code">-->
|
||||||
|
<!-- <img :src="codeUrl" @click="getCode" class="login-code-img" />-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </el-form-item>-->
|
||||||
|
<el-checkbox
|
||||||
|
v-model="loginForm.rememberMe"
|
||||||
|
style="margin: 0px 0px 25px 0px"
|
||||||
|
>记住密码
|
||||||
|
</el-checkbox>
|
||||||
|
<el-form-item style="width: 100%">
|
||||||
|
<el-button
|
||||||
|
:loading="loading"
|
||||||
|
size="large"
|
||||||
|
type="primary"
|
||||||
|
style="width: 100%"
|
||||||
|
@click.prevent="handleLogin"
|
||||||
|
>
|
||||||
|
<span v-if="!loading">登 录</span>
|
||||||
|
<span v-else>登 录 中...</span>
|
||||||
|
</el-button>
|
||||||
|
<!-- <div style="float: right" v-if="register">-->
|
||||||
|
<!-- <router-link class="link-type" :to="'/register'"-->
|
||||||
|
<!-- >立即注册-->
|
||||||
|
<!-- </router-link>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<!-- 底部 -->
|
||||||
|
<div class="el-login-footer">
|
||||||
|
<span>Copyright © 2018-2022 ruoyi.vip All Rights Reserved.</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { Lock, User } from "@element-plus/icons-vue";
|
||||||
|
import { decrypt, encrypt } from "@/utils/jsencrypt";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
import { useUserStore } from "@/store/user";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const loginForm: any = ref({
|
||||||
|
username: "admin",
|
||||||
|
password: "admin123",
|
||||||
|
rememberMe: false,
|
||||||
|
code: "",
|
||||||
|
uuid: "",
|
||||||
|
});
|
||||||
|
const router = useRouter();
|
||||||
|
const loginRules = {
|
||||||
|
username: [{ required: true, trigger: "blur", message: "请输入您的账号" }],
|
||||||
|
password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
|
||||||
|
code: [{ required: true, trigger: "change", message: "请输入验证码" }],
|
||||||
|
};
|
||||||
|
const loginRef = ref();
|
||||||
|
const captchaEnabled = ref(false);
|
||||||
|
const codeUrl = ref("");
|
||||||
|
const loading = ref(false);
|
||||||
|
const redirect = ref(undefined);
|
||||||
|
|
||||||
|
function handleLogin() {
|
||||||
|
loginRef.value.validate((valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
loading.value = true;
|
||||||
|
// 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
|
||||||
|
if (loginForm.value.rememberMe) {
|
||||||
|
Cookies.set("username", loginForm.value.username, { expires: 30 });
|
||||||
|
Cookies.set("password", encrypt(loginForm.value.password), {
|
||||||
|
expires: 30,
|
||||||
|
});
|
||||||
|
Cookies.set("rememberMe", loginForm.value.rememberMe, { expires: 30 });
|
||||||
|
} else {
|
||||||
|
// 否则移除
|
||||||
|
Cookies.remove("username");
|
||||||
|
Cookies.remove("password");
|
||||||
|
Cookies.remove("rememberMe");
|
||||||
|
}
|
||||||
|
// 调用action的登录方法
|
||||||
|
userStore
|
||||||
|
.login(loginForm.value)
|
||||||
|
.then(() => {
|
||||||
|
router.push({ path: redirect.value || "/" });
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
// 重新获取验证码
|
||||||
|
// if (captchaEnabled.value) {
|
||||||
|
// getCode();
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCookie() {
|
||||||
|
const username = Cookies.get("username");
|
||||||
|
const password = Cookies.get("password");
|
||||||
|
const rememberMe = Cookies.get("rememberMe");
|
||||||
|
loginForm.value = {
|
||||||
|
username: username === undefined ? loginForm.value.username : username,
|
||||||
|
password:
|
||||||
|
password === undefined ? loginForm.value.password : decrypt(password),
|
||||||
|
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getCookie();
|
||||||
|
</script>
|
||||||
|
<!--<script setup>-->
|
||||||
|
<!--import { getCodeImg } from "@/api/login";-->
|
||||||
|
<!--import Cookies from "js-cookie";-->
|
||||||
|
<!--import { encrypt, decrypt } from "@/utils/jsencrypt";-->
|
||||||
|
<!--import useUserStore from "@/store/modules/user";-->
|
||||||
|
|
||||||
|
<!--const userStore = useUserStore();-->
|
||||||
|
<!--const router = useRouter();-->
|
||||||
|
<!--const { proxy } = getCurrentInstance();-->
|
||||||
|
|
||||||
|
<!---->
|
||||||
|
<!--const loading = ref(false);-->
|
||||||
|
<!--// 验证码开关-->
|
||||||
|
<!---->
|
||||||
|
<!--// 注册开关-->
|
||||||
|
<!--const register = ref(false);-->
|
||||||
|
<!--const redirect = ref(undefined);-->
|
||||||
|
|
||||||
|
<!--function getCode() {-->
|
||||||
|
<!-- getCodeImg().then((res) => {-->
|
||||||
|
<!-- captchaEnabled.value =-->
|
||||||
|
<!-- res.captchaOnOff === undefined ? true : res.captchaOnOff;-->
|
||||||
|
<!-- register.value = res.registerUser === undefined ? true : res.registerUser;-->
|
||||||
|
<!-- if (captchaEnabled.value) {-->
|
||||||
|
<!-- codeUrl.value = "data:image/gif;base64," + res.img;-->
|
||||||
|
<!-- loginForm.value.uuid = res.uuid;-->
|
||||||
|
<!-- }-->
|
||||||
|
<!-- });-->
|
||||||
|
<!--}-->
|
||||||
|
|
||||||
|
<!--function getCookie() {-->
|
||||||
|
<!-- const username = Cookies.get("username");-->
|
||||||
|
<!-- const password = Cookies.get("password");-->
|
||||||
|
<!-- const rememberMe = Cookies.get("rememberMe");-->
|
||||||
|
<!-- loginForm.value = {-->
|
||||||
|
<!-- username: username === undefined ? loginForm.value.username : username,-->
|
||||||
|
<!-- password:-->
|
||||||
|
<!-- password === undefined ? loginForm.value.password : decrypt(password),-->
|
||||||
|
<!-- rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),-->
|
||||||
|
<!-- };-->
|
||||||
|
<!--}-->
|
||||||
|
|
||||||
|
<!--getCode();-->
|
||||||
|
<!--getCookie();-->
|
||||||
|
<!--</script>-->
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.login {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
background-image: url("../assets/login-background.jpg");
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 0px auto 30px auto;
|
||||||
|
text-align: center;
|
||||||
|
color: #707070;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form {
|
||||||
|
border-radius: 6px;
|
||||||
|
background: #ffffff;
|
||||||
|
width: 400px;
|
||||||
|
padding: 25px 25px 5px 25px;
|
||||||
|
|
||||||
|
.el-input {
|
||||||
|
height: 40px;
|
||||||
|
|
||||||
|
input {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-icon {
|
||||||
|
height: 39px;
|
||||||
|
width: 14px;
|
||||||
|
margin-left: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-tip {
|
||||||
|
font-size: 13px;
|
||||||
|
text-align: center;
|
||||||
|
color: #bfbfbf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-code {
|
||||||
|
width: 33%;
|
||||||
|
height: 40px;
|
||||||
|
float: right;
|
||||||
|
|
||||||
|
img {
|
||||||
|
cursor: pointer;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-login-footer {
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
color: #fff;
|
||||||
|
font-family: Arial;
|
||||||
|
font-size: 12px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-code-img {
|
||||||
|
height: 40px;
|
||||||
|
padding-left: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,11 +1,8 @@
|
|||||||
/** @type {import("tailwindcss").Config} */
|
/** @type {import("tailwindcss").Config} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: [
|
content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
|
||||||
"./index.html",
|
|
||||||
"./src/**/*.{vue,js,ts,jsx,tsx}"
|
|
||||||
],
|
|
||||||
theme: {
|
theme: {
|
||||||
extend: {}
|
extend: {},
|
||||||
},
|
},
|
||||||
plugins: []
|
plugins: [],
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
{
|
{
|
||||||
"extends": "@vue/tsconfig/tsconfig.node.json",
|
"extends": "@vue/tsconfig/tsconfig.node.json",
|
||||||
"include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"],
|
"include": [
|
||||||
|
"vite.config.*",
|
||||||
|
"vitest.config.*",
|
||||||
|
"cypress.config.*",
|
||||||
|
"playwright.config.*"
|
||||||
|
],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"composite": true,
|
"composite": true,
|
||||||
"types": ["node"]
|
"types": ["node"]
|
||||||
|
@ -2,23 +2,48 @@ import { fileURLToPath, URL } from "node:url";
|
|||||||
|
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import vue from "@vitejs/plugin-vue";
|
import vue from "@vitejs/plugin-vue";
|
||||||
|
import AutoImport from "unplugin-auto-import/vite";
|
||||||
|
import Components from "unplugin-vue-components/vite";
|
||||||
|
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [vue()],
|
plugins: [
|
||||||
|
vue(),
|
||||||
|
AutoImport({
|
||||||
|
resolvers: [
|
||||||
|
ElementPlusResolver(),
|
||||||
|
// IconsResolver({
|
||||||
|
// prefix: "Icon"
|
||||||
|
// })
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
Components({
|
||||||
|
resolvers: [
|
||||||
|
// Auto register icon components
|
||||||
|
// 自动注册图标组件
|
||||||
|
// IconsResolver({
|
||||||
|
// enabledCollections: ["ep"]
|
||||||
|
// }),
|
||||||
|
ElementPlusResolver(),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
// Icons({
|
||||||
|
// autoInstall: true
|
||||||
|
// })
|
||||||
|
],
|
||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
"/dev-api": {
|
"/dev-api": {
|
||||||
target: "http://118.195.192.58:1618",
|
target: "http://118.195.192.58:1618",
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (p) => p.replace(/^\/dev-api/, "")
|
rewrite: (p) => p.replace(/^\/dev-api/, ""),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
"@": fileURLToPath(new URL("./src", import.meta.url))
|
"@": fileURLToPath(new URL("./src", import.meta.url)),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user