feat: 完善登陆页面的部分功能
parent
f7818bda5c
commit
acd815736e
20
.env
20
.env
|
|
@ -2,29 +2,27 @@
|
||||||
# 应用配置
|
# 应用配置
|
||||||
# =====================================================================================
|
# =====================================================================================
|
||||||
# 网站标题
|
# 网站标题
|
||||||
VITE_APP_TITLE = 绝弹管理系统
|
VITE_TITLE = 绝弹管理系统
|
||||||
# 网站副标题
|
# 网站副标题
|
||||||
VITE_APP_SUBTITLE = 快速开发web应用的模板工具
|
VITE_SUBTITLE = 快速开发web应用的模板工具
|
||||||
# Axios基本URL
|
# API接口前缀
|
||||||
VITE_APP_API_BASE_URL = /api
|
VITE_API_PREFIX = http://127.0.0.1:3030/
|
||||||
|
# API文档地址 备注:需为符合 OPENAPI 规范的json文件
|
||||||
|
VITE_API_SWAGGER = http://127.0.0.1:3030/openapi.json
|
||||||
|
|
||||||
# =====================================================================================
|
# =====================================================================================
|
||||||
# 开发设置
|
# 开发设置
|
||||||
# =====================================================================================
|
# =====================================================================================
|
||||||
# API接口地址(开发环境)
|
|
||||||
VITE_API_BASE_URL = http://127.0.0.1:3030
|
|
||||||
# API代理地址(开发环境)
|
# API代理地址(开发环境)
|
||||||
VITE_API_PROXY_URL = /api
|
VITE_API_PROXY_URL = /api
|
||||||
# API文档地址(开发环境) 备注:需为openapi规范的json文件
|
|
||||||
VITE_API_DOCS_URL = http://127.0.0.1:3030/openapi.json
|
|
||||||
# 端口号(开发环境)
|
# 端口号(开发环境)
|
||||||
VITE_DEV_PORT = 3020
|
VITE_PORT = 3020
|
||||||
# 主机地址(开发环境)
|
# 主机地址(开发环境)
|
||||||
VITE_DEV_HOST = 0.0.0.0
|
VITE_HOST = 0.0.0.0
|
||||||
|
|
||||||
# =====================================================================================
|
# =====================================================================================
|
||||||
# 构建设置
|
# 构建设置
|
||||||
# =====================================================================================
|
# =====================================================================================
|
||||||
# 构建时加载的文件后缀.
|
# 构建时加载的文件后缀.
|
||||||
# 例如:设置为todo则会首先尝试加载index.todo.vue文件,不存在时再加载index.vue文件
|
# 例如:设置为todo则会首先尝试加载index.todo.vue文件,不存在时再加载index.vue文件
|
||||||
VITE_BUILD_EXTENSION = todo
|
VITE_EXTENSION = todo
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="./favicon.ico" />
|
<link rel="icon" type="image/svg+xml" 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>%VITE_APP_TITLE% - %VITE_APP_SUBTITLE%</title>
|
<title>%VITE_TITLE% - %VITE_SUBTITLE%</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app" class="dark:bg-slate-900 dark:text-slate-200">
|
<div id="app" class="dark:bg-slate-900 dark:text-slate-200">
|
||||||
|
|
@ -51,7 +51,7 @@
|
||||||
</style>
|
</style>
|
||||||
<div class="loading">
|
<div class="loading">
|
||||||
<img src="/assets/loading.svg" alt="loading" class="loading-image" />
|
<img src="/assets/loading.svg" alt="loading" class="loading-image" />
|
||||||
<h1 class="loading-title">欢迎访问%VITE_APP_TITLE%</h1>
|
<h1 class="loading-title">欢迎访问%VITE_TITLE%</h1>
|
||||||
<div class="loading-tip">正在加载中, 请稍后...</div>
|
<div class="loading-tip">正在加载中, 请稍后...</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"numeral": "^2.0.6",
|
"numeral": "^2.0.6",
|
||||||
"pinia": "^2.0.33",
|
"pinia": "^2.0.33",
|
||||||
|
"pinia-plugin-persistedstate": "^3.2.0",
|
||||||
"plop": "^3.1.2",
|
"plop": "^3.1.2",
|
||||||
"release-it": "^15.10.1",
|
"release-it": "^15.10.1",
|
||||||
"swagger-typescript-api": "^12.0.4",
|
"swagger-typescript-api": "^12.0.4",
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,9 @@ devDependencies:
|
||||||
pinia:
|
pinia:
|
||||||
specifier: ^2.0.33
|
specifier: ^2.0.33
|
||||||
version: 2.1.4(typescript@4.9.5)(vue@3.3.4)
|
version: 2.1.4(typescript@4.9.5)(vue@3.3.4)
|
||||||
|
pinia-plugin-persistedstate:
|
||||||
|
specifier: ^3.2.0
|
||||||
|
version: 3.2.0(pinia@2.1.4)
|
||||||
plop:
|
plop:
|
||||||
specifier: ^3.1.2
|
specifier: ^3.1.2
|
||||||
version: 3.1.2
|
version: 3.1.2
|
||||||
|
|
@ -5833,6 +5836,14 @@ packages:
|
||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
/pinia-plugin-persistedstate@3.2.0(pinia@2.1.4):
|
||||||
|
resolution: {integrity: sha512-tZbNGf2vjAQcIm7alK40sE51Qu/m9oWr+rEgNm/2AWr1huFxj72CjvpQcIQzMknDBJEkQznCLAGtJTIcLKrKdw==}
|
||||||
|
peerDependencies:
|
||||||
|
pinia: ^2.0.0
|
||||||
|
dependencies:
|
||||||
|
pinia: 2.1.4(typescript@4.9.5)(vue@3.3.4)
|
||||||
|
dev: true
|
||||||
|
|
||||||
/pinia@2.1.4(typescript@4.9.5)(vue@3.3.4):
|
/pinia@2.1.4(typescript@4.9.5)(vue@3.3.4):
|
||||||
resolution: {integrity: sha512-vYlnDu+Y/FXxv1ABo1vhjC+IbqvzUdiUC3sfDRrRyY2CQSrqqaa+iiHmqtARFxJVqWQMCJfXx1PBvFs9aJVLXQ==}
|
resolution: {integrity: sha512-vYlnDu+Y/FXxv1ABo1vhjC+IbqvzUdiUC3sfDRrRyY2CQSrqqaa+iiHmqtARFxJVqWQMCJfXx1PBvFs9aJVLXQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
## 修改
|
|
||||||
|
|
||||||
route-docs.ejs
|
|
||||||
- 移除 `@description` 关键字
|
|
||||||
|
|
@ -8,17 +8,17 @@ const env = loadEnv("development", process.cwd());
|
||||||
|
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
const output = await generateApi({
|
const output = await generateApi({
|
||||||
url: env.VITE_API_DOCS_URL,
|
url: env.VITE_API_SWAGGER,
|
||||||
templates: path.resolve(__dirname, "./template"),
|
templates: path.resolve(__dirname, "./template"),
|
||||||
output: path.resolve(process.cwd(), "src/api/service"),
|
output: path.resolve(process.cwd(), "src/api/service"),
|
||||||
name: "index.ts",
|
name: "Api.ts",
|
||||||
singleHttpClient: false,
|
singleHttpClient: false,
|
||||||
httpClientType: "axios",
|
httpClientType: "axios",
|
||||||
unwrapResponseData: false,
|
unwrapResponseData: false,
|
||||||
moduleNameIndex: 1,
|
moduleNameIndex: 1,
|
||||||
moduleNameFirstTag: true,
|
moduleNameFirstTag: true,
|
||||||
cleanOutput: true,
|
cleanOutput: true,
|
||||||
// generateRouteTypes: true,
|
generateRouteTypes: true,
|
||||||
extractRequestParams: true,
|
extractRequestParams: true,
|
||||||
modular: false,
|
modular: false,
|
||||||
prettier: {
|
prettier: {
|
||||||
|
|
@ -61,3 +61,11 @@ const run = async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板修改备注:
|
||||||
|
*
|
||||||
|
* route-docs.ejs
|
||||||
|
* - 移除 `@description` 关键字
|
||||||
|
*/
|
||||||
|
|
@ -57,7 +57,6 @@ module.exports = {
|
||||||
return order.indexOf(a.title) - order.indexOf(b.title);
|
return order.indexOf(a.title) - order.indexOf(b.title);
|
||||||
},
|
},
|
||||||
commitPartial: loadTemplate("commit"),
|
commitPartial: loadTemplate("commit"),
|
||||||
// headerPartial: loadTemplate('header'),
|
|
||||||
mainTemplate: loadTemplate("main"),
|
mainTemplate: loadTemplate("main"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ export default function plugin(): Plugin {
|
||||||
configResolved(resolvedConfig) {
|
configResolved(resolvedConfig) {
|
||||||
config = resolvedConfig;
|
config = resolvedConfig;
|
||||||
const defaultExt = config.mode === "development" ? "dev" : "prod";
|
const defaultExt = config.mode === "development" ? "dev" : "prod";
|
||||||
extension = config.env.VITE_BUILD_EXTENTION || defaultExt;
|
extension = config.env.VITE_EXTENTION || defaultExt;
|
||||||
},
|
},
|
||||||
|
|
||||||
async transformIndexHtml(html) {
|
async transformIndexHtml(html) {
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
export * from "./instance";
|
export * from "./instance/api";
|
||||||
export * from "./service";
|
export * from "./service/Api";
|
||||||
|
export * from "./helper/useRequest";
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,15 @@
|
||||||
import { Api } from "../service";
|
import { Api } from "../service/Api";
|
||||||
import { toast, IToastOptions } from "@/components";
|
import { toast, IToastOptions } from "@/components";
|
||||||
import { useUserStore, store } from "@/store";
|
import { useUserStore, store } from "@/store";
|
||||||
|
|
||||||
const userStore = useUserStore(store);
|
const userStore = useUserStore(store);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义扩展, 例如添加额外的请求函数
|
* API 接口实例
|
||||||
*/
|
|
||||||
class Service extends Api<unknown> {
|
|
||||||
github = {
|
|
||||||
/**
|
|
||||||
* 获取当前仓库信息
|
|
||||||
*/
|
|
||||||
getRepoInfo: async () => {
|
|
||||||
const info: Record<string, any> = await this.request({
|
|
||||||
baseURL: "https://api.github.com",
|
|
||||||
path: "/repos/juetan/apptify-admin",
|
|
||||||
method: "GET",
|
|
||||||
});
|
|
||||||
return info;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* api实例
|
|
||||||
* @see src/api/instance/instance.ts
|
* @see src/api/instance/instance.ts
|
||||||
*/
|
*/
|
||||||
const api = new Service({
|
export const api = new Api({
|
||||||
baseURL: import.meta.env.VITE_API_BASE_URL,
|
baseURL: import.meta.env.VITE_API_PREFIX,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -42,19 +23,17 @@ api.instance.interceptors.request.use(
|
||||||
if (config.toast) {
|
if (config.toast) {
|
||||||
let options: IToastOptions = {};
|
let options: IToastOptions = {};
|
||||||
if (typeof config.toast === "string") {
|
if (typeof config.toast === "string") {
|
||||||
options = {
|
options = { message: config.toast };
|
||||||
message: config.toast,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
if (typeof config.toast === "object") {
|
if (typeof config.toast === "object") {
|
||||||
options = config.toast;
|
options = config.toast;
|
||||||
}
|
}
|
||||||
config._closeToast = toast(options);
|
config.closeToast = toast(options);
|
||||||
}
|
}
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
error.config?._closeToast?.();
|
error.config?.closeToast?.();
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
@ -64,14 +43,14 @@ api.instance.interceptors.request.use(
|
||||||
*/
|
*/
|
||||||
api.instance.interceptors.response.use(
|
api.instance.interceptors.response.use(
|
||||||
(res) => {
|
(res) => {
|
||||||
res.config?._closeToast?.();
|
res.config.closeToast?.();
|
||||||
if (res.data?.code && res.data.code !== 2000) {
|
if (res.data?.code && res.data.code !== 2000) {
|
||||||
return Promise.reject(res);
|
return Promise.reject(res);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
error.config?._closeToast?.();
|
error.config.closeToast?.();
|
||||||
if (error.request) {
|
if (error.request) {
|
||||||
console.log("request error", error.request);
|
console.log("request error", error.request);
|
||||||
}
|
}
|
||||||
|
|
@ -81,5 +60,3 @@ api.instance.interceptors.response.use(
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export { api };
|
|
||||||
|
|
@ -4,14 +4,14 @@ import { IToastOptions } from "@/components";
|
||||||
declare module "axios" {
|
declare module "axios" {
|
||||||
interface AxiosRequestConfig {
|
interface AxiosRequestConfig {
|
||||||
/**
|
/**
|
||||||
* toast config
|
* 请求弹窗配置
|
||||||
* @default false
|
* @default false
|
||||||
*/
|
*/
|
||||||
toast?: boolean | string | IToastOptions;
|
toast?: boolean | string | IToastOptions;
|
||||||
/**
|
/**
|
||||||
* close toast(internal)
|
* 关闭弹窗
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_closeToast?: () => void;
|
closeToast?: () => void;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
export * from "./instance";
|
|
||||||
export * from "./useRequest";
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -26,6 +26,7 @@ export interface TableColumnButton {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 操作类型
|
* 操作类型
|
||||||
|
* @description `delete` 需配置`onClick`属性,`modify` 需配置根对象下的 `modify` 属性
|
||||||
*/
|
*/
|
||||||
type?: "delete" | "modify";
|
type?: "delete" | "modify";
|
||||||
|
|
||||||
|
|
@ -79,7 +80,7 @@ export interface UseTableOptions extends Omit<TableProps, "search" | "create" |
|
||||||
*/
|
*/
|
||||||
items?: (Partial<IFormItem> & {
|
items?: (Partial<IFormItem> & {
|
||||||
/**
|
/**
|
||||||
* 继承common.items中指定field值的项
|
* 继承`create.items`中指定field值的项
|
||||||
*/
|
*/
|
||||||
extend?: string;
|
extend?: string;
|
||||||
})[];
|
})[];
|
||||||
|
|
@ -93,7 +94,7 @@ export interface UseTableOptions extends Omit<TableProps, "search" | "create" |
|
||||||
/**
|
/**
|
||||||
* 新建弹窗配置
|
* 新建弹窗配置
|
||||||
*/
|
*/
|
||||||
create?: FormModalProps;
|
create?: Partial<FormModalProps>;
|
||||||
/**
|
/**
|
||||||
* 新建弹窗配置
|
* 新建弹窗配置
|
||||||
*/
|
*/
|
||||||
|
|
@ -105,7 +106,7 @@ export interface UseTableOptions extends Omit<TableProps, "search" | "create" |
|
||||||
extend: boolean;
|
extend: boolean;
|
||||||
items?: (FormModalProps["items"][number] & {
|
items?: (FormModalProps["items"][number] & {
|
||||||
/**
|
/**
|
||||||
* 继承`create`弹窗配置中指定field值的项
|
* 继承`create.items`弹窗配置中指定field值的项
|
||||||
*/
|
*/
|
||||||
extend?: string;
|
extend?: string;
|
||||||
})[];
|
})[];
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import { UseTableOptions } from "./use-interface";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表格组件hook
|
* 表格组件hook
|
||||||
* @see src/components/table/use-table.tsx
|
* @see `src/components/table/use-table.tsx`
|
||||||
*/
|
*/
|
||||||
export const useTable = (optionsOrFn: UseTableOptions | (() => UseTableOptions)): any => {
|
export const useTable = (optionsOrFn: UseTableOptions | (() => UseTableOptions)): any => {
|
||||||
const options: UseTableOptions = typeof optionsOrFn === "function" ? optionsOrFn() : optionsOrFn;
|
const options: UseTableOptions = typeof optionsOrFn === "function" ? optionsOrFn() : optionsOrFn;
|
||||||
|
|
@ -51,9 +51,16 @@ export const useTable = (optionsOrFn: UseTableOptions | (() => UseTableOptions))
|
||||||
Modal.warning({
|
Modal.warning({
|
||||||
...config.columnButtonDelete,
|
...config.columnButtonDelete,
|
||||||
onOk: async () => {
|
onOk: async () => {
|
||||||
const resData: any = await action?.onClick?.(data);
|
try {
|
||||||
resData.msg && Message.success(resData?.msg || "");
|
const resData: any = await action?.onClick?.(data);
|
||||||
getTable()?.loadData();
|
resData.msg && Message.success(resData?.msg || "");
|
||||||
|
getTable()?.loadData();
|
||||||
|
} catch (error: any) {
|
||||||
|
const message = error.response?.data?.message;
|
||||||
|
if (message) {
|
||||||
|
Message.warning(`提示:${message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -97,8 +104,7 @@ export const useTable = (optionsOrFn: UseTableOptions | (() => UseTableOptions))
|
||||||
if (item.extend) {
|
if (item.extend) {
|
||||||
const createItem = createItems.find((i) => i.field === item.extend);
|
const createItem = createItems.find((i) => i.field === item.extend);
|
||||||
if (createItem) {
|
if (createItem) {
|
||||||
const mergedItem = merge({}, createItem, item);
|
searchItems.push(merge({}, createItem, item));
|
||||||
searchItems.push(mergedItem);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { createApp } from "vue";
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import { router } from "./router";
|
import { router } from "./router";
|
||||||
import { store } from "./store";
|
import { store } from "./store";
|
||||||
import { style } from "./style";
|
import { style } from "./styles";
|
||||||
|
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="page-login w-full h-full grid grid-rows-[auto_1fr_auto]">
|
<div class="page-login w-full h-full grid grid-rows-[auto_1fr_auto]">
|
||||||
<div class=" top-0 m-0 h-20 w-full px-10 z-10">
|
<div class="top-0 m-0 h-20 w-full px-10 z-10">
|
||||||
<div class="md:hidden flex items-center justify-between h-13">
|
<div class="md:hidden flex items-center justify-between h-13">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<img src="/favicon.ico" alt="" width="20" height="20" class="mr-1" />
|
<img src="/favicon.ico" alt="" width="20" height="20" class="mr-1" />
|
||||||
|
|
@ -55,13 +55,15 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { api } from "@/api";
|
||||||
import { dayjs } from "@/plugins";
|
import { dayjs } from "@/plugins";
|
||||||
import { useAppStore } from "@/store";
|
import { useAppStore, useUserStore } from "@/store";
|
||||||
import { FieldRule, Form, Modal } from "@arco-design/web-vue";
|
import { FieldRule, Form, Modal } from "@arco-design/web-vue";
|
||||||
import { reactive } from "vue";
|
import { reactive } from "vue";
|
||||||
|
|
||||||
const meridiem = dayjs.localeData().meridiem(dayjs().hour(), dayjs().minute());
|
const meridiem = dayjs.localeData().meridiem(dayjs().hour(), dayjs().minute());
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
const model = reactive({ username: "admin", password: "admin" });
|
const model = reactive({ username: "admin", password: "admin" });
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
@ -93,11 +95,19 @@ const onForgetPasswordClick = () => {
|
||||||
|
|
||||||
const onSubmitClick = async () => {
|
const onSubmitClick = async () => {
|
||||||
const errors = await formRef.value?.validate();
|
const errors = await formRef.value?.validate();
|
||||||
if (errors) return;
|
if (errors) {
|
||||||
loading.value = true;
|
return;
|
||||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
}
|
||||||
loading.value = false;
|
try {
|
||||||
router.push({ path: "/" });
|
loading.value = true;
|
||||||
|
const res = await api.auth.login(model);
|
||||||
|
userStore.setUser(res.data.data);
|
||||||
|
router.push({ path: "/" });
|
||||||
|
} catch {
|
||||||
|
console.log(1);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,23 @@ const table = useTable({
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
common: {
|
search: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
extend: "name",
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
title: "新建角色",
|
||||||
|
modalProps: {
|
||||||
|
width: 580,
|
||||||
|
maskClosable: false,
|
||||||
|
},
|
||||||
|
formProps: {
|
||||||
|
layout: "vertical",
|
||||||
|
},
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
field: "name",
|
field: "name",
|
||||||
|
|
@ -77,26 +93,7 @@ const table = useTable({
|
||||||
options: () => api.permission.getPermissions(),
|
options: () => api.permission.getPermissions(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
modalProps: {
|
|
||||||
width: 580,
|
|
||||||
maskClosable: false,
|
|
||||||
},
|
|
||||||
formProps: {
|
|
||||||
layout: "vertical",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
search: {
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
field: "name",
|
|
||||||
label: "角色名称",
|
|
||||||
type: "input",
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
title: "新建角色",
|
|
||||||
submit: ({ model }) => {
|
submit: ({ model }) => {
|
||||||
return api.role.addRole(model as any);
|
return api.role.addRole(model as any);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -10,142 +10,136 @@ import { Table, useTable } from "@/components";
|
||||||
import { dayjs } from "@/plugins";
|
import { dayjs } from "@/plugins";
|
||||||
import { Avatar, Button } from "@arco-design/web-vue";
|
import { Avatar, Button } from "@arco-design/web-vue";
|
||||||
|
|
||||||
const table = useTable(() => {
|
const table = useTable({
|
||||||
const nicknameRender = ({ record }: any) => {
|
data: async (model, paging) => {
|
||||||
return (
|
return api.user.getUsers({ ...model, ...paging });
|
||||||
<div class="flex items-center">
|
},
|
||||||
<Avatar size={32}>
|
columns: [
|
||||||
<img src={record.avatar} alt="" />
|
{
|
||||||
</Avatar>
|
type: "index",
|
||||||
<span class="ml-2 flex-1 flex flex-col overflow-hidden">
|
|
||||||
<span>{record.nickname}</span>
|
|
||||||
<span class="text-gray-400 text-xs truncate">账号:{record.username}</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
data: async (model, paging) => {
|
|
||||||
return api.user.getUsers({ ...model, ...paging });
|
|
||||||
},
|
},
|
||||||
columns: [
|
{
|
||||||
{
|
title: "用户昵称",
|
||||||
type: "index",
|
dataIndex: "username",
|
||||||
|
width: 200,
|
||||||
|
render: ({ record }) => {
|
||||||
|
return (
|
||||||
|
<div class="flex items-center">
|
||||||
|
<Avatar size={32}>
|
||||||
|
<img src={record.avatar} alt="" />
|
||||||
|
</Avatar>
|
||||||
|
<span class="ml-2 flex-1 flex flex-col overflow-hidden">
|
||||||
|
<span>{record.nickname}</span>
|
||||||
|
<span class="text-gray-400 text-xs truncate">账号:{record.username}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
title: "用户昵称",
|
{
|
||||||
dataIndex: "username",
|
title: "用户描述",
|
||||||
width: 200,
|
dataIndex: "description",
|
||||||
render: nicknameRender,
|
},
|
||||||
},
|
{
|
||||||
{
|
title: "用户邮箱",
|
||||||
title: "用户描述",
|
dataIndex: "email",
|
||||||
dataIndex: "description",
|
},
|
||||||
},
|
{
|
||||||
{
|
title: "创建时间",
|
||||||
title: "用户邮箱",
|
dataIndex: "createdAt",
|
||||||
dataIndex: "email",
|
width: 200,
|
||||||
},
|
render: ({ record }) => dayjs(record.createdAt).format(),
|
||||||
{
|
},
|
||||||
title: "创建时间",
|
{
|
||||||
dataIndex: "createdAt",
|
title: "操作",
|
||||||
width: 200,
|
type: "button",
|
||||||
render: ({ record }) => dayjs(record.createdAt).format(),
|
width: 148,
|
||||||
},
|
buttons: [
|
||||||
{
|
{
|
||||||
title: "操作",
|
type: "modify",
|
||||||
type: "button",
|
text: "修改",
|
||||||
width: 148,
|
},
|
||||||
buttons: [
|
{
|
||||||
{
|
type: "delete",
|
||||||
type: "modify",
|
text: "删除",
|
||||||
text: "修改",
|
onClick: async ({ record }) => {
|
||||||
|
return api.user.delUser(record.id);
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
type: "delete",
|
],
|
||||||
text: "删除",
|
},
|
||||||
onClick: async (data) => {
|
],
|
||||||
return api.user.deleteUser(data.record.id);
|
search: {
|
||||||
},
|
items: [
|
||||||
},
|
{
|
||||||
],
|
extend: "username",
|
||||||
|
required: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
search: {
|
},
|
||||||
items: [
|
create: {
|
||||||
{
|
title: "新建用户",
|
||||||
extend: "username",
|
trigger: () => (
|
||||||
required: false,
|
<Button type="primary">
|
||||||
},
|
{{
|
||||||
],
|
icon: () => <i class="icon-park-outline-people-plus-one" />,
|
||||||
|
default: () => "添加",
|
||||||
|
}}
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
modalProps: {
|
||||||
|
width: 772,
|
||||||
|
maskClosable: false,
|
||||||
},
|
},
|
||||||
create: {
|
formProps: {
|
||||||
title: "新建用户",
|
layout: "vertical",
|
||||||
trigger: () => (
|
class: "!grid grid-cols-2 gap-x-3",
|
||||||
<Button type="primary">
|
|
||||||
{{
|
|
||||||
icon: () => <i class="icon-park-outline-people-plus-one" />,
|
|
||||||
default: () => "添加",
|
|
||||||
}}
|
|
||||||
</Button>
|
|
||||||
),
|
|
||||||
modalProps: {
|
|
||||||
width: 772,
|
|
||||||
maskClosable: false,
|
|
||||||
},
|
|
||||||
formProps: {
|
|
||||||
layout: "vertical",
|
|
||||||
class: "!grid grid-cols-2 gap-x-3",
|
|
||||||
},
|
|
||||||
model: {
|
|
||||||
avatarUrl: "",
|
|
||||||
},
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
field: "username",
|
|
||||||
label: "登录账号",
|
|
||||||
type: "input",
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "nickname",
|
|
||||||
label: "用户昵称",
|
|
||||||
type: "input",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "description",
|
|
||||||
label: "个人描述",
|
|
||||||
type: "input",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "password",
|
|
||||||
label: "密码",
|
|
||||||
type: "password",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "头像",
|
|
||||||
field: "avatar?avatarUrl",
|
|
||||||
type: "select",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "startTime:endTime",
|
|
||||||
label: "日期范围",
|
|
||||||
type: "dateRange",
|
|
||||||
nodeProps: {},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
submit: ({ model }) => {
|
|
||||||
console.log(model);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
modify: {
|
items: [
|
||||||
extend: true,
|
{
|
||||||
title: "修改用户",
|
field: "username",
|
||||||
submit: ({ model }) => {
|
label: "登录账号",
|
||||||
return api.user.updateUser(model.id, model);
|
type: "input",
|
||||||
|
required: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
field: "nickname",
|
||||||
|
label: "用户昵称",
|
||||||
|
type: "input",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "description",
|
||||||
|
label: "个人描述",
|
||||||
|
type: "input",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "password",
|
||||||
|
label: "密码",
|
||||||
|
type: "password",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "头像",
|
||||||
|
field: "avatar",
|
||||||
|
type: "select",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "startTime:endTime",
|
||||||
|
label: "日期范围",
|
||||||
|
type: "dateRange",
|
||||||
|
nodeProps: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
submit: ({ model }) => {
|
||||||
|
console.log(model);
|
||||||
},
|
},
|
||||||
};
|
},
|
||||||
|
modify: {
|
||||||
|
extend: true,
|
||||||
|
title: "修改用户",
|
||||||
|
submit: ({ model }) => {
|
||||||
|
return api.user.updateUser(model.id, model);
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { NavigationGuardWithThis } from "vue-router";
|
||||||
|
import { store, useUserStore } from "@/store";
|
||||||
|
import { Message } from "@arco-design/web-vue";
|
||||||
|
|
||||||
|
const userStore = useUserStore(store);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限守卫
|
||||||
|
* @description 校验用户是否有路由的访问权限
|
||||||
|
*/
|
||||||
|
export function useAuthGuard() {
|
||||||
|
const whitelist = ["/404"];
|
||||||
|
const signoutlist = ["/login"];
|
||||||
|
const authGuard: NavigationGuardWithThis<undefined> = async function (to, from, next) {
|
||||||
|
if (to.meta.auth === false) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
if (whitelist.includes(to.fullPath)) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
if (signoutlist.includes(to.fullPath)) {
|
||||||
|
if (userStore.id) {
|
||||||
|
Message.warning(`提示:您已登陆,如需重新请退出后再操作!`);
|
||||||
|
return next(false);
|
||||||
|
}
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
if (!userStore.id) {
|
||||||
|
return next("/login");
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
return authGuard;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { NavigationGuardWithThis } from "vue-router";
|
||||||
|
import { NProgress } from "@/plugins";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 进度条守卫
|
||||||
|
* @description 在路由跳转时显示进度条
|
||||||
|
*/
|
||||||
|
export const useNprogressGuard = () => {
|
||||||
|
const before: NavigationGuardWithThis<undefined> = function (to, from, next) {
|
||||||
|
NProgress.start();
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
const after: NavigationGuardWithThis<undefined> = function (to, from, next) {
|
||||||
|
NProgress.done();
|
||||||
|
};
|
||||||
|
return { before, after };
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { NavigationGuardWithThis } from "vue-router";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标题首位
|
||||||
|
* @description 路由跳转后更新页面标题
|
||||||
|
*/
|
||||||
|
export const useTitleGuard = () => {
|
||||||
|
const titleGuard: NavigationGuardWithThis<undefined> = function (to, from, next) {
|
||||||
|
const title = to.meta.title || import.meta.env.VITE_APP_TITLE;
|
||||||
|
const subtitle = import.meta.env.VITE_APP_SUBTITLE;
|
||||||
|
document.title = `${title} | ${subtitle}`;
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
return titleGuard;
|
||||||
|
};
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
import { Router } from 'vue-router';
|
|
||||||
import { NProgress } from '@/plugins';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置进度条
|
|
||||||
* @param router 路由实例
|
|
||||||
*/
|
|
||||||
export const useNprogress = (router: Router) => {
|
|
||||||
router.beforeEach((to, from, next) => {
|
|
||||||
NProgress.start();
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
|
|
||||||
router.afterEach(() => {
|
|
||||||
NProgress.done();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置文档标题
|
|
||||||
* @param router 路由实例
|
|
||||||
*/
|
|
||||||
export const useTitle = (router: Router) => {
|
|
||||||
router.beforeEach((to, from, next) => {
|
|
||||||
const title = to.meta.title || import.meta.env.VITE_APP_TITLE;
|
|
||||||
const subtitle = import.meta.env.VITE_APP_SUBTITLE;
|
|
||||||
document.title = `${title} | ${subtitle}`;
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置权限
|
|
||||||
* @param router 路由实例
|
|
||||||
*/
|
|
||||||
export const useAuth = (router: Router) => {
|
|
||||||
router.beforeEach((to, from, next) => {
|
|
||||||
if (to.meta.auth) {
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
import { createRouter, createWebHashHistory } from "vue-router";
|
import { createRouter, createWebHashHistory } from "vue-router";
|
||||||
import { useAuth, useNprogress, useTitle } from "../guards";
|
|
||||||
import { routes } from "../routes";
|
import { routes } from "../routes";
|
||||||
|
import { useAuthGuard } from "../guards/guard-auth";
|
||||||
|
import { useNprogressGuard } from "../guards/guard-nprogress";
|
||||||
|
import { useTitleGuard } from "../guards/guard-title";
|
||||||
|
|
||||||
|
const nprogressGuard = useNprogressGuard();
|
||||||
|
const titleGuard = useTitleGuard();
|
||||||
|
const authGuard = useAuthGuard();
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHashHistory(),
|
history: createWebHashHistory(),
|
||||||
|
|
@ -13,8 +19,9 @@ const router = createRouter({
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
useNprogress(router);
|
router.beforeEach(nprogressGuard.before);
|
||||||
useTitle(router);
|
router.beforeEach(nprogressGuard.after);
|
||||||
useAuth(router);
|
router.beforeEach(titleGuard);
|
||||||
|
router.beforeEach(authGuard);
|
||||||
|
|
||||||
export { router };
|
export { router };
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,35 @@
|
||||||
import { useDark } from "@vueuse/core";
|
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
export const useAppStore = defineStore({
|
export const useAppStore = defineStore({
|
||||||
id: "app",
|
id: "app",
|
||||||
state: () => {
|
state: () => ({
|
||||||
const isDark = useDark({
|
isDarkMode: false,
|
||||||
onChanged: (isDark) => {
|
title: import.meta.env.VITE_TITLE,
|
||||||
if (isDark) {
|
subtitle: import.meta.env.VITE_SUBTITLE,
|
||||||
document.body.setAttribute("arco-theme", "dark");
|
}),
|
||||||
document.body.classList.add("dark");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
document.body.setAttribute("arco-theme", "light");
|
|
||||||
document.body.classList.remove("dark");
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
count: 0,
|
|
||||||
isDark,
|
|
||||||
title: import.meta.env.VITE_APP_TITLE,
|
|
||||||
subtitle: import.meta.env.VITE_APP_SUBTITLE,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
getters: {
|
|
||||||
doubleCount(state) {
|
|
||||||
return state.count * 2;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
actions: {
|
actions: {
|
||||||
increment() {
|
/**
|
||||||
this.count++;
|
* 切换暗/亮模式
|
||||||
},
|
*/
|
||||||
toggleDark() {
|
toggleDark() {
|
||||||
this.isDark = !this.isDark;
|
this.isDarkMode ? this.setLight() : this.setDark();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 切换为亮模式
|
||||||
|
*/
|
||||||
|
setLight() {
|
||||||
|
document.body.setAttribute("arco-theme", "light");
|
||||||
|
document.body.classList.remove("dark");
|
||||||
|
this.isDarkMode = false;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 切换为暗模式
|
||||||
|
*/
|
||||||
|
setDark() {
|
||||||
|
document.body.setAttribute("arco-theme", "dark");
|
||||||
|
document.body.classList.add("dark");
|
||||||
|
this.isDarkMode = true;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
persist: true,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
import { createPinia } from "pinia";
|
import { createPinia } from "pinia";
|
||||||
|
import persistedstatePlugin from "pinia-plugin-persistedstate";
|
||||||
|
|
||||||
export const store = createPinia();
|
export const store = createPinia();
|
||||||
|
store.use(persistedstatePlugin);
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,18 @@
|
||||||
import { useStorage } from "@vueuse/core";
|
import { LoginedUserVo } from "@/api";
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
export const useUserStore = defineStore({
|
export const useUserStore = defineStore({
|
||||||
id: "user",
|
id: "user",
|
||||||
state: () => {
|
state: () => {
|
||||||
const user = useStorage("APP_USER", {
|
return {
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
id: 0,
|
||||||
/**
|
/**
|
||||||
* 用户名称
|
* 用户名称
|
||||||
*/
|
*/
|
||||||
name: "绝弹",
|
username: "绝弹",
|
||||||
/**
|
/**
|
||||||
* 用户头像地址
|
* 用户头像地址
|
||||||
*/
|
*/
|
||||||
|
|
@ -17,22 +21,35 @@ export const useUserStore = defineStore({
|
||||||
* JWT令牌
|
* JWT令牌
|
||||||
*/
|
*/
|
||||||
accessToken: "",
|
accessToken: "",
|
||||||
});
|
/**
|
||||||
return user;
|
* 刷新令牌
|
||||||
|
*/
|
||||||
|
refreshToken: "",
|
||||||
|
};
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
/**
|
||||||
|
* 设置令牌
|
||||||
|
*/
|
||||||
setToken(token: string) {
|
setToken(token: string) {
|
||||||
this.accessToken = token;
|
this.accessToken = token;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 清除用户信息
|
||||||
|
*/
|
||||||
clearUser() {
|
clearUser() {
|
||||||
this.name = "";
|
this.username = "";
|
||||||
this.avatar = "";
|
this.avatar = "";
|
||||||
this.accessToken = "";
|
this.accessToken = "";
|
||||||
},
|
},
|
||||||
setUser(user: { name: string; avatar: string; accessToken: string }) {
|
/**
|
||||||
this.name = user.name;
|
* 设置用户信息
|
||||||
|
*/
|
||||||
|
setUser(user: LoginedUserVo) {
|
||||||
|
this.username = user.username;
|
||||||
this.avatar = user.avatar;
|
this.avatar = user.avatar;
|
||||||
this.accessToken = user.accessToken;
|
this.accessToken = user.token;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
persist: true,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -11,16 +11,23 @@ declare module '@vue/runtime-core' {
|
||||||
ABreadcrumb: typeof import('@arco-design/web-vue')['Breadcrumb']
|
ABreadcrumb: typeof import('@arco-design/web-vue')['Breadcrumb']
|
||||||
ABreadcrumbItem: typeof import('@arco-design/web-vue')['BreadcrumbItem']
|
ABreadcrumbItem: typeof import('@arco-design/web-vue')['BreadcrumbItem']
|
||||||
AButton: typeof import('@arco-design/web-vue')['Button']
|
AButton: typeof import('@arco-design/web-vue')['Button']
|
||||||
|
ACheckbox: typeof import('@arco-design/web-vue')['Checkbox']
|
||||||
AConfigProvider: typeof import('@arco-design/web-vue')['ConfigProvider']
|
AConfigProvider: typeof import('@arco-design/web-vue')['ConfigProvider']
|
||||||
ADoption: typeof import('@arco-design/web-vue')['Doption']
|
ADoption: typeof import('@arco-design/web-vue')['Doption']
|
||||||
ADrawer: typeof import('@arco-design/web-vue')['Drawer']
|
ADrawer: typeof import('@arco-design/web-vue')['Drawer']
|
||||||
ADropdown: typeof import('@arco-design/web-vue')['Dropdown']
|
ADropdown: typeof import('@arco-design/web-vue')['Dropdown']
|
||||||
|
AForm: typeof import('@arco-design/web-vue')['Form']
|
||||||
|
AFormItem: typeof import('@arco-design/web-vue')['FormItem']
|
||||||
|
AInput: typeof import('@arco-design/web-vue')['Input']
|
||||||
|
AInputPassword: typeof import('@arco-design/web-vue')['InputPassword']
|
||||||
ALayout: typeof import('@arco-design/web-vue')['Layout']
|
ALayout: typeof import('@arco-design/web-vue')['Layout']
|
||||||
ALayoutContent: typeof import('@arco-design/web-vue')['LayoutContent']
|
ALayoutContent: typeof import('@arco-design/web-vue')['LayoutContent']
|
||||||
ALayoutHeader: typeof import('@arco-design/web-vue')['LayoutHeader']
|
ALayoutHeader: typeof import('@arco-design/web-vue')['LayoutHeader']
|
||||||
ALayoutSider: typeof import('@arco-design/web-vue')['LayoutSider']
|
ALayoutSider: typeof import('@arco-design/web-vue')['LayoutSider']
|
||||||
|
ALink: typeof import('@arco-design/web-vue')['Link']
|
||||||
AMenu: typeof import('@arco-design/web-vue')['Menu']
|
AMenu: typeof import('@arco-design/web-vue')['Menu']
|
||||||
AMenuItem: typeof import('@arco-design/web-vue')['MenuItem']
|
AMenuItem: typeof import('@arco-design/web-vue')['MenuItem']
|
||||||
|
ASpace: typeof import('@arco-design/web-vue')['Space']
|
||||||
ASubMenu: typeof import('@arco-design/web-vue')['SubMenu']
|
ASubMenu: typeof import('@arco-design/web-vue')['SubMenu']
|
||||||
ATag: typeof import('@arco-design/web-vue')['Tag']
|
ATag: typeof import('@arco-design/web-vue')['Tag']
|
||||||
ATooltip: typeof import('@arco-design/web-vue')['Tooltip']
|
ATooltip: typeof import('@arco-design/web-vue')['Tooltip']
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,15 @@ interface ImportMetaEnv {
|
||||||
/**
|
/**
|
||||||
* 网站标题
|
* 网站标题
|
||||||
*/
|
*/
|
||||||
VITE_APP_TITLE: string;
|
VITE_TITLE: string;
|
||||||
/**
|
/**
|
||||||
* 网站副标题
|
* 网站副标题
|
||||||
*/
|
*/
|
||||||
VITE_APP_SUBTITLE: string;
|
VITE_SUBTITLE: string;
|
||||||
/**
|
/**
|
||||||
* 自定义的文件后缀
|
* 自定义的文件后缀
|
||||||
*/
|
*/
|
||||||
VITE_BUILD_EXTENSION: string;
|
VITE_EXTENSION: string;
|
||||||
/**
|
/**
|
||||||
* API 地址
|
* API 地址
|
||||||
*/
|
*/
|
||||||
|
|
@ -20,11 +20,11 @@ interface ImportMetaEnv {
|
||||||
/**
|
/**
|
||||||
* 开发服务器主机
|
* 开发服务器主机
|
||||||
*/
|
*/
|
||||||
VITE_DEV_HOST: string;
|
VITE_HOST: string;
|
||||||
/**
|
/**
|
||||||
* 开发服务器端口
|
* 开发服务器端口
|
||||||
*/
|
*/
|
||||||
VITE_DEV_PORT: number;
|
VITE_PORT: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ImportMeta {
|
interface ImportMeta {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { Message } from "@arco-design/web-vue";
|
||||||
|
|
||||||
|
export const message = {
|
||||||
|
warning() {
|
||||||
|
Message.warning(``)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,8 +17,8 @@ import plugin from "./scripts/vite/plugin";
|
||||||
export default defineConfig(({ mode }) => {
|
export default defineConfig(({ mode }) => {
|
||||||
// 加载顺序,后者优先级高:.env .env.locale .env.[mode] .env.[mode].locale
|
// 加载顺序,后者优先级高:.env .env.locale .env.[mode] .env.[mode].locale
|
||||||
const env = loadEnv(mode, process.cwd());
|
const env = loadEnv(mode, process.cwd());
|
||||||
const host = env.VITE_DEV_HOST || "0.0.0.0";
|
const host = env.VITE_HOST || "0.0.0.0";
|
||||||
const port = Number(env.VITE_DEV_PORT || 3020);
|
const port = Number(env.VITE_PORT || 3020);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
base: "./",
|
base: "./",
|
||||||
|
|
@ -39,7 +39,7 @@ export default defineConfig(({ mode }) => {
|
||||||
less: {
|
less: {
|
||||||
javascriptEnabled: true,
|
javascriptEnabled: true,
|
||||||
modifyVars: {
|
modifyVars: {
|
||||||
hack: `true; @import (reference) "${resolve("src/style/css-arco.less")}";`,
|
hack: `true; @import (reference) "${resolve("src/styles/css-arco.less")}";`,
|
||||||
arcoblue: "#66f",
|
arcoblue: "#66f",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue