Browse Source

upgrade: upgrade vben to 2.8.0

pull/648/head
cKey 3 years ago
parent
commit
7c00e03a5b
  1. 2
      apps/vue/.eslintignore
  2. 14
      apps/vue/.eslintrc.js
  3. 17
      apps/vue/.github/workflows/issue-close-require.yml
  4. 29
      apps/vue/.github/workflows/issue-labeled.yml
  5. 24
      apps/vue/.github/workflows/release.yml
  6. 2
      apps/vue/.gitignore
  7. 4
      apps/vue/.gitpod.yml
  8. 8
      apps/vue/.husky/pre-commit
  9. 109
      apps/vue/README.md
  10. 175
      apps/vue/README.zh-CN.md
  11. 4
      apps/vue/build/generate/icon/index.ts
  12. 11
      apps/vue/build/script/buildConf.ts
  13. 6
      apps/vue/build/script/postBuild.ts
  14. 6
      apps/vue/build/vite/plugin/compress.ts
  15. 6
      apps/vue/build/vite/plugin/html.ts
  16. 16
      apps/vue/build/vite/plugin/index.ts
  17. 15
      apps/vue/build/vite/plugin/styleImport.ts
  18. 4
      apps/vue/build/vite/plugin/svgSprite.ts
  19. 6
      apps/vue/build/vite/plugin/theme.ts
  20. 74
      apps/vue/commitlint.config.js
  21. 21
      apps/vue/index.html
  22. 325
      apps/vue/mock/demo/api-cascader.ts
  23. 28
      apps/vue/mock/demo/select-demo.ts
  24. 202
      apps/vue/mock/demo/system.ts
  25. 52
      apps/vue/mock/demo/table-demo.ts
  26. 38
      apps/vue/mock/demo/tree-demo.ts
  27. 8
      apps/vue/mock/sys/user.ts
  28. 197
      apps/vue/package.json
  29. 1
      apps/vue/src/App.vue
  30. 19
      apps/vue/src/api/account/accounts.ts
  31. 7
      apps/vue/src/api/account/model/profilesModel.ts
  32. 11
      apps/vue/src/api/account/profiles.ts
  33. 89
      apps/vue/src/api/api-gateway/aggregate.ts
  34. 26
      apps/vue/src/api/api-gateway/basic.ts
  35. 66
      apps/vue/src/api/api-gateway/global.ts
  36. 73
      apps/vue/src/api/api-gateway/group.ts
  37. 46
      apps/vue/src/api/api-gateway/model/aggregateModel.ts
  38. 80
      apps/vue/src/api/api-gateway/model/basicModel.ts
  39. 39
      apps/vue/src/api/api-gateway/model/globalModel.ts
  40. 38
      apps/vue/src/api/api-gateway/model/groupModel.ts
  41. 70
      apps/vue/src/api/api-gateway/model/routeModel.ts
  42. 70
      apps/vue/src/api/api-gateway/route.ts
  43. 56
      apps/vue/src/api/caching-management/cache/index.ts
  44. 23
      apps/vue/src/api/caching-management/cache/model/index.ts
  45. 12
      apps/vue/src/api/demo/error.ts
  46. 16
      apps/vue/src/api/identity/model/claimModel.ts
  47. 19
      apps/vue/src/api/identity/model/roleModel.ts
  48. 18
      apps/vue/src/api/identity/model/userModel.ts
  49. 10
      apps/vue/src/api/identity/organization-units.ts
  50. 13
      apps/vue/src/api/identity/role.ts
  51. 11
      apps/vue/src/api/identity/user.ts
  52. 52
      apps/vue/src/api/localization/languages.ts
  53. 5
      apps/vue/src/api/localization/model/resourcesModel.ts
  54. 17
      apps/vue/src/api/localization/model/textsModel.ts
  55. 52
      apps/vue/src/api/localization/resources.ts
  56. 43
      apps/vue/src/api/localization/texts.ts
  57. 21
      apps/vue/src/api/messages/notifications.ts
  58. 1
      apps/vue/src/api/multi-tenancy/models/tenantModel.ts
  59. 71
      apps/vue/src/api/openiddict/applications/index.ts
  60. 47
      apps/vue/src/api/openiddict/applications/model/index.ts
  61. 51
      apps/vue/src/api/openiddict/authorizations/index.ts
  62. 21
      apps/vue/src/api/openiddict/authorizations/model/index.ts
  63. 61
      apps/vue/src/api/openiddict/scopes/index.ts
  64. 29
      apps/vue/src/api/openiddict/scopes/model/index.ts
  65. 68
      apps/vue/src/api/openiddict/tokens/index.ts
  66. 29
      apps/vue/src/api/openiddict/tokens/model/index.ts
  67. 3
      apps/vue/src/api/sys/model/menuModel.ts
  68. 2
      apps/vue/src/api/sys/model/userModel.ts
  69. 2
      apps/vue/src/api/sys/user.ts
  70. 51
      apps/vue/src/api/task-management/backgroundJobAction.ts
  71. 10
      apps/vue/src/api/task-management/backgroundJobInfo.ts
  72. 43
      apps/vue/src/api/task-management/model/backgroundJobActionModel.ts
  73. 14
      apps/vue/src/api/task-management/model/backgroundJobInfoModel.ts
  74. 64
      apps/vue/src/api/text-templating/templates/index.ts
  75. 36
      apps/vue/src/api/text-templating/templates/model/index.ts
  76. 4
      apps/vue/src/components/Application/src/AppLocalePicker.vue
  77. 5
      apps/vue/src/components/Application/src/search/AppSearchModal.vue
  78. 166
      apps/vue/src/components/CardList/src/CardList.vue
  79. 2
      apps/vue/src/components/CardList/src/data.ts
  80. 2
      apps/vue/src/components/CodeEditor/index.ts
  81. 10
      apps/vue/src/components/CodeEditor/src/codemirror/codemirror.css
  82. 137
      apps/vue/src/components/CodeEditor/src/codemirrorX/CodeMirrorX.vue
  83. 1
      apps/vue/src/components/CodeEditor/src/json-preview/JsonPreview.vue
  84. 11
      apps/vue/src/components/Container/src/collapse/CollapseContainer.vue
  85. 22
      apps/vue/src/components/ContextMenu/src/ContextMenu.vue
  86. 1
      apps/vue/src/components/ContextMenu/src/typing.ts
  87. 7
      apps/vue/src/components/CountDown/src/CountdownInput.vue
  88. 2
      apps/vue/src/components/Cropper/src/CropperAvatar.vue
  89. 5
      apps/vue/src/components/Description/src/Description.vue
  90. 2
      apps/vue/src/components/Drawer/src/BasicDrawer.vue
  91. 2
      apps/vue/src/components/Drawer/src/components/DrawerFooter.vue
  92. 3
      apps/vue/src/components/Drawer/src/typing.ts
  93. 2
      apps/vue/src/components/Excel/src/Export2Excel.ts
  94. 3
      apps/vue/src/components/Excel/src/ExportExcelModal.vue
  95. 2
      apps/vue/src/components/Excel/src/ImportExcel.vue
  96. 1
      apps/vue/src/components/Form/index.ts
  97. 18
      apps/vue/src/components/Form/src/BasicForm.vue
  98. 43
      apps/vue/src/components/Form/src/TabForm.vue
  99. 4
      apps/vue/src/components/Form/src/componentMap.ts
  100. 5
      apps/vue/src/components/Form/src/components/ApiCascader.vue

2
apps/vue/.eslintignore

@ -13,4 +13,4 @@ dist
.local
/bin
Dockerfile
src/
src/

14
apps/vue/.eslintrc.js

@ -1,6 +1,4 @@
// @ts-check
const { defineConfig } = require('eslint-define-config');
module.exports = defineConfig({
module.exports = {
root: true,
env: {
browser: true,
@ -20,9 +18,7 @@ module.exports = defineConfig({
extends: [
'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
'plugin:prettier/recommended',
'plugin:jest/recommended',
],
rules: {
'vue/script-setup-uses-vars': 'error',
@ -55,8 +51,6 @@ module.exports = defineConfig({
'space-before-function-paren': 'off',
'vue/attributes-order': 'off',
'vue/v-on-event-hyphenation': 'off',
'vue/multi-word-component-names': 'off',
'vue/one-component-per-file': 'off',
'vue/html-closing-bracket-newline': 'off',
'vue/max-attributes-per-line': 'off',
@ -64,8 +58,7 @@ module.exports = defineConfig({
'vue/singleline-html-element-content-newline': 'off',
'vue/attribute-hyphenation': 'off',
'vue/require-default-prop': 'off',
'jest/no-commented-out-tests': 'warn',
'function-url-quotes': 'off',
'vue/require-explicit-emits': 'off',
'vue/html-self-closing': [
'error',
{
@ -78,5 +71,6 @@ module.exports = defineConfig({
math: 'always',
},
],
'vue/multi-word-component-names': 'off',
},
});
};

17
apps/vue/.github/workflows/issue-close-require.yml

@ -0,0 +1,17 @@
name: Issue Close Require
on:
schedule:
- cron: '0 0 * * *'
jobs:
close-issues:
runs-on: ubuntu-latest
steps:
- name: need reproduction
uses: actions-cool/issues-helper@v2.1.1
with:
actions: 'close-issues'
token: ${{ secrets.OPER_TOKEN }}
labels: 'need reproduction'
inactive-day: 3

29
apps/vue/.github/workflows/issue-labeled.yml

@ -0,0 +1,29 @@
name: Issue Labeled
on:
issues:
types: [labeled]
jobs:
reply-labeled:
runs-on: ubuntu-latest
steps:
- name: remove pending
if: github.event.label.name == 'enhancement' || github.event.label.name == 'bug'
uses: actions-cool/issues-helper@v2.1.1
with:
actions: 'remove-labels'
token: ${{ secrets.OPER_TOKEN }}
issue-number: ${{ github.event.issue.number }}
labels: 'bug: pending triage'
- name: need reproduction
if: github.event.label.name == 'need reproduction'
uses: actions-cool/issues-helper@v2.1.1
with:
actions: 'create-comment, remove-labels'
token: ${{ secrets.OPER_TOKEN }}
issue-number: ${{ github.event.issue.number }}
body: |
Hello @${{ github.event.issue.user.login }}. Please provide the complete reproduction steps and code. Issues labeled by `need reproduction` will be closed if no activities in 3 days.
labels: 'bug: pending triage'

24
apps/vue/.github/workflows/release.yml

@ -0,0 +1,24 @@
name: Create Release
on:
push:
tags:
- v*
jobs:
build:
name: Create Release
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@master
- name: Create Release for Tag
id: release_tag
uses: yyx990803/release-tag@master
env:
GITHUB_TOKEN: ${{ secrets.OPER_TOKEN }}
with:
tag_name: ${{ github.ref }}
body: |
Please refer to [CHANGELOG.md](https://github.com/anncwb/vue-vben-admin/blob/main/CHANGELOG.md) for details.

2
apps/vue/.gitignore

@ -4,6 +4,7 @@ dist
.npmrc
.cache
yarn.lock
pnpm-lock.yaml
tests/server/static
tests/server/static/upload
@ -28,3 +29,4 @@ pnpm-debug.log*
*.njsproj
*.sln
*.sw?
/package-lock.json

4
apps/vue/.gitpod.yml

@ -2,5 +2,5 @@ ports:
- port: 3344
onOpen: open-preview
tasks:
- init: yarn
command: yarn dev
- init: pnpm install
command: pnpm run dev

8
apps/vue/.husky/pre-commit

@ -1,8 +1,8 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
. "$(dirname "$0")/common.sh"
#. "$(dirname "$0")/_/husky.sh"
#. "$(dirname "$0")/common.sh"
[ -n "$CI" ] && exit 0
#[ -n "$CI" ] && exit 0
# Format and submit code according to lintstagedrc.js configuration
npm run lint:lint-staged
# npm run lint:lint-staged

109
apps/vue/README.md

@ -79,104 +79,99 @@ git clone https://github.com/anncwb/vue-vben-admin.git
```bash
cd vue-vben-admin
yarn install
pnpm install
```
- 运行
- run
```bash
yarn serve
pnpm serve
```
- 打包
- build
```bash
yarn build
pnpm build
```
## 更新日志
## Change Log
[CHANGELOG](./CHANGELOG.zh_CN.md)
## 项目地址
## Project
- [vue-vben-admin](https://github.com/anncwb/vue-vben-admin) - 完整版
- [vue-vben-admin-thin-next](https://github.com/anncwb/vben-admin-thin-next) - 简化版
- [vue-vben-admin](https://github.com/anncwb/vue-vben-admin) - full version
- [vue-vben-admin-thin-next](https://github.com/anncwb/vben-admin-thin-next) - Simplified version
## 如何贡献
## How to contribute
非常欢迎你的加入![提一个 Issue](https://github.com/anncwb/vue-vben-admin/issues/new/choose) 或者提交一个 Pull Request。
You are very welcome to join![Raise an issue](https://github.com/anncwb/vue-vben-admin/issues/new/choose) Or submit a Pull Request。
**Pull Request:**
1. Fork 代码!
2. 创建自己的分支: `git checkout -b feat/xxxx`
3. 提交你的修改: `git commit -am 'feat(function): add xxxxx'`
4. 推送您的分支: `git push origin feat/xxxx`
5. 提交`pull request`
1. Fork code!
2. Create your own branch: `git checkout -b feat/xxxx`
3. Submit your changes: `git commit -am 'feat(function): add xxxxx'`
4. Push your branch: `git push origin feat/xxxx`
5. submit`pull request`
## Git 贡献提交规范
## Git Contribution submission specification
- 参考 [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) 规范 ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
- reference [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) specification ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
- `feat` 增加新功能
- `fix` 修复问题/BUG
- `style` 代码风格相关无影响运行结果的
- `perf` 优化/性能提升
- `refactor` 重构
- `revert` 撤销修改
- `test` 测试相关
- `docs` 文档/注释
- `chore` 依赖更新/脚手架配置修改等
- `workflow` 工作流改进
- `ci` 持续集成
- `types` 类型定义文件更改
- `wip` 开发中
- `feat` Add new features
- `fix` Fix the problem/BUG
- `style` The code style is related and does not affect the running result
- `perf` Optimization/performance improvement
- `refactor` Refactor
- `revert` Undo edit
- `test` Test related
- `docs` Documentation/notes
- `chore` Dependency update/scaffolding configuration modification etc.
- `workflow` Workflow improvements
- `ci` Continuous integration
- `types` Type definition file changes
- `wip` In development
## 浏览器支持
## Related warehouse
本地开发推荐使用`Chrome 80+` 浏览器
If these plugins are helpful to you, you can give a star support
支持现代浏览器, 不支持 IE
- [vite-plugin-mock](https://github.com/anncwb/vite-plugin-mock) - Used for local and development environment data mock
- [vite-plugin-html](https://github.com/anncwb/vite-plugin-html) - Used for html template conversion and compression
- [vite-plugin-style-import](https://github.com/anncwb/vite-plugin-style-import) - Used for component library style introduction on demand
- [vite-plugin-theme](https://github.com/anncwb/vite-plugin-theme) - Used for online switching of theme colors and other color-related configurations
- [vite-plugin-imagemin](https://github.com/anncwb/vite-plugin-imagemin) - Used to pack compressed image resources
- [vite-plugin-compression](https://github.com/anncwb/vite-plugin-compression) - Used to pack input .gz|.brotil files
- [vite-plugin-svg-icons](https://github.com/anncwb/vite-plugin-svg-icons) - Used to quickly generate svg sprite
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| :-: | :-: | :-: | :-: | :-: |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## 相关仓库
如果这些插件对你有帮助,可以给一个 star 支持下
## Browser support
- [vite-plugin-mock](https://github.com/anncwb/vite-plugin-mock) - 用于本地及开发环境数据 mock
- [vite-plugin-html](https://github.com/anncwb/vite-plugin-html) - 用于 html 模版转换及压缩
- [vite-plugin-style-import](https://github.com/anncwb/vite-plugin-style-import) - 用于组件库样式按需引入
- [vite-plugin-theme](https://github.com/anncwb/vite-plugin-theme) - 用于在线切换主题色等颜色相关配置
- [vite-plugin-imagemin](https://github.com/anncwb/vite-plugin-imagemin) - 用于打包压缩图片资源
- [vite-plugin-compression](https://github.com/anncwb/vite-plugin-compression) - 用于打包输出.gz|.brotil 文件
- [vite-plugin-svg-icons](https://github.com/anncwb/vite-plugin-svg-icons) - 用于快速生成 svg 雪碧图
The `Chrome 80+` browser is recommended for local development
## 后台整合示例
Support modern browsers, not IE
- [lamp-cloud](https://github.com/zuihou/lamp-cloud) - 基于 SpringCloud Alibaba 的微服务中后台快速开发平台
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| :-: | :-: | :-: | :-: | :-: |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## 维护者
## Maintainer
[@Vben](https://github.com/anncwb)
## 捐赠
## Donate
如果你觉得这个项目对你有帮助,你可以帮作者买一杯咖啡表示支持!
If you think this project is helpful to you, you can help the author buy a cup of coffee to show your support!
![donate](https://anncwb.github.io/anncwb/images/sponsor.png)
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aed;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
## 交流
`Vue-vben-Admin` 是完全开源免费的项目,在帮助开发者更方便地进行中大型管理系统开发,同时也提供 QQ 交流群使用问题欢迎在群内提问。
## Discord
- QQ 群 `569291866`
- [github discussions](https://github.com/anncwb/vue-vben-admin/discussions)
- [Discord](https://discord.gg/8GuAdwDhj6)
## License

175
apps/vue/README.zh-CN.md

@ -0,0 +1,175 @@
<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="200" height="200" src="https://anncwb.github.io/anncwb/images/logo.png"> </a> <br> <br>
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
<h1>Vue vben admin</h1>
</div>
**中文** | [English](./README.md)
## 简介
Vue Vben Admin 是一个免费开源的中后台模版。使用了最新的`vue3`,`vite2`,`TypeScript`等主流技术开发,开箱即用的中后台前端解决方案,也可用于学习参考。
## 特性
- **最新技术栈**:使用 Vue3/vite2 等前端前沿技术开发
- **TypeScript**: 应用程序级 JavaScript 的语言
- **主题**:可配置的主题
- **国际化**:内置完善的国际化方案
- **Mock 数据** 内置 Mock 数据方案
- **权限** 内置完善的动态路由权限生成方案
- **组件** 二次封装了多个常用的组件
## 预览
- [vue-vben-admin](https://vvbin.cn/next/) - 完整版中文站点
- [vue-vben-admin-gh-pages](https://anncwb.github.io/vue-vben-admin/) - 完整版 github 站点
- [vben-admin-thin-next](https://vvbin.cn/thin/next/) - 简化版中文站点
- [vben-admin-thin-gh-pages](https://anncwb.github.io/vben-admin-thin-next/) - 简化版 github 站点
测试账号: vben/123456
<p align="center">
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview1.png">
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview2.png">
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
</p>
### 使用 Gitpod
在 Gitpod(适用于 GitHub 的免费在线开发环境)中打开项目,并立即开始编码.
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/anncwb/vue-vben-admin)
## 文档
[文档地址](https://vvbin.cn/doc-next/)
## 准备
- [node](http://nodejs.org/) 和 [git](https://git-scm.com/) -项目开发环境
- [Vite](https://vitejs.dev/) - 熟悉 vite 特性
- [Vue3](https://v3.vuejs.org/) - 熟悉 Vue 基础语法
- [TypeScript](https://www.typescriptlang.org/) - 熟悉`TypeScript`基本语法
- [Es6+](http://es6.ruanyifeng.com/) - 熟悉 es6 基本语法
- [Vue-Router-Next](https://next.router.vuejs.org/) - 熟悉 vue-router 基本使用
- [Ant-Design-Vue](https://2x.antdv.com/docs/vue/introduce-cn/) - ui 基本使用
- [Mock.js](https://github.com/nuysoft/Mock) - mockjs 基本语法
## 安装使用
- 获取项目代码
```bash
git clone https://github.com/anncwb/vue-vben-admin.git
```
- 安装依赖
```bash
cd vue-vben-admin
pnpm install
```
- 运行
```bash
pnpm serve
```
- 打包
```bash
pnpm build
```
## 更新日志
[CHANGELOG](./CHANGELOG.zh_CN.md)
## 项目地址
- [vue-vben-admin](https://github.com/anncwb/vue-vben-admin) - 完整版
- [vue-vben-admin-thin-next](https://github.com/anncwb/vben-admin-thin-next) - 简化版
## 如何贡献
非常欢迎你的加入![提一个 Issue](https://github.com/anncwb/vue-vben-admin/issues/new/choose) 或者提交一个 Pull Request。
**Pull Request:**
1. Fork 代码!
2. 创建自己的分支: `git checkout -b feat/xxxx`
3. 提交你的修改: `git commit -am 'feat(function): add xxxxx'`
4. 推送您的分支: `git push origin feat/xxxx`
5. 提交`pull request`
## Git 贡献提交规范
- 参考 [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) 规范 ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
- `feat` 增加新功能
- `fix` 修复问题/BUG
- `style` 代码风格相关无影响运行结果的
- `perf` 优化/性能提升
- `refactor` 重构
- `revert` 撤销修改
- `test` 测试相关
- `docs` 文档/注释
- `chore` 依赖更新/脚手架配置修改等
- `workflow` 工作流改进
- `ci` 持续集成
- `types` 类型定义文件更改
- `wip` 开发中
## 浏览器支持
本地开发推荐使用`Chrome 80+` 浏览器
支持现代浏览器, 不支持 IE
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| :-: | :-: | :-: | :-: | :-: |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## 相关仓库
如果这些插件对你有帮助,可以给一个 star 支持下
- [vite-plugin-mock](https://github.com/anncwb/vite-plugin-mock) - 用于本地及开发环境数据 mock
- [vite-plugin-html](https://github.com/anncwb/vite-plugin-html) - 用于 html 模版转换及压缩
- [vite-plugin-style-import](https://github.com/anncwb/vite-plugin-style-import) - 用于组件库样式按需引入
- [vite-plugin-theme](https://github.com/anncwb/vite-plugin-theme) - 用于在线切换主题色等颜色相关配置
- [vite-plugin-imagemin](https://github.com/anncwb/vite-plugin-imagemin) - 用于打包压缩图片资源
- [vite-plugin-compression](https://github.com/anncwb/vite-plugin-compression) - 用于打包输出.gz|.brotil 文件
- [vite-plugin-svg-icons](https://github.com/anncwb/vite-plugin-svg-icons) - 用于快速生成 svg 雪碧图
## 后台整合示例
- [lamp-cloud](https://github.com/zuihou/lamp-cloud) - 基于 SpringCloud Alibaba 的微服务中后台快速开发平台
- [matecloud](https://github.com/matevip/matecloud) - MateCloud 微服务脚手架,基于 Spring Cloud 2020.0.3、SpringBoot 2.5.3 的全开源平台
## 维护者
[@Vben](https://github.com/anncwb)
## 捐赠
如果你觉得这个项目对你有帮助,你可以帮作者买一杯咖啡表示支持!
![donate](https://anncwb.github.io/anncwb/images/sponsor.png)
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aed;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
## 交流
`Vue-vben-Admin` 是完全开源免费的项目,在帮助开发者更方便地进行中大型管理系统开发,同时也提供 QQ 交流群使用问题欢迎在群内提问。
- QQ 群 `569291866`
## License
[MIT © Vben-2020](./LICENSE)

4
apps/vue/build/generate/icon/index.ts

@ -1,7 +1,7 @@
import path from 'path';
import fs from 'fs-extra';
import inquirer from 'inquirer';
import chalk from 'chalk';
import colors from 'picocolors';
import pkg from '../../../package.json';
async function generateIcon() {
@ -64,7 +64,7 @@ async function generateIcon() {
}
fs.emptyDir(path.join(process.cwd(), 'node_modules/.vite'));
console.log(
`${chalk.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]`,
`${colors.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]`,
);
});
}

11
apps/vue/build/script/buildConf.ts

@ -3,7 +3,7 @@
*/
import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant';
import fs, { writeFileSync } from 'fs-extra';
import chalk from 'chalk';
import colors from 'picocolors';
import { getEnvConfig, getRootPath } from '../utils';
import { getConfigFileName } from '../getConfigFileName';
@ -21,7 +21,8 @@ function createConfig(params: CreateConfigParams) {
try {
const windowConf = `window.${configName}`;
// Ensure that the variable will not be modified
const configStr = `${windowConf}=${JSON.stringify(config)};
let configStr = `${windowConf}=${JSON.stringify(config)};`;
configStr += `
Object.freeze(${windowConf});
Object.defineProperty(window, "${configName}", {
configurable: false,
@ -31,10 +32,10 @@ function createConfig(params: CreateConfigParams) {
fs.mkdirp(getRootPath(OUTPUT_DIR));
writeFileSync(getRootPath(`${OUTPUT_DIR}/${configFileName}`), configStr);
console.log(chalk.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`);
console.log(chalk.gray(OUTPUT_DIR + '/' + chalk.green(configFileName)) + '\n');
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(chalk.red('configuration file configuration file failed to package:\n' + error));
console.log(colors.red('configuration file configuration file failed to package:\n' + error));
}
}

6
apps/vue/build/script/postBuild.ts

@ -1,7 +1,7 @@
// #!/usr/bin/env node
import { runBuildConfig } from './buildConf';
import chalk from 'chalk';
import colors from 'picocolors';
import pkg from '../../package.json';
@ -14,9 +14,9 @@ export const runBuild = async () => {
runBuildConfig();
}
console.log(`${chalk.cyan(`[${pkg.name}]`)}` + ' - build successfully!');
console.log(`${colors.cyan(`[${pkg.name}]`)}` + ' - build successfully!');
} catch (error) {
console.log(chalk.red('vite build error:\n' + error));
console.log(colors.red('vite build error:\n' + error));
process.exit(1);
}
};

6
apps/vue/build/vite/plugin/compress.ts

@ -2,16 +2,16 @@
* 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 { Plugin } from 'vite';
import type { PluginOption } from 'vite';
import compressPlugin from 'vite-plugin-compression';
export function configCompressPlugin(
compress: 'gzip' | 'brotli' | 'none',
deleteOriginFile = false,
): Plugin | Plugin[] {
): PluginOption | PluginOption[] {
const compressList = compress.split(',');
const plugins: Plugin[] = [];
const plugins: PluginOption[] = [];
if (compressList.includes('gzip')) {
plugins.push(

6
apps/vue/build/vite/plugin/html.ts

@ -2,8 +2,8 @@
* Plugin to minimize and use ejs template syntax in index.html.
* https://github.com/anncwb/vite-plugin-html
*/
import type { Plugin } from 'vite';
import html from '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';
@ -16,7 +16,7 @@ export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
return `${path || '/'}${GLOB_CONFIG_FILE_NAME}?v=${pkg.version}-${new Date().getTime()}`;
};
const htmlPlugin: Plugin[] = html({
const htmlPlugin: PluginOption[] = createHtmlPlugin({
minify: isBuild,
inject: {
// Inject data into ejs template

16
apps/vue/build/vite/plugin/index.ts

@ -1,9 +1,10 @@
import type { Plugin } from 'vite';
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';
@ -14,7 +15,6 @@ import { configVisualizerConfig } from './visualizer';
import { configThemePlugin } from './theme';
import { configImageminPlugin } from './imagemin';
import { configSvgIconsPlugin } from './svgSprite';
import { configHmrPlugin } from './hmr';
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
const {
@ -25,21 +25,21 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE,
} = viteEnv;
const vitePlugins: (Plugin | Plugin[])[] = [
const vitePlugins: (PluginOption | PluginOption[])[] = [
// have to
vue(),
// have to
vueJsx(),
// support name
vueSetupExtend(),
VitePluginCertificate({
source: 'coding',
}),
];
// vite-plugin-windicss
vitePlugins.push(windiCSS());
// TODO
!isBuild && vitePlugins.push(configHmrPlugin());
// @vitejs/plugin-legacy
VITE_LEGACY && isBuild && vitePlugins.push(legacy());
@ -61,12 +61,12 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
// rollup-plugin-visualizer
vitePlugins.push(configVisualizerConfig());
//vite-plugin-theme
// vite-plugin-theme
vitePlugins.push(configThemePlugin(isBuild));
// The following plugins only work in the production environment
if (isBuild) {
//vite-plugin-imagemin
// vite-plugin-imagemin
VITE_USE_IMAGEMIN && vitePlugins.push(configImageminPlugin());
// rollup-plugin-gzip

15
apps/vue/build/vite/plugin/styleImport.ts

@ -2,13 +2,13 @@
* Introduces component library styles on demand.
* https://github.com/anncwb/vite-plugin-style-import
*/
import styleImport from 'vite-plugin-style-import';
import { createStyleImportPlugin } from 'vite-plugin-style-import';
export function configStyleImportPlugin(isBuild: boolean) {
if (!isBuild) {
return [];
}
const styleImportPlugin = styleImport({
export function configStyleImportPlugin(_isBuild: boolean) {
// if (!isBuild) {
// return [];
// }
const styleImportPlugin = createStyleImportPlugin({
libs: [
{
libraryName: 'ant-design-vue',
@ -19,6 +19,7 @@ export function configStyleImportPlugin(isBuild: boolean) {
'anchor-link',
'sub-menu',
'menu-item',
'menu-divider',
'menu-item-group',
'breadcrumb-item',
'breadcrumb-separator',
@ -63,6 +64,8 @@ export function configStyleImportPlugin(isBuild: boolean) {
'layout-footer': 'layout',
'layout-header': 'layout',
'month-picker': 'date-picker',
'range-picker': 'date-picker',
'image-preview-group': 'image',
};
return ignoreList.includes(name)

4
apps/vue/build/vite/plugin/svgSprite.ts

@ -3,11 +3,11 @@
* https://github.com/anncwb/vite-plugin-svg-icons
*/
import SvgIconsPlugin from 'vite-plugin-svg-icons';
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
import path from 'path';
export function configSvgIconsPlugin(isBuild: boolean) {
const svgIconsPlugin = SvgIconsPlugin({
const svgIconsPlugin = createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
svgoOptions: isBuild,
// default

6
apps/vue/build/vite/plugin/theme.ts

@ -2,7 +2,7 @@
* Vite plugin for website theme color switching
* https://github.com/anncwb/vite-plugin-theme
*/
import type { Plugin } from 'vite';
import type { PluginOption } from 'vite';
import path from 'path';
import {
viteThemePlugin,
@ -14,7 +14,7 @@ import {
import { getThemeColors, generateColors } from '../../config/themeConfig';
import { generateModifyVars } from '../../generate/generateModifyVars';
export function configThemePlugin(isBuild: boolean): Plugin[] {
export function configThemePlugin(isBuild: boolean): PluginOption[] {
const colors = generateColors({
mixDarken,
mixLighten,
@ -85,5 +85,5 @@ export function configThemePlugin(isBuild: boolean): Plugin[] {
}),
];
return plugin as unknown as Plugin[];
return plugin as unknown as PluginOption[];
}

74
apps/vue/commitlint.config.js

@ -1,3 +1,23 @@
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const scopes = fs
.readdirSync(path.resolve(__dirname, 'src'), { withFileTypes: true })
.filter((dirent) => dirent.isDirectory())
.map((dirent) => dirent.name.replace(/s$/, ''));
// precomputed scope
const scopeComplete = execSync('git status --porcelain || true')
.toString()
.trim()
.split('\n')
.find((r) => ~r.indexOf('M src'))
?.replace(/(\/)/g, '%%')
?.match(/src%%((\w|-)*)/)?.[1]
?.replace(/s$/, '');
/** @type {import('cz-git').UserConfig} */
module.exports = {
ignores: [(commit) => commit.includes('init')],
extends: ['@commitlint/config-conventional'],
@ -30,4 +50,58 @@ module.exports = {
],
],
},
prompt: {
/** @use `yarn commit :f` */
alias: {
f: 'docs: fix typos',
r: 'docs: update README',
s: 'style: update code format',
b: 'build: bump dependencies',
c: 'chore: update config',
},
customScopesAlign: !scopeComplete ? 'top' : 'bottom',
defaultScope: scopeComplete,
scopes: [...scopes, 'mock'],
allowEmptyIssuePrefixs: false,
allowCustomIssuePrefixs: false,
// English
typesAppend: [
{ value: 'wip', name: 'wip: work in process' },
{ value: 'workflow', name: 'workflow: workflow improvements' },
{ value: 'types', name: 'types: type definition file changes' },
],
// 中英文对照版
// messages: {
// type: '选择你要提交的类型 :',
// scope: '选择一个提交范围 (可选):',
// customScope: '请输入自定义的提交范围 :',
// subject: '填写简短精炼的变更描述 :\n',
// body: '填写更加详细的变更描述 (可选)。使用 "|" 换行 :\n',
// breaking: '列举非兼容性重大的变更 (可选)。使用 "|" 换行 :\n',
// footerPrefixsSelect: '选择关联issue前缀 (可选):',
// customFooterPrefixs: '输入自定义issue前缀 :',
// footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
// confirmCommit: '是否提交或修改commit ?',
// },
// types: [
// { value: 'feat', name: 'feat: 新增功能' },
// { value: 'fix', name: 'fix: 修复缺陷' },
// { value: 'docs', name: 'docs: 文档变更' },
// { value: 'style', name: 'style: 代码格式' },
// { value: 'refactor', name: 'refactor: 代码重构' },
// { value: 'perf', name: 'perf: 性能优化' },
// { value: 'test', name: 'test: 添加疏漏测试或已有测试改动' },
// { value: 'build', name: 'build: 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)' },
// { value: 'ci', name: 'ci: 修改 CI 配置、脚本' },
// { value: 'revert', name: 'revert: 回滚 commit' },
// { value: 'chore', name: 'chore: 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)' },
// { value: 'wip', name: 'wip: 正在开发中' },
// { value: 'workflow', name: 'workflow: 工作流程改进' },
// { value: 'types', name: 'types: 类型定义文件修改' },
// ],
// emptyScopesAlias: 'empty: 不填写',
// customScopesAlias: 'custom: 自定义',
},
};

21
apps/vue/index.html

@ -8,7 +8,6 @@
name="viewport"
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
/>
<title><%= title %></title>
<link rel="icon" href="/favicon.ico" />
</head>
@ -30,7 +29,7 @@
}
html[data-theme='dark'] .app-loading .app-loading-title {
color: rgba(255, 255, 255, 0.85);
color: rgb(255 255 255 / 85%);
}
.app-loading {
@ -48,7 +47,6 @@
top: 50%;
left: 50%;
display: flex;
-webkit-transform: translate3d(-50%, -50%, 0);
transform: translate3d(-50%, -50%, 0);
justify-content: center;
align-items: center;
@ -66,7 +64,7 @@
display: flex;
margin-top: 30px;
font-size: 30px;
color: rgba(0, 0, 0, 0.85);
color: rgb(0 0 0 / 85%);
justify-content: center;
align-items: center;
}
@ -97,7 +95,7 @@
height: 20px;
background-color: #0065cc;
border-radius: 100%;
opacity: 0.3;
opacity: 30%;
transform: scale(0.75);
animation: antSpinMove 1s infinite linear alternate;
transform-origin: 50% 50%;
@ -111,43 +109,38 @@
.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 {
@keyframes antRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg);
}
}
@keyframes antSpinMove {
to {
opacity: 1;
opacity: 100%;
}
}
@-webkit-keyframes antSpinMove {
@keyframes antSpinMove {
to {
opacity: 1;
opacity: 100%;
}
}
</style>

325
apps/vue/mock/demo/api-cascader.ts

@ -0,0 +1,325 @@
import { MockMethod } from 'vite-plugin-mock';
import { resultSuccess } from '../_util';
const areaList: any[] = [
{
id: '530825900854620160',
code: '430000',
parentCode: '100000',
levelType: 1,
name: '湖南省',
province: '湖南省',
city: null,
district: null,
town: null,
village: null,
parentPath: '430000',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 16:33:42',
customized: false,
usable: true,
},
{
id: '530825900883980288',
code: '430100',
parentCode: '430000',
levelType: 2,
name: '长沙市',
province: '湖南省',
city: '长沙市',
district: null,
town: null,
village: null,
parentPath: '430000,430100',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 16:33:42',
customized: false,
usable: true,
},
{
id: '530825900951089152',
code: '430102',
parentCode: '430100',
levelType: 3,
name: '芙蓉区',
province: '湖南省',
city: '长沙市',
district: '芙蓉区',
town: null,
village: null,
parentPath: '430000,430100,430102',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 16:33:42',
customized: false,
usable: true,
},
{
id: '530825901014003712',
code: '430104',
parentCode: '430100',
levelType: 3,
name: '岳麓区',
province: '湖南省',
city: '长沙市',
district: '岳麓区',
town: null,
village: null,
parentPath: '430000,430100,430104',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 16:33:42',
customized: false,
usable: true,
},
{
id: '530825900988837888',
code: '430103',
parentCode: '430100',
levelType: 3,
name: '天心区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: null,
village: null,
parentPath: '430000,430100,430103',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 16:33:42',
customized: false,
usable: true,
},
{
id: '530826672489115648',
code: '430103002',
parentCode: '430103',
levelType: 4,
name: '坡子街街道',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: null,
parentPath: '430000,430100,430103,430103002',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-12-14 15:26:43',
customized: false,
usable: true,
},
{
id: '530840241171607552',
code: '430103002001',
parentCode: '430103002',
levelType: 5,
name: '八角亭社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '八角亭社区',
parentPath: '430000,430100,430103,430103002,430103002001',
createTime: '2020-11-30 15:47:31',
updateTime: '2021-01-20 14:07:23',
customized: false,
usable: true,
},
{
id: '530840241200967680',
code: '430103002002',
parentCode: '430103002',
levelType: 5,
name: '西牌楼社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '西牌楼社区',
parentPath: '430000,430100,430103,430103002,430103002002',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241230327808',
code: '430103002003',
parentCode: '430103002',
levelType: 5,
name: '太平街社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '太平街社区',
parentPath: '430000,430100,430103,430103002,430103002003',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241259687936',
code: '430103002005',
parentCode: '430103002',
levelType: 5,
name: '坡子街社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '坡子街社区',
parentPath: '430000,430100,430103,430103002,430103002005',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241284853760',
code: '430103002006',
parentCode: '430103002',
levelType: 5,
name: '青山祠社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '青山祠社区',
parentPath: '430000,430100,430103,430103002,430103002006',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241310019584',
code: '430103002007',
parentCode: '430103002',
levelType: 5,
name: '沙河社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '沙河社区',
parentPath: '430000,430100,430103,430103002,430103002007',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241381322752',
code: '430103002008',
parentCode: '430103002',
levelType: 5,
name: '碧湘社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '碧湘社区',
parentPath: '430000,430100,430103,430103002,430103002008',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241410682880',
code: '430103002009',
parentCode: '430103002',
levelType: 5,
name: '创远社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '创远社区',
parentPath: '430000,430100,430103,430103002,430103002009',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241431654400',
code: '430103002010',
parentCode: '430103002',
levelType: 5,
name: '楚湘社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '楚湘社区',
parentPath: '430000,430100,430103,430103002,430103002010',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241465208832',
code: '430103002011',
parentCode: '430103002',
levelType: 5,
name: '西湖社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '西湖社区',
parentPath: '430000,430100,430103,430103002,430103002011',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241502957568',
code: '430103002012',
parentCode: '430103002',
levelType: 5,
name: '登仁桥社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '登仁桥社区',
parentPath: '430000,430100,430103,430103002,430103002012',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241553289216',
code: '430103002013',
parentCode: '430103002',
levelType: 5,
name: '文庙坪社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '文庙坪社区',
parentPath: '430000,430100,430103,430103002,430103002013',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
];
export default [
{
url: '/basic-api/cascader/getAreaRecord',
timeout: 1000,
method: 'post',
response: ({ body }) => {
const { parentCode } = body || {};
if (!parentCode) {
return resultSuccess(areaList.filter((it) => it.code === '430000'));
}
return resultSuccess(areaList.filter((it) => it.parentCode === parentCode));
},
},
] as MockMethod[];

28
apps/vue/mock/demo/select-demo.ts

@ -0,0 +1,28 @@
import { MockMethod } from 'vite-plugin-mock';
import { resultSuccess } 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: '/basic-api/select/getDemoOptions',
timeout: 1000,
method: 'get',
response: ({ query }) => {
const { keyword, count } = query;
console.log(keyword);
return resultSuccess(demoList(keyword, count));
},
},
] as MockMethod[];

202
apps/vue/mock/demo/system.ts

@ -0,0 +1,202 @@
import { MockMethod } from 'vite-plugin-mock';
import { resultError, resultPageSuccess, resultSuccess } 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 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 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: '/basic-api/system/getAccountList',
timeout: 100,
method: 'get',
response: ({ query }) => {
const { page = 1, pageSize = 20 } = query;
return resultPageSuccess(page, pageSize, accountList);
},
},
{
url: '/basic-api/system/getRoleListByPage',
timeout: 100,
method: 'get',
response: ({ query }) => {
const { page = 1, pageSize = 20 } = query;
return resultPageSuccess(page, pageSize, roleList);
},
},
{
url: '/basic-api/system/setRoleStatus',
timeout: 500,
method: 'post',
response: ({ query }) => {
const { id, status } = query;
return resultSuccess({ id, status });
},
},
{
url: '/basic-api/system/getAllRoleList',
timeout: 100,
method: 'get',
response: () => {
return resultSuccess(roleList);
},
},
{
url: '/basic-api/system/getDeptList',
timeout: 100,
method: 'get',
response: () => {
return resultSuccess(deptList);
},
},
{
url: '/basic-api/system/getMenuList',
timeout: 100,
method: 'get',
response: () => {
return resultSuccess(menuList);
},
},
{
url: '/basic-api/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
apps/vue/mock/demo/table-demo.ts

@ -0,0 +1,52 @@
import { MockMethod } from 'vite-plugin-mock';
import { Random } from 'mockjs';
import { resultPageSuccess } 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: '/basic-api/table/getDemoList',
timeout: 100,
method: 'get',
response: ({ query }) => {
const { page = 1, pageSize = 20 } = query;
return resultPageSuccess(page, pageSize, demoList);
},
},
] as MockMethod[];

38
apps/vue/mock/demo/tree-demo.ts

@ -0,0 +1,38 @@
import { MockMethod } from 'vite-plugin-mock';
import { resultSuccess } 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: '/basic-api/tree/getDemoOptions',
timeout: 1000,
method: 'get',
response: ({ query }) => {
const { keyword } = query;
console.log(keyword);
return resultSuccess(demoTreeList(keyword));
},
},
] as MockMethod[];

8
apps/vue/mock/sys/user.ts

@ -111,4 +111,12 @@ export default [
return resultSuccess(undefined, { message: 'Token has been destroyed' });
},
},
{
url: '/basic-api/testRetry',
statusCode: 405,
method: 'get',
response: () => {
return resultError('Error!');
},
},
] as MockMethod[];

197
apps/vue/package.json

@ -7,12 +7,13 @@
"url": "https://github.com/anncwb"
},
"scripts": {
"bootstrap": "yarn install",
"commit": "czg",
"bootstrap": "pnpm install",
"serve": "npm run dev",
"dev": "vite",
"build": "cross-env NODE_ENV=production vite build && esno ./build/script/postBuild.ts",
"build:test": "cross-env vite build --mode test && esno ./build/script/postBuild.ts",
"build:no-cache": "yarn clean:cache && npm run build",
"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",
@ -23,124 +24,133 @@
"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:lint-staged": "lint-staged",
"test:unit": "jest",
"test:unit-coverage": "jest --coverage",
"test:gzip": "npx http-server dist --cors --gzip -c-1",
"test:br": "npx http-server dist --cors --brotli -c-1",
"reinstall": "rimraf yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
"reinstall": "rimraf pnpm-lock.yaml && 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.0.1",
"@iconify/iconify": "^2.0.4",
"@ant-design/icons-vue": "^6.1.0",
"@iconify/iconify": "^2.2.1",
"@logicflow/core": "^1.1.13",
"@logicflow/extension": "^1.1.13",
"@microsoft/signalr": "^6.0.0",
"@vueuse/core": "^6.7.4",
"@vueuse/shared": "^6.7.4",
"@zxcvbn-ts/core": "^1.0.0-beta.0",
"ant-design-vue": "2.2.8",
"axios": "^0.24.0",
"codemirror": "^5.62.2",
"@vue/runtime-core": "^3.2.33",
"@vue/shared": "^3.2.33",
"@vueuse/core": "^8.3.0",
"@vueuse/shared": "^8.3.0",
"@zxcvbn-ts/core": "^2.0.1",
"ant-design-vue": "^3.2.0",
"axios": "^0.26.1",
"codemirror": "^5.65.3",
"cropperjs": "^1.5.12",
"crypto-js": "^4.1.1",
"echarts": "^5.2.2",
"cz-git": "^1.3.9",
"czg": "^1.3.9",
"dayjs": "^1.11.1",
"echarts": "^5.3.2",
"intro.js": "^5.1.0",
"lodash-es": "^4.17.21",
"mockjs": "^1.1.0",
"moment": "^2.29.1",
"nprogress": "^0.2.0",
"oidc-client": "^1.11.5",
"path-to-regexp": "^6.2.0",
"pinia": "2.0.0",
"qrcode": "^1.4.4",
"qs": "^6.10.1",
"pinia": "2.0.12",
"print-js": "^1.6.0",
"qrcode": "^1.5.0",
"qs": "^6.10.3",
"resize-observer-polyfill": "^1.5.1",
"showdown": "^2.1.0",
"simple-uploader.js": "^0.5.6",
"sortablejs": "^1.14.0",
"vue": "^3.2.21",
"sortablejs": "^1.15.0",
"tinymce": "^5.10.3",
"vditor": "^3.8.13",
"vue": "^3.2.33",
"vue-cookies": "^1.8.1",
"vue-i18n": "^9.1.9",
"vue-json-pretty": "^1.8.1",
"vue-router": "^4.0.12",
"vue-json-pretty": "^2.0.6",
"vue-router": "^4.0.14",
"vue-types": "^4.1.1",
"xlsx": "^0.17.3"
"xlsx": "^0.18.5"
},
"devDependencies": {
"@commitlint/cli": "^14.1.0",
"@commitlint/config-conventional": "^14.1.0",
"@iconify/json": "^1.1.422",
"@purge-icons/generated": "^0.7.0",
"@commitlint/cli": "^16.2.3",
"@commitlint/config-conventional": "^16.2.1",
"@iconify/json": "^2.1.30",
"@purge-icons/generated": "^0.8.1",
"@types/codemirror": "^5.60.5",
"@types/crypto-js": "^4.0.2",
"@types/crypto-js": "^4.1.1",
"@types/fs-extra": "^9.0.13",
"@types/inquirer": "^8.1.3",
"@types/inquirer": "^8.2.1",
"@types/intro.js": "^3.0.2",
"@types/jest": "^27.0.2",
"@types/lodash-es": "^4.17.5",
"@types/mockjs": "^1.0.4",
"@types/node": "^16.11.6",
"@types/lodash-es": "^4.17.6",
"@types/mockjs": "^1.0.6",
"@types/node": "^17.0.25",
"@types/nprogress": "^0.2.0",
"@types/qrcode": "^1.4.1",
"@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.3.0",
"@typescript-eslint/parser": "^5.3.0",
"@vitejs/plugin-legacy": "^1.6.2",
"@vitejs/plugin-vue": "^1.9.4",
"@vitejs/plugin-vue-jsx": "^1.2.0",
"@vue/compiler-sfc": "3.2.21",
"@vue/test-utils": "^2.0.0-rc.16",
"autoprefixer": "^10.4.0",
"@typescript-eslint/eslint-plugin": "^5.20.0",
"@typescript-eslint/parser": "^5.20.0",
"@vitejs/plugin-legacy": "^1.8.1",
"@vitejs/plugin-vue": "^2.3.1",
"@vitejs/plugin-vue-jsx": "^1.3.10",
"@vue/compiler-sfc": "^3.2.33",
"@vue/test-utils": "^2.0.0-rc.21",
"autoprefixer": "^10.4.4",
"commitizen": "^4.2.4",
"conventional-changelog-cli": "^2.1.1",
"conventional-changelog-cli": "^2.2.2",
"cross-env": "^7.0.3",
"dotenv": "^10.0.0",
"eslint": "^8.1.0",
"eslint-config-prettier": "^8.3.0",
"eslint-define-config": "^1.1.2",
"eslint-plugin-jest": "^25.2.2",
"dotenv": "^16.0.0",
"eslint": "^8.13.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.0.3",
"esno": "^0.10.1",
"fs-extra": "^10.0.0",
"eslint-plugin-vue": "^8.6.0",
"esno": "^0.14.1",
"fs-extra": "^10.1.0",
"husky": "^7.0.4",
"inquirer": "^8.2.0",
"jest": "^27.3.1",
"inquirer": "^8.2.2",
"less": "^4.1.2",
"lint-staged": "11.2.6",
"lint-staged": "12.3.7",
"npm-run-all": "^4.1.5",
"postcss": "^8.3.11",
"postcss-html": "^1.2.0",
"postcss-less": "^5.0.0",
"prettier": "^2.4.1",
"picocolors": "^1.0.0",
"postcss": "^8.4.12",
"postcss-html": "^1.4.1",
"postcss-less": "^6.0.0",
"prettier": "^2.6.2",
"rimraf": "^3.0.2",
"rollup-plugin-visualizer": "^5.5.2",
"stylelint": "^14.0.1",
"stylelint-config-html": "^1.0.0",
"rollup": "^2.70.2",
"rollup-plugin-visualizer": "^5.6.0",
"stylelint": "^14.7.1",
"stylelint-config-prettier": "^9.0.3",
"stylelint-config-standard": "^23.0.0",
"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.4.0",
"typescript": "^4.4.4",
"vite": "^2.6.13",
"vite-plugin-compression": "^0.3.5",
"vite-plugin-html": "^2.1.1",
"vite-plugin-imagemin": "^0.4.6",
"ts-node": "^10.7.0",
"typescript": "^4.6.3",
"vite": "^2.9.5",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.2.0",
"vite-plugin-imagemin": "^0.6.1",
"vite-plugin-mkcert": "^1.6.0",
"vite-plugin-mock": "^2.9.6",
"vite-plugin-purge-icons": "^0.7.0",
"vite-plugin-pwa": "^0.11.3",
"vite-plugin-style-import": "^1.3.0",
"vite-plugin-svg-icons": "^1.0.5",
"vite-plugin-theme": "^0.8.1",
"vite-plugin-vue-setup-extend": "^0.1.0",
"vite-plugin-windicss": "^1.4.12",
"vue-eslint-parser": "^8.0.1",
"vue-tsc": "^0.28.10"
"vite-plugin-purge-icons": "^0.8.1",
"vite-plugin-pwa": "^0.11.13",
"vite-plugin-style-import": "^2.0.0",
"vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-theme": "^0.8.6",
"vite-plugin-vue-setup-extend": "^0.4.0",
"vite-plugin-windicss": "^1.8.4",
"vue-eslint-parser": "^8.3.0",
"vue-tsc": "^0.33.9"
},
"resolutions": {
"//": "Used to install imagemin dependencies, because imagemin may not be installed in China. If it is abroad, you can delete it",
"bin-wrapper": "npm:bin-wrapper-china",
"rollup": "^2.56.3",
"gifsicle": "5.2.0"
@ -156,5 +166,34 @@
"homepage": "https://github.com/anncwb/vue-vben-admin",
"engines": {
"node": "^12 || >=14"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write"
],
"{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [
"prettier --write--parser json"
],
"package.json": [
"prettier --write"
],
"*.vue": [
"eslint --fix",
"prettier --write",
"stylelint --fix"
],
"*.{scss,less,styl,html}": [
"stylelint --fix",
"prettier --write"
],
"*.md": [
"prettier --write"
]
},
"config": {
"commitizen": {
"path": "node_modules/cz-git"
}
}
}

1
apps/vue/src/App.vue

@ -12,6 +12,7 @@
import { useTitle } from '/@/hooks/web/useTitle';
import { useLocale } from '/@/locales/useLocale';
import 'dayjs/locale/zh-cn';
// support Multi-language
const { getAntdLocale } = useLocale();

19
apps/vue/src/api/account/accounts.ts

@ -1,14 +1,18 @@
import { defAbpHttp } from '/@/utils/http/abp';
import { Register, PhoneRegister, PhoneResetPassword } from './model/accountsModel';
import { User } from '/@/api/identity/model/userModel';
import { ListResultDto } from '../model/baseModel';
import { format } from '/@/utils/strings';
enum Api {
Register = '/api/account/register',
RegisterByPhone = '/api/account/phone/register',
ResetPassword = '/api/account/phone/reset-password',
SendEmailSignCode = '/api/account/email/send-signin-code',
SendPhoneSignCode = '/api/account/phone/send-signin-code',
SendPhoneRegisterCode = '/api/account/phone/send-register-code',
SendPhoneResetPasswordCode = '/api/account/phone/send-password-reset-code',
GetTwoFactorProviders = '/api/account/two-factor-providers?userId={userId}',
}
export const register = (input: Register) => {
@ -41,6 +45,15 @@ export const sendPhoneSignCode = (phoneNumber: string) => {
});
};
export const sendEmailSignCode = (emailAddress: string) => {
return defAbpHttp.post<void>({
url: Api.SendEmailSignCode,
data: {
emailAddress: emailAddress,
},
});
};
export const sendPhoneRegisterCode = (phoneNumber: string) => {
return defAbpHttp.post<void>({
url: Api.SendPhoneRegisterCode,
@ -58,3 +71,9 @@ export const sendPhoneResetPasswordCode = (phoneNumber: string) => {
},
});
};
export const getTwoFactorProviders = (userId: string) => {
return defAbpHttp.get<ListResultDto<NameValue<String>>>({
url: format(Api.GetTwoFactorProviders, { userId: userId }),
});
}

7
apps/vue/src/api/account/model/profilesModel.ts

@ -28,3 +28,10 @@ export interface ChangePhoneNumber {
export interface TwoFactorEnabled {
enabled: boolean;
}
export interface SendEmailConfirmCode {
email: string;
appName: string;
returnUrl?: string;
returnUrlHash?: string;
}

11
apps/vue/src/api/account/profiles.ts

@ -5,6 +5,7 @@ import {
ChangePassword,
ChangePhoneNumber,
TwoFactorEnabled,
SendEmailConfirmCode,
} from './model/profilesModel';
enum Api {
@ -15,6 +16,7 @@ enum Api {
ChangePhoneNumber = '/api/account/my-profile/change-phone-number',
GetTwoFactorEnabled = '/api/account/my-profile/two-factor',
ChangeTwoFactorEnabled = '/api/account/my-profile/change-two-factor',
SendEmailConfirmLink = '/api/account/my-profile/send-email-confirm-link',
}
export const get = () => {
@ -37,8 +39,15 @@ export const changePassword = (input: ChangePassword) => {
});
};
export const sendEmailConfirmLink = (input: SendEmailConfirmCode) => {
return defAbpHttp.post<void>({
url: Api.SendEmailConfirmLink,
data: input,
});
};
export const sendChangePhoneNumberCode = (phoneNumber: string) => {
return defAbpHttp.put<void>({
return defAbpHttp.post<void>({
url: Api.SendChangePhoneNumberCode,
data: {
newPhoneNumber: phoneNumber,

89
apps/vue/src/api/api-gateway/aggregate.ts

@ -1,89 +0,0 @@
import { defAbpHttp } from '/@/utils/http/abp';
import {
AggregateRoute,
CreateAggregateRoute,
CreateAggregateRouteConfig,
UpdateAggregateRoute,
GetAggregateRoutePagedRequest,
AggregateRoutePagedResult,
} from './model/aggregateModel';
import { format } from '/@/utils/strings';
enum Api {
RemoteService = 'ApiGateway',
Controller = 'AggregateReRoute',
GetById = '/api/ApiGateway/Aggregates/{routeId}',
GetList = '/api/ApiGateway/Globals',
GetActivedList = '/api/ApiGateway/RouteGroups/Actived',
}
export const create = (input: CreateAggregateRoute) => {
return defAbpHttp.request<AggregateRoute>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'CreateAsync',
data: input,
});
};
export const createConfig = (input: CreateAggregateRouteConfig) => {
return defAbpHttp.request<AggregateRoute>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'AddRouteConfigAsync',
data: input,
});
};
export const deleteById = (routeId: string) => {
return defAbpHttp.request<void>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'DeleteAsync',
params: {
input: {
RouteId: routeId,
},
},
});
};
export const deleteConfig = (routeId: string, routeKey: string) => {
return defAbpHttp.request<void>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'DeleteAsync',
params: {
input: {
RouteId: routeId,
ReRouteKey: routeKey,
},
},
});
};
export const getById = (id: string) => {
return defAbpHttp.get<AggregateRoute>({
url: format(Api.GetById, { routeId: id }),
});
};
export const getList = (input: GetAggregateRoutePagedRequest) => {
return defAbpHttp.request<AggregateRoutePagedResult>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'GetPagedListAsync',
params: {
input: input,
},
});
};
export const update = (input: UpdateAggregateRoute) => {
return defAbpHttp.request<AggregateRoute>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'UpdateAsync',
data: input,
});
};

26
apps/vue/src/api/api-gateway/basic.ts

@ -1,26 +0,0 @@
import { defAbpHttp } from '/@/utils/http/abp';
import { LoadBalancerDescriptor } from './model/basicModel';
import { ListResultDto } from '../model/baseModel';
enum Api {
GetLoadBalancerProviders = '/api/ApiGateway/Basic/LoadBalancers',
GetDefinedAggregatorProvicers = '/api/ApiGateway/Basic/Aggregators',
}
export const getLoadBalancerProviders = () => {
return defAbpHttp.get<ListResultDto<LoadBalancerDescriptor>>({
url: Api.GetLoadBalancerProviders,
});
};
export async function getDefinedAggregatorProviders() {
const { items } = await defAbpHttp.get<ListResultDto<string>>({
url: Api.GetDefinedAggregatorProvicers,
});
// 需要对返回格式转换以适配 ApiSelect组件
return items.map((item) => {
return {
provider: item,
};
});
}

66
apps/vue/src/api/api-gateway/global.ts

@ -1,66 +0,0 @@
import { defAbpHttp } from '/@/utils/http/abp';
import {
GlobalConfiguration,
CreateGlobalConfiguration,
UpdateGlobalConfiguration,
GetGlobalPagedRequest,
GlobalConfigurationPagedResult,
} from './model/globalModel';
enum Api {
RemoteService = 'ApiGateway',
Controller = 'GlobalConfiguration',
GetList = '/api/ApiGateway/Globals',
GetActivedList = '/api/ApiGateway/RouteGroups/Actived',
}
export const create = (input: CreateGlobalConfiguration) => {
return defAbpHttp.request<GlobalConfiguration>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'CreateAsync',
data: input,
});
};
export const update = (input: UpdateGlobalConfiguration) => {
return defAbpHttp.request<GlobalConfiguration>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'UpdateAsync',
data: input,
});
};
export const getByAppId = (appId: string) => {
return defAbpHttp.request<GlobalConfiguration>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'GetAsync',
params: {
input: {
appId: appId,
},
},
});
};
export const getList = (input: GetGlobalPagedRequest) => {
return defAbpHttp.get<GlobalConfigurationPagedResult>({
url: Api.GetList,
params: input,
});
};
export const deleteByAppId = (appId: string) => {
return defAbpHttp.request<GlobalConfiguration>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'DeleteAsync',
params: {
input: {
appId: appId,
},
},
});
};

73
apps/vue/src/api/api-gateway/group.ts

@ -1,73 +0,0 @@
import { defAbpHttp } from '/@/utils/http/abp';
import {
RouteGroup,
CreateRouteGroup,
UpdateRouteGroup,
RouteGroupListResult,
GetRouteGroupPagedRequest,
RouteGroupPagedResult,
} from './model/groupModel';
enum Api {
RemoteService = 'ApiGateway',
Controller = 'RouteGroup',
GetList = '/api/ApiGateway/RouteGroups',
GetActivedList = '/api/ApiGateway/RouteGroups/Actived',
}
export const create = (input: CreateRouteGroup) => {
return defAbpHttp.request<RouteGroup>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'CreateAsync',
data: input,
});
};
export const update = (input: UpdateRouteGroup) => {
return defAbpHttp.request<RouteGroup>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'UpdateAsync',
data: input,
});
};
export const getByAppId = (appId: string) => {
return defAbpHttp.request<RouteGroup>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'GetAsync',
params: {
input: {
appId: appId,
},
},
});
};
export const getActivedList = () => {
return defAbpHttp.get<RouteGroupListResult>({
url: Api.GetList,
});
};
export const getList = (input: GetRouteGroupPagedRequest) => {
return defAbpHttp.get<RouteGroupPagedResult>({
url: Api.GetList,
params: input,
});
};
export const deleteByAppId = (appId: string) => {
return defAbpHttp.request<RouteGroup>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'DeleteAsync',
params: {
input: {
appId: appId,
},
},
});
};

46
apps/vue/src/api/api-gateway/model/aggregateModel.ts

@ -1,46 +0,0 @@
import { PagedAndSortedResultRequestDto, PagedResultDto } from '../../model/baseModel';
export class AggregateRouteConfig {
reRouteKey = '';
parameter = '';
jsonPath = '';
}
export class CreateAggregateRouteConfig extends AggregateRouteConfig {
routeId = '';
}
export class AggregateRouteBase {
reRouteKeys: string[] = [];
upstreamPathTemplate = '';
upstreamHost = '';
reRouteIsCaseSensitive = true;
aggregator = '';
priority?: number;
upstreamHttpMethod: string[] = [];
}
export class AggregateRoute extends AggregateRouteBase {
appId = '';
name = '';
reRouteId = '';
concurrencyStamp = '';
reRouteKeysConfig: AggregateRouteConfig[] = [];
}
export class CreateAggregateRoute extends AggregateRouteBase {
appId = '';
name = '';
}
export class UpdateAggregateRoute extends AggregateRouteBase {
routeId = '';
concurrencyStamp = '';
}
export class GetAggregateRoutePagedRequest extends PagedAndSortedResultRequestDto {
appId = '';
filter = '';
}
export class AggregateRoutePagedResult extends PagedResultDto<AggregateRoute> {}

80
apps/vue/src/api/api-gateway/model/basicModel.ts

@ -1,80 +0,0 @@
export class ServiceDiscoveryProvider {
host!: string;
port?: number;
type!: string;
token?: string;
configurationKey?: string;
pollingInterval?: number;
namespace?: string;
scheme?: string;
}
export class RateLimitOptions {
clientIdHeader?: string;
httpStatusCode?: number;
quotaExceededMessage?: string;
rateLimitCounterPrefix?: string;
disableRateLimitHeaders!: boolean;
}
export class RateLimitRuleOptions {
clientWhitelist?: string[] = [];
enableRateLimiting!: boolean;
period?: string;
periodTimespan?: boolean;
limit?: number;
}
export class QoSOptions {
timeoutValue?: number = 10000;
durationOfBreak?: number = 60000;
exceptionsAllowedBeforeBreaking?: number = 50;
}
export class LoadBalancerOptions {
type?: string = '';
key?: string = '';
expiry?: number = 0;
}
export class HostAndPort {
host = '';
port?: number = 80;
}
export class HttpHandlerOptions {
useProxy = false;
useTracing = false;
allowAutoRedirect = false;
useCookieContainer = false;
maxConnectionsPerServer?: number = 0;
}
export class FileCacheOptions {
ttlSeconds?: number = 0;
region?: string = '';
}
export class AuthenticationOptions {
authenticationProviderKey?: string = '';
allowedScopes?: string[] = [];
}
export class SecurityOptions {
ipAllowedList?: string[] = [];
ipBlockedList?: string[] = [];
}
export class LoadBalancerDescriptor {
type!: string;
displayName!: string;
}
export const HttpMethods: { [key: string]: string } = {
['GET']: 'blue',
['POST']: 'green',
['PUT']: 'orange',
['DELETE']: 'red',
['OPTIONS']: 'cyan',
['PATCH']: 'pink',
};

39
apps/vue/src/api/api-gateway/model/globalModel.ts

@ -1,39 +0,0 @@
import { PagedAndSortedResultRequestDto, PagedResultDto } from '../../model/baseModel';
import {
HttpHandlerOptions,
LoadBalancerOptions,
QoSOptions,
RateLimitOptions,
ServiceDiscoveryProvider,
} from './basicModel';
export class GlobalConfigurationBase {
baseUrl = '';
requestIdKey?: string = '';
downstreamScheme?: string = '';
downstreamHttpVersion?: string = '';
qoSOptions!: QoSOptions;
rateLimitOptions!: RateLimitOptions;
httpHandlerOptions!: HttpHandlerOptions;
loadBalancerOptions!: LoadBalancerOptions;
serviceDiscoveryProvider!: ServiceDiscoveryProvider;
}
export class GlobalConfiguration extends GlobalConfigurationBase {
appId!: string;
itemId!: string;
}
export class CreateGlobalConfiguration extends GlobalConfigurationBase {
appId = '';
}
export class UpdateGlobalConfiguration extends GlobalConfigurationBase {
itemId!: string;
}
export class GetGlobalPagedRequest extends PagedAndSortedResultRequestDto {
filter = '';
}
export class GlobalConfigurationPagedResult extends PagedResultDto<GlobalConfiguration> {}

38
apps/vue/src/api/api-gateway/model/groupModel.ts

@ -1,38 +0,0 @@
import {
FullAuditedEntityDto,
ListResultDto,
PagedAndSortedResultRequestDto,
PagedResultDto,
} from '../../model/baseModel';
export class RouteGroup extends FullAuditedEntityDto {
id!: string;
name!: string;
appId!: string;
appName!: string;
appIpAddress?: string;
description?: string;
isActive!: boolean;
}
export class CreateOrUpdateRouteGroup {
name = '';
appId = '';
appName = '';
isActive = true;
appIpAddress?: string = '';
description?: string = '';
}
export class CreateRouteGroup extends CreateOrUpdateRouteGroup {}
export class UpdateRouteGroup extends CreateOrUpdateRouteGroup {}
export class GetRouteGroupPagedRequest extends PagedAndSortedResultRequestDto {
filter = '';
sorting = 'AppId';
}
export class RouteGroupPagedResult extends PagedResultDto<RouteGroup> {}
export class RouteGroupListResult extends ListResultDto<RouteGroup> {}

70
apps/vue/src/api/api-gateway/model/routeModel.ts

@ -1,70 +0,0 @@
import { PagedAndSortedResultRequestDto, PagedResultDto } from '../../model/baseModel';
import {
AuthenticationOptions,
FileCacheOptions,
HostAndPort,
HttpHandlerOptions,
LoadBalancerOptions,
QoSOptions,
RateLimitRuleOptions,
SecurityOptions,
} from './basicModel';
export class RouteBase {
reRouteName = ''; // TODO: 需要修改名称
downstreamPathTemplate = '';
changeDownstreamPathTemplate?: { [key: string]: string };
upstreamPathTemplate = '';
upstreamHttpMethod!: string[];
addHeadersToRequest?: { [key: string]: string };
upstreamHeaderTransform?: { [key: string]: string };
downstreamHeaderTransform?: { [key: string]: string };
addClaimsToRequest?: { [key: string]: string };
routeClaimsRequirement?: { [key: string]: string };
addQueriesToRequest?: { [key: string]: string };
requestIdKey? = '';
reRouteIsCaseSensitive? = true;
serviceName? = '';
serviceNamespace? = '';
downstreamScheme? = 'HTTP';
downstreamHostAndPorts!: HostAndPort[];
upstreamHost = '';
key? = '';
delegatingHandlers?: string[];
priority? = 0;
timeout? = 30000;
dangerousAcceptAnyServerCertificateValidator?: boolean = true;
downstreamHttpVersion? = '';
downstreamHttpMethod? = '';
securityOptions?: SecurityOptions;
qoSOptions?: QoSOptions;
rateLimitOptions?: RateLimitRuleOptions;
loadBalancerOptions?: LoadBalancerOptions;
fileCacheOptions?: FileCacheOptions;
authenticationOptions?: AuthenticationOptions;
httpHandlerOptions?: HttpHandlerOptions;
}
export class Route extends RouteBase {
id!: number;
appId!: string;
reRouteId!: string;
concurrencyStamp!: string;
}
export class CreateRoute extends RouteBase {
appId = '';
}
export class UpdateRoute extends RouteBase {
reRouteId = '';
concurrencyStamp!: string;
}
export class GetRoutePagedRequest extends PagedAndSortedResultRequestDto {
appId!: string;
filter = '';
sorting = 'ReRouteName';
}
export class RoutePagedResult extends PagedResultDto<Route> {}

70
apps/vue/src/api/api-gateway/route.ts

@ -1,70 +0,0 @@
import { defAbpHttp } from '/@/utils/http/abp';
import {
Route,
CreateRoute,
UpdateRoute,
GetRoutePagedRequest,
RoutePagedResult,
} from './model/routeModel';
enum Api {
RemoteService = 'ApiGateway',
Controller = 'ReRoute',
GetList = '/api/ApiGateway/Globals',
GetActivedList = '/api/ApiGateway/RouteGroups/Actived',
}
export const create = (input: CreateRoute) => {
return defAbpHttp.request<Route>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'CreateAsync',
data: input,
});
};
export const deleteById = (id: string) => {
return defAbpHttp.request<void>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'DeleteAsync',
params: {
input: {
RouteId: id,
},
},
});
};
export const getById = (id: string) => {
return defAbpHttp.request<Route>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'GetAsync',
params: {
input: {
RouteId: id,
},
},
});
};
export const getList = (input: GetRoutePagedRequest) => {
return defAbpHttp.request<RoutePagedResult>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'GetListAsync',
params: {
input: input,
},
});
};
export const update = (input: UpdateRoute) => {
return defAbpHttp.request<Route>({
service: Api.RemoteService,
controller: Api.Controller,
action: 'UpdateAsync',
data: input,
});
};

56
apps/vue/src/api/caching-management/cache/index.ts

@ -0,0 +1,56 @@
import { defAbpHttp } from '/@/utils/http/abp';
import {
CacheKeys,
CacheValue,
CacheRefreshRequest,
GetCacheKeysRequest,
} from './model';
const remoteServiceName = 'CachingManagement';
const controllerName = 'Cache';
export const getKeys = (input: GetCacheKeysRequest) => {
return defAbpHttp.request<CacheKeys>({
service: remoteServiceName,
controller: controllerName,
action: 'GetKeysAsync',
params: {
input: input,
},
});
};
export const getValue = (key: string) => {
return defAbpHttp.request<CacheValue>({
service: remoteServiceName,
controller: controllerName,
action: 'GetValueAsync',
params: {
input: {
key: key,
}
},
});
};
export const refresh = (input: CacheRefreshRequest) => {
return defAbpHttp.request<void>({
service: remoteServiceName,
controller: controllerName,
action: 'RefreshAsync',
data: input,
});
};
export const remove = (key: string) => {
return defAbpHttp.request<void>({
service: remoteServiceName,
controller: controllerName,
action: 'RemoveAsync',
params: {
input: {
key: key,
}
},
});
};

23
apps/vue/src/api/caching-management/cache/model/index.ts

@ -0,0 +1,23 @@
export interface CacheKeys {
nextMarker: string;
keys: string[],
}
export interface CacheValue {
type: string;
size: number;
expiration?: Date;
values: {[key:string]: any};
}
export interface CacheRefreshRequest {
key: string;
absoluteExpiration?: Date;
slidingExpiration?: Date;
}
export interface GetCacheKeysRequest {
prefix?: string;
marker?: string;
filter?: string;
}

12
apps/vue/src/api/demo/error.ts

@ -1,12 +0,0 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
// The address does not exist
Error = '/error',
}
/**
* @description: Trigger ajax error
*/
export const fireErrorApi = () => defHttp.get({ url: Api.Error });

16
apps/vue/src/api/identity/model/claimModel.ts

@ -45,3 +45,19 @@ export class GetIdentityClaimTypePagedRequest extends PagedAndSortedResultReques
export class IdentityClaimTypeListResult extends ListResultDto<IdentityClaimType> {}
export class IdentityClaimTypePagedResult extends PagedResultDto<IdentityClaimType> {}
export class IdentityClaim {
claimType = '';
claimValue = '';
}
export class DeleteIdentityClaim {
claimType = '';
claimValue = '';
}
export class CreateIdentityClaim extends IdentityClaim {}
export class UpdateIdentityClaim extends IdentityClaim {
newClaimValue!: string;
}

19
apps/vue/src/api/identity/model/roleModel.ts

@ -3,6 +3,7 @@ import {
PagedAndSortedResultRequestDto,
PagedResultDto,
} from '../../model/baseModel';
import { IdentityClaim } from './claimModel';
export class RoleBase {
name!: string;
@ -38,23 +39,7 @@ export class ChangeRoleOrganizationUnitDto {
organizationUnitIds: string[] = [];
}
export class RoleClaimBase {
claimType = '';
claimValue = '';
}
export class DeleteRoleClaim {
claimType = '';
claimValue = '';
}
export class CreateRoleClaim extends RoleClaimBase {}
export class UpdateRoleClaim extends RoleClaimBase {
newClaimValue!: string;
}
export class RoleClaim extends RoleClaimBase {
export class RoleClaim extends IdentityClaim {
id!: string;
}

18
apps/vue/src/api/identity/model/userModel.ts

@ -5,6 +5,7 @@ import {
PagedAndSortedResultRequestDto,
PagedResultDto,
} from '../../model/baseModel';
import { IdentityClaim } from './claimModel';
/** 用户对象接口 */
export interface IUser {
@ -29,6 +30,10 @@ export interface ChangePassword {
newPassword: string;
}
export interface SetPassword {
password: string;
}
/** 用户对象 */
export class User extends FullAuditedEntityDto implements IUser {
/** 用户名 */
@ -96,18 +101,7 @@ export class GetUserPagedRequest extends PagedAndSortedResultRequestDto {
export class UserPagedResult extends PagedResultDto<User> {}
export class UserClaimBase {
claimType = '';
claimValue = '';
}
export class CreateUserClaim extends UserClaimBase {}
export class UpdateUserClaim extends UserClaimBase {
newClaimValue!: string;
}
export class UserClaim extends UserClaimBase {
export class UserClaim extends IdentityClaim {
id!: string;
}

10
apps/vue/src/api/identity/organization-units.ts

@ -15,8 +15,8 @@ enum Api {
Create = '/api/identity/organization-units',
Delete = '/api/identity/organization-units/{id}',
Update = '/api/identity/organization-units/{id}',
GetById = '/api/identity/organization-units/{id}',
GetList = '/api/identity/organization-units',
GetById = '/api/identity/organization-units/{id}',
GetList = '/api/identity/organization-units',
GetAllList = '/api/identity/organization-units/all',
GetUnaddedMemberList = '/api/identity/organization-units/{id}/unadded-users',
GetMemberList = '/api/identity/organization-units/{id}/users',
@ -47,6 +47,12 @@ export const deleteById = (id: string) => {
});
};
export const get = (id: string) => {
return defAbpHttp.get<OrganizationUnit>({
url: format(Api.GetById, { id: id }),
});
}
export const getList = (input: GetOrganizationUnitPagedRequest) => {
return defAbpHttp.get<OrganizationUnitPagedResult>({
url: Api.GetList,

13
apps/vue/src/api/identity/role.ts

@ -6,21 +6,20 @@ import {
RolePagedResult,
UpdateRole,
CreateRole,
CreateRoleClaim,
RoleClaimListResult,
UpdateRoleClaim,
RoleClaim,
} from './model/roleModel';
import { format } from '/@/utils/strings';
import { CreateIdentityClaim, UpdateIdentityClaim } from './model/claimModel';
enum Api {
RemoteService = 'AbpIdentity',
Controller = 'IdentityRole',
Create = '/api/identity/roles',
CreateClaim = '/api/identity/roles/{id}/claims',
DeleteClaim = '',
DeleteClaim = '/api/identity/roles/{id}/claims',
Update = '/api/identity/roles/{id}',
UpdateClaim = '',
UpdateClaim = '/api/identity/roles/{id}/claims',
GetById = '/api/identity/roles/{id}',
GetAllList = '/api/identity/roles/all',
GetClaimList = '/api/identity/roles/{id}/claims',
@ -36,7 +35,7 @@ export const create = (input: CreateRole) => {
});
};
export const createClaim = (id: string, input: CreateRoleClaim) => {
export const createClaim = (id: string, input: CreateIdentityClaim) => {
return defAbpHttp.post<void>({
url: format(Api.CreateClaim, { id: id }),
data: input,
@ -50,9 +49,9 @@ export const update = (id: string, input: UpdateRole) => {
});
};
export const updateClaim = (id: string, input: UpdateRoleClaim) => {
export const updateClaim = (id: string, input: UpdateIdentityClaim) => {
return defAbpHttp.put<void>({
url: format(Api.CreateClaim, { id: id }),
url: format(Api.UpdateClaim, { id: id }),
data: input,
});
};

11
apps/vue/src/api/identity/user.ts

@ -3,16 +3,15 @@ import {
User,
UserClaimListResult,
CreateUser,
CreateUserClaim,
ChangePassword,
SetPassword,
UpdateUser,
GetUserPagedRequest,
UserPagedResult,
UpdateUserClaim,
UserClaim,
} from './model/userModel';
import { RoleListResult } from './model/roleModel';
import { format } from '/@/utils/strings';
import { CreateIdentityClaim, UpdateIdentityClaim } from './model/claimModel';
enum Api {
Create = '/api/identity/users',
@ -40,14 +39,14 @@ export const create = (input: CreateUser) => {
});
};
export const createClaim = (id: string, input: CreateUserClaim) => {
export const createClaim = (id: string, input: CreateIdentityClaim) => {
return defAbpHttp.post<void>({
url: format(Api.CreateClaim, { id: id }),
data: input,
});
};
export const changePassword = (id: string, input: ChangePassword) => {
export const changePassword = (id: string, input: SetPassword) => {
return defAbpHttp.put<void>({
url: Api.ChangePassword,
data: input,
@ -116,7 +115,7 @@ export const update = (id: string, input: UpdateUser) => {
});
};
export const updateClaim = (id: string, input: UpdateUserClaim) => {
export const updateClaim = (id: string, input: UpdateIdentityClaim) => {
return defAbpHttp.put<void>({
url: format(Api.CreateClaim, { id: id }),
data: input,

52
apps/vue/src/api/localization/languages.ts

@ -1,56 +1,12 @@
import { defAbpHttp } from '/@/utils/http/abp';
import {
Language,
LanguageCreateOrUpdate,
GetLanguagePagedRequest,
LanguageListResult,
LanguagePagedResult,
} from './model/languagesModel';
import { format } from '/@/utils/strings';
import { LanguageListResult } from './model/languagesModel';
enum Api {
Create = '/api/localization/languages',
DeleteById = '/api/localization/languages/{id}',
GetById = '/api/localization/languages/{id}',
GetList = '/api/localization/languages',
GetAllList = '/api/localization/languages/all',
GetList = '/api/abp/localization/languages',
}
export const get = (id: string) => {
return defAbpHttp.get<Language>({
url: format(Api.GetById, { id: id }),
});
};
export const create = (input: LanguageCreateOrUpdate) => {
return defAbpHttp.post<Language>({
url: Api.Create,
data: input,
});
};
export const deleteById = (id: string) => {
return defAbpHttp.delete<void>({
url: format(Api.GetById, { id: id }),
});
};
export const update = (id: string, input: LanguageCreateOrUpdate) => {
return defAbpHttp.put<Language>({
url: format(Api.GetById, { id: id }),
data: input,
});
};
export const getList = (input: GetLanguagePagedRequest) => {
return defAbpHttp.get<LanguagePagedResult>({
url: Api.GetList,
params: input,
});
};
export const getAll = () => {
export const getList = () => {
return defAbpHttp.get<LanguageListResult>({
url: Api.GetAllList,
url: Api.GetList,
});
};

5
apps/vue/src/api/localization/model/resourcesModel.ts

@ -1,13 +1,10 @@
import {
AuditedEntityDto,
ListResultDto,
PagedAndSortedResultRequestDto,
PagedResultDto,
} from '/@/api/model/baseModel';
export interface Resource extends AuditedEntityDto {
id: string;
enable: boolean;
export interface Resource {
name: string;
displayName: string;
description: string;

17
apps/vue/src/api/localization/model/textsModel.ts

@ -1,7 +1,6 @@
import { PagedAndSortedResultRequestDto, PagedResultDto } from '/@/api/model/baseModel';
import { ListResultDto } from '/@/api/model/baseModel';
export interface Text {
id?: number;
key: boolean;
value: string;
cultureName: string;
@ -9,7 +8,6 @@ export interface Text {
}
export interface TextDifference {
id: number;
key: boolean;
value: string;
cultureName: string;
@ -18,19 +16,14 @@ export interface TextDifference {
targetValue: string;
}
export interface TextCreateOrUpdate {
value: string;
}
export interface TextCreate extends TextCreateOrUpdate {
export interface SetTextInput {
key: boolean;
value: string;
cultureName: string;
resourceName: string;
}
export type TextUpdate = TextCreateOrUpdate;
export class TextPagedResult extends PagedResultDto<TextDifference> {}
export class TextListResult extends ListResultDto<TextDifference> {}
export interface GetTextByKey {
key: boolean;
@ -38,7 +31,7 @@ export interface GetTextByKey {
resourceName: string;
}
export class GetTextPagedRequest extends PagedAndSortedResultRequestDto {
export class GetTextRequest {
filter = '';
cultureName = '';
targetCultureName = '';

52
apps/vue/src/api/localization/resources.ts

@ -1,56 +1,12 @@
import { defAbpHttp } from '/@/utils/http/abp';
import {
Resource,
ResourceCreateOrUpdate,
GetResourcePagedRequest,
ResourceListResult,
ResourcePagedResult,
} from './model/resourcesModel';
import { format } from '/@/utils/strings';
import { ResourceListResult } from './model/resourcesModel';
enum Api {
Create = '/api/localization/resources',
DeleteById = '/api/localization/resources/{id}',
GetById = '/api/localization/resources/{id}',
GetList = '/api/localization/resources',
GetAllList = '/api/localization/resources/all',
GetList = '/api/abp/localization/resources',
}
export const get = (id: string) => {
return defAbpHttp.get<Resource>({
url: format(Api.GetById, { id: id }),
});
};
export const create = (input: ResourceCreateOrUpdate) => {
return defAbpHttp.post<Resource>({
url: Api.Create,
data: input,
});
};
export const deleteById = (id: string) => {
return defAbpHttp.delete<void>({
url: format(Api.GetById, { id: id }),
});
};
export const update = (id: string, input: ResourceCreateOrUpdate) => {
return defAbpHttp.put<Resource>({
url: format(Api.GetById, { id: id }),
data: input,
});
};
export const getList = (input: GetResourcePagedRequest) => {
return defAbpHttp.get<ResourcePagedResult>({
url: Api.GetList,
params: input,
});
};
export const getAll = () => {
export const getList = () => {
return defAbpHttp.get<ResourceListResult>({
url: Api.GetAllList,
url: Api.GetList,
});
};

43
apps/vue/src/api/localization/texts.ts

@ -1,28 +1,18 @@
import { defAbpHttp } from '/@/utils/http/abp';
import {
Text,
TextCreate,
TextUpdate,
SetTextInput,
GetTextByKey,
GetTextPagedRequest,
TextPagedResult,
GetTextRequest,
TextListResult,
} from './model/textsModel';
import { format } from '/@/utils/strings';
enum Api {
Create = '/api/localization/texts',
DeleteById = '/api/localization/texts/{id}',
GetById = '/api/localization/texts/{id}',
GetList = '/api/localization/texts',
GetByCulture = '/api/localization/texts/by-culture-key',
SetText = '/api/localization/texts',
GetList = '/api/abp/localization/texts',
GetByCulture = '/api/abp/localization/texts/by-culture-key',
}
export const get = (id: number) => {
return defAbpHttp.get<Text>({
url: format(Api.GetById, { id: id }),
});
};
export const getByCulture = (input: GetTextByKey) => {
return defAbpHttp.get<Text>({
url: Api.GetByCulture,
@ -30,28 +20,15 @@ export const getByCulture = (input: GetTextByKey) => {
});
};
export const create = (input: TextCreate) => {
return defAbpHttp.post<Text>({
url: Api.Create,
data: input,
});
};
export const deleteById = (id: string) => {
return defAbpHttp.delete<void>({
url: format(Api.GetById, { id: id }),
});
};
export const update = (id: number, input: TextUpdate) => {
export const setText = (input: SetTextInput) => {
return defAbpHttp.put<Text>({
url: format(Api.GetById, { id: id }),
url: Api.SetText,
data: input,
});
};
export const getList = (input: GetTextPagedRequest) => {
return defAbpHttp.get<TextPagedResult>({
export const getList = (input: GetTextRequest) => {
return defAbpHttp.get<TextListResult>({
url: Api.GetList,
params: input,
});

21
apps/vue/src/api/messages/notifications.ts

@ -3,13 +3,34 @@ import {
GetNotificationPagedRequest,
NotificationPagedResult,
NotificationGroupListResult,
NotificationReadState,
} from './model/notificationsModel';
import { format } from '/@/utils/strings';
enum Api {
GetById = '/api/my-notifilers/{id}',
GetList = '/api/my-notifilers',
GetAssignableNotifiers = '/api/my-notifilers/assignables',
Read = '/api/my-notifilers/{id}/read',
MarkReadState = '/api/my-notifilers/mark-read-state',
}
export const markReadState = (ids: string[], state: NotificationReadState = NotificationReadState.Read) => {
return defHttp.put<void>({
url: Api.MarkReadState,
data: {
idList: ids,
state: state,
},
});
};
export const deleteById = (id: string) => {
return defHttp.delete<void>({
url: format(Api.GetById, { id: id }),
});
};
export const getList = (input: GetNotificationPagedRequest) => {
return defHttp.get<NotificationPagedResult>({
url: Api.GetList,

1
apps/vue/src/api/multi-tenancy/models/tenantModel.ts

@ -40,4 +40,5 @@ export class FindTenantResult {
name = '';
tenantId = '';
success = '';
isActive = false;
}

71
apps/vue/src/api/openiddict/applications/index.ts

@ -0,0 +1,71 @@
import { defAbpHttp } from '/@/utils/http/abp';
import {
OpenIddictApplicationDto,
OpenIddictApplicationCreateDto,
OpenIddictApplicationUpdateDto,
OpenIddictApplicationGetListInput,
} from './model';
import { PagedResultDto } from '../../model/baseModel';
const remoteServiceName = 'AbpOpenIddict';
const controllerName = 'OpenIddictApplication';
export const getById = (id: string) => {
return defAbpHttp.request<OpenIddictApplicationDto>({
service: remoteServiceName,
controller: controllerName,
action: 'GetAsync',
params: {
id: id,
},
});
};
export const getList = (input: OpenIddictApplicationGetListInput) => {
return defAbpHttp.get<PagedResultDto<OpenIddictApplicationDto>>({
url: '/api/openiddict/applications',
params: input,
}, {
withToken: false
});
};
// export const getList = (input: OpenIddictApplicationGetListInput) => {
// return defAbpHttp.pagedRequest<OpenIddictApplicationDto>({
// service: remoteServiceName,
// controller: controllerName,
// action: 'GetListAsync',
// params: {
// input: input,
// },
// });
// };
export const deleteById = (id: string) => {
return defAbpHttp.request<void>({
service: remoteServiceName,
controller: controllerName,
action: 'DeleteAsync',
params: {
id: id,
},
});
};
export const create = (input: OpenIddictApplicationCreateDto) => {
return defAbpHttp.request<OpenIddictApplicationDto>({
service: remoteServiceName,
controller: controllerName,
action: 'CreateAsync',
data: input,
});
};
export const update = (input: OpenIddictApplicationUpdateDto) => {
return defAbpHttp.request<OpenIddictApplicationDto>({
service: remoteServiceName,
controller: controllerName,
action: 'UpdateAsync',
data: input,
});
};

47
apps/vue/src/api/openiddict/applications/model/index.ts

@ -0,0 +1,47 @@
import { ExtensibleObject, ExtensibleAuditedEntity, PagedAndSortedResultRequestDto } from '../../../model/baseModel';
export interface OpenIddictApplicationDto extends ExtensibleAuditedEntity<string> {
clientId: string;
clientSecret?: string;
consentType?: string;
displayName?: string;
displayNames?: {[key: string]: string};
endpoints?: string[];
grantTypes?: string[];
responseTypes?: string[];
scopes?: string[];
postLogoutRedirectUris?: string[];
properties?: {[key: string]: string};
redirectUris?: string[];
requirements?: string[];
type?: string;
clientUri?: string;
logoUri?: string;
}
export interface OpenIddictApplicationGetListInput extends PagedAndSortedResultRequestDto {
filter?: string;
}
interface OpenIddictApplicationCreateOrUpdateDto extends ExtensibleObject {
clientId: string;
clientSecret?: string;
consentType?: string;
displayName?: string;
displayNames?: {[key: string]: string};
endpoints?: string[];
grantTypes?: string[];
responseTypes?: string[];
scopes?: string[];
postLogoutRedirectUris?: string[];
properties?: {[key: string]: string};
redirectUris?: string[];
requirements?: string[];
type?: string;
clientUri?: string;
logoUri?: string;
}
export type OpenIddictApplicationCreateDto = OpenIddictApplicationCreateOrUpdateDto;
export type OpenIddictApplicationUpdateDto = OpenIddictApplicationCreateOrUpdateDto;

51
apps/vue/src/api/openiddict/authorizations/index.ts

@ -0,0 +1,51 @@
import { defAbpHttp } from '/@/utils/http/abp';
import {
OpenIddictAuthorizationDto,
OpenIddictAuthorizationGetListInput,
} from './model';
import { PagedResultDto } from '../../model/baseModel';
const remoteServiceName = 'AbpOpenIddict';
const controllerName = 'OpenIddictAuthorization';
export const getById = (id: string) => {
return defAbpHttp.request<OpenIddictAuthorizationDto>({
service: remoteServiceName,
controller: controllerName,
action: 'GetAsync',
params: {
id: id,
},
});
};
// export const getList = (input: OpenIddictAuthorizationGetListInput) => {
// return defAbpHttp.pagedRequest<OpenIddictAuthorizationDto>({
// service: remoteServiceName,
// controller: controllerName,
// action: 'GetListAsync',
// params: {
// input: input,
// },
// });
// };
export const getList = (input: OpenIddictAuthorizationGetListInput) => {
return defAbpHttp.get<PagedResultDto<OpenIddictAuthorizationDto>>({
url: '/api/openiddict/authorizations',
params: input,
}, {
withToken: false
});
};
export const deleteById = (id: string) => {
return defAbpHttp.request<void>({
service: remoteServiceName,
controller: controllerName,
action: 'DeleteAsync',
params: {
id: id,
},
});
};

21
apps/vue/src/api/openiddict/authorizations/model/index.ts

@ -0,0 +1,21 @@
import { ExtensibleAuditedEntity, PagedAndSortedResultRequestDto } from '../../../model/baseModel';
export interface OpenIddictAuthorizationDto extends ExtensibleAuditedEntity<string> {
applicationId?: string;
creationDate?: Date;
properties?: {[key: string]: string};
scopes?: string[];
type?: string;
status?: string;
subject?: string;
}
export interface OpenIddictAuthorizationGetListInput extends PagedAndSortedResultRequestDto {
filter?: string;
subject?: string;
clientId?: string;
status?: string;
type?: string;
beginCreationTime?: Date;
endCreationTime?: string;
}

61
apps/vue/src/api/openiddict/scopes/index.ts

@ -0,0 +1,61 @@
import { defAbpHttp } from '/@/utils/http/abp';
import {
OpenIddictScopeDto,
OpenIddictScopeCreateDto,
OpenIddictScopeUpdateDto,
OpenIddictScopeGetListInput,
} from './model';
const remoteServiceName = 'AbpOpenIddict';
const controllerName = 'OpenIddictScope';
export const getById = (id: string) => {
return defAbpHttp.request<OpenIddictScopeDto>({
service: remoteServiceName,
controller: controllerName,
action: 'GetAsync',
params: {
id: id,
},
});
};
export const getList = (input: OpenIddictScopeGetListInput) => {
return defAbpHttp.pagedRequest<OpenIddictScopeDto>({
service: remoteServiceName,
controller: controllerName,
action: 'GetListAsync',
params: {
input: input,
},
});
};
export const deleteById = (id: string) => {
return defAbpHttp.request<void>({
service: remoteServiceName,
controller: controllerName,
action: 'DeleteAsync',
params: {
id: id,
},
});
};
export const create = (input: OpenIddictScopeCreateDto) => {
return defAbpHttp.request<OpenIddictScopeDto>({
service: remoteServiceName,
controller: controllerName,
action: 'CreateAsync',
data: input,
});
};
export const update = (input: OpenIddictScopeUpdateDto) => {
return defAbpHttp.request<OpenIddictScopeDto>({
service: remoteServiceName,
controller: controllerName,
action: 'UpdateAsync',
data: input,
});
};

29
apps/vue/src/api/openiddict/scopes/model/index.ts

@ -0,0 +1,29 @@
import { ExtensibleObject, ExtensibleAuditedEntity, PagedAndSortedResultRequestDto } from '../../../model/baseModel';
export interface OpenIddictScopeDto extends ExtensibleAuditedEntity<string> {
name: string;
displayName?: string;
displayNames?: {[key: string]: string};
description?: string;
descriptions?: {[key: string]: string};
properties?: {[key: string]: string};
resources?: {[key: string]: string};
}
export interface OpenIddictScopeGetListInput extends PagedAndSortedResultRequestDto {
filter?: string;
}
interface OpenIddictScopeCreateOrUpdateDto extends ExtensibleObject {
name: string;
displayName?: string;
displayNames?: {[key: string]: string};
description?: string;
descriptions?: {[key: string]: string};
properties?: {[key: string]: string};
resources?: {[key: string]: string};
}
export type OpenIddictScopeCreateDto = OpenIddictScopeCreateOrUpdateDto;
export type OpenIddictScopeUpdateDto = OpenIddictScopeCreateOrUpdateDto;

68
apps/vue/src/api/openiddict/tokens/index.ts

@ -0,0 +1,68 @@
import { defAbpHttp } from '/@/utils/http/abp';
import {
OpenIddictTokenDto,
OpenIddictTokenGetListInput,
} from './model';
import { PagedResultDto } from '../../model/baseModel';
const remoteServiceName = 'AbpOpenIddict';
const controllerName = 'OpenIddictToken';
// export const getById = (id: string) => {
// return defAbpHttp.request<OpenIddictTokenDto>({
// service: remoteServiceName,
// controller: controllerName,
// action: 'GetAsync',
// params: {
// id: id,
// },
// });
// };
export const getById = (id: string) => {
return defAbpHttp.get<OpenIddictTokenDto>({
url: `/api/openiddict/tokens/${id}`,
}, {
withToken: false
});
};
// export const getList = (input: OpenIddictTokenGetListInput) => {
// return defAbpHttp.pagedRequest<OpenIddictTokenDto>({
// service: remoteServiceName,
// controller: controllerName,
// action: 'GetListAsync',
// params: {
// input: input,
// },
// });
// };
export const getList = (input: OpenIddictTokenGetListInput) => {
return defAbpHttp.get<PagedResultDto<OpenIddictTokenDto>>({
url: '/api/openiddict/tokens',
params: input,
}, {
withToken: false
});
};
// export const deleteById = (id: string) => {
// return defAbpHttp.request<void>({
// service: remoteServiceName,
// controller: controllerName,
// action: 'DeleteAsync',
// params: {
// id: id,
// },
// });
// };
export const deleteById = (id: string) => {
return defAbpHttp.delete<void>({
url: `/api/openiddict/tokens/${id}`,
}, {
withToken: false
});
};

29
apps/vue/src/api/openiddict/tokens/model/index.ts

@ -0,0 +1,29 @@
import { ExtensibleAuditedEntity, PagedAndSortedResultRequestDto } from '../../../model/baseModel';
export interface OpenIddictTokenDto extends ExtensibleAuditedEntity<string> {
applicationId?: string;
authorizationId?: string;
creationDate?: Date;
expirationDate?: Date;
payload?: string;
properties?: string;
redemptionDate?: Date;
referenceId?: string;
type?: string;
status?: string;
subject?: string;
}
export interface OpenIddictTokenGetListInput extends PagedAndSortedResultRequestDto {
filter?: string;
clientId?: string;
authorizationId?: string;
subject?: string;
status?: string;
type?: string;
referenceId?: string;
beginCreationTime?: Date;
endCreationTime?: string;
beginExpirationDate?: Date;
endExpirationDate?: Date;
}

3
apps/vue/src/api/sys/model/menuModel.ts

@ -1,8 +1,7 @@
import type { RouteMeta } from '/@/router/types';
import type { RouteMeta } from 'vue-router';
export interface RouteItem {
path: string;
component: any;
components?: any;
meta: RouteMeta;
name?: string;
alias?: string | string[];

2
apps/vue/src/api/sys/model/userModel.ts

@ -4,6 +4,8 @@
export interface LoginParams {
username: string;
password: string;
twoFactorProvider?: string;
twoFactorCode?: string;
}
export interface LoginByPhoneParams {

2
apps/vue/src/api/sys/user.ts

@ -28,6 +28,8 @@ export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal')
grant_type: 'password',
username: params.username,
password: params.password,
TwoFactorProvider: params.twoFactorProvider,
TwoFactorCode: params.twoFactorCode,
};
return defHttp.post<LoginResultModel>(
{

51
apps/vue/src/api/task-management/backgroundJobAction.ts

@ -0,0 +1,51 @@
import { defAbpHttp } from '/@/utils/http/abp';
import {
BackgroundJobAction,
BackgroundJobActionDefinition,
CreateBackgroundJobAction,
UpdateBackgroundJobAction,
BackgroundJobActionGetDefinitionsInput
} from './model/backgroundJobActionModel';
import { format } from '/@/utils/strings';
import { ListResultDto } from '../model/baseModel';
enum Api {
AddAction = '/api/task-management/background-jobs/actions/{jobId}',
UpdateAction = '/api/task-management/background-jobs/actions/{id}',
DeleteAction = '/api/task-management/background-jobs/actions/{id}',
GetActions = '/api/task-management/background-jobs/actions/{jobId}',
GetDefinitions = '/api/task-management/background-jobs/actions/definitions',
}
export const addAction = (jobId: string, input: CreateBackgroundJobAction) => {
return defAbpHttp.post<BackgroundJobAction>({
url: format(Api.AddAction, { jobId: jobId }),
data: input,
});
};
export const updateAction = (id: string, input: UpdateBackgroundJobAction) => {
return defAbpHttp.put<BackgroundJobAction>({
url: format(Api.UpdateAction, { id: id }),
data: input,
});
};
export const deleteAction = (id: string) => {
return defAbpHttp.delete<void>({
url: format(Api.DeleteAction, { id: id }),
});
};
export const getActions = (jobId: string) => {
return defAbpHttp.get<ListResultDto<BackgroundJobAction>>({
url: format(Api.GetActions, { jobId: jobId }),
});
};
export const getDefinitions = (input: BackgroundJobActionGetDefinitionsInput) => {
return defAbpHttp.get<ListResultDto<BackgroundJobActionDefinition>>({
url: Api.GetDefinitions,
params: input,
});
};

10
apps/vue/src/api/task-management/backgroundJobInfo.ts

@ -3,10 +3,11 @@ import {
BackgroundJobInfo,
BackgroundJobInfoCreate,
BackgroundJobInfoUpdate,
BackgroundJobDefinition,
BackgroundJobInfoGetListInput,
} from './model/backgroundJobInfoModel';
import { format } from '/@/utils/strings';
import { PagedResultDto } from '../model/baseModel';
import { ListResultDto, PagedResultDto } from '../model/baseModel';
enum Api {
GetById = '/api/task-management/background-jobs/{id}',
@ -25,6 +26,7 @@ enum Api {
BulkStart = '/api/task-management/background-jobs/bulk-start',
BulkStop = '/api/task-management/background-jobs/bulk-stop',
BulkDelete = '/api/task-management/background-jobs/bulk-delete',
GetDefinitions = '/api/task-management/background-jobs/definitions',
}
export const getById = (id: string) => {
@ -40,6 +42,12 @@ export const getList = (input: BackgroundJobInfoGetListInput) => {
});
};
export const getDefinitions = () => {
return defAbpHttp.get<ListResultDto<BackgroundJobDefinition>>({
url: Api.GetDefinitions,
});
};
export const create = (input: BackgroundJobInfoCreate) => {
return defAbpHttp.post<BackgroundJobInfo>({
url: Api.Create,

43
apps/vue/src/api/task-management/model/backgroundJobActionModel.ts

@ -0,0 +1,43 @@
export enum JobActionType {
Failed = -1,
Successed = 0,
}
export interface BackgroundJobAction {
id: string;
jobId: string;
name: string;
displayName?: string;
isEnabled: boolean;
paramters: ExtraPropertyDictionary;
}
export interface BackgroundJobActionParamter {
name: string;
required: boolean;
displayName: string;
description?: string;
}
export interface BackgroundJobActionDefinition {
name: string;
type: JobActionType;
displayName: string;
description?: string;
paramters: BackgroundJobActionParamter[];
}
export interface CreateBackgroundJobAction {
name: string;
isEnabled: boolean;
paramters: ExtraPropertyDictionary;
}
export interface UpdateBackgroundJobAction {
isEnabled: boolean;
paramters: ExtraPropertyDictionary;
}
export interface BackgroundJobActionGetDefinitionsInput {
type?: JobActionType;
}

14
apps/vue/src/api/task-management/model/backgroundJobInfoModel.ts

@ -29,6 +29,20 @@ export enum JobPriority {
High = 25
}
export interface BackgroundJobParamter {
name: string;
required: boolean;
DisplayName: string;
Description?: string;
}
export interface BackgroundJobDefinition {
name: string;
displayName: string;
description?: string;
paramters: BackgroundJobParamter[];
}
export interface BackgroundJobInfo extends ExtensibleAuditedEntity<string>, IHasConcurrencyStamp {
isEnabled: boolean;
name: string;

64
apps/vue/src/api/text-templating/templates/index.ts

@ -0,0 +1,64 @@
import { defAbpHttp } from '/@/utils/http/abp';
import { PagedResultDto } from '../../model/baseModel';
import {
TextTemplateDefinition,
TextTemplateContent,
TextTemplateContentGetInput,
TextTemplateUpdateInput,
TextTemplateRestoreInput,
TextTemplateDefinitionGetListInput,
} from './model';
const remoteServiceName = 'AbpTextTemplating';
const controllerName = 'TextTemplate';
export const get = (name: string) => {
return defAbpHttp.request<TextTemplateDefinition>({
service: remoteServiceName,
controller: controllerName,
action: 'GetAsync',
params: {
name: name,
},
});
};
export const getContent = (input: TextTemplateContentGetInput) => {
return defAbpHttp.request<TextTemplateContent>({
service: remoteServiceName,
controller: controllerName,
action: 'GetContentAsync',
params: {
input: input,
},
});
}
export const getList = (input: TextTemplateDefinitionGetListInput) => {
return defAbpHttp.request<PagedResultDto<TextTemplateDefinition>>({
service: remoteServiceName,
controller: controllerName,
action: 'GetListAsync',
params: {
input: input,
},
});
};
export const restoreToDefault = (input: TextTemplateRestoreInput) => {
return defAbpHttp.request<void>({
service: remoteServiceName,
controller: controllerName,
action: 'RestoreToDefaultAsync',
data: input,
});
};
export const update = (input: TextTemplateUpdateInput) => {
return defAbpHttp.request<TextTemplateDefinition>({
service: remoteServiceName,
controller: controllerName,
action: 'UpdateAsync',
data: input,
});
};

36
apps/vue/src/api/text-templating/templates/model/index.ts

@ -0,0 +1,36 @@
import { PagedAndSortedResultRequestDto } from "/@/api/model/baseModel";
export interface TextTemplateDefinition {
name: string;
displayName: string;
defaultCultureName?: string;
isInlineLocalized: boolean;
isLayout: boolean;
layout?: string;
}
export interface TextTemplateContent {
name: string;
content?: string;
culture?: string;
}
export interface TextTemplateContentGetInput {
name: string;
culture?: string;
}
export interface TextTemplateRestoreInput {
name: string;
culture?: string;
}
export interface TextTemplateUpdateInput {
name: string;
culture?: string;
content: string;
}
export interface TextTemplateDefinitionGetListInput extends PagedAndSortedResultRequestDto {
filter?: string;
}

4
apps/vue/src/components/Application/src/AppLocalePicker.vue

@ -4,11 +4,11 @@
-->
<template>
<Dropdown
placement="bottomCenter"
placement="bottom"
:trigger="['click']"
:dropMenuList="localeList"
:selectedKeys="selectedKeys"
@menuEvent="handleMenuEvent"
@menu-event="handleMenuEvent"
overlayClassName="app-locale-picker-overlay"
>
<span class="cursor-pointer flex items-center">

5
apps/vue/src/components/Application/src/search/AppSearchModal.vue

@ -4,7 +4,7 @@
<div :class="getClass" @click.stop v-if="visible">
<div :class="`${prefixCls}-content`" v-click-outside="handleClose">
<div :class="`${prefixCls}-input__wrapper`">
<Input
<a-input
:class="`${prefixCls}-input`"
:placeholder="t('common.searchText')"
ref="inputRef"
@ -14,7 +14,7 @@
<template #prefix>
<SearchOutlined />
</template>
</Input>
</a-input>
<span :class="`${prefixCls}-cancel`" @click="handleClose">
{{ t('common.cancelText') }}
</span>
@ -62,7 +62,6 @@
import { SearchOutlined } from '@ant-design/icons-vue';
import AppSearchFooter from './AppSearchFooter.vue';
import Icon from '/@/components/Icon';
import { Input } from '/@/components/Input';
// @ts-ignore
import vClickOutside from '/@/directives/clickOutside';
import { useDesign } from '/@/hooks/web/useDesign';

166
apps/vue/src/components/CardList/src/CardList.vue

@ -1,3 +1,80 @@
<template>
<div class="p-2">
<div class="p-4 mb-2 bg-white">
<BasicForm @register="registerForm" />
</div>
<div class="p-2 bg-white">
<List
:grid="{ gutter: 5, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: grid }"
:data-source="data"
:pagination="paginationProp"
>
<template #header>
<div class="flex justify-end space-x-2"
><slot name="header"></slot>
<Tooltip>
<template #title>
<div class="w-50">每行显示数量</div
><Slider
id="slider"
v-bind="sliderProp"
v-model:value="grid"
@change="sliderChange"
/></template>
<Button><TableOutlined /></Button>
</Tooltip>
<Tooltip @click="fetch">
<template #title>刷新</template>
<Button><RedoOutlined /></Button>
</Tooltip>
</div>
</template>
<template #renderItem="{ item }">
<ListItem>
<Card>
<template #title></template>
<template #cover>
<div :class="height">
<Image :src="item.imgs[0]" />
</div>
</template>
<template #actions>
<!-- <SettingOutlined key="setting" />-->
<EditOutlined key="edit" />
<Dropdown
:trigger="['hover']"
:dropMenuList="[
{
text: '删除',
event: '1',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, item.id),
},
},
]"
popconfirm
>
<EllipsisOutlined key="ellipsis" />
</Dropdown>
</template>
<CardMeta>
<template #title>
<TypographyText :content="item.name" :ellipsis="{ tooltip: item.address }" />
</template>
<template #avatar>
<Avatar :src="item.avatar" />
</template>
<template #description>{{ item.time }}</template>
</CardMeta>
</Card>
</ListItem>
</template>
</List>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed, onMounted, ref } from 'vue';
import {
@ -9,6 +86,7 @@
import { List, Card, Image, Typography, Tooltip, Slider, Avatar } from 'ant-design-vue';
import { Dropdown } from '/@/components/Dropdown';
import { BasicForm, useForm } from '/@/components/Form';
import { propTypes } from '/@/utils/propTypes';
import { Button } from '/@/components/Button';
import { isFunction } from '/@/utils/is';
import { useSlider, grid } from './data';
@ -20,15 +98,9 @@
//
const props = defineProps({
// API
params: {
type: Object,
default: () => ({}),
},
params: propTypes.object.def({}),
//api
api: {
type: Function,
default: null,
},
api: propTypes.func,
});
//
const emit = defineEmits(['getMethod', 'delete']);
@ -103,81 +175,3 @@
emit('delete', id);
}
</script>
<template>
<div class="p-2">
<div class="p-4 mb-2 bg-white">
<BasicForm @register="registerForm" />
</div>
{{ sliderProp.width }}
<div class="p-2 bg-white">
<List
:grid="{ gutter: 5, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: grid }"
:data-source="data"
:pagination="paginationProp"
>
<template #header>
<div class="flex justify-end space-x-2"
><slot name="header"></slot>
<Tooltip>
<template #title>
<div class="w-50">每行显示数量</div
><Slider
id="slider"
v-bind="sliderProp"
v-model:value="grid"
@change="sliderChange"
/></template>
<Button><TableOutlined /></Button>
</Tooltip>
<Tooltip @click="fetch">
<template #title>刷新</template>
<Button><RedoOutlined /></Button>
</Tooltip>
</div>
</template>
<template #renderItem="{ item }">
<ListItem>
<Card>
<template #title></template>
<template #cover>
<div :class="height">
<Image :src="item.imgs[0]" />
</div>
</template>
<template #actions>
<EditOutlined key="edit" />
<Dropdown
:trigger="['hover']"
:dropMenuList="[
{
text: '删除',
event: '1',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, item.id),
},
},
]"
popconfirm
>
<EllipsisOutlined key="ellipsis" />
</Dropdown>
</template>
<CardMeta>
<template #title>
<TypographyText :content="item.name" :ellipsis="{ tooltip: item.address }" />
</template>
<template #avatar>
<Avatar :src="item.avatar" />
</template>
<template #description>{{ item.time }}</template>
</CardMeta>
</Card>
</ListItem>
</template>
</List>
</div>
</div>
</template>

2
apps/vue/src/components/CardList/src/data.ts

@ -1,5 +1,5 @@
import { ref } from 'vue';
//每行个数
// 每行个数
export const grid = ref(12);
// slider属性
export const useSlider = (min = 6, max = 12) => {

2
apps/vue/src/components/CodeEditor/index.ts

@ -1,8 +1,10 @@
import { withInstall } from '/@/utils';
import codeEditor from './src/CodeEditor.vue';
import codeEditorX from './src/codemirrorX/CodeMirrorX.vue';
import jsonPreview from './src/json-preview/JsonPreview.vue';
export const CodeEditor = withInstall(codeEditor);
export const CodeEditorX = withInstall(codeEditorX);
export const JsonPreview = withInstall(jsonPreview);
export * from './src/typing';

10
apps/vue/src/components/CodeEditor/src/codemirror/codemirror.css

@ -39,7 +39,7 @@
.CodeMirror-gutters {
position: absolute;
top: 0;
left: 0;
left: 5 !important;
z-index: 3;
min-height: 100%;
white-space: nowrap;
@ -49,11 +49,11 @@
.CodeMirror-linenumber {
min-width: 20px;
padding: 0 3px 0 5px;
padding: 1 8px 0 5px;
color: var(--comment);
text-align: right;
text-align: left !important;
white-space: nowrap;
opacity: 60%;
opacity: 0.6;
}
.CodeMirror-guttermarker {
@ -90,7 +90,7 @@
display: inline-block;
font-size: 0.8em;
content: '>';
opacity: 80%;
opacity: 0.8;
transform: rotate(90deg);
transition: transform 0.2s;
}

137
apps/vue/src/components/CodeEditor/src/codemirrorX/CodeMirrorX.vue

@ -0,0 +1,137 @@
<template>
<textarea style="overflow: auto;" ref="codeEditor"></textarea>
</template>
<script lang="ts" setup>
import { computed, ref, unref, watch, nextTick, onMounted } from 'vue';
import CodeMirror from 'codemirror';
import '../codemirror/codemirror.css';
import 'codemirror/theme/idea.css';
import 'codemirror/theme/dracula.css';
import 'codemirror/mode/javascript/javascript';
import 'codemirror/mode/htmlmixed/htmlmixed';
import 'codemirror/mode/css/css';
import 'codemirror/addon/fold/foldcode';
import 'codemirror/addon/fold/foldgutter';
import 'codemirror/addon/fold/foldgutter.css';
import 'codemirror/addon/fold/brace-fold';
import 'codemirror/addon/fold/xml-fold';
import 'codemirror/addon/fold/comment-fold';
import 'codemirror/addon/fold/markdown-fold';
import 'codemirror/addon/fold/indent-fold';
import 'codemirror/addon/edit/closebrackets';
import 'codemirror/addon/edit/closetag';
import 'codemirror/addon/edit/matchtags';
import 'codemirror/addon/edit/matchbrackets';
import 'codemirror/addon/selection/active-line';
import "codemirror/addon/scroll/annotatescrollbar";
import 'codemirror/addon/dialog/dialog';
import 'codemirror/addon/dialog/dialog.css';
import 'codemirror/addon/display/autorefresh';
import 'codemirror/addon/display/placeholder';
import 'codemirror/addon/selection/mark-selection';
import { MODE } from './../typing';
import { isString } from '/@/utils/is';
import { useAppStore } from '/@/store/modules/app';
import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
const codeEditor = ref();
const appStore = useAppStore();
let editor: Nullable<CodeMirror.Editor>;
const props = defineProps({
mode: {
type: String as PropType<MODE>,
default: MODE.JSON,
validator(value: any) {
//
return Object.values(MODE).includes(value);
},
},
modelValue: {
type: [Object, String] as PropType<Record<string, any> | string>,
default: '',
},
readonly: {
type: Boolean,
default: false,
},
});
const emits = defineEmits(['update:modelValue', 'format-error']);
const getValue = computed(() => {
const { mode, modelValue } = props;
if (mode !== MODE.JSON) {
return modelValue as string;
}
let result = modelValue;
if (isString(result)) {
try {
result = JSON.parse(result);
} catch (e) {
emits('format-error', modelValue);
return modelValue as string;
}
}
return JSON.stringify(result, null, 2);
});
watch(
() => getValue.value,
async (value) => {
await nextTick();
const oldValue = editor?.getValue();
if (value !== oldValue) {
setTimeout(() => {
editor?.setValue(value);
}, 100);
}
},
{ flush: 'post' },
);
watch(
() => appStore.getDarkMode,
async () => {
setTheme();
},
{
immediate: true,
},
);
function setTheme() {
unref(editor)?.setOption(
'theme',
appStore.getDarkMode === 'light' ? 'idea' : 'dracula',
);
}
onMounted(() => {
editor = CodeMirror.fromTextArea(codeEditor.value, {
value: '',
autoRefresh: true,
mode: props.mode,
indentWithTabs: false, // n*tabntabfalse
smartIndent: true, // true
lineNumbers: true, //
matchBrackets: true, //
readOnly: props.readonly,
// :
foldGutter: true,
lineWrapping: true,
// :
styleActiveLine: true, //
});
// change
editor.on("change", () => {
// v-model
emits('update:modelValue', editor!.getValue());
});
useWindowSizeFn(editor.refresh);
});
</script>

1
apps/vue/src/components/CodeEditor/src/json-preview/JsonPreview.vue

@ -3,7 +3,6 @@
</template>
<script lang="ts" setup>
import { defineProps } from 'vue';
import VueJsonPretty from 'vue-json-pretty';
import 'vue-json-pretty/lib/styles.css';

11
apps/vue/src/components/Container/src/collapse/CollapseContainer.vue

@ -1,6 +1,6 @@
<template>
<div :class="prefixCls">
<CollapseHeader v-bind="$props" :prefixCls="prefixCls" :show="show" @expand="handleExpand">
<CollapseHeader v-bind="props" :prefixCls="prefixCls" :show="show" @expand="handleExpand">
<template #title>
<slot name="title"></slot>
</template>
@ -25,6 +25,7 @@
<script lang="ts" setup>
import type { PropType } from 'vue';
import { ref } from 'vue';
import { isNil } from 'lodash-es';
// component
import { Skeleton } from 'ant-design-vue';
import { CollapseTransition } from '/@/components/Transition';
@ -66,13 +67,17 @@
/**
* @description: Handling development events
*/
function handleExpand() {
show.value = !show.value;
function handleExpand(val: boolean) {
show.value = isNil(val) ? !show.value : val;
if (props.triggerWindowResize) {
// 200 milliseconds here is because the expansion has animation,
useTimeoutFn(triggerWindowResize, 200);
}
}
defineExpose({
handleExpand,
});
</script>
<style lang="less">
@prefix-cls: ~'@{namespace}-collapse-container';

22
apps/vue/src/components/ContextMenu/src/ContextMenu.vue

@ -60,9 +60,11 @@
const top = body.clientHeight < y + menuHeight ? y - menuHeight : y;
return {
...styles,
position: 'absolute',
width: `${width}px`,
left: `${left + 1}px`,
top: `${top + 1}px`,
zIndex: 9999,
};
});
@ -87,7 +89,8 @@
}
function renderMenuItem(items: ContextMenuItem[]) {
return items.map((item) => {
const visibleItems = items.filter((item) => !item.hidden);
return visibleItems.map((item) => {
const { disabled, label, children, divider = false } = item;
const contentProps = {
@ -124,15 +127,11 @@
}
const { items } = props;
return (
<Menu
inlineIndent={12}
mode="vertical"
class={prefixCls}
ref={wrapRef}
style={unref(getStyle)}
>
{renderMenuItem(items)}
</Menu>
<div class={prefixCls}>
<Menu inlineIndent={12} mode="vertical" ref={wrapRef} style={unref(getStyle)}>
{renderMenuItem(items)}
</Menu>
</div>
);
};
},
@ -185,6 +184,9 @@
background-clip: padding-box;
user-select: none;
&__item {
margin: 0 !important;
}
.item-style();
.ant-divider {

1
apps/vue/src/components/ContextMenu/src/typing.ts

@ -6,6 +6,7 @@ export interface Axis {
export interface ContextMenuItem {
label: string;
icon?: string;
hidden?: boolean;
disabled?: boolean;
handler?: Fn;
divider?: boolean;

7
apps/vue/src/components/CountDown/src/CountdownInput.vue

@ -1,16 +1,15 @@
<template>
<Input v-bind="$attrs" autocomplete="off" :class="prefixCls" :size="size" :value="state">
<a-input v-bind="$attrs" :class="prefixCls" :size="size" :value="state">
<template #addonAfter>
<CountButton :size="size" :count="count" :value="state" :beforeStartFunc="sendCodeApi" />
</template>
<template #[item]="data" v-for="item in Object.keys($slots).filter((k) => k !== 'addonAfter')">
<slot :name="item" v-bind="data || {}"></slot>
</template>
</Input>
</a-input>
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue';
import { Input } from 'ant-design-vue';
import CountButton from './CountButton.vue';
import { useDesign } from '/@/hooks/web/useDesign';
import { useRuleFormItem } from '/@/hooks/component/useFormItem';
@ -27,7 +26,7 @@
export default defineComponent({
name: 'CountDownInput',
components: { CountButton, Input },
components: { CountButton },
inheritAttrs: false,
props,
setup(props) {

2
apps/vue/src/components/Cropper/src/CropperAvatar.vue

@ -22,7 +22,7 @@
<CopperModal
@register="register"
@uploadSuccess="handleUploadSuccess"
@upload-success="handleUploadSuccess"
:uploadApi="uploadApi"
:src="sourceValue"
/>

5
apps/vue/src/components/Description/src/Description.vue

@ -3,7 +3,7 @@
import type { DescriptionsProps } from 'ant-design-vue/es/descriptions/index';
import type { CSSProperties } from 'vue';
import type { CollapseContainerOptions } from '/@/components/Container/index';
import { defineComponent, computed, ref, unref } from 'vue';
import { defineComponent, computed, ref, unref, toRefs } from 'vue';
import { get } from 'lodash-es';
import { Descriptions } from 'ant-design-vue';
import { CollapseContainer } from '/@/components/Container/index';
@ -121,6 +121,9 @@
return null;
}
const getField = get(_data, field);
if (getField && !toRefs(_data).hasOwnProperty(field)) {
return isFunction(render) ? render('', _data) : '';
}
return isFunction(render) ? render(getField, _data) : getField ?? '';
};

2
apps/vue/src/components/Drawer/src/BasicDrawer.vue

@ -94,7 +94,7 @@
opt.width = '100%';
}
const detailCls = `${prefixCls}__detail`;
opt.wrapClassName = wrapClassName ? `${wrapClassName} ${detailCls}` : detailCls;
opt.class = wrapClassName ? `${wrapClassName} ${detailCls}` : detailCls;
if (!getContainer) {
// TODO type error?

2
apps/vue/src/components/Drawer/src/components/DrawerFooter.vue

@ -47,7 +47,7 @@
const heightStr = `${props.height}`;
return {
height: heightStr,
lineHeight: heightStr,
lineHeight: `calc(${heightStr} - 1px)`,
};
});

3
apps/vue/src/components/Drawer/src/typing.ts

@ -128,13 +128,12 @@ export interface DrawerProps extends DrawerFooterProps {
* @type any (string | slot)
*/
title?: VNodeChild | JSX.Element;
/**
* The class name of the container of the Drawer dialog.
* @type string
*/
wrapClassName?: string;
class?: string;
/**
* Style of wrapper element which **contains mask** compare to `drawerStyle`
* @type object

2
apps/vue/src/components/Excel/src/Export2Excel.ts

@ -1,4 +1,4 @@
import xlsx from 'xlsx';
import * as xlsx from 'xlsx';
import type { WorkBook } from 'xlsx';
import type { JsonToSheet, AoAToSheet } from './typing';

3
apps/vue/src/components/Excel/src/ExportExcelModal.vue

@ -6,6 +6,7 @@
@register="registerModal"
>
<BasicForm
layout="vertical"
:labelWidth="100"
:schemas="schemas"
:showActionButtonGroup="false"
@ -28,6 +29,7 @@
field: 'filename',
component: 'Input',
label: t('component.excel.fileName'),
colProps: { span: 24 },
rules: [{ required: true }],
},
{
@ -35,6 +37,7 @@
component: 'Select',
label: t('component.excel.fileType'),
defaultValue: 'xlsx',
colProps: { span: 24 },
rules: [{ required: true }],
componentProps: {
options: [

2
apps/vue/src/components/Excel/src/ImportExcel.vue

@ -14,7 +14,7 @@
</template>
<script lang="ts">
import { defineComponent, ref, unref } from 'vue';
import XLSX from 'xlsx';
import * as XLSX from 'xlsx';
import { dateUtil } from '/@/utils/dateUtil';
import type { ExcelData } from './typing';

1
apps/vue/src/components/Form/index.ts

@ -12,5 +12,6 @@ export { default as RadioButtonGroup } from './src/components/RadioButtonGroup.v
export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue';
export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue';
export { default as ApiCascader } from './src/components/ApiCascader.vue';
export { default as ApiTransfer } from './src/components/ApiTransfer.vue';
export { BasicForm, TabForm };

18
apps/vue/src/components/Form/src/BasicForm.vue

@ -58,6 +58,7 @@
import { createFormContext } from './hooks/useFormContext';
import { useAutoFocus } from './hooks/useAutoFocus';
import { useModalContext } from '/@/components/Modal';
import { useDebounceFn } from '@vueuse/core';
import { basicProps } from './props';
import { useDesign } from '/@/hooks/web/useDesign';
@ -66,7 +67,7 @@
name: 'BasicForm',
components: { FormItem, Form, Row, FormAction },
props: basicProps,
emits: ['advanced-change', 'reset', 'submit', 'register'],
emits: ['advanced-change', 'reset', 'submit', 'register', 'field-value-change'],
setup(props, { emit, attrs }) {
const formModel = reactive<Recordable>({});
const modalFn = useModalContext();
@ -122,7 +123,7 @@
if (!Array.isArray(defaultValue)) {
schema.defaultValue = dateUtil(defaultValue);
} else {
const def: moment.Moment[] = [];
const def: any[] = [];
defaultValue.forEach((item) => {
def.push(dateUtil(item));
});
@ -131,9 +132,9 @@
}
}
if (unref(getProps).showAdvancedButton) {
return schemas.filter((schema) => schema.component !== 'Divider') as FormSchema[];
return schemas.filter((schema) => schema.component !== 'Divider');
} else {
return schemas as FormSchema[];
return schemas;
}
});
@ -225,6 +226,14 @@
},
);
watch(
() => formModel,
useDebounceFn(() => {
unref(getProps).submitOnChange && handleSubmit();
}, 300),
{ deep: true },
);
async function setProps(formProps: Partial<FormProps>): Promise<void> {
propsRef.value = deepMerge(unref(propsRef) || {}, formProps);
}
@ -235,6 +244,7 @@
if (!validateTrigger || validateTrigger === 'change') {
validateFields([key]).catch((_) => {});
}
emit('field-value-change', key, value);
}
function handleEnterPress(e: KeyboardEvent) {

43
apps/vue/src/components/Form/src/TabForm.vue

@ -1,6 +1,6 @@
<template>
<Form
v-bind="{ ...$attrs, ...$props, ...getProps }"
v-bind="getBindValue"
:class="getFormClass"
ref="formElRef"
:model="formModel"
@ -34,7 +34,7 @@
</TabPane>
</Tabs>
<FormAction v-bind="{ ...getProps, ...advanceState }" @toggle-advanced="handleToggleAdvanced">
<FormAction v-bind="getFormActionBindProps" @toggle-advanced="handleToggleAdvanced">
<template
#[item]="data"
v-for="item in ['resetBefore', 'submitBefore', 'advanceBefore', 'advanceAfter']"
@ -48,9 +48,10 @@
</template>
<script lang="ts">
import type { FormActionType, FormProps, FormSchema, TabFormSchema } from './types/form';
import dayjs from 'dayjs';
import type { FormActionType, TabFormProps, FormSchema, TabFormSchema } from './types/form';
import type { AdvanceState } from './types/hooks';
import type { CSSProperties, Ref } from 'vue';
import type { Ref } from 'vue';
import { defineComponent, reactive, ref, computed, unref, onMounted, watch, nextTick } from 'vue';
import { Form, Row, Tabs } from 'ant-design-vue';
@ -73,8 +74,7 @@
import { tabProps } from './props';
import { useDesign } from '/@/hooks/web/useDesign';
import type { RowProps } from 'ant-design-vue/lib/grid/Row';
import { mergeWith } from 'lodash-es';
export default defineComponent({
name: 'TabForm',
@ -88,7 +88,7 @@
},
props: tabProps,
emits: ['advanced-change', 'reset', 'submit', 'register'],
setup(props, { emit }) {
setup(props, { emit, attrs }) {
const formModel = reactive<Recordable>({});
const modalFn = useModalContext();
@ -102,15 +102,19 @@
const defaultValueRef = ref<Recordable>({});
const isInitedDefaultRef = ref(false);
const activedTabKey = ref('');
const propsRef = ref<Partial<FormProps>>({});
const propsRef = ref<Partial<TabFormProps>>({});
const schemaRef = ref<Nullable<TabFormSchema[]>>(null);
const formElRef = ref<Nullable<FormActionType>>(null);
const { prefixCls } = useDesign('basic-form');
const getBindValue = computed(
() => ({ ...attrs, ...props, ...unref(getProps) } as Recordable),
);
// Get the basic configuration of the form
const getProps = computed((): FormProps => {
return { ...props, ...unref(propsRef) } as FormProps;
const getProps = computed((): TabFormProps => {
return mergeWith(props, unref(propsRef)) as TabFormProps;
});
const getFormClass = computed(() => {
@ -123,7 +127,7 @@
});
// Get uniform row style and Row configuration for the entire form
const getRow = computed((): CSSProperties | RowProps => {
const getRow = computed((): Recordable => {
const { baseRowStyle = {}, rowProps } = unref(getProps);
return {
style: baseRowStyle,
@ -140,7 +144,7 @@
if (!Array.isArray(defaultValue)) {
schema.defaultValue = dateUtil(defaultValue);
} else {
const def: moment.Moment[] = [];
const def: dayjs.Dayjs[] = [];
defaultValue.forEach((item) => {
def.push(dateUtil(item));
});
@ -148,7 +152,11 @@
}
}
}
return schemas as TabFormSchema[];
if (unref(getProps).showAdvancedButton) {
return schemas.filter((schema) => schema.component !== 'Divider') as TabFormSchema[];
} else {
return schemas as TabFormSchema[];
}
});
const getTabSchema = computed((): { key: string; schemas: FormSchema[] }[] => {
@ -253,7 +261,7 @@
},
);
async function setProps(formProps: Partial<FormProps>): Promise<void> {
async function setProps(formProps: Partial<TabFormProps>): Promise<void> {
propsRef.value = deepMerge(unref(propsRef) || {}, formProps);
}
@ -294,6 +302,7 @@
});
return {
getBindValue,
handleToggleAdvanced,
handleEnterPress,
activedTabKey,
@ -305,10 +314,12 @@
formElRef,
getSchema,
getTabSchema,
formActionType,
formActionType: formActionType as any,
setFormModel,
prefixCls,
getFormClass,
getFormActionBindProps: computed(
(): Recordable => ({ ...getProps.value, ...advanceState }),
),
...formActionType,
};
},

4
apps/vue/src/components/Form/src/componentMap.ts

@ -24,8 +24,10 @@ import {
import ApiRadioGroup from './components/ApiRadioGroup.vue';
import RadioButtonGroup from './components/RadioButtonGroup.vue';
import ApiSelect from './components/ApiSelect.vue';
import ApiTree from './components/ApiTree.vue';
import ApiTreeSelect from './components/ApiTreeSelect.vue';
import ApiCascader from './components/ApiCascader.vue';
import ApiTransfer from './components/ApiTransfer.vue';
import { BasicUpload } from '/@/components/Upload';
import { StrengthMeter } from '/@/components/StrengthMeter';
import { IconPicker } from '/@/components/Icon';
@ -44,6 +46,7 @@ componentMap.set('AutoComplete', AutoComplete);
componentMap.set('Select', Select);
componentMap.set('ApiSelect', ApiSelect);
componentMap.set('ApiTree', ApiTree);
componentMap.set('TreeSelect', TreeSelect);
componentMap.set('ApiTreeSelect', ApiTreeSelect);
componentMap.set('ApiRadioGroup', ApiRadioGroup);
@ -56,6 +59,7 @@ componentMap.set('ApiCascader', ApiCascader);
componentMap.set('Cascader', Cascader);
componentMap.set('Slider', Slider);
componentMap.set('Rate', Rate);
componentMap.set('ApiTransfer', ApiTransfer);
componentMap.set('DatePicker', DatePicker);
componentMap.set('MonthPicker', DatePicker.MonthPicker);

5
apps/vue/src/components/Form/src/components/ApiCascader.vue

@ -26,7 +26,7 @@
import { get, omit } from 'lodash-es';
import { useRuleFormItem } from '/@/hooks/component/useFormItem';
import { LoadingOutlined } from '@ant-design/icons-vue';
import { useI18n } from '/@/hooks/web/useI18n';
interface Option {
value: string;
label: string;
@ -76,7 +76,7 @@
const loading = ref<boolean>(false);
const emitData = ref<any[]>([]);
const isFirstLoad = ref(true);
const { t } = useI18n();
// Embedded in the form, just use the hook binding to perform form verification
const [state] = useRuleFormItem(props, 'value', 'change', emitData);
@ -188,6 +188,7 @@
state,
options,
loading,
t,
handleChange,
loadData,
handleRenderDisplay,

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

Loading…
Cancel
Save