Compare commits

..

128 Commits

Author SHA1 Message Date
Soybean
889c859865 Merge pull request #82 from tclyjy/main
feat(layouts): 添加侧边栏/头部的反转模式来增加对比度
2022-04-27 16:46:09 +08:00
元家怿
3c8dd772f8 feat(layouts): 添加侧边栏/头部的反转模式来增加对比度 2022-04-27 16:39:20 +08:00
Soybean
20347b7d65 Merge pull request #79 from toolvcn/相思
feat(projects): HTML lang 修改为 zh-cmn-Hans
2022-04-22 13:31:11 +08:00
相思
dbeb595c0b feat(projects): HTML lang 修改为 zh-cmn-Hans 2022-04-22 13:00:50 +08:00
Soybean
5e276421ad refactor(projects): 代码优化 2022-04-22 09:07:53 +08:00
Soybean
219f87f467 fix(projects): 添加获取路由组件文件未找到时的错误提示 2022-04-21 09:04:18 +08:00
Soybean
b35ed8960d refactor(projects): 去除在pinia的getters的函数调用副作用,用watch代替 2022-04-21 00:46:03 +08:00
Soybean
24010d05fb feat(projects): 登录页背景图片位置适配移动端 2022-04-21 00:26:21 +08:00
Soybean
ec0776e268 feat(projects): 登录页面适配移动端 2022-04-21 00:15:34 +08:00
Soybean
cecce83bc3 build(deps): update deps 2022-04-18 23:47:38 +08:00
Soybean
4eb46ea3dd chore(deps): update deps 2022-04-14 00:02:19 +08:00
Soybean
e8b534b84e refactor(projects): 代码优化 2022-04-13 23:45:15 +08:00
Soybean
46e1ae7825 fix(projects): 修复获取vite环境变量的方式 2022-04-07 22:48:52 +08:00
Soybean
60a55a776e docs(projects): update README.md 2022-04-06 14:34:52 +08:00
Soybean
bed4292ed3 feat(projects): 添加请求适配器的请求示例 2022-04-04 19:13:15 +08:00
Soybean
6bed9ead38 feat(projects): 插件方式按需引入naiveUI 2022-04-04 17:41:55 +08:00
Soybean
3fb13ca9e7 fix(projects): 修复在新版vite下环境变量获取不到的问题 2022-04-04 17:30:26 +08:00
Soybean
2d6d179d66 fix(projects): 去除从环境文件引入端口号导致的错误 2022-04-03 01:07:25 +08:00
Soybean
eebb753884 Merge pull request #70 from yanbowe/main
fix(projects): 全局搜索弹窗弹出时动画闪屏问题
2022-04-02 14:13:39 +08:00
yanbowen
bb1bbf2724 fix(projects): 全局搜索弹窗弹出时动画闪屏问题 2022-04-02 10:35:21 +08:00
Soybean
df56abe18d style(projects): update prettier config 2022-04-01 14:47:57 +08:00
Soybean
ca2dfa6185 feat(projects): 新增静态路由 2022-03-30 01:30:12 +08:00
Soybean
bbfdcc8276 Merge pull request #67 from Southliu/main
perf: refresh-koken命名
2022-03-24 15:59:00 +08:00
“Southliu”
1715504789 perf: refresh-koken命名 2022-03-24 11:49:07 +08:00
Soybean
9a90f18e77 docs(projects): update README.md 2022-03-23 15:21:09 +08:00
Soybean
21645537d5 docs(projects): update README.md 2022-03-15 01:34:31 +08:00
Soybean
e6c26fcb4a fix(projects): 修复路由守卫的动态路由逻辑 2022-03-14 15:16:28 +08:00
Soybean
20911dd882 refactor(projects): lint命令修改 2022-03-13 19:42:01 +08:00
Soybean
cd7ca8f4c7 fix(projects): 修复vite alias 2022-03-13 18:37:44 +08:00
Soybean
ca707a456b build(projects): vite.config代码优化 2022-03-13 18:14:27 +08:00
Soybean
d0522ce514 chore(release): 0.9.3 2022-03-12 21:22:49 +08:00
Soybean
f83c7b59b8 feat(projects): 新增自定义svg图标动态渲染 2022-03-12 21:22:01 +08:00
Soybean
f5a043b11a feat(projects): 添加全局组件自动引入注册 2022-03-12 19:56:58 +08:00
Soybean
094dca961f feat(projects): 添加网络代理 2022-03-12 19:35:49 +08:00
Soybean
8191490f39 feat(projects): 重构项目的TS类型架构,去除interface文件夹 2022-03-12 17:45:37 +08:00
Soybean
75de2b0604 build(projects): update tsconfig、eslintrc 2022-03-12 16:21:40 +08:00
Soybean
4093dcd6dc Merge pull request #62 from Imgodmaoyouknow/main
docs(other): 注释文案修改
2022-03-10 17:40:52 +08:00
毛博文
d00643c9f5 docs(other): 注释文案修改 2022-03-10 17:07:06 +08:00
Soybean
b8db2116df docs(projects): update README.md 2022-03-06 21:23:00 +08:00
Soybean
a0dfa3d30d docs(projects): update README.md 2022-03-06 03:33:37 +08:00
Soybean
4e31abd446 refactor(projects): 代码优化 2022-03-06 00:00:51 +08:00
Soybean
f42ee9dbe5 build(projects): 更新tsconfig.json 2022-03-05 23:20:00 +08:00
Soybean
f5c56c355c feat(projects): 新增子菜单图标和多页签图标 2022-03-05 05:37:40 +08:00
Soybean
a1a57a185c feat(projects): 引入soybean-admin-tab、去除vite-plugin-svg-icons,用unplugin-icons实现自定义svg的iconify写法、代码优化 2022-03-05 05:00:26 +08:00
Soybean
b298af1ddb build(deps): upgrade deps 2022-03-04 04:20:35 +08:00
Soybean
43d685ccd3 Merge pull request #54 from pany-ang/main
fix(projects): 修复 BASE_URL 没有生效的问题
2022-03-03 16:26:44 +08:00
pany
72d7dcfa5e fix(projects): 修复 BASE_URL 没有生效的问题 2022-03-03 12:01:14 +08:00
Soybean
1e2fdda090 style(components): 代码优化 2022-03-03 00:35:44 +08:00
Soybean
8d00b238f7 build(deps): upgrade deps 2022-03-03 00:11:04 +08:00
Soybean
8cdad54236 docs(projects): update README.md 2022-03-01 12:07:13 +08:00
Soybean
6298e61328 Merge pull request #52 from bundlejs/main
fix(projects): 修复页面切换动画开关不生效
2022-02-28 14:57:29 +08:00
bundle
9d4ed617fb fix(projects): 修复页面切换动画开关不生效 2022-02-28 13:50:52 +08:00
Soybean
f92d7ecfbe Merge pull request #51 from Lsq128/main
feat(components): svgIcon,添加type,调整size方案
2022-02-27 08:45:59 +08:00
Lsq128
ce4e039f48 feat(components): svgIcon,添加type,调整size方案 2022-02-26 23:47:34 +08:00
Soybean
1a9efee591 Merge pull request #48 from Lsq128/main
feat(projects): 添加SvgIcon,配置vite plugin
2022-02-25 21:58:03 +08:00
Liushengqun
378d55ac0e feat(projects): 添加SvgIcon,配置vite plugin 2022-02-25 17:56:00 +08:00
Soybean
50c8b9daa1 build(deps): upgrade deps 2022-02-25 11:06:48 +08:00
Soybean
c4546bdfa3 fix(projects): 修复页面切换动画无变化 2022-02-25 10:57:05 +08:00
Soybean
5b401a79ba docs(projects): update README.md 2022-02-24 17:30:48 +08:00
Soybean
7add5c2edf fix(components): 组件LoadingEmptyWrapper添加背景颜色动画过渡 2022-02-23 21:44:32 +08:00
Soybean
811b15e672 fix(components): 修复组件LoadingEmptyWrapper适应暗黑模式 2022-02-23 21:38:04 +08:00
Soybean
c1182fef0a refactor(components): 去除packages的soybean-layout,通过npm的方式引入 2022-02-23 02:29:10 +08:00
Soybean
7ba332cd6a build(deps): 升级依赖 2022-02-20 22:57:08 +08:00
Soybean
a810ef85b1 feat(projects): 添加naiveUI按需引入 2022-02-17 01:01:17 +08:00
Soybean
225e7128b6 docs(projects): update README.md 2022-02-16 19:28:49 +08:00
Soybean
3aded40461 docs(projects): update README.md 2022-02-16 19:17:21 +08:00
Soybean
57c692be74 build(deps): 升级依赖 2022-02-16 13:14:59 +08:00
Soybean
284af63cfe build(deps): 升级依赖 2022-02-12 23:39:42 +08:00
Soybean
e856cdb7b2 docs(projects): update README.md 2022-02-11 16:55:14 +08:00
Soybean
114072277f chore(release): 0.9.2 2022-02-11 16:27:20 +08:00
Soybean
e65034d946 refactor(projects): 重构路由页面组件的导入 2022-02-11 16:15:50 +08:00
Soybean
a7a269d6a6 fix(projects): 修复项目配置拷贝功能 2022-02-07 23:22:55 +08:00
Soybean
2c9660fdbf fix(components): 修复Tab在移动端设备无法点击的问题 2022-02-07 15:46:35 +08:00
Soybean
e93b94cb24 fix(projects): 修复分析页和工作台的布局问题 2022-02-07 15:00:04 +08:00
Soybean
3befb22903 docs(projects): update README.md 2022-02-07 09:17:27 +08:00
Soybean
7ed5d0de2d docs(projects): update README.md 2022-02-07 09:16:18 +08:00
Soybean
47f2871cb5 docs(projects): update README.md 2022-02-03 17:48:04 +08:00
Soybean
852ddb64ad Merge pull request #37 from yanbowe/main
feat(projects): 迁移全局搜索菜单功能
2022-01-24 15:52:11 +08:00
yanbowen
7e1f9f1138 Merge branch 'honghuangdc:main' into main 2022-01-24 15:44:11 +08:00
yanbowen
554d7fd611 feat(projects): 迁移全局搜索菜单功能 2022-01-24 15:34:57 +08:00
Soybean
1797f29a79 Merge pull request #36 from dxxzst/main
build(projects): update .eslintignore
2022-01-24 14:28:37 +08:00
Grazing Wind
50063187ec Update .eslintignore
add package.json to .eslintignore
2022-01-24 13:57:42 +08:00
Soybean
b16721b2b7 build(projects): add license 2022-01-24 12:26:04 +08:00
Soybean
facc00e8b4 fix(projects): vite配置修复 2022-01-24 11:30:08 +08:00
Soybean
02c51e6fb9 docs(projects): update README.md 2022-01-24 01:28:35 +08:00
Soybean
be374089ba chore(release): 0.9.1 2022-01-24 00:54:16 +08:00
Soybean
68b42304d5 feat(projects): 新版重构完成 2022-01-24 00:53:51 +08:00
Soybean
32a7cc408e chore(release): 0.1.3 2022-01-24 00:01:51 +08:00
Soybean
651e58dcb6 refactor(projects): 细节完善 2022-01-24 00:00:59 +08:00
Soybean
b61b0ce25f fix(projects): 修复路由守卫的动态路由逻辑 2022-01-22 16:16:07 +08:00
Soybean
21bab1f7c3 fix(projects): 修复未登录时会调用获取用户路由的接口 2022-01-22 14:05:19 +08:00
Soybean
4f9d544d43 refactor(projects): 请求构造函数适配不同后端接口的数据结构 2022-01-22 03:25:41 +08:00
Soybean
db75c91400 chore(release): 0.1.2 2022-01-22 01:53:21 +08:00
Soybean
37092974d3 feat(projects): 添加缓存主题色 2022-01-22 01:46:56 +08:00
Soybean
1d63a83822 feat(projects): 添加页面缓存、记录在tab中的缓存页面的滚动条位置 2022-01-22 00:01:34 +08:00
Soybean
db3c25ea14 chore(release): 0.1.1 精简版发布 2022-01-20 21:32:16 +08:00
Soybean
5eddb4910c docs(projects): update README.md 2022-01-20 21:29:30 +08:00
Soybean
ce531ce5dd feat(projects): 细节完善、迁移页面 2022-01-20 21:24:01 +08:00
Soybean
28efbdbc70 feat(projects): 迁移多页签 2022-01-20 02:59:29 +08:00
Soybean
cc290accc2 feat(projects): 细节完善 2022-01-19 00:36:53 +08:00
Soybean
579e07400e fix(projects): 修复vertical-mix布局、重构初始化的loading 2022-01-18 03:21:02 +08:00
Soybean
b2a4ddf5e3 refactor(projects): 恢复pinia默认写法 2022-01-17 03:42:16 +08:00
Soybean
28b5d22401 fix(projects): 修复面包屑数据 2022-01-14 14:17:34 +08:00
Soybean
839b82ba8b feat(projects): 请求拦截器添加刷新token 2022-01-12 19:53:45 +08:00
Soybean
09c7658c21 feat(projects): 面包屑 2022-01-11 19:03:42 +08:00
Soybean
e25afe2fad feat(projects): 添加侧边菜单 2022-01-11 08:22:31 +08:00
Soybean
371fad4f26 build(projects): 添加vercel打包的环境 2022-01-10 19:24:13 +08:00
Soybean
a090d398fc feat(projects): 添加头部折叠按钮 2022-01-10 12:43:04 +08:00
Soybean
6d132c5977 feat(projects): 主题配置抽屉: 迁移其他功能 2022-01-09 13:25:42 +08:00
Soybean
912bfdf439 feat(projects): 主题配置抽屉:迁移暗黑模式、布局模式、添加颜色选择面板 2022-01-09 12:24:39 +08:00
Soybean
bf020a8258 feat(projects): theme store完成 2022-01-08 20:49:21 +08:00
Soybean
10e4d81bd6 feat(projects): 添加抽屉 2022-01-07 18:51:06 +08:00
Soybean
0653fb144f feat(projects): 创建自定义布局组件SoybeanLayout 2022-01-07 15:44:28 +08:00
Soybean
006467a062 feat(projects): 新增BasicLayout布局 2022-01-07 02:50:50 +08:00
Soybean
0c5770dfd2 build(projects): 修改vscode配置 2022-01-06 14:40:07 +08:00
Soybean
0e783bcf7b fix(projects): 去除Layout组件冗余代码 2022-01-06 11:38:46 +08:00
Soybean
e5793e1c8d style(projects): 路由相关文件夹简化 2022-01-06 11:37:06 +08:00
Soybean
85b55bb37a feat(projects): 多级路由的所有子路由转换成二级路由 2022-01-06 11:30:02 +08:00
Soybean
b36a62b150 refactor(projects): 单独路由逻辑重构、路由转换函数优化 2022-01-06 02:42:00 +08:00
Soybean
c804b21ceb feat(projects): 添加NaiveProvider组件 2022-01-05 19:06:23 +08:00
Soybean
5bfb8199b4 fix(projects): 修复redirect-not-found子路由 2022-01-05 13:49:42 +08:00
Soybean
ab9a6a2f39 refactor(projects): 单独一级路由相关逻辑重构 2022-01-05 11:56:28 +08:00
Soybean
b93b80cb4b feat(projects): 迁移登录完成 2022-01-05 01:36:16 +08:00
Soybean
f5a36a05cb feat(projects): 登录页面开始迁移 2022-01-04 19:09:00 +08:00
Soybean
035fa114c9 feat(projects): 初始化加载效果:应用主题颜色 2022-01-04 14:05:18 +08:00
Soybean
2c196841bd feat(projects): 集成naiveUI主题配置,将css vars添加至html 2022-01-04 02:20:32 +08:00
Soybean
0d2a5629e8 feat(projects): 路由页面跳转权限完成 2022-01-04 00:00:48 +08:00
Soybean
de2057f141 refactor(projects): 精简版+动态路由权限初步 2022-01-03 22:20:10 +08:00
425 changed files with 12722 additions and 23025 deletions

View File

@@ -1,12 +1,11 @@
# Editor configuration, see http://editorconfig.org
# 表示是最顶层的 EditorConfig 配置文件
root = true
[*] # 表示所有文件适用
charset = utf-8 # 设置文件字符集为 utf-8
indent_style = tab # 缩进风格tab | space
indent_size = 2 # 缩进大小
end_of_line = lf # 控制换行类型(lf | cr | crlf)
trim_trailing_whitespace = true # 去除行首的任意空白字符
insert_final_newline = true # 始终在文件末尾插入一个新行
[*]
charset = utf-8
indent_style = tab
indent_size = 2
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true

11
.env
View File

@@ -1,9 +1,12 @@
# 变量需要以VITE开头
VITE_BASE_URL=/
VITE_APP_NAME=SoybeanAdmin
VITE_APP_TITLE=SoybeanAdmin
VITE_APP_TITLE=Soybean管理系统
VITE_APP_DESC=中后台管理系统模版
VITE_APP_DESC=SoybeanAdmin是一个中后台管理系统模版
# 权限路由模式: static dynamic
VITE_AUTH_ROUTE_MODE=dynamic
VITE_VISUALIZER=false

38
.env-config.ts Normal file
View File

@@ -0,0 +1,38 @@
/** 请求环境配置 */
type ServiceEnv = Record<
EnvType,
{
/** 请求地址 */
url: string;
/** 代理地址 */
proxy: string;
}
>;
/** 环境配置 */
const serviceEnvConfig: ServiceEnv = {
dev: {
url: 'http://localhost:8080',
proxy: '/api'
},
test: {
url: 'http://localhost:8080',
proxy: '/api'
},
prod: {
url: 'http://localhost:8080',
proxy: '/api'
}
};
/**
* 获取环境配置
* @param env 环境描述
*/
export function getEnvConfig(env: ImportMetaEnv) {
const { VITE_ENV_TYPE = 'dev' } = env;
const envConfig = {
http: serviceEnvConfig[VITE_ENV_TYPE]
};
return envConfig;
}

View File

@@ -1,5 +1 @@
#请求的环境
VITE_HTTP_ENV=DEV
#请求地址
VITE_HTTP_URL=https://test.aisuit.com.cn
VITE_HTTP_PROXY=true

View File

@@ -1,5 +1 @@
#请求的环境 正式环境
VITE_HTTP_ENV=PROD
#请求地址
VITE_HTTP_URL=http://192.168.100.43:8201

View File

@@ -1,4 +0,0 @@
VITE_HTTP_ENV=STAGING
#请求地址
VITE_HTTP_URL=http://192.168.100.43:8201

View File

@@ -11,4 +11,6 @@ lib
/docs
.vscode
.local
index.html
package.json
!.env-config.ts
components.d.ts

View File

@@ -1,13 +1,10 @@
module.exports = {
env: {
browser: true,
es2021: true
es2021: true,
'vue/setup-compiler-macros': true
},
globals: {
defineProps: 'readonly',
defineEmits: 'readonly',
defineExpose: 'readonly',
withDefaults: 'readonly',
PROJECT_BUILD_TIME: 'readonly',
AMap: 'readonly',
BMap: 'readonly',
@@ -20,27 +17,195 @@ module.exports = {
sourceType: 'module'
},
plugins: ['vue', '@typescript-eslint'],
extends: ['plugin:vue/vue3-recommended', 'airbnb-base', '@vue/typescript/recommended', 'plugin:prettier/recommended'],
extends: [
'airbnb-base',
'eslint:recommended',
'plugin:vue/vue3-recommended',
'plugin:prettier/recommended',
'@vue/eslint-config-typescript/recommended',
'@vue/eslint-config-prettier',
'@vue/typescript/recommended'
],
rules: {
'no-unused-vars': 'off',
'import/extensions': 'off',
'import/no-extraneous-dependencies': 'off',
'import/no-unresolved': 0,
'no-shadow': 0,
'import/prefer-default-export': 0,
'import/order': [
'error',
{
'newlines-between': 'never',
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
pathGroups: [
{
pattern: 'vue',
group: 'external',
position: 'before'
},
{
pattern: 'vue-router',
group: 'external',
position: 'before'
},
{
pattern: 'vuex',
group: 'external',
position: 'before'
},
{
pattern: 'pinia',
group: 'external',
position: 'before'
},
// ui framework, such as "naive-ui"
// {
// pattern: 'naive-ui',
// group: 'external',
// position: 'before'
// },
{
pattern: '@/config',
group: 'internal',
position: 'before'
},
{
pattern: '@/settings',
group: 'internal',
position: 'before'
},
{
pattern: '@/enum',
group: 'internal',
position: 'before'
},
{
pattern: '@/plugins',
group: 'internal',
position: 'before'
},
{
pattern: '@/layouts',
group: 'internal',
position: 'before'
},
{
pattern: '@/views',
group: 'internal',
position: 'before'
},
{
pattern: '@/components',
group: 'internal',
position: 'before'
},
{
pattern: '@/router',
group: 'internal',
position: 'before'
},
{
pattern: '@/store',
group: 'internal',
position: 'before'
},
{
pattern: '@/composables',
group: 'internal',
position: 'before'
},
{
pattern: '@/hooks',
group: 'internal',
position: 'before'
},
{
pattern: '@/service',
group: 'internal',
position: 'before'
},
{
pattern: '@/utils',
group: 'internal',
position: 'before'
},
{
pattern: '@/assets',
group: 'internal',
position: 'before'
},
{
pattern: '@/**',
group: 'internal',
position: 'before'
},
{
pattern: '@/interface',
group: 'internal',
position: 'before'
}
],
pathGroupsExcludedImportTypes: [
'vue',
'vue-router',
'vuex',
'pinia'
// 'naive-ui'
]
}
],
'import/no-unresolved': 'off',
'import/prefer-default-export': 'off',
'max-classes-per-file': 'off',
'no-param-reassign': [
'error',
{
props: true,
ignorePropertyModificationsFor: ['state', 'acc', 'e']
}
],
'no-plusplus': 'off',
'no-shadow': 'off',
'no-unused-vars': 'off',
'no-use-before-define': 'off',
'vue/multi-word-component-names': 0,
'max-classes-per-file': 0,
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/no-inferrable-types': 0,
'@typescript-eslint/ban-ts-ignore': 'off',
'@typescript-eslint/ban-types': 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-empty-function': 'off',
'vue/multi-word-component-names': [
'error',
{
ignores: ['index']
}
],
'@typescript-eslint/ban-types': [
'error',
{
types: {
'{}': {
message: 'Use object instead',
fixWith: 'object'
}
}
}
],
'@typescript-eslint/no-empty-interface': [
'error',
{
allowSingleExtends: true
}
],
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-unused-vars': ['warn', { ignoreRestSiblings: true }],
'@typescript-eslint/no-shadow': 'error',
'@typescript-eslint/no-unused-vars': ['warn', { ignoreRestSiblings: true, varsIgnorePattern: '^_' }],
'@typescript-eslint/no-use-before-define': ['error', { classes: true, functions: false, typedefs: false }]
}
},
overrides: [
{
files: ['*.vue'],
rules: {
'no-undef': 'off'
}
},
{
files: ['*.html'],
rules: {
'vue/comment-directive': 'off'
}
}
]
};

25
.gitignore vendored
View File

@@ -1,7 +1,30 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
.idea
stats.html
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
!.vscode/settings.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

1
.husky/.gitignore vendored
View File

@@ -1 +0,0 @@
_

View File

@@ -1,4 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
pnpm lint:fix && pnpm vtsc
npm run lint && npm run typecheck

View File

@@ -1,19 +1,27 @@
module.exports = {
printWidth: 120, // 超过最大值换行
tabWidth: 2, // 缩进字节数
useTabs: false, // 缩进使用tab不使用空格
semi: true, // 句尾添加分号
singleQuote: true, // 使用单引号代替双引号
proseWrap: 'preserve', // 默认值。因为使用了一些折行敏感型的渲染器如GitHub comment而按照markdown文本样式进行折行
arrowParens: 'avoid', // (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid省略括号
bracketSpacing: true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }"
endOfLine: 'auto', // 结尾是 \n \r \n\r auto
eslintIntegration: false, //不让prettier使用eslint的代码格式进行校验
htmlWhitespaceSensitivity: 'ignore', // 指定HTML文件的全局空白区域敏感度 有效选项:"css"- 遵守CSS display属性的默认值。"strict" - 空格被认为是敏感的。"ignore" - 空格被认为是不敏感的。html 中空格也会占位影响布局prettier 格式化的时候可能会将文本换行,造成布局错乱
ignorePath: '.prettierignore', // 不使用prettier格式化的文件填写在项目的.prettierignore文件中
jsxSingleQuote: false, // 在jsx中使用单引号代替双引号
requireConfig: false, // Require a 'prettierconfig' to format prettier
stylelintIntegration: false, //不让prettier使用stylelint的代码格式进行校验
trailingComma: 'none', // 在对象或数组最后一个元素后面是否加逗号在ES5中加尾逗号
tslintIntegration: false // 不让prettier使用tslint的代码格式进行校验
}
module.exports = { // https://prettier.io/docs/en/options.html
arrowParens: 'avoid',
bracketSameLine: false,
bracketSpacing: true,
embeddedLanguageFormatting: 'auto',
htmlWhitespaceSensitivity: 'css',
insertPragma: false,
jsxSingleQuote: false,
printWidth: 120,
proseWrap: 'preserve',
quoteProps: 'as-needed',
requirePragma: false,
semi: true,
singleQuote: true,
tabWidth: 2,
trailingComma: 'none',
useTabs: false,
vueIndentScriptAndStyle: false,
overrides: [
{
files: '*.html',
options: {
parser: 'html',
},
},
],
};

View File

@@ -4,7 +4,8 @@
"formulahendry.auto-complete-tag",
"steoates.autoimport",
"formulahendry.auto-rename-tag",
"coenraads.bracket-pair-colorizer",
"coenraads.bracket-pair-colorizer-2",
"naumovs.color-highlight",
"pranaygp.vscode-css-peek",
"mikestead.dotenv",
"editorconfig.editorconfig",
@@ -23,6 +24,7 @@
"yzhang.markdown-all-in-one",
"pkief.material-icon-theme",
"zhuangtongfa.material-theme",
"jimdong.naive-ui-snippets",
"christian-kohler.path-intellisense",
"esbenp.prettier-vscode",
"johnsoncodehk.volar",

View File

@@ -9,6 +9,8 @@
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"editor.bracketPairColorization.enabled": true,
"editor.guides.bracketPairs": "active",
"git.enableSmartCommit": true,
"path-intellisense.mappings": {
"@": "${workspaceFolder}/src",
@@ -54,18 +56,21 @@
"[markdown]": {
"editor.defaultFormatter": "yzhang.markdown-all-in-one"
},
"workbench.productIconTheme": "fluent-icons",
"vue3snippets.enable-compile-vue-file-on-did-save-code": false,
"editor.formatOnSave": false,
"material-icon-theme.activeIconPack": "angular",
"material-icon-theme.files.associations": {},
"material-icon-theme.folders.associations": {
"enum": "typescript",
"enums": "typescript",
"store": "context",
"stores": "context",
"composable": "hook",
"composables": "hook",
"directive": "tools",
"directives": "tools",
"business": "core"
"business": "core",
"request": "api",
"adapter": "middleware"
}
}

View File

@@ -2,140 +2,111 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [0.0.5](https://github.com/honghuangdc/soybean-admin/compare/v0.0.4...v0.0.5) (2021-11-28)
### [0.9.3](https://github.com/honghuangdc/soybean-admin/compare/v0.9.2...v0.9.3) (2022-03-12)
### Features
* **projects:** 新增组件页面:按钮、卡片示例 ([bdc39af](https://github.com/honghuangdc/soybean-admin/commit/bdc39aff1b05845cbcfcab8d40620d7b8ba52d13))
* **components:** svgIcon,添加type,调整size方案 ([ce4e039](https://github.com/honghuangdc/soybean-admin/commit/ce4e039f48001b47a2933e807f5410a9573781b9))
* **projects:** 引入soybean-admin-tab、去除vite-plugin-svg-icons用unplugin-icons实现自定义svg的iconify写法、代码优化 ([a1a57a1](https://github.com/honghuangdc/soybean-admin/commit/a1a57a185ce5004888ca4e1611973665ee46980b))
* **projects:** 新增子菜单图标和多页签图标 ([f5c56c3](https://github.com/honghuangdc/soybean-admin/commit/f5c56c355ce41157b20ed0a10272a28e6d8b2b49))
* **projects:** 新增自定义svg图标动态渲染 ([f83c7b5](https://github.com/honghuangdc/soybean-admin/commit/f83c7b59b893ab6e210188e92c4177b3d01392ce))
* **projects:** 添加naiveUI按需引入 ([a810ef8](https://github.com/honghuangdc/soybean-admin/commit/a810ef85b19e4b74f3ddb3c69d17c050e556ee90))
* **projects:** 添加SvgIcon,配置vite plugin ([378d55a](https://github.com/honghuangdc/soybean-admin/commit/378d55ac0e11cdf115ce3cb8e281d60f7fc4ff7a))
* **projects:** 添加全局组件自动引入注册 ([f5a043b](https://github.com/honghuangdc/soybean-admin/commit/f5a043b11a403927828ae922bdae411a4e5ae3c6))
* **projects:** 添加网络代理 ([094dca9](https://github.com/honghuangdc/soybean-admin/commit/094dca961f608404352ac360f44496423d88dae8))
* **projects:** 重构项目的TS类型架构去除interface文件夹 ([8191490](https://github.com/honghuangdc/soybean-admin/commit/8191490f39fc011096edd77c3156eb4fe33d4e1c))
### Bug Fixes
* **components:** 修复HorizontalLayout布局 ([9fb641f](https://github.com/honghuangdc/soybean-admin/commit/9fb641f71e74e054c84cda8e18969d1168ef2903))
* **components:** 修复组件LoadingEmptyWrapper适应暗黑模式 ([811b15e](https://github.com/honghuangdc/soybean-admin/commit/811b15e672c9d69e9c5789eb11ab2db7bd729f37))
* **components:** 组件LoadingEmptyWrapper添加背景颜色动画过渡 ([7add5c2](https://github.com/honghuangdc/soybean-admin/commit/7add5c2edfcabadb77084179d464b849d880d5e6))
* **projects:** 修复 BASE_URL 没有生效的问题 ([72d7dcf](https://github.com/honghuangdc/soybean-admin/commit/72d7dcfa5ee8dc6f3601f4d65c6aca9ad2cc5d5c))
* **projects:** 修复页面切换动画开关不生效 ([9d4ed61](https://github.com/honghuangdc/soybean-admin/commit/9d4ed617fb80095e521d8063718283459711118f))
* **projects:** 修复页面切换动画无变化 ([c4546bd](https://github.com/honghuangdc/soybean-admin/commit/c4546bdfa303f1e89c0d7ddd46b54e4ec5170096))
### [0.0.4](https://github.com/honghuangdc/soybean-admin/compare/v0.0.3...v0.0.4) (2021-11-25)
### [0.9.2](https://github.com/honghuangdc/soybean-admin/compare/v0.9.1...v0.9.2) (2022-02-11)
### Features
* **components:** 添加多页签Tab点击后自动往中间滚动 ([8ce627a](https://github.com/honghuangdc/soybean-admin/commit/8ce627a397ee2605d967e7f9c8aa558b99fca22d))
* **projects:** 新增网址导航页面 ([32aa5ee](https://github.com/honghuangdc/soybean-admin/commit/32aa5ee75af80c2f959b74573d5c44c452d2715c))
* **storage:** local存储增加有效期 ([e6c9b35](https://github.com/honghuangdc/soybean-admin/commit/e6c9b35ab402df7d9ebb82306131fc30d0a8b893))
* **projects:** 迁移全局搜索菜单功能 ([554d7fd](https://github.com/honghuangdc/soybean-admin/commit/554d7fd6114b9cf6df571c3cb02f4cb0cc6dcfd4))
### Bug Fixes
* **components:** 修复多页签按钮风格的tab滚动问题 ([c429cd0](https://github.com/honghuangdc/soybean-admin/commit/c429cd0293dbfbf6b6df539857c276d3218de754))
* **components:** 修复多页签Tab自动滚动问题 ([20aa39f](https://github.com/honghuangdc/soybean-admin/commit/20aa39f14ed0239f02118b62a6aa4706b1f9dd21))
* **projects:** 添加西瓜视频实例在onUnMounted的销毁多页签居中距离精确 ([738964a](https://github.com/honghuangdc/soybean-admin/commit/738964a76975dc3cb1f3206eb13a7612b92f1aed))
* **projects:** 修复打包构建时图标错误 ([93f9aa9](https://github.com/honghuangdc/soybean-admin/commit/93f9aa9584be803704cf0ff54c8da0f84b71c408))
* **types:** 添加dotEnv类型的非空判断 ([cff11d9](https://github.com/honghuangdc/soybean-admin/commit/cff11d91758a470ad6ff33888ed24747b2cc0c03))
* **components:** 修复Tab在移动端设备无法点击的问题 ([2c9660f](https://github.com/honghuangdc/soybean-admin/commit/2c9660fdbf9a84e980db0aff5cd0aed0f75963ca))
* **projects:** 修复分析页和工作台的布局问题 ([e93b94c](https://github.com/honghuangdc/soybean-admin/commit/e93b94cb2435a130bb1d94a703328af342cd24c9))
* **projects:** 修复项目配置拷贝功能 ([a7a269d](https://github.com/honghuangdc/soybean-admin/commit/a7a269d6a61ccd25883e6bb69639d39e0260587d))
* **projects:** vite配置修复 ([facc00e](https://github.com/honghuangdc/soybean-admin/commit/facc00e8b4998dc8bd338e3b63a652b4bfe2ed3e))
### [0.0.3](https://github.com/honghuangdc/soybean-admin/compare/v0.0.2...v0.0.3) (2021-11-23)
### 0.0.2 (2021-11-21)
### [0.9.1](https://github.com/honghuangdc/soybean-admin/compare/v0.1.3...v0.9.1) (2022-01-23)
### Features
* **component:** 增加剪贴板示例 ([f1cd995](https://github.com/honghuangdc/soybean-admin/commit/f1cd9955d9ef0dd06e6eb0ab88ab6be80db789a3))
* **components:** 添加面包屑 ([c1cdc3a](https://github.com/honghuangdc/soybean-admin/commit/c1cdc3a9ed673d0fd84aa1eaa9fc72468bd5aaf9))
* **components:** 添加图片验证码 ([336c776](https://github.com/honghuangdc/soybean-admin/commit/336c7766f9130619b7076e832d7ade7cbc3049f2))
* **components:** 添加主题配置抽屉,添加暗黑主题 ([a87593f](https://github.com/honghuangdc/soybean-admin/commit/a87593f58a1185d6360b8e49ffe1c9fff768770e))
* **components:** 添加vertical-mix的导航模式下的菜单 ([f24ec1c](https://github.com/honghuangdc/soybean-admin/commit/f24ec1c5326c117e618aed8b3e1867c24fcd84f4))
* **projects:** 布局调整 ([eda87f0](https://github.com/honghuangdc/soybean-admin/commit/eda87f041d5d87ae9612f369608e486a8e563f17))
* **projects:** 菜单数据及组件接入 ([3226a72](https://github.com/honghuangdc/soybean-admin/commit/3226a724be65935ce89fe6ae67f49a20d255c6ac))
* **projects:** 导航栏模式配置:界面实现及主题配置布局调整 ([f002124](https://github.com/honghuangdc/soybean-admin/commit/f002124ee11bc93e6b9955549143b695417e7f8d))
* **projects:** 登录页面实现 ([f1e7cf6](https://github.com/honghuangdc/soybean-admin/commit/f1e7cf608ea7d61dcd24f8780cde9cc4c59658ce))
* **projects:** 多页签绑定路由 ([f29bc05](https://github.com/honghuangdc/soybean-admin/commit/f29bc05dd9f53144ef56440033a6f747c112e83d))
* **projects:** 分析页更新,添加关于页面 ([8e18218](https://github.com/honghuangdc/soybean-admin/commit/8e18218196c52e6a34b96bc313044b6e47886f85))
* **projects:** 工作台页面:添加技术栈官网链接 ([364c64b](https://github.com/honghuangdc/soybean-admin/commit/364c64b4641e48bcf8cc8600680bcaa39a1a9413))
* **projects:** 工作台页面布局 ([4c85569](https://github.com/honghuangdc/soybean-admin/commit/4c85569b764b176c9c3a7f9ba3092ff3567e5512))
* **projects:** 首页更新 ([5c01006](https://github.com/honghuangdc/soybean-admin/commit/5c01006306873944671a4f1d863ced6ba23f6245))
* **projects:** 四种基本布局完成 ([86d4a20](https://github.com/honghuangdc/soybean-admin/commit/86d4a207eef8daf01c6336e8aaedf3aebb90e7a7))
* **projects:** 添加百度地图插件 ([6abe094](https://github.com/honghuangdc/soybean-admin/commit/6abe094ff23f52fdd62c025bce17debd9ea2f907))
* **projects:** 添加多级菜单页面 ([3f49d6d](https://github.com/honghuangdc/soybean-admin/commit/3f49d6db30aee0a6c1007cb00069835b102deb70))
* **projects:** 添加多页签风格:按钮和浏览器两种风格 ([3cfa0f1](https://github.com/honghuangdc/soybean-admin/commit/3cfa0f103cf788e57ee26743e89bf5fe33a09660))
* **projects:** 添加多页签右键菜单 ([d6f5237](https://github.com/honghuangdc/soybean-admin/commit/d6f5237c8c167314d578312dcad7505737f0b4c8))
* **projects:** 添加富文本和markdown编辑器插件及示例页面 ([60c2064](https://github.com/honghuangdc/soybean-admin/commit/60c20647a0d8e6d877a0f23a6e7da05ff09d14a0))
* **projects:** 添加固定路由 ([ff4a09c](https://github.com/honghuangdc/soybean-admin/commit/ff4a09c452c98791f7d67ba5f135e9cf5099c29c))
* **projects:** 添加环境文件env对应的类型 ([4f05095](https://github.com/honghuangdc/soybean-admin/commit/4f050953363b364815a08103047df3fe377d8f56))
* **projects:** 添加判断是否是移动端的hooks ([0a9fba9](https://github.com/honghuangdc/soybean-admin/commit/0a9fba90b5e51fd2d39c47490f49dac7599a9742))
* **projects:** 添加全屏显示 ([0a1711d](https://github.com/honghuangdc/soybean-admin/commit/0a1711d5b1d8e863d24a55690fa8696c79acaaf9))
* **projects:** 添加项目配置拷贝 ([2d9d5c0](https://github.com/honghuangdc/soybean-admin/commit/2d9d5c0353ca6d2dc86965fe383bf2925a47d239))
* **projects:** 添加exception页面403404500 ([d012c4e](https://github.com/honghuangdc/soybean-admin/commit/d012c4ecf2cd325567d419684153955560ce90da))
* **projects:** 添加multiTab标签页 ([eec0b36](https://github.com/honghuangdc/soybean-admin/commit/eec0b36f594e0d337f13d3d0ce30b1f768614f5c))
* **projects:** 添加reload context ([03ebd49](https://github.com/honghuangdc/soybean-admin/commit/03ebd49c8639bf7f4f88b1a0523d2caec2d248ee))
* **projects:** 添加svg logo自适应主题颜色 ([e1e5579](https://github.com/honghuangdc/soybean-admin/commit/e1e5579e8fe71ed97e2ce11d907705157874bd71))
* **projects:** 添加swiper插件 ([27f600c](https://github.com/honghuangdc/soybean-admin/commit/27f600c4677afeacd3e67f189df139db5cde0aa3))
* **projects:** 头部添加菜单折叠按钮和github地址 ([3ec1fc8](https://github.com/honghuangdc/soybean-admin/commit/3ec1fc8f0c23fcba56d4bffb20028948f985659c))
* **projects:** 项目初始化搭建集成eslint规范集成代码提交规范 ([6754da4](https://github.com/honghuangdc/soybean-admin/commit/6754da4d83976a02eced801220320d8c9aa1da85))
* **projects:** 新增导航模式配置 ([49c2dc4](https://github.com/honghuangdc/soybean-admin/commit/49c2dc4f23913c9ef86ee046c6ae53d4406cbca7))
* **projects:** 新增顶部菜单 ([221d2cc](https://github.com/honghuangdc/soybean-admin/commit/221d2cc02dfdf3f78cb415f26c88f1f274942222))
* **projects:** 新增多页签缓存功能 ([d86f891](https://github.com/honghuangdc/soybean-admin/commit/d86f891c64f802bbca50e31e3e4f7ccdad65eed1))
* **projects:** 新增高德地图插件 ([ea82edc](https://github.com/honghuangdc/soybean-admin/commit/ea82edc1146fefa208bb9e6f985dfb000d197d16))
* **projects:** 新增视频插件 ([6a692d4](https://github.com/honghuangdc/soybean-admin/commit/6a692d4f99942389cd2a5e72ebc852a92e80f742))
* **projects:** 新增腾讯地图插件 ([3f02c21](https://github.com/honghuangdc/soybean-admin/commit/3f02c215c54fde4c85bf13e92c2620553d5a1840))
* **projects:** 新增文档页面 ([7654b2a](https://github.com/honghuangdc/soybean-admin/commit/7654b2adf3d0bf051d13b401dfa3534ca7ee3e0c))
* **projects:** 新增主题配置 ([ed67b79](https://github.com/honghuangdc/soybean-admin/commit/ed67b797c215fe165808505f4b0b9400f3182383))
* **projects:** 新增主题配置:页面功能 ([8601ce2](https://github.com/honghuangdc/soybean-admin/commit/8601ce2ea184455fcba1d17d759cd4b933b31d96))
* **projects:** 新增主题颜色配置 ([d93493b](https://github.com/honghuangdc/soybean-admin/commit/d93493b91ca856573c306e890e8c6f6a46b5bda3))
* **projects:** 增加Icon以及打印功能示例 ([d5bce26](https://github.com/honghuangdc/soybean-admin/commit/d5bce26454c7d7c9da29e01675624f985755779f))
* **projects:** 主题配置:页面功能和页面显示 ([a0392b3](https://github.com/honghuangdc/soybean-admin/commit/a0392b3d28f89f2b5fcf5b4d2b82ab7a068a23b8))
* **projects:** vertical-mix的导航模式的二级菜单显示 ([736f314](https://github.com/honghuangdc/soybean-admin/commit/736f3146cb7cb3f56e06a8185ec8532f25c40b13))
* **route:** 增加功能示例模块 ([efd29bc](https://github.com/honghuangdc/soybean-admin/commit/efd29bc331f630b57eab800bba08b22c53115d76))
* **projects:** 新版重构完成 ([68b4230](https://github.com/honghuangdc/soybean-admin/commit/68b42304d5964246775c7a82dcc1406c5db7a4e4))
### [0.1.3](https://github.com/honghuangdc/soybean-admin/compare/v0.1.2...v0.1.3) (2022-01-23)
### Bug Fixes
* **多页签:** 在pc模式下右键某个多页签会切换路由 ([a4394dc](https://github.com/honghuangdc/soybean-admin/commit/a4394dc3ee81ea2abc9a9fd243714309a1b4e6ab))
* **components:** 修复按钮Tab自适应主题颜色 ([3d1f419](https://github.com/honghuangdc/soybean-admin/commit/3d1f41925d54ebe89f1bbbdfe916be59bb97c9cf))
* **components:** 修复BaseLayout的HorizontalLayout ([0344f46](https://github.com/honghuangdc/soybean-admin/commit/0344f46c9377acfb52c28cf373a5416845d1aa1b))
* **components:** 修复tab组件适应暗黑主题模式 ([2fe3d27](https://github.com/honghuangdc/soybean-admin/commit/2fe3d27a36b641339fd87eaa7acad8c3424b97b4))
* **components:** tab组件在黑暗模式下泛白的颜色问题以及chromeTab的重叠问题 ([6797dbf](https://github.com/honghuangdc/soybean-admin/commit/6797dbf1b0617dcca662a25cf663d93dc4ad5807))
* **deps:** 降低vite版本新版本有些许问题 ([b429c8b](https://github.com/honghuangdc/soybean-admin/commit/b429c8b8ca61191c6bed1c52742ddd5fcf9ddc3a))
* **deps:** 去除图片验证码依赖 ([76a1afa](https://github.com/honghuangdc/soybean-admin/commit/76a1afae4e87c3c08f7fd31b20323c0456565f64))
* **deps:** vite依赖放入devDependencies ([7527b1f](https://github.com/honghuangdc/soybean-admin/commit/7527b1f07cdc2d82ec0104ed7317c7ff731da0b7))
* **hooks:** 修复登录页切换登录页参数丢失问题 ([789855a](https://github.com/honghuangdc/soybean-admin/commit/789855a3786623893aa55a2f6c977155394a8a44))
* **hooks:** 修复toLogin函数导致登录重定向地址过多 ([b4adf67](https://github.com/honghuangdc/soybean-admin/commit/b4adf678a4f96f670f9cbdcaebe21378fa94c77c))
* **projects:** 布局修复:从填充屏幕高的页面切换至滚动页面导致布局坍塌 ([2fdb5f5](https://github.com/honghuangdc/soybean-admin/commit/2fdb5f563f7d9fa00d8e5343d992342ff34e3a5a))
* **projects:** 更正dashboard的布局文件 ([31fda0c](https://github.com/honghuangdc/soybean-admin/commit/31fda0ce992457972205db3a39e4c7327d21c087))
* **projects:** 关于页面:开发环境依赖更正 ([3b3baf9](https://github.com/honghuangdc/soybean-admin/commit/3b3baf93ee36423bfe4fc0ab24eda0f99ce92363))
* **projects:** 腾讯地图容器高自适应 ([d7054c5](https://github.com/honghuangdc/soybean-admin/commit/d7054c599b1ce59a123667443863a8054ba19a90))
* **projects:** 头部logo链接更正 ([5d8c3f5](https://github.com/honghuangdc/soybean-admin/commit/5d8c3f54a3e414cdeff35bf5ddb2a1e13d7d703a))
* **projects:** 完善侧边菜单展开逻辑 ([b5f0512](https://github.com/honghuangdc/soybean-admin/commit/b5f05128abcf2403181b7cc7800d9e6593844657))
* **projects:** 修复百度地图sdk地址 ([9a97d23](https://github.com/honghuangdc/soybean-admin/commit/9a97d23c755b7fa7c3166d783e99cac10a0a9753))
* **projects:** 修复登录的重定向地址 ([f97f226](https://github.com/honghuangdc/soybean-admin/commit/f97f2266566164cad912e7ffcdebee1c1b2f4324))
* **projects:** 修复登录页刷新跳404 ([358d4e8](https://github.com/honghuangdc/soybean-admin/commit/358d4e8a1992aa040b909ae580470a0fd2142f5f))
* **projects:** 修复顶部加载条主题 ([ea5917d](https://github.com/honghuangdc/soybean-admin/commit/ea5917d2258356bbcb296420ea1d017f5ad05b7a))
* **projects:** 修复多级菜单页面multitab显示问题 ([f0474bd](https://github.com/honghuangdc/soybean-admin/commit/f0474bd96104dcca332d35d8202eedc3df00eb10))
* **projects:** 修复多页签删除功能 ([99adbc5](https://github.com/honghuangdc/soybean-admin/commit/99adbc5a30c9128d005dc8096d58c5b320f67fef))
* **projects:** 修复分析页折线图表布局问题 ([43b832b](https://github.com/honghuangdc/soybean-admin/commit/43b832bee0dc1d852f3e435f16eaa37f27b0f66c))
* **projects:** 修复富文本编辑器在亮色主题下全屏后背景色丢失 ([4ab7702](https://github.com/honghuangdc/soybean-admin/commit/4ab7702186e1121e50f1d4725b73f28498aba312))
* **projects:** 修复没有子页面的路由写法问题 ([b80c224](https://github.com/honghuangdc/soybean-admin/commit/b80c2246641d44b9ad35dfbfb3d17500cfcb6e43))
* **projects:** 修复同时显示两种multiTab ([5be2e2a](https://github.com/honghuangdc/soybean-admin/commit/5be2e2a2e5658e09c47a4dc1331129e14ed6d761))
* **projects:** 修复页面滚动和页面100%视高占比 ([fa2cc78](https://github.com/honghuangdc/soybean-admin/commit/fa2cc789371999de6b2f698ba7ed87a4d740ad37))
* **projects:** 修复页面滚动行为 ([57e00e6](https://github.com/honghuangdc/soybean-admin/commit/57e00e64177bc9925ca95785335786836571766a))
* **projects:** 修复页面缓存 ([fa0a907](https://github.com/honghuangdc/soybean-admin/commit/fa0a907941a90ed72288205fef14b0923a0ffd8e))
* **projects:** 修复页面缓存,添加多页签删除 ([2489374](https://github.com/honghuangdc/soybean-admin/commit/248937479cc9ccb936116300d628dfa734014b37))
* **projects:** 修复在暗黑模式下第一次进入网页不会触发暗黑模式监听 ([c4a652e](https://github.com/honghuangdc/soybean-admin/commit/c4a652e21e4c3e2ee6e86e04e46d5dccd579d584))
* **projects:** 修复主题配置 ([ff24fda](https://github.com/honghuangdc/soybean-admin/commit/ff24fda5ee12074e7130122ca311d0ce174cc184))
* **projects:** 修复主题相关,自适应操作系统暗黑模式 ([bfa42d7](https://github.com/honghuangdc/soybean-admin/commit/bfa42d769d464dbc8d51689c5fc8c59a348941fb))
* **projects:** 修复globalFooter适应暗黑模式 ([93f08d9](https://github.com/honghuangdc/soybean-admin/commit/93f08d90671b3ddfbdb969d5b13f4a3fa9903a19))
* **projects:** 修复multiTab关闭逻辑添加关闭左边和右边的标签右键操作 ([ed90cb8](https://github.com/honghuangdc/soybean-admin/commit/ed90cb8f8e8d3bbf594757caa950f8521869ece4))
* **projects:** 修复tab过多时样式坍塌添加tab横向滚动 ([0ec4d21](https://github.com/honghuangdc/soybean-admin/commit/0ec4d218e365f54ab0c138a955dcd990cbf2d9bc))
* **projects:** 修复tab在移动端无法点击 ([1a76de0](https://github.com/honghuangdc/soybean-admin/commit/1a76de04463b0344b39c09df0e0762825d66653b))
* **projects:** 修复vertical sider自适应主题 ([9097fa3](https://github.com/honghuangdc/soybean-admin/commit/9097fa386687d077a480033d9978cfbd59e0e3a0))
* **projects:** 修复vertical-mix导航模式的二级菜单显示问题 ([6f286e6](https://github.com/honghuangdc/soybean-admin/commit/6f286e674724db12d6c5a4339ba6f3db720b781d))
* **projects:** 页面各部分背景颜色添加自然过渡 ([1c5fdca](https://github.com/honghuangdc/soybean-admin/commit/1c5fdca59637c141ae1f0b47d9bcf05788a631c2))
* **projects:** wangEditor在暗黑模式下的背景色问题 ([a7de314](https://github.com/honghuangdc/soybean-admin/commit/a7de31404508a2d4436435d06cdb63f851a86029))
* **types:** 数据类型 EnumDataType.boolean 为 [object Boolean] ([e9b5560](https://github.com/honghuangdc/soybean-admin/commit/e9b55608f960c0d3cdeca91af6f2777a23fd20dd))
* **types:** 修复naive组件回调函数参数类型错误 ([667282f](https://github.com/honghuangdc/soybean-admin/commit/667282f81a8822006242d612a08ac59571e3508e))
* **types:** 修复TS类型错误 ([45d31a0](https://github.com/honghuangdc/soybean-admin/commit/45d31a0f5625784423bea463b2373b0cd35b37f5))
* **utils:** utils函数名称更正 ([68f4d01](https://github.com/honghuangdc/soybean-admin/commit/68f4d012cc3cce1df5cb61dfa0212126ea0b202e))
* **projects:** 修复未登录时会调用获取用户路由的接口 ([21bab1f](https://github.com/honghuangdc/soybean-admin/commit/21bab1f7c30611fe59dc91c7a73050ccb49a4658))
* **projects:** 修复路由守卫的动态路由逻辑 ([b61b0ce](https://github.com/honghuangdc/soybean-admin/commit/b61b0ce25fdcbaf29ca64cbcc467e12faa947625))
### [0.1.2](https://github.com/honghuangdc/soybean-admin/compare/v0.1.1...v0.1.2) (2022-01-21)
### Performance Improvements
### Features
* **projects:** 添加windicss指定的扫描目录提升构建性能 ([8e6b0b2](https://github.com/honghuangdc/soybean-admin/commit/8e6b0b299d2ef50f2b85e67b7a1aa7fd2ac1bce1))
* **projects:** 添加缓存主题色 ([3709297](https://github.com/honghuangdc/soybean-admin/commit/37092974d37b2e661d4cbf9d27c89b5e99119cd7))
* **projects:** 添加页面缓存、记录在tab中的缓存页面的滚动条位置 ([1d63a83](https://github.com/honghuangdc/soybean-admin/commit/1d63a838226df4f48e7f2a15b5a05d4b496d3c69))
### [0.1.1](https://github.com/honghuangdc/soybean-admin/compare/v0.0.5...v0.1.1) (2022-01-20)
### Features
* **projects:** theme store完成 ([bf020a8](https://github.com/honghuangdc/soybean-admin/commit/bf020a82580e6b1fbda1cc1e0bd6176770434884))
* **projects:** 主题配置抽屉: 迁移其他功能 ([6d132c5](https://github.com/honghuangdc/soybean-admin/commit/6d132c59770e925cfc61217dcefa5b4d937604df))
* **projects:** 主题配置抽屉:迁移暗黑模式、布局模式、添加颜色选择面板 ([912bfdf](https://github.com/honghuangdc/soybean-admin/commit/912bfdf4390ab624d3f8e343be88e8c1cf7ab5b6))
* **projects:** 创建自定义布局组件SoybeanLayout ([0653fb1](https://github.com/honghuangdc/soybean-admin/commit/0653fb144fe9d49f24ef4fe6e4a58de6de342b78))
* **projects:** 初始化加载效果:应用主题颜色 ([035fa11](https://github.com/honghuangdc/soybean-admin/commit/035fa114c9fd638cf467e6a73a8e4c558f503deb))
* **projects:** 图标选择器增加扩展树形 ([041012b](https://github.com/honghuangdc/soybean-admin/commit/041012b3ee04d960c1e38895839225613f7af377))
* **projects:** 增加Icon选择器组件 ([9472b51](https://github.com/honghuangdc/soybean-admin/commit/9472b51811f419e9139de81c73f2c71d170700c2))
* **projects:** 增加全局搜索菜单功能 ([b9ce691](https://github.com/honghuangdc/soybean-admin/commit/b9ce69130b12712013228326f883e2d973e4e46a))
* **projects:** 增加项目文档外链 ([1901a0b](https://github.com/honghuangdc/soybean-admin/commit/1901a0bfb7bfa516dfda552675397ddec96b8d4b))
* **projects:** 多级路由的所有子路由转换成二级路由 ([85b55bb](https://github.com/honghuangdc/soybean-admin/commit/85b55bb37a0a06e2645b96ed81aefe463127121a))
* **projects:** 引入mockjs ([9bc682d](https://github.com/honghuangdc/soybean-admin/commit/9bc682dae878c084e38a0e2c9a4a2de171023c48))
* **projects:** 新增BasicLayout布局 ([006467a](https://github.com/honghuangdc/soybean-admin/commit/006467a0626f427da3f516d90c15bf1e1eef0e55))
* **projects:** 添加cryptojs对本地缓存数据进行加密 ([7a0648d](https://github.com/honghuangdc/soybean-admin/commit/7a0648dba55a98f61f4d81696307d86c82a1d34d))
* **projects:** 添加NaiveProvider组件 ([c804b21](https://github.com/honghuangdc/soybean-admin/commit/c804b21ceb92133c6ea7cc64c87521cc164e40ce))
* **projects:** 添加侧边菜单 ([e25afe2](https://github.com/honghuangdc/soybean-admin/commit/e25afe2fadfe86b9330ee02190a4e40b8321714c))
* **projects:** 添加头部折叠按钮 ([a090d39](https://github.com/honghuangdc/soybean-admin/commit/a090d398fc071e246b92d0da80883cf5cbedba0e))
* **projects:** 添加常用组件、composables函数 ([230a50a](https://github.com/honghuangdc/soybean-admin/commit/230a50a4cf4d2ebb62b19d6324234243cf6b2f0d))
* **projects:** 添加抽屉 ([10e4d81](https://github.com/honghuangdc/soybean-admin/commit/10e4d81bd6a0b35d8cfb4f7a1e981f8ef6ab87cc))
* **projects:** 添加表格页面示例 ([51c744c](https://github.com/honghuangdc/soybean-admin/commit/51c744c8e2c8ed9691e92e35b6a88582f22c30d8))
* **projects:** 添加路由跳转浏览器新标签 ([987cef3](https://github.com/honghuangdc/soybean-admin/commit/987cef336338987f2e6f0d5aba8f6d4602b297ca))
* **projects:** 登录页面开始迁移 ([f5a36a0](https://github.com/honghuangdc/soybean-admin/commit/f5a36a05cb626ec62115283f1d2c534b2a787bdd))
* **projects:** 细节完善 ([cc290ac](https://github.com/honghuangdc/soybean-admin/commit/cc290accc29282e9ba655356e2695b6ca4b23605))
* **projects:** 细节完善、迁移页面 ([ce531ce](https://github.com/honghuangdc/soybean-admin/commit/ce531ce5dda0b4a1024aa6bd3d68835b59760d57))
* **projects:** 菜单搜索增加大小写转换 ([2907868](https://github.com/honghuangdc/soybean-admin/commit/29078689b0652cf4ae852c93d8601a157579adcc))
* **projects:** 请求拦截器添加刷新token ([839b82b](https://github.com/honghuangdc/soybean-admin/commit/839b82ba8b052b02e24bcfe6da54160609a4fd4b))
* **projects:** 路由页面跳转权限完成 ([0d2a562](https://github.com/honghuangdc/soybean-admin/commit/0d2a5629e89c73a32d6c79f04b51543e1513e006))
* **projects:** 迁移多页签 ([28efbdb](https://github.com/honghuangdc/soybean-admin/commit/28efbdbc70733d22011a0eee084d35711429d188))
* **projects:** 迁移登录完成 ([b93b80c](https://github.com/honghuangdc/soybean-admin/commit/b93b80cb4b35268dfb6a09517a2494af24748dac))
* **projects:** 集成naiveUI主题配置将css vars添加至html ([2c19684](https://github.com/honghuangdc/soybean-admin/commit/2c196841bd8527d7acccefe6a7545e0a49d532f7))
* **projects:** 面包屑 ([09c7658](https://github.com/honghuangdc/soybean-admin/commit/09c7658c21c7dda461dbb528e85b638b5a7dfacd))
### Bug Fixes
* **deps:** 降低vite版本 ([c9c5ca9](https://github.com/honghuangdc/soybean-admin/commit/c9c5ca9989eddb084f2706155473123c5dcfc334))
* **projects:** 修复redirect-not-found子路由 ([5bfb819](https://github.com/honghuangdc/soybean-admin/commit/5bfb8199b463d9ca6430577b5c493c0b78967aa9))
* **projects:** 修复vertical-mix布局、重构初始化的loading ([579e074](https://github.com/honghuangdc/soybean-admin/commit/579e07400e1b9a52934ed808a37c8579a41e8e74))
* **projects:** 修复网络请求错误空信息的提示 ([ff9216b](https://github.com/honghuangdc/soybean-admin/commit/ff9216b621aaef0a8203386fa1c3ca5477a2edea))
* **projects:** 修复面包屑数据 ([28b5d22](https://github.com/honghuangdc/soybean-admin/commit/28b5d224010a28669ad3a1919fc49f6e2dc808cd))
* **projects:** 去除Layout组件冗余代码 ([0e783bc](https://github.com/honghuangdc/soybean-admin/commit/0e783bcf7be0b3a083fe950adfb0afc72b510f97))
* **projects:** 请求相关细节修复 ([2ad1ad3](https://github.com/honghuangdc/soybean-admin/commit/2ad1ad32b8410d84902a33d825032c282ca6df86))

View File

@@ -7,15 +7,16 @@
## 简介
Soybean Admin 是一个基于 Vue3、Vite、Naive UI、TypeScript 的免费中后台模版,它使用了最新的前端技术栈,内置丰富的插件,有着极高的代码规范,开箱即用的中后台前端解决方案,也可用于学习参考。
Soybean Admin 是一个基于 Vue3、Vite、TypeScript、Naive UI 的免费中后台模版,它使用了最新的前端技术栈,内置丰富的主题配置,有着极高的代码规范,基于mock实现的动态权限路由开箱即用的中后台前端解决方案,也可用于学习参考。
## 特性
- **最新技术栈**:使用 Vue3/vite2 等前端前沿技术开发, 使用高效率的npm包管理器pnpm
- **TypeScript**: 应用程序级 JavaScript 的语言
- **主题**:丰富可配置的主题
- **主题**:丰富可配置的主题、暗黑模式基于windicss的动态主题颜色
- **代码规范**:丰富的规范插件及极高的代码规范
- **路由配置**:简易的路由配置
- **权限路由**:简易的路由配置、基于mock的动态路由能快速实现后端动态路由
- **请求函数**基于axios的完善的请求函数封装提供Promise和hooks两种请求函数
## 预览
@@ -25,28 +26,47 @@ Soybean Admin 是一个基于 Vue3、Vite、Naive UI、TypeScript 的免费中
- [项目文档](https://docs.soybean.pro)
### 代码仓库
## 代码仓库
- [github](https://github.com/honghuangdc/soybean-admin)
- [gitee](https://gitee.com/honghuangdc/soybean-admin)
## 项目示例图
![](https://i.loli.net/2021/11/24/pIhTKP7fdCqbVHl.png)
![](https://i.loli.net/2021/11/24/gxRwsLnKi6IVp7C.png)
![](https://s2.loli.net/2022/01/24/ovK6Oyqr7gIMu2n.png)
![](https://i.loli.net/2021/11/24/UmVfjSJbxH6iYc2.png)
![](https://s2.loli.net/2022/01/24/O8loxYhMySHwGfJ.png)
![](https://i.loli.net/2021/11/24/Uot1bcfGXiF726T.png)
![](https://s2.loli.net/2022/01/24/HKwpJ7Ab6j8fVvk.png)
![](https://i.loli.net/2021/11/24/WzOIvlgJZaUtGm7.png)
![](https://s2.loli.net/2022/01/24/bqJRSDZHBv3jsif.png)
### 使用 Gitpod
![](https://s2.loli.net/2022/01/24/wXpHeau6UrSTWdF.png)
在 Gitpod适用于 GitHub 的免费在线开发环境)中打开项目,并立即开始编码.
![](https://s2.loli.net/2022/02/16/pBwF2gaxXnKZe3D.png)
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/honghuangdc/soybean-admin)
![](https://s2.loli.net/2022/02/16/pfuxVEPsTJIXw5n.png)
## 开发计划
- [x] 添加前端静态路由
- [ ] 集成unocss替换windicss(新分支unocss)
- [ ] 用户角色切换示例、按钮级别权限指令
- [ ] 最近功能的有关文档更新
- [ ] 引入ECharts替换AntV G2Plot
- [ ] 性能优化(优化递归函数)
- [ ] 精简版(新分支thin)
- [ ] 表单、表格示例
- [ ] 添加锁屏组件、全局Iframe组件
- [ ] 示例页面完善
- [ ] 其他UI版本
- [ ] element-plus版本
- [ ] soybean-admin cli工具(选择不同UI)
- [ ] 前端可视化创建路由页面
- [ ] soybean-admin 后台服务java版: [soybean-admin-java](https://github.com/honghuangdc/soybean-admin-java)
- [ ] soybean-admin 后台服务go版: [soybean-admin-go](https://github.com/honghuangdc/soybean-admin-go)
- [ ] soybean-admin 后台服务nodejs版: [soybean-admin-nestjs](https://github.com/honghuangdc/soybean-admin-nestjs)
## 安装使用
@@ -74,6 +94,12 @@ pnpm dev
pnpm build
```
::: warning 注意
**本地环境需要安装 pnpm 6.x 、Node.js 14.x 和 Git**
:::
## 如何贡献
非常欢迎您的加入![提一个 Issue](https://github.com/honghuangdc/soybean-admin/issues/new) 或者提交一个 Pull Request。
@@ -104,21 +130,19 @@ pnpm i -g commitizen
## 交流
`Soybean Admin` 是完全开源免费的项目,在帮助开发者更方便地进行中大型管理系统开发,同时也提供 QQ 交流群使用问题欢迎在群内提问。
`Soybean Admin` 是完全开源免费的项目,在帮助开发者更方便地进行中大型管理系统开发,同时也提供微信和QQ交流群使用问题欢迎在群内提问。
- 本人微信号honghuangdc欢迎来技术交流业务咨询。
- 微信交流群:
<div style="text-align:left">
<img src="https://s2.loli.net/2021/12/29/m65oExs7yHcPbKZ.jpg" style="width:200px" />
</div>
**微信群的人数已经满200个了无法扫码可以添加本人的微信再邀请进入**
- QQ `711301266`
- QQ交流`711301266`
<div style="text-align:left">
<img src="https://i.loli.net/2021/11/24/1J6REWXiHomU2kM.jpg" style="width:200px" />
</div>
- 本人微信号honghuangdc欢迎来技术交流业务咨询。
## License
[MIT © Soybean-2021](./LICENSE)

View File

@@ -3,6 +3,6 @@ import dayjs from 'dayjs';
/** 项目构建时间 */
const PROJECT_BUILD_TIME = JSON.stringify(dayjs().format('YYYY-MM-DD HH:mm:ss'));
export default {
export const viteDefine = {
PROJECT_BUILD_TIME
};

3
build/config/index.ts Normal file
View File

@@ -0,0 +1,3 @@
export * from './path';
export * from './define';
export * from './proxy';

15
build/config/path.ts Normal file
View File

@@ -0,0 +1,15 @@
import { fileURLToPath } from 'url';
/**
* 解析路径
* @param basePath - 基础路径
*/
export function resolvePath(rootPath: string, basePath: string) {
const root = fileURLToPath(new URL(rootPath, basePath));
const src = `${root}src`;
return {
root,
src
};
}

23
build/config/proxy.ts Normal file
View File

@@ -0,0 +1,23 @@
import type { ProxyOptions } from 'vite';
import { getEnvConfig } from '../../.env-config';
/**
* 设置网络代理
* @param viteEnv - vite环境描述
*/
export function createViteProxy(viteEnv: ImportMetaEnv) {
const isOpenProxy = viteEnv.VITE_HTTP_PROXY === 'true';
if (!isOpenProxy) return undefined;
const { http } = getEnvConfig(viteEnv);
const proxy: Record<string, string | ProxyOptions> = {
[http.proxy]: {
target: http.url,
changeOrigin: true,
rewrite: path => path.replace(new RegExp(`^${http.proxy}`), '')
}
};
return proxy;
}

5
build/env/index.ts vendored
View File

@@ -1,5 +0,0 @@
import dotenv from 'dotenv';
const { parsed: viteEnv } = dotenv.config(); // 加载环境
export default viteEnv!;

View File

@@ -1,5 +1,2 @@
import viteEnv from './env';
import plugins from './plugins';
import define from './define';
export { viteEnv, plugins, define };
export * from './plugins';
export * from './config';

View File

@@ -0,0 +1,22 @@
import Icons from 'unplugin-icons/vite';
import IconsResolver from 'unplugin-icons/resolver';
import Components from 'unplugin-vue-components/vite';
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers';
import { FileSystemIconLoader } from 'unplugin-icons/loaders';
export default (srcPath: string) => {
return [
Icons({
compiler: 'vue3',
customCollections: {
custom: FileSystemIconLoader(`${srcPath}/assets/svg`)
},
scale: 1,
defaultClass: 'inline-block'
}),
Components({
dts: true,
resolvers: [NaiveUiResolver(), IconsResolver({ customCollections: ['custom'], componentPrefix: 'icon' })]
})
];
};

View File

@@ -1,12 +1,17 @@
import { minifyHtml, injectHtml } from 'vite-plugin-html'; // html插件(使用变量、压缩)
import viteEnv from '../env';
import { loadEnv } from 'vite';
import type { ConfigEnv, PluginOption } from 'vite';
import { createHtmlPlugin } from 'vite-plugin-html';
export default [
minifyHtml(),
injectHtml({
injectData: {
appName: viteEnv.VITE_APP_NAME,
appTitle: viteEnv.VITE_APP_TITLE
export default (config: ConfigEnv): PluginOption[] => {
const viteEnv = loadEnv(config.mode, process.cwd());
return createHtmlPlugin({
minify: true,
inject: {
data: {
appName: viteEnv.VITE_APP_NAME,
appTitle: viteEnv.VITE_APP_TITLE
}
}
})
];
});
};

View File

@@ -1,10 +0,0 @@
import Icons from 'unplugin-icons/vite'; // iconify图标
import IconsResolver from 'unplugin-icons/resolver';
import Components from 'unplugin-vue-components/vite'; // 从指定目录自动导入组件
export default [
Components({
resolvers: [IconsResolver({ componentPrefix: 'icon' })]
}),
Icons({ scale: 1, defaultClass: 'inline-block' })
];

View File

@@ -1,10 +1,27 @@
import type { ConfigEnv, PluginOption } from 'vite';
import vue from './vue';
import html from './html';
import iconify from './iconify';
import autoImport from './auto-import';
import windicss from './windicss';
import visualizer from './visualizer';
import mock from './mock';
import visualizer from './visualizer';
const plugins = [vue, ...html, ...iconify, windicss, visualizer, mock];
/**
* vite插件
* @param configEnv - 环境
* @param srcPath - src路径
* @param viteEnv - 环境变量配置
*/
export function setupVitePlugins(
configEnv: ConfigEnv,
srcPath: string,
viteEnv: ImportMetaEnv
): (PluginOption | PluginOption[])[] {
const plugins = [vue, html(configEnv), ...autoImport(srcPath), windicss, mock];
export default plugins;
if (configEnv.command === 'build' && viteEnv.VITE_VISUALIZER === 'true') {
plugins.push(visualizer);
}
return plugins;
}

100
components.d.ts vendored Normal file
View File

@@ -0,0 +1,100 @@
// generated by unplugin-vue-components
// We suggest you to commit this file into source control
// Read more: https://github.com/vuejs/vue-next/pull/3399
declare module 'vue' {
export interface GlobalComponents {
BetterScroll: typeof import('./src/components/custom/BetterScroll.vue')['default']
CountTo: typeof import('./src/components/custom/CountTo.vue')['default']
DarkModeContainer: typeof import('./src/components/common/DarkModeContainer.vue')['default']
DarkModeSwitch: typeof import('./src/components/common/DarkModeSwitch.vue')['default']
GithubLink: typeof import('./src/components/custom/GithubLink.vue')['default']
HoverContainer: typeof import('./src/components/common/HoverContainer.vue')['default']
IconAntDesignCloseOutlined: typeof import('~icons/ant-design/close-outlined')['default']
IconAntDesignEnterOutlined: typeof import('~icons/ant-design/enter-outlined')['default']
IconAntDesignSettingOutlined: typeof import('~icons/ant-design/setting-outlined')['default']
IconCustomActivity: typeof import('~icons/custom/activity')['default']
IconCustomAvatar: typeof import('~icons/custom/avatar')['default']
IconCustomBanner: typeof import('~icons/custom/banner')['default']
IconCustomCast: typeof import('~icons/custom/cast')['default']
IconCustomEmptyData: typeof import('~icons/custom/empty-data')['default']
IconCustomLogo: typeof import('~icons/custom/logo')['default']
IconCustomLogoFill: typeof import('~icons/custom/logo-fill')['default']
IconCustomNetworkError: typeof import('~icons/custom/network-error')['default']
IconCustomNoPermission: typeof import('~icons/custom/no-permission')['default']
IconCustomNotFound: typeof import('~icons/custom/not-found')['default']
IconCustomServiceError: typeof import('~icons/custom/service-error')['default']
IconGridiconsFullscreen: typeof import('~icons/gridicons/fullscreen')['default']
IconGridiconsFullscreenExit: typeof import('~icons/gridicons/fullscreen-exit')['default']
IconIcOutlineCheck: typeof import('~icons/ic/outline-check')['default']
IconLineMdMenuFoldLeft: typeof import('~icons/line-md/menu-fold-left')['default']
IconLineMdMenuUnfoldLeft: typeof import('~icons/line-md/menu-unfold-left')['default']
IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default']
IconMdiArrowUpThin: typeof import('~icons/mdi/arrow-up-thin')['default']
IconMdiClose: typeof import('~icons/mdi/close')['default']
IconMdiGithub: typeof import('~icons/mdi/github')['default']
IconMdiMoonWaningCrescent: typeof import('~icons/mdi/moon-waning-crescent')['default']
IconMdiPin: typeof import('~icons/mdi/pin')['default']
IconMdiPinOff: typeof import('~icons/mdi/pin-off')['default']
IconMdiRefresh: typeof import('~icons/mdi/refresh')['default']
IconMdiWechat: typeof import('~icons/mdi/wechat')['default']
IconMdiWhiteBalanceSunny: typeof import('~icons/mdi/white-balance-sunny')['default']
IconPhCaretDoubleLeftBold: typeof import('~icons/ph/caret-double-left-bold')['default']
IconPhCaretDoubleRightBold: typeof import('~icons/ph/caret-double-right-bold')['default']
IconSelect: typeof import('./src/components/custom/IconSelect.vue')['default']
IconUilSearch: typeof import('~icons/uil/search')['default']
ImageVerify: typeof import('./src/components/custom/ImageVerify.vue')['default']
LoadingEmptyWrapper: typeof import('./src/components/business/LoadingEmptyWrapper.vue')['default']
LoginAgreement: typeof import('./src/components/business/LoginAgreement.vue')['default']
NaiveProvider: typeof import('./src/components/common/NaiveProvider.vue')['default']
NBreadcrumb: typeof import('naive-ui')['NBreadcrumb']
NBreadcrumbItem: typeof import('naive-ui')['NBreadcrumbItem']
NButton: typeof import('naive-ui')['NButton']
NCard: typeof import('naive-ui')['NCard']
NCheckbox: typeof import('naive-ui')['NCheckbox']
NColorPicker: typeof import('naive-ui')['NColorPicker']
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NDataTable: typeof import('naive-ui')['NDataTable']
NDescriptions: typeof import('naive-ui')['NDescriptions']
NDescriptionsItem: typeof import('naive-ui')['NDescriptionsItem']
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
NDivider: typeof import('naive-ui')['NDivider']
NDrawer: typeof import('naive-ui')['NDrawer']
NDrawerContent: typeof import('naive-ui')['NDrawerContent']
NDropdown: typeof import('naive-ui')['NDropdown']
NEmpty: typeof import('naive-ui')['NEmpty']
NForm: typeof import('naive-ui')['NForm']
NFormItem: typeof import('naive-ui')['NFormItem']
NGradientText: typeof import('naive-ui')['NGradientText']
NGrid: typeof import('naive-ui')['NGrid']
NGridItem: typeof import('naive-ui')['NGridItem']
NInput: typeof import('naive-ui')['NInput']
NInputGroup: typeof import('naive-ui')['NInputGroup']
NInputNumber: typeof import('naive-ui')['NInputNumber']
NList: typeof import('naive-ui')['NList']
NListItem: typeof import('naive-ui')['NListItem']
NLoadingBarProvider: typeof import('naive-ui')['NLoadingBarProvider']
NMenu: typeof import('naive-ui')['NMenu']
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
NModal: typeof import('naive-ui')['NModal']
NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
NPopover: typeof import('naive-ui')['NPopover']
NScrollbar: typeof import('naive-ui')['NScrollbar']
NSelect: typeof import('naive-ui')['NSelect']
NSpace: typeof import('naive-ui')['NSpace']
NSpin: typeof import('naive-ui')['NSpin']
NStatistic: typeof import('naive-ui')['NStatistic']
NSwitch: typeof import('naive-ui')['NSwitch']
NTabPane: typeof import('naive-ui')['NTabPane']
NTabs: typeof import('naive-ui')['NTabs']
NTag: typeof import('naive-ui')['NTag']
NThing: typeof import('naive-ui')['NThing']
NTimeline: typeof import('naive-ui')['NTimeline']
NTimelineItem: typeof import('naive-ui')['NTimelineItem']
NTooltip: typeof import('naive-ui')['NTooltip']
SystemLogo: typeof import('./src/components/common/SystemLogo.vue')['default']
WebSiteLink: typeof import('./src/components/custom/WebSiteLink.vue')['default']
}
}
export { }

View File

@@ -1,32 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<html lang="zh-cmn-Hans">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<link rel="stylesheet" href="/resource/loading.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%= appName %></title>
</head>
<body>
<div id="appProvider" style="display: none"></div>
<div id="app">
<!-- 页面渲染之前加载动画 -->
<div class="app-loading">
<img class="app-loading_logo" src="/resource/logo.png" />
<div class="app-loading__dot-wrapper">
<div class="app-loading__dot">
<i class="left top"></i>
<i class="left bottom delay-400"></i>
<i class="right top delay-800"></i>
<i class="right bottom delay-1200"></i>
<div class="loading-container">
<div id="loadingLogo" class="loading-svg"></div>
<div class="loading-spin__container">
<div class="loading-spin">
<div class="left-0 top-0 loading-spin-item"></div>
<div class="left-0 bottom-0 loading-spin-item loading-delay-500"></div>
<div class="right-0 top-0 loading-spin-item loading-delay-1000"></div>
<div class="right-0 bottom-0 loading-spin-item loading-delay-1500"></div>
</div>
</div>
<h2 class="app-loading_title"><%= appTitle %></h2>
<style>
@import '/resource/loading.css';
</style>
<h2 class="loading-title"><%= appTitle %></h2>
</div>
<!-- End -->
</div>
<script src="/resource/loading.js"></script>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@@ -1,16 +1,93 @@
import type { MockMethod } from 'vite-plugin-mock';
import type { BackendServiceResult } from '@/interface';
export default [
const token: ApiAuth.Token = {
token: '__TEMP_TOKEN__',
refreshToken: '__TEMP_REFRESH_TOKEN__'
};
const apis: MockMethod[] = [
// 获取验证码
{
url: '/api/getUser',
method: 'get',
response: (): BackendServiceResult => {
url: '/mock/getSmsCode',
method: 'post',
response: (): Service.MockServiceResult<boolean> => {
return {
code: 200,
message: 'ok',
data: '测试mock数据'
data: true
};
}
},
// 密码登录
{
url: '/mock/loginByPwd',
method: 'post',
response: (): Service.MockServiceResult<ApiAuth.Token> => {
return {
code: 200,
message: 'ok',
data: token
};
}
},
// 验证码登录
{
url: '/mock/loginByCode',
method: 'post',
response: (): Service.MockServiceResult<ApiAuth.Token> => {
return {
code: 200,
message: 'ok',
data: token
};
}
},
// 获取用户信息(请求头携带token)
{
url: '/mock/getUserInfo',
method: 'get',
response: (): Service.MockServiceResult<ApiAuth.UserInfo> => {
return {
code: 200,
message: 'ok',
data: {
userId: '0',
userName: 'Soybean',
userPhone: '15170283876',
userRole: 'super'
}
};
}
},
{
url: '/mock/testToken',
method: 'post',
response: (option: any): Service.MockServiceResult<true | null> => {
if (option.headers?.authorization !== token.token) {
return {
code: 66666,
message: 'token 失效',
data: null
};
}
return {
code: 200,
message: 'ok',
data: true
};
}
},
{
url: '/mock/updateToken',
method: 'post',
response: (): Service.MockServiceResult<ApiAuth.Token> => {
return {
code: 200,
message: 'ok',
data: token
};
}
}
] as MockMethod[];
];
export default apis;

20
mock/api/demo.ts Normal file
View File

@@ -0,0 +1,20 @@
import type { MockMethod } from 'vite-plugin-mock';
const apis: MockMethod[] = [
{
url: '/mock/apiDemoWithAdapter',
method: 'post',
response: (): Service.MockServiceResult<ApiDemo.DataWithAdapter> => {
return {
code: 200,
message: 'ok',
data: {
dataId: '123',
dataName: 'demoName'
}
};
}
}
];
export default apis;

View File

@@ -1,3 +1,4 @@
import auth from './auth';
import route from './route';
export default [...auth];
export default [...auth, ...route];

372
mock/api/route.ts Normal file
View File

@@ -0,0 +1,372 @@
import type { MockMethod } from 'vite-plugin-mock';
const routes: AuthRoute.Route[] = [
{
name: 'dashboard',
path: '/dashboard',
component: 'basic',
children: [
{
name: 'dashboard_analysis',
path: '/dashboard/analysis',
component: 'self',
meta: {
title: '分析页',
requiresAuth: true,
icon: 'icon-park-outline:analysis'
}
},
{
name: 'dashboard_workbench',
path: '/dashboard/workbench',
component: 'self',
meta: {
title: '工作台',
requiresAuth: true,
permissions: ['super', 'admin'],
icon: 'icon-park-outline:workbench'
}
}
],
meta: {
title: '仪表盘',
icon: 'carbon:dashboard',
order: 1
}
},
{
name: 'document',
path: '/document',
component: 'basic',
children: [
{
name: 'document_vue',
path: '/document/vue',
component: 'self',
meta: {
title: 'vue文档',
requiresAuth: true,
icon: 'mdi:vuejs'
}
},
{
name: 'document_vue-new',
path: '/document/vue-new',
component: 'self',
meta: {
title: 'vue文档(新版)',
requiresAuth: true,
icon: 'mdi:vuejs'
}
},
{
name: 'document_vite',
path: '/document/vite',
component: 'self',
meta: {
title: 'vite文档',
requiresAuth: true,
icon: 'simple-icons:vite'
}
},
{
name: 'document_project',
path: '/document/project',
meta: {
title: '项目文档(外链)',
requiresAuth: true,
icon: 'mdi:file-link-outline',
href: 'https://docs.soybean.pro/'
}
}
],
meta: {
title: '文档',
icon: 'carbon:document',
order: 2
}
},
{
name: 'component',
path: '/component',
component: 'basic',
children: [
{
name: 'component_button',
path: '/component/button',
component: 'self',
meta: {
title: '按钮',
requiresAuth: true,
icon: 'ic:baseline-radio-button-checked'
}
},
{
name: 'component_card',
path: '/component/card',
component: 'self',
meta: {
title: '卡片',
requiresAuth: true,
icon: 'mdi:card-outline'
}
},
{
name: 'component_table',
path: '/component/table',
component: 'self',
meta: {
title: '表格',
requiresAuth: true,
icon: 'mdi:table-large'
}
}
],
meta: {
title: '组件示例',
icon: 'fluent:app-store-24-regular',
order: 3
}
},
{
name: 'plugin',
path: '/plugin',
component: 'basic',
children: [
{
name: 'plugin_map',
path: '/plugin/map',
component: 'self',
meta: {
title: '地图',
requiresAuth: true,
icon: 'mdi:map'
}
},
{
name: 'plugin_video',
path: '/plugin/video',
component: 'self',
meta: {
title: '视频',
requiresAuth: true,
icon: 'mdi:video'
}
},
{
name: 'plugin_editor',
path: '/plugin/editor',
component: 'multi',
children: [
{
name: 'plugin_editor_quill',
path: '/plugin/editor/quill',
component: 'self',
meta: {
title: '富文本编辑器',
requiresAuth: true,
icon: 'mdi:file-document-edit-outline'
}
},
{
name: 'plugin_editor_markdown',
path: '/plugin/editor/markdown',
component: 'self',
meta: {
title: 'markdown编辑器',
requiresAuth: true,
icon: 'ri:markdown-line'
}
}
],
meta: {
title: '编辑器',
icon: 'icon-park-outline:editor'
}
},
{
name: 'plugin_swiper',
path: '/plugin/swiper',
component: 'self',
meta: {
title: 'Swiper插件',
requiresAuth: true,
icon: 'simple-icons:swiper'
}
},
{
name: 'plugin_copy',
path: '/plugin/copy',
component: 'self',
meta: {
title: '剪贴板',
requiresAuth: true,
icon: 'mdi:clipboard-outline'
}
},
{
name: 'plugin_icon',
path: '/plugin/icon',
component: 'self',
meta: {
title: '图标',
requiresAuth: true,
icon: 'ic:baseline-insert-emoticon'
}
},
{
name: 'plugin_print',
path: '/plugin/print',
component: 'self',
meta: {
title: '打印',
requiresAuth: true,
icon: 'ic:baseline-local-printshop'
}
}
],
meta: {
title: '插件示例',
icon: 'clarity:plugin-line',
order: 4
}
},
{
name: 'exception',
path: '/exception',
component: 'basic',
children: [
{
name: 'exception_403',
path: '/exception/403',
component: 'self',
meta: {
title: '异常页403',
requiresAuth: true,
icon: 'ic:baseline-block'
}
},
{
name: 'exception_404',
path: '/exception/404',
component: 'self',
meta: {
title: '异常页404',
requiresAuth: true,
icon: 'ic:baseline-web-asset-off'
}
},
{
name: 'exception_500',
path: '/exception/500',
component: 'self',
meta: {
title: '异常页500',
requiresAuth: true,
icon: 'ic:baseline-wifi-off'
}
}
],
meta: {
title: '异常页',
icon: 'ant-design:exception-outlined',
order: 5
}
},
{
name: 'multi-menu',
path: '/multi-menu',
component: 'basic',
children: [
{
name: 'multi-menu_first',
path: '/multi-menu/first',
component: 'multi',
children: [
{
name: 'multi-menu_first_second',
path: '/multi-menu/first/second',
component: 'self',
meta: {
title: '二级菜单',
requiresAuth: true,
icon: 'ic:outline-menu'
}
},
{
name: 'multi-menu_first_second-new',
path: '/multi-menu/first/second-new',
component: 'multi',
children: [
{
name: 'multi-menu_first_second-new_third',
path: '/multi-menu/first/second-new/third',
component: 'self',
meta: {
title: '三级菜单',
requiresAuth: true,
icon: 'ic:outline-menu'
}
}
],
meta: {
title: '二级菜单(有子菜单)',
icon: 'ic:outline-menu'
}
}
],
meta: {
title: '一级菜单',
icon: 'ic:outline-menu'
}
}
],
meta: {
title: '多级菜单',
icon: 'carbon:menu',
order: 6
}
},
{
name: 'about',
path: '/about',
component: 'self',
meta: {
title: '关于',
requiresAuth: true,
singleLayout: 'basic',
permissions: ['super', 'admin', 'test'],
icon: 'fluent:book-information-24-regular',
order: 7
}
}
];
function dataMiddleware(data: AuthRoute.Route[]): ApiRoute.Route {
const routeHomeName: AuthRoute.RouteKey = 'dashboard_analysis';
function sortRoutes(sorts: AuthRoute.Route[]) {
return sorts.sort((next, pre) => Number(next.meta?.order) - Number(pre.meta?.order));
}
return {
routes: sortRoutes(data),
home: routeHomeName
};
}
const apis: MockMethod[] = [
{
url: '/mock/getUserRoutes',
method: 'post',
response: (): Service.MockServiceResult => {
return {
code: 200,
message: 'ok',
data: dataMiddleware(routes)
};
}
}
];
export default apis;

View File

@@ -1,26 +1,21 @@
{
"name": "soybean-admin",
"version": "0.0.5",
"author": {
"name": "Soybean",
"email": "honghuangdc@gmail.com",
"url": "https://github.com/honghuangdc"
},
"version": "0.9.3",
"scripts": {
"release": "standard-version",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md",
"dev": "vite",
"dev:prod": "vite --mode production",
"dev:staging": "vite --mode staging",
"vtsc": "vue-tsc --noEmit --skipLibCheck",
"build": "npm run vtsc && vite build",
"build:dev": "npm run vtsc && vite build --mode development",
"build:staging": "npm run vtsc && vite build --mode staging",
"serve": "vite preview",
"lint": "eslint ./src --ext .vue,.js,jsx,.ts,tsx",
"lint:fix": "eslint --fix ./src --ext .vue,.js,jsx,.ts,tsx",
"dev": "cross-env VITE_ENV_TYPE=dev vite",
"dev:test": "cross-env VITE_ENV_TYPE=test vite",
"dev:prod": "cross-env VITE_ENV_TYPE=prod vite",
"build": "npm run typecheck && cross-env VITE_ENV_TYPE=prod vite build",
"build:dev": "npm run typecheck && cross-env VITE_ENV_TYPE=dev vite build",
"build:test": "npm run typecheck && cross-env VITE_ENV_TYPE=test vite build",
"build:vercel": "cross-env VITE_HASH_ROUTE=true vite build",
"preview": "vite preview --port 5050",
"typecheck": "vue-tsc --noEmit",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix",
"prepare": "husky install",
"postinstall": "patch-package"
"postinstall": "patch-package",
"release": "standard-version",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md"
},
"lint-staged": {
"*.{vue,js,jsx,ts,tsx}": "eslint --fix"
@@ -31,77 +26,75 @@
}
},
"dependencies": {
"@antv/g2plot": "^2.4.5",
"@antv/g2plot": "^2.4.15",
"@better-scroll/core": "^2.4.2",
"@vueuse/core": "^7.5.1",
"axios": "^0.24.0",
"chroma-js": "^2.1.2",
"clipboard": "^2.0.8",
"@vueuse/core": "^8.3.1",
"axios": "^0.26.1",
"clipboard": "^2.0.10",
"colord": "^2.9.2",
"crypto-js": "^4.1.1",
"dayjs": "^1.10.7",
"dayjs": "^1.11.1",
"form-data": "^4.0.0",
"naive-ui": "^2.23.2",
"pinia": "^2.0.9",
"lodash-es": "^4.17.21",
"naive-ui": "^2.28.2",
"pinia": "^2.0.13",
"print-js": "^1.6.0",
"qs": "^6.10.2",
"swiper": "^7.4.1",
"vditor": "^3.8.10",
"vue": "^3.2.26",
"vue-router": "^4.0.12",
"wangeditor": "^4.7.11",
"xgplayer": "^2.31.4"
"qs": "^6.10.3",
"soybean-admin-layout": "^1.0.4",
"soybean-admin-tab": "^1.2.3",
"swiper": "^8.1.3",
"ua-parser-js": "^1.0.2",
"vditor": "^3.8.13",
"vue": "3.2.33",
"vue-router": "^4.0.14",
"wangeditor": "^4.7.15",
"xgplayer": "^2.31.6"
},
"devDependencies": {
"@amap/amap-jsapi-types": "^0.0.8",
"@commitlint/cli": "^16.0.1",
"@commitlint/config-conventional": "^16.0.0",
"@iconify/json": "^1.1.450",
"@iconify/vue": "^3.1.1",
"@commitlint/cli": "^16.2.3",
"@commitlint/config-conventional": "^16.2.1",
"@iconify/json": "^2.1.30",
"@iconify/vue": "^3.2.1",
"@types/bmapgl": "^0.0.5",
"@types/chroma-js": "^2.1.3",
"@types/crypto-js": "^4.1.0",
"@types/crypto-js": "^4.1.1",
"@types/node": "^17.0.25",
"@types/qs": "^6.9.7",
"@typescript-eslint/eslint-plugin": "^5.8.1",
"@typescript-eslint/parser": "^5.8.1",
"@vitejs/plugin-vue": "^2.0.1",
"@vue/compiler-sfc": "^3.2.26",
"@types/ua-parser-js": "^0.7.36",
"@typescript-eslint/eslint-plugin": "^5.20.0",
"@typescript-eslint/parser": "^5.20.0",
"@vitejs/plugin-vue": "^2.3.1",
"@vue/eslint-config-prettier": "^7.0.0",
"@vue/eslint-config-typescript": "^10.0.0",
"@vue/tsconfig": "^0.1.3",
"commitizen": "^4.2.4",
"cross-env": "^7.0.3",
"cz-conventional-changelog": "^3.3.0",
"cz-customizable": "^6.3.0",
"dotenv": "^10.0.0",
"eslint": "^8.6.0",
"eslint": "^8.13.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.25.3",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.2.0",
"eslint-plugin-vue": "^8.6.0",
"husky": "^7.0.4",
"lint-staged": "^12.1.4",
"lint-staged": "^12.4.0",
"mockjs": "^1.1.0",
"patch-package": "^6.4.7",
"postinstall-postinstall": "^2.1.0",
"prettier": "^2.5.1",
"rollup-plugin-visualizer": "^5.5.2",
"sass": "^1.45.2",
"typescript": "^4.5.4",
"unplugin-icons": "^0.13.0",
"unplugin-vue-components": "^0.17.11",
"vite": "~2.5.10",
"vite-plugin-html": "^2.1.2",
"prettier": "^2.6.2",
"rollup-plugin-visualizer": "^5.6.0",
"sass": "^1.50.1",
"typescript": "^4.6.3",
"unplugin-icons": "^0.14.1",
"unplugin-vue-components": "0.18.5",
"vite": "^2.9.5",
"vite-plugin-html": "^3.2.0",
"vite-plugin-html-template": "^1.1.2",
"vite-plugin-mock": "^2.9.6",
"vite-plugin-windicss": "^1.6.1",
"vue-tsc": "^0.30.1",
"vueuc": "^0.4.19",
"windicss": "^3.4.2"
},
"homepage": "https://github.com/honghuangdc/soybean-admin",
"repository": {
"type": "git",
"url": "git+https://github.com/honghuangdc/soybean-admin.git"
},
"bugs": {
"url": "https://github.com/honghuangdc/soybean-admin/issues"
"vite-plugin-windicss": "^1.8.4",
"vue-tsc": "^0.34.9",
"vueuc": "^0.4.32",
"windicss": "^3.5.1"
}
}

11991
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,91 +1,91 @@
.app-loading {
position: fixed;
left: 0;
top: 0;
z-index: -1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background-color:#f5f7f9;
.loading-container {
position: fixed;
left: 0;
top: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
}
.app-loading_logo {
width: 128px;
height: 128px;
.loading-svg {
width: 128px;
height: 128px;
color: var(--primary-color);
}
.app-loading__dot-wrapper {
width: 56px;
height: 56px;
margin: 36px 0;
.loading-spin__container {
width: 56px;
height: 56px;
margin: 36px 0;
}
.app-loading__dot {
position: relative;
height: 100%;
transform: rotate(45deg);
animation-name: loadingRotate;
animation-duration: 1.2s;
animation-iteration-count: infinite;
animation-timing-function: linear;
.loading-spin {
position: relative;
height: 100%;
animation: loadingSpin 1s linear infinite;
}
@keyframes loadingRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg);
}
}
@-webkit-keyframes loadingRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg);
}
}
.app-loading__dot > i {
position: absolute;
display: block;
width: 18px;
height: 18px;
background: #1890ff;
border-radius: 50%;
-webkit-transform: scale(0.75);
transform: scale(0.75);
transform-origin: 50% 50%;
opacity: 0.3;
animation: spinOpacity 1s infinite linear alternate;
}
@keyframes spinOpacity {
to {
opacity: 1;
}
}
@-webkit-keyframes spinOpacity {
to {
opacity: 1;
}
}
.delay-400 {
animation-delay: 0.4s !important;
}
.delay-800 {
animation-delay: 0.8s !important;
}
.delay-1200 {
animation-delay: 1.2s !important;
}
.left {
.left-0 {
left: 0;
}
.right {
.right-0 {
right: 0;
}
.top {
.top-0 {
top: 0;
}
.bottom {
.bottom-0 {
bottom: 0;
}
.app-loading_title {
.loading-spin-item {
position: absolute;
height: 16px;
width: 16px;
background-color: var(--primary-color);
border-radius: 8px;
-webkit-animation: loadingPulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
animation: loadingPulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes loadingSpin {
from {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes loadingPulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: .5;
}
}
.loading-delay-500 {
-webkit-animation-delay: 500ms;
animation-delay: 500ms;
}
.loading-delay-1000 {
-webkit-animation-delay: 1000ms;
animation-delay: 1000ms;
}
.loading-delay-1500 {
-webkit-animation-delay: 1500ms;
animation-delay: 1500ms;
}
.loading-title {
font-size: 28px;
font-weight: 500;
color: #646464;
}

View File

@@ -0,0 +1,44 @@
/**
* 初始化加载效果的svg格式logo
* @param {string} id - 元素id
*/
function initSvgLogo(id) {
const svgStr = `<svg width="128px" height="128px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" viewBox="0 0 158.9 158.9" style="enable-background:new 0 0 158.9 158.9;" xml:space="preserve">
<path style="fill:none" d="M0,158.9C0,106.3,0,53.7,0,1.1C0,0.2,0.2,0,1.1,0c52.2,0,104.5,0,156.7,0c0.9,0,1.1,0.2,1.1,1.1
c0,52.2,0,104.5,0,156.7c0,0.9-0.2,1.1-1.1,1.1C105.2,158.8,52.6,158.8,0,158.9z" />
<path style="fill:currentColor" d="M81.3,55.9c-0.1-11.7-2.9-22.5-9.4-32.4c-1-1.5-2.1-2.9-2.5-4.7c-0.7-3.4,0.9-6.9,4-8.6c3-1.7,6.8-1.2,9.3,1.2
c2.4,2.6,4.4,5.6,5.9,8.8c4.7,8.9,7.6,18.6,8.4,28.6c1,12.5-0.7,25-5.2,36.7c-0.9,2.5-1.9,4.9-3,7.3c-0.3,0.4-0.3,1,0,1.4
c9.6,13.3,21.8,23,37.8,27.2c6.4,1.7,13.1,2.3,19.7,1.6c4.2-0.4,7.9,2.7,8.4,6.9c0.7,4.3-2.3,8.3-6.6,9c0,0,0,0-0.1,0
c-7.7,0.9-15.5,0.5-23-1.3c-13.9-3.1-26.7-10-36.9-19.9c-4.4-4.2-8.4-8.8-11.9-13.7c-0.5-0.8-1.4-1.2-2.3-1.1
c-9.5,0.7-18.8,3.3-27.4,7.6c-11.6,6-20.7,14.6-26.4,26.4c-0.7,1.9-2,3.5-3.7,4.7c-2.9,1.7-6.6,1.5-9.2-0.7c-2.8-2.2-3.8-6-2.4-9.3
c2.2-5.2,5.1-10.1,8.7-14.5c12.2-15.4,28.2-24.6,47.3-28.6c4-0.8,8.1-1.4,12.2-1.6c0.5,0,1-0.3,1.2-0.8c3.3-7.1,5.5-14.6,6.5-22.3
C81.1,61.2,81.3,58.6,81.3,55.9z" />
<path style="fill:currentColor" d="M136.3,108.3c-3.8-0.5-7.6-1.4-11.1-2.9c-7.7-2.8-14.4-7.5-19.7-13.8c-2.9-3.3-2.5-8.4,0.8-11.3
c1.4-1.2,3.1-1.9,4.9-1.9c2.5-0.1,5,1,6.5,2.9c4.9,5.6,11.6,9.4,18.9,10.8c1.5,0.2,3.1,0.6,4.5,1.2c3.2,1.8,4.8,5.6,3.8,9.2
C144,106.1,140.8,108.4,136.3,108.3z" />
<path style="fill:currentColor" d="M55.7,33.3c3,0.2,5.6,2.2,6.6,5c2.2,5.4,3.4,11.2,3.6,17c0.3,5.9-0.6,11.7-2.5,17.3c-2,5.8-8.2,7.8-12.9,4.2
c-2.6-2.2-3.6-5.8-2.4-9c1.4-4,1.9-8.2,1.7-12.4c-0.2-3.8-1-7.5-2.4-11C45.3,38.9,49.2,33.3,55.7,33.3z" />
<path style="fill:currentColor" d="M77.9,126.6c0,3.9-2.8,7.2-6.7,7.9c-7.8,1.5-14.8,5.9-19.7,12.2c-2.7,3.5-7.6,4.2-11.2,1.6
c-3.6-2.6-4.3-7.6-1.7-11.2c0.1-0.1,0.2-0.3,0.3-0.4c4.1-5.2,9.3-9.6,15.1-12.8c4.4-2.5,9.1-4.2,14-5.1
C73.3,117.7,77.9,121.3,77.9,126.6z" />
</svg>`;
const appEl = document.querySelector(id);
const div = document.createElement('div');
div.innerHTML = svgStr;
if (appEl) {
appEl.appendChild(div);
}
}
function addThemeColorCssVars() {
const key = '__THEME_COLOR__';
const defaultColor = '#1890ff';
const themeColor = window.localStorage.getItem(key) || defaultColor;
const cssVars = `--primary-color: ${themeColor}`;
document.documentElement.style.cssText = cssVars;
}
addThemeColorCssVars();
initSvgLogo('#loadingLogo');

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -1,13 +1,24 @@
<template>
<app-provider>
<router-view />
</app-provider>
<n-config-provider
:theme="theme.naiveTheme"
:theme-overrides="theme.naiveThemeOverrides"
:locale="zhCN"
:date-locale="dateZhCN"
class="h-full"
>
<naive-provider>
<router-view />
</naive-provider>
</n-config-provider>
</template>
<script lang="ts" setup>
import { fetchTestMock } from '@/service';
import AppProvider from './AppProvider.vue';
<script setup lang="ts">
import { RouterView } from 'vue-router';
import { zhCN, dateZhCN } from 'naive-ui';
import { useThemeStore, subscribeStore } from '@/store';
fetchTestMock();
const theme = useThemeStore();
subscribeStore();
</script>
<style></style>
<style scoped></style>

View File

@@ -1,33 +0,0 @@
<template>
<n-config-provider
class="h-full"
:locale="zhCN"
:date-locale="dateZhCN"
:theme="naiveTheme"
:theme-overrides="theme.themeOverrids"
>
<n-element class="h-full">
<naive-provider>
<slot></slot>
</naive-provider>
</n-element>
</n-config-provider>
</template>
<script lang="ts" setup>
import { NConfigProvider, NElement, zhCN, dateZhCN } from 'naive-ui';
import { NaiveProvider } from '@/components';
import { useThemeStore } from '@/store';
import { useDarkMode, useGlobalEvent } from '@/composables';
const theme = useThemeStore();
const { naiveTheme } = useDarkMode();
const { initGlobalEventListener } = useGlobalEvent();
function init() {
initGlobalEventListener();
}
init();
</script>
<style></style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-activity"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline></svg>

After

Width:  |  Height:  |  Size: 282 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-at-sign"><circle cx="12" cy="12" r="4"></circle><path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-3.92 7.94"></path></svg>

After

Width:  |  Height:  |  Size: 322 B

View File

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 19 KiB

1
src/assets/svg/cast.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-cast"><path d="M2 16.1A5 5 0 0 1 5.9 20M2 12.05A9 9 0 0 1 9.95 20M2 8V6a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-6"></path><line x1="2" y1="20" x2="2.01" y2="20"></line></svg>

After

Width:  |  Height:  |  Size: 387 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chrome"><circle cx="12" cy="12" r="10"></circle><circle cx="12" cy="12" r="4"></circle><line x1="21.17" y1="8" x2="12" y2="8"></line><line x1="3.95" y1="6.06" x2="8.54" y2="14"></line><line x1="10.88" y1="21.94" x2="15.46" y2="14"></line></svg>

After

Width:  |  Height:  |  Size: 448 B

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 158.9 158.9" style="enable-background:new 0 0 158.9 158.9;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;}
.st1{fill:#409EFF;}
</style>
<path class="st0" d="M0,158.9C0,106.3,0,53.7,0,1.1C0,0.2,0.2,0,1.1,0c52.2,0,104.5,0,156.7,0c0.9,0,1.1,0.2,1.1,1.1
c0,52.2,0,104.5,0,156.7c0,0.9-0.2,1.1-1.1,1.1C105.2,158.8,52.6,158.8,0,158.9z"/>
<path class="st1" d="M81.3,55.9c-0.1-11.7-2.9-22.5-9.4-32.4c-1-1.5-2.1-2.9-2.5-4.7c-0.7-3.4,0.9-6.9,4-8.6c3-1.7,6.8-1.2,9.3,1.2
c2.4,2.6,4.4,5.6,5.9,8.8c4.7,8.9,7.6,18.6,8.4,28.6c1,12.5-0.7,25-5.2,36.7c-0.9,2.5-1.9,4.9-3,7.3c-0.3,0.4-0.3,1,0,1.4
c9.6,13.3,21.8,23,37.8,27.2c6.4,1.7,13.1,2.3,19.7,1.6c4.2-0.4,7.9,2.7,8.4,6.9c0.7,4.3-2.3,8.3-6.6,9c0,0,0,0-0.1,0
c-7.7,0.9-15.5,0.5-23-1.3c-13.9-3.1-26.7-10-36.9-19.9c-4.4-4.2-8.4-8.8-11.9-13.7c-0.5-0.8-1.4-1.2-2.3-1.1
c-9.5,0.7-18.8,3.3-27.4,7.6c-11.6,6-20.7,14.6-26.4,26.4c-0.7,1.9-2,3.5-3.7,4.7c-2.9,1.7-6.6,1.5-9.2-0.7c-2.8-2.2-3.8-6-2.4-9.3
c2.2-5.2,5.1-10.1,8.7-14.5c12.2-15.4,28.2-24.6,47.3-28.6c4-0.8,8.1-1.4,12.2-1.6c0.5,0,1-0.3,1.2-0.8c3.3-7.1,5.5-14.6,6.5-22.3
C81.1,61.2,81.3,58.6,81.3,55.9z"/>
<path class="st1" d="M136.3,108.3c-3.8-0.5-7.6-1.4-11.1-2.9c-7.7-2.8-14.4-7.5-19.7-13.8c-2.9-3.3-2.5-8.4,0.8-11.3
c1.4-1.2,3.1-1.9,4.9-1.9c2.5-0.1,5,1,6.5,2.9c4.9,5.6,11.6,9.4,18.9,10.8c1.5,0.2,3.1,0.6,4.5,1.2c3.2,1.8,4.8,5.6,3.8,9.2
C144,106.1,140.8,108.4,136.3,108.3z"/>
<path class="st1" d="M55.7,33.3c3,0.2,5.6,2.2,6.6,5c2.2,5.4,3.4,11.2,3.6,17c0.3,5.9-0.6,11.7-2.5,17.3c-2,5.8-8.2,7.8-12.9,4.2
c-2.6-2.2-3.6-5.8-2.4-9c1.4-4,1.9-8.2,1.7-12.4c-0.2-3.8-1-7.5-2.4-11C45.3,38.9,49.2,33.3,55.7,33.3z"/>
<path class="st1" d="M77.9,126.6c0,3.9-2.8,7.2-6.7,7.9c-7.8,1.5-14.8,5.9-19.7,12.2c-2.7,3.5-7.6,4.2-11.2,1.6
c-3.6-2.6-4.3-7.6-1.7-11.2c0.1-0.1,0.2-0.3,0.3-0.4c4.1-5.2,9.3-9.6,15.1-12.8c4.4-2.5,9.1-4.2,14-5.1
C73.3,117.7,77.9,121.3,77.9,126.6z"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

1
src/assets/svg/copy.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-copy"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>

After

Width:  |  Height:  |  Size: 351 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 77 KiB

1
src/assets/svg/heart.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-heart"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path></svg>

After

Width:  |  Height:  |  Size: 371 B

View File

@@ -0,0 +1 @@
<svg viewBox="0 0 158.88 158.88"><path d="M158.86.3v157.48c0 .9-.2 1.1-1.1 1.1H.24a2.61 2.61 0 01-.11-1.3V1.67C.14 0 0 .18 1.61.18h156a2.62 2.62 0 011.25.12z" fill="currentColor"/><path d="M158.86.3H2C0 .31.27 0 .27 2v156.85c-.07-.05-.25.12-.24-.12s0-.64 0-1Q0 79.46 0 1.14C0 .24.2 0 1.1 0h156.68c.35.08.81-.2 1.08.3z" fill="#fff"/><path d="M93.65 51.52a68.65 68.65 0 01-6.47 28.81 1.72 1.72 0 00.19 2c6.08 8.28 13.58 14.79 23.19 18.69a46.22 46.22 0 0017.15 3.39 28.87 28.87 0 003.34-.25 6.2 6.2 0 017 5.12 6.07 6.07 0 01-5.15 7.14 50.39 50.39 0 01-18.06-1c-15.85-3.66-28-12.75-37.44-25.7a2.15 2.15 0 00-2.23-1.09c-14 1.37-26.17 6.43-35.5 17.21a38.47 38.47 0 00-6.23 9.74 6.21 6.21 0 01-8.17 3.42 6.14 6.14 0 01-3.27-8.2 49.31 49.31 0 019.63-14.62c10.56-11.44 23.8-17.54 39.09-19.54a13.93 13.93 0 012.84-.34c1.61.14 2.18-.73 2.73-2A54.38 54.38 0 0081.12 51a44 44 0 00-8-25 6.11 6.11 0 01-.65-6.46A6 6 0 0177.75 16a6.34 6.34 0 015.66 3 53.61 53.61 0 017.17 14.28 59.33 59.33 0 013.07 18.24z" fill="#fff"/><path d="M46.92 118.63a6 6 0 011.35-3.88 37.89 37.89 0 0122.5-14 6.08 6.08 0 016.65 2.47 6.18 6.18 0 01-3.84 9.63 26.09 26.09 0 00-15.71 9.77 6.2 6.2 0 01-10.95-4zM124.3 92.8a34.66 34.66 0 01-9.82-2.48 35.46 35.46 0 01-14.65-10.45 6.19 6.19 0 012.84-9.93 5.79 5.79 0 016.44 1.73 26.79 26.79 0 0016.51 8.85 6 6 0 015 5.54 6.21 6.21 0 01-4.29 6.46 6.55 6.55 0 01-2.03.28zM69.32 53.27a33.46 33.46 0 01-2.27 12.52 6.21 6.21 0 01-10.94 1 6.09 6.09 0 01-.65-5.4 26 26 0 00-.53-18.25 6.21 6.21 0 0111.49-4.72 40.24 40.24 0 012.9 14.85z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

1
src/assets/svg/logo.svg Normal file
View File

@@ -0,0 +1 @@
<svg viewBox="0 0 158.88 158.88"><path d="M0 158.86V1.1C0 .2.2 0 1.1 0h156.68c.9 0 1.1.2 1.1 1.1v156.68c0 .9-.2 1.1-1.1 1.1Q78.9 158.83 0 158.86z" fill="#ffffff00"/><path d="M81.28 55.9c-.1-11.67-2.93-22.55-9.37-32.38-1-1.5-2.14-2.86-2.5-4.71a8.1 8.1 0 014-8.61 7.89 7.89 0 019.3 1.23 36 36 0 015.9 8.83 75.18 75.18 0 018.44 28.58 83.21 83.21 0 01-5.23 36.74 103 103 0 01-3 7.28 1.2 1.2 0 000 1.41c9.58 13.3 21.76 23 37.85 27.24a54.35 54.35 0 0019.68 1.57 7.72 7.72 0 018.36 6.9 7.9 7.9 0 01-6.7 9 64.74 64.74 0 01-23-1.33 77.68 77.68 0 01-36.93-19.88 93.64 93.64 0 01-11.91-13.71 2.18 2.18 0 00-2.3-1.06 72.75 72.75 0 00-27.38 7.55c-11.6 6-20.67 14.58-26.4 26.45a10.13 10.13 0 01-3.7 4.7 8 8 0 01-9.19-.7 7.86 7.86 0 01-2.36-9.28 60.32 60.32 0 018.72-14.52c12.2-15.43 28.21-24.59 47.32-28.57A85.08 85.08 0 0173.07 87a1.22 1.22 0 001.18-.8 76.06 76.06 0 006.53-22.3 57.87 57.87 0 00.5-8z" fill="currentColor"/><path d="M136.26 108.34a44.72 44.72 0 01-11.13-2.87 46.11 46.11 0 01-19.66-13.76 8 8 0 015.72-13.22 7.93 7.93 0 016.54 2.93 33.27 33.27 0 0018.87 10.75 14.76 14.76 0 014.48 1.18 8.08 8.08 0 013.84 9.21c-.92 3.52-4.13 5.81-8.66 5.78zM55.66 33.32a7.61 7.61 0 016.64 5 49.14 49.14 0 013.64 17 46.33 46.33 0 01-2.46 17.28c-2 5.77-8.24 7.79-12.89 4.15a8.1 8.1 0 01-2.39-9 31.68 31.68 0 001.68-12.36 35.77 35.77 0 00-2.43-11c-2.1-5.45 1.75-11.07 8.21-11.07zM77.92 126.57a8 8 0 01-6.68 7.86 32.88 32.88 0 00-19.7 12.19 8.13 8.13 0 01-11.21 1.62 8 8 0 01-1.41-11.58A51.05 51.05 0 0154 123.81a45.85 45.85 0 0114-5.1c5.35-1.04 9.91 2.56 9.92 7.86z" fill="currentColor"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 50 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 33 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 74 KiB

1
src/assets/svg/wind.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-wind"><path d="M9.59 4.59A2 2 0 1 1 11 8H2m10.59 11.41A2 2 0 1 0 14 16H2m15.73-8.27A2.5 2.5 0 1 1 19.5 12H2"></path></svg>

After

Width:  |  Height:  |  Size: 326 B

View File

@@ -6,19 +6,15 @@
<n-spin :show="true" :size="loadingSize" />
</div>
<div v-show="isEmpty" class="absolute-center">
<div class="relative" :class="emptyNetworkClass">
<svg-empty-data class="text-primary" />
<p class="absolute-lb w-full text-center">{{ emptyDesc }}</p>
<div class="relative">
<icon-custom-empty-data :class="iconClass" />
<p class="absolute-lb w-full text-center" :class="descClass">{{ emptyDesc }}</p>
</div>
</div>
<div v-show="!network" class="absolute-center">
<div
class="relative"
:class="[{ 'cursor-pointer': showNetworkReload }, emptyNetworkClass]"
@click="handleReload"
>
<svg-network-error class="text-primary" />
<p class="absolute-lb w-full text-center">{{ networkErrorDesc }}</p>
<div class="relative" :class="{ 'cursor-pointer': showNetworkReload }" @click="handleReload">
<icon-custom-network-error :class="iconClass" />
<p class="absolute-lb w-full text-center" :class="descClass">{{ networkErrorDesc }}</p>
</div>
</div>
</div>
@@ -26,11 +22,9 @@
</template>
<script setup lang="ts">
import { computed, watch, nextTick } from 'vue';
import { NSpin } from 'naive-ui';
import { computed, watch, nextTick, onUnmounted } from 'vue';
import { NETWORK_ERROR_MSG } from '@/config';
import { useBoolean } from '@/hooks';
import { SvgEmptyData, SvgNetworkError } from '../../svg';
interface Props {
/** 是否加载 */
@@ -43,8 +37,10 @@ interface Props {
placeholderClass?: string;
/** 空数据描述文本 */
emptyDesc?: string;
/** 空数据和网络异常占位class */
emptyNetworkClass?: string;
/** 图标的class */
iconClass?: string;
/** 描述文本的class */
descClass?: string;
/** 显示网络异常的重试点击按钮 */
showNetworkReload?: boolean;
}
@@ -53,9 +49,10 @@ const props = withDefaults(defineProps<Props>(), {
loading: false,
empty: false,
loadingSize: 'medium',
placeholderClass: 'bg-white',
placeholderClass: 'bg-white dark:bg-dark transition-background-color duration-300 ease-in-out',
emptyDesc: '暂无数据',
emptyNetworkClass: 'w-320px h-320px text-16px text-[#666]',
iconClass: 'text-320px text-primary',
descClass: 'text-16px text-[#666]',
showNetworkReload: false
});
@@ -80,7 +77,7 @@ function handleReload() {
});
}
watch(
const stopHandle = watch(
() => props.loading,
newValue => {
//
@@ -89,5 +86,9 @@ watch(
}
}
);
onUnmounted(() => {
stopHandle();
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,47 @@
<template>
<div class="w-full text-14px">
<n-checkbox v-model:checked="checked">我已经仔细阅读并接受</n-checkbox>
<n-button :text="true" type="primary" @click="handleClickProtocol">用户协议</n-button>
<n-button :text="true" type="primary" @click="handleClickPolicy">隐私权政策</n-button>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
interface Props {
/** 是否勾选 */
value?: boolean;
}
interface Emits {
(e: 'update:value', value: boolean): void;
/** 点击协议 */
(e: 'click-protocol'): void;
/** 点击隐私政策 */
(e: 'click-policy'): void;
}
const props = withDefaults(defineProps<Props>(), {
value: true
});
const emit = defineEmits<Emits>();
const checked = computed({
get() {
return props.value;
},
set(newValue: boolean) {
emit('update:value', newValue);
}
});
function handleClickProtocol() {
emit('click-protocol');
}
function handleClickPolicy() {
emit('click-policy');
}
</script>
<style scoped></style>

View File

@@ -1,611 +0,0 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
<g id="freepik--background-complete--inject-83">
<rect y="382.4" width="500" height="0.25" style="fill: #ebebeb"></rect>
<rect x="416.78" y="398.49" width="33.12" height="0.25" style="fill: #ebebeb"></rect>
<rect x="322.53" y="401.21" width="8.69" height="0.25" style="fill: #ebebeb"></rect>
<rect x="396.59" y="389.21" width="19.19" height="0.25" style="fill: #ebebeb"></rect>
<rect x="52.46" y="390.89" width="43.19" height="0.25" style="fill: #ebebeb"></rect>
<rect x="104.56" y="390.89" width="6.33" height="0.25" style="fill: #ebebeb"></rect>
<rect x="131.47" y="395.11" width="93.68" height="0.25" style="fill: #ebebeb"></rect>
<path
d="M237,337.8H43.91a5.71,5.71,0,0,1-5.7-5.71V60.66A5.71,5.71,0,0,1,43.91,55H237a5.71,5.71,0,0,1,5.71,5.71V332.09A5.71,5.71,0,0,1,237,337.8ZM43.91,55.2a5.46,5.46,0,0,0-5.45,5.46V332.09a5.46,5.46,0,0,0,5.45,5.46H237a5.47,5.47,0,0,0,5.46-5.46V60.66A5.47,5.47,0,0,0,237,55.2Z"
style="fill: #ebebeb"
></path>
<path
d="M453.31,337.8H260.21a5.72,5.72,0,0,1-5.71-5.71V60.66A5.72,5.72,0,0,1,260.21,55h193.1A5.71,5.71,0,0,1,459,60.66V332.09A5.71,5.71,0,0,1,453.31,337.8ZM260.21,55.2a5.47,5.47,0,0,0-5.46,5.46V332.09a5.47,5.47,0,0,0,5.46,5.46h193.1a5.47,5.47,0,0,0,5.46-5.46V60.66a5.47,5.47,0,0,0-5.46-5.46Z"
style="fill: #ebebeb"
></path>
<rect
x="301.09"
y="78.79"
width="108.81"
height="196.62"
transform="translate(710.99 354.2) rotate(180)"
style="fill: #e6e6e6"
></rect>
<rect
x="296.07"
y="78.79"
width="111.48"
height="196.62"
transform="translate(703.63 354.2) rotate(180)"
style="fill: #f0f0f0"
></rect>
<rect
x="301.09"
y="275.41"
width="108.81"
height="4.66"
transform="translate(710.99 555.48) rotate(180)"
style="fill: #e6e6e6"
></rect>
<rect
x="294.26"
y="275.41"
width="111.48"
height="4.66"
transform="translate(700.01 555.48) rotate(180)"
style="fill: #f0f0f0"
></rect>
<rect
x="260.53"
y="128.39"
width="182.56"
height="97.42"
transform="translate(528.91 -174.71) rotate(90)"
style="fill: #fafafa"
></rect>
<polygon
points="330.66 268.38 358.08 85.82 377.56 85.82 350.13 268.38 330.66 268.38"
style="fill: #fff"
></polygon>
<polygon
points="333.75 268.38 361.18 85.82 380.65 85.82 353.22 268.38 333.75 268.38"
style="fill: #fff"
></polygon>
<polygon
points="354.31 268.38 381.74 85.82 389.33 85.82 361.91 268.38 354.31 268.38"
style="fill: #fff"
></polygon>
<rect
x="212.27"
y="176.65"
width="182.56"
height="0.89"
transform="translate(480.65 -126.45) rotate(90)"
style="fill: #e6e6e6"
></rect>
<polygon
points="294.41 91.12 403.22 91.12 403.86 88.55 295.06 88.55 294.41 91.12"
style="fill: #ebebeb; opacity: 0.6000000000000001"
></polygon>
<polygon
points="294.41 95.32 403.22 95.32 403.86 92.76 295.06 92.76 294.41 95.32"
style="fill: #ebebeb; opacity: 0.6000000000000001"
></polygon>
<polygon
points="294.41 99.53 403.22 99.53 403.86 96.97 295.06 96.97 294.41 99.53"
style="fill: #ebebeb; opacity: 0.6000000000000001"
></polygon>
<polygon
points="294.41 103.74 403.22 103.74 403.86 101.17 295.06 101.17 294.41 103.74"
style="fill: #ebebeb; opacity: 0.6000000000000001"
></polygon>
<polygon
points="294.41 107.95 403.22 107.95 403.86 105.38 295.06 105.38 294.41 107.95"
style="fill: #ebebeb; opacity: 0.6000000000000001"
></polygon>
<polygon
points="294.41 112.15 403.22 112.15 403.86 109.59 295.06 109.59 294.41 112.15"
style="fill: #ebebeb; opacity: 0.6000000000000001"
></polygon>
<rect x="274.53" y="67" width="156.92" height="3.79" style="fill: #f0f0f0"></rect>
<rect x="420.36" y="63.81" width="8.25" height="242.84" style="fill: #fafafa; opacity: 0.8"></rect>
<rect x="420.36" y="63.81" width="2.14" height="242.84" style="fill: #f0f0f0; opacity: 0.8"></rect>
<rect x="412.11" y="63.81" width="8.25" height="242.84" style="fill: #fafafa; opacity: 0.8"></rect>
<rect x="412.11" y="63.81" width="2.14" height="242.84" style="fill: #f0f0f0; opacity: 0.8"></rect>
<rect x="403.86" y="63.81" width="8.25" height="242.84" style="fill: #fafafa; opacity: 0.8"></rect>
<rect x="292.84" y="63.81" width="8.25" height="242.84" style="fill: #fafafa; opacity: 0.8"></rect>
<rect x="292.84" y="63.81" width="2.14" height="242.84" style="fill: #f0f0f0; opacity: 0.8"></rect>
<rect x="284.6" y="63.81" width="8.25" height="242.84" style="fill: #fafafa; opacity: 0.8"></rect>
<rect x="284.6" y="63.81" width="2.14" height="242.84" style="fill: #f0f0f0; opacity: 0.8"></rect>
<rect x="276.35" y="63.81" width="8.25" height="242.84" style="fill: #fafafa; opacity: 0.8"></rect>
<rect
x="85.34"
y="78.79"
width="108.81"
height="196.62"
transform="translate(279.49 354.2) rotate(180)"
style="fill: #e6e6e6"
></rect>
<rect
x="80.32"
y="78.79"
width="111.48"
height="196.62"
transform="translate(272.12 354.2) rotate(180)"
style="fill: #f0f0f0"
></rect>
<rect
x="85.34"
y="275.41"
width="108.81"
height="4.66"
transform="translate(279.49 555.48) rotate(180)"
style="fill: #e6e6e6"
></rect>
<rect
x="78.51"
y="275.41"
width="111.48"
height="4.66"
transform="translate(268.5 555.48) rotate(180)"
style="fill: #f0f0f0"
></rect>
<rect
x="44.78"
y="128.39"
width="182.56"
height="97.42"
transform="translate(313.16 41.04) rotate(90)"
style="fill: #fafafa"
></rect>
<polygon
points="114.91 268.38 142.33 85.82 161.81 85.82 134.38 268.38 114.91 268.38"
style="fill: #fff"
></polygon>
<polygon points="118 268.38 145.42 85.82 164.9 85.82 137.47 268.38 118 268.38" style="fill: #fff"></polygon>
<polygon
points="138.56 268.38 165.99 85.82 173.58 85.82 146.16 268.38 138.56 268.38"
style="fill: #fff"
></polygon>
<rect
x="-3.49"
y="176.65"
width="182.56"
height="0.89"
transform="translate(264.9 89.3) rotate(90)"
style="fill: #e6e6e6"
></rect>
<polygon
points="78.66 91.12 187.47 91.12 188.11 88.55 79.31 88.55 78.66 91.12"
style="fill: #ebebeb; opacity: 0.6000000000000001"
></polygon>
<polygon
points="78.66 95.32 187.47 95.32 188.11 92.76 79.31 92.76 78.66 95.32"
style="fill: #ebebeb; opacity: 0.6000000000000001"
></polygon>
<polygon
points="78.66 99.53 187.47 99.53 188.11 96.97 79.31 96.97 78.66 99.53"
style="fill: #ebebeb; opacity: 0.6000000000000001"
></polygon>
<polygon
points="78.66 103.74 187.47 103.74 188.11 101.17 79.31 101.17 78.66 103.74"
style="fill: #ebebeb; opacity: 0.6000000000000001"
></polygon>
<polygon
points="78.66 107.95 187.47 107.95 188.11 105.38 79.31 105.38 78.66 107.95"
style="fill: #ebebeb; opacity: 0.6000000000000001"
></polygon>
<polygon
points="78.66 112.15 187.47 112.15 188.11 109.59 79.31 109.59 78.66 112.15"
style="fill: #ebebeb; opacity: 0.6000000000000001"
></polygon>
<rect x="58.78" y="67" width="156.92" height="3.79" style="fill: #f0f0f0"></rect>
<rect x="204.61" y="63.81" width="8.25" height="242.84" style="fill: #fafafa; opacity: 0.8"></rect>
<rect x="204.61" y="63.81" width="2.14" height="242.84" style="fill: #f0f0f0; opacity: 0.8"></rect>
<rect x="196.36" y="63.81" width="8.25" height="242.84" style="fill: #fafafa; opacity: 0.8"></rect>
<rect x="196.36" y="63.81" width="2.14" height="242.84" style="fill: #f0f0f0; opacity: 0.8"></rect>
<rect x="188.11" y="63.81" width="8.25" height="242.84" style="fill: #fafafa; opacity: 0.8"></rect>
<rect x="77.09" y="63.81" width="8.25" height="242.84" style="fill: #fafafa; opacity: 0.8"></rect>
<rect x="77.09" y="63.81" width="2.14" height="242.84" style="fill: #f0f0f0; opacity: 0.8"></rect>
<rect x="68.84" y="63.81" width="8.25" height="242.84" style="fill: #fafafa; opacity: 0.8"></rect>
<rect x="68.84" y="63.81" width="2.14" height="242.84" style="fill: #f0f0f0; opacity: 0.8"></rect>
<rect x="60.59" y="63.81" width="8.25" height="242.84" style="fill: #fafafa; opacity: 0.8"></rect>
<rect
x="375.76"
y="291.61"
width="16.81"
height="84"
transform="translate(768.34 667.22) rotate(180)"
style="fill: #f0f0f0"
></rect>
<rect
x="243.98"
y="375.61"
width="142.46"
height="6.79"
transform="translate(630.42 758.01) rotate(180)"
style="fill: #f0f0f0"
></rect>
<rect x="237.85" y="291.61" width="137.92" height="84" style="fill: #f5f5f5"></rect>
<rect x="250.41" y="300.51" width="112.79" height="27.94" style="fill: #f0f0f0"></rect>
<rect x="250.41" y="334.85" width="112.79" height="27.94" style="fill: #f0f0f0"></rect>
<path
d="M293.44,304.36h26.73a2.41,2.41,0,0,0,2.41-2.41h0a2.42,2.42,0,0,0-2.41-2.41H293.44A2.42,2.42,0,0,0,291,302h0A2.41,2.41,0,0,0,293.44,304.36Z"
style="fill: #f5f5f5"
></path>
<path
d="M293.44,338.71h26.73a2.42,2.42,0,0,0,2.41-2.41h0a2.41,2.41,0,0,0-2.41-2.41H293.44A2.41,2.41,0,0,0,291,336.3h0A2.42,2.42,0,0,0,293.44,338.71Z"
style="fill: #f5f5f5"
></path>
<rect
x="233.59"
y="288.33"
width="142.18"
height="3.28"
transform="translate(609.35 579.95) rotate(180)"
style="fill: #f0f0f0"
></rect>
<rect x="375.76" y="288.33" width="21.28" height="3.28" style="fill: #e6e6e6"></rect>
<path
d="M108.34,376.83h0a7.25,7.25,0,0,1-7.23-7.23V298.84a7.25,7.25,0,0,1,7.23-7.23h0a7.24,7.24,0,0,1,7.22,7.23V369.6A7.24,7.24,0,0,1,108.34,376.83Z"
style="fill: #f5f5f5"
></path>
<path
d="M112.47,374h0a4.9,4.9,0,0,1-4.88-4.88V299.34a4.9,4.9,0,0,1,4.88-4.88h0a4.9,4.9,0,0,1,4.89,4.88V369.1A4.9,4.9,0,0,1,112.47,374Z"
style="fill: #ebebeb"
></path>
<path
d="M118.83,376.83h0a7.24,7.24,0,0,1-7.22-7.23V298.84a7.24,7.24,0,0,1,7.22-7.23h0a7.25,7.25,0,0,1,7.23,7.23V369.6A7.25,7.25,0,0,1,118.83,376.83Z"
style="fill: #f5f5f5"
></path>
<path
d="M123,374h0a4.89,4.89,0,0,1-4.88-4.88V299.34a4.89,4.89,0,0,1,4.88-4.88h0a4.89,4.89,0,0,1,4.88,4.88V369.1A4.89,4.89,0,0,1,123,374Z"
style="fill: #ebebeb"
></path>
<rect x="122.1" y="291.61" width="14.45" height="85.22" rx="7.23" style="fill: #f5f5f5"></rect>
<path
d="M133.47,374h0a4.89,4.89,0,0,1-4.88-4.88V299.34a4.89,4.89,0,0,1,4.88-4.88h0a4.89,4.89,0,0,1,4.88,4.88V369.1A4.89,4.89,0,0,1,133.47,374Z"
style="fill: #ebebeb"
></path>
<path
d="M139.83,376.83h0a7.25,7.25,0,0,1-7.23-7.23V298.84a7.25,7.25,0,0,1,7.23-7.23h0a7.25,7.25,0,0,1,7.23,7.23V369.6A7.25,7.25,0,0,1,139.83,376.83Z"
style="fill: #f5f5f5"
></path>
<path
d="M144,374h0a4.9,4.9,0,0,1-4.89-4.88V299.34a4.9,4.9,0,0,1,4.89-4.88h0a4.9,4.9,0,0,1,4.88,4.88V369.1A4.9,4.9,0,0,1,144,374Z"
style="fill: #ebebeb"
></path>
<path
d="M150.33,376.83h0a7.25,7.25,0,0,1-7.23-7.23V298.84a7.25,7.25,0,0,1,7.23-7.23h0a7.25,7.25,0,0,1,7.23,7.23V369.6A7.25,7.25,0,0,1,150.33,376.83Z"
style="fill: #f5f5f5"
></path>
<path
d="M154.47,374h0a4.9,4.9,0,0,1-4.89-4.88V299.34a4.9,4.9,0,0,1,4.89-4.88h0a4.9,4.9,0,0,1,4.88,4.88V369.1A4.9,4.9,0,0,1,154.47,374Z"
style="fill: #ebebeb"
></path>
<path
d="M160.83,376.83h0a7.25,7.25,0,0,1-7.23-7.23V298.84a7.25,7.25,0,0,1,7.23-7.23h0a7.24,7.24,0,0,1,7.22,7.23V369.6A7.24,7.24,0,0,1,160.83,376.83Z"
style="fill: #f5f5f5"
></path>
<path
d="M165,374h0a4.9,4.9,0,0,1-4.88-4.88V299.34a4.9,4.9,0,0,1,4.88-4.88h0a4.9,4.9,0,0,1,4.89,4.88V369.1A4.9,4.9,0,0,1,165,374Z"
style="fill: #ebebeb"
></path>
<path
d="M171.33,376.83h0a7.25,7.25,0,0,1-7.23-7.23V298.84a7.25,7.25,0,0,1,7.23-7.23h0a7.24,7.24,0,0,1,7.22,7.23V369.6A7.24,7.24,0,0,1,171.33,376.83Z"
style="fill: #f5f5f5"
></path>
<rect x="157.39" y="364.15" width="24.4" height="3.2" rx="1.6" style="fill: #f5f5f5"></rect>
<path
d="M180.19,306.38H159a1.6,1.6,0,0,1-1.6-1.6h0a1.6,1.6,0,0,1,1.6-1.6h21.2a1.6,1.6,0,0,1,1.6,1.6h0A1.6,1.6,0,0,1,180.19,306.38Z"
style="fill: #f5f5f5"
></path>
</g>
<g id="freepik--Shadow--inject-83">
<ellipse
id="freepik--path--inject-83"
cx="250"
cy="416.24"
rx="193.89"
ry="11.32"
style="fill: #f5f5f5"
></ellipse>
</g>
<g id="freepik--information-tab--inject-83">
<path
d="M409.83,248.66h-239a9.25,9.25,0,0,1-9.32-9.93l8.76-141.08a10.75,10.75,0,0,1,10.55-9.94h239a9.26,9.26,0,0,1,9.32,9.94l-8.76,141.08A10.75,10.75,0,0,1,409.83,248.66Z"
style="fill: currentColor"
></path>
<path
d="M409.83,248.66h-239a9.25,9.25,0,0,1-9.32-9.93l8.76-141.08a10.75,10.75,0,0,1,10.55-9.94h239a9.26,9.26,0,0,1,9.32,9.94l-8.76,141.08A10.75,10.75,0,0,1,409.83,248.66Z"
style="fill: #fff; opacity: 0.8"
></path>
<path
d="M201.46,128.36H173a2.61,2.61,0,0,1-2.64-2.81l.81-13a3,3,0,0,1,3-2.82h28.46Z"
style="fill: #fff; opacity: 0.4"
></path>
<path
d="M419.67,90.2H211.28a8,8,0,0,0-7.91,7.45l-2,32.37H172.9a3,3,0,0,0-3,2.82l-.75,12.2a2.61,2.61,0,0,0,2.64,2.82h28.46l-5.64,90.87a6.92,6.92,0,0,0,7,7.45H410a8,8,0,0,0,7.91-7.45l8.76-141.08A6.91,6.91,0,0,0,419.67,90.2Z"
style="fill: #fff"
></path>
<path
d="M199,167.36H170.58a2.62,2.62,0,0,1-2.65-2.82l.76-12.2a3,3,0,0,1,3-2.82h28.46Z"
style="fill: #fff; opacity: 0.4"
></path>
<path
d="M197.83,186.86H169.37a2.62,2.62,0,0,1-2.65-2.82l.76-12.21a3,3,0,0,1,3-2.81h28.46Z"
style="fill: #fff; opacity: 0.4"
></path>
<path
d="M196.62,206.36H168.16a2.63,2.63,0,0,1-2.65-2.82l.76-12.21a3.05,3.05,0,0,1,3-2.82h28.46Z"
style="fill: #fff; opacity: 0.4"
></path>
<path
d="M195.41,225.85H167A2.62,2.62,0,0,1,164.3,223l.76-12.2a3,3,0,0,1,3-2.82h28.47Z"
style="fill: #fff; opacity: 0.4"
></path>
<path
d="M172.63,145.59a1.13,1.13,0,0,1-1.15-1.23l.66-10.71a1.48,1.48,0,0,1,1.44-1.36H197.7a1.13,1.13,0,0,1,1.15,1.23l-.66,10.72a1.48,1.48,0,0,1-1.44,1.35Z"
style="fill: currentColor; opacity: 0.2"
></path>
<path
d="M253,107H218.57a4.47,4.47,0,0,1-4.49-4.79h0a5.17,5.17,0,0,1,5.08-4.78h34.41a4.46,4.46,0,0,1,4.49,4.78h0A5.19,5.19,0,0,1,253,107Z"
style="fill: currentColor; opacity: 0.30000000000000004"
></path>
<path
d="M417,102.22a5.17,5.17,0,0,1-5.08,4.79,4.46,4.46,0,0,1-4.49-4.79,5.16,5.16,0,0,1,5.08-4.78A4.45,4.45,0,0,1,417,102.22Z"
style="fill: currentColor"
></path>
<path
d="M319.53,188.84H218a8.83,8.83,0,0,1-8.9-9.49L212.15,130a10.23,10.23,0,0,1,10.07-9.48H323.78a8.81,8.81,0,0,1,8.89,9.48l-3.06,49.34A10.26,10.26,0,0,1,319.53,188.84Zm-97.34-67.9a9.79,9.79,0,0,0-9.63,9.07l-3.06,49.34a8.43,8.43,0,0,0,8.51,9.07H319.56a9.79,9.79,0,0,0,9.63-9.07L332.26,130a8.44,8.44,0,0,0-8.51-9.07Z"
style="fill: currentColor; opacity: 0.4"
></path>
<path
d="M230.33,153.34l14.57,9.43a33,33,0,0,1,11.33-10.27L248.4,137A52.81,52.81,0,0,0,230.33,153.34Z"
style="fill: currentColor"
></path>
<path
d="M230.33,153.34l14.57,9.43a33,33,0,0,1,11.33-10.27L248.4,137A52.81,52.81,0,0,0,230.33,153.34Z"
style="fill: #fff; opacity: 0.8"
></path>
<path
d="M221.55,178.6h17.84a31.51,31.51,0,0,1,5.51-15.83l-14.57-9.43A50.28,50.28,0,0,0,221.55,178.6Z"
style="fill: #263238"
></path>
<path
d="M272.36,130.76a49.82,49.82,0,0,0-24,6.22l7.83,15.52a31.31,31.31,0,0,1,15-3.89,27.86,27.86,0,0,1,28.13,30h17.84C318.88,152.18,298.79,130.76,272.36,130.76Z"
style="fill: currentColor"
></path>
<path d="M260.78,207h-52.3a.85.85,0,0,1-.85-.91l.23-3.68a1,1,0,0,1,1-.91h52.3Z" style="fill: currentColor"></path>
<path
d="M260.78,207h66a1,1,0,0,0,1-.91l.23-3.68a.85.85,0,0,0-.85-.91h-66Z"
style="fill: currentColor; opacity: 0.2"
></path>
<path
d="M296.3,221.51H207.58a.84.84,0,0,1-.85-.91l.23-3.67a1,1,0,0,1,1-.91h88.72Z"
style="fill: currentColor"
></path>
<path
d="M296.3,221.51h29.58a1,1,0,0,0,1-.91l.23-3.67a.84.84,0,0,0-.85-.91H296.64Z"
style="fill: currentColor; opacity: 0.2"
></path>
<path
d="M217.1,236H206.68a.85.85,0,0,1-.85-.91l.23-3.68a1,1,0,0,1,1-.91h10.42Z"
style="fill: currentColor"
></path>
<path
d="M217.1,236H325a1,1,0,0,0,1-.91l.23-3.68a.85.85,0,0,0-.86-.91H217.44Z"
style="fill: currentColor; opacity: 0.2"
></path>
<path
d="M348.77,236.45a.38.38,0,0,1-.39-.41l7.16-115.31a.44.44,0,0,1,.44-.41.38.38,0,0,1,.38.41L349.2,236A.44.44,0,0,1,348.77,236.45Z"
style="fill: currentColor"
></path>
<path
d="M356.83,150.94a3,3,0,0,1-2.93,2.76,2.57,2.57,0,0,1-2.59-2.76,3,3,0,0,1,2.94-2.76A2.55,2.55,0,0,1,356.83,150.94Z"
style="fill: #fff"
></path>
<path
d="M353.88,154.11a3,3,0,0,1-3-3.17,3.43,3.43,0,0,1,3.37-3.18,3,3,0,0,1,3,3.18A3.42,3.42,0,0,1,353.88,154.11Zm.34-5.52a2.53,2.53,0,0,0-2.49,2.35,2.18,2.18,0,0,0,2.2,2.34,2.53,2.53,0,0,0,2.49-2.34A2.18,2.18,0,0,0,354.22,148.59Z"
style="fill: currentColor"
></path>
<path
d="M355.29,175.78a3,3,0,0,1-2.93,2.76,2.57,2.57,0,0,1-2.59-2.76A3,3,0,0,1,352.7,173,2.56,2.56,0,0,1,355.29,175.78Z"
style="fill: #fff"
></path>
<path
d="M352.34,179a3,3,0,0,1-3-3.17,3.43,3.43,0,0,1,3.37-3.18,3,3,0,0,1,3,3.18A3.42,3.42,0,0,1,352.34,179Zm.34-5.52a2.53,2.53,0,0,0-2.49,2.35,2.17,2.17,0,0,0,2.2,2.34,2.53,2.53,0,0,0,2.49-2.34A2.18,2.18,0,0,0,352.68,173.43Z"
style="fill: currentColor"
></path>
<polygon points="351.78 187.86 348.13 193.57 354.73 193.57 351.78 187.86" style="fill: #fff"></polygon>
<path
d="M354.7,194h-6.6a.39.39,0,0,1-.34-.2.42.42,0,0,1,0-.42l3.66-5.71a.42.42,0,0,1,.71,0l3,5.71a.44.44,0,0,1-.4.62Zm-5.83-.82H354l-2.3-4.48Z"
style="fill: currentColor"
></path>
<path
d="M398.45,236.45a.38.38,0,0,1-.39-.41l7.16-115.31a.44.44,0,0,1,.44-.41.38.38,0,0,1,.39.41L398.89,236A.45.45,0,0,1,398.45,236.45Z"
style="fill: currentColor"
></path>
<path
d="M403.67,196.71a2.56,2.56,0,0,0-2.58-2.76,3,3,0,0,0-2.94,2.76,2.57,2.57,0,0,0,2.59,2.76A3,3,0,0,0,403.67,196.71Z"
style="fill: #fff"
></path>
<path
d="M400.72,199.88a3,3,0,0,1-3-3.17,3.42,3.42,0,0,1,3.37-3.17,3,3,0,0,1,3,3.17A3.42,3.42,0,0,1,400.72,199.88Zm.34-5.52a2.54,2.54,0,0,0-2.49,2.35,2.19,2.19,0,0,0,2.2,2.35,2.54,2.54,0,0,0,2.49-2.35A2.19,2.19,0,0,0,401.06,194.36Z"
style="fill: currentColor"
></path>
<path
d="M407.53,134.6a2.56,2.56,0,0,0-2.59-2.76A3,3,0,0,0,402,134.6a2.57,2.57,0,0,0,2.59,2.76A3,3,0,0,0,407.53,134.6Z"
style="fill: #fff"
></path>
<path
d="M404.57,137.77a2.94,2.94,0,0,1-3-3.17,3.43,3.43,0,0,1,3.37-3.18,3,3,0,0,1,3,3.18A3.43,3.43,0,0,1,404.57,137.77Zm.35-5.52a2.53,2.53,0,0,0-2.49,2.35,2.17,2.17,0,0,0,2.2,2.34,2.53,2.53,0,0,0,2.49-2.34A2.18,2.18,0,0,0,404.92,132.25Z"
style="fill: currentColor"
></path>
<polygon points="402.64 168.92 399.7 163.2 406.29 163.2 402.64 168.92" style="fill: #fff"></polygon>
<path
d="M402.61,169.33a.38.38,0,0,1-.34-.21l-2.95-5.71a.43.43,0,0,1,0-.41.44.44,0,0,1,.37-.21h6.6a.39.39,0,0,1,.35.21.43.43,0,0,1,0,.41L403,169.12A.47.47,0,0,1,402.61,169.33Zm-2.22-5.71,2.3,4.47,2.86-4.47Z"
style="fill: currentColor"
></path>
<path
d="M373.61,236.45a.38.38,0,0,1-.39-.41l7.16-115.31a.44.44,0,0,1,.44-.41.37.37,0,0,1,.38.41L374.05,236A.45.45,0,0,1,373.61,236.45Z"
style="fill: currentColor"
></path>
<path
d="M381.24,158a3,3,0,0,1-2.94,2.76,2.55,2.55,0,0,1-2.58-2.76,3,3,0,0,1,2.93-2.76A2.57,2.57,0,0,1,381.24,158Z"
style="fill: #fff"
></path>
<path
d="M378.28,161.2a3,3,0,0,1-3-3.18,3.42,3.42,0,0,1,3.37-3.17,3,3,0,0,1,3,3.17A3.43,3.43,0,0,1,378.28,161.2Zm.34-5.53a2.54,2.54,0,0,0-2.49,2.35,2.19,2.19,0,0,0,2.2,2.35,2.54,2.54,0,0,0,2.49-2.35A2.18,2.18,0,0,0,378.62,155.67Z"
style="fill: currentColor"
></path>
<path
d="M377.81,213.26a3,3,0,0,1-2.93,2.76,2.56,2.56,0,0,1-2.59-2.76,3,3,0,0,1,2.93-2.76A2.57,2.57,0,0,1,377.81,213.26Z"
style="fill: #fff"
></path>
<path
d="M374.85,216.43a3,3,0,0,1-3-3.17,3.43,3.43,0,0,1,3.37-3.18,3,3,0,0,1,3,3.18A3.42,3.42,0,0,1,374.85,216.43Zm.34-5.52a2.53,2.53,0,0,0-2.49,2.35,2.18,2.18,0,0,0,2.2,2.34,2.53,2.53,0,0,0,2.49-2.34A2.18,2.18,0,0,0,375.19,210.91Z"
style="fill: currentColor"
></path>
<polygon points="380.46 126.12 376.8 131.84 383.4 131.84 380.46 126.12" style="fill: #fff"></polygon>
<path
d="M383.37,132.25h-6.59a.39.39,0,0,1-.35-.21.43.43,0,0,1,0-.41l3.65-5.71a.43.43,0,0,1,.72,0l2.94,5.71a.4.4,0,0,1,0,.41A.47.47,0,0,1,383.37,132.25Zm-5.82-.83h5.16L380.4,127Z"
style="fill: currentColor"
></path>
</g>
<g id="freepik--Character--inject-83">
<path
d="M111.54,155.81l-1,4.87-1,5c-.66,3.32-1.22,6.64-1.73,9.9-.26,1.63-.46,3.24-.63,4.83s-.32,3.13-.4,4.62a40,40,0,0,0,0,4.08c0,1.17.26,2.17.21,2.28l-.67-1.15c-.3-.3-.85-.58-.94-.45s.26.36.9.53a13.51,13.51,0,0,0,2.51.35,29.74,29.74,0,0,0,3.22-.08,65.84,65.84,0,0,0,7.23-1c1.25-.24,2.52-.49,3.78-.77l3.74-.81.5-.11a5.25,5.25,0,0,1,4.24,9.34l-1.87,1.38-1.84,1.26c-1.26.8-2.53,1.58-3.85,2.3a55.3,55.3,0,0,1-8.46,3.78,41.08,41.08,0,0,1-4.87,1.31,26.44,26.44,0,0,1-5.69.54,20.16,20.16,0,0,1-7-1.34,16.42,16.42,0,0,1-7.2-5.61,7.56,7.56,0,0,1-.52-.86l-.15-.29a28,28,0,0,1-2.55-8,47.2,47.2,0,0,1-.64-6.62q-.11-3.13,0-6.1t.41-5.85c.34-3.84.91-7.58,1.56-11.29.34-1.85.68-3.69,1.1-5.52.2-.92.4-1.84.63-2.76l.74-2.83a10.47,10.47,0,0,1,20.39,4.73Z"
style="fill: currentColor"
></path>
<path
d="M111.54,155.81l-1,4.87-1,5c-.66,3.32-1.22,6.64-1.73,9.9-.26,1.63-.46,3.24-.63,4.83s-.32,3.13-.4,4.62a40,40,0,0,0,0,4.08c0,1.17.26,2.17.21,2.28l-.67-1.15c-.3-.3-.85-.58-.94-.45s.26.36.9.53a13.51,13.51,0,0,0,2.51.35,29.74,29.74,0,0,0,3.22-.08,65.84,65.84,0,0,0,7.23-1c1.25-.24,2.52-.49,3.78-.77l3.74-.81.5-.11a5.25,5.25,0,0,1,4.24,9.34l-1.87,1.38-1.84,1.26c-1.26.8-2.53,1.58-3.85,2.3a55.3,55.3,0,0,1-8.46,3.78,41.08,41.08,0,0,1-4.87,1.31,26.44,26.44,0,0,1-5.69.54,20.16,20.16,0,0,1-7-1.34,16.42,16.42,0,0,1-7.2-5.61,7.56,7.56,0,0,1-.52-.86l-.15-.29a28,28,0,0,1-2.55-8,47.2,47.2,0,0,1-.64-6.62q-.11-3.13,0-6.1t.41-5.85c.34-3.84.91-7.58,1.56-11.29.34-1.85.68-3.69,1.1-5.52.2-.92.4-1.84.63-2.76l.74-2.83a10.47,10.47,0,0,1,20.39,4.73Z"
style="opacity: 0.2"
></path>
<path
d="M86.23,411.58S76.77,403,77,400.28l-7.86-4-4.68,8.08,4.34,2.43L70,406.4l.79,1.37c3.92,2,12.48,5.91,15.47,5.8A1.92,1.92,0,0,0,86.23,411.58Z"
style="fill: #263238"
></path>
<path
d="M86.91,310.62c5.72-41,3.85-65.87,9.86-86.06l37.2-3s-16.49,65-24,92.06-31.23,88.42-31.23,88.42l-10.35-5.3S76.84,342.32,86.91,310.62Z"
style="fill: #263238"
></path>
<path
d="M117.25,251.87c-2.53,5.85-7.47,43.42-7.45,62.18,0-.13.08-.28.12-.42,2.65-9.51,6.42-23.72,10.18-38.13Z"
style="opacity: 0.2"
></path>
<path
d="M146,412.92s-15.43-3.5-16.14-6h-9.79l-.81,9.33h5.44l1-.86,1.22.86c4.4,0,17.12,0,19.86-1.6C146.8,413.23,146,412.92,146,412.92Z"
style="fill: #263238"
></path>
<path
d="M119.87,311.77c-8.17-55.51-8.17-89.88-8.17-89.88l36.4-.59s-4.37,66.2-5.89,93.93c-1.57,28.83-10.57,92.29-10.57,92.29H119S116,347.42,119.87,311.77Z"
style="fill: #263238"
></path>
<path
d="M115.92,117.67c-1.73,10.89-4.87,16.73-7,22.14,3.67,3.42,11.53,7.65,19.46,7.54s6.49-5.48,4.36-8.25c-5.69-2.87-5.91-5.77-4.52-8.31Z"
style="fill: #7f3e3b"
></path>
<path d="M102.32,141.35s5.06-5.95,7.06-6.95,17.13,1,20.7,1.72,7.92,6,7.92,6Z" style="fill: #263238"></path>
<path
d="M141,116.76c-.16.72.09,1.38.56,1.48s1-.4,1.14-1.12-.09-1.38-.56-1.48S141.14,116,141,116.76Z"
style="fill: #263238"
></path>
<path d="M140.71,117.75a26.08,26.08,0,0,0,2.06,6.87c-1.54.91-3.58-.1-3.58-.1Z" style="fill: #630f0f"></path>
<path
d="M143.46,112.63a.41.41,0,0,1-.4,0,3.39,3.39,0,0,0-3.11.1.42.42,0,0,1-.59-.12.43.43,0,0,1,.12-.6,4.23,4.23,0,0,1,3.92-.18.43.43,0,0,1,.22.57A.38.38,0,0,1,143.46,112.63Z"
style="fill: #263238"
></path>
<path
d="M117.18,109.46c-1.43,8.92-2.73,14.07.72,19.55,5.18,8.24,17,6.56,21.07-1.78,3.68-7.5,5.41-20.83-2.45-26.19A12.46,12.46,0,0,0,117.18,109.46Z"
style="fill: #7f3e3b"
></path>
<path
d="M133.39,118c7.22,1.56,5.12-7.36,3.39-8.25,4.34,2.6,7.22-.42,7-3.14,3.32-.55,3.15-6,.87-6.17-1.44-3.77-8.17-6.94-9.42-4.61-3.63-4.22-13.35-3.5-11.94-.44-3.69-.72-11.55-.39-8.92,5.17-5.61.72-5.34,10.32-1.68,11.32-3.83,2.12-.12,9.36,1.53,13.9S132.31,126.28,133.39,118Z"
style="fill: #263238"
></path>
<path
d="M129.28,117.09a7.61,7.61,0,0,0,1.18,5.45c1.41,2,3.59.75,4.44-1.66.76-2.16.94-5.8-1.07-6.89S129.65,114.65,129.28,117.09Z"
style="fill: #7f3e3b"
></path>
<path
d="M102.83,140.35c12.3-1.51,29.75-1.38,41.33.64A13.17,13.17,0,0,1,155,152.91c1.44,17.67-2.47,48.55-5.85,79.64-27.25,9.14-54.91-.13-54.91-.13-.61-6.27,2.77-26.82,4.88-37.79-1.55-11.32-5.48-24.29-7.69-39.34A13.15,13.15,0,0,1,102.83,140.35Z"
style="fill: currentColor"
></path>
<path
d="M139.84,165.09c1.86,10.64,7.75,23.32,13.14,31.71.74-7.35,1.36-14.35,1.75-20.81Z"
style="opacity: 0.2"
></path>
<path
d="M229.93,140.44a17.77,17.77,0,0,0-19.06,30c-1.78,2.4-7,9.45-8.59,12.17-2,3.29-3,6.25-1.62,7.07s3.48-1.51,5.43-4.8c1.62-2.71,5.34-10.65,6.59-13.37a17.77,17.77,0,0,0,17.25-31.06Zm4.27,23.23a15.54,15.54,0,1,1-5.41-21.31A15.53,15.53,0,0,1,234.2,163.67Z"
style="fill: currentColor"
></path>
<path
d="M234.93,164.1a16.39,16.39,0,1,1-5.71-22.46A16.38,16.38,0,0,1,234.93,164.1Z"
style="fill: currentColor; opacity: 0.2"
></path>
<path
d="M209.43,179.66l-2.17-1.92a3.36,3.36,0,0,0-3-.76l-5,1.14a6.28,6.28,0,0,0-4.4,3.72l-.48,1.16c3.37,3.43,9.54,4.66,9.54,4.66l1.73.54a2.79,2.79,0,0,0,3.57-1.76l1.13-3.39A3.27,3.27,0,0,0,209.43,179.66Z"
style="fill: #7f3e3b"
></path>
<path
d="M154.47,149.29l2,4.39,2.11,4.48c1.41,3,2.9,5.89,4.39,8.72q1.13,2.12,2.32,4.11c.77,1.33,1.56,2.61,2.36,3.79A38.85,38.85,0,0,0,170,177.9c.7.86,1.42,1.48,1.44,1.58l-1.24-.51a12,12,0,0,0,4.36,1.1,43.06,43.06,0,0,0,6.37.08c2.28-.1,4.63-.34,7-.62,1.19-.15,2.4-.29,3.61-.47l3.58-.48.49-.07a5.26,5.26,0,0,1,3.6,9.6l-1.82,1.2-1.79,1.08c-1.21.69-2.43,1.36-3.69,2s-2.53,1.21-3.84,1.75-2.66,1-4,1.49a46,46,0,0,1-8.9,2,28.27,28.27,0,0,1-10.86-.66,4.81,4.81,0,0,1-.75-.28l-.48-.23a26.69,26.69,0,0,1-6.86-4.74,46.93,46.93,0,0,1-4.48-4.82,83.07,83.07,0,0,1-6.74-9.64c-2-3.23-3.74-6.51-5.39-9.8-.81-1.66-1.62-3.31-2.36-5-.37-.84-.75-1.69-1.1-2.54l-1.08-2.67a10.47,10.47,0,0,1,19.22-8.3Z"
style="fill: currentColor"
></path>
</g>
<g id="freepik--Plant--inject-83">
<path
d="M362.85,378.84c-1.54-12.09,5.2-21.84,11.72-31.28,7.67-11.1,15.6-22.57,10.91-38.32a33,33,0,0,0-6.31-11.77,40.88,40.88,0,0,1-13.75,18c-8.7,6.48-19,8.52-26.17,5.21-4.05-1.86-9-6.25-9.75-16.53-.74-10.52,5.37-18,16.33-20s24.27,2,33,11.41a43.49,43.49,0,0,0,1.84-20.25l1-.14a44.23,44.23,0,0,1-2.07,21.24A33.94,33.94,0,0,1,386.44,309c4.83,16.2-3.24,27.88-11.05,39.17-6.71,9.71-13,18.88-11.55,30.58Zm-11.33-94.2a31.2,31.2,0,0,0-5.51.48c-10.41,1.89-16.21,9-15.52,18.93.54,7.75,3.71,13.18,9.18,15.69,6.87,3.16,16.75,1.16,25.16-5.1a39.92,39.92,0,0,0,13.6-18A36.79,36.79,0,0,0,351.52,284.64Z"
style="fill: #263238"
></path>
<path
d="M381.57,278.67c-7.92-7.07-8.83-16.4-4.19-18.37C383.81,257.57,386.21,268.93,381.57,278.67Z"
style="fill: currentColor"
></path>
<path
d="M375.56,347c-5.66-9-6-20.22.91-21C382.76,325.26,384.14,335.92,375.56,347Z"
style="fill: currentColor"
></path>
<path
d="M381.75,281.64c-1.09-6.71,2.21-11.71,5.31-10.82C391.35,272.05,388,278.66,381.75,281.64Z"
style="fill: currentColor"
></path>
<path
d="M366.18,314.07c-3.47-7.48-1.25-14.41,2.67-14.39C374.27,299.72,372.48,308.55,366.18,314.07Z"
style="fill: currentColor"
></path>
<path
d="M352.86,284.24c-7.14,1.21-12.5-2.28-11.57-5.59C342.58,274.06,349.65,277.62,352.86,284.24Z"
style="fill: currentColor"
></path>
<path
d="M352.86,284.24c-4.38-2.34-5-5.82-2.76-6.75C353.25,276.2,354.75,280.39,352.86,284.24Z"
style="fill: currentColor"
></path>
<path
d="M387.28,314c-1.73-4.67.1-7.7,2.41-6.89C392.9,308.24,391.25,312.36,387.28,314Z"
style="fill: currentColor"
></path>
<path
d="M331.11,310.73c-4.95.54-7.44-2-6.09-4C326.9,303.87,330.5,306.48,331.11,310.73Z"
style="fill: currentColor"
></path>
<rect
x="385.12"
y="386.95"
width="17.52"
height="1"
transform="translate(-43.09 725.57) rotate(-82.26)"
style="fill: currentColor"
></rect>
<rect
x="387.27"
y="404.29"
width="8.47"
height="1"
transform="translate(-62.35 738.17) rotate(-82.26)"
style="fill: currentColor"
></rect>
<path
d="M344,371.23l5.79,42.34a3.09,3.09,0,0,0,3.06,2.67h31.26a3.09,3.09,0,0,0,3.06-2.67l5.79-42.34a3.09,3.09,0,0,0-3.06-3.5H347A3.09,3.09,0,0,0,344,371.23Z"
style="fill: currentColor"
></path>
</g>
</svg>
</template>
<script lang="ts" setup></script>
<style scoped></style>

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +0,0 @@
import Banner1 from './Banner1.vue';
import Banner2 from './Banner2.vue';
import Banner3 from './Banner3.vue';
export { Banner1, Banner2, Banner3 };

View File

@@ -1,24 +0,0 @@
<template>
<div :style="{ color }">
<banner1 v-if="type === '1'" />
<banner2 v-if="type === '2'" />
<banner3 v-if="type === '3'" />
</div>
</template>
<script lang="ts" setup>
import { Banner1, Banner2, Banner3 } from './components';
interface Props {
/** banner类型 */
type?: '1' | '2' | '3';
/** 主题颜色 */
color?: string;
}
withDefaults(defineProps<Props>(), {
type: '1',
color: '#409eff'
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,18 @@
<template>
<div
class="dark:(bg-[#18181c] text-white text-opacity-82) transition-all duration-300 ease-in-out"
:class="inverted ? 'bg-[#001428] text-white' : 'bg-white text-[#333639]'"
>
<slot></slot>
</div>
</template>
<script setup lang="ts">
interface Props {
inverted?: boolean;
}
withDefaults(defineProps<Props>(), {
inverted: false
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,39 @@
<template>
<div class="flex-center text-18px hover:text-primary cursor-pointer" @click="handleSwitch">
<icon-mdi-moon-waning-crescent v-if="darkMode" />
<icon-mdi-white-balance-sunny v-else />
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
interface Props {
/** 暗黑模式 */
dark?: boolean;
}
interface Emits {
(e: 'update:dark', darkMode: boolean): void;
}
const props = withDefaults(defineProps<Props>(), {
dark: false
});
const emit = defineEmits<Emits>();
const darkMode = computed({
get() {
return props.dark;
},
set(newValue: boolean) {
emit('update:dark', newValue);
}
});
function handleSwitch() {
darkMode.value = !darkMode.value;
}
</script>
<style scoped></style>

View File

@@ -16,7 +16,6 @@
<script lang="ts" setup>
import { computed } from 'vue';
import { NTooltip } from 'naive-ui';
import type { FollowerPlacement } from 'vueuc';
interface Props {

View File

@@ -1,31 +0,0 @@
<template>
<div class="absolute-lt wh-full overflow-hidden">
<div class="absolute -right-300px -top-900px">
<corner-top :start-color="themeColor" :end-color="stopColor" />
</div>
<div class="absolute -left-200px -bottom-400px">
<corner-bottom :start-color="themeColor" :end-color="stopColor" />
</div>
</div>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { mixColor } from '@/utils';
import { CornerTop, CornerBottom } from './components';
interface Props {
/** 主题颜色 */
themeColor?: string;
}
const props = withDefaults(defineProps<Props>(), {
themeColor: '#409EFF'
});
const COLOR_WHITE = '#ffffff';
const stopColor = computed(() => {
return mixColor(COLOR_WHITE, props.themeColor, 0.7);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,35 @@
<template>
<n-loading-bar-provider>
<n-dialog-provider>
<n-notification-provider>
<n-message-provider>
<slot></slot>
<naive-provider-content />
</n-message-provider>
</n-notification-provider>
</n-dialog-provider>
</n-loading-bar-provider>
</template>
<script setup lang="ts">
import { defineComponent, h } from 'vue';
import { useLoadingBar, useDialog, useMessage, useNotification } from 'naive-ui';
// 挂载naive组件的方法至window, 以便在路由钩子函数和请求函数里面调用
function registerNaiveTools() {
window.$loadingBar = useLoadingBar();
window.$dialog = useDialog();
window.$message = useMessage();
window.$notification = useNotification();
}
const NaiveProviderContent = defineComponent({
setup() {
registerNaiveTools();
},
render() {
return h('div');
}
});
</script>
<style scoped></style>

View File

@@ -1,18 +0,0 @@
<template>
<div></div>
</template>
<script lang="ts" setup>
import { useLoadingBar, useDialog, useMessage, useNotification } from 'naive-ui';
// 挂载naive组件的方法至window, 以便在路由钩子函数和请求函数里面调用
function registerNaiveTools() {
window.$loadingBar = useLoadingBar();
window.$dialog = useDialog();
window.$message = useMessage();
window.$notification = useNotification();
}
registerNaiveTools();
</script>
<style scoped></style>

View File

@@ -1,3 +0,0 @@
import NaiveProviderContent from './NaiveProviderContent.vue';
export { NaiveProviderContent };

View File

@@ -1,18 +0,0 @@
<template>
<n-loading-bar-provider>
<n-dialog-provider>
<n-notification-provider>
<n-message-provider>
<slot></slot>
<naive-provider-content />
</n-message-provider>
</n-notification-provider>
</n-dialog-provider>
</n-loading-bar-provider>
</template>
<script setup lang="ts">
import { NLoadingBarProvider, NDialogProvider, NNotificationProvider, NMessageProvider } from 'naive-ui';
import { NaiveProviderContent } from './components';
</script>
<style scoped></style>

View File

@@ -0,0 +1,16 @@
<template>
<icon-custom-logo-fill v-if="fill" />
<icon-custom-logo v-else />
</template>
<script lang="ts" setup>
interface Props {
/** logo是否填充 */
fill?: boolean;
}
withDefaults(defineProps<Props>(), {
fill: false
});
</script>
<style scoped></style>

View File

@@ -1,31 +0,0 @@
<template>
<svg viewBox="0 0 158.88 158.88">
<path
d="M158.86.3q0,78.74,0,157.48c0,.9-.2,1.1-1.1,1.1q-78.77,0-157.52,0a2.61,2.61,0,0,1-.11-1.3q0-78,0-155.91C.14,0,0,.18,1.61.18h156A2.62,2.62,0,0,1,158.86.3Z"
style="fill: currentColor"
/>
<path
d="M158.86.3H2C0,.31.27,0,.27,2q0,78.42,0,156.85c-.07-.05-.25.12-.24-.12s0-.64,0-1Q0,79.46,0,1.14C0,.24.2,0,1.1,0l156.68,0C158.13.08,158.59-.2,158.86.3Z"
style="fill: #ffffff"
/>
<path
d="M93.65,51.52a68.65,68.65,0,0,1-6.47,28.81,1.72,1.72,0,0,0,.19,2c6.08,8.28,13.58,14.79,23.19,18.69a46.22,46.22,0,0,0,17.15,3.39,28.87,28.87,0,0,0,3.34-.25,6.2,6.2,0,0,1,7,5.12,6.07,6.07,0,0,1-5.15,7.14,50.39,50.39,0,0,1-18.06-1c-15.85-3.66-28-12.75-37.44-25.7a2.15,2.15,0,0,0-2.23-1.09C61.17,90,49,95.06,39.67,105.84a38.47,38.47,0,0,0-6.23,9.74A6.21,6.21,0,0,1,25.27,119,6.14,6.14,0,0,1,22,110.8a49.31,49.31,0,0,1,9.63-14.62c10.56-11.44,23.8-17.54,39.09-19.54a13.93,13.93,0,0,1,2.84-.34c1.61.14,2.18-.73,2.73-2A54.38,54.38,0,0,0,81.12,51a44,44,0,0,0-8-25,6.11,6.11,0,0,1-.65-6.46A6,6,0,0,1,77.75,16a6.34,6.34,0,0,1,5.66,3,53.61,53.61,0,0,1,7.17,14.28A59.33,59.33,0,0,1,93.65,51.52Z"
style="fill: #ffffff"
/>
<path
d="M46.92,118.63a6,6,0,0,1,1.35-3.88,37.89,37.89,0,0,1,22.5-14,6.08,6.08,0,0,1,6.65,2.47,6.18,6.18,0,0,1-3.84,9.63,26.09,26.09,0,0,0-15.71,9.77,6.2,6.2,0,0,1-10.95-4Z"
style="fill: #ffffff"
/>
<path
d="M124.3,92.8a34.66,34.66,0,0,1-9.82-2.48A35.46,35.46,0,0,1,99.83,79.87a6.19,6.19,0,0,1,2.84-9.93,5.79,5.79,0,0,1,6.44,1.73,26.79,26.79,0,0,0,16.51,8.85,6,6,0,0,1,5,5.54,6.21,6.21,0,0,1-4.29,6.46A6.55,6.55,0,0,1,124.3,92.8Z"
style="fill: #ffffff"
/>
<path
d="M69.32,53.27a33.46,33.46,0,0,1-2.27,12.52,6.21,6.21,0,0,1-10.94,1,6.09,6.09,0,0,1-.65-5.4,26,26,0,0,0-.53-18.25,6.21,6.21,0,0,1,11.49-4.72A40.24,40.24,0,0,1,69.32,53.27Z"
style="fill: #ffffff"
/>
</svg>
</template>
<script setup lang="ts"></script>
<style scoped></style>

View File

@@ -1,32 +0,0 @@
<template>
<svg viewBox="0 0 158.88 158.88">
<path
d="M0,158.86Q0,80,0,1.1C0,.2.2,0,1.1,0Q79.44,0,157.78,0c.9,0,1.1.2,1.1,1.1q0,78.35,0,156.68c0,.9-.2,1.1-1.1,1.1Q78.9,158.83,0,158.86Z"
transform="translate(0)"
style="fill: #ffffff00"
/>
<path
d="M81.28,55.9c-.1-11.67-2.93-22.55-9.37-32.38-1-1.5-2.14-2.86-2.5-4.71a8.1,8.1,0,0,1,4-8.61,7.89,7.89,0,0,1,9.3,1.23,36,36,0,0,1,5.9,8.83,75.18,75.18,0,0,1,8.44,28.58,83.21,83.21,0,0,1-5.23,36.74c-.91,2.47-1.91,4.9-3,7.28a1.2,1.2,0,0,0,0,1.41c9.58,13.3,21.76,23,37.85,27.24a54.35,54.35,0,0,0,19.68,1.57,7.72,7.72,0,0,1,8.36,6.9,7.9,7.9,0,0,1-6.7,9,64.74,64.74,0,0,1-23-1.33,77.68,77.68,0,0,1-36.93-19.88,93.64,93.64,0,0,1-11.91-13.71A2.18,2.18,0,0,0,73.87,103a72.75,72.75,0,0,0-27.38,7.55c-11.6,6-20.67,14.58-26.4,26.45a10.13,10.13,0,0,1-3.7,4.7A8,8,0,0,1,7.2,141a7.86,7.86,0,0,1-2.36-9.28,60.32,60.32,0,0,1,8.72-14.52c12.2-15.43,28.21-24.59,47.32-28.57A85.08,85.08,0,0,1,73.07,87a1.22,1.22,0,0,0,1.18-.8A76.06,76.06,0,0,0,80.78,63.9,57.87,57.87,0,0,0,81.28,55.9Z"
transform="translate(0)"
style="fill: currentColor"
/>
<path
d="M136.26,108.34a44.72,44.72,0,0,1-11.13-2.87,46.11,46.11,0,0,1-19.66-13.76,8,8,0,0,1,5.72-13.22,7.93,7.93,0,0,1,6.54,2.93A33.27,33.27,0,0,0,136.6,92.17a14.76,14.76,0,0,1,4.48,1.18,8.08,8.08,0,0,1,3.84,9.21C144,106.08,140.79,108.37,136.26,108.34Z"
transform="translate(0)"
style="fill: currentColor"
/>
<path
d="M55.66,33.32a7.61,7.61,0,0,1,6.64,5,49.14,49.14,0,0,1,3.64,17,46.33,46.33,0,0,1-2.46,17.28c-2,5.77-8.24,7.79-12.89,4.15a8.1,8.1,0,0,1-2.39-9,31.68,31.68,0,0,0,1.68-12.36,35.77,35.77,0,0,0-2.43-11C45.35,38.94,49.2,33.32,55.66,33.32Z"
transform="translate(0)"
style="fill: currentColor"
/>
<path
d="M77.92,126.57a8,8,0,0,1-6.68,7.86,32.88,32.88,0,0,0-19.7,12.19,8.13,8.13,0,0,1-11.21,1.62,8,8,0,0,1-1.41-11.58A51.05,51.05,0,0,1,54,123.81a45.85,45.85,0,0,1,14-5.1C73.35,117.67,77.91,121.27,77.92,126.57Z"
transform="translate(0)"
style="fill: currentColor"
/>
</svg>
</template>
<script setup lang="ts"></script>
<style scoped></style>

View File

@@ -1,4 +0,0 @@
import SvgLogo from './SvgLogo.vue';
import SvgFillLogo from './SvgFillLogo.vue';
export { SvgLogo, SvgFillLogo };

View File

@@ -1,23 +0,0 @@
<template>
<div :style="{ color }">
<svg-fill-logo v-if="fill" />
<svg-logo v-else />
</div>
</template>
<script lang="ts" setup>
import { SvgLogo, SvgFillLogo } from './components';
interface Props {
/** logo是否填充 */
fill?: boolean;
/** logo的主题颜色 */
color?: string;
}
withDefaults(defineProps<Props>(), {
fill: false,
color: '#409EFF'
});
</script>
<style scoped></style>

View File

@@ -1,9 +0,0 @@
import NaiveProvider from './NaiveProvider/index.vue';
import SystemLogo from './SystemLogo/index.vue';
import LoginBg from './LoginBg/index.vue';
import BannerSvg from './BannerSvg/index.vue';
import HoverContainer from './HoverContainer/index.vue';
import LoadingEmptyWrapper from './LoadingEmptyWrapper/index.vue';
import IconSelect from './IconSelect/index.vue';
export { NaiveProvider, SystemLogo, LoginBg, BannerSvg, HoverContainer, LoadingEmptyWrapper, IconSelect };

View File

@@ -1,6 +1,6 @@
<template>
<div ref="scrollbar" class="h-full text-left">
<div ref="scrollbarContent" class="inline-block" :class="{ 'h-full': !isScrollY }">
<div ref="bsWrap" class="h-full text-left">
<div ref="bsContent" class="inline-block" :class="{ 'h-full': !isScrollY }">
<slot></slot>
</div>
</div>
@@ -8,9 +8,9 @@
<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue';
import { useElementSize } from '@vueuse/core';
import BScroll from '@better-scroll/core';
import type { Options } from '@better-scroll/core';
import { useElementSize } from '@vueuse/core';
interface Props {
/** better-scroll的配置: https://better-scroll.github.io/docs/zh-CN/guide/base-scroll-options.html */
@@ -19,20 +19,22 @@ interface Props {
const props = defineProps<Props>();
const scrollbar = ref<HTMLElement | null>(null);
const bsInstance = ref<BScroll | null>(null);
const scrollbarContent = ref<HTMLElement | null>(null);
const bsWrap = ref<HTMLElement>();
const instance = ref<BScroll>();
const bsContent = ref<HTMLElement>();
const isScrollY = computed(() => Boolean(props.options.scrollY));
function initBetterScroll() {
bsInstance.value = new BScroll(scrollbar.value!, props.options);
if (!bsWrap.value) return;
instance.value = new BScroll(bsWrap.value, props.options);
}
// BS
const { width, height } = useElementSize(scrollbarContent);
watch([() => width.value, () => height.value], () => {
if (bsInstance.value) {
bsInstance.value.refresh();
const { width: wrapWidth } = useElementSize(bsWrap);
const { width, height } = useElementSize(bsContent);
watch([() => wrapWidth.value, () => width.value, () => height.value], () => {
if (instance.value) {
instance.value.refresh();
}
});
@@ -40,6 +42,6 @@ onMounted(() => {
initBetterScroll();
});
defineExpose({ bsInstance });
defineExpose({ instance });
</script>
<style scoped></style>

View File

@@ -1,66 +0,0 @@
<template>
<div
class="relative flex-center h-30px pl-14px border-1px border-[#e5e7eb] dark:border-[#ffffff3d] rounded-2px transition-border-color duration-300 ease-in-out cursor-pointer"
:class="[closable ? 'pr-6px' : 'pr-14px']"
:style="buttonStyle"
@mouseenter="setTrue"
@mouseleave="setFalse"
>
<span class="whitespace-nowrap">
<slot></slot>
</span>
<div v-if="closable" class="pl-10px">
<icon-close :is-primary="isActive || isHover" :primary-color="primaryColor" @click="handleClose" />
</div>
</div>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { useBoolean } from '@/hooks';
import { IconClose } from '@/components';
import { addColorAlpha } from '@/utils';
interface Props {
/** 激活状态 */
isActive?: boolean;
/** 主题颜色 */
primaryColor?: string;
/** 是否显示关闭图标 */
closable?: boolean;
/** 暗黑模式 */
darkMode?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
isActive: false,
primaryColor: '#409EFF',
closable: true,
darkMode: false
});
const emit = defineEmits<{
/** 点击关闭图标 */
(e: 'close'): void;
}>();
const { bool: isHover, setTrue, setFalse } = useBoolean();
function handleClose(e: MouseEvent) {
e.stopPropagation();
emit('close');
}
const buttonStyle = computed(() => {
const style: { [key: string]: string } = {};
if (props.isActive || isHover.value) {
style.color = props.primaryColor;
style.borderColor = addColorAlpha(props.primaryColor, 0.3);
if (props.isActive) {
const alpha = props.darkMode ? 0.15 : 0.1;
style.backgroundColor = addColorAlpha(props.primaryColor, alpha);
}
}
return style;
});
</script>
<style scoped></style>

View File

@@ -1,79 +0,0 @@
<template>
<svg>
<defs>
<symbol id="geometry-left" viewBox="0 0 214 36">
<path d="M17 0h197v36H0v-2c4.5 0 9-3.5 9-8V8c0-4.5 3.5-8 8-8z"></path>
</symbol>
<symbol id="geometry-right" viewBox="0 0 214 36">
<use xlink:href="#geometry-left"></use>
</symbol>
<clipPath>
<rect width="100%" height="100%" x="0"></rect>
</clipPath>
</defs>
<svg width="52%" height="100%">
<use
xlink:href="#geometry-left"
width="214"
height="36"
:fill="fill"
class="transition-fill duration-300 ease-in-out"
></use>
</svg>
<g transform="scale(-1, 1)">
<svg width="52%" height="100%" x="-100%" y="0">
<use
xlink:href="#geometry-right"
width="214"
height="36"
:fill="fill"
class="transition-fill duration-300 ease-in-out"
></use>
</svg>
</g>
</svg>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { mixColor } from '@/utils';
interface Props {
/** 激活状态 */
isActive?: boolean;
/** 鼠标悬浮状态 */
isHover?: boolean;
/** 主题颜色 */
primaryColor?: string;
/** 暗黑模式 */
darkMode?: boolean;
}
/** 填充的背景颜色: [默认颜色, 暗黑主题颜色] */
type FillColor = [string, string];
const props = withDefaults(defineProps<Props>(), {
isActive: false,
isHover: false,
primaryColor: '#409EFF',
darkMode: false
});
const defaultColor: FillColor = ['#fff', '#18181c'];
const hoverColor: FillColor = ['#dee1e6', '#3f3c37'];
const mixColors: FillColor = ['#ffffff', '#000000'];
const fill = computed(() => {
const index = Number(props.darkMode);
let color = defaultColor[index];
if (props.isHover) {
color = hoverColor[index];
}
if (props.isActive) {
const alpha = props.darkMode ? 0.1 : 0.15;
color = mixColor(mixColors[index], props.primaryColor, alpha);
}
return color;
});
</script>
<style scoped></style>

View File

@@ -1,3 +0,0 @@
import SvgRadiusBg from './SvgRadiusBg.vue';
export { SvgRadiusBg };

View File

@@ -1,66 +0,0 @@
<template>
<div
class="relative flex-y-center h-34px px-24px cursor-pointer"
:class="{ '-mr-18px': !isLast, 'z-10': isActive, 'z-9': isHover }"
@mouseenter="setTrue"
@mouseleave="setFalse"
>
<div class="absolute-lb wh-full overflow-hidden">
<svg-radius-bg
class="wh-full"
:is-active="isActive"
:is-hover="isHover"
:dark-mode="darkMode"
:primary-color="primaryColor"
/>
</div>
<span class="relative whitespace-nowrap z-2">
<slot></slot>
</span>
<div v-if="closable" class="pl-18px">
<icon-close :is-primary="isActive" :primary-color="primaryColor" @click="handleClose" />
</div>
<n-divider v-if="!isHover && !isActive" :vertical="true" class="absolute right-0 !bg-[#a4abb8] z-2" />
</div>
</template>
<script setup lang="ts">
import { NDivider } from 'naive-ui';
import { useBoolean } from '@/hooks';
import IconClose from '../IconClose/index.vue';
import { SvgRadiusBg } from './components';
interface Props {
/** 激活状态 */
isActive?: boolean;
/** 主题颜色 */
primaryColor?: string;
/** 是否显示关闭图标 */
closable?: boolean;
/** 暗黑模式 */
darkMode?: boolean;
/** 是否是最后一个 */
isLast: boolean;
}
withDefaults(defineProps<Props>(), {
isActive: false,
primaryColor: '#409EFF',
closable: true,
darkMode: false,
isLast: false
});
const emit = defineEmits<{
/** 点击关闭图标 */
(e: 'close'): void;
}>();
const { bool: isHover, setTrue, setFalse } = useBoolean();
function handleClose(e: MouseEvent) {
e.stopPropagation();
emit('close');
}
</script>
<style scoped></style>

View File

@@ -95,9 +95,11 @@ watch([() => props.startValue, () => props.endValue], () => {
start();
}
});
watchEffect(() => {
source.value = props.startValue;
});
onMounted(() => {
if (props.autoplay) {
start();

View File

@@ -3,7 +3,7 @@
</template>
<script setup lang="ts">
import WebSiteLink from '../WebSiteLink/index.vue';
import WebSiteLink from './WebSiteLink.vue';
interface Props {
/** github链接 */

View File

@@ -1,35 +0,0 @@
<template>
<div
class="relative flex-center w-18px h-18px text-14px"
:style="{ color: isPrimary ? primaryColor : defaultColor }"
@mouseenter="setTrue"
@mouseleave="setFalse"
>
<transition name="transition-opacity">
<icon-mdi:close-circle v-if="isHover" key="hover" class="absolute" />
<icon-mdi:close v-else key="unhover" class="absolute" />
</transition>
</div>
</template>
<script lang="ts" setup>
import { useBoolean } from '@/hooks';
interface Props {
/** 激活状态 */
isPrimary?: boolean;
/** 主题颜色 */
primaryColor?: string;
/** 默认颜色 */
defaultColor?: string;
}
withDefaults(defineProps<Props>(), {
isPrimary: false,
primaryColor: '#409EFF',
defaultColor: '#9ca3af'
});
const { bool: isHover, setTrue, setFalse } = useBoolean();
</script>
<style scoped></style>

View File

@@ -26,7 +26,6 @@
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { NPopover, NInput, NEmpty } from 'naive-ui';
import { Icon } from '@iconify/vue';
import { useThemeStore } from '@/store';
@@ -50,8 +49,10 @@ const props = withDefaults(defineProps<Props>(), {
const emit = defineEmits<Emits>();
const theme = useThemeStore();
const searchValue = ref('');
const iconsList = computed(() => props.icons.filter(v => v.includes(searchValue.value)));
const modelValue = computed({
get() {
return props.value;

View File

@@ -9,14 +9,16 @@ import { watch } from 'vue';
import { useImageVerify } from '@/hooks';
interface Props {
code: string;
code?: string;
}
interface Emits {
(e: 'update:code', code: string): void;
}
const props = defineProps<Props>();
const props = withDefaults(defineProps<Props>(), {
code: ''
});
const emit = defineEmits<Emits>();

View File

@@ -1,290 +0,0 @@
<template>
<div ref="mousewheelRef" class="h-full cursor-move">
<svg ref="svgRef" class="w-full h-full select-none" @mousedown="dragStart">
<g :style="{ transform }">
<slot></slot>
</g>
</svg>
<slot name="absolute"></slot>
</div>
</template>
<script setup lang="ts">
import { reactive, ref, computed, watch, onMounted, onBeforeUnmount } from 'vue';
import type { SScaleRange, STranslate, SPosition, SCoord, SNodeSize } from '@/interface';
interface Props {
/** 缩放比例 */
scale?: number;
/** 缩放范围 */
scaleRange?: SScaleRange;
/** g标签相对于svg标签的左上角的偏移量 */
translate?: STranslate;
/** 节点尺寸 */
nodeSize?: SNodeSize;
/** 是否开启按坐标居中画布 */
centerSvg?: boolean;
/** 居中的坐标 */
centerCoord?: SCoord;
}
interface Emits {
(e: 'update:scale', scale: number): void;
(e: 'update:translate', translate: STranslate): void;
}
interface SvgConfig {
/** 距离可视区左边的距离 */
left: number;
/** 距离可视区顶部的距离 */
top: number;
/** svg画布宽 */
width: number;
/** svg画布高 */
height: number;
}
interface DragScale {
/** 画布缩放比例 */
scale: number;
/** 画布缩放比例取值范围 */
scaleRange: SScaleRange;
/** 画布移动距离 */
translate: STranslate;
/** 是否在拖动 */
isDragging: boolean;
/** 拖动前的鼠标距离可视区左边和上边的距离 */
lastPosition: SPosition;
/** svg的属性 */
svgConfig: SvgConfig;
}
interface WheelDelta {
wheelDelta: number;
wheelDeltaX: number;
wheelDeltaY: number;
}
type DOMWheelEvent = WheelEvent & WheelDelta;
type WheelDirection = 'up' | 'down';
const props = withDefaults(defineProps<Props>(), {
scale: 1,
scaleRange: () => [0.2, 3],
translate: () => ({ x: 0, y: 0 }),
nodeSize: () => ({ w: 100, h: 100 }),
centerSvg: false,
centerCoord: () => ({ x: 0, y: 0 })
});
const emit = defineEmits<Emits>();
/** 最外层容器,用于鼠标滚轮事件 */
const mousewheelRef = ref<HTMLElement>();
/** 基本属性 */
const dragScale = reactive<DragScale>({
scale: props.scale,
scaleRange: [...props.scaleRange],
translate: { ...props.translate },
isDragging: false,
lastPosition: {
x: 0,
y: 0
},
svgConfig: {
left: 0,
top: 0,
width: 1000,
height: 500
}
});
function setDragScale(data: Partial<DragScale>) {
Object.assign(dragScale, data);
}
/** svg dom */
const svgRef = ref<SVGElement | null>(null);
function initSvgConfig() {
if (svgRef.value) {
const { left, top, width, height } = svgRef.value.getBoundingClientRect();
setDragScale({ svgConfig: { left, top, width, height } });
}
}
/** 缩放和平移样式 */
const transform = computed(() => {
const { scale, translate } = dragScale;
const { x, y } = translate;
return `translate(${x}px, ${y}px) scale(${scale})`;
});
/**
* 更新偏移量
* @param delta - 偏移量的增量
*/
function updateTranslate(delta: STranslate) {
const { x, y } = dragScale.translate;
const update = { x: x + delta.x, y: y + delta.y };
setDragScale({ translate: update });
}
/**
* 缩放后将视图移动到鼠标的位置
* @param mouseX - 鼠标x坐标
* @param mouseY - 鼠标y坐标
* @param oldScale - 缩放前的缩放比例
*/
function correctTranslate(mouseX: number, mouseY: number, oldScale: number) {
const { scale, translate } = dragScale;
const { x, y } = translate;
const sourceCoord = {
x: (mouseX - x) / oldScale,
y: (mouseY - y) / oldScale
};
const sourceTranslate = {
x: sourceCoord.x * (1 - scale),
y: sourceCoord.y * (1 - scale)
};
const update = {
x: sourceTranslate.x - (sourceCoord.x - mouseX),
y: sourceTranslate.y - (sourceCoord.y - mouseY)
};
setDragScale({ translate: update });
}
// 拖拽事件
/** 拖拽开始 */
function dragStart(e: MouseEvent) {
if (e.button !== 0) {
// 只允许鼠标点击左键拖动
return;
}
const { clientX: x, clientY: y } = e;
setDragScale({ isDragging: true, lastPosition: { x, y } });
}
/** 拖拽中 */
function dragMove(e: MouseEvent) {
if (dragScale.isDragging) {
const { clientX: x, clientY: y } = e; // 当前鼠标的位置
const { x: lX, y: lY } = dragScale.lastPosition; // 上一次鼠标的位置
const delta = { x: x - lX, y: y - lY }; // 鼠标的偏移量
updateTranslate(delta);
setDragScale({ lastPosition: { x, y } });
}
}
/** 拖拽结束 */
function dragEnd() {
setDragScale({ isDragging: false });
}
/** 缩放事件 */
function handleScale(e: WheelEvent, direction: WheelDirection) {
const { clientX, clientY } = e;
const { left, top } = dragScale.svgConfig;
const mouseX = clientX - left;
const mouseY = clientY - top;
const { scale: oldScale, scaleRange } = dragScale;
const [min, max] = scaleRange;
const scaleParam = 0.045;
const updateParam = direction === 'up' ? 1 + scaleParam : 1 - scaleParam;
const newScale = oldScale * updateParam;
if (newScale >= min && newScale <= max) {
dragScale.scale = newScale;
} else {
dragScale.scale = newScale < min ? min : max;
}
correctTranslate(mouseX, mouseY, oldScale);
}
/** 鼠标滚轮缩放事件 */
function handleMousewheel(e: WheelEvent) {
e.preventDefault();
const direction: WheelDirection = (e as DOMWheelEvent).wheelDeltaY > 0 ? 'up' : 'down';
handleScale(e, direction);
}
/** 监听拖拽事件 */
function initDragEventListener() {
window.addEventListener('mousemove', dragMove);
window.addEventListener('mouseup', dragEnd);
}
/** 监听鼠标滚轮事件 */
function initMousewheelEventListener() {
if (mousewheelRef.value) {
mousewheelRef.value.addEventListener('wheel', handleMousewheel);
}
}
/** 卸载监听事件 */
function destroyEventListener() {
window.removeEventListener('mousemove', dragMove);
window.removeEventListener('mouseup', dragEnd);
if (mousewheelRef.value) {
mousewheelRef.value.removeEventListener('wheel', handleMousewheel);
}
}
// 根据指定坐标居中布局
function handleCenterSvg() {
const { x, y } = props.centerCoord;
const isCoordValid = !Number.isNaN(x) && !Number.isNaN(y);
if (props.centerSvg && isCoordValid) {
const { w, h } = props.nodeSize;
const { width, height } = dragScale.svgConfig;
const translate = { x: width / 2 - x - w / 2, y: height / 2 - y - h / 2 };
setDragScale({ translate });
} else {
setDragScale({ translate: { x: 0, y: 0 } });
}
}
// 将scale和translate进行双向数据绑定
watch(
() => props.scale,
newValue => {
setDragScale({ scale: newValue });
}
);
watch(
() => props.translate,
newValue => {
setDragScale({ translate: newValue });
}
);
watch(
() => dragScale.scale,
newValue => {
emit('update:scale', newValue);
}
);
watch(
() => dragScale.translate,
newValue => {
emit('update:translate', newValue);
}
);
// 监听centerCoord居中画布
watch([() => props.centerSvg, () => props.centerCoord], () => {
handleCenterSvg();
});
/** 初始化 */
function init() {
initDragEventListener();
initMousewheelEventListener();
initSvgConfig();
handleCenterSvg();
}
onMounted(() => {
init();
});
// 卸载监听事件
onBeforeUnmount(() => {
destroyEventListener();
});
</script>
<style scoped></style>

View File

@@ -1,124 +0,0 @@
<template>
<div class="flex-col-center select-none">
<icon-mdi-plus-circle
class="text-20px cursor-pointer"
:style="{ color: themeColor }"
@click="handleSliderValue('plus')"
/>
<div class="h-120px pr-4px">
<n-slider
v-model:value="sliderValue"
:vertical="true"
:tooltip="false"
:style="`--rail-color: #efefef;--fill-color:${themeColor};--fill-color-hover:${themeColor}`"
/>
</div>
<div class="absolute -right-40px h-20px" :style="{ bottom: sliderLabelBottom }">
{{ sliderLabel }}
</div>
<icon-mdi-minus-circle
class="text-20px cursor-pointer"
:style="{ color: themeColor }"
@click="handleSliderValue('minus')"
/>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue';
import { NSlider } from 'naive-ui';
import type { SScaleRange, STranslate } from '@/interface';
interface Props {
/** 主题颜色 */
themeColor: string;
/** 缩放比例 */
scale?: number;
/** 缩放范围 */
scaleRange?: SScaleRange;
}
interface Emits {
(e: 'update:scale', scale: number): void;
(e: 'update:translate', translate: STranslate): void;
}
const props = withDefaults(defineProps<Props>(), {
scale: 1,
scaleRange: () => [0.2, 3]
});
const emit = defineEmits<Emits>();
const sliderValue = ref(getSliderValue());
const sliderLabel = computed(() => formatSlider(sliderValue.value));
const sliderLabelBottom = computed(() => getSliderLabelBottom(sliderValue.value));
function getSliderValue() {
const {
scale,
scaleRange: [min, max]
} = props;
let value = 50;
if (scale - 1 >= 0) {
value = ((scale - 1) / (Number(max) - 1)) * 50 + 50;
} else {
value = ((scale - Number(min)) / (1 - Number(min))) * 50;
}
return value;
}
function getScale(sliderValue: number) {
const [min, max] = props.scaleRange;
let scale = 1;
if (sliderValue >= 50) {
scale = ((sliderValue - 50) / 50) * (Number(max) - 1) + 1;
} else {
scale = (sliderValue / 50) * (1 - Number(min)) + Number(min);
}
return scale;
}
function handleSliderValue(type: 'plus' | 'minus') {
let step = 10;
if (sliderValue.value >= 50) {
step = 5;
}
if (type === 'minus') {
step *= -1;
}
const newValue = sliderValue.value + step;
if (newValue >= 0 && newValue <= 100) {
sliderValue.value = newValue;
} else {
sliderValue.value = newValue < 0 ? 0 : 100;
}
}
function formatSlider(sliderValue: number) {
const scale = getScale(sliderValue);
const percent = `${Math.round(scale * 100)}%`;
return percent;
}
function getSliderLabelBottom(sliderValue: number) {
return `${19 + (102 * sliderValue) / 100}px`;
}
watch(sliderValue, newValue => {
const updateScale = getScale(newValue);
emit('update:scale', updateScale);
});
watch(
() => props.scale,
() => {
sliderValue.value = getSliderValue();
}
);
</script>
<style scoped>
:deep(.n-slider-rail) {
width: 4px;
}
</style>

View File

@@ -1,80 +0,0 @@
<template>
<g>
<path :d="line" style="fill: none" :style="lineStyle"></path>
<path :d="arrow" style="stroke-width: 0" :style="arrowStyle"></path>
</g>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import type { SCoord } from '@/interface';
interface Props {
/** 边的起始坐标 */
sourceCoord: SCoord;
/** 边的终点坐标 */
targetCoord: SCoord;
/** 边的线宽 */
width?: number;
/** 填充颜色 */
color?: string;
/** 是否高亮 */
highlight?: boolean;
/** 高亮的颜色 */
highlightColor?: string;
/** 是否显示终点箭头 */
showArrow?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
width: 2,
color: '#000',
highlight: false,
highlightColor: '#f00',
showArrow: true
});
const line = computed(() => {
const {
sourceCoord: { x: sX, y: sY },
targetCoord: { x: tX, y: tY },
showArrow
} = props;
const horizontalGap = Math.abs(sX - tX);
const start = `M${sX} ${sY}`;
const end = showArrow ? `${tX - 5} ${tY}` : `${tX} ${tY}`;
const control1 = `C${sX + (horizontalGap * 2) / 3} ${sY}`;
const control2 = `${tX - (horizontalGap * 2) / 3} ${tY}`;
return `${start} ${control1} ${control2} ${end}`;
});
const arrow = computed(() => {
const { x, y } = props.targetCoord;
const M = `M${x - 10} ${y}`;
const L1 = `L ${x - 10} ${y - 5 + 0.2472}`;
const A1 = `A 4 4 0 0 1 ${x - 10 + 0.178885} ${y - 5 + 0.08944}`;
const L2 = `L ${x - 0.8944} ${y - 0.4472}`;
const A2 = `A 5 5 0 0 1 ${x - 0.8944} ${y + 0.4472}`;
const L3 = `L ${x - 10 + 0.178885} ${y + 5 - 0.08944}`;
const A3 = `A 4 4 0 0 1 ${x - 10} ${y + 5 - 0.2472}`;
return `${M} ${L1} ${A1} ${L2} ${A2} ${L3} ${A3}`;
});
const lineStyle = computed(() => {
const { highlight, highlightColor, color } = props;
const stroke = highlight ? highlightColor : color;
return {
stroke,
strokeWidth: props.width
};
});
const arrowStyle = computed(() => {
const { highlight, highlightColor, color } = props;
const fill = highlight ? highlightColor : color;
return {
fill
};
});
</script>
<style scoped></style>

View File

@@ -1,28 +0,0 @@
<template>
<g :transform="transform">
<foreignObject :width="props.size.w" :height="props.size.h">
<slot></slot>
</foreignObject>
</g>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import type { SNodeSize } from '@/interface';
interface Props {
/** 节点尺寸 */
size?: SNodeSize;
/** 节点坐标 */
x: number;
/** 节点坐标 */
y: number;
}
const props = withDefaults(defineProps<Props>(), {
size: () => ({ w: 100, h: 100 })
});
const transform = computed(() => `translate(${props.x}, ${props.y})`);
</script>
<style scoped></style>

View File

@@ -1,6 +0,0 @@
import DragScaleSvg from './DragScaleSvg.vue';
import SvgNode from './SvgNode.vue';
import SvgEdge from './SvgEdge.vue';
import ScaleSlider from './ScaleSlider.vue';
export { DragScaleSvg, SvgNode, SvgEdge, ScaleSlider };

View File

@@ -1,123 +0,0 @@
<template>
<drag-scale-svg
v-model:scale="dragScaleConfig.scale"
v-model:translate="dragScaleConfig.translate"
:scale-range="dragScaleConfig.scaleRange"
:center-svg="centerSvg"
:center-coord="centerCoord"
>
<g>
<svg-edge
v-for="(edge, index) in allEdges.unhighlights"
:key="`unhighlight${index}`"
v-bind="edge"
:color="edgeColor"
/>
<svg-edge
v-for="(edge, index) in allEdges.highlights"
:key="`highlight${index}`"
v-bind="edge"
:color="edgeColor"
:highlight="true"
:highlight-color="highlightColor"
/>
</g>
<g>
<svg-node v-for="node in nodes" :key="node.id" :x="node.x" :y="node.y" :size="nodeSize">
<slot name="node" v-bind="node"></slot>
</svg-node>
</g>
<template #absolute>
<scale-slider
v-model:scale="dragScaleConfig.scale"
v-model:translate="dragScaleConfig.translate"
:theme-color="sliderColor"
class="absolute bottom-56px transition-right duration-300 ease-in-out"
:style="{ right: sliderRight + 'px' }"
/>
</template>
</drag-scale-svg>
</template>
<script setup lang="ts">
import { reactive, computed } from 'vue';
import type { SScaleRange, STranslate, SGraphNode, SGraphEdge, SNodeSize, SCoord } from '@/interface';
import { DragScaleSvg, SvgNode, SvgEdge, ScaleSlider } from './components';
interface Props {
/** 图的节点 */
nodes: SGraphNode[];
/** 图的关系线 */
edges: SGraphEdge[];
/** 节点尺寸 */
nodeSize?: SNodeSize;
/** 边的填充颜色 */
edgeColor?: string;
/** 高亮颜色 */
highlightColor?: string;
/** 需要高亮关系线的节点坐标 */
highlightCoord?: SCoord;
/** 锁放条的颜色 */
sliderColor?: string;
/** 缩放条距离父元素右边的距离 */
sliderRight?: number;
/** 是否开启按坐标居中画布 */
centerSvg?: boolean;
/** 居中的坐标 */
centerCoord?: SCoord;
}
/** 可缩放拖拽容器的配置属性 */
interface GragScaleConfig {
/** 缩放比例 */
scale: number;
/** 缩放范围 */
scaleRange: SScaleRange;
/** g标签相对于svg标签的左上角的偏移量 */
translate: STranslate;
}
const props = withDefaults(defineProps<Props>(), {
nodeSize: () => ({ w: 100, h: 100 }),
edgeColor: '#000',
highlightColor: '#fadb14',
highlightCoord: () => ({ x: NaN, y: NaN }),
sliderColor: '#000',
sliderRight: 48,
centerSvg: false,
centerCoord: () => ({ x: 0, y: 0 })
});
const dragScaleConfig = reactive<GragScaleConfig>({
scale: 1,
scaleRange: [0.2, 3],
translate: { x: 0, y: 0 }
});
/** 区分是否高亮的边 */
const allEdges = computed(() => {
const {
edges,
highlightCoord: { x: hX, y: hY },
nodeSize: { w, h }
} = props;
const highlights: SGraphEdge[] = [];
const unhighlights: SGraphEdge[] = [];
edges.forEach(edge => {
const { x: sX, y: sY } = edge.sourceCoord;
const { x: tX, y: tY } = edge.targetCoord;
const isSourceHighlight = hX === sX - w && hY + h / 2 === sY;
const isTargetHighlight = hX === tX && hY + h / 2 === tY;
if (isSourceHighlight || isTargetHighlight) {
highlights.push(edge);
} else {
unhighlights.push(edge);
}
});
return {
highlights,
unhighlights
};
});
</script>
<style scoped></style>

View File

@@ -1,40 +0,0 @@
<template>
<hover-container class="w-40px h-full text-14px text-[#999] hover:text-primary" @click="toggleDarkMode">
<icon-mdi-moon-waning-crescent v-if="dark" />
<icon-mdi-white-balance-sunny v-else />
</hover-container>
</template>
<script lang="ts" setup>
import { watch } from 'vue';
import { HoverContainer } from '../../common';
import { useBoolean } from '@/hooks';
interface Props {
/** 暗黑模式 */
dark?: boolean;
}
interface Emits {
(e: 'update', darkMode: boolean): void;
}
const props = withDefaults(defineProps<Props>(), {
dark: false
});
const emit = defineEmits<Emits>();
const { bool: darkMode, setBool: setDarkMode, toggle: toggleDarkMode } = useBoolean(props.dark);
watch(
() => props.dark,
newValue => {
setDarkMode(newValue);
}
);
watch(darkMode, newValue => {
emit('update', newValue);
});
</script>
<style scoped></style>

View File

@@ -1,11 +0,0 @@
import CountTo from './CountTo/index.vue';
import IconClose from './IconClose/index.vue';
import ButtonTab from './ButtonTab/index.vue';
import ChromeTab from './ChromeTab/index.vue';
import BetterScroll from './BetterScroll/index.vue';
import WebSiteLink from './WebSiteLink/index.vue';
import GithubLink from './GithubLink/index.vue';
import ThemeSwitch from './ThemeSwitch/index.vue';
import ImageVerify from './ImageVerify/index.vue';
export { CountTo, IconClose, ButtonTab, ChromeTab, BetterScroll, WebSiteLink, GithubLink, ThemeSwitch, ImageVerify };

View File

@@ -1,3 +0,0 @@
export * from './common';
export * from './custom';
export * from './svg';

Some files were not shown because too many files have changed in this diff Show More