Browse Source

统一命名格式

master
Fuyuu 1 year ago
parent
commit
4b7e095ce0
  1. 19
      .editorconfig
  2. 23
      .env
  3. 46
      .env.development
  4. 42
      .env.production
  5. 34
      .env.test
  6. 15
      .eslintignore
  7. 81
      .eslintrc.js
  8. 35
      .gitignore
  9. 6
      .gitpod.yml
  10. 9
      .prettierignore
  11. 3
      .stylelintignore
  12. 48
      .yarnclean
  13. 30
      Dockerfile
  14. 31
      LICENSE
  15. 420
      README.md
  16. 80
      build/config/themeConfig.ts
  17. 8
      build/constant.ts
  18. 37
      build/generate/generateModifyVars.ts
  19. 68
      build/generate/icon/index.ts
  20. 7
      build/getConfigFileName.ts
  21. 47
      build/script/buildConf.ts
  22. 23
      build/script/postBuild.ts
  23. 92
      build/utils.ts
  24. 32
      build/vite/plugin/compress.ts
  25. 40
      build/vite/plugin/html.ts
  26. 34
      build/vite/plugin/imagemin.ts
  27. 80
      build/vite/plugin/index.ts
  28. 19
      build/vite/plugin/mock.ts
  29. 33
      build/vite/plugin/pwa.ts
  30. 81
      build/vite/plugin/styleImport.ts
  31. 17
      build/vite/plugin/svgSprite.ts
  32. 100
      build/vite/plugin/theme.ts
  33. 17
      build/vite/plugin/visualizer.ts
  34. 34
      build/vite/proxy.ts
  35. 32
      commitlint.config.js
  36. 56
      electron/electron.js
  37. 175
      index.html
  38. 36
      jest.config.mjs
  39. 18
      mock/_createProductionServer.ts
  40. 63
      mock/_util.ts
  41. 70
      mock/demo/account.ts
  42. 28
      mock/demo/select-demo.ts
  43. 298
      mock/demo/system.ts
  44. 52
      mock/demo/table-demo.ts
  45. 38
      mock/demo/tree-demo.ts
  46. 270
      mock/sys/menu.ts
  47. 124
      mock/sys/user.ts
  48. 0
      npm
  49. 43976
      package-lock.json
  50. 357
      package.json
  51. 16804
      pnpm-lock.yaml
  52. 5
      postcss.config.js
  53. 20
      prettier.config.js
  54. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_0.json
  55. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_1.json
  56. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_10.json
  57. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_11.json
  58. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_12.json
  59. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_13.json
  60. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_14.json
  61. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_15.json
  62. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_16.json
  63. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_17.json
  64. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_18.json
  65. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_19.json
  66. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_2.json
  67. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_20.json
  68. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_21.json
  69. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_22.json
  70. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_23.json
  71. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_24.json
  72. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_25.json
  73. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_26.json
  74. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_27.json
  75. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_3.json
  76. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_4.json
  77. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_5.json
  78. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_6.json
  79. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_7.json
  80. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_8.json
  81. 1
      public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_9.json
  82. BIN
      public/earthsdk/XbsjCesium/Assets/Images/bing_maps_credit.png
  83. BIN
      public/earthsdk/XbsjCesium/Assets/Images/cesium_credit.png
  84. BIN
      public/earthsdk/XbsjCesium/Assets/Images/google_earth_credit.png
  85. BIN
      public/earthsdk/XbsjCesium/Assets/Images/ion-credit.png
  86. BIN
      public/earthsdk/XbsjCesium/Assets/Textures/LensFlare/DirtMask.jpg
  87. BIN
      public/earthsdk/XbsjCesium/Assets/Textures/LensFlare/StarBurst.jpg
  88. BIN
      public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/0/0/0.jpg
  89. BIN
      public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/0/1/0.jpg
  90. BIN
      public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/1/0/0.jpg
  91. BIN
      public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/1/0/1.jpg
  92. BIN
      public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/1/1/0.jpg
  93. BIN
      public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/1/1/1.jpg
  94. BIN
      public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/1/2/0.jpg
  95. BIN
      public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/1/2/1.jpg
  96. BIN
      public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/1/3/0.jpg
  97. BIN
      public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/1/3/1.jpg
  98. BIN
      public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/2/0/0.jpg
  99. BIN
      public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/2/0/1.jpg
  100. BIN
      public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/2/0/2.jpg

19
.editorconfig

@ -0,0 +1,19 @@
root = true
[*]
charset=utf-8
end_of_line=lf
insert_final_newline=true
indent_style=space
indent_size=2
max_line_length = 100
[*.{yml,yaml,json}]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab

23
.env

@ -0,0 +1,23 @@
# port
VITE_PORT = 3200
# 网站标题
# VITE_GLOB_APP_TITLE = 企业级低代码平台
VITE_GLOB_APP_TITLE=边海防智能监控站
# 简称,用于配置文件名字 不要出现空格、数字开头等特殊字符
VITE_GLOB_APP_SHORT_NAME = JeecgBootAdmin
# 单点登录服务端地址
VITE_GLOB_APP_CAS_BASE_URL=http://cas.test.com:8443/cas
# 是否开启单点登录
VITE_GLOB_APP_OPEN_SSO = false
# 开启微前端模式
VITE_GLOB_APP_OPEN_QIANKUN=true
# 文件预览地址
VITE_GLOB_ONLINE_VIEW_URL=http://fileview.jeecg.com/onlinePreview

46
.env.development

@ -0,0 +1,46 @@
###
# @Author: Fuyuu 1805498209@qq.com
# @Date: 2023-11-24 10:15:22
# @LastEditors: Fuyuu 1805498209@qq.com
# @LastEditTime: 2023-11-24 18:10:19
# @FilePath: \dt-admin-pc\.env.development
# @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
###
# 是否打开mock
VITE_USE_MOCK = true
# 发布路径
VITE_PUBLIC_PATH = /
# 跨域代理,您可以配置多个 ,请注意,没有换行符
# VITE_PROXY = [["/jeecgboot","http://localhost:8088/military"],["/upload","http://localhost:3300/upload"]]
VITE_PROXY = [["/dt","http://192.168.1.174:8088/dt"],["/upload","http://localhost:3300/upload"]]
# 控制台不输出
VITE_DROP_CONSOLE = false
#后台接口父地址(必填)
VITE_GLOB_API_URL=/dt
#后台接口全路径地址(必填)
# VITE_GLOB_DOMAIN_URL=http://localhost:8088/jmilitary
VITE_GLOB_DOMAIN_URL=http://192.168.1.174:8088/dt
# 接口前缀
VITE_GLOB_API_URL_PREFIX=
#微前端qiankun应用,命名必须以VITE_APP_SUB_开头,jeecg-app-1为子应用的项目名称,也是子应用的路由父路径
VITE_APP_SUB_jeecg-app-1 = '//localhost:8092'
#地图地址
VITE_GLOB_EARTHMAP_URL=/dt
#地图地址-卫星
VITE_GLOB_SATELLITE_URL=/mapTile/satellite_ny/
#地图地址-矢量
VITE_GLOB_VECTOR_URL=/mapTile/vector_ny/
#地图地址-地形
VITE_GLOB_TERRAIN_URL=/mapTile/terrain_ny/
#静态资源
#VITE_GLOB_STATICDOMAIN_URL=VITE_GLOB_DOMAIN_URL + '/sys/common/static'

42
.env.production

@ -0,0 +1,42 @@
###
# @Author: Fuyuu 1805498209@qq.com
# @Date: 2023-11-24 10:15:22
# @LastEditors: Fuyuu 1805498209@qq.com
# @LastEditTime: 2023-11-28 14:15:57
# @FilePath: \dt-admin-pc\.env.production
# @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
###
# 是否启用mock
VITE_USE_MOCK = true
# 发布路径
VITE_PUBLIC_PATH = /
# 控制台不输出
VITE_DROP_CONSOLE = true
# 是否启用gzip或brotli压缩
# 选项值: gzip | brotli | none
# 如果需要多个可以使用“,”分隔
VITE_BUILD_COMPRESS = 'gzip'
# 使用压缩时是否删除原始文件,默认为false
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
#后台接口父地址(必填)
VITE_GLOB_API_URL=http://192.168.1.174:8088/dt/
#后台接口全路径地址(必填)
VITE_GLOB_DOMAIN_URL=http://192.168.1.174:8088/dt/
# 接口父路径前缀
VITE_GLOB_API_URL_PREFIX=
# 是否启用图像压缩
VITE_USE_IMAGEMIN= true
# 使用pwa
VITE_USE_PWA = false
# 是否兼容旧浏览器
VITE_LEGACY = false

34
.env.test

@ -0,0 +1,34 @@
# 是否启用mock
VITE_USE_MOCK = true
# 发布路径
VITE_PUBLIC_PATH = /
# 控制台不输出
VITE_DROP_CONSOLE = true
# 是否启用gzip或brotli压缩
# 选项值: gzip | brotli | none
# 如果需要多个可以使用“,”分隔
VITE_BUILD_COMPRESS = 'gzip'
# 使用压缩时是否删除原始文件,默认为false
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
#后台接口父地址(必填)
VITE_GLOB_API_URL=/jeecgboot
#后台接口全路径地址(必填)
VITE_GLOB_DOMAIN_URL=http://localhost:8080/jeecg-boot
# 接口父路径前缀
VITE_GLOB_API_URL_PREFIX=
# 是否启用图像压缩
VITE_USE_IMAGEMIN= true
# 使用pwa
VITE_USE_PWA = false
# 是否兼容旧浏览器
VITE_LEGACY = false

15
.eslintignore

@ -0,0 +1,15 @@
*.sh
node_modules
*.md
*.woff
*.ttf
.vscode
.idea
dist
/public
/docs
.husky
.local
/bin
Dockerfile

81
.eslintrc.js

@ -0,0 +1,81 @@
// @ts-check
const { defineConfig } = require('eslint-define-config');
module.exports = defineConfig({
root: true,
env: {
browser: true,
node: true,
es6: true,
},
globals:{
"Cesium": true
},
parser: 'vue-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser',
ecmaVersion: 2020,
sourceType: 'module',
jsxPragma: 'React',
ecmaFeatures: {
jsx: true,
},
},
extends: [
'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
'plugin:prettier/recommended',
'plugin:jest/recommended',
],
rules: {
'vue/script-setup-uses-vars': 'error',
'@typescript-eslint/ban-ts-ignore': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/no-empty-function': 'off',
'vue/custom-event-name-casing': 'off',
'no-use-before-define': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/ban-types': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],
'no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],
'space-before-function-paren': 'off',
'vue/attributes-order': 'off',
'vue/one-component-per-file': 'off',
'vue/html-closing-bracket-newline': 'off',
'vue/max-attributes-per-line': 'off',
'vue/multiline-html-element-content-newline': 'off',
'vue/singleline-html-element-content-newline': 'off',
'vue/attribute-hyphenation': 'off',
'vue/require-default-prop': 'off',
'vue/html-self-closing': [
'error',
{
html: {
void: 'always',
normal: 'never',
component: 'always',
},
svg: 'always',
math: 'always',
},
],
},
});

35
.gitignore

@ -0,0 +1,35 @@
node_modules
.DS_Store
.github
dist
dist_electron
.npmrc
.cache
tests/server/static
tests/server/static/upload
.local
# local env files
.env.local
.env.*.local
.eslintcache
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
# .vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
/os_del.cmd
/.vscode/
/.history/
/svn clear.bat

6
.gitpod.yml

@ -0,0 +1,6 @@
ports:
- port: 3344
onOpen: open-preview
tasks:
- init: yarn
command: yarn dev

9
.prettierignore

@ -0,0 +1,9 @@
/dist/*
.local
.output.js
/node_modules/**
**/*.svg
**/*.sh
/public/*

3
.stylelintignore

@ -0,0 +1,3 @@
/dist/*
/public/*
public/*

48
.yarnclean

@ -0,0 +1,48 @@
# test directories
__tests__
test
tests
powered-test
# asset directories
docs
doc
website
images
assets
# examples
example
examples
# code coverage directories
coverage
.nyc_output
# build scripts
Makefile
Gulpfile.js
Gruntfile.js
# configs
appveyor.yml
circle.yml
codeship-services.yml
codeship-steps.yml
wercker.yml
.tern-project
.gitattributes
.editorconfig
.*ignore
.eslintrc
.jshintrc
.flowconfig
.documentup.json
.yarn-metadata.json
.travis.yml
# misc
*.md
!istanbul-reports/lib/html/assets
!istanbul-api/node_modules/istanbul-reports/lib/html/assets

30
Dockerfile

@ -0,0 +1,30 @@
FROM nginx
MAINTAINER jeecgos@163.com
VOLUME /tmp
ENV LANG en_US.UTF-8
RUN echo "server { \
listen 80; \
location /jeecgboot/ { \
proxy_pass http://jeecg-boot-system:8080/jeecg-boot/; \
proxy_redirect off; \
proxy_set_header Host jeecg-boot-system; \
proxy_set_header X-Real-IP \$remote_addr; \
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; \
} \
#解决Router(mode: 'history')模式下,刷新路由地址不能找到页面的问题 \
location / { \
root /var/www/html/; \
index index.html index.htm; \
if (!-e \$request_filename) { \
rewrite ^(.*)\$ /index.html?s=\$1 last; \
break; \
} \
} \
access_log /var/log/nginx/access.log ; \
} " > /etc/nginx/conf.d/default.conf \
&& mkdir -p /var/www \
&& mkdir -p /var/www/html
ADD dist/ /var/www/html/
EXPOSE 80
EXPOSE 443

31
LICENSE

@ -1,9 +1,32 @@
MIT License
Copyright (c) <year> <copyright holders>
Copyright (c) 2020-present, Jeecg
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
开源协议补充
JeecgBoot 是由 北京敲敲云科技有限公司 发行的软件。 总部位于北京,地址:中国·北京·朝阳区科荟前街1号院奥林佳泰大厦。邮箱:jeecgos@163.com
本软件受适用的国家软件著作权法(包括国际条约)和双重保护许可。
1.允许基于本平台软件开展业务系统开发。
2.不得基于该平台软件的基础,修改包装成一个与JeecgBoot平台软件功能类似的产品进行发布、销售,或与JeecgBoot参与同类软件产品市场的竞争。
违反此条款属于侵权行为,须赔偿侵权经济损失,同时立即停止著作权侵权行为。
解释权归:http://www.jeecg.com

420
README.md

@ -1,4 +1,418 @@
# dt-admin-pc-v2
数字孪生Web 后台dt( digital twin)2.0版本
统一命名格式
## 源码下载
- 后台源码 :http://192.168.1.200/lxc/dt-java.git
- 前端源码 :http://192.168.1.200/lxc/dt-admin.git
- 地图3D展示:http://192.168.1.200/lxc/dt-map-web.git
##### 项目说明
| 项目名 | 说明 |
|--------------------|------------------------|
| `dt-admin` | Vue3版前端代码 |
| `dt-java` | SpringBoot后台项目(支持微服务) |
| `dt-map-web` |Cesium 项目 |
## 技术文档
- 官方文档:[http://help.jeecg.com](http://help.jeecg.com)
- 官方网站: [http://www.jeecg.com](http://www.jeecg.com)
- 在线演示:[低代码演示](http://boot3.jeecg.com) | [敲敲云零代码](https://www.qiaoqiaoyun.com)
- 快速入门:[常见问题](http://help.jeecg.com/qa.html) | [入门视频](https://www.bilibili.com/video/BV1V34y187Y9 "入门视频") | [ 代码生成](http://help.jeecg.com/vue3/codegen/online.html)
## 安装与使用
> 环境要求: 版本要求Node 14.18+ / 16+ 版本以上,不再支持 Node 12 / 13 / 15。
> 建议使用pnpm,如果使用yarn,请用Yarn1.x版本,否则依赖可能安装不上。
- Get the project code
```bash
git clone https://github.com/jeecgboot/jeecgboot-vue3.git
```
- Installation dependencies
```bash
cd jeecgboot-vue3
pnpm install
```
- 配置接口地址 `.env.development`
```bash
VITE_PROXY = [["/jeecgboot","http://localhost:8080/jeecg-boot"],["/upload","http://localhost:3300/upload"]]
VITE_GLOB_DOMAIN_URL=http://localhost:8080/jeecg-boot
```
> 说明:把`http://localhost:8080/jeecg-boot` 换成自己地址,其他不用改。
- run
```bash
pnpm serve
```
- build
```bash
pnpm build
```
## Docker镜像启动前端(单体模式)
- host设置
>注意: 需要把`127.0.0.1`替换成真实IP 比如`192.`开头,不然后端不通。
```bash
127.0.0.1 jeecg-boot-system
127.0.0.1 jeecg-boot-gateway
```
- 下载项目
```bash
git clone https://github.com/jeecgboot/jeecgboot-vue3.git
cd jeecgboot-vue3
```
- 配置接口域名 `.env.production`
```bash
VITE_GLOB_API_URL=/jeecgboot
VITE_GLOB_DOMAIN_URL=http://jeecg-boot-system:8080/jeecg-boot
```
后台单体启动 [见此文档](https://help.jeecg.com/java/setup/docker/up.html)
- 编译项目
```bash
pnpm install
pnpm build
```
- 启动容器
```bash
docker build -t jeecgboot-vue3 .
docker run --name jeecgboot-vue3-nginx -p 80:80 -d jeecgboot-vue3
```
- 访问前台
http://localhost
## Docker镜像启动前端(微服务模式)
> 这里只写与单体的区别步骤
- 区别1. 修改后台域名
.env.production
```bash
VITE_GLOB_API_URL=/jeecgboot
VITE_GLOB_DOMAIN_URL=http://jeecg-boot-gateway:9999
```
后台微服务启动 [见此文档](https://help.jeecg.com/java/springcloud/docker.html)
- 区别2. 修改Dockerfile文件
```bash
- 把`http://jeecg-boot-system:8080/jeecg-boot`替换成 `http://jeecg-boot-gateway:9999`
- 把`jeecg-boot-system`替换成 `jeecg-boot-gateway`
```
- 其他与单体模式一样
```bash
镜像需要重现构建,最好把单体的镜像删掉,重新构建docker镜像。
```
## 入门必备
本项目需要一定前端基础知识,请确保掌握 Vue 的基础知识,以便能处理一些常见的问题。 建议在开发前先学一下以下内容,提前了解和学习这些知识,会对项目理解非常有帮助:
* [JeecgBoot-Vue3文档](http://help.jeecg.com)
* [Vue3 文档](https://cn.vuejs.org/)
* [Vben文档](https://doc.vvbin.cn)
* [Ant-Design-Vue](https://www.antdv.com/docs/vue/introduce-cn/)
* [TypeScript](https://www.typescriptlang.org/)
* [Vue-router](https://router.vuejs.org/zh)
* [Es6](https://es6.ruanyifeng.com/)
* [Vitejs](https://cn.vitejs.dev/guide/)
* [Pinia(vuex替代方案)](https://pinia.esm.dev/introduction.html)
* [Vue-RFCS](https://github.com/vuejs/rfcs)
* [Vue2 迁移到 3](https://v3.vuejs.org/guide/migration/introduction.html)
* [vxetable文档](https://vxetable.cn)
* [~~WindiCss~~](https://windicss.netlify.app/)
## 浏览器支持
**本地开发**推荐使用`Chrome 最新版`浏览器,**不支持**`Chrome 90`以下版本。
**生产环境**支持现代浏览器,不支持 IE。
| [![IE](https://raw.githubusercontent.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png)](http://godban.github.io/browsers-support-badges/)IE | [![ Edge](https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png)](http://godban.github.io/browsers-support-badges/)Edge | [![Firefox](https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png)](http://godban.github.io/browsers-support-badges/)Firefox | [![Chrome](https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png)](http://godban.github.io/browsers-support-badges/)Chrome | [![Safari](https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png)](http://godban.github.io/browsers-support-badges/)Safari |
| --- | --- | --- | --- | --- |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## 功能模块
> vue3版本已经实现了系统管理、系统监控、报表、各种组件、前端权限、GUI代码生成、Online表单、Online报表等平台功能,完全可以用于生产环境。
```
├─首页
│ ├─首页(四套首页满足不同场景需求)
│ ├─工作台
├─系统管理
│ ├─用户管理
│ ├─角色管理
│ ├─菜单管理
│ ├─权限设置(支持按钮权限、数据权限)
│ ├─表单权限(控制字段禁用、隐藏)
│ ├─部门管理
│ ├─我的部门(二级管理员)
│ └─字典管理
│ └─分类字典
│ └─系统公告
│ └─职务管理
│ └─通讯录
│ └─对象存储
│ └─多租户管理
├─系统监控
│ ├─网关路由配置(gateway)
│ ├─定时任务
│ ├─数据源管理
│ ├─系统日志
│ ├─消息中心(支持短信、邮件、微信推送等等)
│ ├─数据日志(记录数据快照,可对比快照,查看数据变更情况)
│ ├─系统通知
│ ├─SQL监控
│ ├─性能监控
│ │ ├─监控 Redis
│ │ ├─Tomcat
│ │ ├─jvm
│ │ ├─服务器信息
│ │ ├─请求追踪
│ │ ├─磁盘监控
├─消息中心
│ ├─我的消息
│ ├─消息管理
│ ├─模板管理
├─积木报表设计器
│─报表示例
│ ├─曲线图
│ └─饼状图
│ └─柱状图
│ └─折线图
│ └─面积图
│ └─雷达图
│ └─仪表图
│ └─进度条
│ └─排名列表
│ └─等等
│─大屏模板
│ ├─作战指挥中心大屏
│ └─物流服务中心大屏
├─代码生成器(GUI)
│ ├─代码生成器功能(一键生成前后端代码,生成后无需修改直接用,绝对是后端开发福音)
│ ├─代码生成器模板(提供4套模板,分别支持单表和一对多模型,不同风格选择)
│ ├─代码生成器模板(生成代码,自带excel导入导出)
│ ├─查询过滤器(查询逻辑无需编码,系统根据页面配置自动生成)
│ ├─高级查询器(弹窗自动组合查询条件)
│ ├─Excel导入导出工具集成(支持单表,一对多 导入导出)
│ ├─平台移动自适应支持
│─常用示例
│ ├─自定义组件示例
│ ├─JVxeTable示例(ERP行业复杂排版效果)
│ ├─单表模型例子
│ └─一对多模型例子
│ └─打印例子
│ └─一对多内嵌示例
│ └─异步树Table
│ └─图片拖拽排序
│ └─图片翻页
│ └─图片预览
│ └─PDF预览
│─封装通用组件
│ ├─行编辑表格JVxeTable
│ └─省略显示组件
│ └─时间控件
│ └─高级查询 (未实现)
│ └─用户选择组件
│ └─报表组件封装
│ └─字典组件
│ └─下拉多选组件
│ └─选人组件
│ └─选部门组件
│ └─通过部门选人组件
│ └─封装曲线、柱状图、饼状图、折线图等等报表的组件(经过封装,使用简单)
│ └─在线code编辑器
│ └─上传文件组件
│ └─树列表组件
│ └─表单禁用组件
│ └─等等
│─更多页面模板
│ └─Mock示例(子菜单很多)
│ └─页面&导航(子菜单很多)
│ └─组件&功能(子菜单很多)
├─高级功能
│ ├─支持微前端
│ ├─提供CAS单点登录
│ ├─集成Websocket消息通知机制
│ ├─支持第三方登录(QQ、钉钉、微信等)
│ ├─系统编码规则
├─Online在线开发(低代码)
│ ├─Online在线表单 - 功能已开放
│ ├─Online代码生成器 - 功能已开放
│ ├─Online在线报表 - 功能已开放
│ ├─Online在线图表(暂未开源)
│ ├─多数据源管理
│─流程模块功能 (暂未开源)
│ ├─流程设计器
│ ├─表单设计器
│ ├─大屏设计器
│ ├─门户设计/仪表盘设计器
│ └─我的任务
│ └─历史流程
│ └─历史流程
│ └─流程实例管理
│ └─流程监听管理
│ └─流程表达式
│ └─我发起的流程
│ └─我的抄送
│ └─流程委派、抄送、跳转
│ └─OA办公组件
└─其他模块
└─更多功能开发中。。
```
## 系统效果
系统后台
![](https://oscimg.oschina.net/oscnet/up-000530d95df337b43089ac77e562494f454.png)
![输入图片说明](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/site/vue3_20220310142354.png "在这里输入图片标题")
![输入图片说明](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/site/vue3_20220310142409.png "在这里输入图片标题")
![输入图片说明](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/site/vue3_20220310142401.png "在这里输入图片标题")
![输入图片说明](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/site/vue3_11.png "在这里输入图片标题")
Online开发&代码生成
![](https://oscimg.oschina.net/oscnet/up-e8862f2c3c14eace9090c20a8fb928234a4.png)
![](https://oscimg.oschina.net/oscnet/up-e3b3a736236bc66f255a9a32ab3f9b7196b.png)
![](https://oscimg.oschina.net/oscnet/up-221b8cbdea3c17d31a1365023a73d3d439f.png)
![](https://oscimg.oschina.net/oscnet/up-14092f6f213b26ab145cf70b2dc6dec5635.png)
系统交互
![](https://oscimg.oschina.net/oscnet/up-78b151fc888d4319377bf1cc311fe826871.png)
![](https://oscimg.oschina.net/oscnet/up-16c07e000278329b69b228ae3189814b8e9.png)
流程设计
![](https://oscimg.oschina.net/oscnet/up-981ce174e4fbb48c8a2ce4ccfd7372e2994.png)
![输入图片说明](https://static.oschina.net/uploads/img/201907/05165142_yyQ7.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160917_9Ftz.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160633_u59G.png "在这里输入图片标题")
简版流程设计
![](https://oscimg.oschina.net/oscnet/up-1dc0d052149ec675f3e4fad632b82b48add.png)
![](https://oscimg.oschina.net/oscnet/up-de31bc2f9d9b8332c554b0954cc73d79593.png)
![](https://oscimg.oschina.net/oscnet/up-7f83b25159663686d67ed080eb16068c3b4.png)
仪表盘设计器
![](https://oscimg.oschina.net/oscnet/up-9c9d41288c31398d76b390bdd400f13a582.png)
![](https://oscimg.oschina.net/oscnet/up-fad98d42b2cf92f92a903c9cff7579f18ec.png)
报表设计器
![](https://oscimg.oschina.net/oscnet/up-64648de000851f15f6c7b9573d107ebb5f8.png)
![](https://oscimg.oschina.net/oscnet/up-fa52b44445db281c51d3f267dce7450d21b.gif)
![](https://oscimg.oschina.net/oscnet/up-68a19149d640f1646c8ed89ed4375e3326c.png)
![](https://oscimg.oschina.net/oscnet/up-f7e9cb2e3740f2d19ff63b40ec2dd554f96.png)
表单设计器
![](https://oscimg.oschina.net/oscnet/up-5f8cb657615714b02190b355e59f60c5937.png)
![](https://oscimg.oschina.net/oscnet/up-d9659b2f324e33218476ec98c9b400e6508.png)
![](https://oscimg.oschina.net/oscnet/up-4868615395272d3206dbb960ade02dbc291.png)
大屏设计器
![](https://oscimg.oschina.net/oscnet/up-402a6034124474bfef8dfc5b4b2bac1ce5c.png)
![](https://oscimg.oschina.net/oscnet/up-6f7ba2e2ebbeea0d203db8d69fd87644c9f.png)
![](https://oscimg.oschina.net/oscnet/up-ee8d34f318da466b8a6070a6e3111d12ce7.png)
![](https://oscimg.oschina.net/oscnet/up-6b81781b43086819049c4421206810667c5.png)
报表效果
![](https://static.oschina.net/uploads/img/201904/14160828_pkFr.png "")
![](https://static.oschina.net/uploads/img/201904/14160834_Lo23.png "")
![](https://static.oschina.net/uploads/img/201904/14160842_QK7B.png "")
![](https://static.oschina.net/uploads/img/201904/14160849_GBm5.png "")
![](https://static.oschina.net/uploads/img/201904/14160858_6RAM.png "")
接口文档
![](https://oscimg.oschina.net/oscnet/up-e6ea09dbaa01b8458c2e23614077ba9507f.png)
手机端
![](https://oscimg.oschina.net/oscnet/da543c5d0d57baab0cecaa4670c8b68c521.jpg)
![](https://oscimg.oschina.net/oscnet/fda4bd82cab9d682de1c1fbf2060bf14fa6.jpg)
PAD端
![](https://oscimg.oschina.net/oscnet/e90fef970a8c33790ab03ffd6c4c7cec225.jpg)
![](https://oscimg.oschina.net/oscnet/d78218803a9e856a0aa82b45efc49849a0c.jpg)
![](https://oscimg.oschina.net/oscnet/59c23b230f52384e588ee16309b44fa20de.jpg)

80
build/config/themeConfig.ts

@ -0,0 +1,80 @@
import { generate } from '@ant-design/colors';
// export const primaryColor = '#1890FF';
export const primaryColor = '#009688';
export const darkMode = 'light';
type Fn = (...arg: any) => any;
type GenerateTheme = 'default' | 'dark';
export interface GenerateColorsParams {
mixLighten: Fn;
mixDarken: Fn;
tinycolor: any;
color?: string;
}
export function generateAntColors(color: string, theme: GenerateTheme = 'default') {
return generate(color, {
theme,
});
}
export function getThemeColors(color?: string) {
const tc = color || primaryColor;
const lightColors = generateAntColors(tc);
const primary = lightColors[5];
const modeColors = generateAntColors(primary, 'dark');
return [...lightColors, ...modeColors];
}
export function generateColors({
color = primaryColor,
mixLighten,
mixDarken,
tinycolor,
}: GenerateColorsParams) {
const arr = new Array(19).fill(0);
const lightens = arr.map((_t, i) => {
return mixLighten(color, i / 5);
});
const darkens = arr.map((_t, i) => {
return mixDarken(color, i / 5);
});
const alphaColors = arr.map((_t, i) => {
return tinycolor(color)
.setAlpha(i / 20)
.toRgbString();
});
const shortAlphaColors = alphaColors.map((item) => item.replace(/\s/g, '').replace(/0\./g, '.'));
const tinycolorLightens = arr
.map((_t, i) => {
return tinycolor(color)
.lighten(i * 5)
.toHexString();
})
.filter((item) => item !== '#ffffff');
const tinycolorDarkens = arr
.map((_t, i) => {
return tinycolor(color)
.darken(i * 5)
.toHexString();
})
.filter((item) => item !== '#000000');
return [
...lightens,
...darkens,
...alphaColors,
...shortAlphaColors,
...tinycolorDarkens,
...tinycolorLightens,
].filter((item) => !item.includes('-'));
}

8
build/constant.ts

@ -0,0 +1,8 @@
/**
* The name of the configuration file entered in the production environment
*/
const path = require('path');
export const GLOB_CONFIG_FILE_NAME = '_app.config.js';
export const OUTPUT_DIR = 'dist';

37
build/generate/generateModifyVars.ts

@ -0,0 +1,37 @@
import { generateAntColors, primaryColor } from '../config/themeConfig';
import { getThemeVariables } from 'ant-design-vue/dist/theme';
import { resolve } from 'path';
/**
* less global variable
*/
export function generateModifyVars(dark = false) {
const palettes = generateAntColors(primaryColor);
const primary = palettes[5];
const primaryColorObj: Record<string, string> = {};
for (let index = 0; index < 10; index++) {
primaryColorObj[`primary-${index + 1}`] = palettes[index];
}
const modifyVars = getThemeVariables({ dark });
return {
...modifyVars,
// Used for global import to avoid the need to import each style file separately
// reference: Avoid repeated references
hack: `${modifyVars.hack} @import (reference) "${resolve('src/design/config.less')}";`,
'primary-color': primary,
...primaryColorObj,
'info-color': primary,
'processing-color': primary,
'success-color': '#55D187', // Success color
'error-color': '#ED6F6F', // False color
'warning-color': '#EFBD47', // Warning color
//'border-color-base': '#EEEEEE',
'font-size-base': '14px', // Main font size
'border-radius-base': '2px', // Component/float fillet
'link-color': primary, // Link color
'app-content-background': '#fafafa', // Link color
};
}

68
build/generate/icon/index.ts

@ -0,0 +1,68 @@
import path from 'path';
import fs from 'fs-extra';
import inquirer from 'inquirer';
import colors from 'picocolors';
import pkg from '../../../package.json';
async function generateIcon() {
const dir = path.resolve(process.cwd(), 'node_modules/@iconify/json');
const raw = await fs.readJSON(path.join(dir, 'collections.json'));
const collections = Object.entries(raw).map(([id, v]) => ({
...(v as any),
id,
}));
const choices = collections.map((item) => ({ key: item.id, value: item.id, name: item.name }));
inquirer
.prompt([
{
type: 'list',
name: 'useType',
choices: [
{ key: 'local', value: 'local', name: 'Local' },
{ key: 'onLine', value: 'onLine', name: 'OnLine' },
],
message: 'How to use icons?',
},
{
type: 'list',
name: 'iconSet',
choices: choices,
message: 'Select the icon set that needs to be generated?',
},
{
type: 'input',
name: 'output',
message: 'Select the icon set that needs to be generated?',
default: 'src/components/Icon/data',
},
])
.then(async (answers) => {
const { iconSet, output, useType } = answers;
const outputDir = path.resolve(process.cwd(), output);
fs.ensureDir(outputDir);
const genCollections = collections.filter((item) => [iconSet].includes(item.id));
const prefixSet: string[] = [];
for (const info of genCollections) {
const data = await fs.readJSON(path.join(dir, 'json', `${info.id}.json`));
if (data) {
const { prefix } = data;
const isLocal = useType === 'local';
const icons = Object.keys(data.icons).map((item) => `${isLocal ? prefix + ':' : ''}${item}`);
await fs.writeFileSync(
path.join(output, `icons.data.ts`),
`export default ${isLocal ? JSON.stringify(icons) : JSON.stringify({ prefix, icons })}`
);
prefixSet.push(prefix);
}
}
fs.emptyDir(path.join(process.cwd(), 'node_modules/.vite'));
console.log(`${colors.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]`);
});
}
generateIcon();

7
build/getConfigFileName.ts

@ -0,0 +1,7 @@
/**
* Get the configuration file variable name
* @param env
*/
export const getConfigFileName = (env: Record<string, any>) => {
return `__PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || '__APP'}__CONF__`.toUpperCase().replace(/\s/g, '');
};

47
build/script/buildConf.ts

@ -0,0 +1,47 @@
/**
* Generate additional configuration files when used for packaging. The file can be configured with some global variables, so that it can be changed directly externally without repackaging
*/
import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant';
import fs, { writeFileSync } from 'fs-extra';
import colors from 'picocolors';
import { getEnvConfig, getRootPath } from '../utils';
import { getConfigFileName } from '../getConfigFileName';
import pkg from '../../package.json';
interface CreateConfigParams {
configName: string;
config: any;
configFileName?: string;
}
function createConfig(params: CreateConfigParams) {
const { configName, config, configFileName } = params;
try {
const windowConf = `window.${configName}`;
// Ensure that the variable will not be modified
let configStr = `${windowConf}=${JSON.stringify(config)};`;
configStr += `
Object.freeze(${windowConf});
Object.defineProperty(window, "${configName}", {
configurable: false,
writable: false,
});
`.replace(/\s/g, '');
fs.mkdirp(getRootPath(OUTPUT_DIR));
writeFileSync(getRootPath(`${OUTPUT_DIR}/${configFileName}`), configStr);
console.log(colors.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`);
console.log(colors.gray(OUTPUT_DIR + '/' + colors.green(configFileName)) + '\n');
} catch (error) {
console.log(colors.red('configuration file configuration file failed to package:\n' + error));
}
}
export function runBuildConfig() {
const config = getEnvConfig();
const configFileName = getConfigFileName(config);
createConfig({ config, configName: configFileName, configFileName: GLOB_CONFIG_FILE_NAME });
}

23
build/script/postBuild.ts

@ -0,0 +1,23 @@
// #!/usr/bin/env node
import { runBuildConfig } from './buildConf';
import colors from 'picocolors';
import pkg from '../../package.json';
export const runBuild = async () => {
try {
const argvList = process.argv.splice(2);
// Generate configuration file
if (!argvList.includes('disabled-config')) {
runBuildConfig();
}
console.log(`${colors.cyan(`[${pkg.name}]`)}` + ' - build successfully!');
} catch (error) {
console.log(colors.red('vite build error:\n' + error));
process.exit(1);
}
};
runBuild();

92
build/utils.ts

@ -0,0 +1,92 @@
import fs from 'fs';
import path from 'path';
import dotenv from 'dotenv';
export function isDevFn(mode: string): boolean {
return mode === 'development';
}
export function isProdFn(mode: string): boolean {
return mode === 'production';
}
/**
* Whether to generate package preview
*/
export function isReportMode(): boolean {
return process.env.REPORT === 'true';
}
// Read all environment variable configuration files to process.env
export function wrapperEnv(envConf: Recordable): ViteEnv {
const ret: any = {};
for (const envName of Object.keys(envConf)) {
let realName = envConf[envName].replace(/\\n/g, '\n');
realName = realName === 'true' ? true : realName === 'false' ? false : realName;
if (envName === 'VITE_PORT') {
realName = Number(realName);
}
if (envName === 'VITE_PROXY' && realName) {
try {
realName = JSON.parse(realName.replace(/'/g, '"'));
} catch (error) {
realName = '';
}
}
ret[envName] = realName;
if (typeof realName === 'string') {
process.env[envName] = realName;
} else if (typeof realName === 'object') {
process.env[envName] = JSON.stringify(realName);
}
}
return ret;
}
/**
*
*/
function getConfFiles() {
const script = process.env.npm_lifecycle_script;
const reg = new RegExp('--mode ([a-z_\\d]+)');
const result = reg.exec(script as string) as any;
if (result) {
const mode = result[1] as string;
return ['.env', `.env.${mode}`];
}
return ['.env', '.env.production'];
}
/**
* Get the environment variables starting with the specified prefix
* @param match prefix
* @param confFiles ext
*/
export function getEnvConfig(match = 'VITE_GLOB_', confFiles = getConfFiles()) {
let envConfig = {};
confFiles.forEach((item) => {
try {
const env = dotenv.parse(fs.readFileSync(path.resolve(process.cwd(), item)));
envConfig = { ...envConfig, ...env };
} catch (e) {
console.error(`Error in parsing ${item}`, e);
}
});
const reg = new RegExp(`^(${match})`);
Object.keys(envConfig).forEach((key) => {
if (!reg.test(key)) {
Reflect.deleteProperty(envConfig, key);
}
});
return envConfig;
}
/**
* Get user root directory
* @param dir file path
*/
export function getRootPath(...dir: string[]) {
return path.resolve(process.cwd(), ...dir);
}

32
build/vite/plugin/compress.ts

@ -0,0 +1,32 @@
/**
* Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated
* https://github.com/anncwb/vite-plugin-compression
*/
import type { PluginOption } from 'vite';
import compressPlugin from 'vite-plugin-compression';
export function configCompressPlugin(compress: 'gzip' | 'brotli' | 'none', deleteOriginFile = false): PluginOption | PluginOption[] {
const compressList = compress.split(',');
const plugins: PluginOption[] = [];
if (compressList.includes('gzip')) {
plugins.push(
compressPlugin({
ext: '.gz',
deleteOriginFile,
})
);
}
if (compressList.includes('brotli')) {
plugins.push(
compressPlugin({
ext: '.br',
algorithm: 'brotliCompress',
deleteOriginFile,
})
);
}
return plugins;
}

40
build/vite/plugin/html.ts

@ -0,0 +1,40 @@
/**
* Plugin to minimize and use ejs template syntax in index.html.
* https://github.com/anncwb/vite-plugin-html
*/
import type { PluginOption } from 'vite';
import { createHtmlPlugin } from 'vite-plugin-html';
import pkg from '../../../package.json';
import { GLOB_CONFIG_FILE_NAME } from '../../constant';
export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
const { VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH } = env;
const path = VITE_PUBLIC_PATH.endsWith('/') ? VITE_PUBLIC_PATH : `${VITE_PUBLIC_PATH}/`;
const getAppConfigSrc = () => {
return `${path || '/'}${GLOB_CONFIG_FILE_NAME}?v=${pkg.version}-${new Date().getTime()}`;
};
const htmlPlugin: PluginOption[] = createHtmlPlugin({
minify: isBuild,
inject: {
// Inject data into ejs template
data: {
title: VITE_GLOB_APP_TITLE,
},
// Embed the generated app.config.js file
tags: isBuild
? [
{
tag: 'script',
attrs: {
src: getAppConfigSrc(),
},
},
]
: [],
},
});
return htmlPlugin;
}

34
build/vite/plugin/imagemin.ts

@ -0,0 +1,34 @@
// Image resource files used to compress the output of the production environment
// https://github.com/anncwb/vite-plugin-imagemin
import viteImagemin from 'vite-plugin-imagemin';
export function configImageminPlugin() {
const plugin = viteImagemin({
gifsicle: {
optimizationLevel: 7,
interlaced: false,
},
optipng: {
optimizationLevel: 7,
},
mozjpeg: {
quality: 20,
},
pngquant: {
quality: [0.8, 0.9],
speed: 4,
},
svgo: {
plugins: [
{
name: 'removeViewBox',
},
{
name: 'removeEmptyAttrs',
active: false,
},
],
},
});
return plugin;
}

80
build/vite/plugin/index.ts

@ -0,0 +1,80 @@
import { PluginOption } from 'vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import legacy from '@vitejs/plugin-legacy';
import purgeIcons from 'vite-plugin-purge-icons';
import windiCSS from 'vite-plugin-windicss';
import VitePluginCertificate from 'vite-plugin-mkcert';
import vueSetupExtend from 'vite-plugin-vue-setup-extend';
import { configHtmlPlugin } from './html';
import { configPwaConfig } from './pwa';
import { configMockPlugin } from './mock';
import { configCompressPlugin } from './compress';
import { configStyleImportPlugin } from './styleImport';
import { configVisualizerConfig } from './visualizer';
import { configThemePlugin } from './theme';
import { configImageminPlugin } from './imagemin';
import { configSvgIconsPlugin } from './svgSprite';
import OptimizationPersist from 'vite-plugin-optimize-persist'
import PkgConfig from 'vite-plugin-package-config'
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
const { VITE_USE_IMAGEMIN, VITE_USE_MOCK, VITE_LEGACY, VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE } = viteEnv;
const vitePlugins: (PluginOption | PluginOption[])[] = [
// have to
vue(),
// have to
vueJsx(),
// support name
vueSetupExtend(),
// @ts-ignore
VitePluginCertificate({
source: 'coding',
}),
];
// vite-plugin-windicss
vitePlugins.push(windiCSS());
// @vitejs/plugin-legacy
VITE_LEGACY && isBuild && vitePlugins.push(legacy());
// vite-plugin-html
vitePlugins.push(configHtmlPlugin(viteEnv, isBuild));
// vite-plugin-svg-icons
vitePlugins.push(configSvgIconsPlugin(isBuild));
// vite-plugin-mock
VITE_USE_MOCK && vitePlugins.push(configMockPlugin(isBuild));
// vite-plugin-purge-icons
vitePlugins.push(purgeIcons());
// vite-plugin-style-import
vitePlugins.push(configStyleImportPlugin(isBuild));
// rollup-plugin-visualizer
vitePlugins.push(configVisualizerConfig());
// vite-plugin-theme
vitePlugins.push(configThemePlugin(isBuild));
// The following plugins only work in the production environment
if (isBuild) {
// vite-plugin-imagemin
VITE_USE_IMAGEMIN && vitePlugins.push(configImageminPlugin());
// rollup-plugin-gzip
vitePlugins.push(configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE));
// vite-plugin-pwa
vitePlugins.push(configPwaConfig(viteEnv));
}
//vite-plugin-theme【解决vite首次打开界面加载慢问题】
vitePlugins.push(PkgConfig());
vitePlugins.push(OptimizationPersist());
return vitePlugins;
}

19
build/vite/plugin/mock.ts

@ -0,0 +1,19 @@
/**
* Mock plugin for development and production.
* https://github.com/anncwb/vite-plugin-mock
*/
import { viteMockServe } from 'vite-plugin-mock';
export function configMockPlugin(isBuild: boolean) {
return viteMockServe({
ignore: /^\_/,
mockPath: 'mock',
localEnabled: !isBuild,
prodEnabled: isBuild,
injectCode: `
import { setupProdMockServer } from '../mock/_createProductionServer';
setupProdMockServer();
`,
});
}

33
build/vite/plugin/pwa.ts

@ -0,0 +1,33 @@
/**
* Zero-config PWA for Vite
* https://github.com/antfu/vite-plugin-pwa
*/
import { VitePWA } from 'vite-plugin-pwa';
export function configPwaConfig(env: ViteEnv) {
const { VITE_USE_PWA, VITE_GLOB_APP_TITLE, VITE_GLOB_APP_SHORT_NAME } = env;
if (VITE_USE_PWA) {
// vite-plugin-pwa
const pwaPlugin = VitePWA({
manifest: {
name: VITE_GLOB_APP_TITLE,
short_name: VITE_GLOB_APP_SHORT_NAME,
icons: [
{
src: './resource/img/pwa-192x192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: './resource/img/pwa-512x512.png',
sizes: '512x512',
type: 'image/png',
},
],
},
});
return pwaPlugin;
}
return [];
}

81
build/vite/plugin/styleImport.ts

@ -0,0 +1,81 @@
/**
* Introduces component library styles on demand.
* https://github.com/anncwb/vite-plugin-style-import
*/
import { createStyleImportPlugin } from 'vite-plugin-style-import';
export function configStyleImportPlugin(_isBuild: boolean) {
if (!_isBuild) {
return [];
}
const styleImportPlugin = createStyleImportPlugin({
libs: [
{
libraryName: 'ant-design-vue',
esModule: true,
resolveStyle: (name) => {
// 这里是无需额外引入样式文件的“子组件”列表
const ignoreList = [
'anchor-link',
'sub-menu',
'menu-item',
'menu-divider',
'menu-item-group',
'breadcrumb-item',
'breadcrumb-separator',
'form-item',
'step',
'select-option',
'select-opt-group',
'card-grid',
'card-meta',
'collapse-panel',
'descriptions-item',
'list-item',
'list-item-meta',
'table-column',
'table-column-group',
'tab-pane',
'tab-content',
'timeline-item',
'tree-node',
'skeleton-input',
'skeleton-avatar',
'skeleton-title',
'skeleton-paragraph',
'skeleton-image',
'skeleton-button',
];
// 这里是需要额外引入样式的子组件列表
// 单独引入子组件时需引入组件样式,否则会在打包后导致子组件样式丢失
const replaceList = {
'typography-text': 'typography',
'typography-title': 'typography',
'typography-paragraph': 'typography',
'typography-link': 'typography',
'dropdown-button': 'dropdown',
'input-password': 'input',
'input-search': 'input',
'input-group': 'input',
'radio-group': 'radio',
'checkbox-group': 'checkbox',
'layout-sider': 'layout',
'layout-content': 'layout',
'layout-footer': 'layout',
'layout-header': 'layout',
'month-picker': 'date-picker',
'range-picker': 'date-picker',
'image-preview-group': 'image',
};
return ignoreList.includes(name)
? ''
: replaceList.hasOwnProperty(name)
? `ant-design-vue/es/${replaceList[name]}/style/index`
: `ant-design-vue/es/${name}/style/index`;
},
},
],
});
return styleImportPlugin;
}

17
build/vite/plugin/svgSprite.ts

@ -0,0 +1,17 @@
/**
* Vite Plugin for fast creating SVG sprites.
* https://github.com/anncwb/vite-plugin-svg-icons
*/
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
import path from 'path';
export function configSvgIconsPlugin(isBuild: boolean) {
const svgIconsPlugin = createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
svgoOptions: isBuild,
// default
symbolId: 'icon-[dir]-[name]',
});
return svgIconsPlugin;
}

100
build/vite/plugin/theme.ts

@ -0,0 +1,100 @@
/**
* Vite plugin for website theme color switching
* https://github.com/anncwb/vite-plugin-theme
*/
import type { PluginOption } from 'vite';
import path from 'path';
import { viteThemePlugin, antdDarkThemePlugin, mixLighten, mixDarken, tinycolor } from '@rys-fe/vite-plugin-theme';
import { getThemeColors, generateColors } from '../../config/themeConfig';
import { generateModifyVars } from '../../generate/generateModifyVars';
export function configThemePlugin(isBuild: boolean): PluginOption[] {
const colors = generateColors({
mixDarken,
mixLighten,
tinycolor,
});
// update-begin-修复编译后主题色切换不生效黑屏的问题-----------------------
// https://github.com/vbenjs/vue-vben-admin/issues/1445
// 抽取出viteThemePlugin插件,下方会根据不同环境设置enforce
const vite_theme_plugin = viteThemePlugin({
resolveSelector: (s) => {
s = s.trim();
switch (s) {
case '.ant-steps-item-process .ant-steps-item-icon > .ant-steps-icon':
return '.ant-steps-item-icon > .ant-steps-icon';
case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled)':
case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover':
case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):active':
return s;
case '.ant-steps-item-icon > .ant-steps-icon':
return s;
case '.ant-select-item-option-selected:not(.ant-select-item-option-disabled)':
return s;
default:
if (s.indexOf('.ant-btn') >= -1) {
// 按钮被重新定制过,需要过滤掉class防止覆盖
return s;
}
}
return s.startsWith('[data-theme') ? s : `[data-theme] ${s}`;
},
colorVariables: [...getThemeColors(), ...colors],
});
vite_theme_plugin.forEach(function (item) {
//对vite:theme插件特殊配置
if ('vite:theme' === item.name) {
// 打包时去除enforce: "post",vite 2.6.x适配,否则生成app-theme-style为空,因为async transform(code, id) {的code没有正确获取
if (isBuild) {
delete item.enforce;
}
}
});
// update-end-修复编译后主题色切换不生效黑屏的问题-----------------------
const plugin = [
vite_theme_plugin,
antdDarkThemePlugin({
preloadFiles: [
path.resolve(process.cwd(), 'node_modules/ant-design-vue/dist/antd.less'),
//path.resolve(process.cwd(), 'node_modules/ant-design-vue/dist/antd.dark.less'),
path.resolve(process.cwd(), 'src/design/index.less'),
],
filter: (id) => (isBuild ? !id.endsWith('antd.less') : true),
// extractCss: false,
darkModifyVars: {
...generateModifyVars(true),
'text-color': '#c9d1d9',
'primary-1': 'rgb(255 255 255 / 8%)',
'text-color-base': '#c9d1d9',
'component-background': '#151515',
'heading-color': 'rgb(255 255 255 / 65%)',
// black: '#0e1117',
// #8b949e
'text-color-secondary': '#8b949e',
'border-color-base': '#303030',
'header-light-bottom-border-color': '#303030',
// 'border-color-split': '#30363d',
'item-active-bg': '#111b26',
'app-content-background': '#1e1e1e',
'tree-node-selected-bg': '#11263c',
'alert-success-border-color': '#274916',
'alert-success-bg-color': '#162312',
'alert-success-icon-color': '#49aa19',
'alert-info-border-color': '#153450',
'alert-info-bg-color': '#111b26',
'alert-info-icon-color': '#177ddc',
'alert-warning-border-color': '#594214',
'alert-warning-bg-color': '#2b2111',
'alert-warning-icon-color': '#d89614',
'alert-error-border-color': '#58181c',
'alert-error-bg-color': '#2a1215',
'alert-error-icon-color': '#a61d24',
},
}),
];
return plugin as unknown as PluginOption[];
}

17
build/vite/plugin/visualizer.ts

@ -0,0 +1,17 @@
/**
* Package file volume analysis
*/
import visualizer from 'rollup-plugin-visualizer';
import { isReportMode } from '../../utils';
export function configVisualizerConfig() {
if (isReportMode()) {
return visualizer({
filename: './node_modules/.cache/visualizer/stats.html',
open: true,
gzipSize: true,
brotliSize: true,
}) as Plugin;
}
return [];
}

34
build/vite/proxy.ts

@ -0,0 +1,34 @@
/**
* Used to parse the .env.development proxy configuration
*/
import type { ProxyOptions } from 'vite';
type ProxyItem = [string, string];
type ProxyList = ProxyItem[];
type ProxyTargetList = Record<string, ProxyOptions>;
const httpsRE = /^https:\/\//;
/**
* Generate proxy
* @param list
*/
export function createProxy(list: ProxyList = []) {
const ret: ProxyTargetList = {};
for (const [prefix, target] of list) {
const isHttps = httpsRE.test(target);
// https://github.com/http-party/node-http-proxy#options
ret[prefix] = {
target: target,
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(new RegExp(`^${prefix}`), ''),
// https is require secure=false
...(isHttps ? { secure: false } : {}),
};
}
return ret;
}

32
commitlint.config.js

@ -0,0 +1,32 @@
module.exports = {
ignores: [(commit) => commit.includes('init')],
extends: ['@commitlint/config-conventional'],
rules: {
'body-leading-blank': [2, 'always'],
'footer-leading-blank': [1, 'always'],
'header-max-length': [2, 'always', 108],
'subject-empty': [2, 'never'],
'type-empty': [2, 'never'],
'type-enum': [
2,
'always',
[
'feat',
'fix',
'perf',
'style',
'docs',
'test',
'refactor',
'build',
'ci',
'chore',
'revert',
'wip',
'workflow',
'types',
'release',
],
],
},
};

56
electron/electron.js

@ -0,0 +1,56 @@
// electron/electron.js
const path = require('path');
const { app, BrowserWindow } = require('electron');
const isDev = process.env.IS_DEV == "true" ? true : false;
function createWindow() {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
//preload: path.join(__dirname, 'preload.js'),
javascript: true,
plugins: true,
allowRunningInsecureContent: true,
nodeIntegration: true,
},
});
// and load the index.html of the app.
// win.loadFile("index.html");
mainWindow.loadURL(
isDev
? 'http://localhost:3200'
: `file://${path.join(__dirname, '../dist/index.html')}`
);
// mainWindow.loadURL('http://127.0.0.1:5500');
// Open the DevTools.
// if (isDev) {
mainWindow.webContents.openDevTools();
// }
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
});
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});

175
index.html

@ -0,0 +1,175 @@
<!DOCTYPE html>
<html lang="zh_CN" id="htmlRoot">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit" />
<meta
name="viewport"
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
/>
<script src="<%= BASE_URL %>earthsdk/XbsjEarth/XbsjEarth.js"></script>
<script src="<%= BASE_URL %>earthsdk/XbsjEarthUI/xbsj.js"></script>
<script src="<%= BASE_URL %>earthsdk/XbsjCesium/Cesium.js"></script>
<script type="text/javascript" src="<%= BASE_URL %>military/third/api/getImosSdkJs"></script>
<link rel="stylesheet" href="<%= BASE_URL %>earthsdk/XbsjCesium/Widgets/widgets.css">
<script src="<%= BASE_URL %>js/d3kit/libs/cesium-d3kit.js"></script>
<title><%= title %></title>
<link rel="icon" href="/zgxlogo.png" />
<!-- 全局配置 -->
<script>
window._CONFIG = {};
</script>
</head>
<body>
<script>
(() => {
var htmlRoot = document.getElementById('htmlRoot');
var theme = window.localStorage.getItem('__APP__DARK__MODE__');
if (htmlRoot && theme) {
htmlRoot.setAttribute('data-theme', theme);
theme = htmlRoot = null;
}
})();
</script>
<div id="app">
<style>
html[data-theme='dark'] .app-loading {
background-color: #2c344a;
}
html[data-theme='dark'] .app-loading .app-loading-title {
color: rgba(255, 255, 255, 0.85);
}
.app-loading {
display: flex;
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
flex-direction: column;
background-color: #f4f7f9;
}
.app-loading .app-loading-wrap {
position: absolute;
top: 50%;
left: 50%;
display: flex;
-webkit-transform: translate3d(-50%, -50%, 0);
transform: translate3d(-50%, -50%, 0);
justify-content: center;
align-items: center;
flex-direction: column;
}
.app-loading .dots {
display: flex;
padding: 98px;
justify-content: center;
align-items: center;
}
.app-loading .app-loading-title {
display: flex;
margin-top: 30px;
font-size: 30px;
color: rgba(0, 0, 0, 0.85);
justify-content: center;
align-items: center;
}
.app-loading .app-loading-logo {
display: block;
width: 90px;
margin: 0 auto;
margin-bottom: 20px;
}
.dot {
position: relative;
display: inline-block;
width: 48px;
height: 48px;
margin-top: 30px;
font-size: 32px;
transform: rotate(45deg);
box-sizing: border-box;
animation: antRotate 1.2s infinite linear;
}
.dot i {
position: absolute;
display: block;
width: 20px;
height: 20px;
background-color: #0065cc;
border-radius: 100%;
opacity: 0.3;
transform: scale(0.75);
animation: antSpinMove 1s infinite linear alternate;
transform-origin: 50% 50%;
}
.dot i:nth-child(1) {
top: 0;
left: 0;
}
.dot i:nth-child(2) {
top: 0;
right: 0;
-webkit-animation-delay: 0.4s;
animation-delay: 0.4s;
}
.dot i:nth-child(3) {
right: 0;
bottom: 0;
-webkit-animation-delay: 0.8s;
animation-delay: 0.8s;
}
.dot i:nth-child(4) {
bottom: 0;
left: 0;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s;
}
@keyframes antRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg);
}
}
@-webkit-keyframes antRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg);
}
}
@keyframes antSpinMove {
to {
opacity: 1;
}
}
@-webkit-keyframes antSpinMove {
to {
opacity: 1;
}
}
</style>
<div class="app-loading">
<div class="app-loading-wrap">
<!-- <img src="/resource/img/zgxlogo.png" class="app-loading-logo" alt="Logo" /> -->
<div class="app-loading-dots">
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
</div>
<div class="app-loading-title"><%= title %></div>
</div>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

36
jest.config.mjs

@ -0,0 +1,36 @@
export default {
preset: 'ts-jest',
roots: ['<rootDir>/tests/'],
clearMocks: true,
moduleDirectories: ['node_modules', 'src'],
moduleFileExtensions: ['js', 'ts', 'vue', 'tsx', 'jsx', 'json', 'node'],
modulePaths: ['<rootDir>/src', '<rootDir>/node_modules'],
testMatch: [
'**/tests/**/*.[jt]s?(x)',
'**/?(*.)+(spec|test).[tj]s?(x)',
'(/__tests__/.*|(\\.|/)(test|spec))\\.(js|ts)$',
],
testPathIgnorePatterns: [
'<rootDir>/tests/server/',
'<rootDir>/tests/__mocks__/',
'/node_modules/',
],
transform: {
'^.+\\.tsx?$': 'ts-jest',
},
transformIgnorePatterns: ['<rootDir>/tests/__mocks__/', '/node_modules/'],
// A map from regular expressions to module names that allow to stub out resources with a single module
moduleNameMapper: {
'\\.(vs|fs|vert|frag|glsl|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/tests/__mocks__/fileMock.ts',
'\\.(sass|s?css|less)$': '<rootDir>/tests/__mocks__/styleMock.ts',
'\\?worker$': '<rootDir>/tests/__mocks__/workerMock.ts',
'^/@/(.*)$': '<rootDir>/src/$1',
},
testEnvironment: 'jsdom',
verbose: true,
collectCoverage: false,
coverageDirectory: 'coverage',
collectCoverageFrom: ['src/**/*.{js,ts,vue}'],
coveragePathIgnorePatterns: ['^.+\\.d\\.ts$'],
};

18
mock/_createProductionServer.ts

@ -0,0 +1,18 @@
import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer';
const modules = import.meta.glob('./**/*.ts', { eager: true });
const mockModules: any[] = [];
Object.keys(modules).forEach((key) => {
if (key.includes('/_')) {
return;
}
mockModules.push(...(modules as Recordable)[key].default);
});
/**
* Used in a production environment. Need to manually import all modules
*/
export function setupProdMockServer() {
createProdMockServer(mockModules);
}

63
mock/_util.ts

@ -0,0 +1,63 @@
// Interface data format used to return a unified format
export function resultSuccess<T = Recordable>(result: T, { message = 'ok' } = {}) {
return {
code: 0,
result,
message,
type: 'success',
};
}
export function resultPageSuccess<T = any>(
pageNo: number,
pageSize: number,
list: T[],
{ message = 'ok' } = {}
) {
const pageData = pagination(pageNo, pageSize, list);
return {
...resultSuccess({
records: pageData,
total: list.length,
}),
message,
};
}
export function resultError(message = 'Request failed', { code = -1, result = null } = {}) {
return {
code,
result,
message,
type: 'error',
};
}
export function pagination<T = any>(pageNo: number, pageSize: number, array: T[]): T[] {
const offset = (pageNo - 1) * Number(pageSize);
const ret =
offset + Number(pageSize) >= array.length
? array.slice(offset, array.length)
: array.slice(offset, offset + Number(pageSize));
return ret;
}
export interface requestParams {
method: string;
body: any;
headers?: { authorization?: string };
query: any;
}
/**
* @description request数据中获取token
*
*/
export function getRequestToken({ headers }: requestParams): string | undefined {
return headers?.authorization;
}
//TODO 接口父路径(写死不够灵活)
export const baseUrl = '/jeecgboot/mock';

70
mock/demo/account.ts

@ -0,0 +1,70 @@
import { MockMethod } from 'vite-plugin-mock';
import { resultSuccess, resultError, baseUrl } from '../_util';
import { ResultEnum } from '../../src/enums/httpEnum';
const userInfo = {
name: 'Jeecg',
userid: '00000001',
email: 'test@gmail.com',
signature: '海纳百川,有容乃大',
introduction: '微笑着,努力着,欣赏着',
title: '交互专家',
group: '某某某事业群-某某平台部-某某技术部-UED',
tags: [
{
key: '0',
label: '很有想法的',
},
{
key: '1',
label: '专注设计',
},
{
key: '2',
label: '辣~',
},
{
key: '3',
label: '大长腿',
},
{
key: '4',
label: '川妹子',
},
{
key: '5',
label: '海纳百川',
},
],
notifyCount: 12,
unreadCount: 11,
country: 'China',
address: 'Xiamen City 77',
phone: '0592-268888888',
};
export default [
{
url: `${baseUrl}/account/getAccountInfo`,
timeout: 1000,
method: 'get',
response: () => {
return resultSuccess(userInfo);
},
},
{
url: `${baseUrl}/user/sessionTimeout`,
method: 'post',
statusCode: 401,
response: () => {
return resultError();
},
},
{
url: '/basic-api/user/tokenExpired',
method: 'post',
statusCode: 200,
response: () => {
return resultError('Token Expired!', { code: ResultEnum.TIMEOUT as number });
},
},
] as MockMethod[];

28
mock/demo/select-demo.ts

@ -0,0 +1,28 @@
import { MockMethod } from 'vite-plugin-mock';
import { resultSuccess, baseUrl } from '../_util';
const demoList = (keyword, count = 20) => {
const result = {
list: [] as any[],
};
for (let index = 0; index < count; index++) {
result.list.push({
name: `${keyword ?? ''}选项${index}`,
id: `${index}`,
});
}
return result;
};
export default [
{
url: `${baseUrl}/select/getDemoOptions`,
timeout: 1000,
method: 'get',
response: ({ query }) => {
const { keyword,count} = query;
console.log(keyword);
return resultSuccess(demoList(keyword,count));
},
},
] as MockMethod[];

298
mock/demo/system.ts

@ -0,0 +1,298 @@
import { MockMethod } from 'vite-plugin-mock';
import { resultError, resultPageSuccess, resultSuccess, baseUrl } from '../_util';
const accountList = (() => {
const result: any[] = [];
for (let index = 0; index < 20; index++) {
result.push({
id: `${index}`,
account: '@first',
email: '@email',
nickname: '@cname()',
role: '@first',
createTime: '@datetime',
remark: '@cword(10,20)',
'status|1': ['0', '1'],
});
}
return result;
})();
const userList = (() => {
const result: any[] = [];
for (let index = 0; index < 20; index++) {
result.push({
id: `${index}`,
username: '@first',
email: '@email',
realname: '@cname()',
createTime: '@datetime',
remark: '@cword(10,20)',
avatar: 'https://q1.qlogo.cn/g?b=qq&nk=190848757&s=640'
});
}
return result;
})();
const roleList = (() => {
const result: any[] = [];
for (let index = 0; index < 4; index++) {
result.push({
id: index + 1,
orderNo: `${index + 1}`,
roleName: ['超级管理员', '管理员', '文章管理员', '普通用户'][index],
roleValue: '@first',
createTime: '@datetime',
remark: '@cword(10,20)',
menu: [['0', '1', '2'], ['0', '1'], ['0', '2'], ['2']][index],
'status|1': ['0', '1'],
});
}
return result;
})();
const newRoleList = (() => {
const result: any[] = [];
for (let index = 0; index < 4; index++) {
result.push({
id: index + 1,
orderNo: `${index + 1}`,
roleName: ['超级管理员', '管理员', '文章管理员', '普通用户'][index],
roleCode: '@first',
createTime: '@datetime',
remark: '@cword(10,20)'
});
}
return result;
})();
const testList = (() => {
const result: any[] = [];
for (let index = 0; index < 4; index++) {
result.push({
id: index + 1,
orderNo: `${index + 1}`,
testName: ['数据1', '数据2', '数据3', '数据4'][index],
testValue: '@first',
createTime: '@datetime'
});
}
return result;
})();
const tableDemoList = (() => {
const result: any[] = [];
for (let index = 0; index < 4; index++) {
result.push({
id: index + 1,
orderCode: '2008200' + `${index + 1}`,
orderMoney: '@natural(1000,3000)',
ctype: '@natural(1,2)',
content: '@cword(10,20)',
orderDate: '@datetime'
});
}
return result;
})();
const deptList = (() => {
const result: any[] = [];
for (let index = 0; index < 3; index++) {
result.push({
id: `${index}`,
deptName: ['华东分部', '华南分部', '西北分部'][index],
orderNo: index + 1,
createTime: '@datetime',
remark: '@cword(10,20)',
'status|1': ['0', '0', '1'],
children: (() => {
const children: any[] = [];
for (let j = 0; j < 4; j++) {
children.push({
id: `${index}-${j}`,
deptName: ['研发部', '市场部', '商务部', '财务部'][j],
orderNo: j + 1,
createTime: '@datetime',
remark: '@cword(10,20)',
'status|1': ['0', '1'],
parentDept: `${index}`,
children: undefined,
});
}
return children;
})(),
});
}
return result;
})();
const menuList = (() => {
const result: any[] = [];
for (let index = 0; index < 3; index++) {
result.push({
id: `${index}`,
icon: ['ion:layers-outline', 'ion:git-compare-outline', 'ion:tv-outline'][index],
component: 'LAYOUT',
type: '0',
menuName: ['Dashboard', '权限管理', '功能'][index],
permission: '',
orderNo: index + 1,
createTime: '@datetime',
'status|1': ['0', '0', '1'],
children: (() => {
const children: any[] = [];
for (let j = 0; j < 4; j++) {
children.push({
id: `${index}-${j}`,
type: '1',
menuName: ['菜单1', '菜单2', '菜单3', '菜单4'][j],
icon: 'ion:document',
permission: ['menu1:view', 'menu2:add', 'menu3:update', 'menu4:del'][index],
component: [
'/dashboard/welcome/index',
'/dashboard/Analysis/index',
'/dashboard/workbench/index',
'/dashboard/test/index',
][j],
orderNo: j + 1,
createTime: '@datetime',
'status|1': ['0', '1'],
parentMenu: `${index}`,
children: (() => {
const children: any[] = [];
for (let k = 0; k < 4; k++) {
children.push({
id: `${index}-${j}-${k}`,
type: '2',
menuName: '按钮' + (j + 1) + '-' + (k + 1),
icon: '',
permission:
['menu1:view', 'menu2:add', 'menu3:update', 'menu4:del'][index] +
':btn' +
(k + 1),
component: [
'/dashboard/welcome/index',
'/dashboard/Analysis/index',
'/dashboard/workbench/index',
'/dashboard/test/index',
][j],
orderNo: j + 1,
createTime: '@datetime',
'status|1': ['0', '1'],
parentMenu: `${index}-${j}`,
children: undefined,
});
}
return children;
})(),
});
}
return children;
})(),
});
}
return result;
})();
export default [
{
url: `${baseUrl}/system/getAccountList`,
timeout: 100,
method: 'get',
response: ({ query }) => {
const { page = 1, pageSize = 20 } = query;
return resultPageSuccess(page, pageSize, accountList);
},
},
{
url: `${baseUrl}/sys/user/list`,
timeout: 100,
method: 'get',
response: ({ query }) => {
const { page = 1, pageSize = 20 } = query;
return resultPageSuccess(page, pageSize, userList);
},
},
{
url: `${baseUrl}/system/getRoleListByPage`,
timeout: 100,
method: 'get',
response: ({ query }) => {
const { page = 1, pageSize = 20 } = query;
return resultPageSuccess(page, pageSize, roleList);
},
},
{
url: `${baseUrl}/sys/role/list`,
timeout: 100,
method: 'get',
response: ({ query }) => {
const { page = 1, pageSize = 20 } = query;
return resultPageSuccess(page, pageSize, newRoleList);
},
},
{
url: `${baseUrl}/system/getTestListByPage`,
timeout: 100,
method: 'get',
response: ({ query }) => {
const { page = 1, pageSize = 20 } = query;
return resultPageSuccess(page, pageSize, testList);
},
},
{
url: `${baseUrl}/system/getDemoTableListByPage`,
timeout: 100,
method: 'get',
response: ({ query }) => {
const { page = 1, pageSize = 20 } = query;
return resultPageSuccess(page, pageSize, tableDemoList);
},
},
{
url: `${baseUrl}/system/setRoleStatus`,
timeout: 500,
method: 'post',
response: ({ query }) => {
const { id, status } = query;
return resultSuccess({ id, status });
},
},
{
url: `${baseUrl}/system/getAllRoleList`,
timeout: 100,
method: 'get',
response: () => {
return resultSuccess(roleList);
},
},
{
url: `${baseUrl}/system/getDeptList`,
timeout: 100,
method: 'get',
response: () => {
return resultSuccess(deptList);
},
},
{
url: `${baseUrl}/system/getMenuList`,
timeout: 100,
method: 'get',
response: () => {
return resultSuccess(menuList);
},
},
{
url: `${baseUrl}/system/accountExist`,
timeout: 500,
method: 'post',
response: ({ body }) => {
const { account } = body || {};
if (account && account.indexOf('admin') !== -1) {
return resultError('该字段不能包含admin');
} else {
return resultSuccess(`${account} can use`);
}
},
},
] as MockMethod[];

52
mock/demo/table-demo.ts

@ -0,0 +1,52 @@
import { MockMethod } from 'vite-plugin-mock';
import { Random } from 'mockjs';
import { resultPageSuccess, baseUrl } from '../_util';
function getRandomPics(count = 10): string[] {
const arr: string[] = [];
for (let i = 0; i < count; i++) {
arr.push(Random.image('800x600', Random.color(), Random.color(), Random.title()));
}
return arr;
}
const demoList = (() => {
const result: any[] = [];
for (let index = 0; index < 200; index++) {
result.push({
id: `${index}`,
beginTime: '@datetime',
endTime: '@datetime',
address: '@city()',
name: '@cname()',
name1: '@cname()',
name2: '@cname()',
name3: '@cname()',
name4: '@cname()',
name5: '@cname()',
name6: '@cname()',
name7: '@cname()',
name8: '@cname()',
avatar: Random.image('400x400', Random.color(), Random.color(), Random.first()),
imgArr: getRandomPics(Math.ceil(Math.random() * 3) + 1),
imgs: getRandomPics(Math.ceil(Math.random() * 3) + 1),
date: `@date('yyyy-MM-dd')`,
time: `@time('HH:mm')`,
'no|100000-10000000': 100000,
'status|1': ['normal', 'enable', 'disable'],
});
}
return result;
})();
export default [
{
url: `${baseUrl}/table/getDemoList`,
timeout: 100,
method: 'get',
response: ({ query }) => {
const { page = 1, pageSize = 20 } = query;
return resultPageSuccess(page, pageSize, demoList);
},
},
] as MockMethod[];

38
mock/demo/tree-demo.ts

@ -0,0 +1,38 @@
import { MockMethod } from 'vite-plugin-mock';
import { resultSuccess, baseUrl } from '../_util';
const demoTreeList = (keyword) => {
const result = {
list: [] as Recordable[],
};
for (let index = 0; index < 5; index++) {
const children: Recordable[] = [];
for (let j = 0; j < 3; j++) {
children.push({
title: `${keyword ?? ''}选项${index}-${j}`,
value: `${index}-${j}`,
key: `${index}-${j}`,
});
}
result.list.push({
title: `${keyword ?? ''}选项${index}`,
value: `${index}`,
key: `${index}`,
children,
});
}
return result;
};
export default [
{
url: `${baseUrl}/tree/getDemoOptions`,
timeout: 1000,
method: 'get',
response: ({ query }) => {
const { keyword } = query;
console.log(keyword);
return resultSuccess(demoTreeList(keyword));
},
},
] as MockMethod[];

270
mock/sys/menu.ts

@ -0,0 +1,270 @@
import { resultSuccess, resultError, getRequestToken, requestParams,baseUrl} from '../_util';
import { MockMethod } from 'vite-plugin-mock';
import { createFakeUserList } from './user';
// single
const dashboardRoute = {
path: '/dashboard',
name: 'Dashboard',
component: 'LAYOUT',
redirect: '/dashboard/analysis',
meta: {
title: 'routes.dashboard.dashboard',
hideChildrenInMenu: true,
icon: 'bx:bx-home',
},
children: [
{
path: 'analysis',
name: 'Analysis',
component: '/dashboard/Analysis/index',
meta: {
hideMenu: true,
hideBreadcrumb: true,
title: 'routes.dashboard.analysis',
currentActiveMenu: '/dashboard',
icon: 'bx:bx-home',
},
},
{
path: 'workbench',
name: 'Workbench',
component: '/dashboard/workbench/index',
meta: {
hideMenu: true,
hideBreadcrumb: true,
title: 'routes.dashboard.workbench',
currentActiveMenu: '/dashboard',
icon: 'bx:bx-home',
},
},
],
};
const backRoute = {
path: 'back',
name: 'PermissionBackDemo',
meta: {
title: 'routes.demo.permission.back',
},
children: [
{
path: 'page',
name: 'BackAuthPage',
component: '/demo/permission/back/index',
meta: {
title: 'routes.demo.permission.backPage',
},
},
{
path: 'btn',
name: 'BackAuthBtn',
component: '/demo/permission/back/Btn',
meta: {
title: 'routes.demo.permission.backBtn',
},
},
],
};
const authRoute = {
path: '/permission',
name: 'Permission',
component: 'LAYOUT',
redirect: '/permission/front/page',
meta: {
icon: 'carbon:user-role',
title: 'routes.demo.permission.permission',
},
children: [backRoute],
};
const levelRoute = {
path: '/level',
name: 'Level',
component: 'LAYOUT',
redirect: '/level/menu1/menu1-1',
meta: {
icon: 'carbon:user-role',
title: 'routes.demo.level.level',
},
children: [
{
path: 'menu1',
name: 'Menu1Demo',
meta: {
title: 'Menu1',
},
children: [
{
path: 'menu1-1',
name: 'Menu11Demo',
meta: {
title: 'Menu1-1',
},
children: [
{
path: 'menu1-1-1',
name: 'Menu111Demo',
component: '/demo/level/Menu111',
meta: {
title: 'Menu111',
},
},
],
},
{
path: 'menu1-2',
name: 'Menu12Demo',
component: '/demo/level/Menu12',
meta: {
title: 'Menu1-2',
},
},
],
},
{
path: 'menu2',
name: 'Menu2Demo',
component: '/demo/level/Menu2',
meta: {
title: 'Menu2',
},
},
],
};
const sysRoute = {
path: '/system',
name: 'System',
component: 'LAYOUT',
redirect: '/system/account',
meta: {
icon: 'ion:settings-outline',
title: 'routes.demo.system.moduleName',
},
children: [
{
path: 'account',
name: 'AccountManagement',
meta: {
title: 'routes.demo.system.account',
ignoreKeepAlive: true,
},
component: '/demo/system/account/index',
},
{
path: 'account_detail/:id',
name: 'AccountDetail',
meta: {
hideMenu: true,
title: 'routes.demo.system.account_detail',
ignoreKeepAlive: true,
showMenu: false,
currentActiveMenu: '/system/account',
},
component: '/demo/system/account/AccountDetail',
},
{
path: 'role',
name: 'RoleManagement',
meta: {
title: 'routes.demo.system.role',
ignoreKeepAlive: true,
},
component: '/demo/system/role/index',
},
{
path: 'menu',
name: 'MenuManagement',
meta: {
title: 'routes.demo.system.menu',
ignoreKeepAlive: true,
},
component: '/demo/system/menu/index',
},
{
path: 'dept',
name: 'DeptManagement',
meta: {
title: 'routes.demo.system.dept',
ignoreKeepAlive: true,
},
component: '/demo/system/dept/index',
},
{
path: 'changePassword',
name: 'ChangePassword',
meta: {
title: 'routes.demo.system.password',
ignoreKeepAlive: true,
},
component: '/demo/system/password/index',
},
],
};
const linkRoute = {
path: '/link',
name: 'Link',
component: 'LAYOUT',
meta: {
icon: 'ion:tv-outline',
title: 'routes.demo.iframe.frame',
},
children: [
{
path: 'doc',
name: 'Doc',
meta: {
title: 'routes.demo.iframe.doc',
frameSrc: 'https://vvbin.cn/doc-next/',
},
},
{
path: 'https://vvbin.cn/doc-next/',
name: 'DocExternal',
component: 'LAYOUT',
meta: {
title: 'routes.demo.iframe.docExternal',
},
},
],
};
export default [
{
url: `${baseUrl}/sys/permission/getUserPermissionByToken`,
timeout: 1000,
method: 'get',
response: (request: requestParams) => {
const token = getRequestToken(request);
if (!token) {
return resultError('Invalid token!');
}
const checkUser = createFakeUserList().find((item) => item.token === token);
if (!checkUser) {
return resultError('Invalid user token!');
}
const id = checkUser.userId;
let menu: Object[];
switch (id) {
case '1':
dashboardRoute.redirect = dashboardRoute.path + '/' + dashboardRoute.children[0].path;
menu = [dashboardRoute, authRoute, levelRoute, sysRoute, linkRoute];
break;
case '2':
dashboardRoute.redirect = dashboardRoute.path + '/' + dashboardRoute.children[1].path;
menu = [dashboardRoute, authRoute, levelRoute, linkRoute];
break;
default:
menu = [];
}
return resultSuccess(menu);
},
},
] as MockMethod[];

124
mock/sys/user.ts

@ -0,0 +1,124 @@
import { MockMethod } from 'vite-plugin-mock';
import { resultError, resultSuccess, getRequestToken, requestParams, baseUrl } from '../_util';
export function createFakeUserList() {
return [
{
userId: '1',
username: 'admin',
realname: '管理员',
avatar: 'https://q1.qlogo.cn/g?b=qq&nk=190848757&s=640',
desc: 'manager',
password: '123456',
token: 'fakeToken1',
homePath: '/dashboard/analysis',
roles: [
{
roleName: 'Super Admin',
value: 'super',
},
],
},
{
userId: '2',
username: 'jeecg',
password: '123456',
realname: '测试用户',
avatar: 'https://q1.qlogo.cn/g?b=qq&nk=339449197&s=640',
desc: 'tester',
token: 'fakeToken2',
homePath: '/dashboard/workbench',
roles: [
{
roleName: 'Tester',
value: 'test',
},
],
},
];
}
const fakeCodeList: any = {
'1': ['1000', '3000', '5000'],
'2': ['2000', '4000', '6000'],
};
export default [
// mock user login
{
url: `${baseUrl}/sys/login`,
timeout: 200,
method: 'post',
response: ({ body }) => {
const { username, password } = body;
const checkUser = createFakeUserList().find(
(item) => item.username === username && password === item.password
);
if (!checkUser) {
return resultError('Incorrect account or password!');
}
const { userId, username: _username, token, realname, desc, roles } = checkUser;
return resultSuccess({
roles,
userId,
username: _username,
token,
realname,
desc,
});
},
},
{
url: `${baseUrl}/sys/user/getUserInfo`,
method: 'get',
response: (request: requestParams) => {
const token = getRequestToken(request);
if (!token) return resultError('Invalid token');
const checkUser = createFakeUserList().find((item) => item.token === token);
if (!checkUser) {
return resultError('The corresponding user information was not obtained!');
}
return resultSuccess(checkUser);
},
},
{
url: `${baseUrl}/sys/permission/getPermCode`,
timeout: 200,
method: 'get',
response: (request: requestParams) => {
const token = getRequestToken(request);
if (!token) return resultError('Invalid token');
const checkUser = createFakeUserList().find((item) => item.token === token);
if (!checkUser) {
return resultError('Invalid token!');
}
const codeList = fakeCodeList[checkUser.userId];
return resultSuccess(codeList);
},
},
{
url: `${baseUrl}/sys/logout`,
timeout: 200,
method: 'get',
response: (request: requestParams) => {
const token = getRequestToken(request);
if (!token) return resultError('Invalid token');
const checkUser = createFakeUserList().find((item) => item.token === token);
if (!checkUser) {
return resultError('Invalid token!');
}
return resultSuccess(undefined, { message: 'Token has been destroyed' });
},
},
{
url: `${baseUrl}/sys/randomImage/1629428467008`,
timeout: 200,
method: 'get',
response: (request: requestParams) => {
const result =
'data:image/jpg;base64,/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAjAGkDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3h/ME5lErCKNSHi8rO44yCp65/P060gmdbbIaKecxl0VDsEmOmMk8cgZ96dcypFGpkEm0uOUzxznJI6DjnPH54ryTWNW1+P436T4ftNev4LTU7Brhw9tbCSHiZxGrNCcKCijkMeuSSOAD1KJ7hrTZNK0d1Iz7egGVPRSV6HGRkE4z1xV5SWQEqVJGSpxke3FeYL4n1PSfi5pXhK7vxrFlf27XVveyQRrcQHa4KFo1CMhMLdFUjfy2F59NjZm3Bl2kMRxnGO3JA7Y/HI7UAVrjfbWt3NJLNKmCwVAoaNcc4PHTk8+n5rKs1tDGtsdw5X94GkOT90ls5xnr14PYDNeUfDzxvq3xCuNZvG8SNp1zBKHtdFgtYpFjhAADuWXfKpJwwRkIwcFd6geg+Dm12Tw9bN4hkX+0Y5bmKcLGVV9s7KjLkA7dijBPLAgnJ5oWgGrb36zBtqyPh9oKwuvG4DncByCeeexPsLHm7jH5amSNxnzFI2gY479/bNVrxYZpRD57Q3JRkikRFLxlgfmUspGQEbrkccg8V5l8PfEOt6h4p8YW+r+JJf7M8OXZhjWWC2jjMQaZSZWWNSMLGDkFQD1BHFAHq7usMcksjnYoLHI+6AOen0pqllZfNkUMWZVUdG5yOvOcD+dcclt4j1/XlvtM8T3dn4cIc7kgt2a4PGwwBoTiLqfMZm34+VQpVz0Ou2t/eWfk2GrXGmTNxHcW9ukxV8EAOrqwKZIJ+6fl+8M0AXjHcb5GWdcN9xWjyF6ehGe/5j05jmdri3cxPJGI3YOAOXABGARnGTjkcjpwenmvwt8Y61czeIdM8b6g0esaW3mTR3SwQJFAB99dijcOpZySoBjI+8TXR+EtK16SNdR1rWL64WUNPaWtxbxQGBXbKCVY0VjKq/f525dgBxuKA6i4ZfsSEyq0R275Wm8v5f7wZe/TjgHNWqiiSWNEV5vNwp3MygFj68cAdeMen4y0wKk6Mtysp3yQsvktEoyPmI+YgnGB9O57dPIfGML3H7SnhaGO+msXfS2C3EIjLqcXPTzFZeenIPXjnFeyiIJIzx4XzH3SZBO75ccc8dF/L3zXHah4D0K58US+ILuLUPtcMeI5l1G5WT5i+VjYSDYCW2hVIHLDaMg0AX9K8FaVZ+IJPEVxPc6rrTAxLf3rqzRJgKURUVUToeQoPzNk8mt0qRJF5uTMVdBNGuAucHoScdByeOPcAxRw3MdzOpuC3nZkQiEBY8EcMf4sggfRT0qYQSJBJGJWlGwKodirZxjlxzzxzjIOfYAA8Tn+HehfErRoPGvhDUP7J1uQCaWK3YmJLpQWZT0aN95X5xxgBgp3ZPb/AAi8U6r4q8BRajriv9qW5khFy6hBcrkEOoCqAAW2cZ5Q85yBdtPAfhSTSv7Og0mWxiWH7PcQ288lq86Y2/vjEy+cCM8sW6t6mukt9PttNsobLTbC0gtY34gjURIgzuJVVGM55xxz3oAnZf8ASI38vcQrLu3fdBwenccfy96+abbwjqHiu8+K1lpt/NFJBqYlW1MwSO5KzzECRmBJwA2ASBuKljxkfSF9ai7jeESzRtJGy5R3UAdCcoVIOGOCCD36qMc9oHgHw/oGrSalpMd1a3DuWnRb6Z1lYr/y2VnYOw3sQT03Z96AMn4W+PP+Et0xrLVZmi8TaerRX9pJH5Rba2BIE9egbGMMSCACtdxOHuYmXy3CCVRjIHmLkbs5HTrx3A9DXJN8LvCraj/adpa3SajtZBqC6rdGaMhdgw3mZOB8uMjgY9q39X0Sx1myuLLUknWwbLSLDdyQrKGUhgxRlOPvZUnac5OT0AseQfEHT7u71CP4keHrbTZJtFSGWQ/Zmk+3gMytMByDGm0BXwrbVdwwVYmPqXhvxDZeKdEj1bRL6AWM42NvT9/DLtVQkmWOXBx16jbjIINGl+GdPs9I/seG6nSAfIY7e/n3qqEBVSQuZI1A25RWABOOhO7P8NeA/DejRveaBpb2IuW2k/bJmDxjIDlJNyk4LYyOjHBGaAOwjeQogYxtIuBNtbhTjPH6cHsalqlbWMFrcSNuVnkkeZAwG5c/eI79wOO2O+SbtABSMiuMMoYZBwRnkHIP50UUALRRRQAUUUUAFFFFACBVUsVUAscsQOpxjn8AKWiigBFVUQIihVUYAAwAKY8EUkqSOgZ0BCk9uQf5qD+FFFAElFFFAH//2Q==';
return resultSuccess(result);
},
},
] as MockMethod[];

0
npm

43976
package-lock.json

File diff suppressed because it is too large

357
package.json

@ -0,0 +1,357 @@
{
"name": "jeecgboot-vue3",
"version": "3.5.1",
"author": {
"name": "jeecg",
"email": "jeecgos@163.com",
"url": "https://github.com/jeecgboot/jeecgboot-vue3"
},
"main": "electron/electron.js",
"build": {
"appId": "com.my-website.my-app",
"productName": "MyApp",
"copyright": "Copyright © 2022 ${author}",
"mac": {
"category": "public.app-category.utilities"
},
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true
},
"files": [
"dist/**/*",
"electron/**/*"
],
"extraResources": [
"./_app.config.js"
],
"directories": {
"buildResources": "assets",
"output": "dist_electron"
},
"electronDownload": {
"mirror": "https://npm.taobao.org/mirrors/electron/"
}
},
"scripts": {
"electron:serve": "cross-env IS_DEV=true electron .",
"electron:start": "npm run dev & npm run electron:serve",
"electron:dev": "concurrently \"npm run dev\" \"npm run electron:serve\" ",
"electron:build.win": "npm run build && electron-builder --win --dir",
"electron:builder": "electron-builder --win --dir",
"bootstrap": "pnpm install",
"serve": "npm run dev",
"dev": "vite",
"clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite",
"clean:lib": "rimraf node_modules",
"build": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=8192 vite build && esno ./build/script/postBuild.ts",
"build:test": "cross-env NODE_OPTIONS=--max-old-space-size=8192 vite build --mode test && esno ./build/script/postBuild.ts",
"build:no-cache": "pnpm clean:cache && npm run build",
"report": "cross-env REPORT=true npm run build",
"type:check": "vue-tsc --noEmit --skipLibCheck",
"preview": "npm run build && vite preview",
"preview:dist": "vite preview",
"log": "conventional-changelog -p angular -i CHANGELOG.md -s",
"lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
"lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
"lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
"lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js",
"lint:pretty": "pretty-quick --staged",
"test:unit": "jest",
"test:unit-coverage": "jest --coverage",
"test:gzip": "http-server dist --cors --gzip -c-1",
"test:br": "http-server dist --cors --brotli -c-1",
"reinstall": "rimraf pnpm-lock.yaml && yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
"prepare": "husky install",
"gen:icon": "esno ./build/generate/icon/index.ts"
},
"dependencies": {
"@ant-design/colors": "^6.0.0",
"@ant-design/icons-vue": "^6.1.0",
"@easydarwin/easyplayer": "^5.0.7",
"@iconify/iconify": "^2.2.1",
"@jeecg/online": "3.4.4-RC",
"@logicflow/core": "^1.1.13",
"@logicflow/extension": "^1.1.13",
"@vue/compiler-ssr": "^3.3.4",
"@vue/runtime-core": "^3.2.33",
"@vue/server-renderer": "^3.3.4",
"@vue/shared": "^3.2.33",
"@vueuse/core": "^8.3.0",
"@vueuse/shared": "^8.3.0",
"@zxcvbn-ts/core": "^2.0.1",
"ant-design-vue": "^3.2.12",
"autofit.js": "^3.0.4",
"axios": "^0.26.1",
"china-area-data": "^5.0.1",
"clipboard": "^2.0.8",
"codemirror": "^5.65.3",
"concurrently": "^8.2.2",
"cron-parser": "^3.5.0",
"cropperjs": "^1.5.12",
"crypto-js": "^4.1.1",
"dayjs": "^1.11.1",
"dom-align": "^1.12.2",
"earthsdk": "^1.7.16",
"echarts": "^5.3.2",
"electron-packager": "^17.1.2",
"emoji-mart-vue-fast": "^11.1.1",
"enquire.js": "^2.1.6",
"intro.js": "^5.1.0",
"jquery": "^3.7.0",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"lodash.get": "^4.4.2",
"md5": "^2.3.0",
"mitt": "^3.0.1",
"mockjs": "^1.1.0",
"moment": "^2.29.4",
"nprogress": "^0.2.0",
"particles.vue3": "^2.11.0",
"path-to-regexp": "^6.2.0",
"pinia": "2.0.12",
"pinyin-pro": "^3.11.0",
"print-js": "^1.6.0",
"qrcode": "^1.5.0",
"qrcodejs2": "0.0.2",
"qs": "^6.10.3",
"resize-observer-polyfill": "^1.5.1",
"serve": "^14.2.1",
"showdown": "^2.1.0",
"sortablejs": "^1.15.0",
"tinymce": "^5.10.3",
"tsparticles": "^2.11.0",
"v-scale-screen": "^2.2.0",
"vditor": "^3.8.13",
"vue": "^3.2.33",
"vue-cesium": "^3.2.2",
"vue-class-component": "^8.0.0-0",
"vue-cropper": "^0.5.6",
"vue-cropperjs": "^5.0.0",
"vue-i18n": "^9.1.9",
"vue-infinite-scroll": "^2.0.2",
"vue-json-pretty": "^2.0.6",
"vue-print-nb-jeecg": "^1.0.12",
"vue-router": "^4.0.14",
"vue-types": "^4.1.1",
"vue3-colorpicker": "^2.2.2",
"vue3-seamless-scroll": "^2.0.1",
"vuedraggable": "^4.1.0",
"vxe-table": "4.1.0",
"vxe-table-plugin-antd": "3.0.5",
"wait-on": "^7.0.1",
"xe-utils": "^3.3.1",
"xss": "^1.0.13"
},
"devDependencies": {
"@commitlint/cli": "^16.2.3",
"@commitlint/config-conventional": "^16.2.1",
"@iconify/json": "^2.1.30",
"@purge-icons/generated": "^0.8.1",
"@rys-fe/vite-plugin-theme": "^0.8.6",
"@types/codemirror": "^5.60.5",
"@types/crypto-js": "^4.1.1",
"@types/fs-extra": "^9.0.13",
"@types/inquirer": "^8.2.1",
"@types/intro.js": "^3.0.2",
"@types/jest": "^27.0.2",
"@types/lodash-es": "^4.17.6",
"@types/mockjs": "^1.0.6",
"@types/node": "^17.0.25",
"@types/nprogress": "^0.2.0",
"@types/pinyin": "^2.10.0",
"@types/qrcode": "^1.4.2",
"@types/qs": "^6.9.7",
"@types/showdown": "^1.9.4",
"@types/sortablejs": "^1.10.7",
"@typescript-eslint/eslint-plugin": "^5.20.0",
"@typescript-eslint/parser": "^5.20.0",
"@vitejs/plugin-legacy": "^2.0.0",
"@vitejs/plugin-vue": "^3.0.1",
"@vitejs/plugin-vue-jsx": "^1.3.10",
"@vue/compiler-sfc": "^3.2.33",
"@vue/test-utils": "^2.0.0-rc.21",
"autoprefixer": "^10.4.4",
"commitizen": "^4.2.4",
"conventional-changelog-cli": "^2.2.2",
"cross-env": "^7.0.3",
"cz-git": "^1.3.9",
"czg": "^1.3.9",
"dotenv": "^16.0.0",
"electron": "^27.0.2",
"electron-builder": "^24.6.4",
"eslint": "^8.22.0",
"eslint-config-prettier": "^8.6.0",
"eslint-define-config": "^1.14.0",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-vue": "^9.9.0",
"esno": "^0.14.1",
"fs-extra": "^10.1.0",
"http-server": "^14.0.0",
"husky": "^7.0.4",
"inquirer": "^8.2.2",
"is-ci": "^3.0.0",
"jest": "^27.3.1",
"less": "^4.1.2",
"lint-staged": "12.3.7",
"npm-run-all": "^4.1.5",
"picocolors": "^1.0.0",
"postcss": "^8.4.12",
"postcss-html": "^1.4.1",
"postcss-less": "^6.0.0",
"prettier": "^2.6.2",
"pretty-quick": "^3.1.1",
"rimraf": "^3.0.2",
"rollup": "^2.70.2",
"rollup-plugin-visualizer": "^5.6.0",
"stylelint": "^14.7.1",
"stylelint-config-prettier": "^9.0.3",
"stylelint-config-recommended": "^7.0.0",
"stylelint-config-recommended-vue": "^1.4.0",
"stylelint-config-standard": "^25.0.0",
"stylelint-order": "^5.0.0",
"ts-jest": "^27.0.7",
"ts-node": "^10.7.0",
"typescript": "^4.6.3",
"vite": "^3.0.2",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.2.0",
"vite-plugin-imagemin": "^0.6.1",
"vite-plugin-mkcert": "^1.10.1",
"vite-plugin-mock": "^2.9.6",
"vite-plugin-optimize-persist": "^0.1.2",
"vite-plugin-package-config": "^0.1.1",
"vite-plugin-purge-icons": "^0.8.2",
"vite-plugin-pwa": "^0.12.3",
"vite-plugin-style-import": "^2.0.0",
"vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-vue-setup-extend": "^0.4.0",
"vite-plugin-windicss": "^1.8.7",
"vue-eslint-parser": "^8.3.0",
"vue-tsc": "^0.33.9"
},
"resolutions": {
"bin-wrapper": "npm:bin-wrapper-china",
"rollup": "^2.72.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/jeecgboot/jeecgboot-vue3.git"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/jeecgboot/jeecgboot-vue3/issues"
},
"homepage": "https://github.com/jeecgboot/jeecgboot-vue3",
"engines": {
"node": "^12 || >=14"
},
"vite": {
"optimizeDeps": {
"include": [
"@ant-design/colors",
"@ant-design/icons-vue",
"@vueuse/core",
"@vueuse/shared",
"@zxcvbn-ts/core",
"ant-design-vue",
"axios",
"china-area-data",
"clipboard",
"codemirror",
"codemirror/addon/fold/brace-fold.js",
"codemirror/addon/fold/comment-fold.js",
"codemirror/addon/fold/foldcode.js",
"codemirror/addon/fold/foldgutter.js",
"codemirror/addon/fold/indent-fold.js",
"codemirror/addon/hint/anyword-hint.js",
"codemirror/addon/hint/show-hint.js",
"codemirror/addon/selection/active-line.js",
"codemirror/mode/clike/clike.js",
"codemirror/mode/css/css.js",
"codemirror/mode/javascript/javascript.js",
"codemirror/mode/markdown/markdown.js",
"codemirror/mode/python/python.js",
"codemirror/mode/r/r.js",
"codemirror/mode/shell/shell.js",
"codemirror/mode/sql/sql.js",
"codemirror/mode/swift/swift.js",
"codemirror/mode/vue/vue.js",
"codemirror/mode/xml/xml.js",
"cron-parser",
"cropperjs",
"crypto-js/aes",
"crypto-js/enc-base64",
"crypto-js/enc-utf8",
"crypto-js/md5",
"crypto-js/mode-ecb",
"crypto-js/pad-pkcs7",
"dom-align",
"echarts",
"echarts/charts",
"echarts/components",
"echarts/core",
"echarts/renderers",
"emoji-mart-vue-fast/src",
"intro.js",
"lodash-es",
"md5",
"nprogress",
"path-to-regexp",
"pinia",
"print-js",
"qrcode",
"qs",
"resize-observer-polyfill",
"showdown",
"sortablejs",
"tinymce/icons/default/icons",
"tinymce/plugins/advlist",
"tinymce/plugins/anchor",
"tinymce/plugins/autolink",
"tinymce/plugins/autosave",
"tinymce/plugins/code",
"tinymce/plugins/codesample",
"tinymce/plugins/contextmenu",
"tinymce/plugins/directionality",
"tinymce/plugins/fullscreen",
"tinymce/plugins/hr",
"tinymce/plugins/image",
"tinymce/plugins/insertdatetime",
"tinymce/plugins/link",
"tinymce/plugins/lists",
"tinymce/plugins/media",
"tinymce/plugins/nonbreaking",
"tinymce/plugins/noneditable",
"tinymce/plugins/pagebreak",
"tinymce/plugins/paste",
"tinymce/plugins/preview",
"tinymce/plugins/print",
"tinymce/plugins/save",
"tinymce/plugins/searchreplace",
"tinymce/plugins/spellchecker",
"tinymce/plugins/tabfocus",
"tinymce/plugins/table",
"tinymce/plugins/template",
"tinymce/plugins/textcolor",
"tinymce/plugins/textpattern",
"tinymce/plugins/visualblocks",
"tinymce/plugins/visualchars",
"tinymce/plugins/wordcount",
"tinymce/themes/silver",
"tinymce/tinymce",
"vditor",
"vue",
"vue-i18n",
"vue-print-nb-jeecg/src/printarea",
"vue-router",
"vue-types",
"vxe-table",
"vxe-table-plugin-antd",
"xe-utils",
"xss"
]
}
}
}

16804
pnpm-lock.yaml

File diff suppressed because it is too large

5
postcss.config.js

@ -0,0 +1,5 @@
module.exports = {
plugins: {
autoprefixer: {},
},
};

20
prettier.config.js

@ -0,0 +1,20 @@
module.exports = {
printWidth: 150,
tabWidth: 2,
useTabs: false,
semi: true, //语句末尾使用分号
vueIndentScriptAndStyle: true,
singleQuote: true, // 使用单引号
quoteProps: 'as-needed',
bracketSpacing: true,
trailingComma: 'es5',
jsxBracketSameLine: false,
jsxSingleQuote: false,
arrowParens: 'always',
insertPragma: false,
requirePragma: false,
proseWrap: 'never',
htmlWhitespaceSensitivity: 'strict',
endOfLine: 'auto',
rangeStart: 0,
};

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_0.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_1.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_10.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_11.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_12.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_13.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_14.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_15.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_16.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_17.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_18.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_19.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_2.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_20.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_21.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_22.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_23.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_24.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_25.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_26.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_27.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_3.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_4.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_5.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_6.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_7.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_8.json

File diff suppressed because one or more lines are too long

1
public/earthsdk/XbsjCesium/Assets/IAU2006_XYS/IAU2006_XYS_9.json

File diff suppressed because one or more lines are too long

BIN
public/earthsdk/XbsjCesium/Assets/Images/bing_maps_credit.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Images/cesium_credit.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Images/google_earth_credit.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Images/ion-credit.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Textures/LensFlare/DirtMask.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Textures/LensFlare/StarBurst.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/0/0/0.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/0/1/0.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/1/0/0.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/1/0/1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/1/1/0.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/1/1/1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/1/2/0.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/1/2/1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/1/3/0.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/1/3/1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/2/0/0.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/2/0/1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
public/earthsdk/XbsjCesium/Assets/Textures/NaturalEarthII/2/0/2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

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

Loading…
Cancel
Save