mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-26 00:26:20 +08:00
Compare commits
57 Commits
v2.9.0
...
v3.0.0-alp
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6ec0a01de7 | ||
![]() |
4cddaee88a | ||
![]() |
70e44af191 | ||
![]() |
82eaf1a74b | ||
![]() |
a969d2091a | ||
![]() |
e285947716 | ||
![]() |
cfbd5e9851 | ||
![]() |
122db78e84 | ||
![]() |
5c69b3d5a8 | ||
![]() |
335f30c887 | ||
![]() |
6a9bd686d5 | ||
![]() |
6890dd7201 | ||
![]() |
762e5dee14 | ||
![]() |
fa18365c21 | ||
![]() |
feadf64ee3 | ||
![]() |
553ee9c7ae | ||
![]() |
9f8e010534 | ||
![]() |
14ba72dd1c | ||
![]() |
be0d35394c | ||
![]() |
b14a15e66b | ||
![]() |
ae5f5cb13c | ||
![]() |
ccaa84c305 | ||
![]() |
357beabaeb | ||
![]() |
7469312ffc | ||
![]() |
401fcaf325 | ||
![]() |
5e8ef2f64f | ||
![]() |
8e5a6b7ce5 | ||
![]() |
279977b817 | ||
![]() |
a5ed79fc94 | ||
![]() |
660024c6f3 | ||
![]() |
d25df8321e | ||
![]() |
6b30c9f7bb | ||
![]() |
aedb8e53aa | ||
![]() |
358b77fe96 | ||
![]() |
5e99463cd0 | ||
![]() |
5e4be0adbc | ||
![]() |
c2590cbfb5 | ||
![]() |
08d4e34b77 | ||
![]() |
7a8978dcff | ||
![]() |
af54b0fbc6 | ||
![]() |
4418eccfab | ||
![]() |
02d41197b6 | ||
![]() |
ba2415c3b4 | ||
![]() |
84a5fc1256 | ||
![]() |
8180b2d15f | ||
![]() |
699cf6d7af | ||
![]() |
fea323cff1 | ||
![]() |
dc39567a14 | ||
![]() |
ab74480083 | ||
![]() |
9579a45b3c | ||
![]() |
302afe5860 | ||
![]() |
7b21e9dc24 | ||
![]() |
f05b90f86b | ||
![]() |
1b30834eb3 | ||
![]() |
c5f97b9d9f | ||
![]() |
3a1ec7ac86 | ||
![]() |
4c63b1abb7 |
4
.browserslistrc
Normal file
4
.browserslistrc
Normal file
@@ -0,0 +1,4 @@
|
||||
> 1%
|
||||
last 2 versions
|
||||
not dead
|
||||
not ie 11
|
6
.env
6
.env
@@ -1,8 +1,2 @@
|
||||
# port
|
||||
VITE_PORT = 3100
|
||||
|
||||
# spa-title
|
||||
VITE_GLOB_APP_TITLE = Vben Admin
|
||||
|
||||
# spa shortname
|
||||
VITE_GLOB_APP_SHORT_NAME = vue_vben_admin
|
||||
|
23
.env.analyze
Normal file
23
.env.analyze
Normal file
@@ -0,0 +1,23 @@
|
||||
# Whether to open mock
|
||||
VITE_USE_MOCK = true
|
||||
|
||||
# public path
|
||||
VITE_PUBLIC_PATH = /
|
||||
|
||||
# Whether to enable gzip or brotli compression
|
||||
# Optional: gzip | brotli | none
|
||||
# If you need multiple forms, you can use `,` to separate
|
||||
VITE_BUILD_COMPRESS = 'none'
|
||||
|
||||
|
||||
# Basic interface address SPA
|
||||
VITE_GLOB_API_URL=/basic-api
|
||||
|
||||
# File upload address, optional
|
||||
# It can be forwarded by nginx or write the actual address directly
|
||||
VITE_GLOB_UPLOAD_URL=/upload
|
||||
|
||||
# Interface prefix
|
||||
VITE_GLOB_API_URL_PREFIX=
|
||||
|
||||
VITE_ENABLE_ANALYZE = true
|
@@ -4,14 +4,6 @@ VITE_USE_MOCK = true
|
||||
# public path
|
||||
VITE_PUBLIC_PATH = /
|
||||
|
||||
# Cross-domain proxy, you can configure multiple
|
||||
# Please note that no line breaks
|
||||
VITE_PROXY = [["/basic-api","http://localhost:3000"],["/upload","http://localhost:3300/upload"]]
|
||||
# VITE_PROXY=[["/api","https://vvbin.cn/test"]]
|
||||
|
||||
# Delete console
|
||||
VITE_DROP_CONSOLE = false
|
||||
|
||||
# Basic interface address SPA
|
||||
VITE_GLOB_API_URL=/basic-api
|
||||
|
||||
|
@@ -4,16 +4,11 @@ VITE_USE_MOCK = true
|
||||
# public path
|
||||
VITE_PUBLIC_PATH = /
|
||||
|
||||
# Delete console
|
||||
VITE_DROP_CONSOLE = true
|
||||
|
||||
# Whether to enable gzip or brotli compression
|
||||
# Optional: gzip | brotli | none
|
||||
# If you need multiple forms, you can use `,` to separate
|
||||
VITE_BUILD_COMPRESS = 'none'
|
||||
|
||||
# Whether to delete origin files when using compress, default false
|
||||
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
|
||||
|
||||
# Basic interface address SPA
|
||||
VITE_GLOB_API_URL=/basic-api
|
||||
@@ -24,12 +19,3 @@ VITE_GLOB_UPLOAD_URL=/upload
|
||||
|
||||
# Interface prefix
|
||||
VITE_GLOB_API_URL_PREFIX=
|
||||
|
||||
# Whether to enable image compression
|
||||
VITE_USE_IMAGEMIN= true
|
||||
|
||||
# use pwa
|
||||
VITE_USE_PWA = false
|
||||
|
||||
# Is it compatible with older browsers
|
||||
VITE_LEGACY = false
|
||||
|
15
.env.test
15
.env.test
@@ -5,17 +5,11 @@ VITE_USE_MOCK = true
|
||||
# public path
|
||||
VITE_PUBLIC_PATH = /
|
||||
|
||||
# Delete console
|
||||
VITE_DROP_CONSOLE = true
|
||||
|
||||
# Whether to enable gzip or brotli compression
|
||||
# Optional: gzip | brotli | none
|
||||
# If you need multiple forms, you can use `,` to separate
|
||||
VITE_BUILD_COMPRESS = 'none'
|
||||
|
||||
# Whether to delete origin files when using compress, default false
|
||||
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
|
||||
|
||||
# Basic interface address SPA
|
||||
VITE_GLOB_API_URL=/basic-api
|
||||
|
||||
@@ -25,12 +19,3 @@ VITE_GLOB_UPLOAD_URL=/upload
|
||||
|
||||
# Interface prefix
|
||||
VITE_GLOB_API_URL_PREFIX=
|
||||
|
||||
# Whether to enable image compression
|
||||
VITE_USE_IMAGEMIN= true
|
||||
|
||||
# use pwa
|
||||
VITE_USE_PWA = false
|
||||
|
||||
# Is it compatible with older browsers
|
||||
VITE_LEGACY = false
|
||||
|
74
.eslintrc.js
74
.eslintrc.js
@@ -1,76 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
es6: true,
|
||||
},
|
||||
parser: 'vue-eslint-parser',
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser',
|
||||
ecmaVersion: 2020,
|
||||
sourceType: 'module',
|
||||
jsxPragma: 'React',
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
},
|
||||
extends: [
|
||||
'plugin:vue/vue3-recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:prettier/recommended',
|
||||
],
|
||||
rules: {
|
||||
'vue/script-setup-uses-vars': 'error',
|
||||
'@typescript-eslint/ban-ts-ignore': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-var-requires': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'vue/custom-event-name-casing': 'off',
|
||||
'no-use-before-define': 'off',
|
||||
'@typescript-eslint/no-use-before-define': 'off',
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'@typescript-eslint/ban-types': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
'no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
'space-before-function-paren': 'off',
|
||||
|
||||
'vue/attributes-order': 'off',
|
||||
'vue/one-component-per-file': 'off',
|
||||
'vue/html-closing-bracket-newline': 'off',
|
||||
'vue/max-attributes-per-line': 'off',
|
||||
'vue/multiline-html-element-content-newline': 'off',
|
||||
'vue/singleline-html-element-content-newline': 'off',
|
||||
'vue/attribute-hyphenation': 'off',
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/require-explicit-emits': 'off',
|
||||
'vue/html-self-closing': [
|
||||
'error',
|
||||
{
|
||||
html: {
|
||||
void: 'always',
|
||||
normal: 'never',
|
||||
component: 'always',
|
||||
},
|
||||
svg: 'always',
|
||||
math: 'always',
|
||||
},
|
||||
],
|
||||
'vue/multi-word-component-names': 'off',
|
||||
},
|
||||
extends: ['@vben'],
|
||||
};
|
||||
|
7
.github/workflows/deploy.yml
vendored
7
.github/workflows/deploy.yml
vendored
@@ -98,7 +98,7 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
NODE_OPTIONS: '--max_old_space_size=4096'
|
||||
run: |
|
||||
yarn install
|
||||
yarn run build
|
||||
@@ -116,8 +116,3 @@ jobs:
|
||||
PUBLISH_BRANCH: gh-pages
|
||||
PUBLISH_DIR: ./dist
|
||||
CNAME: vben.vvbin.cn
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,8 +1,8 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
.npmrc
|
||||
.cache
|
||||
.turbo
|
||||
|
||||
tests/server/static
|
||||
tests/server/static/upload
|
||||
|
@@ -7,4 +7,4 @@
|
||||
PATH="/usr/local/bin:$PATH"
|
||||
|
||||
# Format and submit code according to lintstagedrc.js configuration
|
||||
npm run lint:lint-staged
|
||||
pnpm exec lint-staged
|
||||
|
7
.npmrc
Normal file
7
.npmrc
Normal file
@@ -0,0 +1,7 @@
|
||||
public-hoist-pattern[]=husky
|
||||
public-hoist-pattern[]=*eslint*
|
||||
public-hoist-pattern[]=*prettier*
|
||||
public-hoist-pattern[]=lint-staged
|
||||
public-hoist-pattern[]=*stylelint*
|
||||
public-hoist-pattern[]=@commitlint/cli
|
||||
public-hoist-pattern[]=@vben/eslint-config
|
@@ -1,9 +1,11 @@
|
||||
/dist/*
|
||||
dist
|
||||
.local
|
||||
.output.js
|
||||
/node_modules/**
|
||||
node_modules
|
||||
.nvmrc
|
||||
|
||||
**/*.svg
|
||||
**/*.sh
|
||||
|
||||
/public/*
|
||||
public
|
||||
.npmrc
|
||||
|
@@ -7,4 +7,13 @@ module.exports = {
|
||||
proseWrap: 'never',
|
||||
htmlWhitespaceSensitivity: 'strict',
|
||||
endOfLine: 'auto',
|
||||
plugins: ['prettier-plugin-packagejson'],
|
||||
overrides: [
|
||||
{
|
||||
files: '.*rc',
|
||||
options: {
|
||||
parser: 'json',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
@@ -1,3 +1,2 @@
|
||||
/dist/*
|
||||
/public/*
|
||||
public/*
|
||||
dist
|
||||
public
|
||||
|
4
.stylelintrc.js
Normal file
4
.stylelintrc.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['@vben/stylelint-config'],
|
||||
};
|
8
.vscode/settings.json
vendored
8
.vscode/settings.json
vendored
@@ -84,7 +84,8 @@
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
"source.fixAll.eslint": true,
|
||||
"source.fixAll.stylelint": true
|
||||
},
|
||||
"[vue]": {
|
||||
"editor.codeActionsOnSave": {
|
||||
@@ -103,7 +104,6 @@
|
||||
"i18n-ally.enabledFrameworks": ["vue", "react"],
|
||||
"cSpell.words": [
|
||||
"vben",
|
||||
"windi",
|
||||
"browserslist",
|
||||
"tailwindcss",
|
||||
"esnext",
|
||||
@@ -164,7 +164,9 @@
|
||||
"*.ts": "$(capture).test.ts, $(capture).test.tsx",
|
||||
"*.tsx": "$(capture).test.ts, $(capture).test.tsx",
|
||||
"*.env": "$(capture).env.*",
|
||||
"package.json": "pnpm-lock.yaml,yarn.lock,LICENSE,README*,CHANGELOG*,CNAME,.gitattributes,.gitignore,prettier.config.js,stylelint.config.js,commitlint.config.js,.stylelintignore,.prettierignore,.gitpod.yml,.eslintrc.js,.eslintignore"
|
||||
"CHANGELOG.md": "CHANGELOG*",
|
||||
"package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,LICENSE,.gitattributes,.gitignore,.gitpod.yml,CNAME,README*,.npmrc,.browserslistrc,.nvmrc",
|
||||
".eslintrc.js": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.js,.prettierrc.js,.stylelintrc.js"
|
||||
},
|
||||
"terminal.integrated.scrollback": 10000
|
||||
}
|
||||
|
@@ -131,9 +131,6 @@ If these plugins are helpful to you, you can give a star support
|
||||
|
||||
- [vite-plugin-mock](https://github.com/anncwb/vite-plugin-mock) - Used for local and development environment data mock
|
||||
- [vite-plugin-html](https://github.com/anncwb/vite-plugin-html) - Used for html template conversion and compression
|
||||
- [vite-plugin-style-import](https://github.com/anncwb/vite-plugin-style-import) - Used for component library style introduction on demand
|
||||
- [vite-plugin-theme](https://github.com/anncwb/vite-plugin-theme) - Used for online switching of theme colors and other color-related configurations
|
||||
- [vite-plugin-imagemin](https://github.com/anncwb/vite-plugin-imagemin) - Used to pack compressed image resources
|
||||
- [vite-plugin-compression](https://github.com/anncwb/vite-plugin-compression) - Used to pack input .gz|.brotil files
|
||||
- [vite-plugin-svg-icons](https://github.com/anncwb/vite-plugin-svg-icons) - Used to quickly generate svg sprite
|
||||
|
||||
|
@@ -141,9 +141,6 @@ pnpm build
|
||||
|
||||
- [vite-plugin-mock](https://github.com/anncwb/vite-plugin-mock) - 用于本地及开发环境数据 mock
|
||||
- [vite-plugin-html](https://github.com/anncwb/vite-plugin-html) - 用于 html 模版转换及压缩
|
||||
- [vite-plugin-style-import](https://github.com/anncwb/vite-plugin-style-import) - 用于组件库样式按需引入
|
||||
- [vite-plugin-theme](https://github.com/anncwb/vite-plugin-theme) - 用于在线切换主题色等颜色相关配置
|
||||
- [vite-plugin-imagemin](https://github.com/anncwb/vite-plugin-imagemin) - 用于打包压缩图片资源
|
||||
- [vite-plugin-compression](https://github.com/anncwb/vite-plugin-compression) - 用于打包输出.gz|.brotil 文件
|
||||
- [vite-plugin-svg-icons](https://github.com/anncwb/vite-plugin-svg-icons) - 用于快速生成 svg 雪碧图
|
||||
|
||||
|
0
apps/portal-view/.gitkeep
Normal file
0
apps/portal-view/.gitkeep
Normal file
@@ -3,34 +3,34 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"start": "nodemon",
|
||||
"build": "rimraf ./dist && tsup ./index.ts --dts --format cjs,esm ",
|
||||
"compile": "rimraf ./dist && tsup ./index.ts --dts --format cjs,esm ",
|
||||
"prod": "npx pm2 start ecosystem.config.js --env production",
|
||||
"restart": "pm2 restart ecosystem.config.js --env production",
|
||||
"start": "nodemon",
|
||||
"stop": "npx pm2 stop ecosystem.config.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"fs-extra": "^10.0.1",
|
||||
"koa": "^2.13.4",
|
||||
"koa-body": "^4.2.0",
|
||||
"koa-bodyparser": "^4.3.0",
|
||||
"fs-extra": "^11.1.1",
|
||||
"koa": "^2.14.1",
|
||||
"koa-body": "^6.0.1",
|
||||
"koa-bodyparser": "^4.4.0",
|
||||
"koa-route": "^3.2.0",
|
||||
"koa-router": "^10.1.1",
|
||||
"koa-router": "^12.0.0",
|
||||
"koa-static": "^5.0.0",
|
||||
"koa-websocket": "^6.0.0",
|
||||
"koa-websocket": "^7.0.0",
|
||||
"koa2-cors": "^2.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/koa": "^2.13.4",
|
||||
"@types/koa": "^2.13.6",
|
||||
"@types/koa-bodyparser": "^5.0.2",
|
||||
"@types/koa-router": "^7.4.4",
|
||||
"@types/node": "^17.0.21",
|
||||
"nodemon": "^2.0.15",
|
||||
"pm2": "^5.2.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-node": "^10.7.0",
|
||||
"tsconfig-paths": "^3.14.0",
|
||||
"tsup": "^5.12.1",
|
||||
"typescript": "^4.6.2"
|
||||
"@types/node": "^18.15.11",
|
||||
"nodemon": "^2.0.22",
|
||||
"pm2": "^5.3.0",
|
||||
"rimraf": "^4.4.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"tsup": "^6.7.0",
|
||||
"typescript": "^5.0.3"
|
||||
}
|
||||
}
|
7
apps/test-server/tsconfig.json
Normal file
7
apps/test-server/tsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "@vben/ts-config/node-server.json",
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": false
|
||||
}
|
||||
}
|
@@ -1,79 +0,0 @@
|
||||
import { generate } from '@ant-design/colors';
|
||||
|
||||
export const primaryColor = '#0960bd';
|
||||
|
||||
export const darkMode = 'light';
|
||||
|
||||
type Fn = (...arg: any) => any;
|
||||
|
||||
type GenerateTheme = 'default' | 'dark';
|
||||
|
||||
export interface GenerateColorsParams {
|
||||
mixLighten: Fn;
|
||||
mixDarken: Fn;
|
||||
tinycolor: any;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export function generateAntColors(color: string, theme: GenerateTheme = 'default') {
|
||||
return generate(color, {
|
||||
theme,
|
||||
});
|
||||
}
|
||||
|
||||
export function getThemeColors(color?: string) {
|
||||
const tc = color || primaryColor;
|
||||
const lightColors = generateAntColors(tc);
|
||||
const primary = lightColors[5];
|
||||
const modeColors = generateAntColors(primary, 'dark');
|
||||
|
||||
return [...lightColors, ...modeColors];
|
||||
}
|
||||
|
||||
export function generateColors({
|
||||
color = primaryColor,
|
||||
mixLighten,
|
||||
mixDarken,
|
||||
tinycolor,
|
||||
}: GenerateColorsParams) {
|
||||
const arr = new Array(19).fill(0);
|
||||
const lightens = arr.map((_t, i) => {
|
||||
return mixLighten(color, i / 5);
|
||||
});
|
||||
|
||||
const darkens = arr.map((_t, i) => {
|
||||
return mixDarken(color, i / 5);
|
||||
});
|
||||
|
||||
const alphaColors = arr.map((_t, i) => {
|
||||
return tinycolor(color)
|
||||
.setAlpha(i / 20)
|
||||
.toRgbString();
|
||||
});
|
||||
|
||||
const shortAlphaColors = alphaColors.map((item) => item.replace(/\s/g, '').replace(/0\./g, '.'));
|
||||
|
||||
const tinycolorLightens = arr
|
||||
.map((_t, i) => {
|
||||
return tinycolor(color)
|
||||
.lighten(i * 5)
|
||||
.toHexString();
|
||||
})
|
||||
.filter((item) => item !== '#ffffff');
|
||||
|
||||
const tinycolorDarkens = arr
|
||||
.map((_t, i) => {
|
||||
return tinycolor(color)
|
||||
.darken(i * 5)
|
||||
.toHexString();
|
||||
})
|
||||
.filter((item) => item !== '#000000');
|
||||
return [
|
||||
...lightens,
|
||||
...darkens,
|
||||
...alphaColors,
|
||||
...shortAlphaColors,
|
||||
...tinycolorDarkens,
|
||||
...tinycolorLightens,
|
||||
].filter((item) => !item.includes('-'));
|
||||
}
|
@@ -1,6 +0,0 @@
|
||||
/**
|
||||
* The name of the configuration file entered in the production environment
|
||||
*/
|
||||
export const GLOB_CONFIG_FILE_NAME = '_app.config.js';
|
||||
|
||||
export const OUTPUT_DIR = 'dist';
|
@@ -1,72 +0,0 @@
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import inquirer from 'inquirer';
|
||||
import colors from 'picocolors';
|
||||
import pkg from '../../../package.json';
|
||||
|
||||
async function generateIcon() {
|
||||
const dir = path.resolve(process.cwd(), 'node_modules/@iconify/json');
|
||||
|
||||
const raw = await fs.readJSON(path.join(dir, 'collections.json'));
|
||||
|
||||
const collections = Object.entries(raw).map(([id, v]) => ({
|
||||
...(v as any),
|
||||
id,
|
||||
}));
|
||||
|
||||
const choices = collections.map((item) => ({ key: item.id, value: item.id, name: item.name }));
|
||||
|
||||
inquirer
|
||||
.prompt([
|
||||
{
|
||||
type: 'list',
|
||||
name: 'useType',
|
||||
choices: [
|
||||
{ key: 'local', value: 'local', name: 'Local' },
|
||||
{ key: 'onLine', value: 'onLine', name: 'OnLine' },
|
||||
],
|
||||
message: 'How to use icons?',
|
||||
},
|
||||
{
|
||||
type: 'list',
|
||||
name: 'iconSet',
|
||||
choices: choices,
|
||||
message: 'Select the icon set that needs to be generated?',
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
name: 'output',
|
||||
message: 'Select the icon set that needs to be generated?',
|
||||
default: 'src/components/Icon/data',
|
||||
},
|
||||
])
|
||||
.then(async (answers) => {
|
||||
const { iconSet, output, useType } = answers;
|
||||
const outputDir = path.resolve(process.cwd(), output);
|
||||
fs.ensureDir(outputDir);
|
||||
const genCollections = collections.filter((item) => [iconSet].includes(item.id));
|
||||
const prefixSet: string[] = [];
|
||||
for (const info of genCollections) {
|
||||
const data = await fs.readJSON(path.join(dir, 'json', `${info.id}.json`));
|
||||
if (data) {
|
||||
const { prefix } = data;
|
||||
const isLocal = useType === 'local';
|
||||
const icons = Object.keys(data.icons).map(
|
||||
(item) => `${isLocal ? prefix + ':' : ''}${item}`,
|
||||
);
|
||||
|
||||
await fs.writeFileSync(
|
||||
path.join(output, `icons.data.ts`),
|
||||
`export default ${isLocal ? JSON.stringify(icons) : JSON.stringify({ prefix, icons })}`,
|
||||
);
|
||||
prefixSet.push(prefix);
|
||||
}
|
||||
}
|
||||
fs.emptyDir(path.join(process.cwd(), 'node_modules/.vite'));
|
||||
console.log(
|
||||
`✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
generateIcon();
|
@@ -1,9 +0,0 @@
|
||||
/**
|
||||
* Get the configuration file variable name
|
||||
* @param env
|
||||
*/
|
||||
export const getConfigFileName = (env: Record<string, any>) => {
|
||||
return `__PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || '__APP'}__CONF__`
|
||||
.toUpperCase()
|
||||
.replace(/\s/g, '');
|
||||
};
|
@@ -1,47 +0,0 @@
|
||||
/**
|
||||
* Generate additional configuration files when used for packaging. The file can be configured with some global variables, so that it can be changed directly externally without repackaging
|
||||
*/
|
||||
import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant';
|
||||
import fs, { writeFileSync } from 'fs-extra';
|
||||
import colors from 'picocolors';
|
||||
|
||||
import { getEnvConfig, getRootPath } from '../utils';
|
||||
import { getConfigFileName } from '../getConfigFileName';
|
||||
|
||||
import pkg from '../../package.json';
|
||||
|
||||
interface CreateConfigParams {
|
||||
configName: string;
|
||||
config: any;
|
||||
configFileName?: string;
|
||||
}
|
||||
|
||||
function createConfig(params: CreateConfigParams) {
|
||||
const { configName, config, configFileName } = params;
|
||||
try {
|
||||
const windowConf = `window.${configName}`;
|
||||
// Ensure that the variable will not be modified
|
||||
let configStr = `${windowConf}=${JSON.stringify(config)};`;
|
||||
configStr += `
|
||||
Object.freeze(${windowConf});
|
||||
Object.defineProperty(window, "${configName}", {
|
||||
configurable: false,
|
||||
writable: false,
|
||||
});
|
||||
`.replace(/\s/g, '');
|
||||
|
||||
fs.mkdirp(getRootPath(OUTPUT_DIR));
|
||||
writeFileSync(getRootPath(`${OUTPUT_DIR}/${configFileName}`), configStr);
|
||||
|
||||
console.log(colors.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`);
|
||||
console.log(colors.gray(OUTPUT_DIR + '/' + colors.green(configFileName)) + '\n');
|
||||
} catch (error) {
|
||||
console.log(colors.red('configuration file configuration file failed to package:\n' + error));
|
||||
}
|
||||
}
|
||||
|
||||
export function runBuildConfig() {
|
||||
const config = getEnvConfig();
|
||||
const configFileName = getConfigFileName(config);
|
||||
createConfig({ config, configName: configFileName, configFileName: GLOB_CONFIG_FILE_NAME });
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
// #!/usr/bin/env node
|
||||
|
||||
import { runBuildConfig } from './buildConf';
|
||||
import colors from 'picocolors';
|
||||
|
||||
import pkg from '../../package.json';
|
||||
|
||||
export const runBuild = async () => {
|
||||
try {
|
||||
const argvList = process.argv.splice(2);
|
||||
|
||||
// Generate configuration file
|
||||
if (!argvList.includes('disabled-config')) {
|
||||
runBuildConfig();
|
||||
}
|
||||
|
||||
console.log(`✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - build successfully!');
|
||||
} catch (error) {
|
||||
console.log(colors.red('vite build error:\n' + error));
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
runBuild();
|
@@ -1,92 +0,0 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
export function isDevFn(mode: string): boolean {
|
||||
return mode === 'development';
|
||||
}
|
||||
|
||||
export function isProdFn(mode: string): boolean {
|
||||
return mode === 'production';
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to generate package preview
|
||||
*/
|
||||
export function isReportMode(): boolean {
|
||||
return process.env.REPORT === 'true';
|
||||
}
|
||||
|
||||
// Read all environment variable configuration files to process.env
|
||||
export function wrapperEnv(envConf: Recordable): ViteEnv {
|
||||
const ret: any = {};
|
||||
|
||||
for (const envName of Object.keys(envConf)) {
|
||||
let realName = envConf[envName].replace(/\\n/g, '\n');
|
||||
realName = realName === 'true' ? true : realName === 'false' ? false : realName;
|
||||
|
||||
if (envName === 'VITE_PORT') {
|
||||
realName = Number(realName);
|
||||
}
|
||||
if (envName === 'VITE_PROXY' && realName) {
|
||||
try {
|
||||
realName = JSON.parse(realName.replace(/'/g, '"'));
|
||||
} catch (error) {
|
||||
realName = '';
|
||||
}
|
||||
}
|
||||
ret[envName] = realName;
|
||||
// if (typeof realName === 'string') {
|
||||
// process.env[envName] = realName;
|
||||
// } else if (typeof realName === 'object') {
|
||||
// process.env[envName] = JSON.stringify(realName);
|
||||
// }
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前环境下生效的配置文件名
|
||||
*/
|
||||
function getConfFiles() {
|
||||
const script = process.env.npm_lifecycle_script;
|
||||
const reg = new RegExp('--mode ([a-z_\\d]+)');
|
||||
const result = reg.exec(script as string) as any;
|
||||
if (result) {
|
||||
const mode = result[1] as string;
|
||||
return ['.env', `.env.${mode}`];
|
||||
}
|
||||
return ['.env', '.env.production'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the environment variables starting with the specified prefix
|
||||
* @param match prefix
|
||||
* @param confFiles ext
|
||||
*/
|
||||
export function getEnvConfig(match = 'VITE_GLOB_', confFiles = getConfFiles()) {
|
||||
let envConfig = {};
|
||||
confFiles.forEach((item) => {
|
||||
try {
|
||||
const env = dotenv.parse(fs.readFileSync(path.resolve(process.cwd(), item)));
|
||||
envConfig = { ...envConfig, ...env };
|
||||
} catch (e) {
|
||||
console.error(`Error in parsing ${item}`, e);
|
||||
}
|
||||
});
|
||||
const reg = new RegExp(`^(${match})`);
|
||||
Object.keys(envConfig).forEach((key) => {
|
||||
if (!reg.test(key)) {
|
||||
Reflect.deleteProperty(envConfig, key);
|
||||
}
|
||||
});
|
||||
return envConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user root directory
|
||||
* @param dir file path
|
||||
*/
|
||||
export function getRootPath(...dir: string[]) {
|
||||
return path.resolve(process.cwd(), ...dir);
|
||||
}
|
@@ -1,40 +0,0 @@
|
||||
/**
|
||||
* Plugin to minimize and use ejs template syntax in index.html.
|
||||
* https://github.com/anncwb/vite-plugin-html
|
||||
*/
|
||||
import type { PluginOption } from 'vite';
|
||||
import { createHtmlPlugin } from 'vite-plugin-html';
|
||||
import pkg from '../../../package.json';
|
||||
import { GLOB_CONFIG_FILE_NAME } from '../../constant';
|
||||
|
||||
export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
|
||||
const { VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH } = env;
|
||||
|
||||
const path = VITE_PUBLIC_PATH.endsWith('/') ? VITE_PUBLIC_PATH : `${VITE_PUBLIC_PATH}/`;
|
||||
|
||||
const getAppConfigSrc = () => {
|
||||
return `${path || '/'}${GLOB_CONFIG_FILE_NAME}?v=${pkg.version}-${new Date().getTime()}`;
|
||||
};
|
||||
|
||||
const htmlPlugin: PluginOption[] = createHtmlPlugin({
|
||||
minify: isBuild,
|
||||
inject: {
|
||||
// Inject data into ejs template
|
||||
data: {
|
||||
title: VITE_GLOB_APP_TITLE,
|
||||
},
|
||||
// Embed the generated app.config.js file
|
||||
tags: isBuild
|
||||
? [
|
||||
{
|
||||
tag: 'script',
|
||||
attrs: {
|
||||
src: getAppConfigSrc(),
|
||||
},
|
||||
},
|
||||
]
|
||||
: [],
|
||||
},
|
||||
});
|
||||
return htmlPlugin;
|
||||
}
|
@@ -1,34 +0,0 @@
|
||||
// Image resource files used to compress the output of the production environment
|
||||
// https://github.com/anncwb/vite-plugin-imagemin
|
||||
import viteImagemin from 'vite-plugin-imagemin';
|
||||
|
||||
export function configImageminPlugin() {
|
||||
const plugin = viteImagemin({
|
||||
gifsicle: {
|
||||
optimizationLevel: 7,
|
||||
interlaced: false,
|
||||
},
|
||||
optipng: {
|
||||
optimizationLevel: 7,
|
||||
},
|
||||
mozjpeg: {
|
||||
quality: 20,
|
||||
},
|
||||
pngquant: {
|
||||
quality: [0.8, 0.9],
|
||||
speed: 4,
|
||||
},
|
||||
svgo: {
|
||||
plugins: [
|
||||
{
|
||||
name: 'removeViewBox',
|
||||
},
|
||||
{
|
||||
name: 'removeEmptyAttrs',
|
||||
active: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
return plugin;
|
||||
}
|
@@ -1,82 +0,0 @@
|
||||
import { PluginOption } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx';
|
||||
import legacy from '@vitejs/plugin-legacy';
|
||||
import purgeIcons from 'vite-plugin-purge-icons';
|
||||
import windiCSS from 'vite-plugin-windicss';
|
||||
import VitePluginCertificate from 'vite-plugin-mkcert';
|
||||
//import vueSetupExtend from 'vite-plugin-vue-setup-extend';
|
||||
import { configHtmlPlugin } from './html';
|
||||
import { configPwaConfig } from './pwa';
|
||||
import { configMockPlugin } from './mock';
|
||||
import { configCompressPlugin } from './compress';
|
||||
import { configStyleImportPlugin } from './styleImport';
|
||||
import { configVisualizerConfig } from './visualizer';
|
||||
import { configThemePlugin } from './theme';
|
||||
import { configImageminPlugin } from './imagemin';
|
||||
import { configSvgIconsPlugin } from './svgSprite';
|
||||
|
||||
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
|
||||
const {
|
||||
VITE_USE_IMAGEMIN,
|
||||
VITE_USE_MOCK,
|
||||
VITE_LEGACY,
|
||||
VITE_BUILD_COMPRESS,
|
||||
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE,
|
||||
} = viteEnv;
|
||||
|
||||
const vitePlugins: (PluginOption | PluginOption[])[] = [
|
||||
// have to
|
||||
vue(),
|
||||
// have to
|
||||
vueJsx(),
|
||||
// support name
|
||||
//vueSetupExtend(),
|
||||
VitePluginCertificate({
|
||||
source: 'coding',
|
||||
}),
|
||||
];
|
||||
|
||||
// vite-plugin-windicss
|
||||
vitePlugins.push(windiCSS());
|
||||
|
||||
// @vitejs/plugin-legacy
|
||||
VITE_LEGACY && isBuild && vitePlugins.push(legacy());
|
||||
|
||||
// vite-plugin-html
|
||||
vitePlugins.push(configHtmlPlugin(viteEnv, isBuild));
|
||||
|
||||
// vite-plugin-svg-icons
|
||||
vitePlugins.push(configSvgIconsPlugin(isBuild));
|
||||
|
||||
// vite-plugin-mock
|
||||
VITE_USE_MOCK && vitePlugins.push(configMockPlugin(isBuild));
|
||||
|
||||
// vite-plugin-purge-icons
|
||||
vitePlugins.push(purgeIcons());
|
||||
|
||||
// vite-plugin-style-import
|
||||
vitePlugins.push(configStyleImportPlugin(isBuild));
|
||||
|
||||
// rollup-plugin-visualizer
|
||||
vitePlugins.push(configVisualizerConfig());
|
||||
|
||||
// vite-plugin-theme
|
||||
vitePlugins.push(configThemePlugin(isBuild));
|
||||
|
||||
// The following plugins only work in the production environment
|
||||
if (isBuild) {
|
||||
// vite-plugin-imagemin
|
||||
VITE_USE_IMAGEMIN && vitePlugins.push(configImageminPlugin());
|
||||
|
||||
// rollup-plugin-gzip
|
||||
vitePlugins.push(
|
||||
configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE),
|
||||
);
|
||||
|
||||
// vite-plugin-pwa
|
||||
vitePlugins.push(configPwaConfig(viteEnv));
|
||||
}
|
||||
|
||||
return vitePlugins;
|
||||
}
|
@@ -1,33 +0,0 @@
|
||||
/**
|
||||
* Zero-config PWA for Vite
|
||||
* https://github.com/antfu/vite-plugin-pwa
|
||||
*/
|
||||
import { VitePWA } from 'vite-plugin-pwa';
|
||||
|
||||
export function configPwaConfig(env: ViteEnv) {
|
||||
const { VITE_USE_PWA, VITE_GLOB_APP_TITLE, VITE_GLOB_APP_SHORT_NAME } = env;
|
||||
|
||||
if (VITE_USE_PWA) {
|
||||
// vite-plugin-pwa
|
||||
const pwaPlugin = VitePWA({
|
||||
manifest: {
|
||||
name: VITE_GLOB_APP_TITLE,
|
||||
short_name: VITE_GLOB_APP_SHORT_NAME,
|
||||
icons: [
|
||||
{
|
||||
src: './resource/img/pwa-192x192.png',
|
||||
sizes: '192x192',
|
||||
type: 'image/png',
|
||||
},
|
||||
{
|
||||
src: './resource/img/pwa-512x512.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
return pwaPlugin;
|
||||
}
|
||||
return [];
|
||||
}
|
@@ -1,83 +0,0 @@
|
||||
/**
|
||||
* Introduces component library styles on demand.
|
||||
* https://github.com/anncwb/vite-plugin-style-import
|
||||
*/
|
||||
import { createStyleImportPlugin, VxeTableResolve } from 'vite-plugin-style-import';
|
||||
|
||||
export function configStyleImportPlugin(_isBuild: boolean) {
|
||||
if (!_isBuild) {
|
||||
return [];
|
||||
}
|
||||
const styleImportPlugin = createStyleImportPlugin({
|
||||
libs: [
|
||||
{
|
||||
libraryName: 'ant-design-vue',
|
||||
esModule: true,
|
||||
resolveStyle: (name) => {
|
||||
// 这里是无需额外引入样式文件的“子组件”列表
|
||||
const ignoreList = [
|
||||
'anchor-link',
|
||||
'sub-menu',
|
||||
'menu-item',
|
||||
'menu-divider',
|
||||
'menu-item-group',
|
||||
'breadcrumb-item',
|
||||
'breadcrumb-separator',
|
||||
'form-item',
|
||||
'step',
|
||||
'select-option',
|
||||
'select-opt-group',
|
||||
'card-grid',
|
||||
'card-meta',
|
||||
'collapse-panel',
|
||||
'descriptions-item',
|
||||
'list-item',
|
||||
'list-item-meta',
|
||||
'table-column',
|
||||
'table-column-group',
|
||||
'tab-pane',
|
||||
'tab-content',
|
||||
'timeline-item',
|
||||
'tree-node',
|
||||
'skeleton-input',
|
||||
'skeleton-avatar',
|
||||
'skeleton-title',
|
||||
'skeleton-paragraph',
|
||||
'skeleton-image',
|
||||
'skeleton-button',
|
||||
];
|
||||
// 这里是需要额外引入样式的子组件列表
|
||||
// 单独引入子组件时需引入组件样式,否则会在打包后导致子组件样式丢失
|
||||
const replaceList = {
|
||||
textarea: 'input',
|
||||
'typography-text': 'typography',
|
||||
'typography-title': 'typography',
|
||||
'typography-paragraph': 'typography',
|
||||
'typography-link': 'typography',
|
||||
'dropdown-button': 'dropdown',
|
||||
'input-password': 'input',
|
||||
'input-search': 'input',
|
||||
'input-group': 'input',
|
||||
'radio-group': 'radio',
|
||||
'checkbox-group': 'checkbox',
|
||||
'layout-sider': 'layout',
|
||||
'layout-content': 'layout',
|
||||
'layout-footer': 'layout',
|
||||
'layout-header': 'layout',
|
||||
'month-picker': 'date-picker',
|
||||
'range-picker': 'date-picker',
|
||||
'image-preview-group': 'image',
|
||||
};
|
||||
|
||||
return ignoreList.includes(name)
|
||||
? ''
|
||||
: replaceList.hasOwnProperty(name)
|
||||
? `ant-design-vue/es/${replaceList[name]}/style/index`
|
||||
: `ant-design-vue/es/${name}/style/index`;
|
||||
},
|
||||
},
|
||||
],
|
||||
resolves: [VxeTableResolve()],
|
||||
});
|
||||
return styleImportPlugin;
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
/**
|
||||
* Vite Plugin for fast creating SVG sprites.
|
||||
* https://github.com/anncwb/vite-plugin-svg-icons
|
||||
*/
|
||||
|
||||
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
|
||||
import path from 'path';
|
||||
|
||||
export function configSvgIconsPlugin(isBuild: boolean) {
|
||||
const svgIconsPlugin = createSvgIconsPlugin({
|
||||
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
|
||||
svgoOptions: isBuild,
|
||||
// default
|
||||
symbolId: 'icon-[dir]-[name]',
|
||||
});
|
||||
return svgIconsPlugin;
|
||||
}
|
@@ -1,89 +0,0 @@
|
||||
/**
|
||||
* Vite plugin for website theme color switching
|
||||
* https://github.com/anncwb/vite-plugin-theme
|
||||
*/
|
||||
import type { PluginOption } from 'vite';
|
||||
import path from 'path';
|
||||
import {
|
||||
viteThemePlugin,
|
||||
antdDarkThemePlugin,
|
||||
mixLighten,
|
||||
mixDarken,
|
||||
tinycolor,
|
||||
} from 'vite-plugin-theme';
|
||||
import { getThemeColors, generateColors } from '../../config/themeConfig';
|
||||
import { generateModifyVars } from '../../generate/generateModifyVars';
|
||||
|
||||
export function configThemePlugin(isBuild: boolean): PluginOption[] {
|
||||
const colors = generateColors({
|
||||
mixDarken,
|
||||
mixLighten,
|
||||
tinycolor,
|
||||
});
|
||||
const plugin = [
|
||||
viteThemePlugin({
|
||||
resolveSelector: (s) => {
|
||||
s = s.trim();
|
||||
switch (s) {
|
||||
case '.ant-steps-item-process .ant-steps-item-icon > .ant-steps-icon':
|
||||
return '.ant-steps-item-icon > .ant-steps-icon';
|
||||
case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled)':
|
||||
case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover':
|
||||
case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):active':
|
||||
return s;
|
||||
case '.ant-steps-item-icon > .ant-steps-icon':
|
||||
return s;
|
||||
case '.ant-select-item-option-selected:not(.ant-select-item-option-disabled)':
|
||||
return s;
|
||||
default:
|
||||
if (s.indexOf('.ant-btn') >= -1) {
|
||||
// 按钮被重新定制过,需要过滤掉class防止覆盖
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return s.startsWith('[data-theme') ? s : `[data-theme] ${s}`;
|
||||
},
|
||||
colorVariables: [...getThemeColors(), ...colors],
|
||||
}),
|
||||
antdDarkThemePlugin({
|
||||
preloadFiles: [
|
||||
path.resolve(process.cwd(), 'node_modules/ant-design-vue/dist/antd.less'),
|
||||
//path.resolve(process.cwd(), 'node_modules/ant-design-vue/dist/antd.dark.less'),
|
||||
path.resolve(process.cwd(), 'src/design/index.less'),
|
||||
],
|
||||
filter: (id) => (isBuild ? !id.endsWith('antd.less') : true),
|
||||
// extractCss: false,
|
||||
darkModifyVars: {
|
||||
...generateModifyVars(true),
|
||||
'text-color': '#c9d1d9',
|
||||
'primary-1': 'rgb(255 255 255 / 8%)',
|
||||
'text-color-base': '#c9d1d9',
|
||||
'component-background': '#151515',
|
||||
'heading-color': 'rgb(255 255 255 / 65%)',
|
||||
// black: '#0e1117',
|
||||
// #8b949e
|
||||
'text-color-secondary': '#8b949e',
|
||||
'border-color-base': '#303030',
|
||||
// 'border-color-split': '#30363d',
|
||||
'item-active-bg': '#111b26',
|
||||
'app-content-background': '#1e1e1e',
|
||||
'tree-node-selected-bg': '#11263c',
|
||||
|
||||
'alert-success-border-color': '#274916',
|
||||
'alert-success-bg-color': '#162312',
|
||||
'alert-success-icon-color': '#49aa19',
|
||||
'alert-info-border-color': '#153450',
|
||||
'alert-info-bg-color': '#111b26',
|
||||
'alert-info-icon-color': '#177ddc',
|
||||
'alert-warning-border-color': '#594214',
|
||||
'alert-warning-bg-color': '#2b2111',
|
||||
'alert-warning-icon-color': '#d89614',
|
||||
'alert-error-border-color': '#58181c',
|
||||
'alert-error-bg-color': '#2a1215',
|
||||
'alert-error-icon-color': '#a61d24',
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
return plugin as unknown as PluginOption[];
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
/**
|
||||
* Package file volume analysis
|
||||
*/
|
||||
import visualizer from 'rollup-plugin-visualizer';
|
||||
import { isReportMode } from '../../utils';
|
||||
|
||||
export function configVisualizerConfig() {
|
||||
if (isReportMode()) {
|
||||
return visualizer({
|
||||
filename: './node_modules/.cache/visualizer/stats.html',
|
||||
open: true,
|
||||
gzipSize: true,
|
||||
brotliSize: true,
|
||||
}) as Plugin;
|
||||
}
|
||||
return [];
|
||||
}
|
@@ -1,34 +0,0 @@
|
||||
/**
|
||||
* Used to parse the .env.development proxy configuration
|
||||
*/
|
||||
import type { ProxyOptions } from 'vite';
|
||||
|
||||
type ProxyItem = [string, string];
|
||||
|
||||
type ProxyList = ProxyItem[];
|
||||
|
||||
type ProxyTargetList = Record<string, ProxyOptions>;
|
||||
|
||||
const httpsRE = /^https:\/\//;
|
||||
|
||||
/**
|
||||
* Generate proxy
|
||||
* @param list
|
||||
*/
|
||||
export function createProxy(list: ProxyList = []) {
|
||||
const ret: ProxyTargetList = {};
|
||||
for (const [prefix, target] of list) {
|
||||
const isHttps = httpsRE.test(target);
|
||||
|
||||
// https://github.com/http-party/node-http-proxy#options
|
||||
ret[prefix] = {
|
||||
target: target,
|
||||
changeOrigin: true,
|
||||
ws: true,
|
||||
rewrite: (path) => path.replace(new RegExp(`^${prefix}`), ''),
|
||||
// https is require secure=false
|
||||
...(isHttps ? { secure: false } : {}),
|
||||
};
|
||||
}
|
||||
return ret;
|
||||
}
|
76
index.html
76
index.html
@@ -8,20 +8,10 @@
|
||||
name="viewport"
|
||||
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
|
||||
/>
|
||||
<title><%= title %></title>
|
||||
<title><%= VITE_GLOB_APP_TITLE %></title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
(() => {
|
||||
var htmlRoot = document.getElementById('htmlRoot');
|
||||
var theme = window.localStorage.getItem('__APP__DARK__MODE__');
|
||||
if (htmlRoot && theme) {
|
||||
htmlRoot.setAttribute('data-theme', theme);
|
||||
theme = htmlRoot = null;
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<div id="app">
|
||||
<style>
|
||||
html[data-theme='dark'] .app-loading {
|
||||
@@ -34,39 +24,39 @@
|
||||
|
||||
.app-loading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
background-color: #f4f7f9;
|
||||
}
|
||||
|
||||
.app-loading .app-loading-wrap {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
display: flex;
|
||||
transform: translate3d(-50%, -50%, 0);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transform: translate3d(-50%, -50%, 0);
|
||||
}
|
||||
|
||||
.app-loading .dots {
|
||||
display: flex;
|
||||
padding: 98px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 98px;
|
||||
}
|
||||
|
||||
.app-loading .app-loading-title {
|
||||
display: flex;
|
||||
margin-top: 30px;
|
||||
font-size: 30px;
|
||||
color: rgb(0 0 0 / 85%);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 30px;
|
||||
color: rgb(0 0 0 / 85%);
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
.app-loading .app-loading-logo {
|
||||
@@ -77,28 +67,28 @@
|
||||
}
|
||||
|
||||
.dot {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin-top: 30px;
|
||||
font-size: 32px;
|
||||
transform: rotate(45deg);
|
||||
box-sizing: border-box;
|
||||
animation: antRotate 1.2s infinite linear;
|
||||
animation: ant-rotate 1.2s infinite linear;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.dot i {
|
||||
position: absolute;
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #0065cc;
|
||||
border-radius: 100%;
|
||||
opacity: 30%;
|
||||
transform: scale(0.75);
|
||||
animation: antSpinMove 1s infinite linear alternate;
|
||||
transform-origin: 50% 50%;
|
||||
animation: ant-spin-move 1s infinite linear alternate;
|
||||
border-radius: 100%;
|
||||
opacity: 0.3;
|
||||
background-color: #0065cc;
|
||||
}
|
||||
|
||||
.dot i:nth-child(1) {
|
||||
@@ -123,34 +113,38 @@
|
||||
left: 0;
|
||||
animation-delay: 1.2s;
|
||||
}
|
||||
@keyframes antRotate {
|
||||
|
||||
@keyframes ant-rotate {
|
||||
to {
|
||||
transform: rotate(405deg);
|
||||
}
|
||||
}
|
||||
@keyframes antRotate {
|
||||
|
||||
@keyframes ant-rotate {
|
||||
to {
|
||||
transform: rotate(405deg);
|
||||
}
|
||||
}
|
||||
@keyframes antSpinMove {
|
||||
|
||||
@keyframes ant-spin-move {
|
||||
to {
|
||||
opacity: 100%;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes antSpinMove {
|
||||
|
||||
@keyframes ant-spin-move {
|
||||
to {
|
||||
opacity: 100%;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div class="app-loading">
|
||||
<div class="app-loading-wrap">
|
||||
<img src="/resource/img/logo.png" class="app-loading-logo" alt="Logo" />
|
||||
<img src="/logo.png" class="app-loading-logo" alt="Logo" />
|
||||
<div class="app-loading-dots">
|
||||
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
|
||||
</div>
|
||||
<div class="app-loading-title"><%= title %></div>
|
||||
<div class="app-loading-title"><%= VITE_GLOB_APP_TITLE %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
4
internal/eslint-config/.eslintrc.js
Normal file
4
internal/eslint-config/.eslintrc.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['@vben/eslint-config/strict'],
|
||||
};
|
10
internal/eslint-config/build.config.ts
Normal file
10
internal/eslint-config/build.config.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { defineBuildConfig } from 'unbuild';
|
||||
|
||||
export default defineBuildConfig({
|
||||
clean: true,
|
||||
entries: ['src/index', 'src/strict'],
|
||||
declaration: true,
|
||||
rollup: {
|
||||
emitCJS: true,
|
||||
},
|
||||
});
|
49
internal/eslint-config/package.json
Normal file
49
internal/eslint-config/package.json
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "@vben/eslint-config",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": {
|
||||
"url": "https://github.com/vbenjs/vue-vben-admin/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
||||
"directory": "internal/eslint-config"
|
||||
},
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.mjs",
|
||||
"require": "./dist/index.cjs"
|
||||
},
|
||||
"./strict": {
|
||||
"types": "./dist/strict.d.ts",
|
||||
"import": "./dist/strict.mjs",
|
||||
"require": "./dist/strict.cjs"
|
||||
}
|
||||
},
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"clean": "pnpm rimraf .turbo node_modules dist",
|
||||
"lint": "pnpm eslint .",
|
||||
"stub": "pnpm unbuild --stub"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^5.57.1",
|
||||
"@typescript-eslint/parser": "^5.57.1",
|
||||
"eslint": "^8.37.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-simple-import-sort": "^10.0.0",
|
||||
"eslint-plugin-vue": "^9.10.0",
|
||||
"vue-eslint-parser": "^9.1.1"
|
||||
}
|
||||
}
|
92
internal/eslint-config/src/index.ts
Normal file
92
internal/eslint-config/src/index.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
export default {
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
es6: true,
|
||||
},
|
||||
parser: 'vue-eslint-parser',
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser',
|
||||
ecmaVersion: 2020,
|
||||
sourceType: 'module',
|
||||
jsxPragma: 'React',
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
project: './tsconfig.*?.json',
|
||||
createDefaultProgram: false,
|
||||
extraFileExtensions: ['.vue'],
|
||||
},
|
||||
plugins: ['vue', '@typescript-eslint', 'import'],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:vue/vue3-recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:prettier/recommended',
|
||||
],
|
||||
rules: {
|
||||
'no-unused-vars': 'off',
|
||||
'no-case-declarations': 'off',
|
||||
'no-use-before-define': 'off',
|
||||
'space-before-function-paren': 'off',
|
||||
|
||||
'import/first': 'error',
|
||||
'import/newline-after-import': 'error',
|
||||
'import/no-duplicates': 'error',
|
||||
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/ban-ts-ignore': 'off',
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'@typescript-eslint/ban-types': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-var-requires': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'@typescript-eslint/no-use-before-define': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'vue/script-setup-uses-vars': 'error',
|
||||
'vue/no-reserved-component-names': 'off',
|
||||
'vue/custom-event-name-casing': 'off',
|
||||
'vue/attributes-order': 'off',
|
||||
'vue/one-component-per-file': 'off',
|
||||
'vue/html-closing-bracket-newline': 'off',
|
||||
'vue/max-attributes-per-line': 'off',
|
||||
'vue/multiline-html-element-content-newline': 'off',
|
||||
'vue/singleline-html-element-content-newline': 'off',
|
||||
'vue/attribute-hyphenation': 'off',
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/require-explicit-emits': 'off',
|
||||
'vue/prefer-import-from-vue': 'off',
|
||||
'vue/html-self-closing': [
|
||||
'error',
|
||||
{
|
||||
html: {
|
||||
void: 'always',
|
||||
normal: 'never',
|
||||
component: 'always',
|
||||
},
|
||||
svg: 'always',
|
||||
math: 'always',
|
||||
},
|
||||
],
|
||||
'vue/multi-word-component-names': 'off',
|
||||
// 'sort-imports': [
|
||||
// 'error',
|
||||
// {
|
||||
// ignoreCase: true,
|
||||
// ignoreDeclarationSort: false,
|
||||
// ignoreMemberSort: false,
|
||||
// memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'],
|
||||
// allowSeparatedGroups: false,
|
||||
// },
|
||||
// ],
|
||||
},
|
||||
globals: { defineOptions: 'readonly' },
|
||||
};
|
66
internal/eslint-config/src/strict.ts
Normal file
66
internal/eslint-config/src/strict.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
export default {
|
||||
extends: ['@vben', 'plugin:import/recommended'],
|
||||
plugins: ['simple-import-sort'],
|
||||
rules: {
|
||||
'object-shorthand': ['error', 'always', { ignoreConstructors: false, avoidQuotes: true }],
|
||||
|
||||
'import/no-unresolved': 'off',
|
||||
|
||||
'simple-import-sort/imports': 'error',
|
||||
'simple-import-sort/exports': 'error',
|
||||
'@typescript-eslint/ban-ts-comment': [
|
||||
'error',
|
||||
{
|
||||
'ts-expect-error': 'allow-with-description',
|
||||
'ts-ignore': 'allow-with-description',
|
||||
'ts-nocheck': 'allow-with-description',
|
||||
'ts-check': false,
|
||||
},
|
||||
],
|
||||
|
||||
/**
|
||||
* 【强制】关键字前后有一个空格
|
||||
* @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/keyword-spacing.md
|
||||
*/
|
||||
'keyword-spacing': 'off',
|
||||
'@typescript-eslint/keyword-spacing': [
|
||||
'error',
|
||||
{
|
||||
before: true,
|
||||
after: true,
|
||||
overrides: {
|
||||
return: { after: true },
|
||||
throw: { after: true },
|
||||
case: { after: true },
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
/**
|
||||
* 禁止出现空函数,普通函数(非 async/await/generator)、箭头函数、类上的方法除外
|
||||
* @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-empty-function.md
|
||||
*/
|
||||
'no-empty-function': 'off',
|
||||
'@typescript-eslint/no-empty-function': [
|
||||
'error',
|
||||
{
|
||||
allow: ['arrowFunctions', 'functions', 'methods'],
|
||||
},
|
||||
],
|
||||
|
||||
/**
|
||||
* 优先使用 interface 而不是 type 定义对象类型
|
||||
* @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/consistent-type-definitions.md
|
||||
*/
|
||||
'@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
|
||||
|
||||
'vue/attributes-order': 'error',
|
||||
'vue/require-default-prop': 'error',
|
||||
},
|
||||
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
node: { extensions: ['.ts', '.d.ts', '.tsx'] },
|
||||
},
|
||||
},
|
||||
};
|
5
internal/eslint-config/tsconfig.json
Normal file
5
internal/eslint-config/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "@vben/ts-config/node.json",
|
||||
"include": ["src"]
|
||||
}
|
4
internal/stylelint-config/.eslintrc.js
Normal file
4
internal/stylelint-config/.eslintrc.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['@vben/eslint-config/strict'],
|
||||
};
|
10
internal/stylelint-config/build.config.ts
Normal file
10
internal/stylelint-config/build.config.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { defineBuildConfig } from 'unbuild';
|
||||
|
||||
export default defineBuildConfig({
|
||||
clean: true,
|
||||
entries: ['src/index'],
|
||||
declaration: true,
|
||||
rollup: {
|
||||
emitCJS: true,
|
||||
},
|
||||
});
|
49
internal/stylelint-config/package.json
Normal file
49
internal/stylelint-config/package.json
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "@vben/stylelint-config",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": {
|
||||
"url": "https://github.com/vbenjs/vue-vben-admin/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
||||
"directory": "internal/stylelint-config"
|
||||
},
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.mjs",
|
||||
"require": "./dist/index.cjs"
|
||||
}
|
||||
},
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"clean": "pnpm rimraf .turbo node_modules dist",
|
||||
"lint": "pnpm eslint .",
|
||||
"stub": "pnpm unbuild --stub"
|
||||
},
|
||||
"devDependencies": {
|
||||
"postcss": "^8.4.21",
|
||||
"postcss-html": "^1.5.0",
|
||||
"postcss-less": "^6.0.0",
|
||||
"postcss-scss": "^4.0.6",
|
||||
"prettier": "^2.8.7",
|
||||
"stylelint": "^15.4.0",
|
||||
"stylelint-config-property-sort-order-smacss": "^9.1.0",
|
||||
"stylelint-config-recommended": "^11.0.0",
|
||||
"stylelint-config-recommended-scss": "^9.0.1",
|
||||
"stylelint-config-recommended-vue": "^1.4.0",
|
||||
"stylelint-config-standard": "^32.0.0",
|
||||
"stylelint-config-standard-scss": "^7.0.1",
|
||||
"stylelint-order": "^6.0.3",
|
||||
"stylelint-prettier": "^3.0.0"
|
||||
}
|
||||
}
|
@@ -1,9 +1,29 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
plugins: ['stylelint-order'],
|
||||
extends: ['stylelint-config-standard', 'stylelint-config-prettier'],
|
||||
customSyntax: 'postcss-html',
|
||||
export default {
|
||||
extends: ['stylelint-config-standard', 'stylelint-config-property-sort-order-smacss'],
|
||||
plugins: ['stylelint-order', 'stylelint-prettier'],
|
||||
// customSyntax: 'postcss-html',
|
||||
overrides: [
|
||||
{
|
||||
files: ['**/*.(css|html|vue)'],
|
||||
customSyntax: 'postcss-html',
|
||||
},
|
||||
{
|
||||
files: ['*.less', '**/*.less'],
|
||||
customSyntax: 'postcss-less',
|
||||
extends: ['stylelint-config-standard', 'stylelint-config-recommended-vue'],
|
||||
},
|
||||
{
|
||||
files: ['*.scss', '**/*.scss'],
|
||||
customSyntax: 'postcss-scss',
|
||||
extends: ['stylelint-config-standard-scss', 'stylelint-config-recommended-vue/scss'],
|
||||
rule: {
|
||||
'scss/percent-placeholder-pattern': null,
|
||||
},
|
||||
},
|
||||
],
|
||||
rules: {
|
||||
'selector-not-notation': null,
|
||||
'import-notation': null,
|
||||
'function-no-unknown': null,
|
||||
'selector-class-pattern': null,
|
||||
'selector-pseudo-class-no-unknown': [
|
||||
@@ -32,18 +52,15 @@ module.exports = {
|
||||
'each',
|
||||
'include',
|
||||
'mixin',
|
||||
'extend',
|
||||
],
|
||||
},
|
||||
],
|
||||
'no-empty-source': null,
|
||||
'string-quotes': null,
|
||||
'named-grid-areas-no-invalid': null,
|
||||
'unicode-bom': 'never',
|
||||
'no-descending-specificity': null,
|
||||
'font-family-no-missing-generic-family-keyword': null,
|
||||
'declaration-colon-space-after': 'always-single-line',
|
||||
'declaration-colon-space-before': 'never',
|
||||
// 'declaration-block-trailing-semicolon': 'always',
|
||||
'rule-empty-line-before': [
|
||||
'always',
|
||||
{
|
||||
@@ -67,34 +84,8 @@ module.exports = {
|
||||
},
|
||||
'rules',
|
||||
],
|
||||
{ severity: 'warning' },
|
||||
{ severity: 'error' },
|
||||
],
|
||||
},
|
||||
ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts'],
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.vue', '**/*.vue', '*.html', '**/*.html'],
|
||||
extends: ['stylelint-config-recommended'],
|
||||
rules: {
|
||||
'keyframes-name-pattern': null,
|
||||
'selector-pseudo-class-no-unknown': [
|
||||
true,
|
||||
{
|
||||
ignorePseudoClasses: ['deep', 'global'],
|
||||
},
|
||||
],
|
||||
'selector-pseudo-element-no-unknown': [
|
||||
true,
|
||||
{
|
||||
ignorePseudoElements: ['v-deep', 'v-global', 'v-slotted'],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.less', '**/*.less'],
|
||||
customSyntax: 'postcss-less',
|
||||
extends: ['stylelint-config-standard', 'stylelint-config-recommended-vue'],
|
||||
},
|
||||
],
|
||||
};
|
5
internal/stylelint-config/tsconfig.json
Normal file
5
internal/stylelint-config/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "@vben/ts-config/node.json",
|
||||
"include": ["src"]
|
||||
}
|
27
internal/ts-config/base.json
Normal file
27
internal/ts-config/base.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"display": "Base",
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"declaration": true,
|
||||
"noImplicitOverride": true,
|
||||
"noUnusedLocals": true,
|
||||
"esModuleInterop": true,
|
||||
"useUnknownInCatchVariables": false,
|
||||
"composite": false,
|
||||
"declarationMap": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"inlineSources": false,
|
||||
"isolatedModules": true,
|
||||
"skipLibCheck": true,
|
||||
"noUnusedParameters": false,
|
||||
"preserveWatchOutput": true,
|
||||
"experimentalDecorators": true,
|
||||
"resolveJsonModule": true,
|
||||
"removeComments": true
|
||||
},
|
||||
"exclude": ["**/node_modules/**", "**/dist/**"]
|
||||
}
|
@@ -1,4 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"display": "Node Server Config",
|
||||
"extends": "./base.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"declaration": false,
|
12
internal/ts-config/node.json
Normal file
12
internal/ts-config/node.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"display": "Node Config",
|
||||
"extends": "./base.json",
|
||||
"compilerOptions": {
|
||||
"lib": ["ESNext"],
|
||||
"noImplicitAny": true,
|
||||
"sourceMap": true,
|
||||
"noEmit": true,
|
||||
"baseUrl": "./"
|
||||
}
|
||||
}
|
26
internal/ts-config/package.json
Normal file
26
internal/ts-config/package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "@vben/ts-config",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": {
|
||||
"url": "https://github.com/vbenjs/vue-vben-admin/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
||||
"directory": "internal/ts-config"
|
||||
},
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"base.json",
|
||||
"node.json",
|
||||
"vue.json",
|
||||
"node-server.json"
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/node": "^18.15.11",
|
||||
"unplugin-vue-define-options": "^1.3.3",
|
||||
"vite": "^4.3.0-beta.2"
|
||||
}
|
||||
}
|
11
internal/ts-config/vue-app.json
Normal file
11
internal/ts-config/vue-app.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"display": "Vue Application",
|
||||
"extends": "./base.json",
|
||||
"compilerOptions": {
|
||||
"jsx": "preserve",
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"noImplicitAny": false
|
||||
|
||||
}
|
||||
}
|
4
internal/vite-config/.eslintrc.js
Normal file
4
internal/vite-config/.eslintrc.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['@vben/eslint-config/strict'],
|
||||
};
|
10
internal/vite-config/build.config.ts
Normal file
10
internal/vite-config/build.config.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { defineBuildConfig } from 'unbuild';
|
||||
|
||||
export default defineBuildConfig({
|
||||
clean: true,
|
||||
entries: ['src/index'],
|
||||
declaration: true,
|
||||
rollup: {
|
||||
emitCJS: true,
|
||||
},
|
||||
});
|
59
internal/vite-config/package.json
Normal file
59
internal/vite-config/package.json
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"name": "@vben/vite-config",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": {
|
||||
"url": "https://github.com/vbenjs/vue-vben-admin/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
||||
"directory": "internal/vite-config"
|
||||
},
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.mjs",
|
||||
"require": "./dist/index.cjs"
|
||||
}
|
||||
},
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"clean": "pnpm rimraf .turbo node_modules dist",
|
||||
"lint": "pnpm eslint .",
|
||||
"stub": "pnpm unbuild --stub"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^7.0.0",
|
||||
"vite": "^4.3.0-beta.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^11.0.1",
|
||||
"@vitejs/plugin-vue": "^4.1.0",
|
||||
"@vitejs/plugin-vue-jsx": "^3.0.1",
|
||||
"ant-design-vue": "^3.2.17",
|
||||
"dayjs": "^1.11.7",
|
||||
"dotenv": "^16.0.3",
|
||||
"fs-extra": "^11.1.1",
|
||||
"less": "^4.1.3",
|
||||
"picocolors": "^1.0.0",
|
||||
"pkg-types": "^1.0.2",
|
||||
"rollup-plugin-visualizer": "^5.9.0",
|
||||
"sass": "^1.61.0",
|
||||
"unocss": "^0.50.6",
|
||||
"unplugin-vue-define-options": "^1.3.3",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-dts": "^2.2.0",
|
||||
"vite-plugin-html": "^3.2.0",
|
||||
"vite-plugin-mock": "^2.9.6",
|
||||
"vite-plugin-purge-icons": "^0.9.2",
|
||||
"vite-plugin-svg-icons": "^2.0.1"
|
||||
}
|
||||
}
|
114
internal/vite-config/src/config/application.ts
Normal file
114
internal/vite-config/src/config/application.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
import { readPackageJSON } from 'pkg-types';
|
||||
import { defineConfig, loadEnv, mergeConfig, type UserConfig } from 'vite';
|
||||
|
||||
import { createPlugins } from '../plugins';
|
||||
import { generateModifyVars } from '../utils/modifyVars';
|
||||
import { commonConfig } from './common';
|
||||
|
||||
interface DefineOptions {
|
||||
overrides?: UserConfig;
|
||||
options?: {
|
||||
//
|
||||
};
|
||||
}
|
||||
|
||||
function defineApplicationConfig(defineOptions: DefineOptions = {}) {
|
||||
const { overrides = {} } = defineOptions;
|
||||
|
||||
return defineConfig(async ({ command, mode }) => {
|
||||
const root = process.cwd();
|
||||
const isBuild = command === 'build';
|
||||
const { VITE_USE_MOCK, VITE_BUILD_COMPRESS, VITE_ENABLE_ANALYZE } = loadEnv(mode, root);
|
||||
|
||||
const defineData = await createDefineData(root);
|
||||
const plugins = await createPlugins({
|
||||
isBuild,
|
||||
root,
|
||||
enableAnalyze: VITE_ENABLE_ANALYZE === 'true',
|
||||
enableMock: VITE_USE_MOCK === 'true',
|
||||
compress: VITE_BUILD_COMPRESS,
|
||||
});
|
||||
|
||||
const pathResolve = (pathname: string) => resolve(root, '.', pathname);
|
||||
|
||||
const applicationConfig: UserConfig = {
|
||||
resolve: {
|
||||
alias: [
|
||||
{
|
||||
find: 'vue-i18n',
|
||||
replacement: 'vue-i18n/dist/vue-i18n.cjs.js',
|
||||
},
|
||||
// /@/xxxx => src/xxxx
|
||||
{
|
||||
find: /\/@\//,
|
||||
replacement: pathResolve('src') + '/',
|
||||
},
|
||||
// /#/xxxx => types/xxxx
|
||||
{
|
||||
find: /\/#\//,
|
||||
replacement: pathResolve('types') + '/',
|
||||
},
|
||||
// @/xxxx => src/xxxx
|
||||
{
|
||||
find: /@\//,
|
||||
replacement: pathResolve('src') + '/',
|
||||
},
|
||||
// #/xxxx => types/xxxx
|
||||
{
|
||||
find: /#\//,
|
||||
replacement: pathResolve('types') + '/',
|
||||
},
|
||||
],
|
||||
},
|
||||
define: defineData,
|
||||
build: {
|
||||
target: 'es2015',
|
||||
cssTarget: 'chrome80',
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks: {
|
||||
vue: ['vue', 'pinia', 'vue-router'],
|
||||
// antd: ['ant-design-vue', '@ant-design/icons-vue'],
|
||||
// vxe: ['vxe-table', 'vxe-table-plugin-export-xlsx', 'xe-utils'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
less: {
|
||||
modifyVars: generateModifyVars(),
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins,
|
||||
};
|
||||
|
||||
const mergedConfig = mergeConfig(commonConfig, applicationConfig);
|
||||
|
||||
return mergeConfig(mergedConfig, overrides);
|
||||
});
|
||||
}
|
||||
|
||||
async function createDefineData(root: string) {
|
||||
try {
|
||||
const pkgJson = await readPackageJSON(root);
|
||||
const { dependencies, devDependencies, name, version } = pkgJson;
|
||||
|
||||
const __APP_INFO__ = {
|
||||
pkg: { dependencies, devDependencies, name, version },
|
||||
lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
};
|
||||
return {
|
||||
__APP_INFO__: JSON.stringify(__APP_INFO__),
|
||||
};
|
||||
} catch (error) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
export { defineApplicationConfig };
|
27
internal/vite-config/src/config/common.ts
Normal file
27
internal/vite-config/src/config/common.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { presetTypography, presetUno } from 'unocss';
|
||||
import UnoCSS from 'unocss/vite';
|
||||
import { type UserConfig } from 'vite';
|
||||
|
||||
const commonConfig: UserConfig = {
|
||||
server: {
|
||||
host: true,
|
||||
},
|
||||
esbuild: {
|
||||
drop: ['console', 'debugger'],
|
||||
},
|
||||
build: {
|
||||
reportCompressedSize: false,
|
||||
chunkSizeWarningLimit: 1500,
|
||||
rollupOptions: {
|
||||
// TODO: Prevent memory overflow
|
||||
maxParallelFileOps: 3,
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
UnoCSS({
|
||||
presets: [presetUno(), presetTypography()],
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export { commonConfig };
|
42
internal/vite-config/src/config/package.ts
Normal file
42
internal/vite-config/src/config/package.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { readPackageJSON } from 'pkg-types';
|
||||
import { defineConfig, mergeConfig, type UserConfig } from 'vite';
|
||||
import dts from 'vite-plugin-dts';
|
||||
|
||||
import { commonConfig } from './common';
|
||||
|
||||
interface DefineOptions {
|
||||
overrides?: UserConfig;
|
||||
options?: {
|
||||
//
|
||||
};
|
||||
}
|
||||
|
||||
function definePackageConfig(defineOptions: DefineOptions = {}) {
|
||||
const { overrides = {} } = defineOptions;
|
||||
const root = process.cwd();
|
||||
return defineConfig(async () => {
|
||||
const { dependencies = {}, peerDependencies = {} } = await readPackageJSON(root);
|
||||
const packageConfig: UserConfig = {
|
||||
build: {
|
||||
lib: {
|
||||
entry: 'src/index.ts',
|
||||
formats: ['es'],
|
||||
fileName: () => 'index.mjs',
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [...Object.keys(dependencies), ...Object.keys(peerDependencies)],
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
dts({
|
||||
logLevel: 'error',
|
||||
}),
|
||||
],
|
||||
};
|
||||
const mergedConfig = mergeConfig(commonConfig, packageConfig);
|
||||
|
||||
return mergeConfig(mergedConfig, overrides);
|
||||
});
|
||||
}
|
||||
|
||||
export { definePackageConfig };
|
2
internal/vite-config/src/index.ts
Normal file
2
internal/vite-config/src/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './config/application';
|
||||
export * from './config/package';
|
96
internal/vite-config/src/plugins/appConfig.ts
Normal file
96
internal/vite-config/src/plugins/appConfig.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import colors from 'picocolors';
|
||||
import { readPackageJSON } from 'pkg-types';
|
||||
import { type PluginOption } from 'vite';
|
||||
|
||||
import { getEnvConfig } from '../utils/env';
|
||||
import { createContentHash } from '../utils/hash';
|
||||
|
||||
const GLOBAL_CONFIG_FILE_NAME = '_app.config.js';
|
||||
const PLUGIN_NAME = 'app-config';
|
||||
|
||||
async function createAppConfigPlugin({
|
||||
root,
|
||||
isBuild,
|
||||
}: {
|
||||
root: string;
|
||||
isBuild: boolean;
|
||||
}): Promise<PluginOption> {
|
||||
let publicPath: string;
|
||||
let source: string;
|
||||
if (!isBuild) {
|
||||
return {
|
||||
name: PLUGIN_NAME,
|
||||
};
|
||||
}
|
||||
const { version = '' } = await readPackageJSON(root);
|
||||
|
||||
return {
|
||||
name: PLUGIN_NAME,
|
||||
async configResolved(_config) {
|
||||
let appTitle = _config?.env?.VITE_GLOB_APP_TITLE ?? '';
|
||||
appTitle = appTitle.replace(/\s/g, '_');
|
||||
publicPath = _config.base;
|
||||
source = await getConfigSource(appTitle);
|
||||
},
|
||||
async transformIndexHtml(html) {
|
||||
publicPath = publicPath.endsWith('/') ? publicPath : `${publicPath}/`;
|
||||
|
||||
const appConfigSrc = `${
|
||||
publicPath || '/'
|
||||
}${GLOBAL_CONFIG_FILE_NAME}?v=${version}-${createContentHash(source)}}`;
|
||||
|
||||
return {
|
||||
html,
|
||||
tags: [
|
||||
{
|
||||
tag: 'script',
|
||||
attrs: {
|
||||
src: appConfigSrc,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
async generateBundle() {
|
||||
try {
|
||||
this.emitFile({
|
||||
type: 'asset',
|
||||
fileName: GLOBAL_CONFIG_FILE_NAME,
|
||||
source,
|
||||
});
|
||||
|
||||
console.log(colors.cyan(`✨configuration file is build successfully!`));
|
||||
} catch (error) {
|
||||
console.log(
|
||||
colors.red('configuration file configuration file failed to package:\n' + error),
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configuration file variable name
|
||||
* @param env
|
||||
*/
|
||||
const getVariableName = (title: string) => {
|
||||
return `__PRODUCTION__${title || '__APP'}__CONF__`.toUpperCase().replace(/\s/g, '');
|
||||
};
|
||||
|
||||
async function getConfigSource(appTitle: string) {
|
||||
const config = await getEnvConfig();
|
||||
const variableName = getVariableName(appTitle);
|
||||
const windowVariable = `window.${variableName}`;
|
||||
// Ensure that the variable will not be modified
|
||||
let source = `${windowVariable}=${JSON.stringify(config)};`;
|
||||
source += `
|
||||
Object.freeze(${windowVariable});
|
||||
Object.defineProperty(window, "${variableName}", {
|
||||
configurable: false,
|
||||
writable: false,
|
||||
});
|
||||
`.replace(/\s/g, '');
|
||||
return source;
|
||||
}
|
||||
|
||||
export { createAppConfigPlugin };
|
@@ -5,10 +5,13 @@
|
||||
import type { PluginOption } from 'vite';
|
||||
import compressPlugin from 'vite-plugin-compression';
|
||||
|
||||
export function configCompressPlugin(
|
||||
compress: 'gzip' | 'brotli' | 'none',
|
||||
export function configCompressPlugin({
|
||||
compress,
|
||||
deleteOriginFile = false,
|
||||
): PluginOption | PluginOption[] {
|
||||
}: {
|
||||
compress: string;
|
||||
deleteOriginFile?: boolean;
|
||||
}): PluginOption[] {
|
||||
const compressList = compress.split(',');
|
||||
|
||||
const plugins: PluginOption[] = [];
|
13
internal/vite-config/src/plugins/html.ts
Normal file
13
internal/vite-config/src/plugins/html.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Plugin to minimize and use ejs template syntax in index.html.
|
||||
* https://github.com/anncwb/vite-plugin-html
|
||||
*/
|
||||
import type { PluginOption } from 'vite';
|
||||
import { createHtmlPlugin } from 'vite-plugin-html';
|
||||
|
||||
export function configHtmlPlugin({ isBuild }: { isBuild: boolean }) {
|
||||
const htmlPlugin: PluginOption[] = createHtmlPlugin({
|
||||
minify: isBuild,
|
||||
});
|
||||
return htmlPlugin;
|
||||
}
|
61
internal/vite-config/src/plugins/index.ts
Normal file
61
internal/vite-config/src/plugins/index.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx';
|
||||
// @ts-ignore: type unless
|
||||
import DefineOptions from 'unplugin-vue-define-options/vite';
|
||||
import { type PluginOption } from 'vite';
|
||||
import purgeIcons from 'vite-plugin-purge-icons';
|
||||
|
||||
import { createAppConfigPlugin } from './appConfig';
|
||||
import { configCompressPlugin } from './compress';
|
||||
import { configHtmlPlugin } from './html';
|
||||
import { configMockPlugin } from './mock';
|
||||
import { configSvgIconsPlugin } from './svgSprite';
|
||||
import { configVisualizerConfig } from './visualizer';
|
||||
|
||||
interface Options {
|
||||
isBuild: boolean;
|
||||
root: string;
|
||||
compress: string;
|
||||
enableMock?: boolean;
|
||||
enableAnalyze?: boolean;
|
||||
}
|
||||
|
||||
async function createPlugins({ isBuild, root, enableMock, compress, enableAnalyze }: Options) {
|
||||
const vitePlugins: (PluginOption | PluginOption[])[] = [vue(), vueJsx(), DefineOptions()];
|
||||
|
||||
const appConfigPlugin = await createAppConfigPlugin({ root, isBuild });
|
||||
vitePlugins.push(appConfigPlugin);
|
||||
|
||||
// vite-plugin-html
|
||||
vitePlugins.push(configHtmlPlugin({ isBuild }));
|
||||
|
||||
// vite-plugin-svg-icons
|
||||
vitePlugins.push(configSvgIconsPlugin({ isBuild }));
|
||||
|
||||
// vite-plugin-purge-icons
|
||||
vitePlugins.push(purgeIcons());
|
||||
|
||||
// The following plugins only work in the production environment
|
||||
if (isBuild) {
|
||||
// rollup-plugin-gzip
|
||||
vitePlugins.push(
|
||||
configCompressPlugin({
|
||||
compress,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// rollup-plugin-visualizer
|
||||
if (enableAnalyze) {
|
||||
vitePlugins.push(configVisualizerConfig());
|
||||
}
|
||||
|
||||
// vite-plugin-mock
|
||||
if (enableMock) {
|
||||
vitePlugins.push(configMockPlugin({ isBuild }));
|
||||
}
|
||||
|
||||
return vitePlugins;
|
||||
}
|
||||
|
||||
export { createPlugins };
|
@@ -4,9 +4,9 @@
|
||||
*/
|
||||
import { viteMockServe } from 'vite-plugin-mock';
|
||||
|
||||
export function configMockPlugin(isBuild: boolean) {
|
||||
export function configMockPlugin({ isBuild }: { isBuild: boolean }) {
|
||||
return viteMockServe({
|
||||
ignore: /^\_/,
|
||||
ignore: /^_/,
|
||||
mockPath: 'mock',
|
||||
localEnabled: !isBuild,
|
||||
prodEnabled: isBuild,
|
17
internal/vite-config/src/plugins/svgSprite.ts
Normal file
17
internal/vite-config/src/plugins/svgSprite.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Vite Plugin for fast creating SVG sprites.
|
||||
* https://github.com/anncwb/vite-plugin-svg-icons
|
||||
*/
|
||||
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
import type { PluginOption } from 'vite';
|
||||
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
|
||||
|
||||
export function configSvgIconsPlugin({ isBuild }: { isBuild: boolean }) {
|
||||
const svgIconsPlugin = createSvgIconsPlugin({
|
||||
iconDirs: [resolve(process.cwd(), 'src/assets/icons')],
|
||||
svgoOptions: isBuild,
|
||||
});
|
||||
return svgIconsPlugin as PluginOption;
|
||||
}
|
14
internal/vite-config/src/plugins/visualizer.ts
Normal file
14
internal/vite-config/src/plugins/visualizer.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Package file volume analysis
|
||||
*/
|
||||
import visualizer from 'rollup-plugin-visualizer';
|
||||
import { type PluginOption } from 'vite';
|
||||
|
||||
export function configVisualizerConfig() {
|
||||
return visualizer({
|
||||
filename: './node_modules/.cache/visualizer/stats.html',
|
||||
open: true,
|
||||
gzipSize: true,
|
||||
brotliSize: true,
|
||||
}) as PluginOption;
|
||||
}
|
44
internal/vite-config/src/utils/env.ts
Normal file
44
internal/vite-config/src/utils/env.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { join } from 'node:path';
|
||||
|
||||
import dotenv from 'dotenv';
|
||||
import { readFile } from 'fs-extra';
|
||||
|
||||
/**
|
||||
* 获取当前环境下生效的配置文件名
|
||||
*/
|
||||
function getConfFiles() {
|
||||
const script = process.env.npm_lifecycle_script as string;
|
||||
const reg = new RegExp('--mode ([a-z_\\d]+)');
|
||||
const result = reg.exec(script);
|
||||
if (result) {
|
||||
const mode = result[1];
|
||||
return ['.env', `.env.${mode}`];
|
||||
}
|
||||
return ['.env', '.env.production'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the environment variables starting with the specified prefix
|
||||
* @param match prefix
|
||||
* @param confFiles ext
|
||||
*/
|
||||
export async function getEnvConfig(match = 'VITE_GLOB_', confFiles = getConfFiles()) {
|
||||
let envConfig = {};
|
||||
|
||||
for (const confFile of confFiles) {
|
||||
try {
|
||||
const envPath = await readFile(join(process.cwd(), confFile), { encoding: 'utf8' });
|
||||
const env = dotenv.parse(envPath);
|
||||
envConfig = { ...envConfig, ...env };
|
||||
} catch (e) {
|
||||
console.error(`Error in parsing ${confFile}`, e);
|
||||
}
|
||||
}
|
||||
const reg = new RegExp(`^(${match})`);
|
||||
Object.keys(envConfig).forEach((key) => {
|
||||
if (!reg.test(key)) {
|
||||
Reflect.deleteProperty(envConfig, key);
|
||||
}
|
||||
});
|
||||
return envConfig;
|
||||
}
|
8
internal/vite-config/src/utils/hash.ts
Normal file
8
internal/vite-config/src/utils/hash.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { createHash } from 'node:crypto';
|
||||
|
||||
function createContentHash(content: string, hashLSize = 12) {
|
||||
const hash = createHash('sha256').update(content);
|
||||
return hash.digest('hex').slice(0, hashLSize);
|
||||
}
|
||||
|
||||
export { createContentHash };
|
@@ -1,11 +1,21 @@
|
||||
import { generateAntColors, primaryColor } from '../config/themeConfig';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
import { generate } from '@ant-design/colors';
|
||||
// @ts-ignore: typo
|
||||
import { getThemeVariables } from 'ant-design-vue/dist/theme';
|
||||
import { resolve } from 'path';
|
||||
|
||||
const primaryColor = '#0960bd';
|
||||
|
||||
function generateAntColors(color: string, theme: 'default' | 'dark' = 'default') {
|
||||
return generate(color, {
|
||||
theme,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* less global variable
|
||||
*/
|
||||
export function generateModifyVars(dark = false) {
|
||||
export function generateModifyVars() {
|
||||
const palettes = generateAntColors(primaryColor);
|
||||
const primary = palettes[5];
|
||||
|
||||
@@ -15,10 +25,9 @@ export function generateModifyVars(dark = false) {
|
||||
primaryColorObj[`primary-${index + 1}`] = palettes[index];
|
||||
}
|
||||
|
||||
const modifyVars = getThemeVariables({ dark });
|
||||
const modifyVars = getThemeVariables();
|
||||
return {
|
||||
...modifyVars,
|
||||
// Used for global import to avoid the need to import each style file separately
|
||||
// reference: Avoid repeated references
|
||||
hack: `${modifyVars.hack} @import (reference) "${resolve('src/design/config.less')}";`,
|
||||
'primary-color': primary,
|
||||
@@ -28,7 +37,6 @@ export function generateModifyVars(dark = false) {
|
||||
'success-color': '#55D187', // Success color
|
||||
'error-color': '#ED6F6F', // False color
|
||||
'warning-color': '#EFBD47', // Warning color
|
||||
//'border-color-base': '#EEEEEE',
|
||||
'font-size-base': '14px', // Main font size
|
||||
'border-radius-base': '2px', // Component/float fillet
|
||||
'link-color': primary, // Link color
|
5
internal/vite-config/tsconfig.json
Normal file
5
internal/vite-config/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "@vben/ts-config/node.json",
|
||||
"include": ["src"]
|
||||
}
|
279
package.json
279
package.json
@@ -1,177 +1,45 @@
|
||||
{
|
||||
"name": "vben-admin",
|
||||
"version": "2.9.0",
|
||||
"version": "3.0.0-alpha.1",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": {
|
||||
"url": "https://github.com/vbenjs/vue-vben-admin/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "vben",
|
||||
"email": "anncwb@126.com",
|
||||
"url": "https://github.com/anncwb"
|
||||
},
|
||||
"scripts": {
|
||||
"commit": "czg",
|
||||
"bootstrap": "pnpm install",
|
||||
"serve": "npm run dev",
|
||||
"dev": "vite",
|
||||
"build": "cross-env NODE_ENV=production vite build && esno ./build/script/postBuild.ts",
|
||||
"build:test": "cross-env vite build --mode test && esno ./build/script/postBuild.ts",
|
||||
"build": "cross-env NODE_ENV=production pnpm vite build",
|
||||
"build:analyze": "pnpm vite build --mode analyze",
|
||||
"build:no-cache": "pnpm clean:cache && npm run build",
|
||||
"report": "cross-env REPORT=true npm run build",
|
||||
"type:check": "vue-tsc --noEmit --skipLibCheck",
|
||||
"preview": "npm run build && vite preview",
|
||||
"preview:dist": "vite preview",
|
||||
"log": "conventional-changelog -p angular -i CHANGELOG.md -s",
|
||||
"clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite",
|
||||
"clean:lib": "rimraf node_modules",
|
||||
"build:test": "pnpm vite build --mode test",
|
||||
"commit": "czg",
|
||||
"dev": "pnpm vite",
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
"postinstall": "turbo run stub",
|
||||
"lint": "turbo run lint",
|
||||
"lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
|
||||
"lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
|
||||
"lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
|
||||
"lint:lint-staged": "lint-staged",
|
||||
"test:unit": "jest",
|
||||
"test:gzip": "npx http-server dist --cors --gzip -c-1",
|
||||
"test:br": "npx http-server dist --cors --brotli -c-1",
|
||||
"reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
|
||||
"lint:prettier": "prettier --write .",
|
||||
"lint:stylelint": "stylelint \"**/*.{vue,css,less.scss}\" --fix --cache --cache-location node_modules/.cache/stylelint/",
|
||||
"prepare": "husky install",
|
||||
"gen:icon": "esno ./build/generate/icon/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^6.0.0",
|
||||
"@ant-design/icons-vue": "^6.1.0",
|
||||
"@iconify/iconify": "^2.2.1",
|
||||
"@logicflow/core": "^1.1.13",
|
||||
"@logicflow/extension": "^1.1.13",
|
||||
"@vue/runtime-core": "^3.2.33",
|
||||
"@vue/shared": "^3.2.33",
|
||||
"@vueuse/core": "^8.3.0",
|
||||
"@vueuse/shared": "^8.3.0",
|
||||
"@zxcvbn-ts/core": "^2.0.1",
|
||||
"ant-design-vue": "^3.2.0",
|
||||
"axios": "^0.26.1",
|
||||
"codemirror": "^5.65.3",
|
||||
"cropperjs": "^1.5.12",
|
||||
"crypto-js": "^4.1.1",
|
||||
"dayjs": "^1.11.1",
|
||||
"echarts": "^5.3.2",
|
||||
"exceljs": "^4.3.0",
|
||||
"intro.js": "^5.1.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mockjs": "^1.1.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-to-regexp": "^6.2.0",
|
||||
"pinia": "2.0.12",
|
||||
"print-js": "^1.6.0",
|
||||
"qrcode": "^1.5.0",
|
||||
"qs": "^6.10.3",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"showdown": "^2.1.0",
|
||||
"sortablejs": "^1.15.0",
|
||||
"tinymce": "^5.10.7",
|
||||
"vditor": "^3.8.13",
|
||||
"vue": "^3.2.45",
|
||||
"vue-i18n": "^9.1.9",
|
||||
"vue-json-pretty": "^2.0.6",
|
||||
"vue-router": "^4.0.14",
|
||||
"vue-types": "^4.1.1",
|
||||
"vxe-table": "^4.3.9",
|
||||
"vxe-table-plugin-export-xlsx": "^3.0.4",
|
||||
"xe-utils": "^3.5.7",
|
||||
"xlsx": "^0.18.5",
|
||||
"vuedraggable": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^16.2.3",
|
||||
"@commitlint/config-conventional": "^16.2.1",
|
||||
"@iconify/json": "^2.1.30",
|
||||
"@purge-icons/generated": "^0.8.1",
|
||||
"@types/codemirror": "^5.60.5",
|
||||
"@types/crypto-js": "^4.1.1",
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
"@types/inquirer": "^8.2.1",
|
||||
"@types/intro.js": "^3.0.2",
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"@types/mockjs": "^1.0.6",
|
||||
"@types/node": "^17.0.25",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
"@types/qrcode": "^1.4.2",
|
||||
"@types/qs": "^6.9.7",
|
||||
"@types/showdown": "^1.9.4",
|
||||
"@types/sortablejs": "^1.10.7",
|
||||
"@typescript-eslint/eslint-plugin": "^5.20.0",
|
||||
"@typescript-eslint/parser": "^5.20.0",
|
||||
"@vitejs/plugin-legacy": "^1.8.1",
|
||||
"@vitejs/plugin-vue": "^2.3.1",
|
||||
"@vitejs/plugin-vue-jsx": "^1.3.10",
|
||||
"@vue/compiler-sfc": "^3.2.33",
|
||||
"@vue/test-utils": "^2.0.0-rc.21",
|
||||
"autoprefixer": "^10.4.4",
|
||||
"conventional-changelog-cli": "^2.2.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"cz-git": "^1.3.9",
|
||||
"czg": "^1.3.9",
|
||||
"dotenv": "^16.0.0",
|
||||
"eslint": "^8.13.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-vue": "^8.6.0",
|
||||
"esno": "^0.14.1",
|
||||
"fs-extra": "^10.1.0",
|
||||
"husky": "^7.0.4",
|
||||
"inquirer": "^8.2.2",
|
||||
"less": "^4.1.2",
|
||||
"lint-staged": "12.3.7",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"picocolors": "^1.0.0",
|
||||
"postcss": "^8.4.12",
|
||||
"postcss-html": "^1.4.1",
|
||||
"postcss-less": "^6.0.0",
|
||||
"prettier": "^2.6.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"rollup": "^2.70.2",
|
||||
"rollup-plugin-visualizer": "^5.6.0",
|
||||
"sass": "^1.57.1",
|
||||
"stylelint": "^14.7.1",
|
||||
"stylelint-config-prettier": "^9.0.3",
|
||||
"stylelint-config-recommended": "^7.0.0",
|
||||
"stylelint-config-recommended-vue": "^1.4.0",
|
||||
"stylelint-config-standard": "^25.0.0",
|
||||
"stylelint-order": "^5.0.0",
|
||||
"ts-node": "^10.7.0",
|
||||
"typescript": "^4.6.3",
|
||||
"vite": "^2.9.5",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-html": "^3.2.0",
|
||||
"vite-plugin-imagemin": "^0.6.1",
|
||||
"vite-plugin-mkcert": "^1.6.0",
|
||||
"vite-plugin-mock": "^2.9.6",
|
||||
"vite-plugin-purge-icons": "^0.8.1",
|
||||
"vite-plugin-pwa": "^0.11.13",
|
||||
"vite-plugin-style-import": "^2.0.0",
|
||||
"vite-plugin-svg-icons": "^2.0.1",
|
||||
"vite-plugin-theme": "^0.8.6",
|
||||
"vite-plugin-vue-setup-extend": "^0.4.0",
|
||||
"vite-plugin-windicss": "^1.8.4",
|
||||
"vue-eslint-parser": "^8.3.0",
|
||||
"vue-tsc": "^1.0.9"
|
||||
},
|
||||
"resolutions": {
|
||||
"bin-wrapper": "npm:bin-wrapper-china",
|
||||
"rollup": "^2.56.3",
|
||||
"gifsicle": "5.2.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/anncwb/vue-vben-admin.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/anncwb/vue-vben-admin/issues"
|
||||
},
|
||||
"homepage": "https://github.com/anncwb/vue-vben-admin",
|
||||
"engines": {
|
||||
"node": "^12 || >=14"
|
||||
"preview": "npm run build && vite preview",
|
||||
"reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
|
||||
"serve": "npm run dev",
|
||||
"test:gzip": "npx http-server dist --cors --gzip -c-1",
|
||||
"type:check": "vue-tsc --noEmit --skipLibCheck"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,ts,tsx}": [
|
||||
"eslint --fix",
|
||||
"prettier --write"
|
||||
"prettier --write",
|
||||
"eslint --fix"
|
||||
],
|
||||
"{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [
|
||||
"prettier --write--parser json"
|
||||
@@ -180,13 +48,13 @@
|
||||
"prettier --write"
|
||||
],
|
||||
"*.vue": [
|
||||
"eslint --fix",
|
||||
"prettier --write",
|
||||
"eslint --fix",
|
||||
"stylelint --fix"
|
||||
],
|
||||
"*.{scss,less,styl,html}": [
|
||||
"stylelint --fix",
|
||||
"prettier --write"
|
||||
"prettier --write",
|
||||
"stylelint --fix"
|
||||
],
|
||||
"*.md": [
|
||||
"prettier --write"
|
||||
@@ -196,5 +64,92 @@
|
||||
"commitizen": {
|
||||
"path": "node_modules/cz-git"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons-vue": "^6.1.0",
|
||||
"@iconify/iconify": "^3.1.0",
|
||||
"@logicflow/core": "^1.2.1",
|
||||
"@logicflow/extension": "^1.2.1",
|
||||
"@vben/hooks": "workspace:*",
|
||||
"@vben/shared": "workspace:*",
|
||||
"@vue/shared": "^3.2.47",
|
||||
"@vueuse/core": "^9.13.0",
|
||||
"@vueuse/shared": "^9.13.0",
|
||||
"@zxcvbn-ts/core": "^2.2.1",
|
||||
"ant-design-vue": "^3.2.17",
|
||||
"axios": "^1.3.5",
|
||||
"codemirror": "^5.65.12",
|
||||
"cropperjs": "^1.5.13",
|
||||
"crypto-js": "^4.1.1",
|
||||
"dayjs": "^1.11.7",
|
||||
"echarts": "^5.4.2",
|
||||
"exceljs": "^4.3.0",
|
||||
"intro.js": "^7.0.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mockjs": "^1.1.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-to-regexp": "^6.2.1",
|
||||
"pinia": "2.0.33",
|
||||
"print-js": "^1.6.0",
|
||||
"qrcode": "^1.5.1",
|
||||
"qs": "^6.11.1",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"showdown": "^2.1.0",
|
||||
"sortablejs": "^1.15.0",
|
||||
"tinymce": "^5.10.7",
|
||||
"vditor": "^3.9.1",
|
||||
"vue": "^3.2.47",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-json-pretty": "^2.2.4",
|
||||
"vue-router": "^4.1.6",
|
||||
"vue-types": "^5.0.2",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"vxe-table": "^4.3.11",
|
||||
"vxe-table-plugin-export-xlsx": "^3.0.4",
|
||||
"xe-utils": "^3.5.7",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^17.5.1",
|
||||
"@commitlint/config-conventional": "^17.4.4",
|
||||
"@iconify/json": "^2.2.46",
|
||||
"@purge-icons/generated": "^0.9.0",
|
||||
"@types/codemirror": "^5.60.7",
|
||||
"@types/crypto-js": "^4.1.1",
|
||||
"@types/intro.js": "^5.1.1",
|
||||
"@types/lodash-es": "^4.17.7",
|
||||
"@types/mockjs": "^1.0.7",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
"@types/qrcode": "^1.5.0",
|
||||
"@types/qs": "^6.9.7",
|
||||
"@types/showdown": "^2.0.0",
|
||||
"@types/sortablejs": "^1.15.1",
|
||||
"@vben/eslint-config": "workspace:*",
|
||||
"@vben/stylelint-config": "workspace:*",
|
||||
"@vben/ts-config": "workspace:*",
|
||||
"@vben/types": "workspace:*",
|
||||
"@vben/vite-config": "workspace:*",
|
||||
"@vue/compiler-sfc": "^3.2.47",
|
||||
"@vue/test-utils": "^2.3.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"cz-git": "^1.6.1",
|
||||
"czg": "^1.6.1",
|
||||
"husky": "^8.0.3",
|
||||
"lint-staged": "13.2.0",
|
||||
"prettier": "^2.8.7",
|
||||
"prettier-plugin-packagejson": "^2.4.3",
|
||||
"rimraf": "^4.4.1",
|
||||
"turbo": "^1.8.8",
|
||||
"typescript": "^5.0.3",
|
||||
"unbuild": "^1.2.0",
|
||||
"unplugin-vue-define-options": "^1.3.3",
|
||||
"vite": "^4.3.0-beta.2",
|
||||
"vite-plugin-mock": "^2.9.6",
|
||||
"vue-tsc": "^1.2.0"
|
||||
},
|
||||
"packageManager": "pnpm@8.1.0",
|
||||
"engines": {
|
||||
"node": ">=16.15.1",
|
||||
"pnpm": ">=8.1.0"
|
||||
}
|
||||
}
|
||||
|
0
packages/.gitkeep
Normal file
0
packages/.gitkeep
Normal file
4
packages/hooks/.eslintrc.js
Normal file
4
packages/hooks/.eslintrc.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['@vben/eslint-config/strict'],
|
||||
};
|
10
packages/hooks/build.config.ts
Normal file
10
packages/hooks/build.config.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { defineBuildConfig } from 'unbuild';
|
||||
|
||||
export default defineBuildConfig({
|
||||
clean: true,
|
||||
entries: ['src/index'],
|
||||
declaration: true,
|
||||
rollup: {
|
||||
emitCJS: true,
|
||||
},
|
||||
});
|
38
packages/hooks/package.json
Normal file
38
packages/hooks/package.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "@vben/hooks",
|
||||
"version": "1.0.0",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": {
|
||||
"url": "https://github.com/vbenjs/vue-vben-admin/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
||||
"directory": "packages/hooks"
|
||||
},
|
||||
"license": "MIT",
|
||||
"sideEffects": false,
|
||||
"exports": {
|
||||
".": {
|
||||
"default": "./src/index.ts"
|
||||
}
|
||||
},
|
||||
"main": "./src/index.ts",
|
||||
"module": "./src/index.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"//build": "pnpm unbuild",
|
||||
"//stub": "pnpm unbuild --stub",
|
||||
"clean": "pnpm rimraf .turbo node_modules dist",
|
||||
"lint": "pnpm eslint ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@vueuse/core": "^9.13.0",
|
||||
"vue": "^3.2.47"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vben/types": "workspace:*"
|
||||
}
|
||||
}
|
6
packages/hooks/src/index.ts
Normal file
6
packages/hooks/src/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export * from './onMountedOrActivated';
|
||||
export * from './useAttrs';
|
||||
export * from './useRefs';
|
||||
export * from './useScrollTo';
|
||||
export * from './useWindowSizeFn';
|
||||
export { useTimeoutFn } from '@vueuse/core';
|
25
packages/hooks/src/onMountedOrActivated.ts
Normal file
25
packages/hooks/src/onMountedOrActivated.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { type AnyFunction } from '@vben/types';
|
||||
import { nextTick, onActivated, onMounted } from 'vue';
|
||||
|
||||
/**
|
||||
* 在 OnMounted 或者 OnActivated 时触发
|
||||
* @param hook 任何函数(包括异步函数)
|
||||
*/
|
||||
function onMountedOrActivated(hook: AnyFunction) {
|
||||
let mounted: boolean;
|
||||
|
||||
onMounted(() => {
|
||||
hook();
|
||||
nextTick(() => {
|
||||
mounted = true;
|
||||
});
|
||||
});
|
||||
|
||||
onActivated(() => {
|
||||
if (mounted) {
|
||||
hook();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export { onMountedOrActivated };
|
@@ -1,24 +1,44 @@
|
||||
import { getCurrentInstance, reactive, shallowRef, watchEffect } from 'vue';
|
||||
import type { Ref } from 'vue';
|
||||
interface Params {
|
||||
import { type Recordable } from '@vben/types';
|
||||
import { getCurrentInstance, reactive, type ShallowRef, shallowRef, watchEffect } from 'vue';
|
||||
|
||||
interface UseAttrsOptions {
|
||||
/**
|
||||
* 排除监听事件
|
||||
* @default false
|
||||
*/
|
||||
excludeListeners?: boolean;
|
||||
/**
|
||||
* 排除部分对象 key值
|
||||
* @default []
|
||||
*/
|
||||
excludeKeys?: string[];
|
||||
/**
|
||||
* 排除默认值 key 值 ['class', 'style']
|
||||
* @default true
|
||||
*/
|
||||
excludeDefaultKeys?: boolean;
|
||||
}
|
||||
|
||||
const DEFAULT_EXCLUDE_KEYS = ['class', 'style'];
|
||||
const LISTENER_PREFIX = /^on[A-Z]/;
|
||||
|
||||
export function entries<T>(obj: Recordable<T>): [string, T][] {
|
||||
function entries<T>(obj: Recordable<T>): [string, T][] {
|
||||
return Object.keys(obj).map((key: string) => [key, obj[key]]);
|
||||
}
|
||||
|
||||
export function useAttrs(params: Params = {}): Ref<Recordable> | {} {
|
||||
/**
|
||||
* 获取当前组件的 Attrs 属性
|
||||
* @param UseAttrsOptions
|
||||
*/
|
||||
function useAttrs<T = any>(options: UseAttrsOptions = {}): ShallowRef<Recordable<T>> {
|
||||
const instance = getCurrentInstance();
|
||||
if (!instance) return {};
|
||||
|
||||
const { excludeListeners = false, excludeKeys = [], excludeDefaultKeys = true } = params;
|
||||
const attrs = shallowRef({});
|
||||
|
||||
if (!instance) {
|
||||
return attrs;
|
||||
}
|
||||
|
||||
const { excludeListeners = false, excludeKeys = [], excludeDefaultKeys = true } = options;
|
||||
const allExcludeKeys = excludeKeys.concat(excludeDefaultKeys ? DEFAULT_EXCLUDE_KEYS : []);
|
||||
|
||||
// Since attrs are not reactive, make it reactive instead of doing in `onUpdated` hook for better performance
|
||||
@@ -31,10 +51,12 @@ export function useAttrs(params: Params = {}): Ref<Recordable> | {} {
|
||||
}
|
||||
|
||||
return acm;
|
||||
}, {} as Recordable);
|
||||
}, {} as Recordable<any>);
|
||||
|
||||
attrs.value = res;
|
||||
});
|
||||
|
||||
return attrs;
|
||||
}
|
||||
|
||||
export { useAttrs, type UseAttrsOptions };
|
34
packages/hooks/src/useRefs.ts
Normal file
34
packages/hooks/src/useRefs.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { type ComponentPublicInstance, onBeforeUpdate, type Ref, shallowRef } from 'vue';
|
||||
|
||||
type SetRefsFunctionRef = Element | ComponentPublicInstance | null;
|
||||
|
||||
interface SetRefsFunction {
|
||||
(ref: SetRefsFunctionRef, refs: Record<string, any>): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于模版循环获取 refs
|
||||
* <div :ref="setRefs(index)"></div>
|
||||
* @returns
|
||||
*/
|
||||
function useRefs(): {
|
||||
refs: Ref<HTMLElement[]>;
|
||||
setRefs: (index: number) => SetRefsFunction;
|
||||
} {
|
||||
const refs = shallowRef([]) as Ref<HTMLElement[]>;
|
||||
|
||||
onBeforeUpdate(() => {
|
||||
refs.value = [];
|
||||
});
|
||||
|
||||
const setRefs = (index: number) => (ref: SetRefsFunctionRef, refs: Record<string, any>) => {
|
||||
refs.value[index] = ref;
|
||||
};
|
||||
|
||||
return {
|
||||
refs,
|
||||
setRefs,
|
||||
};
|
||||
}
|
||||
|
||||
export { useRefs };
|
@@ -1,35 +1,49 @@
|
||||
import { isFunction, isUnDef } from '/@/utils/is';
|
||||
import { ref, unref } from 'vue';
|
||||
import { shallowRef, unref } from 'vue';
|
||||
|
||||
export interface ScrollToParams {
|
||||
el: any;
|
||||
interface UseScrollToOptions {
|
||||
/**
|
||||
* 需要滚动的 el dom节点
|
||||
*/
|
||||
el: HTMLElement;
|
||||
/**
|
||||
* 滚动的目标值
|
||||
*/
|
||||
to: number;
|
||||
/**
|
||||
* 滚动时间
|
||||
*/
|
||||
duration?: number;
|
||||
callback?: () => any;
|
||||
/**
|
||||
* 执行完成之后的回调函数
|
||||
* @returns
|
||||
*/
|
||||
callback?: () => void;
|
||||
}
|
||||
|
||||
const easeInOutQuad = (t: number, b: number, c: number, d: number) => {
|
||||
function easeInOutQuad(t: number, b: number, c: number, d: number) {
|
||||
t /= d / 2;
|
||||
if (t < 1) {
|
||||
return (c / 2) * t * t + b;
|
||||
}
|
||||
t--;
|
||||
return (-c / 2) * (t * (t - 2) - 1) + b;
|
||||
};
|
||||
const move = (el: HTMLElement, amount: number) => {
|
||||
el.scrollTop = amount;
|
||||
};
|
||||
}
|
||||
|
||||
const position = (el: HTMLElement) => {
|
||||
return el.scrollTop;
|
||||
};
|
||||
export function useScrollTo({ el, to, duration = 500, callback }: ScrollToParams) {
|
||||
const isActiveRef = ref(false);
|
||||
const start = position(el);
|
||||
function move(el: HTMLElement, amount: number) {
|
||||
el.scrollTop = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* dom节点滚动到指定位置
|
||||
* @param UseScrollToOptions
|
||||
* @returns
|
||||
*/
|
||||
function useScrollTo({ el, to, duration = 500, callback }: UseScrollToOptions) {
|
||||
const isActiveRef = shallowRef(false);
|
||||
const start = el.scrollTop;
|
||||
const change = to - start;
|
||||
const increment = 20;
|
||||
let currentTime = 0;
|
||||
duration = isUnDef(duration) ? 500 : duration;
|
||||
|
||||
const animateScroll = function () {
|
||||
if (!unref(isActiveRef)) {
|
||||
@@ -41,11 +55,10 @@ export function useScrollTo({ el, to, duration = 500, callback }: ScrollToParams
|
||||
if (currentTime < duration && unref(isActiveRef)) {
|
||||
requestAnimationFrame(animateScroll);
|
||||
} else {
|
||||
if (callback && isFunction(callback)) {
|
||||
callback();
|
||||
}
|
||||
callback?.();
|
||||
}
|
||||
};
|
||||
|
||||
const run = () => {
|
||||
isActiveRef.value = true;
|
||||
animateScroll();
|
||||
@@ -57,3 +70,5 @@ export function useScrollTo({ el, to, duration = 500, callback }: ScrollToParams
|
||||
|
||||
return { start: run, stop };
|
||||
}
|
||||
|
||||
export { useScrollTo, type UseScrollToOptions };
|
52
packages/hooks/src/useWindowSizeFn.ts
Normal file
52
packages/hooks/src/useWindowSizeFn.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { type AnyFunction } from '@vben/types';
|
||||
import { tryOnMounted, tryOnUnmounted, useDebounceFn } from '@vueuse/core';
|
||||
|
||||
interface UseWindowSizeOptions {
|
||||
/**
|
||||
* 节流时间
|
||||
* @default 150
|
||||
*/
|
||||
wait?: number;
|
||||
/**
|
||||
* 立即执行
|
||||
* @default false
|
||||
*/
|
||||
immediate?: boolean;
|
||||
/**
|
||||
* 只执行一次
|
||||
* @default false
|
||||
*/
|
||||
once?: boolean;
|
||||
}
|
||||
|
||||
function useWindowSizeFn(fn: AnyFunction, options: UseWindowSizeOptions = {}) {
|
||||
const { wait = 150, immediate } = options;
|
||||
|
||||
let handler = () => {
|
||||
fn();
|
||||
};
|
||||
|
||||
handler = useDebounceFn(handler, wait);
|
||||
|
||||
const start = () => {
|
||||
if (immediate) {
|
||||
handler();
|
||||
}
|
||||
window.addEventListener('resize', handler);
|
||||
};
|
||||
|
||||
const stop = () => {
|
||||
window.removeEventListener('resize', handler);
|
||||
};
|
||||
|
||||
tryOnMounted(() => {
|
||||
start();
|
||||
});
|
||||
|
||||
tryOnUnmounted(() => {
|
||||
stop();
|
||||
});
|
||||
return { start, stop };
|
||||
}
|
||||
|
||||
export { useWindowSizeFn, type UseWindowSizeOptions };
|
5
packages/hooks/tsconfig.json
Normal file
5
packages/hooks/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "@vben/ts-config/vue-app.json",
|
||||
"include": ["src"]
|
||||
}
|
4
packages/shared/.eslintrc.js
Normal file
4
packages/shared/.eslintrc.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['@vben/eslint-config/strict'],
|
||||
};
|
10
packages/shared/build.config.ts
Normal file
10
packages/shared/build.config.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { defineBuildConfig } from 'unbuild';
|
||||
|
||||
export default defineBuildConfig({
|
||||
clean: true,
|
||||
entries: ['src/index'],
|
||||
declaration: true,
|
||||
rollup: {
|
||||
emitCJS: true,
|
||||
},
|
||||
});
|
37
packages/shared/package.json
Normal file
37
packages/shared/package.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "@vben/shared",
|
||||
"version": "1.0.0",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": {
|
||||
"url": "https://github.com/vbenjs/vue-vben-admin/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
||||
"directory": "packages/hooks"
|
||||
},
|
||||
"license": "MIT",
|
||||
"sideEffects": false,
|
||||
"exports": {
|
||||
".": {
|
||||
"default": "./src/index.ts"
|
||||
}
|
||||
},
|
||||
"main": "./src/index.ts",
|
||||
"module": "./src/index.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"//build": "pnpm unbuild",
|
||||
"//stub": "pnpm unbuild --stub",
|
||||
"clean": "pnpm rimraf .turbo node_modules dist",
|
||||
"lint": "pnpm eslint ."
|
||||
},
|
||||
"dependencies": {
|
||||
"vue": "^3.2.47"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/shared": "^3.2.47"
|
||||
}
|
||||
}
|
1
packages/shared/src/index.ts
Normal file
1
packages/shared/src/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './types';
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user