Merge pull request #56 from bufanyun/v2.0

up
This commit is contained in:
maxbad 2024-01-08 17:45:43 +08:00 committed by GitHub
commit de78b3604e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 1544 additions and 1304 deletions

View File

@ -6,19 +6,19 @@
</p> </p>
<p align="center"> <p align="center">
<a href="https://goframe.org/pages/viewpage.action?pageId=1114119" target="_blank"> <a href="https://goframe.org/pages/viewpage.action?pageId=1114119" target="_blank">
<img src="https://img.shields.io/badge/goframe-2.5-green" alt="goframe"> <img src="https://img.shields.io/badge/goframe-2.6-green" alt="goframe">
</a> </a>
<a href="https://v3.vuejs.org/" target="_blank"> <a href="https://v3.vuejs.org/" target="_blank">
<img src="https://img.shields.io/badge/vue.js-vue3.x-green" alt="vue"> <img src="https://img.shields.io/badge/vue.js-vue3.4-green" alt="vue">
</a> </a>
<a href="https://www.naiveui.com" target="_blank"> <a href="https://www.naiveui.com" target="_blank">
<img src="https://img.shields.io/badge/naiveui-%3E2.0.0-blue" alt="naiveui"> <img src="https://img.shields.io/badge/naiveui-%3E2.36.0-blue" alt="naiveui">
</a> </a>
<a href="https://www.tslang.cn/" target="_blank"> <a href="https://www.tslang.cn/" target="_blank">
<img src="https://img.shields.io/badge/typescript-%3E4.0.0-blue" alt="typescript"> <img src="https://img.shields.io/badge/typescript-%3E4.0.0-blue" alt="typescript">
</a> </a>
<a href="https://vitejs.dev/" target="_blank"> <a href="https://vitejs.dev/" target="_blank">
<img src="https://img.shields.io/badge/vite-%3E2.0.0-yellow" alt="vite"> <img src="https://img.shields.io/badge/vite-%3E4.0.0-yellow" alt="vite">
</a> </a>
<a href="https://github.com/bufanyun/hotgo/blob/v2.0/LICENSE" target="_blank"> <a href="https://github.com/bufanyun/hotgo/blob/v2.0/LICENSE" target="_blank">
<img src="https://img.shields.io/badge/license-MIT-success" alt="license"> <img src="https://img.shields.io/badge/license-MIT-success" alt="license">

View File

@ -10,7 +10,7 @@
1. 前往https://nodejs.org/zh-cn/下载当前版本node 1. 前往https://nodejs.org/zh-cn/下载当前版本node
2. 命令行运行 `node -v` 若控制台输出版本号则node安装成功 2. 命令行运行 `node -v` 若控制台输出版本号则node安装成功
3. node 版本需大于 `16.0` 3. node 版本需大于等于 `16.0`
4. 安装yarn`npm install -g yarn` 4. 安装yarn`npm install -g yarn`
5. 命令行运行 `yarn -v` 若控制台输出版本号则前端环境搭建成功 5. 命令行运行 `yarn -v` 若控制台输出版本号则前端环境搭建成功

View File

@ -9,7 +9,7 @@
- node版本 >= v16.0.0 - node版本 >= v16.0.0
- golang版本 >= v1.19 - golang版本 >= v1.19
- goframe版本 >=v2.4.1 - goframe版本 >=v2.6.1
- mysql版本 >=5.7 - mysql版本 >=5.7
> 必须先看[环境搭建文档](start-environment.md),如果安装遇到问题务必先查看[常见问题文档](start-issue.md) > 必须先看[环境搭建文档](start-environment.md),如果安装遇到问题务必先查看[常见问题文档](start-issue.md)

View File

@ -42,7 +42,21 @@
- http服务没有启动或正在启动 - http服务没有启动或正在启动
- 通过一键启动所有服务运行时属正常情况,多服务启动时存在先后顺序问题,`tcpClient`比`tcpServer`先启动完成导致的,等`tcpServer`启动完成后会自动重连 - 通过一键启动所有服务运行时属正常情况,多服务启动时存在先后顺序问题,`tcpClient`比`tcpServer`先启动完成导致的,等`tcpServer`启动完成后会自动重连
详细请参考 - [系统安装](start-installation.md) 详细请参考 - [系统安装](start-installation.md)
### 四、前端相关
#### 1、Error: connect ECONNREFUSED ::1:8000
```text
11:44:52 [vite] http proxy error at /member/info:
Error: connect ECONNREFUSED ::1:8000
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1246:16)
```
- 服务端没有启动
- `.\wen\.env.development`中的`VITE_PROXY`配置的服务器地址或端口与实际不一致

View File

@ -11,6 +11,16 @@
> 如果升级(覆盖)代码后打开会出现 sql 报错, 请检查更新的数据库格式或自行调整 > 如果升级(覆盖)代码后打开会出现 sql 报错, 请检查更新的数据库格式或自行调整
### v2.12.1
updated 2023.12.29
- 修复:修复访问日志权限过滤
- 优化gf版本升级到v2.6.1
- 优化naive-ui版本升级到2.36.0vue版本升级到3.4.0vite版本升级到4.2.7
- 优化优化curd代码生成编辑表单增加自适应详情改为`抽屉`,修复菜单权限关系树,简化`State`
- 优化:优化字典编辑和查询
- 优化:优化角色列表数据加载缓慢问题
### v2.11.5 ### v2.11.5
updated 2023.11.25 updated 2023.11.25

View File

@ -13,15 +13,15 @@ require (
github.com/casbin/casbin/v2 v2.55.0 github.com/casbin/casbin/v2 v2.55.0
github.com/forgoer/openssl v1.4.0 github.com/forgoer/openssl v1.4.0
github.com/go-pay/gopay v1.5.91 github.com/go-pay/gopay v1.5.91
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.7 github.com/gogf/gf/contrib/drivers/mysql/v2 v2.6.1
github.com/gogf/gf/contrib/nosql/redis/v2 v2.5.7 github.com/gogf/gf/contrib/nosql/redis/v2 v2.6.1
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.5.7 github.com/gogf/gf/contrib/trace/jaeger/v2 v2.6.1
github.com/gogf/gf/v2 v2.5.7 github.com/gogf/gf/v2 v2.6.1
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f
github.com/golang-jwt/jwt/v5 v5.0.0 github.com/golang-jwt/jwt/v5 v5.0.0
github.com/gorilla/websocket v1.5.1 github.com/gorilla/websocket v1.5.1
github.com/kayon/iploc v0.0.0-20200312105652-bda3e968a794 github.com/kayon/iploc v0.0.0-20200312105652-bda3e968a794
github.com/minio/minio-go/v7 v7.0.63 github.com/minio/minio-go/v7 v7.0.63
github.com/minio/selfupdate v0.6.0
github.com/mojocn/base64Captcha v1.3.5 github.com/mojocn/base64Captcha v1.3.5
github.com/olekukonko/tablewriter v0.0.5 github.com/olekukonko/tablewriter v0.0.5
github.com/qiniu/go-sdk/v7 v7.14.0 github.com/qiniu/go-sdk/v7 v7.14.0
@ -63,7 +63,7 @@ require (
github.com/fatih/color v1.16.0 // indirect github.com/fatih/color v1.16.0 // indirect
github.com/fatih/structs v1.1.0 // indirect github.com/fatih/structs v1.1.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect
@ -102,7 +102,7 @@ require (
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/redis/go-redis/v9 v9.3.0 // indirect github.com/redis/go-redis/v9 v9.3.1 // indirect
github.com/richardlehane/mscfb v1.0.4 // indirect github.com/richardlehane/mscfb v1.0.4 // indirect
github.com/richardlehane/msoleps v1.0.1 // indirect github.com/richardlehane/msoleps v1.0.1 // indirect
github.com/rivo/uniseg v0.4.4 // indirect github.com/rivo/uniseg v0.4.4 // indirect
@ -124,11 +124,11 @@ require (
go.opentelemetry.io/otel/sdk v1.21.0 // indirect go.opentelemetry.io/otel/sdk v1.21.0 // indirect
go.opentelemetry.io/otel/trace v1.21.0 // indirect go.opentelemetry.io/otel/trace v1.21.0 // indirect
go.uber.org/atomic v1.7.0 // indirect go.uber.org/atomic v1.7.0 // indirect
golang.org/x/crypto v0.15.0 // indirect golang.org/x/crypto v0.16.0 // indirect
golang.org/x/image v0.1.0 // indirect golang.org/x/image v0.1.0 // indirect
golang.org/x/net v0.18.0 // indirect golang.org/x/net v0.19.0 // indirect
golang.org/x/sync v0.1.0 // indirect golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.14.0 // indirect golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect

View File

@ -150,8 +150,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
@ -170,14 +170,16 @@ github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrt
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.7 h1:S6r4QJSoqmOv/Vqhu/gHt4if4dHrNyaQIUbjWc4W7sg= github.com/gogf/gf/contrib/drivers/mysql/v2 v2.6.1 h1:5VW1vlaFNSHHhMliRkGTcDshMeA52Il8T+gffJJaVMc=
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.7/go.mod h1:1/X4iVHxtSHjOMGYvnmFMTdk5zLLhQ6PEkslKTBcTSI= github.com/gogf/gf/contrib/drivers/mysql/v2 v2.6.1/go.mod h1:jxCa1WV/W+q0F4ILebakUsqRrl7iL3qvP+Uci0eXAew=
github.com/gogf/gf/contrib/nosql/redis/v2 v2.5.7 h1:HgOudyYp8F6iVC6YgbqKhPMKgxQJj4MO8VBdJEMPTpk= github.com/gogf/gf/contrib/nosql/redis/v2 v2.6.1 h1:5NWx7rZa8CbPNw1vbLzIXQFEMbKvoJVQM0GyReBRvJ8=
github.com/gogf/gf/contrib/nosql/redis/v2 v2.5.7/go.mod h1:jiRz86SerTb+z4KD4LtxgVw3IEcsWRBnL40FvIAg/sY= github.com/gogf/gf/contrib/nosql/redis/v2 v2.6.1/go.mod h1:iy1Dwp5xWfGfuWixCgGQ06ZX6lp+d9onbmSWWzi111A=
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.5.7 h1:ipIYW9q+Olkg9s86WpdPQ+wTFi1v6rsTiYAZ2ekqxH8= github.com/gogf/gf/contrib/trace/jaeger/v2 v2.6.1 h1:d3/8lWFWmaQ/8mzJ5GxyRpO4racPpZ3yZ8kCuejhhiY=
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.5.7/go.mod h1:KhUqGtEifCUd9pI274UkgSCMByof3aq2nW9GJRbwcOk= github.com/gogf/gf/contrib/trace/jaeger/v2 v2.6.1/go.mod h1:O0nzQLfNJtRApGHJluraTy41jc3LIvTsSkR8WAHb4f0=
github.com/gogf/gf/v2 v2.5.7 h1:h+JSoD6z3d2q0uGszvtahrSm4DiM2ECyNjyTwKIo8wE= github.com/gogf/gf/v2 v2.6.1 h1:n/cfXM506WjhPa6Z1CEDuHNM1XZ7C8JzSDPn2AfuxgQ=
github.com/gogf/gf/v2 v2.5.7/go.mod h1:x2XONYcI4hRQ/4gMNbWHmZrNzSEIg20s2NULbzom5k0= github.com/gogf/gf/v2 v2.6.1/go.mod h1:x2XONYcI4hRQ/4gMNbWHmZrNzSEIg20s2NULbzom5k0=
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f h1:7xfXR/BhG3JDqO1s45n65Oyx9t4E/UqDOXep6jXdLCM=
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f/go.mod h1:HnYoio6S7VaFJdryKcD/r9HgX+4QzYfr00XiXUo/xz0=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
@ -335,8 +337,6 @@ github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.63 h1:GbZ2oCvaUdgT5640WJOpyDhhDxvknAJU2/T3yurwcbQ= github.com/minio/minio-go/v7 v7.0.63 h1:GbZ2oCvaUdgT5640WJOpyDhhDxvknAJU2/T3yurwcbQ=
github.com/minio/minio-go/v7 v7.0.63/go.mod h1:Q6X7Qjb7WMhvG65qKf4gUgA5XaiSox74kR1uAEjxRS4= github.com/minio/minio-go/v7 v7.0.63/go.mod h1:Q6X7Qjb7WMhvG65qKf4gUgA5XaiSox74kR1uAEjxRS4=
github.com/minio/selfupdate v0.6.0 h1:i76PgT0K5xO9+hjzKcacQtO7+MjJ4JKA8Ak8XQ9DDwU=
github.com/minio/selfupdate v0.6.0/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
@ -410,8 +410,8 @@ github.com/qiniu/go-sdk/v7 v7.14.0/go.mod h1:btsaOc8CA3hdVloULfFdDgDc+g4f3TDZEFs
github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs= github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/redis/go-redis/v9 v9.3.0 h1:RiVDjmig62jIWp7Kk4XVLs0hzV6pI3PyTnnL0cnn0u0= github.com/redis/go-redis/v9 v9.3.1 h1:KqdY8U+3X6z+iACvumCNxnoluToB+9Me+TvyFa21Mds=
github.com/redis/go-redis/v9 v9.3.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/redis/go-redis/v9 v9.3.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM= github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
github.com/richardlehane/msoleps v1.0.1 h1:RfrALnSNXzmXLbGct/P2b4xkFz4e8Gmj/0Vj9M9xC1o= github.com/richardlehane/msoleps v1.0.1 h1:RfrALnSNXzmXLbGct/P2b4xkFz4e8Gmj/0Vj9M9xC1o=
@ -541,12 +541,11 @@ golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220408190544-5352b0902921/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220408190544-5352b0902921/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -624,8 +623,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -706,8 +705,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=

View File

@ -12,5 +12,5 @@ const (
UploadDriveCos = "cos" // 腾讯云cos UploadDriveCos = "cos" // 腾讯云cos
UploadDriveOss = "oss" // 阿里云oss UploadDriveOss = "oss" // 阿里云oss
UploadDriveQiNiu = "qiniu" // 七牛云对象存储 UploadDriveQiNiu = "qiniu" // 七牛云对象存储
UploadDriveMinio = "minio" // minio UploadDriveMinio = "minio" // minio对象存储
) )

View File

@ -7,5 +7,5 @@ package consts
// VersionApp HotGo版本 // VersionApp HotGo版本
const ( const (
VersionApp = "2.11.5" VersionApp = "2.12.1"
) )

View File

@ -82,11 +82,11 @@ func init() {
type ( type (
cRunInput struct { cRunInput struct {
g.Meta `name:"run"` g.Meta `name:"run"`
File string `name:"FILE" arg:"true" brief:"{cRunFileBrief}" v:"required"` File string `name:"FILE" arg:"true" brief:"{cRunFileBrief}" v:"required"`
Path string `name:"path" short:"p" brief:"{cRunPathBrief}" d:"./"` Path string `name:"path" short:"p" brief:"{cRunPathBrief}" d:"./"`
Extra string `name:"extra" short:"e" brief:"{cRunExtraBrief}"` Extra string `name:"extra" short:"e" brief:"{cRunExtraBrief}"`
Args string `name:"args" short:"a" brief:"{cRunArgsBrief}"` Args string `name:"args" short:"a" brief:"{cRunArgsBrief}"`
WatchPaths string `name:"watchPaths" short:"w" brief:"{cRunWatchPathsBrief}"` WatchPaths []string `name:"watchPaths" short:"w" brief:"{cRunWatchPathsBrief}"`
} }
cRunOutput struct{} cRunOutput struct{}
) )
@ -97,12 +97,16 @@ func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err err
mlog.Fatalf(`command "go" not found in your environment, please install golang first to proceed this command`) mlog.Fatalf(`command "go" not found in your environment, please install golang first to proceed this command`)
} }
if len(in.WatchPaths) == 1 {
in.WatchPaths = strings.Split(in.WatchPaths[0], ",")
}
app := &cRunApp{ app := &cRunApp{
File: in.File, File: in.File,
Path: in.Path, Path: in.Path,
Options: in.Extra, Options: in.Extra,
Args: in.Args, Args: in.Args,
WatchPaths: strings.Split(in.WatchPaths, ","), WatchPaths: in.WatchPaths,
} }
dirty := gtype.NewBool() dirty := gtype.NewBool()
_, err = gfsnotify.Add(gfile.RealPath("."), func(event *gfsnotify.Event) { _, err = gfsnotify.Add(gfile.RealPath("."), func(event *gfsnotify.Event) {

View File

@ -11,7 +11,7 @@ import (
"fmt" "fmt"
"runtime" "runtime"
"github.com/minio/selfupdate" "github.com/gogf/selfupdate"
"github.com/gogf/gf/v2/container/gset" "github.com/gogf/gf/v2/container/gset"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"

View File

@ -6,6 +6,33 @@
package cmd package cmd
import "context" import (
"context"
"fmt"
var ctx = context.Background() "github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/test/gtest"
)
var (
ctx = context.Background()
testDB gdb.DB
link = "mysql:root:12345678@tcp(127.0.0.1:3306)/test?loc=Local&parseTime=true"
)
func init() {
var err error
testDB, err = gdb.New(gdb.ConfigNode{
Link: link,
})
if err != nil {
panic(err)
}
}
func dropTableWithDb(db gdb.DB, table string) {
dropTableStmt := fmt.Sprintf("DROP TABLE IF EXISTS `%s`", table)
if _, err := db.Exec(ctx, dropTableStmt); err != nil {
gtest.Error(err)
}
}

View File

@ -11,7 +11,6 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/test/gtest" "github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
@ -20,22 +19,11 @@ import (
"hotgo/internal/library/hggen/internal/cmd/gendao" "hotgo/internal/library/hggen/internal/cmd/gendao"
) )
func dropTableWithDb(db gdb.DB, table string) {
dropTableStmt := fmt.Sprintf("DROP TABLE IF EXISTS `%s`", table)
if _, err := db.Exec(ctx, dropTableStmt); err != nil {
gtest.Error(err)
}
}
func Test_Gen_Dao_Default(t *testing.T) { func Test_Gen_Dao_Default(t *testing.T) {
link := "mysql:root:12345678@tcp(127.0.0.1:3306)/test?loc=Local&parseTime=true"
db, err := gdb.New(gdb.ConfigNode{
Link: link,
})
gtest.AssertNil(err)
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
var ( var (
err error
db = testDB
table = "table_user" table = "table_user"
sqlContent = fmt.Sprintf( sqlContent = fmt.Sprintf(
gtest.DataContent(`gendao`, `user.tpl.sql`), gtest.DataContent(`gendao`, `user.tpl.sql`),
@ -123,14 +111,10 @@ func Test_Gen_Dao_Default(t *testing.T) {
} }
func Test_Gen_Dao_TypeMapping(t *testing.T) { func Test_Gen_Dao_TypeMapping(t *testing.T) {
link := "mysql:root:12345678@tcp(127.0.0.1:3306)/test?loc=Local&parseTime=true"
db, err := gdb.New(gdb.ConfigNode{
Link: link,
})
gtest.AssertNil(err)
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
var ( var (
err error
db = testDB
table = "table_user" table = "table_user"
sqlContent = fmt.Sprintf( sqlContent = fmt.Sprintf(
gtest.DataContent(`gendao`, `user.tpl.sql`), gtest.DataContent(`gendao`, `user.tpl.sql`),

View File

@ -0,0 +1,70 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package cmd
import (
"fmt"
"os"
"path/filepath"
"testing"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/guid"
)
func Test_Gen_Pbentity_NameCase(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
db = testDB
table = "table_user"
sqlContent = fmt.Sprintf(
gtest.DataContent(`genpbentity`, `user.tpl.sql`),
table,
)
)
dropTableWithDb(db, table)
array := gstr.SplitAndTrim(sqlContent, ";")
for _, v := range array {
if _, err = db.Exec(ctx, v); err != nil {
t.AssertNil(err)
}
}
defer dropTableWithDb(db, table)
var path = gfile.Temp(guid.S())
err = gfile.Mkdir(path)
t.AssertNil(err)
defer gfile.Remove(path)
root, err := gcmd.NewFromObject(GF)
t.AssertNil(err)
err = root.AddObject(
Gen,
)
t.AssertNil(err)
os.Args = []string{"gf", "gen", "pbentity", "-l", link, "-p", path, "-package=unittest", "-nameCase=SnakeScreaming"}
err = root.RunWithError(ctx)
t.AssertNil(err)
files := []string{
filepath.FromSlash(path + "/table_user.proto"),
}
testPath := gtest.DataPath("genpbentity", "generated_user")
expectFiles := []string{
filepath.FromSlash(testPath + "/table_user.proto"),
}
// check files content
for i := range files {
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
}
})
}

View File

@ -74,7 +74,7 @@ type (
SdkStdVersion bool `short:"v" name:"sdkStdVersion" brief:"{CGenCtrlBriefSdkStdVersion}" orphan:"true"` SdkStdVersion bool `short:"v" name:"sdkStdVersion" brief:"{CGenCtrlBriefSdkStdVersion}" orphan:"true"`
SdkNoV1 bool `short:"n" name:"sdkNoV1" brief:"{CGenCtrlBriefSdkNoV1}" orphan:"true"` SdkNoV1 bool `short:"n" name:"sdkNoV1" brief:"{CGenCtrlBriefSdkNoV1}" orphan:"true"`
Clear bool `short:"c" name:"clear" brief:"{CGenCtrlBriefClear}" orphan:"true"` Clear bool `short:"c" name:"clear" brief:"{CGenCtrlBriefClear}" orphan:"true"`
Merge bool `short:"m" name:"merge" brief:"{CGenCtrlControllerMerge}" orphan:"true"` Merge bool `short:"m" name:"merge" brief:"{CGenCtrlControllerMerge}" orphan:"true"`
} }
CGenCtrlOutput struct{} CGenCtrlOutput struct{}
) )

View File

@ -59,28 +59,29 @@ CONFIGURATION SUPPORT
numeric: numeric:
type: string type: string
` `
CGenDaoBriefPath = `directory path for generated files` CGenDaoBriefPath = `directory path for generated files`
CGenDaoBriefLink = `database configuration, the same as the ORM configuration of GoFrame` CGenDaoBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
CGenDaoBriefTables = `generate models only for given tables, multiple table names separated with ','` CGenDaoBriefTables = `generate models only for given tables, multiple table names separated with ','`
CGenDaoBriefTablesEx = `generate models excluding given tables, multiple table names separated with ','` CGenDaoBriefTablesEx = `generate models excluding given tables, multiple table names separated with ','`
CGenDaoBriefPrefix = `add prefix for all table of specified link/database tables` CGenDaoBriefPrefix = `add prefix for all table of specified link/database tables`
CGenDaoBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','` CGenDaoBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
CGenDaoBriefStdTime = `use time.Time from stdlib instead of gtime.Time for generated time/date fields of tables` CGenDaoBriefRemoveFieldPrefix = `remove specified prefix of the field, multiple prefix separated with ','`
CGenDaoBriefWithTime = `add created time for auto produced go files` CGenDaoBriefStdTime = `use time.Time from stdlib instead of gtime.Time for generated time/date fields of tables`
CGenDaoBriefGJsonSupport = `use gJsonSupport to use *gjson.Json instead of string for generated json fields of tables` CGenDaoBriefWithTime = `add created time for auto produced go files`
CGenDaoBriefImportPrefix = `custom import prefix for generated go files` CGenDaoBriefGJsonSupport = `use gJsonSupport to use *gjson.Json instead of string for generated json fields of tables`
CGenDaoBriefDaoPath = `directory path for storing generated dao files under path` CGenDaoBriefImportPrefix = `custom import prefix for generated go files`
CGenDaoBriefDoPath = `directory path for storing generated do files under path` CGenDaoBriefDaoPath = `directory path for storing generated dao files under path`
CGenDaoBriefEntityPath = `directory path for storing generated entity files under path` CGenDaoBriefDoPath = `directory path for storing generated do files under path`
CGenDaoBriefOverwriteDao = `overwrite all dao files both inside/outside internal folder` CGenDaoBriefEntityPath = `directory path for storing generated entity files under path`
CGenDaoBriefModelFile = `custom file name for storing generated model content` CGenDaoBriefOverwriteDao = `overwrite all dao files both inside/outside internal folder`
CGenDaoBriefModelFileForDao = `custom file name generating model for DAO operations like Where/Data. It's empty in default` CGenDaoBriefModelFile = `custom file name for storing generated model content`
CGenDaoBriefDescriptionTag = `add comment to description tag for each field` CGenDaoBriefModelFileForDao = `custom file name generating model for DAO operations like Where/Data. It's empty in default`
CGenDaoBriefNoJsonTag = `no json tag will be added for each field` CGenDaoBriefDescriptionTag = `add comment to description tag for each field`
CGenDaoBriefNoModelComment = `no model comment will be added for each field` CGenDaoBriefNoJsonTag = `no json tag will be added for each field`
CGenDaoBriefClear = `delete all generated go files that do not exist in database` CGenDaoBriefNoModelComment = `no model comment will be added for each field`
CGenDaoBriefTypeMapping = `custom local type mapping for generated struct attributes relevant to fields of table` CGenDaoBriefClear = `delete all generated go files that do not exist in database`
CGenDaoBriefGroup = ` CGenDaoBriefTypeMapping = `custom local type mapping for generated struct attributes relevant to fields of table`
CGenDaoBriefGroup = `
specifying the configuration group name of database for generated ORM instance, specifying the configuration group name of database for generated ORM instance,
it's not necessary and the default value is "default" it's not necessary and the default value is "default"
` `
@ -145,6 +146,7 @@ func init() {
`CGenDaoBriefTablesEx`: CGenDaoBriefTablesEx, `CGenDaoBriefTablesEx`: CGenDaoBriefTablesEx,
`CGenDaoBriefPrefix`: CGenDaoBriefPrefix, `CGenDaoBriefPrefix`: CGenDaoBriefPrefix,
`CGenDaoBriefRemovePrefix`: CGenDaoBriefRemovePrefix, `CGenDaoBriefRemovePrefix`: CGenDaoBriefRemovePrefix,
`CGenDaoBriefRemoveFieldPrefix`: CGenDaoBriefRemoveFieldPrefix,
`CGenDaoBriefStdTime`: CGenDaoBriefStdTime, `CGenDaoBriefStdTime`: CGenDaoBriefStdTime,
`CGenDaoBriefWithTime`: CGenDaoBriefWithTime, `CGenDaoBriefWithTime`: CGenDaoBriefWithTime,
`CGenDaoBriefDaoPath`: CGenDaoBriefDaoPath, `CGenDaoBriefDaoPath`: CGenDaoBriefDaoPath,
@ -180,6 +182,7 @@ type (
Group string `name:"group" short:"g" brief:"{CGenDaoBriefGroup}" d:"default"` Group string `name:"group" short:"g" brief:"{CGenDaoBriefGroup}" d:"default"`
Prefix string `name:"prefix" short:"f" brief:"{CGenDaoBriefPrefix}"` Prefix string `name:"prefix" short:"f" brief:"{CGenDaoBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenDaoBriefRemovePrefix}"` RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenDaoBriefRemovePrefix}"`
RemoveFieldPrefix string `name:"removeFieldPrefix" short:"rf" brief:"{CGenDaoBriefRemoveFieldPrefix}"`
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenDaoBriefJsonCase}" d:"CamelLower"` JsonCase string `name:"jsonCase" short:"j" brief:"{CGenDaoBriefJsonCase}" d:"CamelLower"`
ImportPrefix string `name:"importPrefix" short:"i" brief:"{CGenDaoBriefImportPrefix}"` ImportPrefix string `name:"importPrefix" short:"i" brief:"{CGenDaoBriefImportPrefix}"`
DaoPath string `name:"daoPath" short:"d" brief:"{CGenDaoBriefDaoPath}" d:"dao"` DaoPath string `name:"daoPath" short:"d" brief:"{CGenDaoBriefDaoPath}" d:"dao"`

View File

@ -138,6 +138,7 @@ type generateDaoInternalInput struct {
func generateDaoInternal(in generateDaoInternalInput) { func generateDaoInternal(in generateDaoInternalInput) {
path := filepath.FromSlash(gfile.Join(in.DirPathDaoInternal, in.FileName+".go")) path := filepath.FromSlash(gfile.Join(in.DirPathDaoInternal, in.FileName+".go"))
removeFieldPrefixArray := gstr.SplitAndTrim(in.RemoveFieldPrefix, ",")
modelContent := gstr.ReplaceByMap( modelContent := gstr.ReplaceByMap(
getTemplateFromPathOrDefault(in.TplDaoInternalPath, consts.TemplateGenDaoInternalContent), getTemplateFromPathOrDefault(in.TplDaoInternalPath, consts.TemplateGenDaoInternalContent),
g.MapStrStr{ g.MapStrStr{
@ -146,8 +147,8 @@ func generateDaoInternal(in generateDaoInternalInput) {
tplVarGroupName: in.Group, tplVarGroupName: in.Group,
tplVarTableNameCamelCase: in.TableNameCamelCase, tplVarTableNameCamelCase: in.TableNameCamelCase,
tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase, tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase,
tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(in.FieldMap)), tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(in.FieldMap, removeFieldPrefixArray)),
tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(in.FieldMap)), tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(in.FieldMap, removeFieldPrefixArray)),
}) })
modelContent = replaceDefaultVar(in.CGenDaoInternalInput, modelContent) modelContent = replaceDefaultVar(in.CGenDaoInternalInput, modelContent)
if err := gfile.PutContents(path, strings.TrimSpace(modelContent)); err != nil { if err := gfile.PutContents(path, strings.TrimSpace(modelContent)); err != nil {
@ -160,16 +161,23 @@ func generateDaoInternal(in generateDaoInternalInput) {
// generateColumnNamesForDao generates and returns the column names assignment content of column struct // generateColumnNamesForDao generates and returns the column names assignment content of column struct
// for specified table. // for specified table.
func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField) string { func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField, removeFieldPrefixArray []string) string {
var ( var (
buffer = bytes.NewBuffer(nil) buffer = bytes.NewBuffer(nil)
array = make([][]string, len(fieldMap)) array = make([][]string, len(fieldMap))
names = sortFieldKeyForDao(fieldMap) names = sortFieldKeyForDao(fieldMap)
) )
for index, name := range names { for index, name := range names {
field := fieldMap[name] field := fieldMap[name]
newFiledName := field.Name
for _, v := range removeFieldPrefixArray {
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
}
array[index] = []string{ array[index] = []string{
" #" + gstr.CaseCamel(field.Name) + ":", " #" + gstr.CaseCamel(newFiledName) + ":",
fmt.Sprintf(` #"%s",`, field.Name), fmt.Sprintf(` #"%s",`, field.Name),
} }
} }
@ -189,12 +197,13 @@ func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField) string {
} }
// generateColumnDefinitionForDao generates and returns the column names definition for specified table. // generateColumnDefinitionForDao generates and returns the column names definition for specified table.
func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField) string { func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField, removeFieldPrefixArray []string) string {
var ( var (
buffer = bytes.NewBuffer(nil) buffer = bytes.NewBuffer(nil)
array = make([][]string, len(fieldMap)) array = make([][]string, len(fieldMap))
names = sortFieldKeyForDao(fieldMap) names = sortFieldKeyForDao(fieldMap)
) )
for index, name := range names { for index, name := range names {
var ( var (
field = fieldMap[name] field = fieldMap[name]
@ -203,8 +212,12 @@ func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField) string
"\r", " ", "\r", " ",
})) }))
) )
newFiledName := field.Name
for _, v := range removeFieldPrefixArray {
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
}
array[index] = []string{ array[index] = []string{
" #" + gstr.CaseCamel(field.Name), " #" + gstr.CaseCamel(newFiledName),
" # " + "string", " # " + "string",
" #" + fmt.Sprintf(`// %s`, comment), " #" + fmt.Sprintf(`// %s`, comment),
} }

View File

@ -126,8 +126,13 @@ func generateStructFieldDefinition(
tagKey = "`" tagKey = "`"
descriptionTag = gstr.Replace(formatComment(field.Comment), `"`, `\"`) descriptionTag = gstr.Replace(formatComment(field.Comment), `"`, `\"`)
) )
removeFieldPrefixArray := gstr.SplitAndTrim(in.RemoveFieldPrefix, ",")
newFiledName := field.Name
for _, v := range removeFieldPrefixArray {
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
}
attrLines = []string{ attrLines = []string{
" #" + gstr.CaseCamel(field.Name), " #" + gstr.CaseCamel(newFiledName),
" #" + localTypeNameStr, " #" + localTypeNameStr,
} }
attrLines = append(attrLines, " #"+fmt.Sprintf(tagKey+`json:"%s"`, jsonTag)) attrLines = append(attrLines, " #"+fmt.Sprintf(tagKey+`json:"%s"`, jsonTag))

View File

@ -31,16 +31,17 @@ import (
type ( type (
CGenPbEntity struct{} CGenPbEntity struct{}
CGenPbEntityInput struct { CGenPbEntityInput struct {
g.Meta `name:"pbentity" config:"{CGenPbEntityConfig}" brief:"{CGenPbEntityBrief}" eg:"{CGenPbEntityEg}" ad:"{CGenPbEntityAd}"` g.Meta `name:"pbentity" config:"{CGenPbEntityConfig}" brief:"{CGenPbEntityBrief}" eg:"{CGenPbEntityEg}" ad:"{CGenPbEntityAd}"`
Path string `name:"path" short:"p" brief:"{CGenPbEntityBriefPath}" d:"manifest/protobuf/pbentity"` Path string `name:"path" short:"p" brief:"{CGenPbEntityBriefPath}" d:"manifest/protobuf/pbentity"`
Package string `name:"package" short:"k" brief:"{CGenPbEntityBriefPackage}"` Package string `name:"package" short:"k" brief:"{CGenPbEntityBriefPackage}"`
Link string `name:"link" short:"l" brief:"{CGenPbEntityBriefLink}"` Link string `name:"link" short:"l" brief:"{CGenPbEntityBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{CGenPbEntityBriefTables}"` Tables string `name:"tables" short:"t" brief:"{CGenPbEntityBriefTables}"`
Prefix string `name:"prefix" short:"f" brief:"{CGenPbEntityBriefPrefix}"` Prefix string `name:"prefix" short:"f" brief:"{CGenPbEntityBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenPbEntityBriefRemovePrefix}"` RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenPbEntityBriefRemovePrefix}"`
NameCase string `name:"nameCase" short:"n" brief:"{CGenPbEntityBriefNameCase}" d:"Camel"` RemoveFieldPrefix string `name:"removeFieldPrefix" short:"rf" brief:"{CGenPbEntityBriefRemoveFieldPrefix}"`
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenPbEntityBriefJsonCase}" d:"CamelLower"` NameCase string `name:"nameCase" short:"n" brief:"{CGenPbEntityBriefNameCase}" d:"Camel"`
Option string `name:"option" short:"o" brief:"{CGenPbEntityBriefOption}"` JsonCase string `name:"jsonCase" short:"j" brief:"{CGenPbEntityBriefJsonCase}" d:"none"`
Option string `name:"option" short:"o" brief:"{CGenPbEntityBriefOption}"`
} }
CGenPbEntityOutput struct{} CGenPbEntityOutput struct{}
@ -87,14 +88,15 @@ CONFIGURATION SUPPORT
option java_package = "protobuf/demos"; option java_package = "protobuf/demos";
option php_namespace = "protobuf/demos"; option php_namespace = "protobuf/demos";
` `
CGenPbEntityBriefPath = `directory path for generated files storing` CGenPbEntityBriefPath = `directory path for generated files storing`
CGenPbEntityBriefPackage = `package path for all entity proto files` CGenPbEntityBriefPackage = `package path for all entity proto files`
CGenPbEntityBriefLink = `database configuration, the same as the ORM configuration of GoFrame` CGenPbEntityBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
CGenPbEntityBriefTables = `generate models only for given tables, multiple table names separated with ','` CGenPbEntityBriefTables = `generate models only for given tables, multiple table names separated with ','`
CGenPbEntityBriefPrefix = `add specified prefix for all entity names and entity proto files` CGenPbEntityBriefPrefix = `add specified prefix for all entity names and entity proto files`
CGenPbEntityBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','` CGenPbEntityBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
CGenPbEntityBriefOption = `extra protobuf options` CGenPbEntityBriefRemoveFieldPrefix = `remove specified prefix of the field, multiple prefix separated with ','`
CGenPbEntityBriefGroup = ` CGenPbEntityBriefOption = `extra protobuf options`
CGenPbEntityBriefGroup = `
specifying the configuration group name of database for generated ORM instance, specifying the configuration group name of database for generated ORM instance,
it's not necessary and the default value is "default" it's not necessary and the default value is "default"
` `
@ -120,20 +122,21 @@ set it to "none" to ignore json tag generating.
func init() { func init() {
gtag.Sets(g.MapStrStr{ gtag.Sets(g.MapStrStr{
`CGenPbEntityConfig`: CGenPbEntityConfig, `CGenPbEntityConfig`: CGenPbEntityConfig,
`CGenPbEntityBrief`: CGenPbEntityBrief, `CGenPbEntityBrief`: CGenPbEntityBrief,
`CGenPbEntityEg`: CGenPbEntityEg, `CGenPbEntityEg`: CGenPbEntityEg,
`CGenPbEntityAd`: CGenPbEntityAd, `CGenPbEntityAd`: CGenPbEntityAd,
`CGenPbEntityBriefPath`: CGenPbEntityBriefPath, `CGenPbEntityBriefPath`: CGenPbEntityBriefPath,
`CGenPbEntityBriefPackage`: CGenPbEntityBriefPackage, `CGenPbEntityBriefPackage`: CGenPbEntityBriefPackage,
`CGenPbEntityBriefLink`: CGenPbEntityBriefLink, `CGenPbEntityBriefLink`: CGenPbEntityBriefLink,
`CGenPbEntityBriefTables`: CGenPbEntityBriefTables, `CGenPbEntityBriefTables`: CGenPbEntityBriefTables,
`CGenPbEntityBriefPrefix`: CGenPbEntityBriefPrefix, `CGenPbEntityBriefPrefix`: CGenPbEntityBriefPrefix,
`CGenPbEntityBriefRemovePrefix`: CGenPbEntityBriefRemovePrefix, `CGenPbEntityBriefRemovePrefix`: CGenPbEntityBriefRemovePrefix,
`CGenPbEntityBriefGroup`: CGenPbEntityBriefGroup, `CGenPbEntityBriefRemoveFieldPrefix`: CGenPbEntityBriefRemoveFieldPrefix,
`CGenPbEntityBriefNameCase`: CGenPbEntityBriefNameCase, `CGenPbEntityBriefGroup`: CGenPbEntityBriefGroup,
`CGenPbEntityBriefJsonCase`: CGenPbEntityBriefJsonCase, `CGenPbEntityBriefNameCase`: CGenPbEntityBriefNameCase,
`CGenPbEntityBriefOption`: CGenPbEntityBriefOption, `CGenPbEntityBriefJsonCase`: CGenPbEntityBriefJsonCase,
`CGenPbEntityBriefOption`: CGenPbEntityBriefOption,
}) })
} }
@ -339,6 +342,7 @@ func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPb
comment = gstr.Replace(comment, `\n`, " ") comment = gstr.Replace(comment, `\n`, " ")
comment, _ = gregex.ReplaceString(`\s{2,}`, ` `, comment) comment, _ = gregex.ReplaceString(`\s{2,}`, ` `, comment)
if jsonTagName := formatCase(field.Name, in.JsonCase); jsonTagName != "" { if jsonTagName := formatCase(field.Name, in.JsonCase); jsonTagName != "" {
jsonTagStr = fmt.Sprintf(`[json_name = "%s"]`, jsonTagName)
// beautiful indent. // beautiful indent.
if index < 10 { if index < 10 {
// 3 spaces // 3 spaces
@ -351,9 +355,16 @@ func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPb
jsonTagStr = " " + jsonTagStr jsonTagStr = " " + jsonTagStr
} }
} }
removeFieldPrefixArray := gstr.SplitAndTrim(in.RemoveFieldPrefix, ",")
newFiledName := field.Name
for _, v := range removeFieldPrefixArray {
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
}
return []string{ return []string{
" #" + localTypeNameStr, " #" + localTypeNameStr,
" #" + formatCase(field.Name, in.NameCase), " #" + formatCase(newFiledName, in.NameCase),
" #= " + gconv.String(index) + jsonTagStr + ";", " #= " + gconv.String(index) + jsonTagStr + ";",
" #" + fmt.Sprintf(`// %s`, comment), " #" + fmt.Sprintf(`// %s`, comment),
} }
@ -368,32 +379,10 @@ func getTplPbEntityContent(tplEntityPath string) string {
// formatCase call gstr.Case* function to convert the s to specified case. // formatCase call gstr.Case* function to convert the s to specified case.
func formatCase(str, caseStr string) string { func formatCase(str, caseStr string) string {
switch gstr.ToLower(caseStr) { if caseStr == "none" {
case gstr.ToLower("Camel"):
return gstr.CaseCamel(str)
case gstr.ToLower("CamelLower"):
return gstr.CaseCamelLower(str)
case gstr.ToLower("Kebab"):
return gstr.CaseKebab(str)
case gstr.ToLower("KebabScreaming"):
return gstr.CaseKebabScreaming(str)
case gstr.ToLower("Snake"):
return gstr.CaseSnake(str)
case gstr.ToLower("SnakeFirstUpper"):
return gstr.CaseSnakeFirstUpper(str)
case gstr.ToLower("SnakeScreaming"):
return gstr.CaseSnakeScreaming(str)
case "none":
return "" return ""
} }
return str return gstr.CaseConvert(str, gstr.CaseTypeMatch(caseStr))
} }
func sortFieldKeyForPbEntity(fieldMap map[string]*gdb.TableField) []string { func sortFieldKeyForPbEntity(fieldMap map[string]*gdb.TableField) []string {

View File

@ -0,0 +1,21 @@
// ==========================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
syntax = "proto3";
package unittest;
option go_package = "unittest";
import "google/protobuf/timestamp.proto";
message TableUser {
uint32 ID = 1; // User ID
string PASSPORT = 2; // User Passport
string PASSWORD = 3; // User Password
string NICKNAME = 4; // User Nickname
string SCORE = 5; // Total score amount.
google.protobuf.Timestamp CREATE_AT = 6; // Created Time
google.protobuf.Timestamp UPDATE_AT = 7; // Updated Time
}

View File

@ -0,0 +1,10 @@
CREATE TABLE `%s` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'User ID',
`passport` varchar(45) NOT NULL COMMENT 'User Passport',
`password` varchar(45) NOT NULL COMMENT 'User Password',
`nickname` varchar(45) NOT NULL COMMENT 'User Nickname',
`score` decimal(10,2) unsigned DEFAULT NULL COMMENT 'Total score amount.',
`create_at` datetime DEFAULT NULL COMMENT 'Created Time',
`update_at` datetime DEFAULT NULL COMMENT 'Updated Time',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View File

@ -24,15 +24,19 @@ var (
) )
func init() { func init() {
logger.SetStack(false)
if genv.Get(headerPrintEnvName).String() == "1" { if genv.Get(headerPrintEnvName).String() == "1" {
logger.SetHeaderPrint(true) logger.SetHeaderPrint(true)
} else { } else {
logger.SetHeaderPrint(false) logger.SetHeaderPrint(false)
} }
if gcmd.GetOpt("debug") != nil || gcmd.GetOpt("gf.debug") != nil { if gcmd.GetOpt("debug") != nil || gcmd.GetOpt("gf.debug") != nil {
logger.SetHeaderPrint(true)
logger.SetStackSkip(4)
logger.SetFlags(logger.GetFlags() | glog.F_FILE_LONG)
logger.SetDebug(true) logger.SetDebug(true)
} else { } else {
logger.SetStack(false)
logger.SetDebug(false) logger.SetDebug(false)
} }
} }

View File

@ -219,6 +219,8 @@ func IsNumberType(goType string) bool {
switch goType { switch goType {
case GoTypeInt, GoTypeUint, GoTypeInt64, GoTypeUint64: case GoTypeInt, GoTypeUint, GoTypeInt64, GoTypeUint64:
return true return true
case GoTypeFloat32, GoTypeFloat64:
return true
} }
return false return false
} }

View File

@ -14,8 +14,10 @@ import (
"github.com/gogf/gf/v2/os/gview" "github.com/gogf/gf/v2/os/gview"
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
"hotgo/internal/consts" "hotgo/internal/consts"
"hotgo/internal/dao"
"hotgo/internal/library/hggen/internal/cmd/gendao" "hotgo/internal/library/hggen/internal/cmd/gendao"
"hotgo/internal/library/hggen/internal/utility/utils" "hotgo/internal/library/hggen/internal/utility/utils"
"hotgo/internal/library/hgorm"
"hotgo/internal/model" "hotgo/internal/model"
"hotgo/internal/model/input/sysin" "hotgo/internal/model/input/sysin"
"hotgo/utility/convert" "hotgo/utility/convert"
@ -668,6 +670,15 @@ func (l *gCurd) generateSqlContent(ctx context.Context, in *CurdPreviewInput) (e
genFile = new(sysin.GenFile) genFile = new(sysin.GenFile)
) )
tplData["dirPid"], tplData["dirLevel"], tplData["dirTree"], err = hgorm.AutoUpdateTree(ctx, &dao.AdminMenu, 0, int64(in.options.Menu.Pid))
if err != nil {
return err
}
tplData["listLevel"] = tplData["dirLevel"].(int) + 1
tplData["btnLevel"] = tplData["dirLevel"].(int) + 2
tplData["sortLevel"] = tplData["dirLevel"].(int) + 3
if in.options.Menu.Pid > 0 { if in.options.Menu.Pid > 0 {
tplData["mainComponent"] = "ParentLayout" tplData["mainComponent"] = "ParentLayout"
} }

View File

@ -32,7 +32,7 @@ func (l *gCurd) generateWebEditFormItem(ctx context.Context, in *CurdPreviewInpu
} }
var ( var (
defaultComponent = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-input placeholder=\"请输入%s\" v-model:value=\"params.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.Dc, field.TsName) defaultComponent = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-input placeholder=\"请输入%s\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.Dc, field.TsName)
component string component string
) )
@ -41,63 +41,63 @@ func (l *gCurd) generateWebEditFormItem(ctx context.Context, in *CurdPreviewInpu
component = defaultComponent component = defaultComponent
case FormModeInputNumber: case FormModeInputNumber:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-input-number placeholder=\"请输入%s\" v-model:value=\"params.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.Dc, field.TsName) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-input-number placeholder=\"请输入%s\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.Dc, field.TsName)
case FormModeInputTextarea: case FormModeInputTextarea:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-input type=\"textarea\" placeholder=\"%s\" v-model:value=\"params.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.Dc, field.TsName) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-input type=\"textarea\" placeholder=\"%s\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.Dc, field.TsName)
case FormModeInputEditor: case FormModeInputEditor:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <Editor style=\"height: 450px\" id=\"%s\" v-model:value=\"params.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, field.TsName) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <Editor style=\"height: 450px\" id=\"%s\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, field.TsName)
case FormModeInputDynamic: case FormModeInputDynamic:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-dynamic-input\n v-model:value=\"params.%s\"\n preset=\"pair\"\n key-placeholder=\"键名\"\n value-placeholder=\"键值\"\n />\n </n-form-item>", field.Dc, field.TsName, field.TsName) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-dynamic-input\n v-model:value=\"formValue.%s\"\n preset=\"pair\"\n key-placeholder=\"键名\"\n value-placeholder=\"键值\"\n />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
case FormModeDate: case FormModeDate:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <DatePicker v-model:formValue=\"params.%s\" type=\"date\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <DatePicker v-model:formValue=\"formValue.%s\" type=\"date\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
// case FormModeDateRange: // 必须要有两个字段,后面优化下 // case FormModeDateRange: // 必须要有两个字段,后面优化下
case FormModeTime: case FormModeTime:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <DatePicker v-model:formValue=\"params.%s\" type=\"datetime\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <DatePicker v-model:formValue=\"formValue.%s\" type=\"datetime\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
// case FormModeTimeRange: // 必须要有两个字段,后面优化下 // case FormModeTimeRange: // 必须要有两个字段,后面优化下
case FormModeRadio: case FormModeRadio:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-radio-group v-model:value=\"params.%s\" name=\"%s\">\n <n-radio-button\n v-for=\"%s in options.%s\"\n :key=\"%s.value\"\n :value=\"%s.value\"\n :label=\"%s.label\"\n />\n </n-radio-group>\n </n-form-item>", field.Dc, field.TsName, field.TsName, field.TsName, field.TsName, in.options.dictMap[field.TsName], field.TsName, field.TsName, field.TsName) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-radio-group v-model:value=\"formValue.%s\" name=\"%s\">\n <n-radio-button\n v-for=\"%s in options.%s\"\n :key=\"%s.value\"\n :value=\"%s.value\"\n :label=\"%s.label\"\n />\n </n-radio-group>\n </n-form-item>", field.Dc, field.TsName, field.TsName, field.TsName, field.TsName, in.options.dictMap[field.TsName], field.TsName, field.TsName, field.TsName)
case FormModeCheckbox: case FormModeCheckbox:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-checkbox-group v-model:value=\"params.%s\">\n <n-space>\n <n-checkbox\n v-for=\"item in options.%s\"\n :key=\"item.value\"\n :value=\"item.value\"\n :label=\"item.label\"\n />\n </n-space>\n </n-checkbox-group>\n </n-form-item>", field.Dc, field.TsName, field.TsName, in.options.dictMap[field.TsName]) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-checkbox-group v-model:value=\"formValue.%s\">\n <n-space>\n <n-checkbox\n v-for=\"item in options.%s\"\n :key=\"item.value\"\n :value=\"item.value\"\n :label=\"item.label\"\n />\n </n-space>\n </n-checkbox-group>\n </n-form-item>", field.Dc, field.TsName, field.TsName, in.options.dictMap[field.TsName])
case FormModeSelect: case FormModeSelect:
if in.options.dictMap[field.TsName] != nil { if in.options.dictMap[field.TsName] != nil {
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-select v-model:value=\"params.%s\" :options=\"options.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, in.options.dictMap[field.TsName]) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-select v-model:value=\"formValue.%s\" :options=\"options.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, in.options.dictMap[field.TsName])
} else { } else {
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-select v-model:value=\"params.%s\" options=\"\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-select v-model:value=\"formValue.%s\" options=\"\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
} }
case FormModeSelectMultiple: case FormModeSelectMultiple:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-select multiple v-model:value=\"params.%s\" :options=\"options.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, in.options.dictMap[field.TsName]) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-select multiple v-model:value=\"formValue.%s\" :options=\"options.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, in.options.dictMap[field.TsName])
case FormModeUploadImage: case FormModeUploadImage:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <UploadImage :maxNumber=\"1\" v-model:value=\"params.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <UploadImage :maxNumber=\"1\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
case FormModeUploadImages: case FormModeUploadImages:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <UploadImage :maxNumber=\"10\" v-model:value=\"params.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <UploadImage :maxNumber=\"10\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
case FormModeUploadFile: case FormModeUploadFile:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <UploadFile :maxNumber=\"1\" v-model:value=\"params.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <UploadFile :maxNumber=\"1\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
case FormModeUploadFiles: case FormModeUploadFiles:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <UploadFile :maxNumber=\"10\" v-model:value=\"params.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <UploadFile :maxNumber=\"10\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
case FormModeSwitch: case FormModeSwitch:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-switch :unchecked-value=\"2\" :checked-value=\"1\" v-model:value=\"params.%s\"\n />\n </n-form-item>", field.Dc, field.TsName, field.TsName) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-switch :unchecked-value=\"2\" :checked-value=\"1\" v-model:value=\"formValue.%s\"\n />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
case FormModeRate: case FormModeRate:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-rate allow-half :default-value=\"params.%s\" :on-update:value=\"update%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, field.GoName) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-rate allow-half :default-value=\"formValue.%s\" :on-update:value=\"update%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, field.GoName)
case FormModeCitySelector: case FormModeCitySelector:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <CitySelector v-model:value=\"params.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName) component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <CitySelector v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
default: default:
component = defaultComponent component = defaultComponent
@ -120,21 +120,21 @@ func (l *gCurd) generateWebEditScript(ctx context.Context, in *CurdPreviewInput)
) )
if in.options.Step.HasMaxSort { if in.options.Step.HasMaxSort {
importBuffer.WriteString(" import { onMounted, ref, computed, watch } from 'vue';\n") importBuffer.WriteString(" import { ref } from 'vue';\n")
if in.Config.Application.Crud.Templates[in.In.GenTemplate].IsAddon { if in.Config.Application.Crud.Templates[in.In.GenTemplate].IsAddon {
importBuffer.WriteString(" import { Edit, MaxSort, View } from '@/api/addons/" + in.In.AddonName + "/" + gstr.LcFirst(in.In.VarName) + "';\n") importBuffer.WriteString(" import { Edit, MaxSort, View } from '@/api/addons/" + in.In.AddonName + "/" + gstr.LcFirst(in.In.VarName) + "';\n")
} else { } else {
importBuffer.WriteString(" import { Edit, MaxSort, View } from '@/api/" + gstr.LcFirst(in.In.VarName) + "';\n") importBuffer.WriteString(" import { Edit, MaxSort, View } from '@/api/" + gstr.LcFirst(in.In.VarName) + "';\n")
} }
setupBuffer.WriteString(" function loadForm(value) {\n loading.value = true;\n\n // 新增\n if (value.id < 1) {\n params.value = newState(value);\n MaxSort()\n .then((res) => {\n params.value.sort = res.sort;\n })\n .finally(() => {\n loading.value = false;\n });\n return;\n }\n\n // 编辑\n View({ id: value.id })\n .then((res) => {\n params.value = res;\n })\n .finally(() => {\n loading.value = false;\n });\n }\n\n watch(\n () => props.formParams,\n (value) => {\n loadForm(value);\n }\n );") setupBuffer.WriteString(" function openModal(state: State) {\n adaModalWidth(dialogWidth);\n showModal.value = true;\n loading.value = true;\n\n // 新增\n if (!state || state.id < 1) {\n formValue.value = newState(state);\n MaxSort()\n .then((res) => {\n formValue.value.sort = res.sort;\n })\n .finally(() => {\n loading.value = false;\n });\n return;\n }\n\n // 编辑\n View({ id: state.id })\n .then((res) => {\n formValue.value = res;\n })\n .finally(() => {\n loading.value = false;\n });\n }")
} else { } else {
importBuffer.WriteString(" import { onMounted, ref, computed, watch } from 'vue';\n") importBuffer.WriteString(" import { ref } from 'vue';\n")
if in.Config.Application.Crud.Templates[in.In.GenTemplate].IsAddon { if in.Config.Application.Crud.Templates[in.In.GenTemplate].IsAddon {
importBuffer.WriteString(" import { Edit, View } from '@/api/addons/" + in.In.AddonName + "/" + gstr.LcFirst(in.In.VarName) + "';\n") importBuffer.WriteString(" import { Edit, View } from '@/api/addons/" + in.In.AddonName + "/" + gstr.LcFirst(in.In.VarName) + "';\n")
} else { } else {
importBuffer.WriteString(" import { Edit, View } from '@/api/" + gstr.LcFirst(in.In.VarName) + "';\n") importBuffer.WriteString(" import { Edit, View } from '@/api/" + gstr.LcFirst(in.In.VarName) + "';\n")
} }
setupBuffer.WriteString(" function loadForm(value) {\n // 新增\n if (value.id < 1) {\n params.value = newState(value);\n loading.value = false;\n return;\n }\n\n loading.value = true;\n // 编辑\n View({ id: value.id })\n .then((res) => {\n params.value = res;\n })\n .finally(() => {\n loading.value = false;\n });\n }\n\n watch(\n () => props.formParams,\n (value) => {\n loadForm(value);\n }\n );") setupBuffer.WriteString(" function openModal(state: State) {\n adaModalWidth(dialogWidth);\n showModal.value = true;\n loading.value = true;\n\n // 新增\n if (!state || state.id < 1) {\n formValue.value = newState(state);\n return;\n }\n\n // 编辑\n View({ id: state.id })\n .then((res) => {\n formValue.value = res;\n })\n .finally(() => {\n loading.value = false;\n });\n }")
} }
for _, field := range in.masterFields { for _, field := range in.masterFields {
@ -159,7 +159,7 @@ func (l *gCurd) generateWebEditScript(ctx context.Context, in *CurdPreviewInput)
importBuffer.WriteString(" import UploadFile from '@/components/Upload/uploadFile.vue';\n") importBuffer.WriteString(" import UploadFile from '@/components/Upload/uploadFile.vue';\n")
} }
case FormModeRate: case FormModeRate:
setupBuffer.WriteString(fmt.Sprintf(" function update%s(num) {\n params.value.%s = num;\n }\n", field.GoName, field.TsName)) setupBuffer.WriteString(fmt.Sprintf(" function update%s(num) {\n formValue.value.%s = num;\n }\n", field.GoName, field.TsName))
case FormModeCitySelector: case FormModeCitySelector:
if !gstr.Contains(importBuffer.String(), `import CitySelector`) { if !gstr.Contains(importBuffer.String(), `import CitySelector`) {
importBuffer.WriteString(" import CitySelector from '@/components/CitySelector/citySelector.vue';\n") importBuffer.WriteString(" import CitySelector from '@/components/CitySelector/citySelector.vue';\n")

View File

@ -22,7 +22,6 @@ const (
func (l *gCurd) webModelTplData(ctx context.Context, in *CurdPreviewInput) (data g.Map, err error) { func (l *gCurd) webModelTplData(ctx context.Context, in *CurdPreviewInput) (data g.Map, err error) {
data = make(g.Map) data = make(g.Map)
data["state"] = l.generateWebModelState(ctx, in) data["state"] = l.generateWebModelState(ctx, in)
data["defaultState"] = l.generateWebModelDefaultState(ctx, in)
data["rules"] = l.generateWebModelRules(ctx, in) data["rules"] = l.generateWebModelRules(ctx, in)
data["formSchema"] = l.generateWebModelFormSchema(ctx, in) data["formSchema"] = l.generateWebModelFormSchema(ctx, in)
if data["columns"], err = l.generateWebModelColumns(ctx, in); err != nil { if data["columns"], err = l.generateWebModelColumns(ctx, in); err != nil {
@ -33,18 +32,7 @@ func (l *gCurd) webModelTplData(ctx context.Context, in *CurdPreviewInput) (data
func (l *gCurd) generateWebModelState(ctx context.Context, in *CurdPreviewInput) string { func (l *gCurd) generateWebModelState(ctx context.Context, in *CurdPreviewInput) string {
buffer := bytes.NewBuffer(nil) buffer := bytes.NewBuffer(nil)
buffer.WriteString("export interface State {\n") buffer.WriteString("export class State {\n")
for _, field := range in.masterFields {
buffer.WriteString(fmt.Sprintf(" %s: %s;\n", field.TsName, field.TsType))
}
buffer.WriteString("}")
return buffer.String()
}
func (l *gCurd) generateWebModelDefaultState(ctx context.Context, in *CurdPreviewInput) string {
buffer := bytes.NewBuffer(nil)
buffer.WriteString("export const defaultState: State = {\n")
for _, field := range in.masterFields { for _, field := range in.masterFields {
var value = field.DefaultValue var value = field.DefaultValue
if value == nil { if value == nil {
@ -56,10 +44,9 @@ func (l *gCurd) generateWebModelDefaultState(ctx context.Context, in *CurdPrevie
if field.Name == "status" { if field.Name == "status" {
value = 1 value = 1
} }
buffer.WriteString(fmt.Sprintf(" %s: %v,\n", field.TsName, value)) buffer.WriteString(fmt.Sprintf(" public %s = %v; // %s\n", field.TsName, value, field.Dc))
} }
buffer.WriteString("};") buffer.WriteString("}")
return buffer.String() return buffer.String()
} }
@ -107,8 +94,10 @@ func (l *gCurd) generateWebModelDictOptions(ctx context.Context, in *CurdPreview
switchLoadOptions string switchLoadOptions string
) )
interfaceOptionsBuffer := bytes.NewBuffer(nil)
interfaceOptionsBuffer.WriteString("export interface IOptions extends Options {\n")
constOptionsBuffer := bytes.NewBuffer(nil) constOptionsBuffer := bytes.NewBuffer(nil)
constOptionsBuffer.WriteString("export const options = ref<Options>({\n") constOptionsBuffer.WriteString("export const options = ref<IOptions>({\n")
for _, v := range dictTypeList { for _, v := range dictTypeList {
// 字段映射字典 // 字段映射字典
@ -120,14 +109,17 @@ func (l *gCurd) generateWebModelDictOptions(ctx context.Context, in *CurdPreview
} }
awaitLoadOptions = fmt.Sprintf("%s '%s',\n", awaitLoadOptions, v.Type) awaitLoadOptions = fmt.Sprintf("%s '%s',\n", awaitLoadOptions, v.Type)
interfaceOptionsBuffer.WriteString(" " + v.Type + ": Option[]; \n")
constOptionsBuffer.WriteString(" " + v.Type + ": [],\n") constOptionsBuffer.WriteString(" " + v.Type + ": [],\n")
} }
interfaceOptionsBuffer.WriteString("};\n")
constOptionsBuffer.WriteString("});\n") constOptionsBuffer.WriteString("});\n")
loadOptionsBuffer := bytes.NewBuffer(nil) loadOptionsBuffer := bytes.NewBuffer(nil)
loadOptionsBuffer.WriteString(fmt.Sprintf(ModelLoadOptionsTemplate, awaitLoadOptions, switchLoadOptions)) loadOptionsBuffer.WriteString(fmt.Sprintf(ModelLoadOptionsTemplate, awaitLoadOptions, switchLoadOptions))
options["interface"] = interfaceOptionsBuffer.String()
options["const"] = constOptionsBuffer.String() options["const"] = constOptionsBuffer.String()
options["load"] = loadOptionsBuffer.String() options["load"] = loadOptionsBuffer.String()

View File

@ -197,7 +197,7 @@ func (s *sAdminRole) Edit(ctx context.Context, in *adminin.RoleEditInp) (err err
} }
func updateRoleChildrenTree(ctx context.Context, _id int64, _level int, _tree string) (err error) { func updateRoleChildrenTree(ctx context.Context, _id int64, _level int, _tree string) (err error) {
var list []*entity.AdminDept var list []*entity.AdminRole
if err = dao.AdminRole.Ctx(ctx).Where("pid", _id).Scan(&list); err != nil { if err = dao.AdminRole.Ctx(ctx).Where("pid", _id).Scan(&list); err != nil {
return return
} }

View File

@ -147,10 +147,6 @@ func (s *sSysDictData) GetTypes(ctx context.Context, id int64) (types []string,
// Select 获取列表 // Select 获取列表
func (s *sSysDictData) Select(ctx context.Context, in *sysin.DataSelectInp) (list sysin.DataSelectModel, err error) { func (s *sSysDictData) Select(ctx context.Context, in *sysin.DataSelectInp) (list sysin.DataSelectModel, err error) {
mod := dao.SysDictData.Ctx(ctx).Where("type", in.Type) mod := dao.SysDictData.Ctx(ctx).Where("type", in.Type)
if in.Type != "" {
mod = mod.Where("type", in.Type)
}
if err = mod.Order("sort asc,id desc").Scan(&list); err != nil { if err = mod.Order("sort asc,id desc").Scan(&list); err != nil {
err = gerror.Wrap(err, consts.ErrorORM) err = gerror.Wrap(err, consts.ErrorORM)
return return

View File

@ -18,6 +18,7 @@ import (
"hotgo/internal/consts" "hotgo/internal/consts"
"hotgo/internal/dao" "hotgo/internal/dao"
"hotgo/internal/library/contexts" "hotgo/internal/library/contexts"
"hotgo/internal/library/hgorm/handler"
"hotgo/internal/library/hgorm/hook" "hotgo/internal/library/hgorm/hook"
"hotgo/internal/library/location" "hotgo/internal/library/location"
"hotgo/internal/library/queue" "hotgo/internal/library/queue"
@ -236,7 +237,7 @@ func (s *sSysLog) AnalysisLog(ctx context.Context) entity.SysLog {
// View 获取指定字典类型信息 // View 获取指定字典类型信息
func (s *sSysLog) View(ctx context.Context, in *sysin.LogViewInp) (res *sysin.LogViewModel, err error) { func (s *sSysLog) View(ctx context.Context, in *sysin.LogViewInp) (res *sysin.LogViewModel, err error) {
if err = dao.SysLog.Ctx(ctx).Hook(hook.CityLabel).Where("id", in.Id).Scan(&res); err != nil { if err = dao.SysLog.Ctx(ctx).Handler(handler.FilterAuth).Hook(hook.CityLabel).Where("id", in.Id).Scan(&res); err != nil {
err = gerror.Wrap(err, consts.ErrorORM) err = gerror.Wrap(err, consts.ErrorORM)
return return
} }
@ -253,13 +254,13 @@ func (s *sSysLog) View(ctx context.Context, in *sysin.LogViewInp) (res *sysin.Lo
// Delete 删除 // Delete 删除
func (s *sSysLog) Delete(ctx context.Context, in *sysin.LogDeleteInp) (err error) { func (s *sSysLog) Delete(ctx context.Context, in *sysin.LogDeleteInp) (err error) {
_, err = dao.SysLog.Ctx(ctx).Where("id", in.Id).Delete() _, err = dao.SysLog.Ctx(ctx).Handler(handler.FilterAuth).Where("id", in.Id).Delete()
return return
} }
// List 列表 // List 列表
func (s *sSysLog) List(ctx context.Context, in *sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error) { func (s *sSysLog) List(ctx context.Context, in *sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error) {
mod := dao.SysLog.Ctx(ctx).FieldsEx("get_data", "header_data", "post_data") mod := dao.SysLog.Ctx(ctx).Handler(handler.FilterAuth).FieldsEx("get_data", "header_data", "post_data")
// 访问路径 // 访问路径
if in.Url != "" { if in.Url != "" {

View File

@ -18,6 +18,167 @@ import (
) )
type ( type (
ISysCurdDemo interface {
// Model 生成演示ORM模型
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
// List 获取生成演示列表
List(ctx context.Context, in *sysin.CurdDemoListInp) (list []*sysin.CurdDemoListModel, totalCount int, err error)
// Export 导出生成演示
Export(ctx context.Context, in *sysin.CurdDemoListInp) (err error)
// Edit 修改/新增生成演示
Edit(ctx context.Context, in *sysin.CurdDemoEditInp) (err error)
// Delete 删除生成演示
Delete(ctx context.Context, in *sysin.CurdDemoDeleteInp) (err error)
// MaxSort 获取生成演示最大排序
MaxSort(ctx context.Context, in *sysin.CurdDemoMaxSortInp) (res *sysin.CurdDemoMaxSortModel, err error)
// View 获取生成演示指定信息
View(ctx context.Context, in *sysin.CurdDemoViewInp) (res *sysin.CurdDemoViewModel, err error)
// Status 更新生成演示状态
Status(ctx context.Context, in *sysin.CurdDemoStatusInp) (err error)
// Switch 更新生成演示开关
Switch(ctx context.Context, in *sysin.CurdDemoSwitchInp) (err error)
}
ISysDictData interface {
// Delete 删除
Delete(ctx context.Context, in *sysin.DictDataDeleteInp) error
// Edit 修改/新增
Edit(ctx context.Context, in *sysin.DictDataEditInp) (err error)
// List 获取列表
List(ctx context.Context, in *sysin.DictDataListInp) (list []*sysin.DictDataListModel, totalCount int, err error)
// GetId 获取指定类型的ID
GetId(ctx context.Context, t string) (id int64, err error)
// GetType 获取指定ID的类型标识
GetType(ctx context.Context, id int64) (types string, err error)
// GetTypes 获取指定ID的所有类型标识包含下级
GetTypes(ctx context.Context, id int64) (types []string, err error)
// Select 获取列表
Select(ctx context.Context, in *sysin.DataSelectInp) (list sysin.DataSelectModel, err error)
}
ISysEmsLog interface {
// Delete 删除
Delete(ctx context.Context, in *sysin.EmsLogDeleteInp) (err error)
// Edit 修改/新增
Edit(ctx context.Context, in *sysin.EmsLogEditInp) (err error)
// Status 更新部门状态
Status(ctx context.Context, in *sysin.EmsLogStatusInp) (err error)
// View 获取指定字典类型信息
View(ctx context.Context, in *sysin.EmsLogViewInp) (res *sysin.EmsLogViewModel, err error)
// List 获取列表
List(ctx context.Context, in *sysin.EmsLogListInp) (list []*sysin.EmsLogListModel, totalCount int, err error)
// Send 发送邮件
Send(ctx context.Context, in *sysin.SendEmsInp) (err error)
// GetTemplate 获取指定邮件模板
GetTemplate(ctx context.Context, template string, config *model.EmailConfig) (val string, err error)
// AllowSend 是否允许发送
AllowSend(ctx context.Context, models *entity.SysEmsLog, config *model.EmailConfig) (err error)
// NowDayCount 当天发送次数
NowDayCount(ctx context.Context, event, email string) (count int, err error)
// VerifyCode 效验验证码
VerifyCode(ctx context.Context, in *sysin.VerifyEmsCodeInp) (err error)
}
ISysLoginLog interface {
// Model 登录日志Orm模型
Model(ctx context.Context) *gdb.Model
// List 获取登录日志列表
List(ctx context.Context, in *sysin.LoginLogListInp) (list []*sysin.LoginLogListModel, totalCount int, err error)
// Export 导出登录日志
Export(ctx context.Context, in *sysin.LoginLogListInp) (err error)
// Delete 删除登录日志
Delete(ctx context.Context, in *sysin.LoginLogDeleteInp) (err error)
// View 获取登录日志指定信息
View(ctx context.Context, in *sysin.LoginLogViewInp) (res *sysin.LoginLogViewModel, err error)
// Push 推送登录日志
Push(ctx context.Context, in *sysin.LoginLogPushInp)
// RealWrite 真实写入
RealWrite(ctx context.Context, models entity.SysLoginLog) (err error)
}
ISysAddons interface {
// List 获取列表
List(ctx context.Context, in *sysin.AddonsListInp) (list []*sysin.AddonsListModel, totalCount int, err error)
// Selects 选项
Selects(ctx context.Context, in *sysin.AddonsSelectsInp) (res *sysin.AddonsSelectsModel, err error)
// Build 提交生成
Build(ctx context.Context, in *sysin.AddonsBuildInp) (err error)
// Install 安装模块
Install(ctx context.Context, in *sysin.AddonsInstallInp) (err error)
// Upgrade 更新模块
Upgrade(ctx context.Context, in *sysin.AddonsUpgradeInp) (err error)
// UnInstall 卸载模块
UnInstall(ctx context.Context, in *sysin.AddonsUnInstallInp) (err error)
}
ISysAttachment interface {
// Model ORM模型
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
// Delete 删除附件
Delete(ctx context.Context, in *sysin.AttachmentDeleteInp) (err error)
// View 获取附件信息
View(ctx context.Context, in *sysin.AttachmentViewInp) (res *sysin.AttachmentViewModel, err error)
// List 获取附件列表
List(ctx context.Context, in *sysin.AttachmentListInp) (list []*sysin.AttachmentListModel, totalCount int, err error)
// ClearKind 清空上传类型
ClearKind(ctx context.Context, in *sysin.AttachmentClearKindInp) (err error)
}
ISysCron interface {
StartCron(ctx context.Context)
// Delete 删除
Delete(ctx context.Context, in *sysin.CronDeleteInp) (err error)
// Edit 修改/新增
Edit(ctx context.Context, in *sysin.CronEditInp) (err error)
// Status 更新状态
Status(ctx context.Context, in *sysin.CronStatusInp) (err error)
// MaxSort 最大排序
MaxSort(ctx context.Context, in *sysin.CronMaxSortInp) (res *sysin.CronMaxSortModel, err error)
// View 获取指定信息
View(ctx context.Context, in *sysin.CronViewInp) (res *sysin.CronViewModel, err error)
// List 获取列表
List(ctx context.Context, in *sysin.CronListInp) (list []*sysin.CronListModel, totalCount int, err error)
// GetName 获取分组名称
GetName(ctx context.Context, id int64) (name string, err error)
// OnlineExec 在线执行
OnlineExec(ctx context.Context, in *sysin.OnlineExecInp) (err error)
// DispatchLog 查看指定任务的调度日志
DispatchLog(ctx context.Context, in *sysin.DispatchLogInp) (res *sysin.DispatchLogModel, err error)
}
ISysServeLicense interface {
// Model 服务许可证ORM模型
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
// List 获取服务许可证列表
List(ctx context.Context, in *sysin.ServeLicenseListInp) (list []*sysin.ServeLicenseListModel, totalCount int, err error)
// Export 导出服务许可证
Export(ctx context.Context, in *sysin.ServeLicenseListInp) (err error)
// Edit 修改/新增服务许可证
Edit(ctx context.Context, in *sysin.ServeLicenseEditInp) (err error)
// Delete 删除服务许可证
Delete(ctx context.Context, in *sysin.ServeLicenseDeleteInp) (err error)
// View 获取服务许可证指定信息
View(ctx context.Context, in *sysin.ServeLicenseViewInp) (res *sysin.ServeLicenseViewModel, err error)
// Status 更新服务许可证状态
Status(ctx context.Context, in *sysin.ServeLicenseStatusInp) (err error)
// AssignRouter 分配服务许可证路由
AssignRouter(ctx context.Context, in *sysin.ServeLicenseAssignRouterInp) (err error)
}
ISysSmsLog interface {
// Delete 删除
Delete(ctx context.Context, in *sysin.SmsLogDeleteInp) (err error)
// Edit 修改/新增
Edit(ctx context.Context, in *sysin.SmsLogEditInp) (err error)
// Status 更新短信状态
Status(ctx context.Context, in *sysin.SmsLogStatusInp) (err error)
// View 获取指定字典类型信息
View(ctx context.Context, in *sysin.SmsLogViewInp) (res *sysin.SmsLogViewModel, err error)
// List 获取列表
List(ctx context.Context, in *sysin.SmsLogListInp) (list []*sysin.SmsLogListModel, totalCount int, err error)
// SendCode 发送验证码
SendCode(ctx context.Context, in *sysin.SendCodeInp) (err error)
// GetTemplate 获取指定短信模板
GetTemplate(ctx context.Context, template string, config *model.SmsConfig) (val string, err error)
// AllowSend 是否允许发送
AllowSend(ctx context.Context, models *entity.SysSmsLog, config *model.SmsConfig) (err error)
// NowDayCount 当天发送次数
NowDayCount(ctx context.Context, event, mobile string) (count int, err error)
// VerifyCode 效验验证码
VerifyCode(ctx context.Context, in *sysin.VerifyCodeInp) (err error)
}
ISysAddonsConfig interface { ISysAddonsConfig interface {
// GetConfigByGroup 获取指定分组的配置 // GetConfigByGroup 获取指定分组的配置
GetConfigByGroup(ctx context.Context, in *sysin.GetAddonsConfigInp) (res *sysin.GetAddonsConfigModel, err error) GetConfigByGroup(ctx context.Context, in *sysin.GetAddonsConfigInp) (res *sysin.GetAddonsConfigModel, err error)
@ -46,6 +207,58 @@ type (
// ClusterSync 集群同步 // ClusterSync 集群同步
ClusterSync(ctx context.Context, message *gredis.Message) ClusterSync(ctx context.Context, message *gredis.Message)
} }
ISysLog interface {
// Export 导出
Export(ctx context.Context, in *sysin.LogListInp) (err error)
// RealWrite 真实写入
RealWrite(ctx context.Context, log entity.SysLog) (err error)
// AutoLog 根据配置自动记录请求日志
AutoLog(ctx context.Context) error
// AnalysisLog 解析日志数据
AnalysisLog(ctx context.Context) entity.SysLog
// View 获取指定字典类型信息
View(ctx context.Context, in *sysin.LogViewInp) (res *sysin.LogViewModel, err error)
// Delete 删除
Delete(ctx context.Context, in *sysin.LogDeleteInp) (err error)
// List 列表
List(ctx context.Context, in *sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error)
}
ISysProvinces interface {
// Tree 关系树选项列表
Tree(ctx context.Context) (list []*sysin.ProvincesTree, err error)
// Delete 删除省市区数据
Delete(ctx context.Context, in *sysin.ProvincesDeleteInp) (err error)
// Edit 修改/新增省市区数据
Edit(ctx context.Context, in *sysin.ProvincesEditInp) (err error)
// Status 更新省市区状态
Status(ctx context.Context, in *sysin.ProvincesStatusInp) (err error)
// MaxSort 最大排序
MaxSort(ctx context.Context, in *sysin.ProvincesMaxSortInp) (res *sysin.ProvincesMaxSortModel, err error)
// View 获取省市区信息
View(ctx context.Context, in *sysin.ProvincesViewInp) (res *sysin.ProvincesViewModel, err error)
// List 获取列表
List(ctx context.Context, in *sysin.ProvincesListInp) (list []*sysin.ProvincesListModel, totalCount int, err error)
// ChildrenList 获取省市区下级列表
ChildrenList(ctx context.Context, in *sysin.ProvincesChildrenListInp) (list []*sysin.ProvincesChildrenListModel, totalCount int, err error)
// UniqueId 获取省市区下级列表
UniqueId(ctx context.Context, in *sysin.ProvincesUniqueIdInp) (res *sysin.ProvincesUniqueIdModel, err error)
// Select 省市区选项
Select(ctx context.Context, in *sysin.ProvincesSelectInp) (res *sysin.ProvincesSelectModel, err error)
}
ISysServeLog interface {
// Model 服务日志Orm模型
Model(ctx context.Context) *gdb.Model
// List 获取服务日志列表
List(ctx context.Context, in *sysin.ServeLogListInp) (list []*sysin.ServeLogListModel, totalCount int, err error)
// Export 导出服务日志
Export(ctx context.Context, in *sysin.ServeLogListInp) (err error)
// Delete 删除服务日志
Delete(ctx context.Context, in *sysin.ServeLogDeleteInp) (err error)
// View 获取服务日志指定信息
View(ctx context.Context, in *sysin.ServeLogViewInp) (res *sysin.ServeLogViewModel, err error)
// RealWrite 真实写入
RealWrite(ctx context.Context, models entity.SysServeLog) (err error)
}
ISysConfig interface { ISysConfig interface {
// InitConfig 初始化系统配置 // InitConfig 初始化系统配置
InitConfig(ctx context.Context) InitConfig(ctx context.Context)
@ -104,64 +317,6 @@ type (
// Select 选项 // Select 选项
Select(ctx context.Context, in *sysin.CronGroupSelectInp) (res *sysin.CronGroupSelectModel, err error) Select(ctx context.Context, in *sysin.CronGroupSelectInp) (res *sysin.CronGroupSelectModel, err error)
} }
ISysCurdDemo interface {
// Model 生成演示ORM模型
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
// List 获取生成演示列表
List(ctx context.Context, in *sysin.CurdDemoListInp) (list []*sysin.CurdDemoListModel, totalCount int, err error)
// Export 导出生成演示
Export(ctx context.Context, in *sysin.CurdDemoListInp) (err error)
// Edit 修改/新增生成演示
Edit(ctx context.Context, in *sysin.CurdDemoEditInp) (err error)
// Delete 删除生成演示
Delete(ctx context.Context, in *sysin.CurdDemoDeleteInp) (err error)
// MaxSort 获取生成演示最大排序
MaxSort(ctx context.Context, in *sysin.CurdDemoMaxSortInp) (res *sysin.CurdDemoMaxSortModel, err error)
// View 获取生成演示指定信息
View(ctx context.Context, in *sysin.CurdDemoViewInp) (res *sysin.CurdDemoViewModel, err error)
// Status 更新生成演示状态
Status(ctx context.Context, in *sysin.CurdDemoStatusInp) (err error)
// Switch 更新生成演示开关
Switch(ctx context.Context, in *sysin.CurdDemoSwitchInp) (err error)
}
ISysLog interface {
// Export 导出
Export(ctx context.Context, in *sysin.LogListInp) (err error)
// RealWrite 真实写入
RealWrite(ctx context.Context, log entity.SysLog) (err error)
// AutoLog 根据配置自动记录请求日志
AutoLog(ctx context.Context) error
// AnalysisLog 解析日志数据
AnalysisLog(ctx context.Context) entity.SysLog
// View 获取指定字典类型信息
View(ctx context.Context, in *sysin.LogViewInp) (res *sysin.LogViewModel, err error)
// Delete 删除
Delete(ctx context.Context, in *sysin.LogDeleteInp) (err error)
// List 列表
List(ctx context.Context, in *sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error)
}
ISysSmsLog interface {
// Delete 删除
Delete(ctx context.Context, in *sysin.SmsLogDeleteInp) (err error)
// Edit 修改/新增
Edit(ctx context.Context, in *sysin.SmsLogEditInp) (err error)
// Status 更新短信状态
Status(ctx context.Context, in *sysin.SmsLogStatusInp) (err error)
// View 获取指定字典类型信息
View(ctx context.Context, in *sysin.SmsLogViewInp) (res *sysin.SmsLogViewModel, err error)
// List 获取列表
List(ctx context.Context, in *sysin.SmsLogListInp) (list []*sysin.SmsLogListModel, totalCount int, err error)
// SendCode 发送验证码
SendCode(ctx context.Context, in *sysin.SendCodeInp) (err error)
// GetTemplate 获取指定短信模板
GetTemplate(ctx context.Context, template string, config *model.SmsConfig) (val string, err error)
// AllowSend 是否允许发送
AllowSend(ctx context.Context, models *entity.SysSmsLog, config *model.SmsConfig) (err error)
// NowDayCount 当天发送次数
NowDayCount(ctx context.Context, event, mobile string) (count int, err error)
// VerifyCode 效验验证码
VerifyCode(ctx context.Context, in *sysin.VerifyCodeInp) (err error)
}
ISysDictType interface { ISysDictType interface {
// Tree 树 // Tree 树
Tree(ctx context.Context) (list []*sysin.DictTypeTree, err error) Tree(ctx context.Context) (list []*sysin.DictTypeTree, err error)
@ -172,28 +327,6 @@ type (
// TreeSelect 获取类型关系树选项 // TreeSelect 获取类型关系树选项
TreeSelect(ctx context.Context, in *sysin.DictTreeSelectInp) (list []*sysin.DictTypeTree, err error) TreeSelect(ctx context.Context, in *sysin.DictTreeSelectInp) (list []*sysin.DictTypeTree, err error)
} }
ISysEmsLog interface {
// Delete 删除
Delete(ctx context.Context, in *sysin.EmsLogDeleteInp) (err error)
// Edit 修改/新增
Edit(ctx context.Context, in *sysin.EmsLogEditInp) (err error)
// Status 更新部门状态
Status(ctx context.Context, in *sysin.EmsLogStatusInp) (err error)
// View 获取指定字典类型信息
View(ctx context.Context, in *sysin.EmsLogViewInp) (res *sysin.EmsLogViewModel, err error)
// List 获取列表
List(ctx context.Context, in *sysin.EmsLogListInp) (list []*sysin.EmsLogListModel, totalCount int, err error)
// Send 发送邮件
Send(ctx context.Context, in *sysin.SendEmsInp) (err error)
// GetTemplate 获取指定邮件模板
GetTemplate(ctx context.Context, template string, config *model.EmailConfig) (val string, err error)
// AllowSend 是否允许发送
AllowSend(ctx context.Context, models *entity.SysEmsLog, config *model.EmailConfig) (err error)
// NowDayCount 当天发送次数
NowDayCount(ctx context.Context, event, email string) (count int, err error)
// VerifyCode 效验验证码
VerifyCode(ctx context.Context, in *sysin.VerifyEmsCodeInp) (err error)
}
ISysGenCodes interface { ISysGenCodes interface {
// Delete 删除 // Delete 删除
Delete(ctx context.Context, in *sysin.GenCodesDeleteInp) (err error) Delete(ctx context.Context, in *sysin.GenCodesDeleteInp) (err error)
@ -220,206 +353,29 @@ type (
// Build 提交生成 // Build 提交生成
Build(ctx context.Context, in *sysin.GenCodesBuildInp) (err error) Build(ctx context.Context, in *sysin.GenCodesBuildInp) (err error)
} }
ISysProvinces interface {
// Tree 关系树选项列表
Tree(ctx context.Context) (list []*sysin.ProvincesTree, err error)
// Delete 删除省市区数据
Delete(ctx context.Context, in *sysin.ProvincesDeleteInp) (err error)
// Edit 修改/新增省市区数据
Edit(ctx context.Context, in *sysin.ProvincesEditInp) (err error)
// Status 更新省市区状态
Status(ctx context.Context, in *sysin.ProvincesStatusInp) (err error)
// MaxSort 最大排序
MaxSort(ctx context.Context, in *sysin.ProvincesMaxSortInp) (res *sysin.ProvincesMaxSortModel, err error)
// View 获取省市区信息
View(ctx context.Context, in *sysin.ProvincesViewInp) (res *sysin.ProvincesViewModel, err error)
// List 获取列表
List(ctx context.Context, in *sysin.ProvincesListInp) (list []*sysin.ProvincesListModel, totalCount int, err error)
// ChildrenList 获取省市区下级列表
ChildrenList(ctx context.Context, in *sysin.ProvincesChildrenListInp) (list []*sysin.ProvincesChildrenListModel, totalCount int, err error)
// UniqueId 获取省市区下级列表
UniqueId(ctx context.Context, in *sysin.ProvincesUniqueIdInp) (res *sysin.ProvincesUniqueIdModel, err error)
// Select 省市区选项
Select(ctx context.Context, in *sysin.ProvincesSelectInp) (res *sysin.ProvincesSelectModel, err error)
}
ISysServeLog interface {
// Model 服务日志Orm模型
Model(ctx context.Context) *gdb.Model
// List 获取服务日志列表
List(ctx context.Context, in *sysin.ServeLogListInp) (list []*sysin.ServeLogListModel, totalCount int, err error)
// Export 导出服务日志
Export(ctx context.Context, in *sysin.ServeLogListInp) (err error)
// Delete 删除服务日志
Delete(ctx context.Context, in *sysin.ServeLogDeleteInp) (err error)
// View 获取服务日志指定信息
View(ctx context.Context, in *sysin.ServeLogViewInp) (res *sysin.ServeLogViewModel, err error)
// RealWrite 真实写入
RealWrite(ctx context.Context, models entity.SysServeLog) (err error)
}
ISysAddons interface {
// List 获取列表
List(ctx context.Context, in *sysin.AddonsListInp) (list []*sysin.AddonsListModel, totalCount int, err error)
// Selects 选项
Selects(ctx context.Context, in *sysin.AddonsSelectsInp) (res *sysin.AddonsSelectsModel, err error)
// Build 提交生成
Build(ctx context.Context, in *sysin.AddonsBuildInp) (err error)
// Install 安装模块
Install(ctx context.Context, in *sysin.AddonsInstallInp) (err error)
// Upgrade 更新模块
Upgrade(ctx context.Context, in *sysin.AddonsUpgradeInp) (err error)
// UnInstall 卸载模块
UnInstall(ctx context.Context, in *sysin.AddonsUnInstallInp) (err error)
}
ISysAttachment interface {
// Model ORM模型
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
// Delete 删除附件
Delete(ctx context.Context, in *sysin.AttachmentDeleteInp) (err error)
// View 获取附件信息
View(ctx context.Context, in *sysin.AttachmentViewInp) (res *sysin.AttachmentViewModel, err error)
// List 获取附件列表
List(ctx context.Context, in *sysin.AttachmentListInp) (list []*sysin.AttachmentListModel, totalCount int, err error)
// ClearKind 清空上传类型
ClearKind(ctx context.Context, in *sysin.AttachmentClearKindInp) (err error)
}
ISysCron interface {
StartCron(ctx context.Context)
// Delete 删除
Delete(ctx context.Context, in *sysin.CronDeleteInp) (err error)
// Edit 修改/新增
Edit(ctx context.Context, in *sysin.CronEditInp) (err error)
// Status 更新状态
Status(ctx context.Context, in *sysin.CronStatusInp) (err error)
// MaxSort 最大排序
MaxSort(ctx context.Context, in *sysin.CronMaxSortInp) (res *sysin.CronMaxSortModel, err error)
// View 获取指定信息
View(ctx context.Context, in *sysin.CronViewInp) (res *sysin.CronViewModel, err error)
// List 获取列表
List(ctx context.Context, in *sysin.CronListInp) (list []*sysin.CronListModel, totalCount int, err error)
// GetName 获取分组名称
GetName(ctx context.Context, id int64) (name string, err error)
// OnlineExec 在线执行
OnlineExec(ctx context.Context, in *sysin.OnlineExecInp) (err error)
// DispatchLog 查看指定任务的调度日志
DispatchLog(ctx context.Context, in *sysin.DispatchLogInp) (res *sysin.DispatchLogModel, err error)
}
ISysDictData interface {
// Delete 删除
Delete(ctx context.Context, in *sysin.DictDataDeleteInp) error
// Edit 修改/新增
Edit(ctx context.Context, in *sysin.DictDataEditInp) (err error)
// List 获取列表
List(ctx context.Context, in *sysin.DictDataListInp) (list []*sysin.DictDataListModel, totalCount int, err error)
// GetId 获取指定类型的ID
GetId(ctx context.Context, t string) (id int64, err error)
// GetType 获取指定ID的类型标识
GetType(ctx context.Context, id int64) (types string, err error)
// GetTypes 获取指定ID的所有类型标识包含下级
GetTypes(ctx context.Context, id int64) (types []string, err error)
// Select 获取列表
Select(ctx context.Context, in *sysin.DataSelectInp) (list sysin.DataSelectModel, err error)
}
ISysLoginLog interface {
// Model 登录日志Orm模型
Model(ctx context.Context) *gdb.Model
// List 获取登录日志列表
List(ctx context.Context, in *sysin.LoginLogListInp) (list []*sysin.LoginLogListModel, totalCount int, err error)
// Export 导出登录日志
Export(ctx context.Context, in *sysin.LoginLogListInp) (err error)
// Delete 删除登录日志
Delete(ctx context.Context, in *sysin.LoginLogDeleteInp) (err error)
// View 获取登录日志指定信息
View(ctx context.Context, in *sysin.LoginLogViewInp) (res *sysin.LoginLogViewModel, err error)
// Push 推送登录日志
Push(ctx context.Context, in *sysin.LoginLogPushInp)
// RealWrite 真实写入
RealWrite(ctx context.Context, models entity.SysLoginLog) (err error)
}
ISysServeLicense interface {
// Model 服务许可证ORM模型
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
// List 获取服务许可证列表
List(ctx context.Context, in *sysin.ServeLicenseListInp) (list []*sysin.ServeLicenseListModel, totalCount int, err error)
// Export 导出服务许可证
Export(ctx context.Context, in *sysin.ServeLicenseListInp) (err error)
// Edit 修改/新增服务许可证
Edit(ctx context.Context, in *sysin.ServeLicenseEditInp) (err error)
// Delete 删除服务许可证
Delete(ctx context.Context, in *sysin.ServeLicenseDeleteInp) (err error)
// View 获取服务许可证指定信息
View(ctx context.Context, in *sysin.ServeLicenseViewInp) (res *sysin.ServeLicenseViewModel, err error)
// Status 更新服务许可证状态
Status(ctx context.Context, in *sysin.ServeLicenseStatusInp) (err error)
// AssignRouter 分配服务许可证路由
AssignRouter(ctx context.Context, in *sysin.ServeLicenseAssignRouterInp) (err error)
}
) )
var ( var (
localSysAddons ISysAddons
localSysAttachment ISysAttachment
localSysCurdDemo ISysCurdDemo localSysCurdDemo ISysCurdDemo
localSysLog ISysLog localSysDictData ISysDictData
localSysEmsLog ISysEmsLog
localSysLoginLog ISysLoginLog
localSysAddonsConfig ISysAddonsConfig
localSysBlacklist ISysBlacklist
localSysCron ISysCron
localSysServeLicense ISysServeLicense
localSysSmsLog ISysSmsLog localSysSmsLog ISysSmsLog
localSysConfig ISysConfig
localSysCronGroup ISysCronGroup
localSysLog ISysLog
localSysProvinces ISysProvinces localSysProvinces ISysProvinces
localSysServeLog ISysServeLog localSysServeLog ISysServeLog
localSysDictType ISysDictType localSysDictType ISysDictType
localSysEmsLog ISysEmsLog
localSysGenCodes ISysGenCodes localSysGenCodes ISysGenCodes
localSysDictData ISysDictData
localSysLoginLog ISysLoginLog
localSysServeLicense ISysServeLicense
localSysAddons ISysAddons
localSysAttachment ISysAttachment
localSysCron ISysCron
localSysCronGroup ISysCronGroup
localSysAddonsConfig ISysAddonsConfig
localSysBlacklist ISysBlacklist
localSysConfig ISysConfig
) )
func SysDictData() ISysDictData {
if localSysDictData == nil {
panic("implement not found for interface ISysDictData, forgot register?")
}
return localSysDictData
}
func RegisterSysDictData(i ISysDictData) {
localSysDictData = i
}
func SysLoginLog() ISysLoginLog {
if localSysLoginLog == nil {
panic("implement not found for interface ISysLoginLog, forgot register?")
}
return localSysLoginLog
}
func RegisterSysLoginLog(i ISysLoginLog) {
localSysLoginLog = i
}
func SysServeLicense() ISysServeLicense {
if localSysServeLicense == nil {
panic("implement not found for interface ISysServeLicense, forgot register?")
}
return localSysServeLicense
}
func RegisterSysServeLicense(i ISysServeLicense) {
localSysServeLicense = i
}
func SysAddons() ISysAddons {
if localSysAddons == nil {
panic("implement not found for interface ISysAddons, forgot register?")
}
return localSysAddons
}
func RegisterSysAddons(i ISysAddons) {
localSysAddons = i
}
func SysAttachment() ISysAttachment { func SysAttachment() ISysAttachment {
if localSysAttachment == nil { if localSysAttachment == nil {
panic("implement not found for interface ISysAttachment, forgot register?") panic("implement not found for interface ISysAttachment, forgot register?")
@ -431,61 +387,6 @@ func RegisterSysAttachment(i ISysAttachment) {
localSysAttachment = i localSysAttachment = i
} }
func SysCron() ISysCron {
if localSysCron == nil {
panic("implement not found for interface ISysCron, forgot register?")
}
return localSysCron
}
func RegisterSysCron(i ISysCron) {
localSysCron = i
}
func SysCronGroup() ISysCronGroup {
if localSysCronGroup == nil {
panic("implement not found for interface ISysCronGroup, forgot register?")
}
return localSysCronGroup
}
func RegisterSysCronGroup(i ISysCronGroup) {
localSysCronGroup = i
}
func SysAddonsConfig() ISysAddonsConfig {
if localSysAddonsConfig == nil {
panic("implement not found for interface ISysAddonsConfig, forgot register?")
}
return localSysAddonsConfig
}
func RegisterSysAddonsConfig(i ISysAddonsConfig) {
localSysAddonsConfig = i
}
func SysBlacklist() ISysBlacklist {
if localSysBlacklist == nil {
panic("implement not found for interface ISysBlacklist, forgot register?")
}
return localSysBlacklist
}
func RegisterSysBlacklist(i ISysBlacklist) {
localSysBlacklist = i
}
func SysConfig() ISysConfig {
if localSysConfig == nil {
panic("implement not found for interface ISysConfig, forgot register?")
}
return localSysConfig
}
func RegisterSysConfig(i ISysConfig) {
localSysConfig = i
}
func SysCurdDemo() ISysCurdDemo { func SysCurdDemo() ISysCurdDemo {
if localSysCurdDemo == nil { if localSysCurdDemo == nil {
panic("implement not found for interface ISysCurdDemo, forgot register?") panic("implement not found for interface ISysCurdDemo, forgot register?")
@ -497,15 +398,81 @@ func RegisterSysCurdDemo(i ISysCurdDemo) {
localSysCurdDemo = i localSysCurdDemo = i
} }
func SysLog() ISysLog { func SysDictData() ISysDictData {
if localSysLog == nil { if localSysDictData == nil {
panic("implement not found for interface ISysLog, forgot register?") panic("implement not found for interface ISysDictData, forgot register?")
} }
return localSysLog return localSysDictData
} }
func RegisterSysLog(i ISysLog) { func RegisterSysDictData(i ISysDictData) {
localSysLog = i localSysDictData = i
}
func SysEmsLog() ISysEmsLog {
if localSysEmsLog == nil {
panic("implement not found for interface ISysEmsLog, forgot register?")
}
return localSysEmsLog
}
func RegisterSysEmsLog(i ISysEmsLog) {
localSysEmsLog = i
}
func SysLoginLog() ISysLoginLog {
if localSysLoginLog == nil {
panic("implement not found for interface ISysLoginLog, forgot register?")
}
return localSysLoginLog
}
func RegisterSysLoginLog(i ISysLoginLog) {
localSysLoginLog = i
}
func SysAddons() ISysAddons {
if localSysAddons == nil {
panic("implement not found for interface ISysAddons, forgot register?")
}
return localSysAddons
}
func RegisterSysAddons(i ISysAddons) {
localSysAddons = i
}
func SysBlacklist() ISysBlacklist {
if localSysBlacklist == nil {
panic("implement not found for interface ISysBlacklist, forgot register?")
}
return localSysBlacklist
}
func RegisterSysBlacklist(i ISysBlacklist) {
localSysBlacklist = i
}
func SysCron() ISysCron {
if localSysCron == nil {
panic("implement not found for interface ISysCron, forgot register?")
}
return localSysCron
}
func RegisterSysCron(i ISysCron) {
localSysCron = i
}
func SysServeLicense() ISysServeLicense {
if localSysServeLicense == nil {
panic("implement not found for interface ISysServeLicense, forgot register?")
}
return localSysServeLicense
}
func RegisterSysServeLicense(i ISysServeLicense) {
localSysServeLicense = i
} }
func SysSmsLog() ISysSmsLog { func SysSmsLog() ISysSmsLog {
@ -519,6 +486,39 @@ func RegisterSysSmsLog(i ISysSmsLog) {
localSysSmsLog = i localSysSmsLog = i
} }
func SysAddonsConfig() ISysAddonsConfig {
if localSysAddonsConfig == nil {
panic("implement not found for interface ISysAddonsConfig, forgot register?")
}
return localSysAddonsConfig
}
func RegisterSysAddonsConfig(i ISysAddonsConfig) {
localSysAddonsConfig = i
}
func SysCronGroup() ISysCronGroup {
if localSysCronGroup == nil {
panic("implement not found for interface ISysCronGroup, forgot register?")
}
return localSysCronGroup
}
func RegisterSysCronGroup(i ISysCronGroup) {
localSysCronGroup = i
}
func SysLog() ISysLog {
if localSysLog == nil {
panic("implement not found for interface ISysLog, forgot register?")
}
return localSysLog
}
func RegisterSysLog(i ISysLog) {
localSysLog = i
}
func SysProvinces() ISysProvinces { func SysProvinces() ISysProvinces {
if localSysProvinces == nil { if localSysProvinces == nil {
panic("implement not found for interface ISysProvinces, forgot register?") panic("implement not found for interface ISysProvinces, forgot register?")
@ -541,26 +541,15 @@ func RegisterSysServeLog(i ISysServeLog) {
localSysServeLog = i localSysServeLog = i
} }
func SysDictType() ISysDictType { func SysConfig() ISysConfig {
if localSysDictType == nil { if localSysConfig == nil {
panic("implement not found for interface ISysDictType, forgot register?") panic("implement not found for interface ISysConfig, forgot register?")
} }
return localSysDictType return localSysConfig
} }
func RegisterSysDictType(i ISysDictType) { func RegisterSysConfig(i ISysConfig) {
localSysDictType = i localSysConfig = i
}
func SysEmsLog() ISysEmsLog {
if localSysEmsLog == nil {
panic("implement not found for interface ISysEmsLog, forgot register?")
}
return localSysEmsLog
}
func RegisterSysEmsLog(i ISysEmsLog) {
localSysEmsLog = i
} }
func SysGenCodes() ISysGenCodes { func SysGenCodes() ISysGenCodes {
@ -573,3 +562,14 @@ func SysGenCodes() ISysGenCodes {
func RegisterSysGenCodes(i ISysGenCodes) { func RegisterSysGenCodes(i ISysGenCodes) {
localSysGenCodes = i localSysGenCodes = i
} }
func SysDictType() ISysDictType {
if localSysDictType == nil {
panic("implement not found for interface ISysDictType, forgot register?")
}
return localSysDictType
}
func RegisterSysDictType(i ISysDictType) {
localSysDictType = i
}

View File

@ -23,7 +23,7 @@ SET @now := now();
-- 菜单目录 -- 菜单目录
INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, '@{.options.Menu.Pid}', '@{.tableComment}', '@{.varName | LcFirst}', '/@{.varName | LcFirst}', '@{.options.Menu.Icon}', '1', '', '', '', '@{.mainComponent}', '1', '', '0', '0', '', '0', '0', '0', '1', '', '@{.options.Menu.Sort}', '', '1', @now, @now); INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, '@{.options.Menu.Pid}', '@{.tableComment}', '@{.varName | LcFirst}', '/@{.varName | LcFirst}', '@{.options.Menu.Icon}', '1', '', '', '', '@{.mainComponent}', '1', '', '0', '0', '', '0', '0', '0', '@{.dirLevel}', '@{.dirTree}', '@{.options.Menu.Sort}', '', '1', @now, @now);
SET @dirId = LAST_INSERT_ID(); SET @dirId = LAST_INSERT_ID();
@ -31,41 +31,41 @@ SET @dirId = LAST_INSERT_ID();
-- 菜单页面 -- 菜单页面
-- 列表 -- 列表
INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @dirId, '@{.tableComment}列表', '@{.varName | LcFirst}Index', 'index', '', '2', '', '/@{.apiPrefix}/list', '', '/@{.componentPrefix}/index', '1', '', '0', '0', '', '0', '0', '0', '2', '', '10', '', '1', @now, @now); INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @dirId, '@{.tableComment}列表', '@{.varName | LcFirst}Index', 'index', '', '2', '', '/@{.apiPrefix}/list', '', '/@{.componentPrefix}/index', '1', '', '0', '0', '', '0', '0', '0', '@{.listLevel}', CONCAT('@{.dirTree}tr_', @dirId,' '), '10', '', '1', @now, @now);
SET @listId = LAST_INSERT_ID(); SET @listId = LAST_INSERT_ID();
@{ if or (eq .options.Step.HasView true) (eq .options.Step.HasEdit true) } @{ if or (eq .options.Step.HasView true) (eq .options.Step.HasEdit true) }
-- 详情 -- 详情
INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @dirId, '@{.tableComment}详情', '@{.varName | LcFirst}View', 'view/:id?', '', '2', '', '/@{.apiPrefix}/view', '', '/@{.componentPrefix}/view', '0', '@{.varName | LcFirst}Index', '0', '0', '', '0', '1', '0', '2', '', '20', '', '1', @now, @now); INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '@{.tableComment}详情', '@{.varName | LcFirst}View', '', '', '3', '', '/@{.apiPrefix}/view', '', '', '1', '', '0', '0', '', '0', '1', '0', '@{.btnLevel}', CONCAT('@{.dirTree}tr_', @dirId, ' tr_', @listId,' '), '10', '', '1', @now, @now);
@{end} @{end}
-- 菜单按钮 -- 菜单按钮
@{ if eq .options.Step.HasEdit true } @{ if eq .options.Step.HasEdit true }
-- 编辑 -- 编辑
INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '编辑/新增@{.tableComment}', '@{.varName | LcFirst}Edit', '', '', '3', '', '/@{.apiPrefix}/edit', '', '', '1', '', '0', '0', '', '0', '1', '0', '3', '', '10', '', '1', @now, @now); INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '编辑/新增@{.tableComment}', '@{.varName | LcFirst}Edit', '', '', '3', '', '/@{.apiPrefix}/edit', '', '', '1', '', '0', '0', '', '0', '1', '0', '@{.btnLevel}', CONCAT('@{.dirTree}tr_', @dirId, ' tr_', @listId,' '), '20', '', '1', @now, @now);
@{end} @{end}
SET @editId = LAST_INSERT_ID(); SET @editId = LAST_INSERT_ID();
@{ if and (eq .options.Step.HasEdit true) (eq .options.Step.HasMaxSort true) } @{ if and (eq .options.Step.HasEdit true) (eq .options.Step.HasMaxSort true) }
-- 获取最大排序 -- 获取最大排序
INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @editId, '获取@{.tableComment}最大排序', '@{.varName | LcFirst}MaxSort', '', '', '3', '', '/@{.apiPrefix}/maxSort', '', '', '1', '', '0', '0', '', '0', '0', '0', '3', '', '10', '', '1', @now, @now); INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @editId, '获取@{.tableComment}最大排序', '@{.varName | LcFirst}MaxSort', '', '', '3', '', '/@{.apiPrefix}/maxSort', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.sortLevel}', CONCAT('@{.dirTree}tr_', @dirId, ' tr_', @listId, ' tr_', @editId,' '), '30', '', '1', @now, @now);
@{end} @{end}
@{ if eq .options.Step.HasDel true } @{ if eq .options.Step.HasDel true }
-- 删除 -- 删除
INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '删除@{.tableComment}', '@{.varName | LcFirst}Delete', '', '', '3', '', '/@{.apiPrefix}/delete', '', '', '1', '', '0', '0', '', '0', '0', '0', '3', '', '10', '', '1', @now, @now); INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '删除@{.tableComment}', '@{.varName | LcFirst}Delete', '', '', '3', '', '/@{.apiPrefix}/delete', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.btnLevel}', CONCAT('@{.dirTree}tr_', @dirId, ' tr_', @listId,' '), '40', '', '1', @now, @now);
@{end} @{end}
@{ if eq .options.Step.HasStatus true } @{ if eq .options.Step.HasStatus true }
-- 更新状态 -- 更新状态
INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '修改@{.tableComment}状态', '@{.varName | LcFirst}Status', '', '', '3', '', '/@{.apiPrefix}/status', '', '', '1', '', '0', '0', '', '0', '0', '0', '3', '', '10', '', '1', @now, @now); INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '修改@{.tableComment}状态', '@{.varName | LcFirst}Status', '', '', '3', '', '/@{.apiPrefix}/status', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.btnLevel}', CONCAT('@{.dirTree}tr_', @dirId, ' tr_', @listId,' '), '50', '', '1', @now, @now);
@{end} @{end}
@{ if eq .options.Step.HasSwitch true } @{ if eq .options.Step.HasSwitch true }
-- 操作开关 -- 操作开关
INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '操作@{.tableComment}开关', '@{.varName | LcFirst}Switch', '', '', '3', '', '/@{.apiPrefix}/switch', '', '', '1', '', '0', '0', '', '0', '0', '0', '3', '', '10', '', '1', @now, @now); INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '操作@{.tableComment}开关', '@{.varName | LcFirst}Switch', '', '', '3', '', '/@{.apiPrefix}/switch', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.btnLevel}', CONCAT('@{.dirTree}tr_', @dirId, ' tr_', @listId,' '), '60', '', '1', @now, @now);
@{end} @{end}
@{ if eq .options.Step.HasExport true } @{ if eq .options.Step.HasExport true }
-- 导出 -- 导出
INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '导出@{.tableComment}', '@{.varName | LcFirst}Export', '', '', '3', '', '/@{.apiPrefix}/export', '', '', '1', '', '0', '0', '', '0', '0', '0', '3', '', '10', '', '1', @now, @now); INSERT INTO `@{.menuTable}` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '导出@{.tableComment}', '@{.varName | LcFirst}Export', '', '', '3', '', '/@{.apiPrefix}/export', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.btnLevel}', CONCAT('@{.dirTree}tr_', @dirId, ' tr_', @listId,' '), '70', '', '1', @now, @now);
@{end} @{end}
COMMIT; COMMIT;

View File

@ -2,24 +2,28 @@
<div> <div>
<n-spin :show="loading" description="请稍候..."> <n-spin :show="loading" description="请稍候...">
<n-modal <n-modal
v-model:show="isShowModal" v-model:show="showModal"
:mask-closable="false"
:show-icon="false" :show-icon="false"
preset="dialog" preset="dialog"
:title="params?.@{.pk.TsName} > 0 ? '编辑 #' + params?.@{.pk.TsName} : '添加'" transform-origin="center"
:title="formValue.@{.pk.TsName} > 0 ? '编辑 #' + formValue.@{.pk.TsName} : '添加'"
:style="{ :style="{
width: dialogWidth, width: dialogWidth,
}" }"
> >
<n-form <n-scrollbar style="max-height: 87vh" class="pr-5">
:model="params" <n-form
:rules="rules" :model="formValue"
ref="formRef" :rules="rules"
label-placement="left" ref="formRef"
:label-width="100" :label-placement="settingStore.isMobile ? 'top' : 'left'"
class="py-4" :label-width="100"
> class="py-4"
@{.formItem} >
</n-form> @{.formItem}
</n-form>
</n-scrollbar>
<template #action> <template #action>
<n-space> <n-space>
<n-button @click="closeForm">取消</n-button> <n-button @click="closeForm">取消</n-button>
@ -33,37 +37,18 @@
<script lang="ts" setup> <script lang="ts" setup>
@{.script.import} import { rules, options, State, newState } from './model'; @{.script.import} import { rules, options, State, newState } from './model';
import { useProjectSettingStore } from '@/store/modules/projectSetting';
import { useMessage } from 'naive-ui'; import { useMessage } from 'naive-ui';
import { adaModalWidth } from '@/utils/hotgo'; import { adaModalWidth } from '@/utils/hotgo';
const emit = defineEmits(['reloadTable', 'updateShowModal']); const emit = defineEmits(['reloadTable']);
interface Props {
showModal: boolean;
formParams?: State;
}
const props = withDefaults(defineProps<Props>(), {
showModal: false,
formParams: () => {
return newState(null);
},
});
const isShowModal = computed({
get: () => {
return props.showModal;
},
set: (value) => {
emit('updateShowModal', value);
},
});
const loading = ref(false);
const params = ref<State>(props.formParams);
const message = useMessage(); const message = useMessage();
const formRef = ref<any>({}); const settingStore = useProjectSettingStore();
const dialogWidth = ref('75%'); const dialogWidth = ref('75%');
const loading = ref(false);
const showModal = ref(false);
const formValue = ref<State>(newState(null));
const formRef = ref<any>({});
const formBtnLoading = ref(false); const formBtnLoading = ref(false);
function confirmForm(e) { function confirmForm(e) {
@ -71,10 +56,10 @@
formBtnLoading.value = true; formBtnLoading.value = true;
formRef.value.validate((errors) => { formRef.value.validate((errors) => {
if (!errors) { if (!errors) {
Edit(params.value).then((_res) => { Edit(formValue.value).then((_res) => {
message.success('操作成功'); message.success('操作成功');
setTimeout(() => { setTimeout(() => {
isShowModal.value = false; showModal.value = false;
emit('reloadTable'); emit('reloadTable');
}); });
}); });
@ -85,15 +70,16 @@
}); });
} }
onMounted(async () => {
adaModalWidth(dialogWidth);
});
function closeForm() { function closeForm() {
isShowModal.value = false; showModal.value = false;
loading.value = false;
} }
@{.script.setup} @{.script.setup}
defineExpose({
openModal,
});
</script> </script>
<style lang="less"></style> <style lang="less"></style>

View File

@ -76,12 +76,8 @@
</template> </template>
</BasicTable> </BasicTable>
</n-card> </n-card>
@{ if eq .options.Step.HasEdit true } <Edit @{ if eq .options.Step.HasEdit true } <Edit @reloadTable="reloadTable" ref="editRef" />@{end}
@reloadTable="reloadTable" @{ if eq .options.Step.HasView true } <View ref="viewRef" />@{end}
@updateShowModal="updateShowModal"
:showModal="showModal"
:formParams="formParams"
/>@{end}
</div> </div>
</template> </template>
@ -92,21 +88,21 @@
import { BasicForm, useForm } from '@/components/Form/index'; import { BasicForm, useForm } from '@/components/Form/index';
import { usePermission } from '@/hooks/web/usePermission'; import { usePermission } from '@/hooks/web/usePermission';
@{.apiImport} @{.apiImport}
import { State, columns, schemas, options, newState } from './model'; import { columns, schemas, options } from './model';
@{.iconsImport} @{.iconsImport}
@{ if or (eq .options.Step.HasView true) (eq .options.Step.HasEdit true) } import { useRouter } from 'vue-router';@{end}
import { getOptionLabel } from '@/utils/hotgo'; import { getOptionLabel } from '@/utils/hotgo';
@{ if eq .options.Step.HasEdit true } import Edit from './edit.vue';@{end} @{ if eq .options.Step.HasEdit true } import Edit from './edit.vue';@{end}
const { hasPermission } = usePermission(); @{ if eq .options.Step.HasView true } import View from './view.vue';@{end}
@{ if or (eq .options.Step.HasView true) (eq .options.Step.HasEdit true) } const router = useRouter();@{end}
const actionRef = ref();
const dialog = useDialog(); const dialog = useDialog();
const message = useMessage(); const message = useMessage();
const { hasPermission } = usePermission();
const actionRef = ref();
const searchFormRef = ref<any>({}); const searchFormRef = ref<any>({});
const viewRef = ref();
const editRef = ref();
const batchDeleteDisabled = ref(true); const batchDeleteDisabled = ref(true);
const checkedIds = ref([]); const checkedIds = ref([]);
const showModal = ref(false);
const formParams = ref<State>();
const actionColumn = reactive({ const actionColumn = reactive({
width: 300, width: 300,
@ -169,15 +165,6 @@
const loadDataTable = async (res) => { const loadDataTable = async (res) => {
return await List({ ...searchFormRef.value?.formModel, ...res }); return await List({ ...searchFormRef.value?.formModel, ...res });
}; };
@{ if eq .options.Step.HasAdd true }
function addTable() {
showModal.value = true;
formParams.value = newState(null);
}@{end}
@{ if or (eq .options.Step.HasAdd true) (eq .options.Step.HasEdit true) }
function updateShowModal(value) {
showModal.value = value;
}@{end}
@{ if eq .options.Step.HasCheck true } function onCheckedRow(rowKeys) { @{ if eq .options.Step.HasCheck true } function onCheckedRow(rowKeys) {
batchDeleteDisabled.value = rowKeys.length <= 0; batchDeleteDisabled.value = rowKeys.length <= 0;
@ -187,14 +174,17 @@
function reloadTable() { function reloadTable() {
actionRef.value.reload(); actionRef.value.reload();
} }
@{ if eq .options.Step.HasView true } @{ if eq .options.Step.HasAdd true }
function handleView(record: Recordable) { function addTable() {
router.push({ name: '@{.varName | LcFirst}View', params: { id: record.@{.pk.TsName} } }); editRef.value.openModal(null);
}@{end} }@{end}
@{ if eq .options.Step.HasEdit true } @{ if eq .options.Step.HasEdit true }
function handleEdit(record: Recordable) { function handleEdit(record: Recordable) {
showModal.value = true; editRef.value.openModal(record);
formParams.value = newState(record as State); }@{end}
@{ if eq .options.Step.HasView true }
function handleView(record: Recordable) {
viewRef.value.openModal(record);
}@{end} }@{end}
@{ if eq .options.Step.HasDel true } function handleDelete(record: Recordable) { @{ if eq .options.Step.HasDel true } function handleDelete(record: Recordable) {
@ -209,9 +199,6 @@
reloadTable(); reloadTable();
}); });
}, },
onNegativeClick: () => {
// message.error('取消');
},
}); });
}@{end} }@{end}
@ -229,9 +216,6 @@
reloadTable(); reloadTable();
}); });
}, },
onNegativeClick: () => {
// message.error('取消');
},
}); });
}@{end} }@{end}

View File

@ -8,24 +8,25 @@ import { isArray, isNullObject } from '@/utils/is';
import { getFileExt } from '@/utils/urlUtils'; import { getFileExt } from '@/utils/urlUtils';
import { defRangeShortcuts, defShortcuts, formatToDate } from '@/utils/dateUtil'; import { defRangeShortcuts, defShortcuts, formatToDate } from '@/utils/dateUtil';
import { validate } from '@/utils/validateUtil'; import { validate } from '@/utils/validateUtil';
import { getOptionLabel, getOptionTag, Options, errorImg } from '@/utils/hotgo'; import { getOptionLabel, getOptionTag, Option, Options, errorImg } from '@/utils/hotgo';
@{ if eq .options.Step.HasSwitch true } @{ if eq .options.Step.HasSwitch true }
import { usePermission } from '@/hooks/web/usePermission'; import { usePermission } from '@/hooks/web/usePermission';
const { hasPermission } = usePermission(); const { hasPermission } = usePermission();
const $message = window['$message']; const $message = window['$message'];
@{end} @{end}
@{.state} @{.state}
@{.defaultState} export function newState(state: State | Record<string, any> | null): State {
export function newState(state: State | null): State {
if (state !== null) { if (state !== null) {
return cloneDeep(state); if (state instanceof State) {
return cloneDeep(state);
}
return new State(state);
} }
return cloneDeep(defaultState); return new State();
} }
@{.dictOptions.interface}
@{.dictOptions.const} @{.dictOptions.const}
@{.rules} @{.rules}
@{.formSchema} @{.formSchema}

View File

@ -1,28 +1,33 @@
<template> <template>
<div> <div>
<div class="n-layout-page-header"> <n-spin :show="loading" description="请稍候...">
<n-card :bordered="false" title="@{.tableComment}详情"> <!-- CURD详情页--> </n-card> <n-drawer v-model:show="showModal" :width="dialogWidth">
</div> <n-drawer-content>
<n-card :bordered="false" class="proCard mt-4" size="small" :segmented="{ content: true }"> <template #header> 生成演示详情 </template>
<n-descriptions label-placement="left" class="py-2" column="4"> <template #footer>
@{.item} <n-button @click="showModal = false"> 关闭 </n-button>
</n-descriptions> </template>
</n-card> <n-descriptions label-placement="left" class="py-2" column="1">
@{.item}
</n-descriptions>
</n-drawer-content>
</n-drawer>
</n-spin>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, onMounted, ref } from 'vue'; import { computed, ref } from 'vue';
import { useRouter } from 'vue-router';
import { useMessage } from 'naive-ui'; import { useMessage } from 'naive-ui';
import { View } from '@{.importWebApi}'; import { View } from '@{.importWebApi}';
import { newState, options } from './model'; import { State, newState, options } from './model';
import { getOptionLabel, getOptionTag } from '@/utils/hotgo'; import { adaModalWidth, getOptionLabel, getOptionTag } from '@/utils/hotgo';
import { getFileExt } from '@/utils/urlUtils'; import { getFileExt } from '@/utils/urlUtils';
const message = useMessage(); const message = useMessage();
const router = useRouter(); const dialogWidth = ref('75%');
const id = Number(router.currentRoute.value.params.id); const loading = ref(false);
const showModal = ref(false);
const formValue = ref(newState(null)); const formValue = ref(newState(null));
const fileAvatarCSS = computed(() => { const fileAvatarCSS = computed(() => {
return { return {
@ -36,12 +41,21 @@
window.open(url); window.open(url);
} }
onMounted(async () => { function openModal(state: State) {
if (id < 1) { adaModalWidth(dialogWidth, 580);
message.error('@{.pk.Dc}不正确请检查'); showModal.value = true;
return; loading.value = true;
} View({ id: state.id })
formValue.value = await View({ @{.pk.TsName}: id }); .then((res) => {
formValue.value = res;
})
.finally(() => {
loading.value = false;
});
}
defineExpose({
openModal,
}); });
</script> </script>

View File

@ -1,7 +1,7 @@
-- hotgo自动生成菜单权限SQL 通常情况下只在首次生成代码时自动执行一次 -- hotgo自动生成菜单权限SQL 通常情况下只在首次生成代码时自动执行一次
-- 如需再次执行请先手动删除生成的菜单权限和在SQL文件E:\Users\Administrator\Desktop\gosrc\hotgo\server\resource\data\generate\curd_demo_menu.sql -- 如需再次执行请先手动删除生成的菜单权限和在SQL文件C:\Users\Administrator\Desktop\gosrc\hotgo_dev\server\storage\data\generate\curd_demo_menu.sql
-- Version: 2.1.0 -- Version: 2.11.5
-- Date: 2023-01-18 15:19:42 -- Date: 2023-12-29 18:18:21
-- Link https://github.com/bufanyun/hotgo -- Link https://github.com/bufanyun/hotgo
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
@ -23,7 +23,7 @@ SET @now := now();
-- 菜单目录 -- 菜单目录
INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, '2097', '生成演示', 'curdDemo', '/curdDemo', 'MenuOutlined', '1', '', '', '', 'ParentLayout', '1', '', '0', '0', '', '0', '0', '0', '1', '', '200', '', '1', @now, @now); INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, '2097', '生成演示', 'curdDemo', '/curdDemo', 'MenuOutlined', '1', '', '', '', 'ParentLayout', '1', '', '0', '0', '', '0', '0', '0', '2', 'tr_2097 ', '200', '', '1', @now, @now);
SET @dirId = LAST_INSERT_ID(); SET @dirId = LAST_INSERT_ID();
@ -31,41 +31,41 @@ SET @dirId = LAST_INSERT_ID();
-- 菜单页面 -- 菜单页面
-- 列表 -- 列表
INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @dirId, '生成演示列表', 'curdDemoIndex', 'index', '', '2', '', '/curdDemo/list', '', '/curdDemo/index', '1', '', '0', '0', '', '0', '0', '0', '2', '', '10', '', '1', @now, @now); INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @dirId, '生成演示列表', 'curdDemoIndex', 'index', '', '2', '', '/curdDemo/list', '', '/curdDemo/index', '1', '', '0', '0', '', '0', '0', '0', '3', CONCAT('tr_2097 tr_', @dirId,' '), '10', '', '1', @now, @now);
SET @listId = LAST_INSERT_ID(); SET @listId = LAST_INSERT_ID();
-- 详情 -- 详情
INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @dirId, '生成演示详情', 'curdDemoView', 'view/:id?', '', '2', '', '/curdDemo/view', '', '/curdDemo/view', '0', 'curdDemoIndex', '0', '0', '', '0', '1', '0', '2', '', '20', '', '1', @now, @now); INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '生成演示详情', 'curdDemoView', '', '', '3', '', '/curdDemo/view', '', '', '1', '', '0', '0', '', '0', '1', '0', '4', CONCAT('tr_2097 tr_', @dirId, ' tr_', @listId,' '), '10', '', '1', @now, @now);
-- 菜单按钮 -- 菜单按钮
-- 编辑 -- 编辑
INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '编辑/新增生成演示', 'curdDemoEdit', '', '', '3', '', '/curdDemo/edit', '', '', '1', '', '0', '0', '', '0', '1', '0', '3', '', '10', '', '1', @now, @now); INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '编辑/新增生成演示', 'curdDemoEdit', '', '', '3', '', '/curdDemo/edit', '', '', '1', '', '0', '0', '', '0', '1', '0', '4', CONCAT('tr_2097 tr_', @dirId, ' tr_', @listId,' '), '20', '', '1', @now, @now);
SET @editId = LAST_INSERT_ID(); SET @editId = LAST_INSERT_ID();
-- 获取最大排序 -- 获取最大排序
INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @editId, '获取生成演示最大排序', 'curdDemoMaxSort', '', '', '3', '', '/curdDemo/maxSort', '', '', '1', '', '0', '0', '', '0', '0', '0', '3', '', '10', '', '1', @now, @now); INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @editId, '获取生成演示最大排序', 'curdDemoMaxSort', '', '', '3', '', '/curdDemo/maxSort', '', '', '1', '', '0', '0', '', '0', '0', '0', '5', CONCAT('tr_2097 tr_', @dirId, ' tr_', @listId, ' tr_', @editId,' '), '30', '', '1', @now, @now);
-- 删除 -- 删除
INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '删除生成演示', 'curdDemoDelete', '', '', '3', '', '/curdDemo/delete', '', '', '1', '', '0', '0', '', '0', '0', '0', '3', '', '10', '', '1', @now, @now); INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '删除生成演示', 'curdDemoDelete', '', '', '3', '', '/curdDemo/delete', '', '', '1', '', '0', '0', '', '0', '0', '0', '4', CONCAT('tr_2097 tr_', @dirId, ' tr_', @listId,' '), '40', '', '1', @now, @now);
-- 更新状态 -- 更新状态
INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '修改生成演示状态', 'curdDemoStatus', '', '', '3', '', '/curdDemo/status', '', '', '1', '', '0', '0', '', '0', '0', '0', '3', '', '10', '', '1', @now, @now); INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '修改生成演示状态', 'curdDemoStatus', '', '', '3', '', '/curdDemo/status', '', '', '1', '', '0', '0', '', '0', '0', '0', '4', CONCAT('tr_2097 tr_', @dirId, ' tr_', @listId,' '), '50', '', '1', @now, @now);
-- 操作开关 -- 操作开关
INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '操作生成演示开关', 'curdDemoSwitch', '', '', '3', '', '/curdDemo/switch', '', '', '1', '', '0', '0', '', '0', '0', '0', '3', '', '10', '', '1', @now, @now); INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '操作生成演示开关', 'curdDemoSwitch', '', '', '3', '', '/curdDemo/switch', '', '', '1', '', '0', '0', '', '0', '0', '0', '4', CONCAT('tr_2097 tr_', @dirId, ' tr_', @listId,' '), '60', '', '1', @now, @now);
-- 导出 -- 导出
INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '导出生成演示', 'curdDemoExport', '', '', '3', '', '/curdDemo/export', '', '', '1', '', '0', '0', '', '0', '0', '0', '3', '', '10', '', '1', @now, @now); INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES (NULL, @listId, '导出生成演示', 'curdDemoExport', '', '', '3', '', '/curdDemo/export', '', '', '1', '', '0', '0', '', '0', '0', '0', '4', CONCAT('tr_2097 tr_', @dirId, ' tr_', @listId,' '), '70', '', '1', @now, @now);
COMMIT; COMMIT;

View File

@ -37,19 +37,12 @@ module.exports = defineConfig({
'@typescript-eslint/ban-types': 'off', '@typescript-eslint/ban-types': 'off',
'@typescript-eslint/no-non-null-assertion': 'off', '@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-unused-vars': [ '@typescript-eslint/no-unused-vars': ['error', { varsIgnorePattern: '.*', args: 'none' }],
'error',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],
'no-unused-vars': [ 'no-unused-vars': [
'error', 'error',
{ // we are only using this rule to check for unused arguments since TS
argsIgnorePattern: '^_', // catches unused variables but not args.
varsIgnorePattern: '^_', { varsIgnorePattern: '.*', args: 'none' },
},
], ],
'space-before-function-paren': 'off', 'space-before-function-paren': 'off',

View File

@ -1,6 +1,6 @@
{ {
"name": "hotgo", "name": "hotgo",
"version": "2.11.5", "version": "2.12.1",
"author": { "author": {
"name": "MengShuai", "name": "MengShuai",
"email": "133814250@qq.com", "email": "133814250@qq.com",
@ -28,39 +28,39 @@
"test prod gzip": "http-server dist --cors --gzip -c-1" "test prod gzip": "http-server dist --cors --gzip -c-1"
}, },
"dependencies": { "dependencies": {
"@vicons/antd": "^0.10.0", "@vicons/antd": "^0.12.0",
"@vicons/ionicons5": "^0.10.0", "@vicons/ionicons5": "^0.12.0",
"@vueup/vue-quill": "^1.1.0", "@vueup/vue-quill": "^1.2.0",
"@vueuse/core": "^5.3.0", "@vueuse/core": "^10.7.1",
"axios": "^0.21.4", "axios": "^0.21.4",
"date-fns": "^2.28.0", "date-fns": "^2.28.0",
"echarts": "^5.3.2", "echarts": "^5.3.2",
"element-resize-detector": "^1.2.4", "element-resize-detector": "^1.2.4",
"highlight.js": "^11.8.0", "highlight.js": "^11.8.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"naive-ui": "^2.34.3", "naive-ui": "^2.36.0",
"pinia": "^2.0.14", "pinia": "^2.1.7",
"qrcode.vue": "3.3.3", "qrcode.vue": "3.3.3",
"qs": "^6.10.3", "qs": "^6.10.3",
"quill-image-uploader": "^1.2.4", "quill-image-uploader": "^1.3.0",
"quill-magic-url": "^4.2.0", "quill-magic-url": "^4.2.0",
"throttle-debounce": "^5.0.0", "throttle-debounce": "^5.0.0",
"vue": "^3.2.35", "vue": "^3.4.0",
"vue-router": "^4.0.15", "vue-router": "^4.2.5",
"vue-types": "^4.1.1", "vue-types": "^5.1.1",
"vue3-json-viewer": "^2.2.2", "vue3-json-viewer": "^2.2.2",
"vuedraggable": "^4.1.0", "vuedraggable": "^4.1.0",
"weixin-js-sdk": "^1.6.0" "weixin-js-sdk": "^1.6.0"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^12.1.4", "@commitlint/cli": "^17.7.0",
"@commitlint/config-conventional": "^12.1.4", "@commitlint/config-conventional": "^17.7.0",
"@types/lodash": "^4.14.182", "@types/lodash": "^4.14.197",
"@types/node": "^15.14.9", "@types/node": "^18.17.4",
"@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^4.33.0", "@typescript-eslint/parser": "^5.62.0",
"@vitejs/plugin-vue": "^1.10.2", "@vitejs/plugin-vue": "^3.2.0",
"@vitejs/plugin-vue-jsx": "^1.3.10", "@vitejs/plugin-vue-jsx": "^2.1.1",
"@vue/compiler-sfc": "^3.2.33", "@vue/compiler-sfc": "^3.2.33",
"@vue/eslint-config-typescript": "^7.0.0", "@vue/eslint-config-typescript": "^7.0.0",
"autoprefixer": "^10.4.7", "autoprefixer": "^10.4.7",
@ -93,11 +93,11 @@
"tailwindcss": "^2.2.19", "tailwindcss": "^2.2.19",
"typescript": "^4.6.4", "typescript": "^4.6.4",
"unplugin-vue-components": "^0.17.21", "unplugin-vue-components": "^0.17.21",
"vite": "^2.9.8", "vite": "^4.2.7",
"vite-plugin-compression": "^0.3.6", "vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^2.1.2", "vite-plugin-html": "^2.1.2",
"vite-plugin-require-transform": "^1.0.5", "vite-plugin-require-transform": "^1.0.5",
"vite-plugin-style-import": "^1.4.1", "vite-plugin-style-import": "^2.0.0",
"vite-plugin-top-level-await": "^1.2.2", "vite-plugin-top-level-await": "^1.2.2",
"vite-plugin-vue-setup-extend": "^0.4.0", "vite-plugin-vue-setup-extend": "^0.4.0",
"vue-eslint-parser": "^7.11.0" "vue-eslint-parser": "^7.11.0"
@ -134,6 +134,6 @@
}, },
"homepage": "https://github.com/bufanyun/hotgo", "homepage": "https://github.com/bufanyun/hotgo",
"engines": { "engines": {
"node": "^12 || >=14" "node": ">=16"
} }
} }

View File

@ -1,4 +1,5 @@
import { http } from '@/utils/http/axios'; import { http } from '@/utils/http/axios';
import { useUserStoreWidthOut } from '@/store/modules/user';
// 获取验证码 // 获取验证码
export function GetCaptcha() { export function GetCaptcha() {
@ -10,9 +11,15 @@ export function GetCaptcha() {
// 上传图片 // 上传图片
export function UploadImage(params) { export function UploadImage(params) {
const useUserStore = useUserStoreWidthOut();
const headers = {
Authorization: useUserStore.token,
uploadType: 'default',
};
return http.request({ return http.request({
url: '/upload/image', url: '/upload/file',
method: 'post', method: 'post',
params, params,
headers,
}); });
} }

View File

@ -83,7 +83,7 @@
ref="fileUploadRef" ref="fileUploadRef"
:width="dialogWidth" :width="dialogWidth"
:finish-call="handleFinishCall" :finish-call="handleFinishCall"
max-upload="20" :max-upload="20"
/> />
<Preview ref="previewRef" /> <Preview ref="previewRef" />

View File

@ -9,8 +9,8 @@ import { PageEnum } from '@/enums/pageEnum';
import { useGlobSetting } from '@/hooks/setting'; import { useGlobSetting } from '@/hooks/setting';
import { isString } from '@/utils/is/'; import { isString, isUrl } from '@/utils/is/';
import { deepMerge, isUrl } from '@/utils'; import { deepMerge } from '@/utils';
import { setObjToUrlParams } from '@/utils/urlUtils'; import { setObjToUrlParams } from '@/utils/urlUtils';
import { CreateAxiosOptions, RequestOptions, Result } from './types'; import { CreateAxiosOptions, RequestOptions, Result } from './types';

View File

@ -250,9 +250,35 @@ export function lighten(color: string, amount: number) {
)}${addLight(color.substring(4, 6), amount)}`; )}${addLight(color.substring(4, 6), amount)}`;
} }
/** // 获取树的所有节点key
* url export function getAllExpandKeys(treeData: any): any[] {
* */ let expandedKeys = [];
export function isUrl(url: string) { const expandKeys = (items: any[]) => {
return /^(http|https):\/\//g.test(url); items.forEach((item: any) => {
expandedKeys.push(item.key);
if (item.children && item.children.length > 0) {
expandKeys(item.children);
}
});
};
expandKeys(unref(treeData));
// 去重并转换为数组
expandedKeys = Array.from(new Set(expandedKeys));
return expandedKeys;
}
// 从树中查找指定ID
export function findTreeDataById(data: any[], id: number | string) {
for (const item of data) {
if (item.id === id) {
return item;
}
if (item.children) {
const found = findTreeDataById(item.children, id);
if (found) return found;
}
}
return null;
} }

View File

@ -1,33 +1,50 @@
import { CSSProperties, VNodeChild } from 'vue'; import { CSSProperties, VNodeChild } from 'vue';
import { createTypes, VueTypeValidableDef, VueTypesInterface } from 'vue-types'; import {
createTypes,
VueTypeExtendCallback,
VueTypeValidableDef,
VueTypesInterface,
} from 'vue-types';
export type VueNode = VNodeChild | JSX.Element; export type VueNode = VNodeChild | JSX.Element;
type PropTypes = VueTypesInterface & { type ExtendedPropTypes = VueTypesInterface & {
readonly style: VueTypeValidableDef<CSSProperties>; readonly style: VueTypeValidableDef<CSSProperties>;
readonly VNodeChild: VueTypeValidableDef<VueNode>; readonly VNodeChild: VueTypeValidableDef<VueNode>;
}; };
const propTypes = createTypes({ class CustomVueTypes
func: undefined, extends (createTypes({
bool: undefined, func: undefined,
string: undefined, bool: undefined,
number: undefined, string: undefined,
object: undefined, number: undefined,
integer: undefined, object: undefined,
}) as PropTypes; integer: undefined,
}) as VueTypesInterface)
implements ExtendedPropTypes
{
static extend(types: VueTypeExtendCallback[]): CustomVueTypes {
return types.reduce((result, { name, ...callbacks }) => {
result[name] = { getter: true, ...callbacks };
return result;
}, this);
}
propTypes.extend([ readonly style!: VueTypeValidableDef<CSSProperties>;
readonly VNodeChild!: VueTypeValidableDef<VueNode>;
}
const propTypes = CustomVueTypes.extend([
{ {
name: 'style', name: 'style',
getter: true,
type: [String, Object], type: [String, Object],
default: undefined, default: undefined,
}, },
{ {
name: 'VNodeChild', name: 'VNodeChild',
getter: true,
type: undefined, type: undefined,
}, },
]); ]);
export { propTypes }; export { propTypes };

View File

@ -2,65 +2,69 @@
<div> <div>
<n-spin :show="loading" description="请稍候..."> <n-spin :show="loading" description="请稍候...">
<n-modal <n-modal
v-model:show="isShowModal" v-model:show="showModal"
:mask-closable="false"
:show-icon="false" :show-icon="false"
preset="dialog" preset="dialog"
:title="params?.id > 0 ? '编辑 #' + params?.id : '添加'" transform-origin="center"
:title="formValue.id > 0 ? '编辑 #' + formValue.id : '添加'"
:style="{ :style="{
width: dialogWidth, width: dialogWidth,
}" }"
> >
<n-form <n-scrollbar style="max-height: 87vh" class="pr-5">
:model="params" <n-form
:rules="rules" :model="formValue"
ref="formRef" :rules="rules"
label-placement="left" ref="formRef"
:label-width="100" :label-placement="settingStore.isMobile ? 'top' : 'left'"
class="py-4" :label-width="100"
> class="py-4"
<n-form-item label="分类ID" path="categoryId"> >
<n-input-number placeholder="请输入分类ID" v-model:value="params.categoryId" /> <n-form-item label="分类ID" path="categoryId">
<n-input-number placeholder="请输入分类ID" v-model:value="formValue.categoryId" />
</n-form-item> </n-form-item>
<n-form-item label="标题" path="title"> <n-form-item label="标题" path="title">
<n-input placeholder="请输入标题" v-model:value="params.title" /> <n-input placeholder="请输入标题" v-model:value="formValue.title" />
</n-form-item> </n-form-item>
<n-form-item label="描述" path="description"> <n-form-item label="描述" path="description">
<n-input type="textarea" placeholder="描述" v-model:value="params.description" /> <n-input type="textarea" placeholder="描述" v-model:value="formValue.description" />
</n-form-item> </n-form-item>
<n-form-item label="内容" path="content"> <n-form-item label="内容" path="content">
<Editor style="height: 450px" id="content" v-model:value="params.content" /> <Editor style="height: 450px" id="content" v-model:value="formValue.content" />
</n-form-item> </n-form-item>
<n-form-item label="单图" path="image"> <n-form-item label="单图" path="image">
<UploadImage :maxNumber="1" v-model:value="params.image" /> <UploadImage :maxNumber="1" v-model:value="formValue.image" />
</n-form-item> </n-form-item>
<n-form-item label="附件" path="attachfile"> <n-form-item label="附件" path="attachfile">
<UploadFile :maxNumber="1" v-model:value="params.attachfile" /> <UploadFile :maxNumber="1" v-model:value="formValue.attachfile" />
</n-form-item> </n-form-item>
<n-form-item label="所在城市" path="cityId"> <n-form-item label="所在城市" path="cityId">
<CitySelector v-model:value="params.cityId" /> <CitySelector v-model:value="formValue.cityId" />
</n-form-item> </n-form-item>
<n-form-item label="显示开关" path="switch"> <n-form-item label="显示开关" path="switch">
<n-switch :unchecked-value="2" :checked-value="1" v-model:value="params.switch" <n-switch :unchecked-value="2" :checked-value="1" v-model:value="formValue.switch"
/> />
</n-form-item> </n-form-item>
<n-form-item label="排序" path="sort"> <n-form-item label="排序" path="sort">
<n-input-number placeholder="请输入排序" v-model:value="params.sort" /> <n-input-number placeholder="请输入排序" v-model:value="formValue.sort" />
</n-form-item> </n-form-item>
<n-form-item label="状态" path="status"> <n-form-item label="状态" path="status">
<n-select v-model:value="params.status" :options="options.sys_normal_disable" /> <n-select v-model:value="formValue.status" :options="options.sys_normal_disable" />
</n-form-item> </n-form-item>
</n-form> </n-form>
</n-scrollbar>
<template #action> <template #action>
<n-space> <n-space>
<n-button @click="closeForm">取消</n-button> <n-button @click="closeForm">取消</n-button>
@ -73,44 +77,25 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, ref, computed, watch } from 'vue'; import { ref } from 'vue';
import { Edit, MaxSort, View } from '@/api/curdDemo'; import { Edit, MaxSort, View } from '@/api/curdDemo';
import Editor from '@/components/Editor/editor.vue'; import Editor from '@/components/Editor/editor.vue';
import UploadImage from '@/components/Upload/uploadImage.vue'; import UploadImage from '@/components/Upload/uploadImage.vue';
import UploadFile from '@/components/Upload/uploadFile.vue'; import UploadFile from '@/components/Upload/uploadFile.vue';
import CitySelector from '@/components/CitySelector/citySelector.vue'; import CitySelector from '@/components/CitySelector/citySelector.vue';
import { rules, options, State, newState } from './model'; import { rules, options, State, newState } from './model';
import { useProjectSettingStore } from '@/store/modules/projectSetting';
import { useMessage } from 'naive-ui'; import { useMessage } from 'naive-ui';
import { adaModalWidth } from '@/utils/hotgo'; import { adaModalWidth } from '@/utils/hotgo';
const emit = defineEmits(['reloadTable', 'updateShowModal']); const emit = defineEmits(['reloadTable']);
interface Props {
showModal: boolean;
formParams?: State;
}
const props = withDefaults(defineProps<Props>(), {
showModal: false,
formParams: () => {
return newState(null);
},
});
const isShowModal = computed({
get: () => {
return props.showModal;
},
set: (value) => {
emit('updateShowModal', value);
},
});
const loading = ref(false);
const params = ref<State>(props.formParams);
const message = useMessage(); const message = useMessage();
const formRef = ref<any>({}); const settingStore = useProjectSettingStore();
const dialogWidth = ref('75%'); const dialogWidth = ref('75%');
const loading = ref(false);
const showModal = ref(false);
const formValue = ref<State>(newState(null));
const formRef = ref<any>({});
const formBtnLoading = ref(false); const formBtnLoading = ref(false);
function confirmForm(e) { function confirmForm(e) {
@ -118,10 +103,10 @@
formBtnLoading.value = true; formBtnLoading.value = true;
formRef.value.validate((errors) => { formRef.value.validate((errors) => {
if (!errors) { if (!errors) {
Edit(params.value).then((_res) => { Edit(formValue.value).then((_res) => {
message.success('操作成功'); message.success('操作成功');
setTimeout(() => { setTimeout(() => {
isShowModal.value = false; showModal.value = false;
emit('reloadTable'); emit('reloadTable');
}); });
}); });
@ -132,23 +117,22 @@
}); });
} }
onMounted(async () => {
adaModalWidth(dialogWidth);
});
function closeForm() { function closeForm() {
isShowModal.value = false; showModal.value = false;
loading.value = false;
} }
function loadForm(value) { function openModal(state: State) {
adaModalWidth(dialogWidth);
showModal.value = true;
loading.value = true; loading.value = true;
// //
if (value.id < 1) { if (!state || state.id < 1) {
params.value = newState(value); formValue.value = newState(state);
MaxSort() MaxSort()
.then((res) => { .then((res) => {
params.value.sort = res.sort; formValue.value.sort = res.sort;
}) })
.finally(() => { .finally(() => {
loading.value = false; loading.value = false;
@ -157,21 +141,18 @@
} }
// //
View({ id: value.id }) View({ id: state.id })
.then((res) => { .then((res) => {
params.value = res; formValue.value = res;
}) })
.finally(() => { .finally(() => {
loading.value = false; loading.value = false;
}); });
} }
watch( defineExpose({
() => props.formParams, openModal,
(value) => { });
loadForm(value);
}
);
</script> </script>
<style lang="less"></style> <style lang="less"></style>

View File

@ -76,12 +76,8 @@
</template> </template>
</BasicTable> </BasicTable>
</n-card> </n-card>
<Edit <Edit @reloadTable="reloadTable" ref="editRef" />
@reloadTable="reloadTable" <View ref="viewRef" />
@updateShowModal="updateShowModal"
:showModal="showModal"
:formParams="formParams"
/>
</div> </div>
</template> </template>
@ -92,21 +88,21 @@
import { BasicForm, useForm } from '@/components/Form/index'; import { BasicForm, useForm } from '@/components/Form/index';
import { usePermission } from '@/hooks/web/usePermission'; import { usePermission } from '@/hooks/web/usePermission';
import { List, Export, Delete, Status } from '@/api/curdDemo'; import { List, Export, Delete, Status } from '@/api/curdDemo';
import { State, columns, schemas, options, newState } from './model'; import { columns, schemas, options } from './model';
import { PlusOutlined, ExportOutlined, DeleteOutlined } from '@vicons/antd'; import { PlusOutlined, ExportOutlined, DeleteOutlined } from '@vicons/antd';
import { useRouter } from 'vue-router';
import { getOptionLabel } from '@/utils/hotgo'; import { getOptionLabel } from '@/utils/hotgo';
import Edit from './edit.vue'; import Edit from './edit.vue';
const { hasPermission } = usePermission(); import View from './view.vue';
const router = useRouter();
const actionRef = ref();
const dialog = useDialog(); const dialog = useDialog();
const message = useMessage(); const message = useMessage();
const { hasPermission } = usePermission();
const actionRef = ref();
const searchFormRef = ref<any>({}); const searchFormRef = ref<any>({});
const viewRef = ref();
const editRef = ref();
const batchDeleteDisabled = ref(true); const batchDeleteDisabled = ref(true);
const checkedIds = ref([]); const checkedIds = ref([]);
const showModal = ref(false);
const formParams = ref<State>();
const actionColumn = reactive({ const actionColumn = reactive({
width: 300, width: 300,
@ -170,15 +166,6 @@
return await List({ ...searchFormRef.value?.formModel, ...res }); return await List({ ...searchFormRef.value?.formModel, ...res });
}; };
function addTable() {
showModal.value = true;
formParams.value = newState(null);
}
function updateShowModal(value) {
showModal.value = value;
}
function onCheckedRow(rowKeys) { function onCheckedRow(rowKeys) {
batchDeleteDisabled.value = rowKeys.length <= 0; batchDeleteDisabled.value = rowKeys.length <= 0;
checkedIds.value = rowKeys; checkedIds.value = rowKeys;
@ -188,13 +175,16 @@
actionRef.value.reload(); actionRef.value.reload();
} }
function handleView(record: Recordable) { function addTable() {
router.push({ name: 'curdDemoView', params: { id: record.id } }); editRef.value.openModal(null);
} }
function handleEdit(record: Recordable) { function handleEdit(record: Recordable) {
showModal.value = true; editRef.value.openModal(record);
formParams.value = newState(record as State); }
function handleView(record: Recordable) {
viewRef.value.openModal(record);
} }
function handleDelete(record: Recordable) { function handleDelete(record: Recordable) {
@ -209,9 +199,6 @@
reloadTable(); reloadTable();
}); });
}, },
onNegativeClick: () => {
// message.error('');
},
}); });
} }
@ -229,9 +216,6 @@
reloadTable(); reloadTable();
}); });
}, },
onNegativeClick: () => {
// message.error('');
},
}); });
} }

View File

@ -8,59 +8,46 @@ import { isArray, isNullObject } from '@/utils/is';
import { getFileExt } from '@/utils/urlUtils'; import { getFileExt } from '@/utils/urlUtils';
import { defRangeShortcuts, defShortcuts, formatToDate } from '@/utils/dateUtil'; import { defRangeShortcuts, defShortcuts, formatToDate } from '@/utils/dateUtil';
import { validate } from '@/utils/validateUtil'; import { validate } from '@/utils/validateUtil';
import { getOptionLabel, getOptionTag, Options, errorImg } from '@/utils/hotgo'; import { getOptionLabel, getOptionTag, Option, Options, errorImg } from '@/utils/hotgo';
import { usePermission } from '@/hooks/web/usePermission'; import { usePermission } from '@/hooks/web/usePermission';
const { hasPermission } = usePermission(); const { hasPermission } = usePermission();
const $message = window['$message']; const $message = window['$message'];
export class State {
export interface State { public id = 0; // ID
id: number; public categoryId = 0; // 分类ID
categoryId: number; public title = ''; // 标题
title: string; public description = ''; // 描述
description: string; public content = ''; // 内容
content: string; public image = ''; // 单图
image: string; public attachfile = ''; // 附件
attachfile: string; public cityId = 0; // 所在城市
cityId: number; public switch = 1; // 显示开关
switch: number; public sort = 0; // 排序
sort: number; public status = 1; // 状态
status: number; public createdBy = 0; // 创建者
createdBy: number; public updatedBy = 0; // 更新者
updatedBy: number; public createdAt = ''; // 创建时间
createdAt: string; public updatedAt = ''; // 修改时间
updatedAt: string; public deletedAt = ''; // 删除时间
deletedAt: string;
} }
export const defaultState: State = { export function newState(state: State | Record<string, any> | null): State {
id: 0, if (state !== null) {
categoryId: 0, if (state instanceof State) {
title: '', return cloneDeep(state);
description: '', }
content: '', return new State(state);
image: '', }
attachfile: '', return new State();
cityId: 0, }
switch: 1,
sort: 0, export interface IOptions extends Options {
status: 1, sys_normal_disable: Option[];
createdBy: 0,
updatedBy: 0,
createdAt: '',
updatedAt: '',
deletedAt: '',
}; };
export function newState(state: State | null): State { export const options = ref<IOptions>({
if (state !== null) {
return cloneDeep(state);
}
return cloneDeep(defaultState);
}
export const options = ref<Options>({
sys_normal_disable: [], sys_normal_disable: [],
}); });

View File

@ -1,11 +1,14 @@
<template> <template>
<div> <div>
<div class="n-layout-page-header"> <n-spin :show="loading" description="请稍候...">
<n-card :bordered="false" title="生成演示详情"> <!-- CURD详情页--> </n-card> <n-drawer v-model:show="showModal" :width="dialogWidth">
</div> <n-drawer-content>
<n-card :bordered="false" class="proCard mt-4" size="small" :segmented="{ content: true }"> <template #header> 生成演示详情 </template>
<n-descriptions label-placement="left" class="py-2" column="4"> <template #footer>
<n-descriptions-item> <n-button @click="showModal = false"> 关闭 </n-button>
</template>
<n-descriptions label-placement="left" class="py-2" column="1">
<n-descriptions-item>
<template #label>分类ID</template> <template #label>分类ID</template>
{{ formValue.categoryId }} {{ formValue.categoryId }}
</n-descriptions-item> </n-descriptions-item>
@ -69,23 +72,25 @@
</n-descriptions-item> </n-descriptions-item>
</n-descriptions> </n-descriptions>
</n-card> </n-drawer-content>
</n-drawer>
</n-spin>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, onMounted, ref } from 'vue'; import { computed, ref } from 'vue';
import { useRouter } from 'vue-router';
import { useMessage } from 'naive-ui'; import { useMessage } from 'naive-ui';
import { View } from '@/api/curdDemo'; import { View } from '@/api/curdDemo';
import { newState, options } from './model'; import { State, newState, options } from './model';
import { getOptionLabel, getOptionTag } from '@/utils/hotgo'; import { adaModalWidth, getOptionLabel, getOptionTag } from '@/utils/hotgo';
import { getFileExt } from '@/utils/urlUtils'; import { getFileExt } from '@/utils/urlUtils';
const message = useMessage(); const message = useMessage();
const router = useRouter(); const dialogWidth = ref('75%');
const id = Number(router.currentRoute.value.params.id); const loading = ref(false);
const showModal = ref(false);
const formValue = ref(newState(null)); const formValue = ref(newState(null));
const fileAvatarCSS = computed(() => { const fileAvatarCSS = computed(() => {
return { return {
@ -99,12 +104,21 @@
window.open(url); window.open(url);
} }
onMounted(async () => { function openModal(state: State) {
if (id < 1) { adaModalWidth(dialogWidth, 580);
message.error('ID不正确请检查'); showModal.value = true;
return; loading.value = true;
} View({ id: state.id })
formValue.value = await View({ id: id }); .then((res) => {
formValue.value = res;
})
.finally(() => {
loading.value = false;
});
}
defineExpose({
openModal,
}); });
</script> </script>

View File

@ -234,7 +234,7 @@
<n-form ref="formRef" :model="formValue"> <n-form ref="formRef" :model="formValue">
<n-alert :show-icon="false">关联表数量建议在三个以下</n-alert> <n-alert :show-icon="false">关联表数量建议在三个以下</n-alert>
<div class="mt-4"></div>
<n-row :gutter="6" v-for="(join, index) in formValue.options.join" :key="index"> <n-row :gutter="6" v-for="(join, index) in formValue.options.join" :key="index">
<n-col :span="6" style="min-width: 200px"> <n-col :span="6" style="min-width: 200px">
<n-form-item label="关联表" path="join.linkTable"> <n-form-item label="关联表" path="join.linkTable">

View File

@ -69,6 +69,7 @@
<n-modal <n-modal
v-model:show="showModal" v-model:show="showModal"
:mask-closable="false"
:show-icon="false" :show-icon="false"
preset="dialog" preset="dialog"
:title="formParams?.id > 0 ? '编辑用户 #' + formParams?.id : '添加用户'" :title="formParams?.id > 0 ? '编辑用户 #' + formParams?.id : '添加用户'"

View File

@ -25,7 +25,13 @@
</n-space> </n-space>
</n-card> </n-card>
<n-modal v-model:show="showModal" :show-icon="false" preset="dialog" :title="editRoleTitle"> <n-modal
v-model:show="showModal"
:show-icon="false"
:mask-closable="false"
preset="dialog"
:title="editRoleTitle"
>
<div class="py-3 menu-list" :style="{ maxHeight: '90vh', height: '70vh' }"> <div class="py-3 menu-list" :style="{ maxHeight: '90vh', height: '70vh' }">
<n-tree <n-tree
block-line block-line
@ -164,10 +170,10 @@
DataScopeSelect, DataScopeSelect,
DataScopeEdit, DataScopeEdit,
} from '@/api/system/role'; } from '@/api/system/role';
import { getMenuList } from '@/api/system/menu'; import { EditMenu, getMenuList } from '@/api/system/menu';
import { columns } from './columns'; import { columns } from './columns';
import { PlusOutlined } from '@vicons/antd'; import { PlusOutlined } from '@vicons/antd';
import { getTreeAll } from '@/utils'; import { getAllExpandKeys, getTreeAll } from '@/utils';
import { statusOptions } from '@/enums/optionsiEnum'; import { statusOptions } from '@/enums/optionsiEnum';
import { cloneDeep } from 'lodash-es'; import { cloneDeep } from 'lodash-es';
import { getDeptList } from '@/api/org/dept'; import { getDeptList } from '@/api/org/dept';
@ -338,9 +344,6 @@
reloadTable(); reloadTable();
}); });
}, },
onNegativeClick: () => {
// message.error('');
},
}); });
} }
@ -394,7 +397,7 @@
if (expandedKeys.value.length) { if (expandedKeys.value.length) {
expandedKeys.value = []; expandedKeys.value = [];
} else { } else {
expandedKeys.value = treeData.value.map((item: any) => item.key) as []; expandedKeys.value = getAllExpandKeys(treeData) as [];
} }
} }
@ -409,45 +412,49 @@
} }
onMounted(async () => { onMounted(async () => {
await loadDataList(); loadDataList();
await loadMenuList(); loadMenuList();
await loadDeptList(); loadDeptList();
await loadDataScopeSelect(); loadDataScopeSelect();
await loadDataTable({}); await loadDataTable({});
}); });
async function loadDataList() { function loadDataList() {
const data = await getRoleList({ pageSize: 100, page: 1 }); getRoleList({ pageSize: 100, page: 1 }).then((res) => {
optionTreeData.value = [ optionTreeData.value = [
{ {
id: 0, id: 0,
key: 0, key: 0,
label: '顶级角色', label: '顶级角色',
pid: 0, pid: 0,
name: '顶级角色', name: '顶级角色',
}, },
]; ];
optionTreeData.value = optionTreeData.value.concat(data.list); optionTreeData.value = optionTreeData.value.concat(res.list);
});
} }
async function loadMenuList() { function loadMenuList() {
const treeMenuList = await getMenuList(); getMenuList().then((res) => {
expandedKeys.value = treeMenuList.list.map((item) => item.key); expandedKeys.value = getAllExpandKeys(res.list) as [];
treeData.value = treeMenuList.list; treeData.value = res.list;
});
} }
async function loadDeptList() { function loadDeptList() {
const tmp = await getDeptList({}); getDeptList({}).then((res) => {
if (tmp.list) { if (res.list) {
deptList.value = tmp.list; deptList.value = res.list;
} }
});
} }
async function loadDataScopeSelect() { function loadDataScopeSelect() {
const option = await DataScopeSelect(); DataScopeSelect().then((res) => {
if (option.list) { if (res.list) {
dataScopeOption.value = option.list; dataScopeOption.value = res.list;
} }
});
} }
function onUpdateValuePid(value: string | number) { function onUpdateValuePid(value: string | number) {

View File

@ -12,15 +12,23 @@
</n-form-item> </n-form-item>
<n-form-item label="提现最低手续费(元)" path="cashMinFee"> <n-form-item label="提现最低手续费(元)" path="cashMinFee">
<n-input placeholder="" v-model:value="formValue.cashMinFee" /> <n-input-number placeholder="" v-model:value="formValue.cashMinFee" style="width: 100%" />
</n-form-item> </n-form-item>
<n-form-item label="提现最低手续费比率" path="cashMinFeeRatio"> <n-form-item label="提现最低手续费比率" path="cashMinFeeRatio">
<n-input placeholder="" v-model:value="formValue.cashMinFeeRatio" /> <n-input-number
placeholder=""
v-model:value="formValue.cashMinFeeRatio"
style="width: 100%"
/>
</n-form-item> </n-form-item>
<n-form-item label="提现最低金额" path="cashMinMoney"> <n-form-item label="提现最低金额" path="cashMinMoney">
<n-input placeholder="" v-model:value="formValue.cashMinMoney" /> <n-input-number
placeholder=""
v-model:value="formValue.cashMinMoney"
style="width: 100%"
/>
</n-form-item> </n-form-item>
<n-form-item label="提现提示信息" path="cashTips"> <n-form-item label="提现提示信息" path="cashTips">
@ -50,8 +58,8 @@
const message = useMessage(); const message = useMessage();
const formValue = ref({ const formValue = ref({
cashSwitch: '', cashSwitch: '',
cashMinFee: '', cashMinFee: 0,
cashMinFeeRatio: '', cashMinFeeRatio: 0,
cashMinMoney: 0, cashMinMoney: 0,
cashTips: '', cashTips: '',
}); });

View File

@ -1,7 +1,13 @@
<template> <template>
<div> <div>
<n-spin :show="show" description="请稍候..."> <n-spin :show="show" description="请稍候...">
<n-form :label-width="100" :model="formValue" :rules="rules" ref="formRef"> <n-form
:label-width="150"
:model="formValue"
:rules="rules"
ref="formRef"
label-placement="left"
>
<n-form-item label="默认驱动" path="smsDrive"> <n-form-item label="默认驱动" path="smsDrive">
<n-select <n-select
placeholder="默认发送驱动" placeholder="默认发送驱动"
@ -35,105 +41,117 @@
</n-input-number> </n-input-number>
</n-form-item> </n-form-item>
<n-divider title-placement="left">阿里云</n-divider> <n-tabs type="card" size="small" v-model:value="tabName">
<n-form-item label="AccessKeyID" path="smsAliYunAccessKeyID"> <n-tab-pane name="aliyun">
<n-input v-model:value="formValue.smsAliYunAccessKeyID" placeholder="" /> <template #tab> 阿里云 </template>
<template #feedback <n-divider title-placement="left"> 阿里云</n-divider>
>应用key和密钥你可以通过 https://ram.console.aliyun.com/manage/ak </template <n-form-item label="AccessKeyID" path="smsAliYunAccessKeyID">
> <n-input v-model:value="formValue.smsAliYunAccessKeyID" placeholder="" />
</n-form-item> <template #feedback>
应用key和密钥你可以通过 https://ram.console.aliyun.com/manage/ak
</template>
</n-form-item>
<n-form-item label="AccessKeySecret" path="smsAliYunAccessKeySecret"> <n-form-item label="AccessKeySecret" path="smsAliYunAccessKeySecret">
<n-input <n-input
type="password" type="password"
v-model:value="formValue.smsAliYunAccessKeySecret" v-model:value="formValue.smsAliYunAccessKeySecret"
show-password-on="click" show-password-on="click"
> >
<template #password-visible-icon> <template #password-visible-icon>
<n-icon :size="16" :component="GlassesOutline" /> <n-icon :size="16" :component="GlassesOutline" />
</template> </template>
<template #password-invisible-icon> <template #password-invisible-icon>
<n-icon :size="16" :component="Glasses" /> <n-icon :size="16" :component="Glasses" />
</template> </template>
</n-input> </n-input>
</n-form-item> </n-form-item>
<n-form-item label="签名" path="smsAliYunSign"> <n-form-item label="签名" path="smsAliYunSign">
<n-input v-model:value="formValue.smsAliYunSign" placeholder="" /> <n-input v-model:value="formValue.smsAliYunSign" placeholder="" />
<template #feedback <template #feedback>
>申请地址https://dysms.console.aliyun.com/domestic/text/sign</template 申请地址https://dysms.console.aliyun.com/domestic/text/sign
> </template>
</n-form-item> </n-form-item>
<n-form-item label="短信模板" path="smsAliYunTemplate"> <n-form-item label="短信模板" path="smsAliYunTemplate">
<n-dynamic-input <n-dynamic-input
v-model:value="formValue.smsAliYunTemplate" v-model:value="formValue.smsAliYunTemplate"
preset="pair" preset="pair"
key-placeholder="事件KEY" key-placeholder="事件KEY"
value-placeholder="模板CODE" value-placeholder="模板CODE"
/> />
</n-form-item> </n-form-item>
</n-tab-pane>
<n-divider title-placement="left">腾讯云</n-divider> <n-tab-pane name="tencent">
<n-form-item label="SecretId" path="smsTencentSecretId"> <template #tab> 腾讯云 </template>
<n-input v-model:value="formValue.smsTencentSecretId" placeholder="" /> <n-divider title-placement="left"> 腾讯云</n-divider>
<template #feedback <n-form-item label="APPID" path="smsTencentSecretId">
>应用key和密钥你可以通过 https://ram.console.aliyun.com/manage/ak </template <n-input v-model:value="formValue.smsTencentSecretId" placeholder="" />
> <template #feedback>
</n-form-item> 子账号密钥获取地址https://cloud.tencent.com/document/product/598/37140
</template>
</n-form-item>
<n-form-item label="SecretKey" path="smsTencentSecretKey"> <n-form-item label="密钥" path="smsTencentSecretKey">
<n-input <n-input
type="password" type="password"
v-model:value="formValue.smsTencentSecretKey" v-model:value="formValue.smsTencentSecretKey"
show-password-on="click" show-password-on="click"
> >
<template #password-visible-icon> <template #password-visible-icon>
<n-icon :size="16" :component="GlassesOutline" /> <n-icon :size="16" :component="GlassesOutline" />
</template> </template>
<template #password-invisible-icon> <template #password-invisible-icon>
<n-icon :size="16" :component="Glasses" /> <n-icon :size="16" :component="Glasses" />
</template> </template>
</n-input> </n-input>
</n-form-item> </n-form-item>
<n-form-item label="接入地域域名" path="smsTencentEndpoint"> <n-form-item label="接入地域域名" path="smsTencentEndpoint">
<n-input v-model:value="formValue.smsTencentEndpoint" placeholder="" /> <n-input v-model:value="formValue.smsTencentEndpoint" placeholder="" />
<template #feedback <template #feedback>
>默认就近地域接入域名为 sms.tencentcloudapi.com 默认就近地域接入域名为 <n-text code>sms.tencentcloudapi.com</n-text>
也支持指定地域域名访问例如广州地域的域名为 也支持指定地域域名访问例如广州地域的域名为
sms.ap-guangzhou.tencentcloudapi.com</template <n-text code>sms.ap-guangzhou.tencentcloudapi.com</n-text>
> </template>
</n-form-item> </n-form-item>
<n-form-item label="地域信息" path="smsTencentRegion"> <n-form-item label="地域信息" path="smsTencentRegion">
<n-input v-model:value="formValue.smsTencentRegion" placeholder="" /> <n-input v-model:value="formValue.smsTencentRegion" placeholder="" />
<template #feedback <template #feedback>
>支持的地域列表参考 支持的地域列表参考
https://cloud.tencent.com/document/api/382/52071#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8</template https://cloud.tencent.com/document/api/382/52071#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8
> </template>
</n-form-item> </n-form-item>
<n-form-item label="短信应用ID" path="smsTencentAppId"> <n-form-item label="短信应用ID" path="smsTencentAppId">
<n-input v-model:value="formValue.smsTencentAppId" placeholder="" /> <n-input v-model:value="formValue.smsTencentAppId" placeholder="" />
<template #feedback <template #feedback>
>查看地址https://console.cloud.tencent.com/smsv2/app-manage</template 查看地址https://console.cloud.tencent.com/smsv2/app-manage
> </template>
</n-form-item> </n-form-item>
<n-form-item label="签名" path="smsTencentSign"> <n-form-item label="签名" path="smsTencentSign">
<n-input v-model:value="formValue.smsTencentSign" placeholder="" /> <n-input v-model:value="formValue.smsTencentSign" placeholder="" />
<template #feedback>查看地址https://console.cloud.tencent.com/smsv2/csms-sign</template> <template #feedback>
</n-form-item> 查看地址https://console.cloud.tencent.com/smsv2/csms-sign
</template>
</n-form-item>
<n-form-item label="短信模板" path="smsTencentTemplate"> <n-form-item label="短信模板" path="smsTencentTemplate">
<n-dynamic-input <n-dynamic-input
v-model:value="formValue.smsTencentTemplate" v-model:value="formValue.smsTencentTemplate"
preset="pair" preset="pair"
key-placeholder="事件KEY" key-placeholder="事件KEY"
value-placeholder="模板ID" value-placeholder="模板ID"
/> />
</n-form-item> </n-form-item>
</n-tab-pane>
<!-- tencent -->
</n-tabs>
<div> <div>
<n-space> <n-space>
@ -184,7 +202,7 @@
<template #action> <template #action>
<n-space> <n-space>
<n-button @click="() => (showModal = false)">关闭</n-button> <n-button @click="() => (showModal = false)">关闭</n-button>
<n-button type="info" :loading="formBtnLoading" @click="confirmForm">发送</n-button> <n-button type="info" :loading="formBtnLoading" @click="confirmForm"> 发送 </n-button>
</n-space> </n-space>
</template> </template>
</n-modal> </n-modal>
@ -192,7 +210,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onMounted } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useMessage } from 'naive-ui'; import { useMessage } from 'naive-ui';
import { getConfig, sendTestSms, updateConfig } from '@/api/sys/config'; import { getConfig, sendTestSms, updateConfig } from '@/api/sys/config';
import { Dicts } from '@/api/dict/dict'; import { Dicts } from '@/api/dict/dict';
@ -222,8 +240,13 @@
config_sms_drive: [], config_sms_drive: [],
}); });
/** 默认选项卡 */
const defaultTabName = 'aliyun';
/** 选项卡名称 */
const tabName = ref<string>(defaultTabName);
const formValue = ref({ const formValue = ref({
smsDrive: 'aliyun', smsDrive: defaultTabName,
smsMinInterval: 60, smsMinInterval: 60,
smsMaxIpLimit: 10, smsMaxIpLimit: 10,
smsCodeExpire: 600, smsCodeExpire: 600,
@ -240,6 +263,14 @@
smsTencentTemplate: null, smsTencentTemplate: null,
}); });
/** 监听类型变化,同步到选项卡中 */
watch(
() => formValue.value.smsDrive,
(smsDrive: string) => {
tabName.value = smsDrive;
}
);
function sendTest() { function sendTest() {
showModal.value = true; showModal.value = true;
formBtnLoading.value = false; formBtnLoading.value = false;

View File

@ -1,7 +1,13 @@
<template> <template>
<div> <div>
<n-spin :show="show" description="请稍候..."> <n-spin :show="show" description="请稍候...">
<n-form :label-width="100" :model="formValue" :rules="rules" ref="formRef"> <n-form
:label-width="150"
:model="formValue"
:rules="rules"
ref="formRef"
label-placement="left"
>
<n-form-item label="默认驱动" path="uploadDrive"> <n-form-item label="默认驱动" path="uploadDrive">
<n-select <n-select
placeholder="默认驱动" placeholder="默认驱动"
@ -36,262 +42,258 @@
<n-form-item label="文件类型限制" path="uploadFileType"> <n-form-item label="文件类型限制" path="uploadFileType">
<n-input v-model:value="formValue.uploadFileType" placeholder="" /> <n-input v-model:value="formValue.uploadFileType" placeholder="" />
</n-form-item> </n-form-item>
<n-tabs type="card" size="small" v-model:value="tabName">
<n-tab-pane name="local">
<template #tab> 本地存储</template>
<n-divider title-placement="left">本地存储</n-divider>
<n-form-item label="本地存储路径" path="uploadLocalPath">
<n-input v-model:value="formValue.uploadLocalPath" placeholder="" />
<template #feedback>填对外访问的相对路径</template>
</n-form-item>
</n-tab-pane>
<template v-if="formValue.uploadDrive == 'local'"> <n-tab-pane name="oss">
<n-divider title-placement="left">本地存储</n-divider> <template #tab> 阿里云OSS存储</template>
<n-form-item label="本地存储路径" path="uploadLocalPath"> <n-divider title-placement="left">阿里云OSS存储</n-divider>
<n-input v-model:value="formValue.uploadLocalPath" placeholder="" /> <n-form-item label="AccessKey ID" path="uploadOssSecretId">
<template #feedback>填对外访问的相对路径</template> <n-input
</n-form-item> type="password"
</template> v-model:value="formValue.uploadOssSecretId"
show-password-on="click"
>
<template #password-visible-icon>
<n-icon :size="16" :component="GlassesOutline" />
</template>
<template #password-invisible-icon>
<n-icon :size="16" :component="Glasses" />
</template>
</n-input>
<template #feedback> 创建地址https://ram.console.aliyun.com/manage/ak </template>
</n-form-item>
<template v-if="formValue.uploadDrive == 'ucloud'"> <n-form-item label="AccessKey Secret" path="uploadOssSecretKey">
<n-divider title-placement="left">ucloud对象存储</n-divider> <n-input
<n-form-item label="公钥" path="uploadUCloudPublicKey"> type="password"
<n-input v-model:value="formValue.uploadOssSecretKey"
type="password" show-password-on="click"
v-model:value="formValue.uploadUCloudPublicKey" >
show-password-on="click" <template #password-visible-icon>
> <n-icon :size="16" :component="GlassesOutline" />
<template #password-visible-icon> </template>
<n-icon :size="16" :component="GlassesOutline" /> <template #password-invisible-icon>
</template> <n-icon :size="16" :component="Glasses" />
<template #password-invisible-icon> </template>
<n-icon :size="16" :component="Glasses" /> </n-input>
</template> </n-form-item>
</n-input> <n-form-item label="Endpoint" path="uploadOssEndpoint">
<template #feedback>获取地址https://console.ucloud.cn/ufile/token</template> <n-input v-model:value="formValue.uploadOssEndpoint" placeholder="" />
</n-form-item> <template #feedback> Endpoint地域节点</template>
</n-form-item>
<n-form-item label="存储路径" path="uploadOssPath">
<n-input v-model:value="formValue.uploadOssPath" placeholder="" />
<template #feedback>填对对象存储中的相对路径</template>
</n-form-item>
<n-form-item label="存储空间名称" path="uploadOssBucket">
<n-input v-model:value="formValue.uploadOssBucket" placeholder="" />
</n-form-item>
<n-form-item label="Bucket 域名" path="uploadOssBucketURL">
<n-input v-model:value="formValue.uploadOssBucketURL" placeholder="" />
</n-form-item>
</n-tab-pane>
<n-form-item label="私钥" path="uploadUCloudPrivateKey"> <n-tab-pane name="cos">
<n-input <template #tab> 腾讯云COS存储</template>
type="password" <n-divider title-placement="left">腾讯云COS存储</n-divider>
v-model:value="formValue.uploadUCloudPrivateKey" <n-form-item label="APPID" path="uploadCosSecretId">
show-password-on="click" <n-input v-model:value="formValue.uploadCosSecretId" />
> <template #feedback>
<template #password-visible-icon> 子账号密钥获取地址https://cloud.tencent.com/document/product/598/37140
<n-icon :size="16" :component="GlassesOutline" />
</template> </template>
<template #password-invisible-icon> </n-form-item>
<n-icon :size="16" :component="Glasses" />
</template>
</n-input>
</n-form-item>
<n-form-item label="存储路径" path="uploadUCloudPath">
<n-input v-model:value="formValue.uploadUCloudPath" placeholder="" />
<template #feedback>填对对象存储中的相对路径</template>
</n-form-item>
<n-form-item label="地域API" path="uploadUCloudBucketHost">
<n-input v-model:value="formValue.uploadUCloudBucketHost" placeholder="" />
</n-form-item>
<n-form-item label="存储桶名称" path="uploadUCloudBucketName">
<n-input v-model:value="formValue.uploadUCloudBucketName" placeholder="" />
<template #feedback>存储空间名称</template>
</n-form-item>
<n-form-item label="存储桶地域host" path="uploadUCloudFileHost">
<n-input v-model:value="formValue.uploadUCloudFileHost" placeholder="" />
<template #feedback>不需要包含桶名称</template>
</n-form-item>
<n-form-item label="访问域名" path="uploadUCloudEndpoint">
<n-input v-model:value="formValue.uploadUCloudEndpoint" placeholder="" />
<template #feedback>格式http://abc.com https://abc.com</template>
</n-form-item>
</template>
<template v-if="formValue.uploadDrive == 'cos'"> <n-form-item label="密钥" path="uploadCosSecretKey">
<n-divider title-placement="left">腾讯云COS存储</n-divider> <n-input
<n-form-item label="secretId" path="uploadCosSecretId"> type="password"
<n-input v-model:value="formValue.uploadCosSecretKey"
type="password" show-password-on="click"
v-model:value="formValue.uploadCosSecretId" >
show-password-on="click" <template #password-visible-icon>
> <n-icon :size="16" :component="GlassesOutline" />
<template #password-visible-icon> </template>
<n-icon :size="16" :component="GlassesOutline" /> <template #password-invisible-icon>
</template> <n-icon :size="16" :component="Glasses" />
<template #password-invisible-icon> </template>
<n-icon :size="16" :component="Glasses" /> </n-input>
</template> </n-form-item>
</n-input> <n-form-item label="存储路径" path="uploadCosPath">
<template #feedback <n-input v-model:value="formValue.uploadCosPath" placeholder="" />
>子账号密钥获取地址https://cloud.tencent.com/document/product/598/37140 <template #feedback>填对对象存储中的相对路径</template>
</template> </n-form-item>
</n-form-item> <n-form-item label="访问域名" path="uploadCosBucketURL">
<n-input v-model:value="formValue.uploadCosBucketURL" placeholder="" />
<template #feedback
>控制台查看地址https://console.cloud.tencent.com/cos5/bucket</template
>
</n-form-item>
</n-tab-pane>
<n-form-item label="secretKey" path="uploadCosSecretKey"> <n-tab-pane name="qiniu">
<n-input <template #tab> 七牛云对象存储</template>
type="password" <n-divider title-placement="left">七牛云对象存储</n-divider>
v-model:value="formValue.uploadCosSecretKey" <n-form-item label="AccessKey" path="uploadQiNiuAccessKey">
show-password-on="click" <n-input
> type="password"
<template #password-visible-icon> v-model:value="formValue.uploadQiNiuAccessKey"
<n-icon :size="16" :component="GlassesOutline" /> show-password-on="click"
</template> >
<template #password-invisible-icon> <template #password-visible-icon>
<n-icon :size="16" :component="Glasses" /> <n-icon :size="16" :component="GlassesOutline" />
</template> </template>
</n-input> <template #password-invisible-icon>
</n-form-item> <n-icon :size="16" :component="Glasses" />
<n-form-item label="存储路径" path="uploadCosBucketURL"> </template>
<n-input v-model:value="formValue.uploadCosBucketURL" placeholder="" /> </n-input>
<template #feedback>填对对象存储中的相对路径</template> <template #feedback>创建地址https://portal.qiniu.com/user/key</template>
</n-form-item> </n-form-item>
<n-form-item label="地域API" path="uploadCosPath">
<n-input v-model:value="formValue.uploadCosPath" placeholder="" />
<template #feedback
>控制台查看地址https://console.cloud.tencent.com/cos5/bucket
</template>
</n-form-item>
</template>
<template v-if="formValue.uploadDrive == 'oss'"> <n-form-item label="SecretKey" path="uploadQiNiuSecretKey">
<n-divider title-placement="left">阿里云OSS存储</n-divider> <n-input
<n-form-item label="AccessKey ID" path="uploadOssSecretId"> type="password"
<n-input v-model:value="formValue.uploadQiNiuSecretKey"
type="password" show-password-on="click"
v-model:value="formValue.uploadOssSecretId" >
show-password-on="click" <template #password-visible-icon>
> <n-icon :size="16" :component="GlassesOutline" />
<template #password-visible-icon> </template>
<n-icon :size="16" :component="GlassesOutline" /> <template #password-invisible-icon>
</template> <n-icon :size="16" :component="Glasses" />
<template #password-invisible-icon> </template>
<n-icon :size="16" :component="Glasses" /> </n-input>
</template> </n-form-item>
</n-input> <n-form-item label="储存路径" path="uploadQiNiuPath">
<template #feedback>创建地址https://ram.console.aliyun.com/manage/ak</template> <n-input v-model:value="formValue.uploadQiNiuPath" placeholder="" />
</n-form-item> <template #feedback>填对对象存储中的相对路径</template>
</n-form-item>
<n-form-item label="存储空间名称" path="uploadQiNiuBucket">
<n-input v-model:value="formValue.uploadQiNiuBucket" placeholder="" />
</n-form-item>
<n-form-item label="访问域名" path="uploadQiNiuDomain">
<n-input v-model:value="formValue.uploadQiNiuDomain" placeholder="" />
</n-form-item>
</n-tab-pane>
<n-form-item label="AccessKey Secret" path="uploadOssSecretKey"> <n-tab-pane name="ucloud">
<n-input <template #tab> ucloud对象存储</template>
type="password" <n-divider title-placement="left">ucloud对象存储</n-divider>
v-model:value="formValue.uploadOssSecretKey" <n-form-item label="公钥" path="uploadUCloudPublicKey">
show-password-on="click" <n-input
> type="password"
<template #password-visible-icon> v-model:value="formValue.uploadUCloudPublicKey"
<n-icon :size="16" :component="GlassesOutline" /> show-password-on="click"
</template> >
<template #password-invisible-icon> <template #password-visible-icon>
<n-icon :size="16" :component="Glasses" /> <n-icon :size="16" :component="GlassesOutline" />
</template> </template>
</n-input> <template #password-invisible-icon>
</n-form-item> <n-icon :size="16" :component="Glasses" />
<n-form-item label="Endpoint" path="uploadOssEndpoint"> </template>
<n-input v-model:value="formValue.uploadOssEndpoint" placeholder="" /> </n-input>
<template #feedback> Endpoint地域节点</template> <template #feedback> 获取地址https://console.ucloud.cn/ufile/token </template>
</n-form-item> </n-form-item>
<n-form-item label="存储路径" path="uploadOssPath">
<n-input v-model:value="formValue.uploadOssPath" placeholder="" />
<template #feedback>填对对象存储中的相对路径</template>
</n-form-item>
<n-form-item label="存储空间名称" path="uploadOssBucket">
<n-input v-model:value="formValue.uploadOssBucket" placeholder="" />
</n-form-item>
<n-form-item label="Bucket 域名" path="uploadOssBucketURL">
<n-input v-model:value="formValue.uploadOssBucketURL" placeholder="" />
</n-form-item>
</template>
<template v-if="formValue.uploadDrive == 'qiniu'"> <n-form-item label="私钥" path="uploadUCloudPrivateKey">
<n-divider title-placement="left">七牛云对象存储</n-divider> <n-input
<n-form-item label="AccessKey" path="uploadQiNiuAccessKey"> type="password"
<n-input v-model:value="formValue.uploadUCloudPrivateKey"
type="password" show-password-on="click"
v-model:value="formValue.uploadQiNiuAccessKey" >
show-password-on="click" <template #password-visible-icon>
> <n-icon :size="16" :component="GlassesOutline" />
<template #password-visible-icon> </template>
<n-icon :size="16" :component="GlassesOutline" /> <template #password-invisible-icon>
</template> <n-icon :size="16" :component="Glasses" />
<template #password-invisible-icon> </template>
<n-icon :size="16" :component="Glasses" /> </n-input>
</template> </n-form-item>
</n-input> <n-form-item label="存储路径" path="uploadUCloudPath">
<template #feedback>创建地址https://portal.qiniu.com/user/key</template> <n-input v-model:value="formValue.uploadUCloudPath" placeholder="" />
</n-form-item> <template #feedback>填对对象存储中的相对路径</template>
</n-form-item>
<n-form-item label="地域API" path="uploadUCloudBucketHost">
<n-input v-model:value="formValue.uploadUCloudBucketHost" placeholder="" />
</n-form-item>
<n-form-item label="存储桶名称" path="uploadUCloudBucketName">
<n-input v-model:value="formValue.uploadUCloudBucketName" placeholder="" />
<template #feedback>存储空间名称</template>
</n-form-item>
<n-form-item label="存储桶地域host" path="uploadUCloudFileHost">
<n-input v-model:value="formValue.uploadUCloudFileHost" placeholder="" />
<template #feedback>不需要包含桶名称</template>
</n-form-item>
<n-form-item label="访问域名" path="uploadUCloudEndpoint">
<n-input v-model:value="formValue.uploadUCloudEndpoint" placeholder="" />
<template #feedback> 格式http://abc.com https://abc.com </template>
</n-form-item>
</n-tab-pane>
<n-form-item label="SecretKey" path="uploadQiNiuSecretKey"> <n-tab-pane name="minio">
<n-input <template #tab> minio对象存储</template>
type="password" <n-divider title-placement="left">minio对象存储</n-divider>
v-model:value="formValue.uploadQiNiuSecretKey" <n-form-item label="AccessKey ID" path="uploadMinioAccessKey">
show-password-on="click" <n-input
> type="password"
<template #password-visible-icon> v-model:value="formValue.uploadMinioAccessKey"
<n-icon :size="16" :component="GlassesOutline" /> show-password-on="click"
</template> >
<template #password-invisible-icon> <template #password-visible-icon>
<n-icon :size="16" :component="Glasses" /> <n-icon :size="16" :component="GlassesOutline" />
</template> </template>
</n-input> <template #password-invisible-icon>
</n-form-item> <n-icon :size="16" :component="Glasses" />
<n-form-item label="储存路径" path="uploadQiNiuPath"> </template>
<n-input v-model:value="formValue.uploadQiNiuPath" placeholder="" /> </n-input>
<template #feedback>填对对象存储中的相对路径</template> <template #feedback>相关文档https://min.io/</template>
</n-form-item> </n-form-item>
<n-form-item label="存储空间名称" path="uploadQiNiuBucket">
<n-input v-model:value="formValue.uploadQiNiuBucket" placeholder="" />
</n-form-item>
<n-form-item label="访问域名" path="uploadQiNiuDomain">
<n-input v-model:value="formValue.uploadQiNiuDomain" placeholder="" />
</n-form-item>
</template>
<template v-if="formValue.uploadDrive == 'minio'"> <n-form-item label="AccessKey Secret" path="uploadMinioSecretKey">
<n-divider title-placement="left">minio配置</n-divider> <n-input
<n-form-item label="AccessKey ID" path="uploadMinioAccessKey"> type="password"
<n-input v-model:value="formValue.uploadMinioSecretKey"
type="password" show-password-on="click"
v-model:value="formValue.uploadMinioAccessKey" >
show-password-on="click" <template #password-visible-icon>
> <n-icon :size="16" :component="GlassesOutline" />
<template #password-visible-icon> </template>
<n-icon :size="16" :component="GlassesOutline" /> <template #password-invisible-icon>
</template> <n-icon :size="16" :component="Glasses" />
<template #password-invisible-icon> </template>
<n-icon :size="16" :component="Glasses" /> </n-input>
</template> </n-form-item>
</n-input> <n-form-item label="Endpoint" path="uploadMinioEndpoint">
<template #feedback>相关文档https://min.io/</template> <n-input v-model:value="formValue.uploadMinioEndpoint" placeholder="" />
</n-form-item> <template #feedback> Endpoint不带http://</template>
</n-form-item>
<n-form-item label="AccessKey Secret" path="uploadMinioSecretKey"> <n-form-item path="uploadMinioUseSSL" label="SSL">
<n-input <n-switch
type="password" v-model:value="formValue.uploadMinioUseSSL"
v-model:value="formValue.uploadMinioSecretKey" :checked-value="1"
show-password-on="click" :unchecked-value="2"
> >
<template #password-visible-icon> <template #checked> 已启用</template>
<n-icon :size="16" :component="GlassesOutline" /> <template #unchecked> 已禁用</template>
</template> </n-switch>
<template #password-invisible-icon> </n-form-item>
<n-icon :size="16" :component="Glasses" /> <n-form-item label="储存路径" path="uploadMinioPath">
</template> <n-input v-model:value="formValue.uploadMinioPath" placeholder="" />
</n-input> </n-form-item>
</n-form-item> <n-form-item label="存储桶名称" path="uploadMinioBucket">
<n-form-item label="Endpoint" path="uploadMinioEndpoint"> <n-input v-model:value="formValue.uploadMinioBucket" placeholder="" />
<n-input v-model:value="formValue.uploadMinioEndpoint" placeholder="" /> </n-form-item>
<template #feedback> Endpoint不带http://</template> <n-form-item label="访问域名" path="uploadMinioDomain">
</n-form-item> <n-input v-model:value="formValue.uploadMinioDomain" placeholder="" />
<n-form-item path="uploadMinioUseSSL"> </n-form-item>
<n-switch </n-tab-pane>
v-model:value="formValue.uploadMinioUseSSL" </n-tabs>
:checked-value="1"
:unchecked-value="2"
>
<template #checked> 启用SSL</template>
<template #unchecked> 禁用SSL</template>
</n-switch>
</n-form-item>
<n-form-item label="储存路径" path="uploadMinioPath">
<n-input v-model:value="formValue.uploadMinioPath" placeholder="" />
</n-form-item>
<n-form-item label="存储桶名称" path="uploadMinioBucket">
<n-input v-model:value="formValue.uploadMinioBucket" placeholder="" />
</n-form-item>
<n-form-item label="对外访问域名" path="uploadMinioDomain">
<n-input v-model:value="formValue.uploadMinioDomain" placeholder="" />
</n-form-item>
</template>
<div> <div>
<n-space> <n-space>
<n-button type="primary" @click="formSubmit">保存更新</n-button> <n-button type="primary" @click="formSubmit">保存更新</n-button>
@ -303,7 +305,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, ref } from 'vue'; import { onMounted, ref, watch } from 'vue';
import { useMessage } from 'naive-ui'; import { useMessage } from 'naive-ui';
import { getConfig, updateConfig } from '@/api/sys/config'; import { getConfig, updateConfig } from '@/api/sys/config';
import { Glasses, GlassesOutline } from '@vicons/ionicons5'; import { Glasses, GlassesOutline } from '@vicons/ionicons5';
@ -327,8 +329,13 @@
config_upload_drive: [], config_upload_drive: [],
}); });
/** 默认选项卡 */
const defaultTabName = 'local';
/** 选项卡名称 */
const tabName = ref<string>(defaultTabName);
const formValue = ref({ const formValue = ref({
uploadDrive: 'local', uploadDrive: defaultTabName,
uploadImageSize: 2, uploadImageSize: 2,
uploadImageType: '', uploadImageType: '',
uploadFileSize: 10, uploadFileSize: 10,
@ -365,6 +372,14 @@
uploadMinioDomain: '', uploadMinioDomain: '',
}); });
/** 监听类型变化,同步到选项卡中 */
watch(
() => formValue.value.uploadDrive,
(uploadDrive: string) => {
tabName.value = uploadDrive;
}
);
function formSubmit() { function formSubmit() {
formRef.value.validate((errors) => { formRef.value.validate((errors) => {
if (!errors) { if (!errors) {

View File

@ -34,18 +34,41 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, reactive, toRefs } from 'vue'; import { defineAsyncComponent, defineComponent, reactive, toRefs } from 'vue';
import BasicSetting from './BasicSetting.vue'; /** 异步加载的组件,用到的时候再加载组件 */
import RevealSetting from './RevealSetting.vue'; const BasicSetting = defineAsyncComponent(() => {
import EmailSetting from './EmailSetting.vue'; return import('./BasicSetting.vue');
import ThemeSetting from './ThemeSetting.vue'; }),
import CashSetting from './CashSetting.vue'; RevealSetting = defineAsyncComponent(() => {
import UploadSetting from './UploadSetting.vue'; return import('./RevealSetting.vue');
import GeoSetting from './GeoSetting.vue'; }),
import SmsSetting from './SmsSetting.vue'; EmailSetting = defineAsyncComponent(() => {
import PaySetting from './PaySetting.vue'; return import('./EmailSetting.vue');
import WechatSetting from './WechatSetting.vue'; }),
import LoginSetting from './LoginSetting.vue'; ThemeSetting = defineAsyncComponent(() => {
return import('./ThemeSetting.vue');
}),
CashSetting = defineAsyncComponent(() => {
return import('./CashSetting.vue');
}),
UploadSetting = defineAsyncComponent(() => {
return import('./UploadSetting.vue');
}),
GeoSetting = defineAsyncComponent(() => {
return import('./GeoSetting.vue');
}),
SmsSetting = defineAsyncComponent(() => {
return import('./SmsSetting.vue');
}),
PaySetting = defineAsyncComponent(() => {
return import('./PaySetting.vue');
}),
WechatSetting = defineAsyncComponent(() => {
return import('./WechatSetting.vue');
}),
LoginSetting = defineAsyncComponent(() => {
return import('./LoginSetting.vue');
});
const typeTabList = [ const typeTabList = [
{ {
name: '基本设置', name: '基本设置',

View File

@ -106,7 +106,8 @@
import { statusOptions } from '@/enums/optionsiEnum'; import { statusOptions } from '@/enums/optionsiEnum';
import { TypeSelect } from '@/api/sys/config'; import { TypeSelect } from '@/api/sys/config';
import { Option } from '@/utils/hotgo'; import { Option } from '@/utils/hotgo';
import {cloneDeep} from "lodash-es"; import { findTreeDataById } from '@/utils';
import { cloneDeep } from 'lodash-es';
const options = ref<Option>(); const options = ref<Option>();
interface Props { interface Props {
checkedId?: number; checkedId?: number;
@ -320,11 +321,14 @@
} }
} }
function handleUpdateTypeIdValue( function handleUpdateTypeIdValue(value) {
value: string | number | Array<string | number> | null, const row = findTreeDataById(typeList.value, value);
_option: TreeSelectOption | null | Array<TreeSelectOption | null> if (!row) {
) { message.error('未找到该节点数据');
return;
}
formParams.value.typeId = value; formParams.value.typeId = value;
formParams.value.type = row.type;
} }
async function loadOptions() { async function loadOptions() {

View File

@ -22,8 +22,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
const root = process.cwd(); const root = process.cwd();
const env = loadEnv(mode, root); const env = loadEnv(mode, root);
const viteEnv = wrapperEnv(env); const viteEnv = wrapperEnv(env);
const { VITE_PUBLIC_PATH, VITE_DROP_CONSOLE, VITE_PORT, VITE_PROXY } = const { VITE_PUBLIC_PATH, VITE_DROP_CONSOLE, VITE_PORT, VITE_PROXY } = viteEnv;
viteEnv;
const isBuild = command === 'build'; const isBuild = command === 'build';
return { return {
base: VITE_PUBLIC_PATH, base: VITE_PUBLIC_PATH,
@ -44,6 +43,9 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
plugins: createVitePlugins(viteEnv, isBuild), plugins: createVitePlugins(viteEnv, isBuild),
define: { define: {
__APP_INFO__: JSON.stringify(__APP_INFO__), __APP_INFO__: JSON.stringify(__APP_INFO__),
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: false,
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: true,
}, },
css: { css: {
preprocessorOptions: { preprocessorOptions: {