feat: Feature/pro docs (#70)
* chore: merge main * feat: update docs * feat: remove coze-assistant * feat: add watermark plugin * feat: update preferences * feat: update docs --------- Co-authored-by: vince <vince292007@gmail.com>pull/48/MERGE
parent
14538f7ed5
commit
376fd17a61
|
@ -11,7 +11,7 @@
|
||||||
},
|
},
|
||||||
"privatePackages": { "version": true, "tag": true },
|
"privatePackages": { "version": true, "tag": true },
|
||||||
"linked": [],
|
"linked": [],
|
||||||
"access": "restricted",
|
"access": "public",
|
||||||
"baseBranch": "main",
|
"baseBranch": "main",
|
||||||
"updateInternalDependencies": "patch",
|
"updateInternalDependencies": "patch",
|
||||||
"ignore": []
|
"ignore": []
|
||||||
|
|
|
@ -45,5 +45,5 @@ jobs:
|
||||||
|
|
||||||
- name: Test and Build
|
- name: Test and Build
|
||||||
run: |
|
run: |
|
||||||
pnpm run test
|
pnpm run test:unit
|
||||||
pnpm run build
|
pnpm run build
|
||||||
|
|
|
@ -68,7 +68,7 @@ jobs:
|
||||||
# run: git config --global user.email "you@example.com" && git config --global user.name "Your Name"
|
# run: git config --global user.email "you@example.com" && git config --global user.name "Your Name"
|
||||||
|
|
||||||
- name: Vitest tests
|
- name: Vitest tests
|
||||||
run: pnpm run test
|
run: pnpm run test:unit
|
||||||
|
|
||||||
# - name: Upload coverage
|
# - name: Upload coverage
|
||||||
# uses: codecov/codecov-action@v4
|
# uses: codecov/codecov-action@v4
|
||||||
|
|
|
@ -7,7 +7,7 @@ ls:
|
||||||
.css: kebab-case | pointcase
|
.css: kebab-case | pointcase
|
||||||
.d.ts: kebab-case | pointcase
|
.d.ts: kebab-case | pointcase
|
||||||
# shadcn 自动生成文件为 PascalCase 格式
|
# shadcn 自动生成文件为 PascalCase 格式
|
||||||
packages/@vben-core/ui-kit/shadcn-ui/src/components/ui:
|
packages/@core/ui-kit/shadcn-ui/src/components/ui:
|
||||||
.vue: PascalCase
|
.vue: PascalCase
|
||||||
|
|
||||||
ignore:
|
ignore:
|
||||||
|
@ -25,3 +25,4 @@ ignore:
|
||||||
- .vscode
|
- .vscode
|
||||||
- .idea
|
- .idea
|
||||||
- node_modules
|
- node_modules
|
||||||
|
- .cache
|
||||||
|
|
|
@ -71,7 +71,8 @@
|
||||||
"**/CVS": true,
|
"**/CVS": true,
|
||||||
"**/.stylelintcache": true,
|
"**/.stylelintcache": true,
|
||||||
"**/.DS_Store": true,
|
"**/.DS_Store": true,
|
||||||
"**/vite.config.mts.*": true
|
"**/vite.config.mts.*": true,
|
||||||
|
"**/tea.yaml": true
|
||||||
},
|
},
|
||||||
"files.watcherExclude": {
|
"files.watcherExclude": {
|
||||||
"**/.git/objects/**": true,
|
"**/.git/objects/**": true,
|
||||||
|
@ -190,7 +191,7 @@
|
||||||
"eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,.ls-lint*,cspell.json",
|
"eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,.ls-lint*,cspell.json",
|
||||||
"tailwind.config.mjs": "postcss.*"
|
"tailwind.config.mjs": "postcss.*"
|
||||||
},
|
},
|
||||||
"commentTranslate.hover.enabled": true,
|
"commentTranslate.hover.enabled": false,
|
||||||
"i18n-ally.keystyle": "nested",
|
"i18n-ally.keystyle": "nested",
|
||||||
"commentTranslate.multiLineMerge": true
|
"commentTranslate.multiLineMerge": true
|
||||||
}
|
}
|
||||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2024-present, Vben Admin
|
Copyright (c) 2024-present, Vben
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
|
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
|
||||||
|
|
||||||
<h1>Vue vben admin</h1>
|
<h1>Vue Vben Admin</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
**English** | [中文](./README.zh-CN.md)
|
**English** | [中文](./README.zh-CN.md)
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
export default defineEventHandler((event) => {
|
||||||
|
// setResponseHeaders(event, {
|
||||||
|
// 'Access-Control-Allow-Credentials': 'true',
|
||||||
|
// 'Access-Control-Allow-Headers': '*',
|
||||||
|
// 'Access-Control-Allow-Methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
|
||||||
|
// 'Access-Control-Allow-Origin': '*',
|
||||||
|
// 'Access-Control-Expose-Headers': '*',
|
||||||
|
// });
|
||||||
|
if (event.method === 'OPTIONS') {
|
||||||
|
event.node.res.statusCode = 204;
|
||||||
|
event.node.res.statusMessage = 'No Content.';
|
||||||
|
return 'OK';
|
||||||
|
}
|
||||||
|
});
|
|
@ -3,4 +3,16 @@ import errorHandler from './error';
|
||||||
export default defineNitroConfig({
|
export default defineNitroConfig({
|
||||||
devErrorHandler: errorHandler,
|
devErrorHandler: errorHandler,
|
||||||
errorHandler: '~/error',
|
errorHandler: '~/error',
|
||||||
|
routeRules: {
|
||||||
|
'/api/**': {
|
||||||
|
cors: true,
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Allow-Credentials': 'true',
|
||||||
|
'Access-Control-Allow-Headers': '*',
|
||||||
|
'Access-Control-Allow-Methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
'Access-Control-Expose-Headers': '*',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -80,8 +80,8 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
|
||||||
icon: 'mdi:button-cursor',
|
icon: 'mdi:button-cursor',
|
||||||
title: 'page.demos.access.adminVisible',
|
title: 'page.demos.access.adminVisible',
|
||||||
},
|
},
|
||||||
name: 'AccessAdminVisible',
|
name: 'AccessAdminVisibleDemo',
|
||||||
path: 'admin-visible',
|
path: '/demos/access/admin-visible',
|
||||||
},
|
},
|
||||||
super: {
|
super: {
|
||||||
component: '/demos/access/super-visible',
|
component: '/demos/access/super-visible',
|
||||||
|
@ -89,8 +89,8 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
|
||||||
icon: 'mdi:button-cursor',
|
icon: 'mdi:button-cursor',
|
||||||
title: 'page.demos.access.superVisible',
|
title: 'page.demos.access.superVisible',
|
||||||
},
|
},
|
||||||
name: 'AccessSuperVisible',
|
name: 'AccessSuperVisibleDemo',
|
||||||
path: 'super-visible',
|
path: '/demos/access/super-visible',
|
||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
component: '/demos/access/user-visible',
|
component: '/demos/access/user-visible',
|
||||||
|
@ -98,8 +98,8 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
|
||||||
icon: 'mdi:button-cursor',
|
icon: 'mdi:button-cursor',
|
||||||
title: 'page.demos.access.userVisible',
|
title: 'page.demos.access.userVisible',
|
||||||
},
|
},
|
||||||
name: 'AccessUserVisible',
|
name: 'AccessUserVisibleDemo',
|
||||||
path: 'user-visible',
|
path: '/demos/access/user-visible',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -117,8 +117,8 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
|
||||||
redirect: '/demos/access',
|
redirect: '/demos/access',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Access',
|
name: 'AccessDemos',
|
||||||
path: 'access',
|
path: '/demosaccess',
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'mdi:cloud-key-outline',
|
icon: 'mdi:cloud-key-outline',
|
||||||
title: 'page.demos.access.backendPermissions',
|
title: 'page.demos.access.backendPermissions',
|
||||||
|
@ -126,8 +126,8 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
|
||||||
redirect: '/demos/access/page-control',
|
redirect: '/demos/access/page-control',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'AccessPageControl',
|
name: 'AccessPageControlDemo',
|
||||||
path: 'page-control',
|
path: '/demos/access/page-control',
|
||||||
component: '/demos/access/index',
|
component: '/demos/access/index',
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'mdi:page-previous-outline',
|
icon: 'mdi:page-previous-outline',
|
||||||
|
@ -135,8 +135,8 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'AccessButtonControl',
|
name: 'AccessButtonControlDemo',
|
||||||
path: 'button-control',
|
path: '/demos/access/button-control',
|
||||||
component: '/demos/access/button-control',
|
component: '/demos/access/button-control',
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'mdi:button-cursor',
|
icon: 'mdi:button-cursor',
|
||||||
|
@ -144,8 +144,8 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'AccessMenuVisible403',
|
name: 'AccessMenuVisible403Demo',
|
||||||
path: 'menu-visible-403',
|
path: '/demos/access/menu-visible-403',
|
||||||
component: '/demos/access/menu-visible-403',
|
component: '/demos/access/menu-visible-403',
|
||||||
meta: {
|
meta: {
|
||||||
authority: ['no-body'],
|
authority: ['no-body'],
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
VITE_PORT = 5555
|
# 应用标题
|
||||||
|
VITE_GLOB_APP_TITLE=Vben Admin
|
||||||
|
|
||||||
# spa-title
|
# 应用命名空间,用于缓存、store等功能的前缀,确保隔离
|
||||||
VITE_GLOB_APP_TITLE = Vben Admin
|
VITE_APP_NAMESPACE=vben-web-antd
|
||||||
|
|
||||||
VITE_APP_NAMESPACE = web-antd
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
|
|
||||||
# public path
|
# public path
|
||||||
VITE_PUBLIC_PATH = /
|
VITE_BASE=/
|
||||||
|
|
||||||
# Basic interface address SPA
|
# Basic interface address SPA
|
||||||
VITE_GLOB_API_URL=/api
|
VITE_GLOB_API_URL=/api
|
||||||
|
|
||||||
VITE_VISUALIZER = true
|
VITE_VISUALIZER=true
|
||||||
|
|
|
@ -1,5 +1,16 @@
|
||||||
VITE_PUBLIC_PATH = /
|
# 端口号
|
||||||
|
VITE_PORT=5555
|
||||||
|
|
||||||
|
VITE_BASE=/
|
||||||
|
|
||||||
|
# 接口地址
|
||||||
VITE_GLOB_API_URL=/api
|
VITE_GLOB_API_URL=/api
|
||||||
|
|
||||||
VITE_NITRO_MOCK = true
|
# 是否开启 Nitro Mock服务,true 为开启,false 为关闭
|
||||||
|
VITE_NITRO_MOCK=true
|
||||||
|
|
||||||
|
# 是否打开 devtools,true 为打开,false 为关闭
|
||||||
|
VITE_DEVTOOLS=false
|
||||||
|
|
||||||
|
# 是否注入全局loading
|
||||||
|
VITE_INJECT_APP_LOADING=true
|
||||||
|
|
|
@ -1,9 +1,16 @@
|
||||||
# public path
|
VITE_BASE=/
|
||||||
VITE_PUBLIC_PATH = /
|
|
||||||
|
|
||||||
# Basic interface address SPA
|
# 接口地址
|
||||||
VITE_GLOB_API_URL = https://mock-napi.vben.pro/api
|
VITE_GLOB_API_URL=https://mock-napi.vben.pro/api
|
||||||
|
|
||||||
VITE_COMPRESS = gzip
|
# 是否开启压缩,可以设置为 none, brotli, gzip
|
||||||
|
VITE_COMPRESS=gzip
|
||||||
|
|
||||||
VITE_PWA = false
|
# 是否开启 PWA
|
||||||
|
VITE_PWA=false
|
||||||
|
|
||||||
|
# vue-router 的模式
|
||||||
|
VITE_ROUTER_HISTORY=hash
|
||||||
|
|
||||||
|
# 是否注入全局loading
|
||||||
|
VITE_INJECT_APP_LOADING=true
|
||||||
|
|
|
@ -14,6 +14,19 @@
|
||||||
<!-- 由 vite 注入 VITE_GLOB_APP_TITLE 变量,在 .env 文件内配置 -->
|
<!-- 由 vite 注入 VITE_GLOB_APP_TITLE 变量,在 .env 文件内配置 -->
|
||||||
<title><%= VITE_GLOB_APP_TITLE %></title>
|
<title><%= VITE_GLOB_APP_TITLE %></title>
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<script>
|
||||||
|
// 生产环境下注入百度统计
|
||||||
|
if (window._VBEN_ADMIN_PRO_APP_CONF_) {
|
||||||
|
var _hmt = _hmt || [];
|
||||||
|
(function () {
|
||||||
|
var hm = document.createElement('script');
|
||||||
|
hm.src =
|
||||||
|
'https://hm.baidu.com/hm.js?d20a01273820422b6aa2ee41b6c9414d';
|
||||||
|
var s = document.getElementsByTagName('script')[0];
|
||||||
|
s.parentNode.insertBefore(hm, s);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
"ant-design-vue": "^4.2.3",
|
"ant-design-vue": "^4.2.3",
|
||||||
"dayjs": "^1.11.12",
|
"dayjs": "^1.11.12",
|
||||||
"pinia": "2.1.7",
|
"pinia": "2.1.7",
|
||||||
"vue": "^3.4.33",
|
"vue": "^3.4.34",
|
||||||
"vue-router": "^4.4.0"
|
"vue-router": "^4.4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace AuthApi {
|
||||||
|
/** 登录接口参数 */
|
||||||
|
export interface LoginParams {
|
||||||
|
password: string;
|
||||||
|
username: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 登录接口返回值 */
|
||||||
|
export interface LoginResult {
|
||||||
|
accessToken: string;
|
||||||
|
desc: string;
|
||||||
|
realName: string;
|
||||||
|
refreshToken: string;
|
||||||
|
userId: string;
|
||||||
|
username: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录
|
||||||
|
*/
|
||||||
|
export async function login(data: AuthApi.LoginParams) {
|
||||||
|
return requestClient.post<AuthApi.LoginResult>('/auth/login', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户权限码
|
||||||
|
*/
|
||||||
|
export async function getAccessCodes() {
|
||||||
|
return requestClient.get<string[]>('/auth/codes');
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import type { RouteRecordStringComponent } from '@vben/types';
|
import type { RouteRecordStringComponent } from '@vben/types';
|
||||||
|
|
||||||
import { requestClient } from '#/apis/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户所有菜单
|
* 获取用户所有菜单
|
|
@ -1,6 +1,6 @@
|
||||||
import type { UserInfo } from '@vben/types';
|
import type { UserInfo } from '@vben/types';
|
||||||
|
|
||||||
import { requestClient } from '#/apis/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户信息
|
* 获取用户信息
|
|
@ -1,4 +1,4 @@
|
||||||
import { requestClient } from '#/apis/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 模拟任意状态码
|
* 模拟任意状态码
|
|
@ -1,3 +1,2 @@
|
||||||
export * from './core';
|
export * from './core';
|
||||||
export * from './demos';
|
export * from './demos';
|
||||||
export type * from './types';
|
|
|
@ -3,6 +3,7 @@
|
||||||
*/
|
*/
|
||||||
import type { HttpResponse } from '@vben/request';
|
import type { HttpResponse } from '@vben/request';
|
||||||
|
|
||||||
|
import { useAppConfig } from '@vben/hooks';
|
||||||
import { preferences } from '@vben/preferences';
|
import { preferences } from '@vben/preferences';
|
||||||
import { RequestClient } from '@vben/request';
|
import { RequestClient } from '@vben/request';
|
||||||
|
|
||||||
|
@ -10,13 +11,11 @@ import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
import { useAccessStore } from '#/store';
|
import { useAccessStore } from '#/store';
|
||||||
|
|
||||||
/**
|
const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
||||||
* 创建请求实例
|
|
||||||
* Create a request instance
|
function createRequestClient(baseURL: string) {
|
||||||
*/
|
|
||||||
function createRequestClient() {
|
|
||||||
const client = new RequestClient({
|
const client = new RequestClient({
|
||||||
baseURL: import.meta.env.VITE_GLOB_API_URL,
|
baseURL,
|
||||||
// 为每个请求携带 Authorization
|
// 为每个请求携带 Authorization
|
||||||
makeAuthorization: () => {
|
makeAuthorization: () => {
|
||||||
return {
|
return {
|
||||||
|
@ -43,6 +42,13 @@ function createRequestClient() {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
makeErrorMessage: (msg) => message.error(msg),
|
makeErrorMessage: (msg) => message.error(msg),
|
||||||
|
|
||||||
|
makeRequestHeaders: () => {
|
||||||
|
return {
|
||||||
|
// 为每个请求携带 Accept-Language
|
||||||
|
'Accept-Language': preferences.app.locale,
|
||||||
|
};
|
||||||
|
},
|
||||||
});
|
});
|
||||||
client.addResponseInterceptor<HttpResponse>((response) => {
|
client.addResponseInterceptor<HttpResponse>((response) => {
|
||||||
const { data: responseData, status } = response;
|
const { data: responseData, status } = response;
|
||||||
|
@ -56,9 +62,4 @@ function createRequestClient() {
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
const requestClient = createRequestClient();
|
export const requestClient = createRequestClient(apiURL);
|
||||||
|
|
||||||
// 其他配置的请求方法
|
|
||||||
// const { request: xxxRequest } = createRequest();
|
|
||||||
|
|
||||||
export { requestClient };
|
|
|
@ -1,17 +0,0 @@
|
||||||
import type { UserApi } from '../types';
|
|
||||||
|
|
||||||
import { requestClient } from '#/apis/request';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 登录
|
|
||||||
*/
|
|
||||||
export async function login(data: UserApi.LoginParams) {
|
|
||||||
return requestClient.post<UserApi.LoginResult>('/auth/login', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取用户权限码
|
|
||||||
*/
|
|
||||||
export async function getAccessCodes() {
|
|
||||||
return requestClient.get<string[]>('/auth/codes');
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export type * from './user';
|
|
|
@ -1,19 +0,0 @@
|
||||||
namespace UserApi {
|
|
||||||
/** 登录接口参数 */
|
|
||||||
export interface LoginParams {
|
|
||||||
password: string;
|
|
||||||
username: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 登录接口返回值 */
|
|
||||||
export interface LoginResult {
|
|
||||||
accessToken: string;
|
|
||||||
desc: string;
|
|
||||||
realName: string;
|
|
||||||
refreshToken: string;
|
|
||||||
userId: string;
|
|
||||||
username: string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type { UserApi };
|
|
|
@ -1,10 +1,9 @@
|
||||||
import { createApp } from 'vue';
|
import { createApp } from 'vue';
|
||||||
|
|
||||||
import { preferences } from '@vben/preferences';
|
|
||||||
import '@vben/styles';
|
import '@vben/styles';
|
||||||
import '@vben/styles/antd';
|
import '@vben/styles/antd';
|
||||||
|
|
||||||
import { loadMessages, setupI18n } from '#/locales';
|
import { setupI18n } from '#/locales';
|
||||||
import { setupStore } from '#/store';
|
import { setupStore } from '#/store';
|
||||||
|
|
||||||
import App from './app.vue';
|
import App from './app.vue';
|
||||||
|
@ -14,11 +13,7 @@ async function bootstrap(namespace: string) {
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
// 国际化 i18n 配置
|
// 国际化 i18n 配置
|
||||||
await setupI18n(app, {
|
await setupI18n(app);
|
||||||
defaultLocale: preferences.app.locale,
|
|
||||||
loadMessages,
|
|
||||||
missingWarn: !import.meta.env.PROD,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 配置 pinia-store
|
// 配置 pinia-store
|
||||||
await setupStore(app, { namespace });
|
await setupStore(app, { namespace });
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import type { SupportedLanguagesType } from '@vben/types';
|
import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales';
|
||||||
import type { Locale } from 'ant-design-vue/es/locale';
|
import type { Locale } from 'ant-design-vue/es/locale';
|
||||||
|
|
||||||
|
import type { App } from 'vue';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
import { $t, loadLocalesMap, setupI18n } from '@vben/locales';
|
import { $t, setupI18n as coreSetup, loadLocalesMap } from '@vben/locales';
|
||||||
|
import { preferences } from '@vben/preferences';
|
||||||
|
|
||||||
import antdEnLocale from 'ant-design-vue/es/locale/en_US';
|
import antdEnLocale from 'ant-design-vue/es/locale/en_US';
|
||||||
import antdDefaultLocale from 'ant-design-vue/es/locale/zh_CN';
|
import antdDefaultLocale from 'ant-design-vue/es/locale/zh_CN';
|
||||||
|
@ -76,4 +78,13 @@ async function loadAntdLocale(lang: SupportedLanguagesType) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function setupI18n(app: App, options: LocaleSetupOptions = {}) {
|
||||||
|
await coreSetup(app, {
|
||||||
|
defaultLocale: preferences.app.locale,
|
||||||
|
loadMessages,
|
||||||
|
missingWarn: !import.meta.env.PROD,
|
||||||
|
...options,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export { $t, antdLocale, loadMessages, setupI18n };
|
export { $t, antdLocale, loadMessages, setupI18n };
|
||||||
|
|
|
@ -33,11 +33,17 @@
|
||||||
"text": "Text Badge",
|
"text": "Text Badge",
|
||||||
"color": "Badge Color"
|
"color": "Badge Color"
|
||||||
},
|
},
|
||||||
|
"activeIcon": {
|
||||||
|
"title": "Active Menu Icon",
|
||||||
|
"children": "Children Active Icon"
|
||||||
|
},
|
||||||
"fallback": { "title": "Fallback Page" },
|
"fallback": { "title": "Fallback Page" },
|
||||||
"features": {
|
"features": {
|
||||||
"title": "Features",
|
"title": "Features",
|
||||||
"hideChildrenInMenu": "Hide Menu Children",
|
"hideChildrenInMenu": "Hide Menu Children",
|
||||||
"loginExpired": "Login Expired",
|
"loginExpired": "Login Expired",
|
||||||
|
"icons": "Icons",
|
||||||
|
"watermark": "Watermark",
|
||||||
"tabs": "Tabs",
|
"tabs": "Tabs",
|
||||||
"tabDetail": "Tab Detail Page"
|
"tabDetail": "Tab Detail Page"
|
||||||
},
|
},
|
||||||
|
|
|
@ -33,6 +33,10 @@
|
||||||
"text": "文本徽标",
|
"text": "文本徽标",
|
||||||
"color": "徽标颜色"
|
"color": "徽标颜色"
|
||||||
},
|
},
|
||||||
|
"activeIcon": {
|
||||||
|
"title": "菜单激活图标",
|
||||||
|
"children": "子级激活图标"
|
||||||
|
},
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"title": "缺省页"
|
"title": "缺省页"
|
||||||
},
|
},
|
||||||
|
@ -40,6 +44,8 @@
|
||||||
"title": "功能",
|
"title": "功能",
|
||||||
"hideChildrenInMenu": "隐藏子菜单",
|
"hideChildrenInMenu": "隐藏子菜单",
|
||||||
"loginExpired": "登录过期",
|
"loginExpired": "登录过期",
|
||||||
|
"icons": "图标",
|
||||||
|
"watermark": "水印",
|
||||||
"tabs": "标签页",
|
"tabs": "标签页",
|
||||||
"tabDetail": "标签详情页"
|
"tabDetail": "标签详情页"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { unmountGlobalLoading } from '@vben/hooks';
|
||||||
import { initPreferences } from '@vben/preferences';
|
import { initPreferences } from '@vben/preferences';
|
||||||
|
|
||||||
import { overridesPreferences } from './preferences';
|
import { overridesPreferences } from './preferences';
|
||||||
|
@ -9,7 +10,8 @@ async function initApplication() {
|
||||||
// name用于指定项目唯一标识
|
// name用于指定项目唯一标识
|
||||||
// 用于区分不同项目的偏好设置以及存储数据的key前缀以及其他一些需要隔离的数据
|
// 用于区分不同项目的偏好设置以及存储数据的key前缀以及其他一些需要隔离的数据
|
||||||
const env = import.meta.env.PROD ? 'prod' : 'dev';
|
const env = import.meta.env.PROD ? 'prod' : 'dev';
|
||||||
const namespace = `${import.meta.env.VITE_APP_NAMESPACE}-${env}`;
|
const appVersion = import.meta.env.VITE_APP_VERSION;
|
||||||
|
const namespace = `${import.meta.env.VITE_APP_NAMESPACE}-${appVersion}-${env}`;
|
||||||
|
|
||||||
// app偏好设置初始化
|
// app偏好设置初始化
|
||||||
await initPreferences({
|
await initPreferences({
|
||||||
|
@ -23,38 +25,7 @@ async function initApplication() {
|
||||||
await bootstrap(namespace);
|
await bootstrap(namespace);
|
||||||
|
|
||||||
// 移除并销毁loading
|
// 移除并销毁loading
|
||||||
destroyAppLoading();
|
unmountGlobalLoading();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 移除并销毁loading
|
|
||||||
* 放在这里是而不是放在 index.html 的app标签内,是因为这样比较不会生硬,渲染过快可能会有闪烁
|
|
||||||
* 通过先添加css动画隐藏,在动画结束后在移除loading节点来改善体验
|
|
||||||
* 不好的地方是会增加一些代码量
|
|
||||||
*/
|
|
||||||
function destroyAppLoading() {
|
|
||||||
// 查找全局 loading 元素
|
|
||||||
const loadingElement = document.querySelector('#__app-loading__');
|
|
||||||
|
|
||||||
if (loadingElement) {
|
|
||||||
// 添加隐藏类,触发过渡动画
|
|
||||||
loadingElement.classList.add('hidden');
|
|
||||||
|
|
||||||
// 查找所有需要移除的注入 loading 元素
|
|
||||||
const injectLoadingElements = document.querySelectorAll(
|
|
||||||
'[data-app-loading^="inject"]',
|
|
||||||
);
|
|
||||||
|
|
||||||
// 当过渡动画结束时,移除 loading 元素和所有注入的 loading 元素
|
|
||||||
loadingElement.addEventListener(
|
|
||||||
'transitionend',
|
|
||||||
() => {
|
|
||||||
loadingElement.remove(); // 移除 loading 元素
|
|
||||||
injectLoadingElements.forEach((el) => el.remove()); // 移除所有注入的 loading 元素
|
|
||||||
},
|
|
||||||
{ once: true },
|
|
||||||
); // 确保事件只触发一次
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initApplication();
|
initApplication();
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
|
import { useAppConfig } from '@vben/hooks';
|
||||||
import { defineOverridesPreferences } from '@vben/preferences';
|
import { defineOverridesPreferences } from '@vben/preferences';
|
||||||
|
|
||||||
|
const { appTitle } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 项目配置文件
|
* @description 项目配置文件
|
||||||
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
||||||
*/
|
*/
|
||||||
export const overridesPreferences = defineOverridesPreferences({
|
export const overridesPreferences = defineOverridesPreferences({
|
||||||
// overrides
|
// overrides
|
||||||
|
app: {
|
||||||
|
name: appTitle,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { preferences } from '@vben/preferences';
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
import { getAllMenus } from '#/apis';
|
import { getAllMenus } from '#/api';
|
||||||
import { BasicLayout, IFrameView } from '#/layouts';
|
import { BasicLayout, IFrameView } from '#/layouts';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
import type { RouteRecordName, RouteRecordRaw } from 'vue-router';
|
import type { RouteRecordName, RouteRecordRaw } from 'vue-router';
|
||||||
|
|
||||||
import { createRouter, createWebHashHistory } from 'vue-router';
|
import {
|
||||||
|
createRouter,
|
||||||
|
createWebHashHistory,
|
||||||
|
createWebHistory,
|
||||||
|
} from 'vue-router';
|
||||||
|
|
||||||
import { traverseTreeValues } from '@vben/utils';
|
import { traverseTreeValues } from '@vben/utils';
|
||||||
|
|
||||||
|
@ -11,11 +15,14 @@ import { routes } from './routes';
|
||||||
* @zh_CN 创建vue-router实例
|
* @zh_CN 创建vue-router实例
|
||||||
*/
|
*/
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHashHistory(import.meta.env.VITE_PUBLIC_PATH),
|
history:
|
||||||
|
import.meta.env.VITE_ROUTER_HISTORY === 'hash'
|
||||||
|
? createWebHashHistory(import.meta.env.VITE_BASE)
|
||||||
|
: createWebHistory(import.meta.env.VITE_BASE),
|
||||||
// 应该添加到路由的初始路由列表。
|
// 应该添加到路由的初始路由列表。
|
||||||
routes,
|
routes,
|
||||||
scrollBehavior: () => ({ left: 0, top: 0 }),
|
scrollBehavior: () => ({ left: 0, top: 0 }),
|
||||||
// 是否应该禁止尾部斜杠。默认为假
|
// 是否应该禁止尾部斜杠。
|
||||||
// strict: true,
|
// strict: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,10 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
path: '/',
|
path: '/',
|
||||||
redirect: '/analytics',
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Analytics',
|
name: 'Analytics',
|
||||||
path: 'analytics',
|
path: '/analytics',
|
||||||
component: () => import('#/views/dashboard/analytics/index.vue'),
|
component: () => import('#/views/dashboard/analytics/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
affixTab: true,
|
affixTab: true,
|
||||||
|
@ -27,7 +26,7 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Workspace',
|
name: 'Workspace',
|
||||||
path: 'workspace',
|
path: '/workspace',
|
||||||
component: () => import('#/views/dashboard/workspace/index.vue'),
|
component: () => import('#/views/dashboard/workspace/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: $t('page.dashboard.workspace'),
|
title: $t('page.dashboard.workspace'),
|
||||||
|
|
|
@ -14,7 +14,6 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
name: 'Demos',
|
name: 'Demos',
|
||||||
path: '/demos',
|
path: '/demos',
|
||||||
redirect: '/demos/access',
|
|
||||||
children: [
|
children: [
|
||||||
// 权限控制
|
// 权限控制
|
||||||
{
|
{
|
||||||
|
@ -22,13 +21,12 @@ const routes: RouteRecordRaw[] = [
|
||||||
icon: 'mdi:shield-key-outline',
|
icon: 'mdi:shield-key-outline',
|
||||||
title: $t('page.demos.access.frontendPermissions'),
|
title: $t('page.demos.access.frontendPermissions'),
|
||||||
},
|
},
|
||||||
name: 'Access',
|
name: 'AccessDemos',
|
||||||
path: 'access',
|
path: '/demos/access',
|
||||||
redirect: '/demos/access/page-control',
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'AccessPageControl',
|
name: 'AccessPageControlDemo',
|
||||||
path: 'page-control',
|
path: '/demos/access/page-control',
|
||||||
component: () => import('#/views/demos/access/index.vue'),
|
component: () => import('#/views/demos/access/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'mdi:page-previous-outline',
|
icon: 'mdi:page-previous-outline',
|
||||||
|
@ -36,8 +34,8 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'AccessButtonControl',
|
name: 'AccessButtonControlDemo',
|
||||||
path: 'button-control',
|
path: '/demos/access/button-control',
|
||||||
component: () => import('#/views/demos/access/button-control.vue'),
|
component: () => import('#/views/demos/access/button-control.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'mdi:button-cursor',
|
icon: 'mdi:button-cursor',
|
||||||
|
@ -45,8 +43,8 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'AccessMenuVisible403',
|
name: 'AccessMenuVisible403Demo',
|
||||||
path: 'menu-visible-403',
|
path: '/demos/access/menu-visible-403',
|
||||||
component: () =>
|
component: () =>
|
||||||
import('#/views/demos/access/menu-visible-403.vue'),
|
import('#/views/demos/access/menu-visible-403.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
|
@ -57,8 +55,8 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'AccessSuperVisible',
|
name: 'AccessSuperVisibleDemo',
|
||||||
path: 'super-visible',
|
path: '/demos/access/super-visible',
|
||||||
component: () => import('#/views/demos/access/super-visible.vue'),
|
component: () => import('#/views/demos/access/super-visible.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
authority: ['super'],
|
authority: ['super'],
|
||||||
|
@ -67,8 +65,8 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'AccessAdminVisible',
|
name: 'AccessAdminVisibleDemo',
|
||||||
path: 'admin-visible',
|
path: '/demos/access/admin-visible',
|
||||||
component: () => import('#/views/demos/access/admin-visible.vue'),
|
component: () => import('#/views/demos/access/admin-visible.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
authority: ['admin'],
|
authority: ['admin'],
|
||||||
|
@ -77,8 +75,8 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'AccessUserVisible',
|
name: 'AccessUserVisibleDemo',
|
||||||
path: 'user-visible',
|
path: '/demos/access/user-visible',
|
||||||
component: () => import('#/views/demos/access/user-visible.vue'),
|
component: () => import('#/views/demos/access/user-visible.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
authority: ['user'],
|
authority: ['user'],
|
||||||
|
@ -94,13 +92,39 @@ const routes: RouteRecordRaw[] = [
|
||||||
icon: 'mdi:feature-highlight',
|
icon: 'mdi:feature-highlight',
|
||||||
title: $t('page.demos.features.title'),
|
title: $t('page.demos.features.title'),
|
||||||
},
|
},
|
||||||
name: 'Features',
|
name: 'FeaturesDemos',
|
||||||
path: 'features',
|
path: '/demos/features',
|
||||||
redirect: '/demos/features/tabs',
|
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
name: 'LoginExpiredDemo',
|
||||||
|
path: '/demos/features/login-expired',
|
||||||
|
component: () =>
|
||||||
|
import('#/views/demos/features/login-expired/index.vue'),
|
||||||
|
meta: {
|
||||||
|
icon: 'mdi:encryption-expiration',
|
||||||
|
title: $t('page.demos.features.loginExpired'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'IconsDemo',
|
||||||
|
path: '/demos/features/icons',
|
||||||
|
component: () => import('#/views/demos/features/icons/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: $t('page.demos.features.icons'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'WatermarkDemo',
|
||||||
|
path: '/demos/features/watermark',
|
||||||
|
component: () =>
|
||||||
|
import('#/views/demos/features/watermark/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: $t('page.demos.features.watermark'),
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'FeatureTabsDemo',
|
name: 'FeatureTabsDemo',
|
||||||
path: 'tabs',
|
path: '/demos/features/tabs',
|
||||||
component: () => import('#/views/demos/features/tabs/index.vue'),
|
component: () => import('#/views/demos/features/tabs/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'lucide:app-window',
|
icon: 'lucide:app-window',
|
||||||
|
@ -109,7 +133,7 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'FeatureTabDetailDemo',
|
name: 'FeatureTabDetailDemo',
|
||||||
path: 'tabs/detail/:id',
|
path: '/demos/features/tabs/detail/:id',
|
||||||
component: () =>
|
component: () =>
|
||||||
import('#/views/demos/features/tabs/tab-detail.vue'),
|
import('#/views/demos/features/tabs/tab-detail.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
|
@ -120,19 +144,19 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'HideChildrenInMenuParent',
|
name: 'HideChildrenInMenuParentDemo',
|
||||||
path: 'hide-menu-children',
|
path: '/demos/features/hide-menu-children',
|
||||||
component: () =>
|
component: () =>
|
||||||
import('#/views/demos/features/hide-menu-children/parent.vue'),
|
import('#/views/demos/features/hide-menu-children/parent.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
hideChildrenInMenu: true,
|
hideChildrenInMenu: true,
|
||||||
icon: 'ic:round-menu',
|
icon: 'ic:round-menu',
|
||||||
title: 'page.demos.features.hideChildrenInMenu',
|
title: $t('page.demos.features.hideChildrenInMenu'),
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'HideChildrenInMenuChildren',
|
name: 'HideChildrenInMenuChildrenDemo',
|
||||||
path: 'hide-children-in-menu',
|
path: '/demos/features/hide-menu-children/children',
|
||||||
component: () =>
|
component: () =>
|
||||||
import(
|
import(
|
||||||
'#/views/demos/features/hide-menu-children/children.vue'
|
'#/views/demos/features/hide-menu-children/children.vue'
|
||||||
|
@ -140,31 +164,20 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'LoginExpired',
|
|
||||||
path: 'login-expired',
|
|
||||||
component: () =>
|
|
||||||
import('#/views/demos/features/login-expired/index.vue'),
|
|
||||||
meta: {
|
|
||||||
icon: 'mdi:encryption-expiration',
|
|
||||||
title: $t('page.demos.features.loginExpired'),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// 面包屑导航
|
// 面包屑导航
|
||||||
{
|
{
|
||||||
name: 'BreadcrumbDemos',
|
name: 'BreadcrumbDemos',
|
||||||
path: 'breadcrumb',
|
path: '/demos/breadcrumb',
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'lucide:navigation',
|
icon: 'lucide:navigation',
|
||||||
title: $t('page.demos.breadcrumb.navigation'),
|
title: $t('page.demos.breadcrumb.navigation'),
|
||||||
},
|
},
|
||||||
redirect: '/demos/breadcrumb/lateral',
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'BreadcrumbLateral',
|
name: 'BreadcrumbLateralDemo',
|
||||||
path: 'lateral',
|
path: '/demos/breadcrumb/lateral',
|
||||||
component: () => import('#/views/demos/breadcrumb/lateral.vue'),
|
component: () => import('#/views/demos/breadcrumb/lateral.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'lucide:navigation',
|
icon: 'lucide:navigation',
|
||||||
|
@ -172,8 +185,8 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'BreadcrumbLateralDetail',
|
name: 'BreadcrumbLateralDetailDemo',
|
||||||
path: 'lateral-detail',
|
path: '/demos/breadcrumb/lateral-detail',
|
||||||
component: () =>
|
component: () =>
|
||||||
import('#/views/demos/breadcrumb/lateral-detail.vue'),
|
import('#/views/demos/breadcrumb/lateral-detail.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
|
@ -183,17 +196,16 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'BreadcrumbLevel',
|
name: 'BreadcrumbLevelDemo',
|
||||||
path: 'level',
|
path: '/demos/breadcrumb/level',
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'lucide:navigation',
|
icon: 'lucide:navigation',
|
||||||
title: $t('page.demos.breadcrumb.level'),
|
title: $t('page.demos.breadcrumb.level'),
|
||||||
},
|
},
|
||||||
redirect: '/demos/breadcrumb/level/detail',
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'BreadcrumbLevelDetail',
|
name: 'BreadcrumbLevelDetailDemo',
|
||||||
path: 'detail',
|
path: '/demos/breadcrumb/level/detail',
|
||||||
component: () =>
|
component: () =>
|
||||||
import('#/views/demos/breadcrumb/level-detail.vue'),
|
import('#/views/demos/breadcrumb/level-detail.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
|
@ -210,13 +222,12 @@ const routes: RouteRecordRaw[] = [
|
||||||
icon: 'mdi:lightbulb-error-outline',
|
icon: 'mdi:lightbulb-error-outline',
|
||||||
title: $t('page.demos.fallback.title'),
|
title: $t('page.demos.fallback.title'),
|
||||||
},
|
},
|
||||||
name: 'Fallback',
|
name: 'FallbackDemos',
|
||||||
path: 'fallback',
|
path: '/demos/fallback',
|
||||||
redirect: '/demos/fallback/403',
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Fallback403',
|
name: 'Fallback403Demo',
|
||||||
path: '403',
|
path: '/demos/fallback/403',
|
||||||
component: () => import('#/views/_core/fallback/forbidden.vue'),
|
component: () => import('#/views/_core/fallback/forbidden.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'mdi:do-not-disturb-alt',
|
icon: 'mdi:do-not-disturb-alt',
|
||||||
|
@ -224,8 +235,8 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Fallback404',
|
name: 'Fallback404Demo',
|
||||||
path: '404',
|
path: '/demos/fallback/404',
|
||||||
component: () => import('#/views/_core/fallback/not-found.vue'),
|
component: () => import('#/views/_core/fallback/not-found.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'mdi:table-off',
|
icon: 'mdi:table-off',
|
||||||
|
@ -233,8 +244,8 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Fallback500',
|
name: 'Fallback500Demo',
|
||||||
path: '500',
|
path: '/demos/fallback/500',
|
||||||
component: () =>
|
component: () =>
|
||||||
import('#/views/_core/fallback/internal-error.vue'),
|
import('#/views/_core/fallback/internal-error.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
|
@ -243,8 +254,8 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'FallbackOffline',
|
name: 'FallbackOfflineDemo',
|
||||||
path: 'offline',
|
path: '/demos/fallback/offline',
|
||||||
component: () => import('#/views/_core/fallback/offline.vue'),
|
component: () => import('#/views/_core/fallback/offline.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'mdi:offline',
|
icon: 'mdi:offline',
|
||||||
|
@ -261,14 +272,13 @@ const routes: RouteRecordRaw[] = [
|
||||||
icon: 'lucide:circle-dot',
|
icon: 'lucide:circle-dot',
|
||||||
title: $t('page.demos.badge.title'),
|
title: $t('page.demos.badge.title'),
|
||||||
},
|
},
|
||||||
name: 'BadgeDemo',
|
name: 'BadgeDemos',
|
||||||
path: 'badge',
|
path: '/demos/badge',
|
||||||
redirect: '/demos/badge/dot',
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'BadgeDotDemo',
|
name: 'BadgeDotDemo',
|
||||||
component: () => import('#/views/demos/badge/index.vue'),
|
component: () => import('#/views/demos/badge/index.vue'),
|
||||||
path: 'dot',
|
path: '/demos/badge/dot',
|
||||||
meta: {
|
meta: {
|
||||||
badgeType: 'dot',
|
badgeType: 'dot',
|
||||||
icon: 'lucide:square-dot',
|
icon: 'lucide:square-dot',
|
||||||
|
@ -278,7 +288,7 @@ const routes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
name: 'BadgeTextDemo',
|
name: 'BadgeTextDemo',
|
||||||
component: () => import('#/views/demos/badge/index.vue'),
|
component: () => import('#/views/demos/badge/index.vue'),
|
||||||
path: 'text',
|
path: '/demos/badge/text',
|
||||||
meta: {
|
meta: {
|
||||||
badge: '10',
|
badge: '10',
|
||||||
icon: 'lucide:square-dot',
|
icon: 'lucide:square-dot',
|
||||||
|
@ -288,7 +298,7 @@ const routes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
name: 'BadgeColorDemo',
|
name: 'BadgeColorDemo',
|
||||||
component: () => import('#/views/demos/badge/index.vue'),
|
component: () => import('#/views/demos/badge/index.vue'),
|
||||||
path: 'color',
|
path: '/demos/badge/color',
|
||||||
meta: {
|
meta: {
|
||||||
badge: 'Hot',
|
badge: 'Hot',
|
||||||
badgeVariants: 'destructive',
|
badgeVariants: 'destructive',
|
||||||
|
@ -298,28 +308,48 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
// 菜单激活图标
|
||||||
|
{
|
||||||
|
meta: {
|
||||||
|
activeIcon: 'fluent-emoji:radioactive',
|
||||||
|
icon: 'bi:radioactive',
|
||||||
|
title: $t('page.demos.activeIcon.title'),
|
||||||
|
},
|
||||||
|
name: 'ActiveIconDemos',
|
||||||
|
path: '/demos/active-icon',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'ActiveIconDemo',
|
||||||
|
component: () => import('#/views/demos/active-icon/index.vue'),
|
||||||
|
path: '/demos/active-icon/children',
|
||||||
|
meta: {
|
||||||
|
activeIcon: 'fluent-emoji:radioactive',
|
||||||
|
icon: 'bi:radioactive',
|
||||||
|
title: $t('page.demos.activeIcon.children'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
// 外部链接
|
// 外部链接
|
||||||
{
|
{
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'ic:round-settings-input-composite',
|
icon: 'ic:round-settings-input-composite',
|
||||||
title: $t('page.demos.outside.title'),
|
title: $t('page.demos.outside.title'),
|
||||||
},
|
},
|
||||||
name: 'Outside',
|
name: 'OutsideDemos',
|
||||||
path: 'outside',
|
path: '/demos/outside',
|
||||||
redirect: '/demos/outside/iframe',
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'iframe',
|
name: 'IframeDemos',
|
||||||
path: 'iframe',
|
path: '/demos/outside/iframe',
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'mdi:newspaper-variant-outline',
|
icon: 'mdi:newspaper-variant-outline',
|
||||||
title: $t('page.demos.outside.embedded'),
|
title: $t('page.demos.outside.embedded'),
|
||||||
},
|
},
|
||||||
redirect: '/demos/outside/iframe/vue-document',
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'VueDocument',
|
name: 'VueDocumentDemo',
|
||||||
path: 'vue-document',
|
path: '/demos/outside/iframe/vue-document',
|
||||||
component: IFrameView,
|
component: IFrameView,
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'logos:vue',
|
icon: 'logos:vue',
|
||||||
|
@ -329,8 +359,8 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Tailwindcss',
|
name: 'TailwindcssDemo',
|
||||||
path: 'tailwindcss',
|
path: '/demos/outside/iframe/tailwindcss',
|
||||||
component: IFrameView,
|
component: IFrameView,
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'devicon:tailwindcss',
|
icon: 'devicon:tailwindcss',
|
||||||
|
@ -342,17 +372,16 @@ const routes: RouteRecordRaw[] = [
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'ExternalLink',
|
name: 'ExternalLinkDemos',
|
||||||
path: 'external-link',
|
path: '/demos/outside/external-link',
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'mdi:newspaper-variant-multiple-outline',
|
icon: 'mdi:newspaper-variant-multiple-outline',
|
||||||
title: $t('page.demos.outside.externalLink'),
|
title: $t('page.demos.outside.externalLink'),
|
||||||
},
|
},
|
||||||
redirect: '/demos/outside/external-link/vite',
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Vite',
|
name: 'ViteDemo',
|
||||||
path: 'vite',
|
path: '/demos/outside/external-link/vite',
|
||||||
component: IFrameView,
|
component: IFrameView,
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'logos:vitejs',
|
icon: 'logos:vitejs',
|
||||||
|
@ -361,8 +390,8 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'VueUse',
|
name: 'VueUseDemo',
|
||||||
path: 'vue-use',
|
path: '/demos/outside/external-link/vue-use',
|
||||||
component: IFrameView,
|
component: IFrameView,
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'logos:vueuse',
|
icon: 'logos:vueuse',
|
||||||
|
@ -380,13 +409,12 @@ const routes: RouteRecordRaw[] = [
|
||||||
icon: 'ic:round-menu',
|
icon: 'ic:round-menu',
|
||||||
title: $t('page.demos.nested.title'),
|
title: $t('page.demos.nested.title'),
|
||||||
},
|
},
|
||||||
name: 'Nested',
|
name: 'NestedDemos',
|
||||||
path: 'nested',
|
path: '/demos/nested',
|
||||||
redirect: '/demos/nested/menu1',
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Menu1',
|
name: 'Menu1Demo',
|
||||||
path: 'menu1',
|
path: '/demos/nested/menu1',
|
||||||
component: () => import('#/views/demos/nested/menu-1.vue'),
|
component: () => import('#/views/demos/nested/menu-1.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'ic:round-menu',
|
icon: 'ic:round-menu',
|
||||||
|
@ -395,18 +423,17 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Menu2',
|
name: 'Menu2Demo',
|
||||||
path: 'menu2',
|
path: '/demos/nested/menu2',
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'ic:round-menu',
|
icon: 'ic:round-menu',
|
||||||
keepAlive: true,
|
keepAlive: true,
|
||||||
title: $t('page.demos.nested.menu2'),
|
title: $t('page.demos.nested.menu2'),
|
||||||
},
|
},
|
||||||
redirect: '/demos/nested/menu2/menu2-1',
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Menu21',
|
name: 'Menu21Demo',
|
||||||
path: 'menu2-1',
|
path: '/demos/nested/menu2/menu2-1',
|
||||||
component: () => import('#/views/demos/nested/menu-2-1.vue'),
|
component: () => import('#/views/demos/nested/menu-2-1.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'ic:round-menu',
|
icon: 'ic:round-menu',
|
||||||
|
@ -417,16 +444,15 @@ const routes: RouteRecordRaw[] = [
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Menu3',
|
name: 'Menu3Demo',
|
||||||
path: 'menu3',
|
path: '/demos/nested/menu3',
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'ic:round-menu',
|
icon: 'ic:round-menu',
|
||||||
title: $t('page.demos.nested.menu3'),
|
title: $t('page.demos.nested.menu3'),
|
||||||
},
|
},
|
||||||
redirect: '/demos/nested/menu3/menu3-1',
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Menu31',
|
name: 'Menu31Demo',
|
||||||
path: 'menu3-1',
|
path: 'menu3-1',
|
||||||
component: () => import('#/views/demos/nested/menu-3-1.vue'),
|
component: () => import('#/views/demos/nested/menu-3-1.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
|
@ -436,17 +462,16 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Menu32',
|
name: 'Menu32Demo',
|
||||||
path: 'menu3-2',
|
path: 'menu3-2',
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'ic:round-menu',
|
icon: 'ic:round-menu',
|
||||||
title: $t('page.demos.nested.menu3_2'),
|
title: $t('page.demos.nested.menu3_2'),
|
||||||
},
|
},
|
||||||
redirect: '/demos/nested/menu3/menu3-2/menu3-2-1',
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Menu321',
|
name: 'Menu321Demo',
|
||||||
path: 'menu3-2-1',
|
path: '/demos/nested/menu3/menu3-2/menu3-2-1',
|
||||||
component: () =>
|
component: () =>
|
||||||
import('#/views/demos/nested/menu-3-2-1.vue'),
|
import('#/views/demos/nested/menu-3-2-1.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
|
|
|
@ -17,11 +17,10 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
name: 'VbenProject',
|
name: 'VbenProject',
|
||||||
path: '/vben-admin',
|
path: '/vben-admin',
|
||||||
redirect: '/vben-admin/about',
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'VbenAbout',
|
name: 'VbenAbout',
|
||||||
path: 'about',
|
path: '/vben-admin/about',
|
||||||
component: () => import('#/views/_core/vben/about/index.vue'),
|
component: () => import('#/views/_core/vben/about/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
badgeType: 'dot',
|
badgeType: 'dot',
|
||||||
|
@ -32,7 +31,7 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'VbenDocument',
|
name: 'VbenDocument',
|
||||||
path: 'document',
|
path: '/vben-admin/document',
|
||||||
component: IFrameView,
|
component: IFrameView,
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'lucide:book-open-text',
|
icon: 'lucide:book-open-text',
|
||||||
|
@ -43,7 +42,7 @@ const routes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'VbenGithub',
|
name: 'VbenGithub',
|
||||||
path: 'github',
|
path: '/vben-admin/github',
|
||||||
component: IFrameView,
|
component: IFrameView,
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'mdi:github',
|
icon: 'mdi:github',
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { resetAllStores, useCoreAccessStore } from '@vben/stores';
|
||||||
import { notification } from 'ant-design-vue';
|
import { notification } from 'ant-design-vue';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
import { getAccessCodes, getUserInfo, login } from '#/apis';
|
import { getAccessCodes, getUserInfo, login } from '#/api';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
export const useAccessStore = defineStore('access', () => {
|
export const useAccessStore = defineStore('access', () => {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
|
defineOptions({ name: 'Fallback403Demo' });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
|
defineOptions({ name: 'Fallback500Demo' });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
|
defineOptions({ name: 'Fallback404Demo' });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
|
defineOptions({ name: 'FallbackOfflineDemo' });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -3,8 +3,6 @@ import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
|
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'AnalyticsTrends' });
|
|
||||||
|
|
||||||
const chartRef = ref<EchartsUIType>();
|
const chartRef = ref<EchartsUIType>();
|
||||||
const { renderEcharts } = useEcharts(chartRef);
|
const { renderEcharts } = useEcharts(chartRef);
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@ import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
|
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'AnalyticsVisitsData' });
|
|
||||||
|
|
||||||
const chartRef = ref<EchartsUIType>();
|
const chartRef = ref<EchartsUIType>();
|
||||||
const { renderEcharts } = useEcharts(chartRef);
|
const { renderEcharts } = useEcharts(chartRef);
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@ import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
|
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'AnalyticsVisitsSales' });
|
|
||||||
|
|
||||||
const chartRef = ref<EchartsUIType>();
|
const chartRef = ref<EchartsUIType>();
|
||||||
const { renderEcharts } = useEcharts(chartRef);
|
const { renderEcharts } = useEcharts(chartRef);
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@ import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
|
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'AnalyticsVisitsSource' });
|
|
||||||
|
|
||||||
const chartRef = ref<EchartsUIType>();
|
const chartRef = ref<EchartsUIType>();
|
||||||
const { renderEcharts } = useEcharts(chartRef);
|
const { renderEcharts } = useEcharts(chartRef);
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@ import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
|
import { EchartsUI, type EchartsUIType, useEcharts } from '@vben/chart-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'AnalyticsVisits' });
|
|
||||||
|
|
||||||
const chartRef = ref<EchartsUIType>();
|
const chartRef = ref<EchartsUIType>();
|
||||||
const { renderEcharts } = useEcharts(chartRef);
|
const { renderEcharts } = useEcharts(chartRef);
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,6 @@ import AnalyticsVisitsData from './analytics-visits-data.vue';
|
||||||
import AnalyticsVisitsSales from './analytics-visits-sales.vue';
|
import AnalyticsVisitsSales from './analytics-visits-sales.vue';
|
||||||
import AnalyticsVisitsSource from './analytics-visits-source.vue';
|
import AnalyticsVisitsSource from './analytics-visits-source.vue';
|
||||||
|
|
||||||
defineOptions({ name: 'Analytics' });
|
|
||||||
|
|
||||||
const overviewItems: AnalysisOverviewItem[] = [
|
const overviewItems: AnalysisOverviewItem[] = [
|
||||||
{
|
{
|
||||||
icon: SvgCardIcon,
|
icon: SvgCardIcon,
|
||||||
|
|
|
@ -22,8 +22,6 @@ import { useAccessStore } from '#/store';
|
||||||
|
|
||||||
import AnalyticsVisitsSource from '../analytics/analytics-visits-source.vue';
|
import AnalyticsVisitsSource from '../analytics/analytics-visits-source.vue';
|
||||||
|
|
||||||
defineOptions({ name: 'Workspace' });
|
|
||||||
|
|
||||||
const accessStore = useAccessStore();
|
const accessStore = useAccessStore();
|
||||||
|
|
||||||
const projectItems: WorkbenchProjectItem[] = [
|
const projectItems: WorkbenchProjectItem[] = [
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'AccessAdminVisible' });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -9,8 +9,6 @@ import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
import { resetAllStores, useAccessStore } from '#/store';
|
import { resetAllStores, useAccessStore } from '#/store';
|
||||||
|
|
||||||
defineOptions({ name: 'AccessButtonControl' });
|
|
||||||
|
|
||||||
const accounts: Record<string, LoginAndRegisterParams> = {
|
const accounts: Record<string, LoginAndRegisterParams> = {
|
||||||
admin: {
|
admin: {
|
||||||
password: '123456',
|
password: '123456',
|
||||||
|
|
|
@ -9,8 +9,6 @@ import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
import { resetAllStores, useAccessStore } from '#/store';
|
import { resetAllStores, useAccessStore } from '#/store';
|
||||||
|
|
||||||
defineOptions({ name: 'Access' });
|
|
||||||
|
|
||||||
const accounts: Record<string, LoginAndRegisterParams> = {
|
const accounts: Record<string, LoginAndRegisterParams> = {
|
||||||
admin: {
|
admin: {
|
||||||
password: '123456',
|
password: '123456',
|
||||||
|
@ -51,7 +49,9 @@ async function handleToggleAccessMode() {
|
||||||
resetAllStores();
|
resetAllStores();
|
||||||
|
|
||||||
await accessStore.authLogin(accounts.super, async () => {
|
await accessStore.authLogin(accounts.super, async () => {
|
||||||
router.go(0);
|
setTimeout(() => {
|
||||||
|
router.go(0);
|
||||||
|
}, 150);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'AccessMenuVisible403' });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'AccessSuperVisible' });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'AccessUserVisible' });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Fallback
|
||||||
|
description="用于菜单激活显示不同的图标"
|
||||||
|
status="coming-soon"
|
||||||
|
title="激活图标示例"
|
||||||
|
/>
|
||||||
|
</template>
|
|
@ -1,7 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'Menu321' });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -5,8 +5,6 @@ import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
defineOptions({ name: 'BreadcrumbLateralDetail' });
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,10 @@ import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
defineOptions({ name: 'BreadcrumbLateral' });
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
function details() {
|
function details() {
|
||||||
router.push({ name: 'BreadcrumbLateralDetail' });
|
router.push({ name: 'BreadcrumbLateralDetailDemo' });
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'BreadcrumbLevelDetail' });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'HideMenuChildren' });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {
|
||||||
|
MdiGithub,
|
||||||
|
MdiGoogle,
|
||||||
|
MdiKeyboardEsc,
|
||||||
|
MdiQqchat,
|
||||||
|
MdiWechat,
|
||||||
|
SvgAvatar1Icon,
|
||||||
|
SvgAvatar2Icon,
|
||||||
|
SvgAvatar3Icon,
|
||||||
|
SvgAvatar4Icon,
|
||||||
|
SvgBellIcon,
|
||||||
|
SvgCakeIcon,
|
||||||
|
SvgCardIcon,
|
||||||
|
SvgDownloadIcon,
|
||||||
|
} from '@vben/icons';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-5">
|
||||||
|
<div class="card-box p-5">
|
||||||
|
<h1 class="text-xl font-semibold">图标</h1>
|
||||||
|
<div class="text-foreground/80 mt-2">
|
||||||
|
图标可在
|
||||||
|
<a
|
||||||
|
class="text-primary"
|
||||||
|
href="https://icon-sets.iconify.design/"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
Iconify
|
||||||
|
</a>
|
||||||
|
中查找,支持多种图标库,如 Material Design, Font Awesome, Jam Icons 等。
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-box mt-5 p-5">
|
||||||
|
<div class="mb-3 text-lg font-semibold">Iconify</div>
|
||||||
|
<div class="flex items-center gap-5">
|
||||||
|
<MdiGithub class="size-8" />
|
||||||
|
<MdiGoogle class="size-8 text-red-500" />
|
||||||
|
<MdiQqchat class="size-8 text-green-500" />
|
||||||
|
<MdiWechat class="size-8" />
|
||||||
|
<MdiKeyboardEsc class="size-8" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-box mt-5 p-5">
|
||||||
|
<div class="mb-3 text-lg font-semibold">Svg Icons</div>
|
||||||
|
<div class="flex items-center gap-5">
|
||||||
|
<SvgAvatar1Icon class="size-8" />
|
||||||
|
<SvgAvatar2Icon class="size-8 text-red-500" />
|
||||||
|
<SvgAvatar3Icon class="size-8 text-green-500" />
|
||||||
|
<SvgAvatar4Icon class="size-8" />
|
||||||
|
<SvgCakeIcon class="size-8" />
|
||||||
|
<SvgBellIcon class="size-8" />
|
||||||
|
<SvgCardIcon class="size-8" />
|
||||||
|
<SvgDownloadIcon class="size-8" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -5,9 +5,7 @@ import { preferences, updatePreferences } from '@vben/preferences';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
import { getMockStatus } from '#/apis';
|
import { getMockStatus } from '#/api';
|
||||||
|
|
||||||
defineOptions({ name: 'LoginExpired' });
|
|
||||||
|
|
||||||
async function handleClick(type: LoginExpiredModeType) {
|
async function handleClick(type: LoginExpiredModeType) {
|
||||||
const loginExpiredMode = preferences.app.loginExpiredMode;
|
const loginExpiredMode = preferences.app.loginExpiredMode;
|
||||||
|
|
|
@ -6,8 +6,6 @@ import { useTabs } from '@vben/hooks';
|
||||||
|
|
||||||
import { Input as AInput, Button } from 'ant-design-vue';
|
import { Input as AInput, Button } from 'ant-design-vue';
|
||||||
|
|
||||||
defineOptions({ name: 'FeatureTabsDemo' });
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const newTabTitle = ref('');
|
const newTabTitle = ref('');
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,6 @@ import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import { useTabs } from '@vben/hooks';
|
import { useTabs } from '@vben/hooks';
|
||||||
|
|
||||||
defineOptions({ name: 'FeatureTabDetailDemo' });
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
const { setTabTitle } = useTabs();
|
const { setTabTitle } = useTabs();
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useWatermark } from '@vben/hooks';
|
||||||
|
|
||||||
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
|
const { destroyWatermark, updateWatermark } = useWatermark();
|
||||||
|
|
||||||
|
async function createWaterMark() {
|
||||||
|
await updateWatermark({
|
||||||
|
advancedStyle: {
|
||||||
|
colorStops: [
|
||||||
|
{
|
||||||
|
color: 'red',
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'blue',
|
||||||
|
offset: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
type: 'linear',
|
||||||
|
},
|
||||||
|
content: 'hello my watermark',
|
||||||
|
globalAlpha: 0.5,
|
||||||
|
gridLayoutOptions: {
|
||||||
|
cols: 2,
|
||||||
|
gap: [20, 20],
|
||||||
|
matrix: [
|
||||||
|
[1, 0],
|
||||||
|
[0, 1],
|
||||||
|
],
|
||||||
|
rows: 2,
|
||||||
|
},
|
||||||
|
height: 200,
|
||||||
|
layout: 'grid',
|
||||||
|
rotate: 22,
|
||||||
|
width: 200,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-5">
|
||||||
|
<div class="card-box p-5">
|
||||||
|
<h1 class="text-xl font-semibold">水印</h1>
|
||||||
|
<div class="text-foreground/80 mt-2">
|
||||||
|
水印使用了
|
||||||
|
<a
|
||||||
|
class="text-primary"
|
||||||
|
href="https://zhensherlock.github.io/watermark-js-plus/"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
watermark-js-plus
|
||||||
|
</a>
|
||||||
|
开源插件,详细配置可见插件配置。
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-box mt-5 p-5">
|
||||||
|
<div class="mb-3 flex gap-3 text-lg font-semibold">
|
||||||
|
<Button type="primary" @click="createWaterMark()">创建水印</Button>
|
||||||
|
<Button danger @click="destroyWatermark">移除水印</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -1,9 +1,10 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'Menu1' });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Fallback status="coming-soon" />
|
<div>
|
||||||
|
<Fallback status="coming-soon" />
|
||||||
|
<input />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'Menu21' });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Fallback status="coming-soon" />
|
<div>
|
||||||
|
<Fallback status="coming-soon" />
|
||||||
|
<input />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'Menu31' });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Fallback status="coming-soon" />
|
<div>
|
||||||
|
<Fallback status="coming-soon" />
|
||||||
|
<input />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Fallback } from '@vben/common-ui';
|
import { Fallback } from '@vben/common-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'Menu321' });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Fallback status="coming-soon" />
|
<div>
|
||||||
|
<Fallback status="coming-soon" />
|
||||||
|
<input />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
"extends": "@vben/tsconfig/node.json",
|
"extends": "@vben/tsconfig/node.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"composite": true,
|
"composite": true,
|
||||||
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||||
"noEmit": false
|
"noEmit": false
|
||||||
},
|
},
|
||||||
"include": ["vite.config.mts"]
|
"include": ["vite.config.mts"]
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
} from '@vben/vite-config';
|
} from '@vben/vite-config';
|
||||||
|
|
||||||
export default defineConfig(async () => {
|
export default defineConfig(async () => {
|
||||||
const { appTitle, port, ...envConfig } = await loadAndConvertEnv();
|
const { appTitle, base, port, ...envConfig } = await loadAndConvertEnv();
|
||||||
return {
|
return {
|
||||||
application: {
|
application: {
|
||||||
...envConfig,
|
...envConfig,
|
||||||
|
@ -16,13 +16,14 @@ export default defineConfig(async () => {
|
||||||
pwaOptions: getDefaultPwaOptions(appTitle),
|
pwaOptions: getDefaultPwaOptions(appTitle),
|
||||||
},
|
},
|
||||||
vite: {
|
vite: {
|
||||||
|
base,
|
||||||
server: {
|
server: {
|
||||||
port,
|
port,
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (path) => path.replace(/^\/api/, ''),
|
rewrite: (path) => path.replace(/^\/api/, ''),
|
||||||
// 代理目标地址 - backend-mock 项目
|
// mock代理目标地址
|
||||||
target: 'http://localhost:5320/api',
|
target: 'http://localhost:5320/api',
|
||||||
ws: true,
|
ws: true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -28,25 +28,25 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"eslint-config-turbo": "^2.0.9",
|
"eslint-config-turbo": "^2.0.9",
|
||||||
"eslint-plugin-command": "^0.2.3"
|
"eslint-plugin-command": "^0.2.3",
|
||||||
|
"eslint-plugin-import-x": "^3.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.7.0",
|
"@eslint/js": "^9.8.0",
|
||||||
"@types/eslint": "^9.6.0",
|
"@types/eslint": "^9.6.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.17.0",
|
"@typescript-eslint/eslint-plugin": "^7.17.0",
|
||||||
"@typescript-eslint/parser": "^7.17.0",
|
"@typescript-eslint/parser": "^7.17.0",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^9.8.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-eslint-comments": "^3.2.0",
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||||
"eslint-plugin-i": "^2.29.1",
|
|
||||||
"eslint-plugin-jsdoc": "^48.8.3",
|
"eslint-plugin-jsdoc": "^48.8.3",
|
||||||
"eslint-plugin-jsonc": "^2.16.0",
|
"eslint-plugin-jsonc": "^2.16.0",
|
||||||
"eslint-plugin-n": "^17.9.0",
|
"eslint-plugin-n": "^17.10.1",
|
||||||
"eslint-plugin-no-only-tests": "^3.1.0",
|
"eslint-plugin-no-only-tests": "^3.1.0",
|
||||||
"eslint-plugin-perfectionist": "^3.0.0",
|
"eslint-plugin-perfectionist": "^3.0.0",
|
||||||
"eslint-plugin-prettier": "^5.2.1",
|
"eslint-plugin-prettier": "^5.2.1",
|
||||||
"eslint-plugin-regexp": "^2.6.0",
|
"eslint-plugin-regexp": "^2.6.0",
|
||||||
"eslint-plugin-unicorn": "^54.0.0",
|
"eslint-plugin-unicorn": "^55.0.0",
|
||||||
"eslint-plugin-unused-imports": "^4.0.1",
|
"eslint-plugin-unused-imports": "^4.0.1",
|
||||||
"eslint-plugin-vitest": "^0.5.4",
|
"eslint-plugin-vitest": "^0.5.4",
|
||||||
"eslint-plugin-vue": "^9.27.0",
|
"eslint-plugin-vue": "^9.27.0",
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
import type { Linter } from 'eslint';
|
import type { Linter } from 'eslint';
|
||||||
|
|
||||||
export async function importPluginConfig(): Promise<Linter.FlatConfig[]> {
|
import * as pluginImport from 'eslint-plugin-import-x';
|
||||||
const [pluginImport] = await Promise.all([
|
|
||||||
// @ts-expect-error - no types
|
|
||||||
import('eslint-plugin-i'),
|
|
||||||
] as const);
|
|
||||||
|
|
||||||
|
export async function importPluginConfig(): Promise<Linter.Config[]> {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
plugins: {
|
plugins: {
|
||||||
|
// @ts-expect-error - This is a dynamic import
|
||||||
import: pluginImport,
|
import: pluginImport,
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
"stylelint-scss": "^6.4.1"
|
"stylelint-scss": "^6.4.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"postcss": "^8.4.39",
|
"postcss": "^8.4.40",
|
||||||
"postcss-html": "^1.7.0",
|
"postcss-html": "^1.7.0",
|
||||||
"postcss-scss": "^4.0.9",
|
"postcss-scss": "^4.0.9",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
|
|
|
@ -37,6 +37,6 @@
|
||||||
"pkg-types": "^1.1.3",
|
"pkg-types": "^1.1.3",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"rimraf": "^6.0.1",
|
"rimraf": "^6.0.1",
|
||||||
"zx": "^7.2.3"
|
"zx": "^8.1.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,17 +46,17 @@
|
||||||
"tailwindcss": "^3.4.3"
|
"tailwindcss": "^3.4.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iconify/json": "^2.2.230",
|
"@iconify/json": "^2.2.231",
|
||||||
"@iconify/tailwind": "^1.1.1",
|
"@iconify/tailwind": "^1.1.1",
|
||||||
"@tailwindcss/nesting": "0.0.0-insiders.565cd3e",
|
"@tailwindcss/nesting": "0.0.0-insiders.565cd3e",
|
||||||
"@tailwindcss/typography": "^0.5.13",
|
"@tailwindcss/typography": "^0.5.13",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.19",
|
||||||
"cssnano": "^7.0.4",
|
"cssnano": "^7.0.4",
|
||||||
"postcss": "^8.4.39",
|
"postcss": "^8.4.40",
|
||||||
"postcss-antd-fixes": "^0.2.0",
|
"postcss-antd-fixes": "^0.2.0",
|
||||||
"postcss-import": "^16.1.0",
|
"postcss-import": "^16.1.0",
|
||||||
"postcss-preset-env": "^9.6.0",
|
"postcss-preset-env": "^9.6.0",
|
||||||
"tailwindcss": "^3.4.6",
|
"tailwindcss": "^3.4.7",
|
||||||
"tailwindcss-animate": "^1.0.7"
|
"tailwindcss-animate": "^1.0.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -20,6 +20,6 @@
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vben/types": "workspace:*",
|
"@vben/types": "workspace:*",
|
||||||
"vite": "^5.3.4"
|
"vite": "^5.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,20 +34,20 @@
|
||||||
"nitropack": "^2.9.7",
|
"nitropack": "^2.9.7",
|
||||||
"resolve.exports": "^2.0.2",
|
"resolve.exports": "^2.0.2",
|
||||||
"vite-plugin-lib-inject-css": "^2.1.1",
|
"vite-plugin-lib-inject-css": "^2.1.1",
|
||||||
"vite-plugin-pwa": "^0.20.0",
|
"vite-plugin-pwa": "^0.20.1",
|
||||||
"vite-plugin-vue-devtools": "^7.3.6"
|
"vite-plugin-vue-devtools": "^7.3.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/html-minifier-terser": "^7.0.2",
|
"@types/html-minifier-terser": "^7.0.2",
|
||||||
"@vben/node-utils": "workspace:*",
|
"@vben/node-utils": "workspace:*",
|
||||||
"@vitejs/plugin-vue": "^5.0.5",
|
"@vitejs/plugin-vue": "^5.1.1",
|
||||||
"@vitejs/plugin-vue-jsx": "^4.0.0",
|
"@vitejs/plugin-vue-jsx": "^4.0.0",
|
||||||
"dayjs": "^1.11.12",
|
"dayjs": "^1.11.12",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"rollup": "^4.19.0",
|
"rollup": "^4.19.1",
|
||||||
"rollup-plugin-visualizer": "^5.12.0",
|
"rollup-plugin-visualizer": "^5.12.0",
|
||||||
"sass": "^1.77.8",
|
"sass": "^1.77.8",
|
||||||
"vite": "^5.3.4",
|
"vite": "^5.3.5",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-dts": "4.0.0-beta.1",
|
"vite-plugin-dts": "4.0.0-beta.1",
|
||||||
"vite-plugin-html": "^3.2.2"
|
"vite-plugin-html": "^3.2.2"
|
||||||
|
|
|
@ -94,7 +94,7 @@ function createCssOptions(injectGlobalScss = true) {
|
||||||
const relativePath = relative(root, filepath);
|
const relativePath = relative(root, filepath);
|
||||||
// apps下的包注入全局样式
|
// apps下的包注入全局样式
|
||||||
if (relativePath.startsWith('apps/')) {
|
if (relativePath.startsWith('apps/')) {
|
||||||
return `@import "@vben/styles/global";\n${content}`;
|
return `@import (reference) "@vben/styles/global";\n${content}`;
|
||||||
}
|
}
|
||||||
return content;
|
return content;
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,16 +7,16 @@ const isDevelopment = process.env.NODE_ENV === 'development';
|
||||||
const getDefaultPwaOptions = (name: string): Partial<PwaPluginOptions> => ({
|
const getDefaultPwaOptions = (name: string): Partial<PwaPluginOptions> => ({
|
||||||
manifest: {
|
manifest: {
|
||||||
description:
|
description:
|
||||||
'Vue Vben Admin is a modern admin dashboard template based on Vue 3. ',
|
'Vben Admin is a modern admin dashboard template based on Vue 3. ',
|
||||||
icons: [
|
icons: [
|
||||||
{
|
{
|
||||||
sizes: '192x192',
|
sizes: '192x192',
|
||||||
src: 'https://cdn.jsdelivr.net/npm/@vbenjs/static-source@0.1.3/source/pwa-icon-192.png',
|
src: 'https://unpkg.com/@vbenjs/static-source@0.1.5/source/pwa-icon-192.png',
|
||||||
type: 'image/png',
|
type: 'image/png',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sizes: '512x512',
|
sizes: '512x512',
|
||||||
src: 'https://cdn.jsdelivr.net/npm/@vbenjs/static-source@0.1.3/source/pwa-icon-512.png',
|
src: 'https://unpkg.com/@vbenjs/static-source@0.1.5/source/pwa-icon-512.png',
|
||||||
type: 'image/png',
|
type: 'image/png',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { join } from 'node:path';
|
import { join } from 'node:path';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|
||||||
import { fs } from '@vben/node-utils';
|
import { fs, readPackageJSON } from '@vben/node-utils';
|
||||||
|
|
||||||
import { type PluginOption } from 'vite';
|
import { type PluginOption } from 'vite';
|
||||||
|
|
||||||
|
@ -15,8 +15,9 @@ async function viteInjectAppLoadingPlugin(
|
||||||
loadingTemplate = 'loading.html',
|
loadingTemplate = 'loading.html',
|
||||||
): Promise<PluginOption | undefined> {
|
): Promise<PluginOption | undefined> {
|
||||||
const loadingHtml = await getLoadingRawByHtmlTemplate(loadingTemplate);
|
const loadingHtml = await getLoadingRawByHtmlTemplate(loadingTemplate);
|
||||||
|
const { version } = await readPackageJSON(process.cwd());
|
||||||
const envRaw = isBuild ? 'prod' : 'dev';
|
const envRaw = isBuild ? 'prod' : 'dev';
|
||||||
const cacheName = `'${env.VITE_APP_NAMESPACE}-${envRaw}-preferences-theme'`;
|
const cacheName = `'${env.VITE_APP_NAMESPACE}-${version}-${envRaw}-preferences-theme'`;
|
||||||
|
|
||||||
// 获取缓存的主题
|
// 获取缓存的主题
|
||||||
// 保证黑暗主题下,刷新页面时,loading也是黑暗主题
|
// 保证黑暗主题下,刷新页面时,loading也是黑暗主题
|
||||||
|
|
|
@ -74,6 +74,7 @@ async function viteMetadataPlugin(
|
||||||
license,
|
license,
|
||||||
version,
|
version,
|
||||||
}),
|
}),
|
||||||
|
'import.meta.env.VITE_APP_VERSION': JSON.stringify(version),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -30,7 +30,7 @@ async function viteLicensePlugin(
|
||||||
handler: (_options: NormalizedOutputOptions, bundle: OutputBundle) => {
|
handler: (_options: NormalizedOutputOptions, bundle: OutputBundle) => {
|
||||||
const date = dateUtil().format('YYYY-MM-DD ');
|
const date = dateUtil().format('YYYY-MM-DD ');
|
||||||
const copyrightText = `/*!
|
const copyrightText = `/*!
|
||||||
* Vue Vben Admin
|
* Vben Admin
|
||||||
* Version: ${version}
|
* Version: ${version}
|
||||||
* Author: vben
|
* Author: vben
|
||||||
* Copyright (C) 2024 Vben
|
* Copyright (C) 2024 Vben
|
||||||
|
|
|
@ -56,24 +56,40 @@ async function loadAndConvertEnv(
|
||||||
match = 'VITE_',
|
match = 'VITE_',
|
||||||
confFiles = getConfFiles(),
|
confFiles = getConfFiles(),
|
||||||
): Promise<
|
): Promise<
|
||||||
{ appTitle: string; port: number } & Partial<ApplicationPluginOptions>
|
{
|
||||||
|
appTitle: string;
|
||||||
|
base: string;
|
||||||
|
port: number;
|
||||||
|
} & Partial<ApplicationPluginOptions>
|
||||||
> {
|
> {
|
||||||
const envConfig = await loadEnv(match, confFiles);
|
const envConfig = await loadEnv(match, confFiles);
|
||||||
const visualizer = envConfig.visualizer || '';
|
const {
|
||||||
const pwa = envConfig.pwa || '';
|
VITE_BASE,
|
||||||
const compress = envConfig.VITE_COMPRESS || '';
|
VITE_COMPRESS,
|
||||||
|
VITE_DEVTOOLS,
|
||||||
|
VITE_GLOB_APP_TITLE,
|
||||||
|
VITE_INJECT_APP_LOADING,
|
||||||
|
VITE_NITRO_MOCK,
|
||||||
|
VITE_PORT,
|
||||||
|
VITE_PWA,
|
||||||
|
VITE_VISUALIZER,
|
||||||
|
} = envConfig;
|
||||||
|
const compress = VITE_COMPRESS || '';
|
||||||
const compressTypes = compress
|
const compressTypes = compress
|
||||||
.split(',')
|
.split(',')
|
||||||
.filter((item) => item === 'brotli' || item === 'gzip');
|
.filter((item) => item === 'brotli' || item === 'gzip');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
appTitle: envConfig?.VITE_GLOB_APP_TITLE ?? 'Vben Admin',
|
appTitle: VITE_GLOB_APP_TITLE ?? 'Vben Admin',
|
||||||
|
base: VITE_BASE || '/',
|
||||||
compress: !!compress,
|
compress: !!compress,
|
||||||
compressTypes: compressTypes as ('brotli' | 'gzip')[],
|
compressTypes: compressTypes as ('brotli' | 'gzip')[],
|
||||||
nitroMock: !!envConfig.VITE_NITRO_MOCK,
|
devtools: VITE_DEVTOOLS === 'true',
|
||||||
port: Number(envConfig.VITE_PORT) || 5173,
|
injectAppLoading: VITE_INJECT_APP_LOADING === 'true',
|
||||||
pwa: !!pwa,
|
nitroMock: VITE_NITRO_MOCK === 'true',
|
||||||
visualizer: !!visualizer,
|
port: Number(VITE_PORT) || 5173,
|
||||||
|
pwa: VITE_PWA === 'true',
|
||||||
|
visualizer: VITE_VISUALIZER === 'true',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
25
package.json
25
package.json
|
@ -7,7 +7,8 @@
|
||||||
"turbo",
|
"turbo",
|
||||||
"vben",
|
"vben",
|
||||||
"vue vben admin",
|
"vue vben admin",
|
||||||
"vben admin pro",
|
"vue vben admin pro",
|
||||||
|
"vben admin",
|
||||||
"vben pro",
|
"vben pro",
|
||||||
"vue",
|
"vue",
|
||||||
"vue admin",
|
"vue admin",
|
||||||
|
@ -26,6 +27,8 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"bootstrap": "pnpm install",
|
"bootstrap": "pnpm install",
|
||||||
"build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 turbo build",
|
"build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 turbo build",
|
||||||
|
"preview": "turbo preview",
|
||||||
|
"build:analyze": "turbo build:analyze",
|
||||||
"build:docker": "./build-local-docker-image.sh",
|
"build:docker": "./build-local-docker-image.sh",
|
||||||
"changeset": "pnpm exec changeset",
|
"changeset": "pnpm exec changeset",
|
||||||
"check": "pnpm run check:dep && pnpm run check:circular && pnpm run check:type && pnpm run check:cspell",
|
"check": "pnpm run check:dep && pnpm run check:circular && pnpm run check:type && pnpm run check:cspell",
|
||||||
|
@ -35,9 +38,8 @@
|
||||||
"check:type": "turbo run typecheck",
|
"check:type": "turbo run typecheck",
|
||||||
"clean": "vsh clean",
|
"clean": "vsh clean",
|
||||||
"commit": "czg",
|
"commit": "czg",
|
||||||
"dev": "cross-env turbo run dev",
|
"dev": "cross-env TURBO_UI=1 turbo run dev",
|
||||||
"dev:ui": "cross-env TURBO_UI=1 turbo run dev",
|
"dev:docs": "pnpm -F @vben/website run docs:dev",
|
||||||
"docs:dev": "pnpm -F @vben/website run docs:dev",
|
|
||||||
"format": "vsh lint --format",
|
"format": "vsh lint --format",
|
||||||
"lint": "vsh lint",
|
"lint": "vsh lint",
|
||||||
"postinstall": "turbo run stub",
|
"postinstall": "turbo run stub",
|
||||||
|
@ -45,7 +47,7 @@
|
||||||
"prepare": "is-ci || husky",
|
"prepare": "is-ci || husky",
|
||||||
"publint": "vsh publint",
|
"publint": "vsh publint",
|
||||||
"reinstall": "pnpm clean --del-lock && pnpm bootstrap",
|
"reinstall": "pnpm clean --del-lock && pnpm bootstrap",
|
||||||
"test": "vitest",
|
"test:unit": "vitest",
|
||||||
"update:deps": " pnpm update --latest --recursive",
|
"update:deps": " pnpm update --latest --recursive",
|
||||||
"version": "pnpm exec changeset version && pnpm install --no-frozen-lockfile"
|
"version": "pnpm exec changeset version && pnpm install --no-frozen-lockfile"
|
||||||
},
|
},
|
||||||
|
@ -54,7 +56,7 @@
|
||||||
"@changesets/cli": "^2.27.7",
|
"@changesets/cli": "^2.27.7",
|
||||||
"@ls-lint/ls-lint": "^2.2.3",
|
"@ls-lint/ls-lint": "^2.2.3",
|
||||||
"@types/jsdom": "^21.1.7",
|
"@types/jsdom": "^21.1.7",
|
||||||
"@types/node": "^20.14.11",
|
"@types/node": "^20.14.12",
|
||||||
"@vben/commitlint-config": "workspace:*",
|
"@vben/commitlint-config": "workspace:*",
|
||||||
"@vben/eslint-config": "workspace:*",
|
"@vben/eslint-config": "workspace:*",
|
||||||
"@vben/lint-staged-config": "workspace:*",
|
"@vben/lint-staged-config": "workspace:*",
|
||||||
|
@ -67,16 +69,16 @@
|
||||||
"@vue/test-utils": "^2.4.6",
|
"@vue/test-utils": "^2.4.6",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"cspell": "^8.12.1",
|
"cspell": "^8.12.1",
|
||||||
"husky": "^9.1.1",
|
"husky": "^9.1.3",
|
||||||
"is-ci": "^3.0.1",
|
"is-ci": "^3.0.1",
|
||||||
"jsdom": "^24.1.1",
|
"jsdom": "^24.1.1",
|
||||||
"rimraf": "^6.0.1",
|
"rimraf": "^6.0.1",
|
||||||
"turbo": "^2.0.9",
|
"turbo": "^2.0.9",
|
||||||
"typescript": "^5.5.4",
|
"typescript": "^5.5.4",
|
||||||
"unbuild": "^2.0.0",
|
"unbuild": "^2.0.0",
|
||||||
"vite": "^5.3.4",
|
"vite": "^5.3.5",
|
||||||
"vitest": "^2.0.4",
|
"vitest": "^2.0.4",
|
||||||
"vue-tsc": "^2.0.28"
|
"vue-tsc": "^2.0.29"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20",
|
"node": ">=20",
|
||||||
|
@ -87,9 +89,7 @@
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"@ctrl/tinycolor": "^4.1.0",
|
"@ctrl/tinycolor": "^4.1.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"eslint": "^8.57.0",
|
"vue": "^3.4.34"
|
||||||
"vue": "^3.4.33",
|
|
||||||
"zx": "^7.2.3"
|
|
||||||
},
|
},
|
||||||
"neverBuiltDependencies": [
|
"neverBuiltDependencies": [
|
||||||
"canvas",
|
"canvas",
|
||||||
|
@ -98,7 +98,6 @@
|
||||||
],
|
],
|
||||||
"updateConfig": {
|
"updateConfig": {
|
||||||
"ignoreDependencies": [
|
"ignoreDependencies": [
|
||||||
"eslint",
|
|
||||||
"zx"
|
"zx"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
"@vueuse/core": "^10.11.0",
|
"@vueuse/core": "^10.11.0",
|
||||||
"radix-vue": "^1.9.2",
|
"radix-vue": "^1.9.2",
|
||||||
"sortablejs": "^1.15.2",
|
"sortablejs": "^1.15.2",
|
||||||
"vue": "^3.4.33"
|
"vue": "^3.4.34"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/sortablejs": "^1.15.8"
|
"@types/sortablejs": "^1.15.8"
|
||||||
|
|
|
@ -31,6 +31,6 @@
|
||||||
"@vben-core/toolkit": "workspace:*",
|
"@vben-core/toolkit": "workspace:*",
|
||||||
"@vben-core/typings": "workspace:*",
|
"@vben-core/typings": "workspace:*",
|
||||||
"@vueuse/core": "^10.11.0",
|
"@vueuse/core": "^10.11.0",
|
||||||
"vue": "^3.4.33"
|
"vue": "^3.4.34"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,15 @@ const defaultPreferences: Preferences = {
|
||||||
compact: false,
|
compact: false,
|
||||||
contentCompact: 'wide',
|
contentCompact: 'wide',
|
||||||
defaultAvatar:
|
defaultAvatar:
|
||||||
'https://cdn.jsdelivr.net/npm/@vbenjs/static-source@0.1.3/source/avatar-v1.webp',
|
'https://unpkg.com/@vbenjs/static-source@0.1.5/source/avatar-v1.webp',
|
||||||
dynamicTitle: true,
|
dynamicTitle: true,
|
||||||
enablePreferences: true,
|
enablePreferences: true,
|
||||||
isMobile: false,
|
isMobile: false,
|
||||||
layout: 'sidebar-nav',
|
layout: 'sidebar-nav',
|
||||||
locale: 'zh-CN',
|
locale: 'zh-CN',
|
||||||
loginExpiredMode: 'page',
|
loginExpiredMode: 'modal',
|
||||||
name: 'Vben Admin',
|
name: 'Vben Admin',
|
||||||
|
watermark: false,
|
||||||
},
|
},
|
||||||
breadcrumb: {
|
breadcrumb: {
|
||||||
enable: true,
|
enable: true,
|
||||||
|
@ -44,8 +45,7 @@ const defaultPreferences: Preferences = {
|
||||||
},
|
},
|
||||||
logo: {
|
logo: {
|
||||||
enable: true,
|
enable: true,
|
||||||
source:
|
source: 'https://unpkg.com/@vbenjs/static-source@0.1.5/source/logo-v1.webp',
|
||||||
'https://cdn.jsdelivr.net/npm/@vbenjs/static-source@0.1.3/source/logo-v1.webp',
|
|
||||||
},
|
},
|
||||||
navigation: {
|
navigation: {
|
||||||
accordion: true,
|
accordion: true,
|
||||||
|
@ -75,6 +75,9 @@ const defaultPreferences: Preferences = {
|
||||||
keepAlive: true,
|
keepAlive: true,
|
||||||
persist: true,
|
persist: true,
|
||||||
showIcon: true,
|
showIcon: true,
|
||||||
|
showMaximize: true,
|
||||||
|
showMore: true,
|
||||||
|
showRefresh: true,
|
||||||
styleType: 'chrome',
|
styleType: 'chrome',
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
|
@ -94,7 +97,6 @@ const defaultPreferences: Preferences = {
|
||||||
progress: true,
|
progress: true,
|
||||||
},
|
},
|
||||||
widget: {
|
widget: {
|
||||||
aiAssistant: true,
|
|
||||||
fullscreen: true,
|
fullscreen: true,
|
||||||
globalSearch: true,
|
globalSearch: true,
|
||||||
languageToggle: true,
|
languageToggle: true,
|
||||||
|
|
|
@ -1,12 +1,4 @@
|
||||||
import type {
|
import type { BuiltinThemeType } from '@vben-core/typings';
|
||||||
BuiltinThemeType,
|
|
||||||
SupportedLanguagesType,
|
|
||||||
} from '@vben-core/typings';
|
|
||||||
|
|
||||||
interface Language {
|
|
||||||
key: SupportedLanguagesType;
|
|
||||||
text: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface BuiltinThemePreset {
|
interface BuiltinThemePreset {
|
||||||
color: string;
|
color: string;
|
||||||
|
@ -15,25 +7,11 @@ interface BuiltinThemePreset {
|
||||||
type: BuiltinThemeType;
|
type: BuiltinThemeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Supported languages
|
|
||||||
*/
|
|
||||||
const SUPPORT_LANGUAGES: Language[] = [
|
|
||||||
{
|
|
||||||
key: 'zh-CN',
|
|
||||||
text: '简体中文',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'en-US',
|
|
||||||
text: 'English',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const BUILT_IN_THEME_PRESETS: BuiltinThemePreset[] = [
|
const BUILT_IN_THEME_PRESETS: BuiltinThemePreset[] = [
|
||||||
{
|
// {
|
||||||
color: 'hsl(231 98% 65%)',
|
// color: 'hsl(231 98% 65%)',
|
||||||
type: 'default',
|
// type: 'default',
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
color: 'hsl(245 82% 67%)',
|
color: 'hsl(245 82% 67%)',
|
||||||
type: 'violet',
|
type: 'violet',
|
||||||
|
@ -102,6 +80,6 @@ const BUILT_IN_THEME_PRESETS: BuiltinThemePreset[] = [
|
||||||
|
|
||||||
export const COLOR_PRESETS = [...BUILT_IN_THEME_PRESETS].slice(0, 7);
|
export const COLOR_PRESETS = [...BUILT_IN_THEME_PRESETS].slice(0, 7);
|
||||||
|
|
||||||
export { BUILT_IN_THEME_PRESETS, SUPPORT_LANGUAGES };
|
export { BUILT_IN_THEME_PRESETS };
|
||||||
|
|
||||||
export type { BuiltinThemePreset };
|
export type { BuiltinThemePreset };
|
||||||
|
|
|
@ -24,17 +24,6 @@ describe('preferences', () => {
|
||||||
preferenceManager = new PreferenceManager();
|
preferenceManager = new PreferenceManager();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('initPreferences should initialize preferences with overrides and namespace', async () => {
|
|
||||||
const overrides = { theme: { colorPrimary: 'hsl(231 98% 65%)' } };
|
|
||||||
const namespace = 'testNamespace';
|
|
||||||
|
|
||||||
await preferenceManager.initPreferences({ namespace, overrides });
|
|
||||||
|
|
||||||
expect(preferenceManager.getPreferences().theme.colorPrimary).toBe(
|
|
||||||
overrides.theme.colorPrimary,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('loads default preferences if no saved preferences found', () => {
|
it('loads default preferences if no saved preferences found', () => {
|
||||||
const preferences = preferenceManager.getPreferences();
|
const preferences = preferenceManager.getPreferences();
|
||||||
expect(preferences).toEqual(defaultPreferences);
|
expect(preferences).toEqual(defaultPreferences);
|
||||||
|
|
|
@ -41,7 +41,7 @@ class PreferenceManager {
|
||||||
|
|
||||||
this.savePreferences = useDebounceFn(
|
this.savePreferences = useDebounceFn(
|
||||||
(preference: Preferences) => this._savePreferences(preference),
|
(preference: Preferences) => this._savePreferences(preference),
|
||||||
100,
|
150,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,12 @@ import type {
|
||||||
LoginExpiredModeType,
|
LoginExpiredModeType,
|
||||||
NavigationStyleType,
|
NavigationStyleType,
|
||||||
PageTransitionType,
|
PageTransitionType,
|
||||||
SupportedLanguagesType,
|
|
||||||
TabsStyleType,
|
TabsStyleType,
|
||||||
ThemeModeType,
|
ThemeModeType,
|
||||||
} from '@vben-core/typings';
|
} from '@vben-core/typings';
|
||||||
|
|
||||||
|
type SupportedLanguagesType = 'en-US' | 'zh-CN';
|
||||||
|
|
||||||
interface AppPreferences {
|
interface AppPreferences {
|
||||||
/** 权限模式 */
|
/** 权限模式 */
|
||||||
accessMode: AccessModeType;
|
accessMode: AccessModeType;
|
||||||
|
@ -44,6 +45,10 @@ interface AppPreferences {
|
||||||
loginExpiredMode: LoginExpiredModeType;
|
loginExpiredMode: LoginExpiredModeType;
|
||||||
/** 应用名 */
|
/** 应用名 */
|
||||||
name: string;
|
name: string;
|
||||||
|
/**
|
||||||
|
* @zh_CN 是否开启水印
|
||||||
|
*/
|
||||||
|
watermark: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BreadcrumbPreferences {
|
interface BreadcrumbPreferences {
|
||||||
|
@ -149,6 +154,12 @@ interface TabbarPreferences {
|
||||||
persist: boolean;
|
persist: boolean;
|
||||||
/** 是否开启多标签页图标 */
|
/** 是否开启多标签页图标 */
|
||||||
showIcon: boolean;
|
showIcon: boolean;
|
||||||
|
/** 显示最大化按钮 */
|
||||||
|
showMaximize: boolean;
|
||||||
|
/** 显示更多按钮 */
|
||||||
|
showMore: boolean;
|
||||||
|
/** 显示刷新按钮 */
|
||||||
|
showRefresh: boolean;
|
||||||
/** 标签页风格 */
|
/** 标签页风格 */
|
||||||
styleType: TabsStyleType;
|
styleType: TabsStyleType;
|
||||||
}
|
}
|
||||||
|
@ -184,8 +195,6 @@ interface TransitionPreferences {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface WidgetPreferences {
|
interface WidgetPreferences {
|
||||||
/** 是否开启vben助手部件 */
|
|
||||||
aiAssistant: boolean;
|
|
||||||
/** 是否启用全屏部件 */
|
/** 是否启用全屏部件 */
|
||||||
fullscreen: boolean;
|
fullscreen: boolean;
|
||||||
/** 是否启用全局搜索部件 */
|
/** 是否启用全局搜索部件 */
|
||||||
|
@ -249,6 +258,7 @@ export type {
|
||||||
PreferencesKeys,
|
PreferencesKeys,
|
||||||
ShortcutKeyPreferences,
|
ShortcutKeyPreferences,
|
||||||
SidebarPreferences,
|
SidebarPreferences,
|
||||||
|
SupportedLanguagesType,
|
||||||
TabbarPreferences,
|
TabbarPreferences,
|
||||||
ThemePreferences,
|
ThemePreferences,
|
||||||
TransitionPreferences,
|
TransitionPreferences,
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {
|
||||||
generatorColorVariables,
|
generatorColorVariables,
|
||||||
} from '@vben-core/toolkit';
|
} from '@vben-core/toolkit';
|
||||||
|
|
||||||
import { BUILT_IN_THEME_PRESETS } from './constants';
|
import { BUILT_IN_THEME_PRESETS, type BuiltinThemePreset } from './constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新主题的 CSS 变量以及其他 CSS 变量
|
* 更新主题的 CSS 变量以及其他 CSS 变量
|
||||||
|
@ -37,9 +37,13 @@ function updateCSSVariables(preferences: Preferences) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取当前的内置主题
|
// 获取当前的内置主题
|
||||||
const currentBuiltType = BUILT_IN_THEME_PRESETS.find(
|
const currentBuiltType = [
|
||||||
(item) => item.type === builtinType,
|
{
|
||||||
);
|
color: preferences.theme.colorPrimary,
|
||||||
|
type: 'default',
|
||||||
|
} as BuiltinThemePreset,
|
||||||
|
...BUILT_IN_THEME_PRESETS,
|
||||||
|
].find((item) => item.type === builtinType);
|
||||||
|
|
||||||
let builtinTypeColorPrimary: string | undefined = '';
|
let builtinTypeColorPrimary: string | undefined = '';
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ const VBEN_DOC_URL = 'https://doc.vben.pro';
|
||||||
* @zh_CN Vben Logo
|
* @zh_CN Vben Logo
|
||||||
*/
|
*/
|
||||||
const VBEN_LOGO_URL =
|
const VBEN_LOGO_URL =
|
||||||
'https://cdn.jsdelivr.net/npm/@vbenjs/static-source@0.1.3/source/logo-v1.webp';
|
'https://unpkg.com/@vbenjs/static-source@0.1.5/source/logo-v1.webp';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @zh_CN Vben Admin 首页地址
|
* @zh_CN Vben Admin 首页地址
|
||||||
|
|
|
@ -85,17 +85,21 @@
|
||||||
|
|
||||||
/* 只有非mac下才进行调整,mac下使用默认滚动条 */
|
/* 只有非mac下才进行调整,mac下使用默认滚动条 */
|
||||||
html:not([data-platform='macOs']) {
|
html:not([data-platform='macOs']) {
|
||||||
*::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
@apply h-[1px] w-[10px];
|
@apply h-[1px] w-[10px];
|
||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
@apply bg-border rounded-sm border-none;
|
@apply bg-border rounded-sm border-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar-track {
|
::-webkit-scrollbar-track {
|
||||||
@apply rounded-sm border-none bg-transparent shadow-none;
|
@apply rounded-sm border-none bg-transparent shadow-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-button {
|
||||||
|
@apply hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iconify/vue": "^4.1.2",
|
"@iconify/vue": "^4.1.2",
|
||||||
"lucide-vue-next": "^0.414.0",
|
"lucide-vue-next": "^0.416.0",
|
||||||
"vue": "^3.4.33"
|
"vue": "^3.4.34"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ctrl/tinycolor": "^4.1.0",
|
"@ctrl/tinycolor": "^4.1.0",
|
||||||
"@vue/shared": "^3.4.33",
|
"@vue/shared": "^3.4.34",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"defu": "^6.1.4",
|
"defu": "^6.1.4",
|
||||||
"lodash.clonedeep": "^4.5.0",
|
"lodash.clonedeep": "^4.5.0",
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"vue": "^3.4.33",
|
"vue": "^3.4.34",
|
||||||
"vue-router": "^4.4.0"
|
"vue-router": "^4.4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue