From 62af998991ad69579f61c0332be473c67c55ff88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=9F=E5=B8=85?= <133814250@qq.com> Date: Sat, 22 Mar 2025 20:23:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=91=E5=B8=83v2.16.10=E7=89=88=E6=9C=AC?= =?UTF-8?q?=EF=BC=8C=E6=9B=B4=E6=96=B0=E5=86=85=E5=AE=B9=E8=AF=B7=E6=9F=A5?= =?UTF-8?q?=E7=9C=8B=EF=BC=9Ahttps://github.com/bufanyun/hotgo/blob/v2.0/d?= =?UTF-8?q?ocs/guide-zh-CN/start-update-log.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +- docs/guide-zh-CN/start-environment.md | 2 +- docs/guide-zh-CN/start-installation.md | 2 +- docs/guide-zh-CN/start-update-log.md | 14 + server/go.mod | 21 +- server/go.sum | 52 +- server/internal/consts/version.go | 2 +- server/internal/library/hggen/hggen.go | 2 +- .../library/hggen/internal/cmd/cmd.go | 6 +- .../library/hggen/internal/cmd/cmd_doc.go | 1 + .../library/hggen/internal/cmd/cmd_fix.go | 6 +- .../library/hggen/internal/cmd/cmd_gen_dao.go | 4 +- .../library/hggen/internal/cmd/cmd_init.go | 1 + .../library/hggen/internal/cmd/cmd_up.go | 1 + .../hggen/internal/cmd/cmd_z_init_test.go | 38 - .../internal/cmd/cmd_z_unit_build_test.go | 151 ---- .../hggen/internal/cmd/cmd_z_unit_fix_test.go | 24 - .../internal/cmd/cmd_z_unit_gen_ctrl_test.go | 309 ------- .../internal/cmd/cmd_z_unit_gen_dao_test.go | 841 ------------------ .../internal/cmd/cmd_z_unit_gen_pb_test.go | 50 -- .../cmd/cmd_z_unit_gen_pbentity_test.go | 210 ----- .../cmd/cmd_z_unit_gen_service_test.go | 155 ---- .../internal/cmd/genctrl/genctrl_api_item.go | 16 +- .../internal/cmd/genctrl/genctrl_ast_parse.go | 27 +- .../internal/cmd/genctrl/genctrl_calculate.go | 6 +- .../cmd/genctrl/genctrl_generate_ctrl.go | 30 +- .../genctrl/genctrl_generate_ctrl_clear.go | 1 + .../cmd/genctrl/genctrl_generate_interface.go | 1 + .../cmd/genctrl/genctrl_generate_sdk.go | 2 + .../hggen/internal/cmd/gendao/gendao.go | 291 ++---- .../hggen/internal/cmd/gendao/gendao_dao.go | 83 +- .../hggen/internal/cmd/gendao/gendao_do.go | 29 +- .../internal/cmd/gendao/gendao_entity.go | 29 +- .../internal/cmd/gendao/gendao_gen_item.go | 4 +- .../hggen/internal/cmd/gendao/gendao_tag.go | 149 ++++ .../hggen/internal/cmd/genenums/genenums.go | 10 +- .../internal/cmd/genenums/genenums_parser.go | 1 + .../library/hggen/internal/cmd/genpb/genpb.go | 1 + .../internal/cmd/genpb/genpb_controller.go | 1 + .../hggen/internal/cmd/genpb/genpb_tag.go | 5 + .../internal/cmd/genpbentity/genpbentity.go | 245 +++-- .../internal/cmd/genservice/genservice.go | 63 +- .../cmd/genservice/genservice_ast_parse.go | 102 ++- .../cmd/genservice/genservice_calculate.go | 76 ++ .../cmd/genservice/genservice_generate.go | 1 + .../genservice_generate_template.go | 1 + .../consts/consts_gen_ctrl_template.go | 4 +- .../consts/consts_gen_ctrl_template_sdk.go | 2 +- .../consts/consts_gen_dao_template_dao.go | 115 ++- .../consts/consts_gen_dao_template_do.go | 10 +- .../consts/consts_gen_dao_template_entity.go | 10 +- .../library/hggen/internal/service/install.go | 8 +- .../utility/utils/utils_http_download.go | 62 +- .../internal/utility/utils/utils_test.go | 1 + server/internal/library/hggen/views/curd.go | 4 +- server/internal/library/hgorm/hook/member.go | 2 +- server/internal/library/storager/mime.go | 16 +- server/internal/library/storager/upload.go | 16 +- server/internal/logic/admin/cash.go | 29 +- server/internal/logic/admin/credits_log.go | 18 +- server/internal/logic/admin/member.go | 48 + server/internal/logic/admin/order.go | 16 + server/internal/logic/sys/log.go | 12 + server/internal/model/input/adminin/cash.go | 9 +- .../model/input/adminin/credits_log.go | 51 +- server/internal/model/input/adminin/order.go | 7 +- server/internal/model/input/sysin/log.go | 21 +- server/internal/service/admin.go | 4 + .../generate/default/curd/logic.go.template | 7 +- server/storage/data/hotgo.sql | 6 +- server/storage/data/sqlite/data.sql | 2 +- web/package.json | 4 +- .../components/ComplexMemberPicker/index.vue | 144 +++ .../components/ComplexMemberPicker/props.ts | 13 + web/src/components/Form/src/BasicForm.vue | 17 +- web/src/components/Form/src/types/index.ts | 3 +- web/src/router/base.ts | 2 +- web/src/utils/index.ts | 1 - web/src/utils/is/index.ts | 4 + web/src/utils/websocket/index.ts | 2 +- web/src/views/apply/attachment/columns.ts | 4 +- web/src/views/apply/attachment/index.vue | 11 +- web/src/views/apply/notice/columns.ts | 6 - web/src/views/apply/notice/edit.vue | 215 +++++ web/src/views/apply/notice/index.vue | 277 +----- web/src/views/apply/notice/model.ts | 113 +++ web/src/views/asset/cash/columns.ts | 15 +- web/src/views/asset/cash/list.vue | 13 +- web/src/views/asset/creditsLog/model.ts | 23 +- .../views/asset/rechargeLog/applyRefund.vue | 1 - web/src/views/asset/rechargeLog/model.ts | 39 +- web/src/views/log/log/columns.ts | 129 +-- web/src/views/log/log/components/Column.vue | 77 ++ web/src/views/log/log/components/props.ts | 12 + web/src/views/log/log/index.vue | 1 - web/src/views/log/log/model.ts | 7 +- web/src/views/permission/menu/editForm.vue | 8 +- web/src/views/system/config/UploadSetting.vue | 90 +- 98 files changed, 1925 insertions(+), 2860 deletions(-) delete mode 100644 server/internal/library/hggen/internal/cmd/cmd_z_init_test.go delete mode 100644 server/internal/library/hggen/internal/cmd/cmd_z_unit_build_test.go delete mode 100644 server/internal/library/hggen/internal/cmd/cmd_z_unit_fix_test.go delete mode 100644 server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_ctrl_test.go delete mode 100644 server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_dao_test.go delete mode 100644 server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_pb_test.go delete mode 100644 server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_pbentity_test.go delete mode 100644 server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_service_test.go create mode 100644 server/internal/library/hggen/internal/cmd/gendao/gendao_tag.go create mode 100644 web/src/components/ComplexMemberPicker/index.vue create mode 100644 web/src/components/ComplexMemberPicker/props.ts create mode 100644 web/src/views/apply/notice/edit.vue create mode 100644 web/src/views/apply/notice/model.ts create mode 100644 web/src/views/log/log/components/Column.vue create mode 100644 web/src/views/log/log/components/props.ts diff --git a/README.md b/README.md index fd16d72..acb3e3c 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,13 @@

- goframe + goframe vue - naiveui + naiveui typescript @@ -136,7 +136,7 @@ * 本项目包含的第三方源码和二进制文件之版权信息另行标注。 -* 版权所有Copyright © 2020-2024 by Ms (https://github.com/bufanyun/hotgo) +* 版权所有Copyright © 2020-2025 by Ms (https://github.com/bufanyun/hotgo) * All rights reserved。 @@ -154,7 +154,7 @@ ## [感谢JetBrains提供的免费GoLand](https://jb.gg/OpenSource) -[![avatar](https://camo.githubusercontent.com/323657c6e81419b8e151e9da4c71f409e3fcc65d630535170c59fe4807dbc905/68747470733a2f2f676f6672616d652e6f72672f646f776e6c6f61642f7468756d626e61696c732f313131343131392f6a6574627261696e732e706e67)](https://jb.gg/OpenSource) +[![avatar](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)](https://jb.gg/OpenSource) ## License diff --git a/docs/guide-zh-CN/start-environment.md b/docs/guide-zh-CN/start-environment.md index e32f5ae..cedfe4f 100644 --- a/docs/guide-zh-CN/start-environment.md +++ b/docs/guide-zh-CN/start-environment.md @@ -25,7 +25,7 @@ > 需要本地具有 git node golang 环境 -- node版本 >= 16.0.0 +- node版本 >= 20.0.0 - golang版本 >= 1.23 - mysql版本 >= 5.7,引擎需要是 innoDB - IDE推荐:Goland diff --git a/docs/guide-zh-CN/start-installation.md b/docs/guide-zh-CN/start-installation.md index c69ddf5..ab69804 100644 --- a/docs/guide-zh-CN/start-installation.md +++ b/docs/guide-zh-CN/start-installation.md @@ -7,7 +7,7 @@ ### 环境要求 -- node版本 >= v16.0.0 +- node版本 >= v20.0.0 - golang版本 >= v1.23 - goframe版本 >=v2.7.0 - mysql版本 >=5.7 diff --git a/docs/guide-zh-CN/start-update-log.md b/docs/guide-zh-CN/start-update-log.md index edda09c..f55c515 100644 --- a/docs/guide-zh-CN/start-update-log.md +++ b/docs/guide-zh-CN/start-update-log.md @@ -11,6 +11,20 @@ > 如果升级(覆盖)代码后打开会出现 sql 报错, 请检查更新的数据库格式或自行调整 +### v2.16.10 +updated 2025.3.22 + +- 增加:增加组合下拉用户筛选组件 +- 优化:文件上传类型限制改为统一由后台配置控制 +- 优化:websocket重连时间调整为10秒,初始化数据库中的网站地址调整为`127.0.0.1` +- 优化:优化访问日志字段展示方式 +- 优化:系统公告发送编辑模态框调整为抽屉 +- 优化:gf版本升级到v2.9.0 +- 优化:naive-ui版本升级到2.41.0 +- 修复:修复vue路由`Redirect`命名重复问题 +- 修复:优化代码生成在插件中`使用生成字典选项`时model包名重复问题 + + ### v2.15.11 updated 2024.11.27 diff --git a/server/go.mod b/server/go.mod index 43f37c1..2329a48 100644 --- a/server/go.mod +++ b/server/go.mod @@ -14,10 +14,10 @@ require ( github.com/forgoer/openssl v1.6.0 github.com/go-pay/crypto v0.0.1 github.com/go-pay/gopay v1.5.104 - github.com/gogf/gf/contrib/drivers/mysql/v2 v2.8.1 - github.com/gogf/gf/contrib/nosql/redis/v2 v2.8.1 + github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.0 + github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.0 github.com/gogf/gf/contrib/trace/jaeger/v2 v2.7.4 - github.com/gogf/gf/v2 v2.8.1 + github.com/gogf/gf/v2 v2.9.0 github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f github.com/golang-jwt/jwt/v5 v5.2.1 github.com/gorilla/websocket v1.5.3 @@ -26,6 +26,7 @@ require ( github.com/mojocn/base64Captcha v1.3.6 github.com/olekukonko/tablewriter v0.0.5 github.com/qiniu/go-sdk/v7 v7.21.1 + github.com/schollz/progressbar/v3 v3.18.0 github.com/shirou/gopsutil/v3 v3.24.5 github.com/silenceper/wechat/v2 v2.1.6 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.993 @@ -35,7 +36,7 @@ require ( github.com/xuri/excelize/v2 v2.6.0 go.opentelemetry.io/otel v1.32.0 golang.org/x/mod v0.20.0 - golang.org/x/net v0.31.0 + golang.org/x/net v0.32.0 golang.org/x/tools v0.24.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -98,12 +99,13 @@ require ( github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7 // indirect - github.com/magiconair/properties v1.8.7 // indirect + github.com/magiconair/properties v1.8.9 // indirect github.com/matishsiao/goInfo v0.0.0-20210923090445-da2e3fa8d45f // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/minio/md5-simd v1.1.2 // indirect + github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -136,11 +138,12 @@ require ( go.opentelemetry.io/otel/sdk v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect go.uber.org/atomic v1.11.0 // indirect - golang.org/x/crypto v0.29.0 // indirect + golang.org/x/crypto v0.30.0 // indirect golang.org/x/image v0.19.0 // indirect - golang.org/x/sync v0.9.0 // indirect - golang.org/x/sys v0.27.0 // indirect - golang.org/x/text v0.20.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/term v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.6.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect diff --git a/server/go.sum b/server/go.sum index 1f69c6f..e875759 100644 --- a/server/go.sum +++ b/server/go.sum @@ -78,6 +78,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM= +github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -162,14 +164,14 @@ github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PU github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= -github.com/gogf/gf/contrib/drivers/mysql/v2 v2.8.1 h1:jbaPawkb8qmaYzrmBDbTa8Zkhzacq1RBOZw+qRJExI4= -github.com/gogf/gf/contrib/drivers/mysql/v2 v2.8.1/go.mod h1:s2aI1fV9AvKi4NtMpv3pV0EHtazkvfUNVQmzapr7UJQ= -github.com/gogf/gf/contrib/nosql/redis/v2 v2.8.1 h1:1vPFyN0GLv24JD3WGhvKzXvKG+fmuixDTawbtfzCzRQ= -github.com/gogf/gf/contrib/nosql/redis/v2 v2.8.1/go.mod h1:IWyGxzplp06tRc6Ah/eCLuBntnKSw9sn1maH0vzPPtw= +github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.0 h1:1f7EeD0lfPHoXfaJDSL7cxRcSRelbsAKgF3MGXY+Uyo= +github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.0/go.mod h1:tToO1PjGkLIR+9DbJ0wrKicYma0H/EUHXOpwel6Dw+0= +github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.0 h1:EEZqu1PNRSmm+7Cqm9A/8+ObgfbMzhE1ps9Z3LD7HgM= +github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.0/go.mod h1:LHrxY+2IzNTHVTPG/s5yaz1VmXbj+CQ7Hr5SeVkHiTw= github.com/gogf/gf/contrib/trace/jaeger/v2 v2.7.4 h1:JnUjXb7C9vmwcZFwXqnxi9H4/I0rir9LmRryIX7xNds= github.com/gogf/gf/contrib/trace/jaeger/v2 v2.7.4/go.mod h1:A3NhV8u45twLq5VdqObhYNhT4szLFLCROw4LzHM+lYg= -github.com/gogf/gf/v2 v2.8.1 h1:1oVQg3G5OgCats4qWFTH3pHLe92nfUQeUDta05tUs1g= -github.com/gogf/gf/v2 v2.8.1/go.mod h1:6iYuZZ+A0ZcH8+4MDS/P0SvTPCvKzRvyAsY1kbkJYJc= +github.com/gogf/gf/v2 v2.9.0 h1:semN5Q5qGjDQEv4620VzxcJzJlSD07gmyJ9Sy9zfbHk= +github.com/gogf/gf/v2 v2.9.0/go.mod h1:sWGQw+pLILtuHmbOxoe0D+0DdaXxbleT57axOLH2vKI= 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/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= @@ -274,8 +276,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7 h1:5RK988zAqB3/AN3opGfRpoQgAVqr6/A5+qRTi67VUZY= github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM= +github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/matishsiao/goInfo v0.0.0-20210923090445-da2e3fa8d45f h1:B0OD7nYl2FPQEVrw8g2uyc1lGEzNbvrKh7fspGZcbvY= github.com/matishsiao/goInfo v0.0.0-20210923090445-da2e3fa8d45f/go.mod h1:aEt7p9Rvh67BYApmZwNDPpgircTO2kgdmDUoF/1QmwA= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -290,6 +292,8 @@ 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/minio-go/v7 v7.0.76 h1:9nxHH2XDai61cT/EFhyIw/wW4vJfpPNvl7lSFpRt+Ng= github.com/minio/minio-go/v7 v7.0.76/go.mod h1:AVM3IUN6WwKzmwBxVdjzhH8xq+f57JSbbvzqvUzR6eg= +github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= +github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= @@ -356,10 +360,12 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= +github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA= +github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec= github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -395,8 +401,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.563/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.993 h1:+iJMmF0q1MPyhLs0+J7CcJ47w/vq6ICsCxnV4gc0dKw= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.993/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= @@ -468,8 +474,8 @@ golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= -golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= +golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk= @@ -511,8 +517,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -523,8 +529,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -559,8 +565,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -568,6 +574,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -579,8 +587,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/server/internal/consts/version.go b/server/internal/consts/version.go index b7ef1d8..11def75 100644 --- a/server/internal/consts/version.go +++ b/server/internal/consts/version.go @@ -7,5 +7,5 @@ package consts // VersionApp HotGo版本 const ( - VersionApp = "2.15.11" + VersionApp = "2.16.10" ) diff --git a/server/internal/library/hggen/hggen.go b/server/internal/library/hggen/hggen.go index 2db397d..cb23db3 100644 --- a/server/internal/library/hggen/hggen.go +++ b/server/internal/library/hggen/hggen.go @@ -49,7 +49,7 @@ func Dao(ctx context.Context) (err error) { inp.ImportPrefix = utils.GetImportPath(inp.Path) inp.Path = tempPathPrefix + "/" + inp.Path - if err = gfile.Remove(inp.Path); err != nil { + if err = gfile.RemoveAll(inp.Path); err != nil { err = gerror.Newf("清理临时生成目录失败:%v", err) return err } diff --git a/server/internal/library/hggen/internal/cmd/cmd.go b/server/internal/library/hggen/internal/cmd/cmd.go index e8b8bc8..d3668ef 100644 --- a/server/internal/library/hggen/internal/cmd/cmd.go +++ b/server/internal/library/hggen/internal/cmd/cmd.go @@ -4,6 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. +// Package cmd provides the management of CLI commands for `gf` tool. package cmd import ( @@ -19,9 +20,8 @@ import ( "hotgo/internal/library/hggen/internal/utility/mlog" ) -var ( - GF = cGF{} -) +// GF is the management object for `gf` command line tool. +var GF = cGF{} type cGF struct { g.Meta `name:"gf" ad:"{cGFAd}"` diff --git a/server/internal/library/hggen/internal/cmd/cmd_doc.go b/server/internal/library/hggen/internal/cmd/cmd_doc.go index 08f8257..163732d 100644 --- a/server/internal/library/hggen/internal/cmd/cmd_doc.go +++ b/server/internal/library/hggen/internal/cmd/cmd_doc.go @@ -19,6 +19,7 @@ import ( "github.com/gogf/gf/v2/encoding/gcompress" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gfile" + "hotgo/internal/library/hggen/internal/utility/mlog" ) diff --git a/server/internal/library/hggen/internal/cmd/cmd_fix.go b/server/internal/library/hggen/internal/cmd/cmd_fix.go index 2e605ee..0a338aa 100644 --- a/server/internal/library/hggen/internal/cmd/cmd_fix.go +++ b/server/internal/library/hggen/internal/cmd/cmd_fix.go @@ -9,13 +9,13 @@ package cmd import ( "context" - "github.com/gogf/gf/v2/os/gproc" - "github.com/gogf/gf/v2/text/gregex" - "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gfile" + "github.com/gogf/gf/v2/os/gproc" + "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gstr" + "hotgo/internal/library/hggen/internal/utility/mlog" ) diff --git a/server/internal/library/hggen/internal/cmd/cmd_gen_dao.go b/server/internal/library/hggen/internal/cmd/cmd_gen_dao.go index c5e445e..c53a52d 100644 --- a/server/internal/library/hggen/internal/cmd/cmd_gen_dao.go +++ b/server/internal/library/hggen/internal/cmd/cmd_gen_dao.go @@ -8,13 +8,15 @@ package cmd import ( //_ "github.com/gogf/gf/contrib/drivers/clickhouse/v2" - // _ "github.com/gogf/gf/contrib/drivers/dm/v2" // precompilation does not support certain target platforms. //_ "github.com/gogf/gf/contrib/drivers/mssql/v2" _ "github.com/gogf/gf/contrib/drivers/mysql/v2" //_ "github.com/gogf/gf/contrib/drivers/oracle/v2" //_ "github.com/gogf/gf/contrib/drivers/pgsql/v2" //_ "github.com/gogf/gf/contrib/drivers/sqlite/v2" + // do not add dm in cli pre-compilation, + // the dm driver does not support certain target platforms. + // _ "github.com/gogf/gf/contrib/drivers/dm/v2" "hotgo/internal/library/hggen/internal/cmd/gendao" ) diff --git a/server/internal/library/hggen/internal/cmd/cmd_init.go b/server/internal/library/hggen/internal/cmd/cmd_init.go index 7ad160e..319f730 100644 --- a/server/internal/library/hggen/internal/cmd/cmd_init.go +++ b/server/internal/library/hggen/internal/cmd/cmd_init.go @@ -19,6 +19,7 @@ import ( "github.com/gogf/gf/v2/os/gres" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gtag" + "hotgo/internal/library/hggen/internal/utility/allyes" "hotgo/internal/library/hggen/internal/utility/mlog" "hotgo/internal/library/hggen/internal/utility/utils" diff --git a/server/internal/library/hggen/internal/cmd/cmd_up.go b/server/internal/library/hggen/internal/cmd/cmd_up.go index 8c8efeb..eebe364 100644 --- a/server/internal/library/hggen/internal/cmd/cmd_up.go +++ b/server/internal/library/hggen/internal/cmd/cmd_up.go @@ -19,6 +19,7 @@ import ( "github.com/gogf/gf/v2/os/gproc" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gtag" + "hotgo/internal/library/hggen/internal/utility/mlog" "hotgo/internal/library/hggen/internal/utility/utils" ) diff --git a/server/internal/library/hggen/internal/cmd/cmd_z_init_test.go b/server/internal/library/hggen/internal/cmd/cmd_z_init_test.go deleted file mode 100644 index 1e71cbd..0000000 --- a/server/internal/library/hggen/internal/cmd/cmd_z_init_test.go +++ /dev/null @@ -1,38 +0,0 @@ -// 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 ( - "context" - "fmt" - - "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) - } -} diff --git a/server/internal/library/hggen/internal/cmd/cmd_z_unit_build_test.go b/server/internal/library/hggen/internal/cmd/cmd_z_unit_build_test.go deleted file mode 100644 index 3392596..0000000 --- a/server/internal/library/hggen/internal/cmd/cmd_z_unit_build_test.go +++ /dev/null @@ -1,151 +0,0 @@ -// 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 ( - "testing" - - "github.com/gogf/gf/v2/os/gfile" - "github.com/gogf/gf/v2/os/gproc" - "github.com/gogf/gf/v2/test/gtest" - "github.com/gogf/gf/v2/text/gstr" -) - -func Test_Build_Single(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - buildPath = gtest.DataPath(`build`, `single`) - pwd = gfile.Pwd() - binaryName = `t.test` - binaryPath = gtest.DataPath(`build`, `single`, binaryName) - f = cBuild{} - ) - defer gfile.Chdir(pwd) - defer gfile.Remove(binaryPath) - err := gfile.Chdir(buildPath) - t.AssertNil(err) - - t.Assert(gfile.Exists(binaryPath), false) - _, err = f.Index(ctx, cBuildInput{ - File: cBuildDefaultFile, - Name: binaryName, - }) - t.AssertNil(err) - t.Assert(gfile.Exists(binaryPath), true) - }) -} - -func Test_Build_Single_Output(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - buildPath = gtest.DataPath(`build`, `single`) - pwd = gfile.Pwd() - binaryName = `tt` - binaryDirPath = gtest.DataPath(`build`, `single`, `tt`) - binaryPath = gtest.DataPath(`build`, `single`, `tt`, binaryName) - f = cBuild{} - ) - defer gfile.Chdir(pwd) - defer gfile.Remove(binaryDirPath) - err := gfile.Chdir(buildPath) - t.AssertNil(err) - - t.Assert(gfile.Exists(binaryPath), false) - _, err = f.Index(ctx, cBuildInput{ - Output: "./tt/tt", - }) - t.AssertNil(err) - t.Assert(gfile.Exists(binaryPath), true) - }) -} - -func Test_Build_Single_Path(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - buildPath = gtest.DataPath(`build`, `single`) - pwd = gfile.Pwd() - dirName = "ttt" - binaryName = `main` - binaryDirPath = gtest.DataPath(`build`, `single`, dirName) - binaryPath = gtest.DataPath(`build`, `single`, dirName, binaryName) - f = cBuild{} - ) - defer gfile.Chdir(pwd) - defer gfile.Remove(binaryDirPath) - err := gfile.Chdir(buildPath) - t.AssertNil(err) - - t.Assert(gfile.Exists(binaryPath), false) - _, err = f.Index(ctx, cBuildInput{ - Path: "ttt", - }) - t.AssertNil(err) - t.Assert(gfile.Exists(binaryPath), true) - }) -} - -func Test_Build_Single_VarMap(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - buildPath = gtest.DataPath(`build`, `varmap`) - pwd = gfile.Pwd() - binaryName = `main` - binaryPath = gtest.DataPath(`build`, `varmap`, binaryName) - f = cBuild{} - ) - defer gfile.Chdir(pwd) - defer gfile.Remove(binaryPath) - err := gfile.Chdir(buildPath) - t.AssertNil(err) - - t.Assert(gfile.Exists(binaryPath), false) - _, err = f.Index(ctx, cBuildInput{ - VarMap: map[string]interface{}{ - "a": "1", - "b": "2", - }, - }) - t.AssertNil(err) - t.Assert(gfile.Exists(binaryPath), true) - - result, err := gproc.ShellExec(ctx, binaryPath) - t.AssertNil(err) - t.Assert(gstr.Contains(result, `a: 1`), true) - t.Assert(gstr.Contains(result, `b: 2`), true) - }) -} - -func Test_Build_Multiple(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - buildPath = gtest.DataPath(`build`, `multiple`) - pwd = gfile.Pwd() - binaryDirPath = gtest.DataPath(`build`, `multiple`, `temp`) - binaryPathLinux = gtest.DataPath(`build`, `multiple`, `temp`, `v1.1`, `linux_amd64`, `ttt`) - binaryPathWindows = gtest.DataPath(`build`, `multiple`, `temp`, `v1.1`, `windows_amd64`, `ttt.exe`) - f = cBuild{} - ) - defer gfile.Chdir(pwd) - defer gfile.Remove(binaryDirPath) - err := gfile.Chdir(buildPath) - t.AssertNil(err) - - t.Assert(gfile.Exists(binaryPathLinux), false) - t.Assert(gfile.Exists(binaryPathWindows), false) - _, err = f.Index(ctx, cBuildInput{ - File: "multiple.go", - Name: "ttt", - Version: "v1.1", - Arch: "amd64", - System: "linux, windows", - Path: "temp", - }) - t.AssertNil(err) - t.Assert(gfile.Exists(binaryPathLinux), true) - t.Assert(gfile.Exists(binaryPathWindows), true) - }) -} diff --git a/server/internal/library/hggen/internal/cmd/cmd_z_unit_fix_test.go b/server/internal/library/hggen/internal/cmd/cmd_z_unit_fix_test.go deleted file mode 100644 index ad53e41..0000000 --- a/server/internal/library/hggen/internal/cmd/cmd_z_unit_fix_test.go +++ /dev/null @@ -1,24 +0,0 @@ -// 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 ( - "testing" - - "github.com/gogf/gf/v2/test/gtest" -) - -func Test_Fix_doFixV25Content(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - content = gtest.DataContent(`fix`, `fix25_content.go`) - f = cFix{} - ) - _, err := f.doFixV25Content(content) - t.AssertNil(err) - }) -} diff --git a/server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_ctrl_test.go b/server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_ctrl_test.go deleted file mode 100644 index 2d4dff4..0000000 --- a/server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_ctrl_test.go +++ /dev/null @@ -1,309 +0,0 @@ -// 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 ( - "path/filepath" - "testing" - - "github.com/gogf/gf/v2/os/gfile" - "github.com/gogf/gf/v2/test/gtest" - "github.com/gogf/gf/v2/util/guid" - "github.com/gogf/gf/v2/util/gutil" - "hotgo/internal/library/hggen/internal/cmd/genctrl" -) - -func Test_Gen_Ctrl_Default(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - path = gfile.Temp(guid.S()) - apiFolder = gtest.DataPath("genctrl", "api") - in = genctrl.CGenCtrlInput{ - SrcFolder: apiFolder, - DstFolder: path, - WatchFile: "", - SdkPath: "", - SdkStdVersion: false, - SdkNoV1: false, - Clear: false, - Merge: false, - } - ) - err := gutil.FillStructWithDefault(&in) - t.AssertNil(err) - - err = gfile.Mkdir(path) - t.AssertNil(err) - defer gfile.Remove(path) - - _, err = genctrl.CGenCtrl{}.Ctrl(ctx, in) - t.AssertNil(err) - - // apiInterface file - var ( - genApi = apiFolder + filepath.FromSlash("/article/article.go") - genApiExpect = apiFolder + filepath.FromSlash("/article/article_expect.go") - ) - defer gfile.Remove(genApi) - t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect)) - - // files - files, err := gfile.ScanDir(path, "*.go", true) - t.AssertNil(err) - t.Assert(files, []string{ - path + filepath.FromSlash("/article/article.go"), - path + filepath.FromSlash("/article/article_new.go"), - path + filepath.FromSlash("/article/article_v1_create.go"), - path + filepath.FromSlash("/article/article_v1_get_list.go"), - path + filepath.FromSlash("/article/article_v1_get_one.go"), - path + filepath.FromSlash("/article/article_v1_update.go"), - path + filepath.FromSlash("/article/article_v2_create.go"), - path + filepath.FromSlash("/article/article_v2_update.go"), - }) - - // content - testPath := gtest.DataPath("genctrl", "controller") - expectFiles := []string{ - testPath + filepath.FromSlash("/article/article.go"), - testPath + filepath.FromSlash("/article/article_new.go"), - testPath + filepath.FromSlash("/article/article_v1_create.go"), - testPath + filepath.FromSlash("/article/article_v1_get_list.go"), - testPath + filepath.FromSlash("/article/article_v1_get_one.go"), - testPath + filepath.FromSlash("/article/article_v1_update.go"), - testPath + filepath.FromSlash("/article/article_v2_create.go"), - testPath + filepath.FromSlash("/article/article_v2_update.go"), - } - for i := range files { - t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i])) - } - }) -} - -func expectFilesContent(t *gtest.T, paths []string, expectPaths []string) { - for i, expectFile := range expectPaths { - val := gfile.GetContents(paths[i]) - expect := gfile.GetContents(expectFile) - t.Assert(val, expect) - } -} - -// gf gen ctrl -m -// In the same module, different API files are added -func Test_Gen_Ctrl_UseMerge_AddNewFile(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - ctrlPath = gfile.Temp(guid.S()) - //ctrlPath = gtest.DataPath("issue", "3460", "controller") - apiFolder = gtest.DataPath("genctrl-merge", "add_new_file", "api") - in = genctrl.CGenCtrlInput{ - SrcFolder: apiFolder, - DstFolder: ctrlPath, - Merge: true, - } - ) - const testNewApiFile = ` -package v1 -import "github.com/gogf/gf/v2/frame/g" -type DictTypeAddReq struct { - g.Meta -} -type DictTypeAddRes struct { -} -` - - err := gfile.Mkdir(ctrlPath) - t.AssertNil(err) - defer gfile.Remove(ctrlPath) - - _, err = genctrl.CGenCtrl{}.Ctrl(ctx, in) - t.AssertNil(err) - - var ( - genApi = filepath.Join(apiFolder, "/dict/dict.go") - genApiExpect = filepath.Join(apiFolder, "/dict/dict_expect.go") - ) - defer gfile.Remove(genApi) - t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect)) - - genCtrlFiles, err := gfile.ScanDir(ctrlPath, "*.go", true) - t.AssertNil(err) - t.Assert(genCtrlFiles, []string{ - filepath.Join(ctrlPath, "/dict/dict.go"), - filepath.Join(ctrlPath, "/dict/dict_new.go"), - filepath.Join(ctrlPath, "/dict/dict_v1_dict_type.go"), - }) - - expectCtrlPath := gtest.DataPath("genctrl-merge", "add_new_file", "controller") - expectFiles := []string{ - filepath.Join(expectCtrlPath, "/dict/dict.go"), - filepath.Join(expectCtrlPath, "/dict/dict_new.go"), - filepath.Join(expectCtrlPath, "/dict/dict_v1_dict_type.go"), - } - - // Line Feed maybe \r\n or \n - expectFilesContent(t, genCtrlFiles, expectFiles) - - // Add a new API file - newApiFilePath := filepath.Join(apiFolder, "/dict/v1/test_new.go") - err = gfile.PutContents(newApiFilePath, testNewApiFile) - t.AssertNil(err) - defer gfile.Remove(newApiFilePath) - - // Then execute the command - _, err = genctrl.CGenCtrl{}.Ctrl(ctx, in) - t.AssertNil(err) - - genApi = filepath.Join(apiFolder, "/dict.go") - genApiExpect = filepath.Join(apiFolder, "/dict_add_new_ctrl_expect.gotest") - - t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect)) - - genCtrlFiles = append(genCtrlFiles, filepath.Join(ctrlPath, "/dict/dict_v1_test_new.go")) - // Use the gotest suffix, otherwise the IDE will delete the import - expectFiles = append(expectFiles, filepath.Join(expectCtrlPath, "/dict/dict_v1_test_new.gotest")) - // Line Feed maybe \r\n or \n - expectFilesContent(t, genCtrlFiles, expectFiles) - - }) - -} - -// gf gen ctrl -m -// In the same module, Add the same file to the API -func Test_Gen_Ctrl_UseMerge_AddNewCtrl(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - ctrlPath = gfile.Temp(guid.S()) - //ctrlPath = gtest.DataPath("issue", "3460", "controller") - apiFolder = gtest.DataPath("genctrl-merge", "add_new_ctrl", "api") - in = genctrl.CGenCtrlInput{ - SrcFolder: apiFolder, - DstFolder: ctrlPath, - Merge: true, - } - ) - - err := gfile.Mkdir(ctrlPath) - t.AssertNil(err) - defer gfile.Remove(ctrlPath) - - _, err = genctrl.CGenCtrl{}.Ctrl(ctx, in) - t.AssertNil(err) - - var ( - genApi = filepath.Join(apiFolder, "/dict/dict.go") - genApiExpect = filepath.Join(apiFolder, "/dict/dict_expect.go") - ) - defer gfile.Remove(genApi) - t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect)) - - genCtrlFiles, err := gfile.ScanDir(ctrlPath, "*.go", true) - t.AssertNil(err) - t.Assert(genCtrlFiles, []string{ - filepath.Join(ctrlPath, "/dict/dict.go"), - filepath.Join(ctrlPath, "/dict/dict_new.go"), - filepath.Join(ctrlPath, "/dict/dict_v1_dict_type.go"), - }) - - expectCtrlPath := gtest.DataPath("genctrl-merge", "add_new_ctrl", "controller") - expectFiles := []string{ - filepath.Join(expectCtrlPath, "/dict/dict.go"), - filepath.Join(expectCtrlPath, "/dict/dict_new.go"), - filepath.Join(expectCtrlPath, "/dict/dict_v1_dict_type.go"), - } - - // Line Feed maybe \r\n or \n - expectFilesContent(t, genCtrlFiles, expectFiles) - - const testNewApiFile = ` - -type DictTypeAddReq struct { - g.Meta -} -type DictTypeAddRes struct { -} -` - dictModuleFileName := filepath.Join(apiFolder, "/dict/v1/dict_type.go") - // Save the contents of the file before the changes - apiFileContents := gfile.GetContents(dictModuleFileName) - - // Add a new API file - err = gfile.PutContentsAppend(dictModuleFileName, testNewApiFile) - t.AssertNil(err) - - //================================== - // Then execute the command - _, err = genctrl.CGenCtrl{}.Ctrl(ctx, in) - t.AssertNil(err) - - genApi = filepath.Join(apiFolder, "/dict.go") - genApiExpect = filepath.Join(apiFolder, "/dict_add_new_ctrl_expect.gotest") - t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect)) - - // Use the gotest suffix, otherwise the IDE will delete the import - expectFiles[2] = filepath.Join(expectCtrlPath, "/dict/dict_v1_test_new.gotest") - // Line Feed maybe \r\n or \n - expectFilesContent(t, genCtrlFiles, expectFiles) - - // Restore the contents of the original API file - err = gfile.PutContents(dictModuleFileName, apiFileContents) - t.AssertNil(err) - }) - -} - -// https://github.com/gogf/gf/issues/3460 -func Test_Gen_Ctrl_UseMerge_Issue3460(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - ctrlPath = gfile.Temp(guid.S()) - //ctrlPath = gtest.DataPath("issue", "3460", "controller") - apiFolder = gtest.DataPath("issue", "3460", "api") - in = genctrl.CGenCtrlInput{ - SrcFolder: apiFolder, - DstFolder: ctrlPath, - WatchFile: "", - SdkPath: "", - SdkStdVersion: false, - SdkNoV1: false, - Clear: false, - Merge: true, - } - ) - - err := gfile.Mkdir(ctrlPath) - t.AssertNil(err) - defer gfile.Remove(ctrlPath) - - _, err = genctrl.CGenCtrl{}.Ctrl(ctx, in) - t.AssertNil(err) - - files, err := gfile.ScanDir(ctrlPath, "*.go", true) - t.AssertNil(err) - t.Assert(files, []string{ - filepath.Join(ctrlPath, "/hello/hello.go"), - filepath.Join(ctrlPath, "/hello/hello_new.go"), - filepath.Join(ctrlPath, "/hello/hello_v1_req.go"), - filepath.Join(ctrlPath, "/hello/hello_v2_req.go"), - }) - - expectCtrlPath := gtest.DataPath("issue", "3460", "controller") - expectFiles := []string{ - filepath.Join(expectCtrlPath, "/hello/hello.go"), - filepath.Join(expectCtrlPath, "/hello/hello_new.go"), - filepath.Join(expectCtrlPath, "/hello/hello_v1_req.go"), - filepath.Join(expectCtrlPath, "/hello/hello_v2_req.go"), - } - - // Line Feed maybe \r\n or \n - for i, expectFile := range expectFiles { - val := gfile.GetContents(files[i]) - expect := gfile.GetContents(expectFile) - t.Assert(val, expect) - } - }) -} diff --git a/server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_dao_test.go b/server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_dao_test.go deleted file mode 100644 index 4947c79..0000000 --- a/server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_dao_test.go +++ /dev/null @@ -1,841 +0,0 @@ -// 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" - "path/filepath" - "testing" - - "github.com/gogf/gf/v2/database/gdb" - "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/os/gcfg" - "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" - "github.com/gogf/gf/v2/util/gutil" - "hotgo/internal/library/hggen/internal/cmd/gendao" -) - -func Test_Gen_Dao_Default(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - err error - db = testDB - table = "table_user" - sqlContent = fmt.Sprintf( - gtest.DataContent(`gendao`, `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()) - group = "test" - in = gendao.CGenDaoInput{ - Path: path, - Link: link, - Tables: "", - TablesEx: "", - Group: group, - Prefix: "", - RemovePrefix: "", - JsonCase: "SnakeScreaming", - ImportPrefix: "", - DaoPath: "", - DoPath: "", - EntityPath: "", - TplDaoIndexPath: "", - TplDaoInternalPath: "", - TplDaoDoPath: "", - TplDaoEntityPath: "", - StdTime: false, - WithTime: false, - GJsonSupport: false, - OverwriteDao: false, - DescriptionTag: false, - NoJsonTag: false, - NoModelComment: false, - Clear: false, - TypeMapping: nil, - FieldMapping: nil, - } - ) - err = gutil.FillStructWithDefault(&in) - t.AssertNil(err) - - err = gfile.Mkdir(path) - t.AssertNil(err) - - // for go mod import path auto retrieve. - err = gfile.Copy( - gtest.DataPath("gendao", "go.mod.txt"), - gfile.Join(path, "go.mod"), - ) - t.AssertNil(err) - - _, err = gendao.CGenDao{}.Dao(ctx, in) - t.AssertNil(err) - defer gfile.Remove(path) - - // files - files, err := gfile.ScanDir(path, "*.go", true) - t.AssertNil(err) - t.Assert(files, []string{ - filepath.FromSlash(path + "/dao/internal/table_user.go"), - filepath.FromSlash(path + "/dao/table_user.go"), - filepath.FromSlash(path + "/model/do/table_user.go"), - filepath.FromSlash(path + "/model/entity/table_user.go"), - }) - // content - testPath := gtest.DataPath("gendao", "generated_user") - expectFiles := []string{ - filepath.FromSlash(testPath + "/dao/internal/table_user.go"), - filepath.FromSlash(testPath + "/dao/table_user.go"), - filepath.FromSlash(testPath + "/model/do/table_user.go"), - filepath.FromSlash(testPath + "/model/entity/table_user.go"), - } - for i, _ := range files { - t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i])) - } - }) -} - -func Test_Gen_Dao_TypeMapping(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - err error - db = testDB - table = "table_user" - sqlContent = fmt.Sprintf( - gtest.DataContent(`gendao`, `user.tpl.sql`), - table, - ) - ) - defer 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()) - group = "test" - in = gendao.CGenDaoInput{ - Path: path, - Link: link, - Tables: "", - TablesEx: "", - Group: group, - Prefix: "", - RemovePrefix: "", - JsonCase: "", - ImportPrefix: "", - DaoPath: "", - DoPath: "", - EntityPath: "", - TplDaoIndexPath: "", - TplDaoInternalPath: "", - TplDaoDoPath: "", - TplDaoEntityPath: "", - StdTime: false, - WithTime: false, - GJsonSupport: false, - OverwriteDao: false, - DescriptionTag: false, - NoJsonTag: false, - NoModelComment: false, - Clear: false, - TypeMapping: map[gendao.DBFieldTypeName]gendao.CustomAttributeType{ - "int": { - Type: "int64", - Import: "", - }, - "decimal": { - Type: "decimal.Decimal", - Import: "github.com/shopspring/decimal", - }, - }, - FieldMapping: nil, - } - ) - err = gutil.FillStructWithDefault(&in) - t.AssertNil(err) - - err = gfile.Mkdir(path) - t.AssertNil(err) - - // for go mod import path auto retrieve. - err = gfile.Copy( - gtest.DataPath("gendao", "go.mod.txt"), - gfile.Join(path, "go.mod"), - ) - t.AssertNil(err) - - _, err = gendao.CGenDao{}.Dao(ctx, in) - t.AssertNil(err) - defer gfile.Remove(path) - - // files - files, err := gfile.ScanDir(path, "*.go", true) - t.AssertNil(err) - t.Assert(files, []string{ - filepath.FromSlash(path + "/dao/internal/table_user.go"), - filepath.FromSlash(path + "/dao/table_user.go"), - filepath.FromSlash(path + "/model/do/table_user.go"), - filepath.FromSlash(path + "/model/entity/table_user.go"), - }) - // content - testPath := gtest.DataPath("gendao", "generated_user_type_mapping") - expectFiles := []string{ - filepath.FromSlash(testPath + "/dao/internal/table_user.go"), - filepath.FromSlash(testPath + "/dao/table_user.go"), - filepath.FromSlash(testPath + "/model/do/table_user.go"), - filepath.FromSlash(testPath + "/model/entity/table_user.go"), - } - for i, _ := range files { - t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i])) - } - }) -} - -func Test_Gen_Dao_FieldMapping(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - err error - db = testDB - table = "table_user" - sqlContent = fmt.Sprintf( - gtest.DataContent(`gendao`, `user.tpl.sql`), - table, - ) - ) - defer 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()) - group = "test" - in = gendao.CGenDaoInput{ - Path: path, - Link: link, - Tables: "", - TablesEx: "", - Group: group, - Prefix: "", - RemovePrefix: "", - JsonCase: "", - ImportPrefix: "", - DaoPath: "", - DoPath: "", - EntityPath: "", - TplDaoIndexPath: "", - TplDaoInternalPath: "", - TplDaoDoPath: "", - TplDaoEntityPath: "", - StdTime: false, - WithTime: false, - GJsonSupport: false, - OverwriteDao: false, - DescriptionTag: false, - NoJsonTag: false, - NoModelComment: false, - Clear: false, - TypeMapping: map[gendao.DBFieldTypeName]gendao.CustomAttributeType{ - "int": { - Type: "int64", - Import: "", - }, - }, - FieldMapping: map[gendao.DBTableFieldName]gendao.CustomAttributeType{ - "table_user.score": { - Type: "decimal.Decimal", - Import: "github.com/shopspring/decimal", - }, - }, - } - ) - err = gutil.FillStructWithDefault(&in) - t.AssertNil(err) - - err = gfile.Mkdir(path) - t.AssertNil(err) - - // for go mod import path auto retrieve. - err = gfile.Copy( - gtest.DataPath("gendao", "go.mod.txt"), - gfile.Join(path, "go.mod"), - ) - t.AssertNil(err) - - _, err = gendao.CGenDao{}.Dao(ctx, in) - t.AssertNil(err) - defer gfile.Remove(path) - - // files - files, err := gfile.ScanDir(path, "*.go", true) - t.AssertNil(err) - t.Assert(files, []string{ - filepath.FromSlash(path + "/dao/internal/table_user.go"), - filepath.FromSlash(path + "/dao/table_user.go"), - filepath.FromSlash(path + "/model/do/table_user.go"), - filepath.FromSlash(path + "/model/entity/table_user.go"), - }) - // content - testPath := gtest.DataPath("gendao", "generated_user_field_mapping") - expectFiles := []string{ - filepath.FromSlash(testPath + "/dao/internal/table_user.go"), - filepath.FromSlash(testPath + "/dao/table_user.go"), - filepath.FromSlash(testPath + "/model/do/table_user.go"), - filepath.FromSlash(testPath + "/model/entity/table_user.go"), - } - for i, _ := range files { - t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i])) - } - }) -} - -func execSqlFile(db gdb.DB, filePath string, args ...any) error { - sqlContent := fmt.Sprintf( - gfile.GetContents(filePath), - args..., - ) - array := gstr.SplitAndTrim(sqlContent, ";") - for _, v := range array { - if _, err := db.Exec(ctx, v); err != nil { - return err - } - } - return nil -} - -// https://github.com/gogf/gf/issues/2572 -func Test_Gen_Dao_Issue2572(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - err error - db = testDB - table1 = "user1" - table2 = "user2" - issueDirPath = gtest.DataPath(`issue`, `2572`) - ) - t.AssertNil(execSqlFile(db, gtest.DataPath(`issue`, `2572`, `sql1.sql`))) - t.AssertNil(execSqlFile(db, gtest.DataPath(`issue`, `2572`, `sql2.sql`))) - defer dropTableWithDb(db, table1) - defer dropTableWithDb(db, table2) - - var ( - path = gfile.Temp(guid.S()) - group = "test" - in = gendao.CGenDaoInput{ - Path: path, - Link: "", - Tables: "", - TablesEx: "", - Group: group, - Prefix: "", - RemovePrefix: "", - JsonCase: "SnakeScreaming", - ImportPrefix: "", - DaoPath: "", - DoPath: "", - EntityPath: "", - TplDaoIndexPath: "", - TplDaoInternalPath: "", - TplDaoDoPath: "", - TplDaoEntityPath: "", - StdTime: false, - WithTime: false, - GJsonSupport: false, - OverwriteDao: false, - DescriptionTag: false, - NoJsonTag: false, - NoModelComment: false, - Clear: false, - TypeMapping: nil, - FieldMapping: nil, - } - ) - err = gutil.FillStructWithDefault(&in) - t.AssertNil(err) - - err = gfile.Copy(issueDirPath, path) - t.AssertNil(err) - - defer gfile.Remove(path) - - pwd := gfile.Pwd() - err = gfile.Chdir(path) - t.AssertNil(err) - - defer gfile.Chdir(pwd) - - _, err = gendao.CGenDao{}.Dao(ctx, in) - t.AssertNil(err) - - generatedFiles, err := gfile.ScanDir(path, "*.go", true) - t.AssertNil(err) - t.Assert(len(generatedFiles), 8) - for i, generatedFile := range generatedFiles { - generatedFiles[i] = gstr.TrimLeftStr(generatedFile, path) - } - t.Assert(gstr.InArray(generatedFiles, - filepath.FromSlash("/dao/internal/user_1.go")), true) - t.Assert(gstr.InArray(generatedFiles, - filepath.FromSlash("/dao/internal/user_2.go")), true) - t.Assert(gstr.InArray(generatedFiles, - filepath.FromSlash("/dao/user_1.go")), true) - t.Assert(gstr.InArray(generatedFiles, - filepath.FromSlash("/dao/user_2.go")), true) - t.Assert(gstr.InArray(generatedFiles, - filepath.FromSlash("/model/do/user_1.go")), true) - t.Assert(gstr.InArray(generatedFiles, - filepath.FromSlash("/model/do/user_2.go")), true) - t.Assert(gstr.InArray(generatedFiles, - filepath.FromSlash("/model/entity/user_1.go")), true) - t.Assert(gstr.InArray(generatedFiles, - filepath.FromSlash("/model/entity/user_2.go")), true) - }) -} - -// https://github.com/gogf/gf/issues/2616 -func Test_Gen_Dao_Issue2616(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - err error - db = testDB - table1 = "user1" - table2 = "user2" - issueDirPath = gtest.DataPath(`issue`, `2616`) - ) - t.AssertNil(execSqlFile(db, gtest.DataPath(`issue`, `2616`, `sql1.sql`))) - t.AssertNil(execSqlFile(db, gtest.DataPath(`issue`, `2616`, `sql2.sql`))) - defer dropTableWithDb(db, table1) - defer dropTableWithDb(db, table2) - - var ( - path = gfile.Temp(guid.S()) - group = "test" - in = gendao.CGenDaoInput{ - Path: path, - Link: "", - Tables: "", - TablesEx: "", - Group: group, - Prefix: "", - RemovePrefix: "", - JsonCase: "SnakeScreaming", - ImportPrefix: "", - DaoPath: "", - DoPath: "", - EntityPath: "", - TplDaoIndexPath: "", - TplDaoInternalPath: "", - TplDaoDoPath: "", - TplDaoEntityPath: "", - StdTime: false, - WithTime: false, - GJsonSupport: false, - OverwriteDao: false, - DescriptionTag: false, - NoJsonTag: false, - NoModelComment: false, - Clear: false, - TypeMapping: nil, - FieldMapping: nil, - } - ) - err = gutil.FillStructWithDefault(&in) - t.AssertNil(err) - - err = gfile.Copy(issueDirPath, path) - t.AssertNil(err) - - defer gfile.Remove(path) - - pwd := gfile.Pwd() - err = gfile.Chdir(path) - t.AssertNil(err) - - defer gfile.Chdir(pwd) - - _, err = gendao.CGenDao{}.Dao(ctx, in) - t.AssertNil(err) - - generatedFiles, err := gfile.ScanDir(path, "*.go", true) - t.AssertNil(err) - t.Assert(len(generatedFiles), 8) - for i, generatedFile := range generatedFiles { - generatedFiles[i] = gstr.TrimLeftStr(generatedFile, path) - } - t.Assert(gstr.InArray(generatedFiles, - filepath.FromSlash("/dao/internal/user_1.go")), true) - t.Assert(gstr.InArray(generatedFiles, - filepath.FromSlash("/dao/internal/user_2.go")), true) - t.Assert(gstr.InArray(generatedFiles, - filepath.FromSlash("/dao/user_1.go")), true) - t.Assert(gstr.InArray(generatedFiles, - filepath.FromSlash("/dao/user_2.go")), true) - t.Assert(gstr.InArray(generatedFiles, - filepath.FromSlash("/model/do/user_1.go")), true) - t.Assert(gstr.InArray(generatedFiles, - filepath.FromSlash("/model/do/user_2.go")), true) - t.Assert(gstr.InArray(generatedFiles, - filepath.FromSlash("/model/entity/user_1.go")), true) - t.Assert(gstr.InArray(generatedFiles, - filepath.FromSlash("/model/entity/user_2.go")), true) - - // Key string to check if overwrite the dao files. - // dao user1 is not be overwritten as configured in config.yaml. - // dao user2 is to be overwritten as configured in config.yaml. - var ( - keyStr = `// I am not overwritten.` - daoUser1Content = gfile.GetContents(path + "/dao/user_1.go") - daoUser2Content = gfile.GetContents(path + "/dao/user_2.go") - ) - t.Assert(gstr.Contains(daoUser1Content, keyStr), true) - t.Assert(gstr.Contains(daoUser2Content, keyStr), false) - }) -} - -// https://github.com/gogf/gf/issues/2746 -func Test_Gen_Dao_Issue2746(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - err error - mdb gdb.DB - link2746 = "mariadb:root:12345678@tcp(127.0.0.1:3307)/test?loc=Local&parseTime=true" - table = "issue2746" - sqlContent = fmt.Sprintf( - gtest.DataContent(`issue`, `2746`, `sql.sql`), - table, - ) - ) - mdb, err = gdb.New(gdb.ConfigNode{ - Link: link2746, - }) - t.AssertNil(err) - - array := gstr.SplitAndTrim(sqlContent, ";") - for _, v := range array { - if _, err = mdb.Exec(ctx, v); err != nil { - t.AssertNil(err) - } - } - defer dropTableWithDb(mdb, table) - - var ( - path = gfile.Temp(guid.S()) - group = "test" - in = gendao.CGenDaoInput{ - Path: path, - Link: link2746, - Tables: "", - TablesEx: "", - Group: group, - Prefix: "", - RemovePrefix: "", - JsonCase: "SnakeScreaming", - ImportPrefix: "", - DaoPath: "", - DoPath: "", - EntityPath: "", - TplDaoIndexPath: "", - TplDaoInternalPath: "", - TplDaoDoPath: "", - TplDaoEntityPath: "", - StdTime: false, - WithTime: false, - GJsonSupport: true, - OverwriteDao: false, - DescriptionTag: false, - NoJsonTag: false, - NoModelComment: false, - Clear: false, - TypeMapping: nil, - FieldMapping: nil, - } - ) - err = gutil.FillStructWithDefault(&in) - t.AssertNil(err) - - err = gfile.Mkdir(path) - t.AssertNil(err) - - _, err = gendao.CGenDao{}.Dao(ctx, in) - t.AssertNil(err) - defer gfile.Remove(path) - - var ( - file = filepath.FromSlash(path + "/model/entity/issue_2746.go") - expectContent = gtest.DataContent(`issue`, `2746`, `issue_2746.go`) - ) - t.Assert(expectContent, gfile.GetContents(file)) - }) -} - -// https://github.com/gogf/gf/issues/3459 -func Test_Gen_Dao_Issue3459(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - err error - db = testDB - table = "table_user" - sqlContent = fmt.Sprintf( - gtest.DataContent(`gendao`, `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 ( - confDir = gtest.DataPath("issue", "3459") - path = gfile.Temp(guid.S()) - group = "test" - in = gendao.CGenDaoInput{ - Path: path, - Link: link, - Tables: "", - TablesEx: "", - Group: group, - Prefix: "", - RemovePrefix: "", - JsonCase: "SnakeScreaming", - ImportPrefix: "", - DaoPath: "", - DoPath: "", - EntityPath: "", - TplDaoIndexPath: "", - TplDaoInternalPath: "", - TplDaoDoPath: "", - TplDaoEntityPath: "", - StdTime: false, - WithTime: false, - GJsonSupport: false, - OverwriteDao: false, - DescriptionTag: false, - NoJsonTag: false, - NoModelComment: false, - Clear: false, - TypeMapping: nil, - } - ) - err = g.Cfg().GetAdapter().(*gcfg.AdapterFile).SetPath(confDir) - t.AssertNil(err) - - err = gutil.FillStructWithDefault(&in) - t.AssertNil(err) - - err = gfile.Mkdir(path) - t.AssertNil(err) - - // for go mod import path auto retrieve. - err = gfile.Copy( - gtest.DataPath("gendao", "go.mod.txt"), - gfile.Join(path, "go.mod"), - ) - t.AssertNil(err) - - _, err = gendao.CGenDao{}.Dao(ctx, in) - t.AssertNil(err) - defer gfile.Remove(path) - - // files - files, err := gfile.ScanDir(path, "*.go", true) - t.AssertNil(err) - t.Assert(files, []string{ - filepath.FromSlash(path + "/dao/internal/table_user.go"), - filepath.FromSlash(path + "/dao/table_user.go"), - filepath.FromSlash(path + "/model/do/table_user.go"), - filepath.FromSlash(path + "/model/entity/table_user.go"), - }) - // content - testPath := gtest.DataPath("gendao", "generated_user") - expectFiles := []string{ - filepath.FromSlash(testPath + "/dao/internal/table_user.go"), - filepath.FromSlash(testPath + "/dao/table_user.go"), - filepath.FromSlash(testPath + "/model/do/table_user.go"), - filepath.FromSlash(testPath + "/model/entity/table_user.go"), - } - for i, _ := range files { - t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i])) - } - }) -} - -// https://github.com/gogf/gf/issues/3749 -func Test_Gen_Dao_Issue3749(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - err error - db = testDB - table = "table_user" - sqlContent = fmt.Sprintf( - gtest.DataContent(`issue`, `3749`, `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()) - group = "test" - in = gendao.CGenDaoInput{ - Path: path, - Link: link, - Group: group, - } - ) - - err = gutil.FillStructWithDefault(&in) - t.AssertNil(err) - - err = gfile.Mkdir(path) - t.AssertNil(err) - - // for go mod import path auto retrieve. - err = gfile.Copy( - gtest.DataPath("gendao", "go.mod.txt"), - gfile.Join(path, "go.mod"), - ) - t.AssertNil(err) - - _, err = gendao.CGenDao{}.Dao(ctx, in) - t.AssertNil(err) - defer gfile.Remove(path) - - // files - files, err := gfile.ScanDir(path, "*.go", true) - t.AssertNil(err) - t.Assert(files, []string{ - filepath.FromSlash(path + "/dao/internal/table_user.go"), - filepath.FromSlash(path + "/dao/table_user.go"), - filepath.FromSlash(path + "/model/do/table_user.go"), - filepath.FromSlash(path + "/model/entity/table_user.go"), - }) - // content - testPath := gtest.DataPath(`issue`, `3749`) - expectFiles := []string{ - filepath.FromSlash(testPath + "/dao/internal/table_user.go"), - filepath.FromSlash(testPath + "/dao/table_user.go"), - filepath.FromSlash(testPath + "/model/do/table_user.go"), - filepath.FromSlash(testPath + "/model/entity/table_user.go"), - } - for i, _ := range files { - t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i])) - } - }) -} - -func Test_Gen_Dao_Sqlite3(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - err error - table = "table_user" - path = gfile.Temp(guid.S()) - linkSqlite3 = fmt.Sprintf("sqlite::@file(%s/db.sqlite3)", path) - sqlContent = fmt.Sprintf( - gtest.DataContent(`gendao`, `sqlite3`, `user.sqlite3.sql`), - table, - ) - ) - err = gfile.Mkdir(path) - t.AssertNil(err) - defer gfile.Remove(path) - - dbSqlite3, err := gdb.New(gdb.ConfigNode{ - Link: linkSqlite3, - }) - t.AssertNil(err) - - array := gstr.SplitAndTrim(sqlContent, ";") - for _, v := range array { - if v == "" { - continue - } - if _, err = dbSqlite3.Exec(ctx, v); err != nil { - t.AssertNil(err) - } - } - - var ( - group = "test" - in = gendao.CGenDaoInput{ - Path: path, - Link: linkSqlite3, - Group: group, - Tables: table, - } - ) - err = gutil.FillStructWithDefault(&in) - t.AssertNil(err) - - // for go mod import path auto retrieve. - err = gfile.Copy( - gtest.DataPath("gendao", "go.mod.txt"), - gfile.Join(path, "go.mod"), - ) - t.AssertNil(err) - - _, err = gendao.CGenDao{}.Dao(ctx, in) - t.AssertNil(err) - defer gfile.Remove(path) - - // files - files, err := gfile.ScanDir(path, "*.go", true) - t.AssertNil(err) - t.Assert(files, []string{ - filepath.FromSlash(path + "/dao/internal/table_user.go"), - filepath.FromSlash(path + "/dao/table_user.go"), - filepath.FromSlash(path + "/model/do/table_user.go"), - filepath.FromSlash(path + "/model/entity/table_user.go"), - }) - // content - testPath := gtest.DataPath("gendao", "generated_user_sqlite3") - expectFiles := []string{ - filepath.FromSlash(testPath + "/dao/internal/table_user.go"), - filepath.FromSlash(testPath + "/dao/table_user.go"), - filepath.FromSlash(testPath + "/model/do/table_user.go"), - filepath.FromSlash(testPath + "/model/entity/table_user.go"), - } - for i, _ := range files { - t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i])) - } - }) -} diff --git a/server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_pb_test.go b/server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_pb_test.go deleted file mode 100644 index 882efe3..0000000 --- a/server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_pb_test.go +++ /dev/null @@ -1,50 +0,0 @@ -// 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 ( - "path/filepath" - "testing" - - "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" - "hotgo/internal/library/hggen/internal/cmd/genpb" -) - -func TestGenPbIssue3882(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - outputPath = gfile.Temp(guid.S()) - outputApiPath = filepath.Join(outputPath, "api") - outputCtrlPath = filepath.Join(outputPath, "controller") - - protobufFolder = gtest.DataPath("issue", "3882") - in = genpb.CGenPbInput{ - Path: protobufFolder, - OutputApi: outputApiPath, - OutputCtrl: outputCtrlPath, - } - err error - ) - err = gfile.Mkdir(outputApiPath) - t.AssertNil(err) - err = gfile.Mkdir(outputCtrlPath) - t.AssertNil(err) - defer gfile.Remove(outputPath) - - _, err = genpb.CGenPb{}.Pb(ctx, in) - t.AssertNil(err) - - var ( - genContent = gfile.GetContents(filepath.Join(outputApiPath, "issue3882.pb.go")) - exceptText = `dc:"Some comment on field with 'one' 'two' 'three' in the comment."` - ) - t.Assert(gstr.Contains(genContent, exceptText), true) - }) -} diff --git a/server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_pbentity_test.go b/server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_pbentity_test.go deleted file mode 100644 index 6516645..0000000 --- a/server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_pbentity_test.go +++ /dev/null @@ -1,210 +0,0 @@ -// 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" - "path/filepath" - "testing" - - "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" - "github.com/gogf/gf/v2/util/gutil" - "hotgo/internal/library/hggen/internal/cmd/genpbentity" -) - -func Test_Gen_Pbentity_Default(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()) - in = genpbentity.CGenPbEntityInput{ - Path: path, - Package: "unittest", - Link: link, - Tables: "", - Prefix: "", - RemovePrefix: "", - RemoveFieldPrefix: "", - NameCase: "", - JsonCase: "", - Option: "", - } - ) - err = gutil.FillStructWithDefault(&in) - t.AssertNil(err) - - err = gfile.Mkdir(path) - t.AssertNil(err) - defer gfile.Remove(path) - - _, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in) - t.AssertNil(err) - - // files - files, err := gfile.ScanDir(path, "*.proto", false) - t.AssertNil(err) - t.Assert(files, []string{ - path + filepath.FromSlash("/table_user.proto"), - }) - - // contents - testPath := gtest.DataPath("genpbentity", "generated") - expectFiles := []string{ - testPath + filepath.FromSlash("/table_user.proto"), - } - for i := range files { - t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i])) - } - }) -} - -func Test_Gen_Pbentity_NameCase_SnakeScreaming(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()) - in = genpbentity.CGenPbEntityInput{ - Path: path, - Package: "unittest", - Link: link, - Tables: "", - Prefix: "", - RemovePrefix: "", - RemoveFieldPrefix: "", - NameCase: "SnakeScreaming", - JsonCase: "", - Option: "", - } - ) - err = gutil.FillStructWithDefault(&in) - t.AssertNil(err) - - err = gfile.Mkdir(path) - t.AssertNil(err) - defer gfile.Remove(path) - - _, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in) - t.AssertNil(err) - - // files - files, err := gfile.ScanDir(path, "*.proto", false) - t.AssertNil(err) - t.Assert(files, []string{ - path + filepath.FromSlash("/table_user.proto"), - }) - - // contents - testPath := gtest.DataPath("genpbentity", "generated") - expectFiles := []string{ - testPath + filepath.FromSlash("/table_user_snake_screaming.proto"), - } - for i := range files { - t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i])) - } - }) -} - -// https://github.com/gogf/gf/issues/3545 -func Test_Issue_3545(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()) - in = genpbentity.CGenPbEntityInput{ - Path: path, - Package: "", - Link: link, - Tables: "", - Prefix: "", - RemovePrefix: "", - RemoveFieldPrefix: "", - NameCase: "", - JsonCase: "", - Option: "", - } - ) - err = gutil.FillStructWithDefault(&in) - t.AssertNil(err) - - err = gfile.Mkdir(path) - t.AssertNil(err) - defer gfile.Remove(path) - - _, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in) - t.AssertNil(err) - - // files - files, err := gfile.ScanDir(path, "*.proto", false) - t.AssertNil(err) - t.Assert(files, []string{ - path + filepath.FromSlash("/table_user.proto"), - }) - - // contents - testPath := gtest.DataPath("issue", "3545") - expectFiles := []string{ - testPath + filepath.FromSlash("/table_user.proto"), - } - for i := range files { - t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i])) - } - }) -} diff --git a/server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_service_test.go b/server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_service_test.go deleted file mode 100644 index c503706..0000000 --- a/server/internal/library/hggen/internal/cmd/cmd_z_unit_gen_service_test.go +++ /dev/null @@ -1,155 +0,0 @@ -// 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 ( - "path/filepath" - "testing" - - "github.com/gogf/gf/v2/os/gfile" - "github.com/gogf/gf/v2/test/gtest" - "github.com/gogf/gf/v2/util/guid" - "github.com/gogf/gf/v2/util/gutil" - "hotgo/internal/library/hggen/internal/cmd/genservice" -) - -func Test_Gen_Service_Default(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - path = gfile.Temp(guid.S()) - dstFolder = path + filepath.FromSlash("/service") - srvFolder = gtest.DataPath("genservice", "logic") - in = genservice.CGenServiceInput{ - SrcFolder: srvFolder, - DstFolder: dstFolder, - DstFileNameCase: "Snake", - WatchFile: "", - StPattern: "", - Packages: nil, - ImportPrefix: "", - Clear: false, - } - ) - err := gutil.FillStructWithDefault(&in) - t.AssertNil(err) - - err = gfile.Mkdir(path) - t.AssertNil(err) - defer gfile.Remove(path) - - _, err = genservice.CGenService{}.Service(ctx, in) - t.AssertNil(err) - - // logic file - var ( - genSrv = srvFolder + filepath.FromSlash("/logic.go") - genSrvExpect = srvFolder + filepath.FromSlash("/logic_expect.go") - ) - defer gfile.Remove(genSrv) - t.Assert(gfile.GetContents(genSrv), gfile.GetContents(genSrvExpect)) - - // files - files, err := gfile.ScanDir(dstFolder, "*.go", true) - t.AssertNil(err) - t.Assert(files, []string{ - dstFolder + filepath.FromSlash("/article.go"), - dstFolder + filepath.FromSlash("/delivery.go"), - dstFolder + filepath.FromSlash("/user.go"), - }) - - // contents - testPath := gtest.DataPath("genservice", "service") - expectFiles := []string{ - testPath + filepath.FromSlash("/article.go"), - testPath + filepath.FromSlash("/delivery.go"), - testPath + filepath.FromSlash("/user.go"), - } - for i := range files { - t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i])) - } - }) -} - -// https://github.com/gogf/gf/issues/3328 -func Test_Issue3328(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - path = gfile.Temp(guid.S()) - dstFolder = path + filepath.FromSlash("/service") - srvFolder = gtest.DataPath("issue", "3328", "logic") - logicGoPath = srvFolder + filepath.FromSlash("/logic.go") - in = genservice.CGenServiceInput{ - SrcFolder: srvFolder, - DstFolder: dstFolder, - DstFileNameCase: "Snake", - WatchFile: "", - StPattern: "", - Packages: nil, - ImportPrefix: "", - Clear: false, - } - ) - gfile.Remove(logicGoPath) - defer gfile.Remove(logicGoPath) - - err := gutil.FillStructWithDefault(&in) - t.AssertNil(err) - - err = gfile.Mkdir(path) - t.AssertNil(err) - defer gfile.Remove(path) - - _, err = genservice.CGenService{}.Service(ctx, in) - t.AssertNil(err) - - files, err := gfile.ScanDir(srvFolder, "*", true) - for _, file := range files { - if file == logicGoPath { - if gfile.IsDir(logicGoPath) { - t.Fatalf("%s should not is folder", logicGoPath) - } - } - } - }) -} - -// https://github.com/gogf/gf/issues/3835 -func Test_Issue3835(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var ( - path = gfile.Temp(guid.S()) - dstFolder = path + filepath.FromSlash("/service") - srvFolder = gtest.DataPath("issue", "3835", "logic") - in = genservice.CGenServiceInput{ - SrcFolder: srvFolder, - DstFolder: dstFolder, - DstFileNameCase: "Snake", - WatchFile: "", - StPattern: "", - Packages: nil, - ImportPrefix: "", - Clear: false, - } - ) - err := gutil.FillStructWithDefault(&in) - t.AssertNil(err) - - err = gfile.Mkdir(path) - t.AssertNil(err) - defer gfile.Remove(path) - - _, err = genservice.CGenService{}.Service(ctx, in) - t.AssertNil(err) - - // contents - var ( - genFile = dstFolder + filepath.FromSlash("/issue_3835.go") - expectFile = gtest.DataPath("issue", "3835", "service", "issue_3835.go") - ) - t.Assert(gfile.GetContents(genFile), gfile.GetContents(expectFile)) - }) -} diff --git a/server/internal/library/hggen/internal/cmd/genctrl/genctrl_api_item.go b/server/internal/library/hggen/internal/cmd/genctrl/genctrl_api_item.go index b495e26..c502e3e 100644 --- a/server/internal/library/hggen/internal/cmd/genctrl/genctrl_api_item.go +++ b/server/internal/library/hggen/internal/cmd/genctrl/genctrl_api_item.go @@ -6,7 +6,11 @@ package genctrl -import "github.com/gogf/gf/v2/text/gstr" +import ( + "fmt" + + "github.com/gogf/gf/v2/text/gstr" +) type apiItem struct { Import string `eg:"demo.com/api/user/v1"` @@ -14,6 +18,7 @@ type apiItem struct { Module string `eg:"user"` Version string `eg:"v1"` MethodName string `eg:"GetList"` + Comment string `eg:"GetList get list"` } func (a apiItem) String() string { @@ -21,3 +26,12 @@ func (a apiItem) String() string { a.Import, a.Module, a.Version, a.MethodName, }, ",") } + +// GetComment returns the comment of apiItem. +func (a apiItem) GetComment() string { + if a.Comment == "" { + return "" + } + // format for handling comments + return fmt.Sprintf("\n// %s %s", a.MethodName, a.Comment) +} diff --git a/server/internal/library/hggen/internal/cmd/genctrl/genctrl_ast_parse.go b/server/internal/library/hggen/internal/cmd/genctrl/genctrl_ast_parse.go index cf27089..9f87bf5 100644 --- a/server/internal/library/hggen/internal/cmd/genctrl/genctrl_ast_parse.go +++ b/server/internal/library/hggen/internal/cmd/genctrl/genctrl_ast_parse.go @@ -17,9 +17,14 @@ import ( "github.com/gogf/gf/v2/text/gstr" ) -// getStructsNameInSrc retrieves all struct names +type structInfo struct { + structName string + comment string +} + +// getStructsNameInSrc retrieves all struct names and comment // that end in "Req" and have "g.Meta" in their body. -func (c CGenCtrl) getStructsNameInSrc(filePath string) (structsName []string, err error) { +func (c CGenCtrl) getStructsNameInSrc(filePath string) (structInfos []*structInfo, err error) { var ( fileContent = gfile.GetContents(filePath) fileSet = token.NewFileSet() @@ -32,8 +37,8 @@ func (c CGenCtrl) getStructsNameInSrc(filePath string) (structsName []string, er ast.Inspect(node, func(n ast.Node) bool { if typeSpec, ok := n.(*ast.TypeSpec); ok { - methodName := typeSpec.Name.Name - if !gstr.HasSuffix(methodName, "Req") { + structName := typeSpec.Name.Name + if !gstr.HasSuffix(structName, "Req") { // ignore struct name that do not end in "Req" return true } @@ -46,7 +51,19 @@ func (c CGenCtrl) getStructsNameInSrc(filePath string) (structsName []string, er if !gstr.Contains(buf.String(), `g.Meta`) { return true } - structsName = append(structsName, methodName) + + comment := typeSpec.Doc.Text() + // remove the struct name from the comment + if gstr.HasPrefix(comment, structName) { + comment = gstr.TrimLeftStr(comment, structName, 1) + } + // remove the comment \n or space + comment = gstr.Trim(comment) + + structInfos = append(structInfos, &structInfo{ + structName: structName, + comment: comment, + }) } } return true diff --git a/server/internal/library/hggen/internal/cmd/genctrl/genctrl_calculate.go b/server/internal/library/hggen/internal/cmd/genctrl/genctrl_calculate.go index 841e49a..62818a4 100644 --- a/server/internal/library/hggen/internal/cmd/genctrl/genctrl_calculate.go +++ b/server/internal/library/hggen/internal/cmd/genctrl/genctrl_calculate.go @@ -10,6 +10,7 @@ import ( "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gstr" + "hotgo/internal/library/hggen/internal/utility/utils" ) @@ -38,15 +39,16 @@ func (c CGenCtrl) getApiItemsInSrc(apiModuleFolderPath string) (items []apiItem, if err != nil { return nil, err } - for _, methodName := range structsInfo { + for _, s := range structsInfo { // remove end "Req" - methodName = gstr.TrimRightStr(methodName, "Req", 1) + methodName := gstr.TrimRightStr(s.structName, "Req", 1) item := apiItem{ Import: gstr.Trim(importPath, `"`), FileName: gfile.Name(apiFileFolderPath), Module: gfile.Basename(apiModuleFolderPath), Version: gfile.Basename(apiVersionFolderPath), MethodName: methodName, + Comment: s.comment, } items = append(items, item) } diff --git a/server/internal/library/hggen/internal/cmd/genctrl/genctrl_generate_ctrl.go b/server/internal/library/hggen/internal/cmd/genctrl/genctrl_generate_ctrl.go index 2c54af4..08cb33e 100644 --- a/server/internal/library/hggen/internal/cmd/genctrl/genctrl_generate_ctrl.go +++ b/server/internal/library/hggen/internal/cmd/genctrl/genctrl_generate_ctrl.go @@ -15,6 +15,7 @@ import ( "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/text/gstr" + "hotgo/internal/library/hggen/internal/consts" "hotgo/internal/library/hggen/internal/utility/mlog" ) @@ -137,10 +138,11 @@ func (c *controllerGenerator) doGenerateCtrlItem(dstModuleFolderPath string, ite if gfile.Exists(methodFilePath) { content = gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFuncMerge, g.MapStrStr{ - "{Module}": item.Module, - "{CtrlName}": ctrlName, - "{Version}": item.Version, - "{MethodName}": item.MethodName, + "{Module}": item.Module, + "{CtrlName}": ctrlName, + "{Version}": item.Version, + "{MethodName}": item.MethodName, + "{MethodComment}": item.GetComment(), }) if gstr.Contains(gfile.GetContents(methodFilePath), fmt.Sprintf(`func (c *%v) %v(`, ctrlName, item.MethodName)) { @@ -151,11 +153,12 @@ func (c *controllerGenerator) doGenerateCtrlItem(dstModuleFolderPath string, ite } } else { content = gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFunc, g.MapStrStr{ - "{Module}": item.Module, - "{ImportPath}": item.Import, - "{CtrlName}": ctrlName, - "{Version}": item.Version, - "{MethodName}": item.MethodName, + "{Module}": item.Module, + "{ImportPath}": item.Import, + "{CtrlName}": ctrlName, + "{Version}": item.Version, + "{MethodName}": item.MethodName, + "{MethodComment}": item.GetComment(), }) if err = gfile.PutContents(methodFilePath, gstr.TrimLeft(content)); err != nil { return err @@ -191,10 +194,11 @@ func (c *controllerGenerator) doGenerateCtrlMergeItem(dstModuleFolderPath string } ctrl := gstr.TrimLeft(gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFuncMerge, g.MapStrStr{ - "{Module}": api.Module, - "{CtrlName}": fmt.Sprintf(`Controller%s`, gstr.UcFirst(api.Version)), - "{Version}": api.Version, - "{MethodName}": api.MethodName, + "{Module}": api.Module, + "{CtrlName}": fmt.Sprintf(`Controller%s`, gstr.UcFirst(api.Version)), + "{Version}": api.Version, + "{MethodName}": api.MethodName, + "{MethodComment}": api.GetComment(), })) ctrlFileItem.controllers.WriteString(ctrl) doneApiSet.Add(api.String()) diff --git a/server/internal/library/hggen/internal/cmd/genctrl/genctrl_generate_ctrl_clear.go b/server/internal/library/hggen/internal/cmd/genctrl/genctrl_generate_ctrl_clear.go index aab8a78..b3fbcc8 100644 --- a/server/internal/library/hggen/internal/cmd/genctrl/genctrl_generate_ctrl_clear.go +++ b/server/internal/library/hggen/internal/cmd/genctrl/genctrl_generate_ctrl_clear.go @@ -11,6 +11,7 @@ import ( "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/text/gstr" + "hotgo/internal/library/hggen/internal/utility/mlog" ) diff --git a/server/internal/library/hggen/internal/cmd/genctrl/genctrl_generate_interface.go b/server/internal/library/hggen/internal/cmd/genctrl/genctrl_generate_interface.go index 29df0e3..a6cc5eb 100644 --- a/server/internal/library/hggen/internal/cmd/genctrl/genctrl_generate_interface.go +++ b/server/internal/library/hggen/internal/cmd/genctrl/genctrl_generate_interface.go @@ -16,6 +16,7 @@ import ( "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" + "hotgo/internal/library/hggen/internal/consts" "hotgo/internal/library/hggen/internal/utility/mlog" "hotgo/internal/library/hggen/internal/utility/utils" diff --git a/server/internal/library/hggen/internal/cmd/genctrl/genctrl_generate_sdk.go b/server/internal/library/hggen/internal/cmd/genctrl/genctrl_generate_sdk.go index 8881bac..17bb64a 100644 --- a/server/internal/library/hggen/internal/cmd/genctrl/genctrl_generate_sdk.go +++ b/server/internal/library/hggen/internal/cmd/genctrl/genctrl_generate_sdk.go @@ -15,6 +15,7 @@ import ( "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gstr" + "hotgo/internal/library/hggen/internal/consts" "hotgo/internal/library/hggen/internal/utility/mlog" ) @@ -179,6 +180,7 @@ func (c *apiSdkGenerator) doGenerateSdkImplementer( "{Version}": item.Version, "{MethodName}": item.MethodName, "{ImplementerName}": implementerName, + "{MethodComment}": item.GetComment(), })) implementerFileContent += "\n" } diff --git a/server/internal/library/hggen/internal/cmd/gendao/gendao.go b/server/internal/library/hggen/internal/cmd/gendao/gendao.go index 8157777..3a80122 100644 --- a/server/internal/library/hggen/internal/cmd/gendao/gendao.go +++ b/server/internal/library/hggen/internal/cmd/gendao/gendao.go @@ -14,115 +14,77 @@ import ( "golang.org/x/mod/modfile" "github.com/gogf/gf/v2/container/garray" + "github.com/gogf/gf/v2/container/gset" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gproc" "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/os/gview" + "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gstr" - "github.com/gogf/gf/v2/util/gtag" - "hotgo/internal/library/hggen/internal/utility/utils" "hotgo/internal/library/hggen/internal/utility/mlog" + "hotgo/internal/library/hggen/internal/utility/utils" ) -const ( - CGenDaoConfig = `gfcli.gen.dao` - CGenDaoUsage = `gf gen dao [OPTION]` - CGenDaoBrief = `automatically generate go files for dao/do/entity` - CGenDaoEg = ` -gf gen dao -gf gen dao -l "mysql:root:12345678@tcp(127.0.0.1:3306)/test" -gf gen dao -p ./model -g user-center -t user,user_detail,user_login -gf gen dao -r user_ -` +type ( + CGenDao struct{} + CGenDaoInput struct { + g.Meta `name:"dao" config:"{CGenDaoConfig}" usage:"{CGenDaoUsage}" brief:"{CGenDaoBrief}" eg:"{CGenDaoEg}" ad:"{CGenDaoAd}"` + Path string `name:"path" short:"p" brief:"{CGenDaoBriefPath}" d:"internal"` + Link string `name:"link" short:"l" brief:"{CGenDaoBriefLink}"` + Tables string `name:"tables" short:"t" brief:"{CGenDaoBriefTables}"` + TablesEx string `name:"tablesEx" short:"x" brief:"{CGenDaoBriefTablesEx}"` + ShardingPattern []string `name:"shardingPattern" short:"sp" brief:"{CGenDaoBriefShardingPattern}"` + Group string `name:"group" short:"g" brief:"{CGenDaoBriefGroup}" d:"default"` + Prefix string `name:"prefix" short:"f" brief:"{CGenDaoBriefPrefix}"` + 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"` + ImportPrefix string `name:"importPrefix" short:"i" brief:"{CGenDaoBriefImportPrefix}"` + DaoPath string `name:"daoPath" short:"d" brief:"{CGenDaoBriefDaoPath}" d:"dao"` + DoPath string `name:"doPath" short:"o" brief:"{CGenDaoBriefDoPath}" d:"model/do"` + EntityPath string `name:"entityPath" short:"e" brief:"{CGenDaoBriefEntityPath}" d:"model/entity"` + TplDaoIndexPath string `name:"tplDaoIndexPath" short:"t1" brief:"{CGenDaoBriefTplDaoIndexPath}"` + TplDaoInternalPath string `name:"tplDaoInternalPath" short:"t2" brief:"{CGenDaoBriefTplDaoInternalPath}"` + TplDaoDoPath string `name:"tplDaoDoPath" short:"t3" brief:"{CGenDaoBriefTplDaoDoPathPath}"` + TplDaoEntityPath string `name:"tplDaoEntityPath" short:"t4" brief:"{CGenDaoBriefTplDaoEntityPath}"` + StdTime bool `name:"stdTime" short:"s" brief:"{CGenDaoBriefStdTime}" orphan:"true"` + WithTime bool `name:"withTime" short:"w" brief:"{CGenDaoBriefWithTime}" orphan:"true"` + GJsonSupport bool `name:"gJsonSupport" short:"n" brief:"{CGenDaoBriefGJsonSupport}" orphan:"true"` + OverwriteDao bool `name:"overwriteDao" short:"v" brief:"{CGenDaoBriefOverwriteDao}" orphan:"true"` + DescriptionTag bool `name:"descriptionTag" short:"c" brief:"{CGenDaoBriefDescriptionTag}" orphan:"true"` + NoJsonTag bool `name:"noJsonTag" short:"k" brief:"{CGenDaoBriefNoJsonTag}" orphan:"true"` + NoModelComment bool `name:"noModelComment" short:"m" brief:"{CGenDaoBriefNoModelComment}" orphan:"true"` + Clear bool `name:"clear" short:"a" brief:"{CGenDaoBriefClear}" orphan:"true"` - CGenDaoAd = ` -CONFIGURATION SUPPORT - Options are also supported by configuration file. - It's suggested using configuration file instead of command line arguments making producing. - The configuration node name is "gfcli.gen.dao", which also supports multiple databases, for example(config.yaml): - gfcli: - gen: - dao: - - link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test" - tables: "order,products" - jsonCase: "CamelLower" - - link: "mysql:root:12345678@tcp(127.0.0.1:3306)/primary" - path: "./my-app" - prefix: "primary_" - tables: "user, userDetail" - typeMapping: - decimal: - type: decimal.Decimal - import: github.com/shopspring/decimal - numeric: - type: string - fieldMapping: - table_name.field_name: - type: decimal.Decimal - import: github.com/shopspring/decimal -` - CGenDaoBriefPath = `directory path for generated files` - CGenDaoBriefLink = `database configuration, the same as the ORM configuration of GoFrame` - CGenDaoBriefTables = `generate models only for 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` - CGenDaoBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','` - CGenDaoBriefRemoveFieldPrefix = `remove specified prefix of the field, multiple prefix separated with ','` - CGenDaoBriefStdTime = `use time.Time from stdlib instead of gtime.Time for generated time/date fields of tables` - CGenDaoBriefWithTime = `add created time for auto produced go files` - CGenDaoBriefGJsonSupport = `use gJsonSupport to use *gjson.Json instead of string for generated json fields of tables` - CGenDaoBriefImportPrefix = `custom import prefix for generated go files` - CGenDaoBriefDaoPath = `directory path for storing generated dao files under path` - CGenDaoBriefDoPath = `directory path for storing generated do files under path` - CGenDaoBriefEntityPath = `directory path for storing generated entity files under path` - CGenDaoBriefOverwriteDao = `overwrite all dao files both inside/outside internal folder` - CGenDaoBriefModelFile = `custom file name for storing generated model content` - CGenDaoBriefModelFileForDao = `custom file name generating model for DAO operations like Where/Data. It's empty in default` - CGenDaoBriefDescriptionTag = `add comment to description tag for each field` - CGenDaoBriefNoJsonTag = `no json tag will be added for each field` - CGenDaoBriefNoModelComment = `no model comment will be added for each field` - CGenDaoBriefClear = `delete all generated go files that do not exist in database` - CGenDaoBriefTypeMapping = `custom local type mapping for generated struct attributes relevant to fields of table` - CGenDaoBriefFieldMapping = `custom local type mapping for generated struct attributes relevant to specific fields of table` - CGenDaoBriefGroup = ` -specifying the configuration group name of database for generated ORM instance, -it's not necessary and the default value is "default" -` - CGenDaoBriefJsonCase = ` -generated json tag case for model struct, cases are as follows: -| Case | Example | -|---------------- |--------------------| -| Camel | AnyKindOfString | -| CamelLower | anyKindOfString | default -| Snake | any_kind_of_string | -| SnakeScreaming | ANY_KIND_OF_STRING | -| SnakeFirstUpper | rgb_code_md5 | -| Kebab | any-kind-of-string | -| KebabScreaming | ANY-KIND-OF-STRING | -` - CGenDaoBriefTplDaoIndexPath = `template file path for dao index file` - CGenDaoBriefTplDaoInternalPath = `template file path for dao internal file` - CGenDaoBriefTplDaoDoPathPath = `template file path for dao do file` - CGenDaoBriefTplDaoEntityPath = `template file path for dao entity file` + TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenDaoBriefTypeMapping}" orphan:"true"` + FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenDaoBriefFieldMapping}" orphan:"true"` - tplVarTableName = `{TplTableName}` - tplVarTableNameCamelCase = `{TplTableNameCamelCase}` - tplVarTableNameCamelLowerCase = `{TplTableNameCamelLowerCase}` - tplVarPackageImports = `{TplPackageImports}` - tplVarImportPrefix = `{TplImportPrefix}` - tplVarStructDefine = `{TplStructDefine}` - tplVarColumnDefine = `{TplColumnDefine}` - tplVarColumnNames = `{TplColumnNames}` - tplVarGroupName = `{TplGroupName}` - tplVarDatetimeStr = `{TplDatetimeStr}` - tplVarCreatedAtDatetimeStr = `{TplCreatedAtDatetimeStr}` - tplVarPackageName = `{TplPackageName}` + // internal usage purpose. + genItems *CGenDaoInternalGenItems + } + CGenDaoOutput struct{} + + CGenDaoInternalInput struct { + CGenDaoInput + DB gdb.DB + TableNames []string + NewTableNames []string + ShardingTableSet *gset.StrSet + } + DBTableFieldName = string + DBFieldTypeName = string + CustomAttributeType struct { + Type string `brief:"custom attribute type name"` + Import string `brief:"custom import for this type"` + } ) var ( createdAt = gtime.Now() + tplView = gview.New() defaultTypeMapping = map[DBFieldTypeName]CustomAttributeType{ "decimal": { Type: "float64", @@ -139,97 +101,6 @@ var ( } ) -func init() { - gtag.Sets(g.MapStrStr{ - `CGenDaoConfig`: CGenDaoConfig, - `CGenDaoUsage`: CGenDaoUsage, - `CGenDaoBrief`: CGenDaoBrief, - `CGenDaoEg`: CGenDaoEg, - `CGenDaoAd`: CGenDaoAd, - `CGenDaoBriefPath`: CGenDaoBriefPath, - `CGenDaoBriefLink`: CGenDaoBriefLink, - `CGenDaoBriefTables`: CGenDaoBriefTables, - `CGenDaoBriefTablesEx`: CGenDaoBriefTablesEx, - `CGenDaoBriefPrefix`: CGenDaoBriefPrefix, - `CGenDaoBriefRemovePrefix`: CGenDaoBriefRemovePrefix, - `CGenDaoBriefRemoveFieldPrefix`: CGenDaoBriefRemoveFieldPrefix, - `CGenDaoBriefStdTime`: CGenDaoBriefStdTime, - `CGenDaoBriefWithTime`: CGenDaoBriefWithTime, - `CGenDaoBriefDaoPath`: CGenDaoBriefDaoPath, - `CGenDaoBriefDoPath`: CGenDaoBriefDoPath, - `CGenDaoBriefEntityPath`: CGenDaoBriefEntityPath, - `CGenDaoBriefGJsonSupport`: CGenDaoBriefGJsonSupport, - `CGenDaoBriefImportPrefix`: CGenDaoBriefImportPrefix, - `CGenDaoBriefOverwriteDao`: CGenDaoBriefOverwriteDao, - `CGenDaoBriefModelFile`: CGenDaoBriefModelFile, - `CGenDaoBriefModelFileForDao`: CGenDaoBriefModelFileForDao, - `CGenDaoBriefDescriptionTag`: CGenDaoBriefDescriptionTag, - `CGenDaoBriefNoJsonTag`: CGenDaoBriefNoJsonTag, - `CGenDaoBriefNoModelComment`: CGenDaoBriefNoModelComment, - `CGenDaoBriefClear`: CGenDaoBriefClear, - `CGenDaoBriefTypeMapping`: CGenDaoBriefTypeMapping, - `CGenDaoBriefFieldMapping`: CGenDaoBriefFieldMapping, - `CGenDaoBriefGroup`: CGenDaoBriefGroup, - `CGenDaoBriefJsonCase`: CGenDaoBriefJsonCase, - `CGenDaoBriefTplDaoIndexPath`: CGenDaoBriefTplDaoIndexPath, - `CGenDaoBriefTplDaoInternalPath`: CGenDaoBriefTplDaoInternalPath, - `CGenDaoBriefTplDaoDoPathPath`: CGenDaoBriefTplDaoDoPathPath, - `CGenDaoBriefTplDaoEntityPath`: CGenDaoBriefTplDaoEntityPath, - }) -} - -type ( - CGenDao struct{} - CGenDaoInput struct { - g.Meta `name:"dao" config:"{CGenDaoConfig}" usage:"{CGenDaoUsage}" brief:"{CGenDaoBrief}" eg:"{CGenDaoEg}" ad:"{CGenDaoAd}"` - Path string `name:"path" short:"p" brief:"{CGenDaoBriefPath}" d:"internal"` - Link string `name:"link" short:"l" brief:"{CGenDaoBriefLink}"` - Tables string `name:"tables" short:"t" brief:"{CGenDaoBriefTables}"` - TablesEx string `name:"tablesEx" short:"x" brief:"{CGenDaoBriefTablesEx}"` - Group string `name:"group" short:"g" brief:"{CGenDaoBriefGroup}" d:"default"` - Prefix string `name:"prefix" short:"f" brief:"{CGenDaoBriefPrefix}"` - 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"` - ImportPrefix string `name:"importPrefix" short:"i" brief:"{CGenDaoBriefImportPrefix}"` - DaoPath string `name:"daoPath" short:"d" brief:"{CGenDaoBriefDaoPath}" d:"dao"` - DoPath string `name:"doPath" short:"o" brief:"{CGenDaoBriefDoPath}" d:"model/do"` - EntityPath string `name:"entityPath" short:"e" brief:"{CGenDaoBriefEntityPath}" d:"model/entity"` - TplDaoIndexPath string `name:"tplDaoIndexPath" short:"t1" brief:"{CGenDaoBriefTplDaoIndexPath}"` - TplDaoInternalPath string `name:"tplDaoInternalPath" short:"t2" brief:"{CGenDaoBriefTplDaoInternalPath}"` - TplDaoDoPath string `name:"tplDaoDoPath" short:"t3" brief:"{CGenDaoBriefTplDaoDoPathPath}"` - TplDaoEntityPath string `name:"tplDaoEntityPath" short:"t4" brief:"{CGenDaoBriefTplDaoEntityPath}"` - StdTime bool `name:"stdTime" short:"s" brief:"{CGenDaoBriefStdTime}" orphan:"true"` - WithTime bool `name:"withTime" short:"w" brief:"{CGenDaoBriefWithTime}" orphan:"true"` - GJsonSupport bool `name:"gJsonSupport" short:"n" brief:"{CGenDaoBriefGJsonSupport}" orphan:"true"` - OverwriteDao bool `name:"overwriteDao" short:"v" brief:"{CGenDaoBriefOverwriteDao}" orphan:"true"` - DescriptionTag bool `name:"descriptionTag" short:"c" brief:"{CGenDaoBriefDescriptionTag}" orphan:"true"` - NoJsonTag bool `name:"noJsonTag" short:"k" brief:"{CGenDaoBriefNoJsonTag}" orphan:"true"` - NoModelComment bool `name:"noModelComment" short:"m" brief:"{CGenDaoBriefNoModelComment}" orphan:"true"` - Clear bool `name:"clear" short:"a" brief:"{CGenDaoBriefClear}" orphan:"true"` - - TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenDaoBriefTypeMapping}" orphan:"true"` - FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenDaoBriefFieldMapping}" orphan:"true"` - - // internal usage purpose. - genItems *CGenDaoInternalGenItems - } - CGenDaoOutput struct{} - - CGenDaoInternalInput struct { - CGenDaoInput - DB gdb.DB - TableNames []string - NewTableNames []string - } - DBTableFieldName = string - DBFieldTypeName = string - CustomAttributeType struct { - Type string `brief:"custom attribute type name"` - Import string `brief:"custom import for this type"` - } -) - func (c CGenDao) Dao(ctx context.Context, in CGenDaoInput) (out *CGenDaoOutput, err error) { in.genItems = newCGenDaoInternalGenItems() if in.Link != "" { @@ -278,9 +149,12 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) { // It uses user passed database configuration. if in.Link != "" { var tempGroup = gtime.TimestampNanoStr() - gdb.AddConfigNode(tempGroup, gdb.ConfigNode{ + err = gdb.AddConfigNode(tempGroup, gdb.ConfigNode{ Link: in.Link, }) + if err != nil { + mlog.Fatalf(`database configuration failed: %+v`, err) + } if db, err = gdb.Instance(tempGroup); err != nil { mlog.Fatalf(`database initialization failed: %+v`, err) } @@ -321,24 +195,51 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) { } // Generating dao & model go files one by one according to given table name. - newTableNames := make([]string, len(tableNames)) + var ( + newTableNames = make([]string, len(tableNames)) + shardingNewTableSet = gset.NewStrSet() + ) for i, tableName := range tableNames { newTableName := tableName for _, v := range removePrefixArray { newTableName = gstr.TrimLeftStr(newTableName, v, 1) } + if len(in.ShardingPattern) > 0 { + for _, pattern := range in.ShardingPattern { + var ( + match []string + regPattern = gstr.Replace(pattern, "?", `(.+)`) + ) + match, err = gregex.MatchString(regPattern, newTableName) + if err != nil { + mlog.Fatalf(`invalid sharding pattern "%s": %+v`, pattern, err) + } + if len(match) < 2 { + continue + } + newTableName = gstr.Replace(pattern, "?", "") + newTableName = gstr.Trim(newTableName, `_.-`) + if shardingNewTableSet.Contains(newTableName) { + tableNames[i] = "" + continue + } + shardingNewTableSet.Add(newTableName) + } + } newTableName = in.Prefix + newTableName newTableNames[i] = newTableName } + tableNames = garray.NewStrArrayFrom(tableNames).FilterEmpty().Slice() in.genItems.Scale() // Dao: index and internal. generateDao(ctx, CGenDaoInternalInput{ - CGenDaoInput: in, - DB: db, - TableNames: tableNames, - NewTableNames: newTableNames, + CGenDaoInput: in, + DB: db, + TableNames: tableNames, + NewTableNames: newTableNames, + ShardingTableSet: shardingNewTableSet, }) // Do. generateDo(ctx, CGenDaoInternalInput{ @@ -411,13 +312,15 @@ func getImportPartContent(ctx context.Context, source string, isDo bool, appendI return packageImportsStr } -func replaceDefaultVar(in CGenDaoInternalInput, origin string) string { - var tplCreatedAtDatetimeStr string - var tplDatetimeStr string = createdAt.String() +func assignDefaultVar(view *gview.View, in CGenDaoInternalInput) { + var ( + tplCreatedAtDatetimeStr string + tplDatetimeStr = createdAt.String() + ) if in.WithTime { tplCreatedAtDatetimeStr = fmt.Sprintf(`Created at %s`, tplDatetimeStr) } - return gstr.ReplaceByMap(origin, g.MapStrStr{ + view.Assigns(g.Map{ tplVarDatetimeStr: tplDatetimeStr, tplVarCreatedAtDatetimeStr: tplCreatedAtDatetimeStr, }) diff --git a/server/internal/library/hggen/internal/cmd/gendao/gendao_dao.go b/server/internal/library/hggen/internal/cmd/gendao/gendao_dao.go index 2b152fa..1e784cb 100644 --- a/server/internal/library/hggen/internal/cmd/gendao/gendao_dao.go +++ b/server/internal/library/hggen/internal/cmd/gendao/gendao_dao.go @@ -18,6 +18,7 @@ import ( "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gfile" + "github.com/gogf/gf/v2/os/gview" "github.com/gogf/gf/v2/text/gstr" "hotgo/internal/library/hggen/internal/consts" @@ -32,22 +33,30 @@ func generateDao(ctx context.Context, in CGenDaoInternalInput) { ) in.genItems.AppendDirPath(dirPathDao) for i := 0; i < len(in.TableNames); i++ { + var ( + realTableName = in.TableNames[i] + newTableName = in.NewTableNames[i] + ) generateDaoSingle(ctx, generateDaoSingleInput{ CGenDaoInternalInput: in, - TableName: in.TableNames[i], - NewTableName: in.NewTableNames[i], + TableName: realTableName, + NewTableName: newTableName, DirPathDao: dirPathDao, DirPathDaoInternal: dirPathDaoInternal, + IsSharding: in.ShardingTableSet.Contains(newTableName), }) } } type generateDaoSingleInput struct { CGenDaoInternalInput - TableName string // TableName specifies the table name of the table. - NewTableName string // NewTableName specifies the prefix-stripped name of the table. + // TableName specifies the table name of the table. + TableName string + // NewTableName specifies the prefix-stripped or custom edited name of the table. + NewTableName string DirPathDao string DirPathDaoInternal string + IsSharding bool } // generateDaoSingle generates the dao and model content of given table. @@ -109,17 +118,26 @@ func generateDaoIndex(in generateDaoIndexInput) { // It should add path to result slice whenever it would generate the path file or not. in.genItems.AppendGeneratedFilePath(path) if in.OverwriteDao || !gfile.Exists(path) { - indexContent := gstr.ReplaceByMap( - getTemplateFromPathOrDefault(in.TplDaoIndexPath, consts.TemplateGenDaoIndexContent), - g.MapStrStr{ - tplVarImportPrefix: in.ImportPrefix, - tplVarTableName: in.TableName, - tplVarTableNameCamelCase: in.TableNameCamelCase, - tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase, - tplVarPackageName: filepath.Base(in.DaoPath), - }) - indexContent = replaceDefaultVar(in.CGenDaoInternalInput, indexContent) - if err := gfile.PutContents(path, strings.TrimSpace(indexContent)); err != nil { + var ( + ctx = context.Background() + tplContent = getTemplateFromPathOrDefault( + in.TplDaoIndexPath, consts.TemplateGenDaoIndexContent, + ) + ) + tplView.ClearAssigns() + tplView.Assigns(gview.Params{ + tplVarTableSharding: in.IsSharding, + tplVarImportPrefix: in.ImportPrefix, + tplVarTableName: in.TableName, + tplVarTableNameCamelCase: in.TableNameCamelCase, + tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase, + tplVarPackageName: filepath.Base(in.DaoPath), + }) + indexContent, err := tplView.ParseContent(ctx, tplContent) + if err != nil { + mlog.Fatalf("parsing template content failed: %v", err) + } + if err = gfile.PutContents(path, strings.TrimSpace(indexContent)); err != nil { mlog.Fatalf("writing content to '%s' failed: %v", path, err) } else { utils.GoFmt(path) @@ -138,20 +156,29 @@ type generateDaoInternalInput struct { } func generateDaoInternal(in generateDaoInternalInput) { + var ( + ctx = context.Background() + removeFieldPrefixArray = gstr.SplitAndTrim(in.RemoveFieldPrefix, ",") + tplContent = getTemplateFromPathOrDefault( + in.TplDaoInternalPath, consts.TemplateGenDaoInternalContent, + ) + ) + tplView.ClearAssigns() + tplView.Assigns(gview.Params{ + tplVarImportPrefix: in.ImportPrefix, + tplVarTableName: in.TableName, + tplVarGroupName: in.Group, + tplVarTableNameCamelCase: in.TableNameCamelCase, + tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase, + tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(in.FieldMap, removeFieldPrefixArray)), + tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(in.FieldMap, removeFieldPrefixArray)), + }) + assignDefaultVar(tplView, in.CGenDaoInternalInput) + modelContent, err := tplView.ParseContent(ctx, tplContent) + if err != nil { + mlog.Fatalf("parsing template content failed: %v", err) + } path := filepath.FromSlash(gfile.Join(in.DirPathDaoInternal, in.FileName+".go")) - removeFieldPrefixArray := gstr.SplitAndTrim(in.RemoveFieldPrefix, ",") - modelContent := gstr.ReplaceByMap( - getTemplateFromPathOrDefault(in.TplDaoInternalPath, consts.TemplateGenDaoInternalContent), - g.MapStrStr{ - tplVarImportPrefix: in.ImportPrefix, - tplVarTableName: in.TableName, - tplVarGroupName: in.Group, - tplVarTableNameCamelCase: in.TableNameCamelCase, - tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase, - tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(in.FieldMap, removeFieldPrefixArray)), - tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(in.FieldMap, removeFieldPrefixArray)), - }) - modelContent = replaceDefaultVar(in.CGenDaoInternalInput, modelContent) in.genItems.AppendGeneratedFilePath(path) if err := gfile.PutContents(path, strings.TrimSpace(modelContent)); err != nil { mlog.Fatalf("writing content to '%s' failed: %v", path, err) diff --git a/server/internal/library/hggen/internal/cmd/gendao/gendao_do.go b/server/internal/library/hggen/internal/cmd/gendao/gendao_do.go index fabb4e6..0d5f791 100644 --- a/server/internal/library/hggen/internal/cmd/gendao/gendao_do.go +++ b/server/internal/library/hggen/internal/cmd/gendao/gendao_do.go @@ -12,8 +12,8 @@ import ( "path/filepath" "strings" - "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gfile" + "github.com/gogf/gf/v2/os/gview" "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gstr" @@ -78,16 +78,23 @@ func generateDo(ctx context.Context, in CGenDaoInternalInput) { func generateDoContent( ctx context.Context, in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string, ) string { - doContent := gstr.ReplaceByMap( - getTemplateFromPathOrDefault(in.TplDaoDoPath, consts.TemplateGenDaoDoContent), - g.MapStrStr{ - tplVarTableName: tableName, - tplVarPackageImports: getImportPartContent(ctx, structDefine, true, nil), - tplVarTableNameCamelCase: tableNameCamelCase, - tplVarStructDefine: structDefine, - tplVarPackageName: filepath.Base(in.DoPath), - }, + var ( + tplContent = getTemplateFromPathOrDefault( + in.TplDaoDoPath, consts.TemplateGenDaoDoContent, + ) ) - doContent = replaceDefaultVar(in, doContent) + tplView.ClearAssigns() + tplView.Assigns(gview.Params{ + tplVarTableName: tableName, + tplVarPackageImports: getImportPartContent(ctx, structDefine, true, nil), + tplVarTableNameCamelCase: tableNameCamelCase, + tplVarStructDefine: structDefine, + tplVarPackageName: filepath.Base(in.DoPath), + }) + assignDefaultVar(tplView, in) + doContent, err := tplView.ParseContent(ctx, tplContent) + if err != nil { + mlog.Fatalf("parsing template content failed: %v", err) + } return doContent } diff --git a/server/internal/library/hggen/internal/cmd/gendao/gendao_entity.go b/server/internal/library/hggen/internal/cmd/gendao/gendao_entity.go index d9f8675..5eeafe7 100644 --- a/server/internal/library/hggen/internal/cmd/gendao/gendao_entity.go +++ b/server/internal/library/hggen/internal/cmd/gendao/gendao_entity.go @@ -11,8 +11,8 @@ import ( "path/filepath" "strings" - "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gfile" + "github.com/gogf/gf/v2/os/gview" "github.com/gogf/gf/v2/text/gstr" "hotgo/internal/library/hggen/internal/consts" @@ -63,16 +63,23 @@ func generateEntity(ctx context.Context, in CGenDaoInternalInput) { func generateEntityContent( ctx context.Context, in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string, appendImports []string, ) string { - entityContent := gstr.ReplaceByMap( - getTemplateFromPathOrDefault(in.TplDaoEntityPath, consts.TemplateGenDaoEntityContent), - g.MapStrStr{ - tplVarTableName: tableName, - tplVarPackageImports: getImportPartContent(ctx, structDefine, false, appendImports), - tplVarTableNameCamelCase: tableNameCamelCase, - tplVarStructDefine: structDefine, - tplVarPackageName: filepath.Base(in.EntityPath), - }, + var ( + tplContent = getTemplateFromPathOrDefault( + in.TplDaoEntityPath, consts.TemplateGenDaoEntityContent, + ) ) - entityContent = replaceDefaultVar(in, entityContent) + tplView.ClearAssigns() + tplView.Assigns(gview.Params{ + tplVarTableName: tableName, + tplVarPackageImports: getImportPartContent(ctx, structDefine, false, appendImports), + tplVarTableNameCamelCase: tableNameCamelCase, + tplVarStructDefine: structDefine, + tplVarPackageName: filepath.Base(in.EntityPath), + }) + assignDefaultVar(tplView, in) + entityContent, err := tplView.ParseContent(ctx, tplContent) + if err != nil { + mlog.Fatalf("parsing template content failed: %v", err) + } return entityContent } diff --git a/server/internal/library/hggen/internal/cmd/gendao/gendao_gen_item.go b/server/internal/library/hggen/internal/cmd/gendao/gendao_gen_item.go index 09fa7fe..fcb7bf9 100644 --- a/server/internal/library/hggen/internal/cmd/gendao/gendao_gen_item.go +++ b/server/internal/library/hggen/internal/cmd/gendao/gendao_gen_item.go @@ -38,14 +38,14 @@ func (i *CGenDaoInternalGenItems) SetClear(clear bool) { i.Items[i.index].Clear = clear } -func (i CGenDaoInternalGenItems) AppendDirPath(storageDirPath string) { +func (i *CGenDaoInternalGenItems) AppendDirPath(storageDirPath string) { i.Items[i.index].StorageDirPaths = append( i.Items[i.index].StorageDirPaths, storageDirPath, ) } -func (i CGenDaoInternalGenItems) AppendGeneratedFilePath(generatedFilePath string) { +func (i *CGenDaoInternalGenItems) AppendGeneratedFilePath(generatedFilePath string) { i.Items[i.index].GeneratedFilePaths = append( i.Items[i.index].GeneratedFilePaths, generatedFilePath, diff --git a/server/internal/library/hggen/internal/cmd/gendao/gendao_tag.go b/server/internal/library/hggen/internal/cmd/gendao/gendao_tag.go new file mode 100644 index 0000000..0487184 --- /dev/null +++ b/server/internal/library/hggen/internal/cmd/gendao/gendao_tag.go @@ -0,0 +1,149 @@ +// 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 gendao + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/util/gtag" +) + +const ( + CGenDaoConfig = `gfcli.gen.dao` + CGenDaoUsage = `gf gen dao [OPTION]` + CGenDaoBrief = `automatically generate go files for dao/do/entity` + CGenDaoEg = ` +gf gen dao +gf gen dao -l "mysql:root:12345678@tcp(127.0.0.1:3306)/test" +gf gen dao -p ./model -g user-center -t user,user_detail,user_login +gf gen dao -r user_ +` + + CGenDaoAd = ` +CONFIGURATION SUPPORT + Options are also supported by configuration file. + It's suggested using configuration file instead of command line arguments making producing. + The configuration node name is "gfcli.gen.dao", which also supports multiple databases, for example(config.yaml): + gfcli: + gen: + dao: + - link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test" + tables: "order,products" + jsonCase: "CamelLower" + - link: "mysql:root:12345678@tcp(127.0.0.1:3306)/primary" + path: "./my-app" + prefix: "primary_" + tables: "user, userDetail" + typeMapping: + decimal: + type: decimal.Decimal + import: github.com/shopspring/decimal + numeric: + type: string + fieldMapping: + table_name.field_name: + type: decimal.Decimal + import: github.com/shopspring/decimal +` + CGenDaoBriefPath = `directory path for generated files` + CGenDaoBriefLink = `database configuration, the same as the ORM configuration of GoFrame` + CGenDaoBriefTables = `generate models only for 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` + CGenDaoBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','` + CGenDaoBriefRemoveFieldPrefix = `remove specified prefix of the field, multiple prefix separated with ','` + CGenDaoBriefStdTime = `use time.Time from stdlib instead of gtime.Time for generated time/date fields of tables` + CGenDaoBriefWithTime = `add created time for auto produced go files` + CGenDaoBriefGJsonSupport = `use gJsonSupport to use *gjson.Json instead of string for generated json fields of tables` + CGenDaoBriefImportPrefix = `custom import prefix for generated go files` + CGenDaoBriefDaoPath = `directory path for storing generated dao files under path` + CGenDaoBriefDoPath = `directory path for storing generated do files under path` + CGenDaoBriefEntityPath = `directory path for storing generated entity files under path` + CGenDaoBriefOverwriteDao = `overwrite all dao files both inside/outside internal folder` + CGenDaoBriefModelFile = `custom file name for storing generated model content` + CGenDaoBriefModelFileForDao = `custom file name generating model for DAO operations like Where/Data. It's empty in default` + CGenDaoBriefDescriptionTag = `add comment to description tag for each field` + CGenDaoBriefNoJsonTag = `no json tag will be added for each field` + CGenDaoBriefNoModelComment = `no model comment will be added for each field` + CGenDaoBriefClear = `delete all generated go files that do not exist in database` + CGenDaoBriefTypeMapping = `custom local type mapping for generated struct attributes relevant to fields of table` + CGenDaoBriefFieldMapping = `custom local type mapping for generated struct attributes relevant to specific fields of table` + CGenDaoBriefShardingPattern = `sharding pattern for table name, e.g. "users_?" will be replace tables "users_001,users_002,..." to "users" dao` + CGenDaoBriefGroup = ` +specifying the configuration group name of database for generated ORM instance, +it's not necessary and the default value is "default" +` + CGenDaoBriefJsonCase = ` +generated json tag case for model struct, cases are as follows: +| Case | Example | +|---------------- |--------------------| +| Camel | AnyKindOfString | +| CamelLower | anyKindOfString | default +| Snake | any_kind_of_string | +| SnakeScreaming | ANY_KIND_OF_STRING | +| SnakeFirstUpper | rgb_code_md5 | +| Kebab | any-kind-of-string | +| KebabScreaming | ANY-KIND-OF-STRING | +` + CGenDaoBriefTplDaoIndexPath = `template file path for dao index file` + CGenDaoBriefTplDaoInternalPath = `template file path for dao internal file` + CGenDaoBriefTplDaoDoPathPath = `template file path for dao do file` + CGenDaoBriefTplDaoEntityPath = `template file path for dao entity file` + + tplVarTableName = `TplTableName` + tplVarTableNameCamelCase = `TplTableNameCamelCase` + tplVarTableNameCamelLowerCase = `TplTableNameCamelLowerCase` + tplVarTableSharding = `TplTableSharding` + tplVarPackageImports = `TplPackageImports` + tplVarImportPrefix = `TplImportPrefix` + tplVarStructDefine = `TplStructDefine` + tplVarColumnDefine = `TplColumnDefine` + tplVarColumnNames = `TplColumnNames` + tplVarGroupName = `TplGroupName` + tplVarDatetimeStr = `TplDatetimeStr` + tplVarCreatedAtDatetimeStr = `TplCreatedAtDatetimeStr` + tplVarPackageName = `TplPackageName` +) + +func init() { + gtag.Sets(g.MapStrStr{ + `CGenDaoConfig`: CGenDaoConfig, + `CGenDaoUsage`: CGenDaoUsage, + `CGenDaoBrief`: CGenDaoBrief, + `CGenDaoEg`: CGenDaoEg, + `CGenDaoAd`: CGenDaoAd, + `CGenDaoBriefPath`: CGenDaoBriefPath, + `CGenDaoBriefLink`: CGenDaoBriefLink, + `CGenDaoBriefTables`: CGenDaoBriefTables, + `CGenDaoBriefTablesEx`: CGenDaoBriefTablesEx, + `CGenDaoBriefPrefix`: CGenDaoBriefPrefix, + `CGenDaoBriefRemovePrefix`: CGenDaoBriefRemovePrefix, + `CGenDaoBriefRemoveFieldPrefix`: CGenDaoBriefRemoveFieldPrefix, + `CGenDaoBriefStdTime`: CGenDaoBriefStdTime, + `CGenDaoBriefWithTime`: CGenDaoBriefWithTime, + `CGenDaoBriefDaoPath`: CGenDaoBriefDaoPath, + `CGenDaoBriefDoPath`: CGenDaoBriefDoPath, + `CGenDaoBriefEntityPath`: CGenDaoBriefEntityPath, + `CGenDaoBriefGJsonSupport`: CGenDaoBriefGJsonSupport, + `CGenDaoBriefImportPrefix`: CGenDaoBriefImportPrefix, + `CGenDaoBriefOverwriteDao`: CGenDaoBriefOverwriteDao, + `CGenDaoBriefModelFile`: CGenDaoBriefModelFile, + `CGenDaoBriefModelFileForDao`: CGenDaoBriefModelFileForDao, + `CGenDaoBriefDescriptionTag`: CGenDaoBriefDescriptionTag, + `CGenDaoBriefNoJsonTag`: CGenDaoBriefNoJsonTag, + `CGenDaoBriefNoModelComment`: CGenDaoBriefNoModelComment, + `CGenDaoBriefClear`: CGenDaoBriefClear, + `CGenDaoBriefTypeMapping`: CGenDaoBriefTypeMapping, + `CGenDaoBriefFieldMapping`: CGenDaoBriefFieldMapping, + `CGenDaoBriefShardingPattern`: CGenDaoBriefShardingPattern, + `CGenDaoBriefGroup`: CGenDaoBriefGroup, + `CGenDaoBriefJsonCase`: CGenDaoBriefJsonCase, + `CGenDaoBriefTplDaoIndexPath`: CGenDaoBriefTplDaoIndexPath, + `CGenDaoBriefTplDaoInternalPath`: CGenDaoBriefTplDaoInternalPath, + `CGenDaoBriefTplDaoDoPathPath`: CGenDaoBriefTplDaoDoPathPath, + `CGenDaoBriefTplDaoEntityPath`: CGenDaoBriefTplDaoEntityPath, + }) +} diff --git a/server/internal/library/hggen/internal/cmd/genenums/genenums.go b/server/internal/library/hggen/internal/cmd/genenums/genenums.go index 962818f..18a34cd 100644 --- a/server/internal/library/hggen/internal/cmd/genenums/genenums.go +++ b/server/internal/library/hggen/internal/cmd/genenums/genenums.go @@ -8,12 +8,14 @@ package genenums import ( "context" + "golang.org/x/tools/go/packages" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gtag" + "hotgo/internal/library/hggen/internal/consts" "hotgo/internal/library/hggen/internal/utility/mlog" ) @@ -22,8 +24,8 @@ type ( CGenEnums struct{} CGenEnumsInput struct { g.Meta `name:"enums" config:"{CGenEnumsConfig}" brief:"{CGenEnumsBrief}" eg:"{CGenEnumsEg}"` - Src string `name:"src" short:"s" dc:"source folder path to be parsed" d:"."` - Path string `name:"path" short:"p" dc:"output go file path storing enums content" d:"internal/boot/boot_enums.go"` + Src string `name:"src" short:"s" dc:"source folder path to be parsed" d:"api"` + Path string `name:"path" short:"p" dc:"output go file path storing enums content" d:"internal/packed/packed_enums.go"` Prefixes []string `name:"prefixes" short:"x" dc:"only exports packages that starts with specified prefixes"` } CGenEnumsOutput struct{} @@ -34,8 +36,8 @@ const ( CGenEnumsBrief = `parse go files in current project and generate enums go file` CGenEnumsEg = ` gf gen enums -gf gen enums -p internal/boot/boot_enums.go -gf gen enums -p internal/boot/boot_enums.go -s . +gf gen enums -p internal/packed/packed_enums.go +gf gen enums -p internal/packed/packed_enums.go -s . gf gen enums -x github.com/gogf ` ) diff --git a/server/internal/library/hggen/internal/cmd/genenums/genenums_parser.go b/server/internal/library/hggen/internal/cmd/genenums/genenums_parser.go index 2cacf95..21b9f96 100644 --- a/server/internal/library/hggen/internal/cmd/genenums/genenums_parser.go +++ b/server/internal/library/hggen/internal/cmd/genenums/genenums_parser.go @@ -9,6 +9,7 @@ package genenums import ( "go/constant" "go/types" + "golang.org/x/tools/go/packages" "github.com/gogf/gf/v2/encoding/gjson" diff --git a/server/internal/library/hggen/internal/cmd/genpb/genpb.go b/server/internal/library/hggen/internal/cmd/genpb/genpb.go index 5139dc2..da4da07 100644 --- a/server/internal/library/hggen/internal/cmd/genpb/genpb.go +++ b/server/internal/library/hggen/internal/cmd/genpb/genpb.go @@ -13,6 +13,7 @@ import ( "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gproc" "github.com/gogf/gf/v2/util/gtag" + "hotgo/internal/library/hggen/internal/utility/mlog" ) diff --git a/server/internal/library/hggen/internal/cmd/genpb/genpb_controller.go b/server/internal/library/hggen/internal/cmd/genpb/genpb_controller.go index f29ec5b..205e0c4 100644 --- a/server/internal/library/hggen/internal/cmd/genpb/genpb_controller.go +++ b/server/internal/library/hggen/internal/cmd/genpb/genpb_controller.go @@ -15,6 +15,7 @@ import ( "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gstr" + "hotgo/internal/library/hggen/internal/utility/utils" ) diff --git a/server/internal/library/hggen/internal/cmd/genpb/genpb_tag.go b/server/internal/library/hggen/internal/cmd/genpb/genpb_tag.go index 6283f6a..2768dcd 100644 --- a/server/internal/library/hggen/internal/cmd/genpb/genpb_tag.go +++ b/server/internal/library/hggen/internal/cmd/genpb/genpb_tag.go @@ -16,6 +16,7 @@ import ( "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" + "hotgo/internal/library/hggen/internal/utility/utils" ) @@ -71,6 +72,10 @@ func (c CGenPb) doTagReplacement(ctx context.Context, content string) (string, e if !lineTagMap.IsEmpty() { tagContent := c.listMapToStructTag(lineTagMap) lineTagMap.Clear() + // If already have it, don't add it anymore + if gstr.Contains(gstr.StrTill(line, "` //"), tagContent) { + continue + } line, _ = gregex.ReplaceString("`(.+)`", fmt.Sprintf("`$1 %s`", tagContent), line) } lines[index] = line diff --git a/server/internal/library/hggen/internal/cmd/genpbentity/genpbentity.go b/server/internal/library/hggen/internal/cmd/genpbentity/genpbentity.go index d4b8022..6320297 100644 --- a/server/internal/library/hggen/internal/cmd/genpbentity/genpbentity.go +++ b/server/internal/library/hggen/internal/cmd/genpbentity/genpbentity.go @@ -11,11 +11,13 @@ import ( "context" "fmt" "path/filepath" + "regexp" "strings" "github.com/olekukonko/tablewriter" - "hotgo/internal/library/hggen/internal/utility/utils" + "github.com/gogf/gf/v2/container/garray" + "github.com/gogf/gf/v2/container/gset" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" @@ -25,8 +27,10 @@ import ( "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gtag" + "hotgo/internal/library/hggen/internal/consts" "hotgo/internal/library/hggen/internal/utility/mlog" + "hotgo/internal/library/hggen/internal/utility/utils" ) type ( @@ -35,14 +39,19 @@ type ( g.Meta `name:"pbentity" config:"{CGenPbEntityConfig}" brief:"{CGenPbEntityBrief}" eg:"{CGenPbEntityEg}" ad:"{CGenPbEntityAd}"` Path string `name:"path" short:"p" brief:"{CGenPbEntityBriefPath}" d:"manifest/protobuf/pbentity"` Package string `name:"package" short:"k" brief:"{CGenPbEntityBriefPackage}"` + GoPackage string `name:"goPackage" short:"g" brief:"{CGenPbEntityBriefGoPackage}"` Link string `name:"link" short:"l" brief:"{CGenPbEntityBriefLink}"` Tables string `name:"tables" short:"t" brief:"{CGenPbEntityBriefTables}"` Prefix string `name:"prefix" short:"f" brief:"{CGenPbEntityBriefPrefix}"` RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenPbEntityBriefRemovePrefix}"` RemoveFieldPrefix string `name:"removeFieldPrefix" short:"rf" brief:"{CGenPbEntityBriefRemoveFieldPrefix}"` + TablesEx string `name:"tablesEx" short:"x" brief:"{CGenDaoBriefTablesEx}"` NameCase string `name:"nameCase" short:"n" brief:"{CGenPbEntityBriefNameCase}" d:"Camel"` JsonCase string `name:"jsonCase" short:"j" brief:"{CGenPbEntityBriefJsonCase}" d:"none"` Option string `name:"option" short:"o" brief:"{CGenPbEntityBriefOption}"` + + TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenPbEntityBriefTypeMapping}" orphan:"true"` + FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenPbEntityBriefFieldMapping}" orphan:"true"` } CGenPbEntityOutput struct{} @@ -52,6 +61,13 @@ type ( TableName string // TableName specifies the table name of the table. NewTableName string // NewTableName specifies the prefix-stripped name of the table. } + + DBTableFieldName = string + DBFieldTypeName = string + CustomAttributeType struct { + Type string `brief:"custom attribute type name"` + Import string `brief:"custom import for this type"` + } ) const ( @@ -69,7 +85,7 @@ gf gen pbentity -r user_ CGenPbEntityAd = ` CONFIGURATION SUPPORT Options are also supported by configuration file. - It's suggested using configuration file instead of command line arguments making producing. + It's suggested using configuration file instead of command line arguments making producing. The configuration node name is "gf.gen.pbentity", which also supports multiple databases, for example(config.yaml): gfcli: gen: @@ -88,13 +104,22 @@ CONFIGURATION SUPPORT option go_package = "protobuf/demos"; option java_package = "protobuf/demos"; option php_namespace = "protobuf/demos"; + typeMapping: + json: + type: google.protobuf.Value + import: google/protobuf/struct.proto + jsonb: + type: google.protobuf.Value + import: google/protobuf/struct.proto ` CGenPbEntityBriefPath = `directory path for generated files storing` CGenPbEntityBriefPackage = `package path for all entity proto files` + CGenPbEntityBriefGoPackage = `go package path for all entity proto files` CGenPbEntityBriefLink = `database configuration, the same as the ORM configuration of GoFrame` CGenPbEntityBriefTables = `generate models only for given tables, multiple table names separated with ','` CGenPbEntityBriefPrefix = `add specified prefix for all entity names and entity proto files` CGenPbEntityBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','` + CGenPbEntityBriefTablesEx = `generate all models exclude the specified tables, multiple prefix separated with ','` CGenPbEntityBriefRemoveFieldPrefix = `remove specified prefix of the field, multiple prefix separated with ','` CGenPbEntityBriefOption = `extra protobuf options` CGenPbEntityBriefGroup = ` @@ -106,7 +131,7 @@ it's not necessary and the default value is "default" case for message attribute names, default is "Camel": | Case | Example | |---------------- |--------------------| -| Camel | AnyKindOfString | +| Camel | AnyKindOfString | | CamelLower | anyKindOfString | default | Snake | any_kind_of_string | | SnakeScreaming | ANY_KIND_OF_STRING | @@ -119,8 +144,95 @@ case for message attribute names, default is "Camel": case for message json tag, cases are the same as "nameCase", default "CamelLower". set it to "none" to ignore json tag generating. ` + + CGenPbEntityBriefTypeMapping = `custom local type mapping for generated struct attributes relevant to fields of table` + CGenPbEntityBriefFieldMapping = `custom local type mapping for generated struct attributes relevant to specific fields of table` ) +var defaultTypeMapping = map[DBFieldTypeName]CustomAttributeType{ + // gdb.LocalTypeString + "string": { + Type: "string", + }, + // gdb.LocalTypeTime + // "time": { + // Type: "google.protobuf.Duration", + // Import: "google/protobuf/duration.proto", + // }, + // gdb.LocalTypeDate + "date": { + Type: "google.protobuf.Timestamp", + Import: "google/protobuf/timestamp.proto", + }, + // gdb.LocalTypeDatetime + "datetime": { + Type: "google.protobuf.Timestamp", + Import: "google/protobuf/timestamp.proto", + }, + // gdb.LocalTypeInt + "int": { + Type: "int32", + }, + // gdb.LocalTypeUint + "uint": { + Type: "uint32", + }, + // gdb.LocalTypeInt64 + "int64": { + Type: "int64", + }, + // gdb.LocalTypeUint64 + "uint64": { + Type: "uint64", + }, + // gdb.LocalTypeIntSlice + "[]int": { + Type: "repeated int32", + }, + // gdb.LocalTypeInt64Slice + "[]int64": { + Type: "repeated int64", + }, + // gdb.LocalTypeUint64Slice + "[]uint64": { + Type: "repeated uint64", + }, + // gdb.LocalTypeInt64Bytes + "int64-bytes": { + Type: "repeated int64", + }, + // gdb.LocalTypeUint64Bytes + "uint64-bytes": { + Type: "repeated uint64", + }, + // gdb.LocalTypeFloat32 + "float32": { + Type: "float", + }, + // gdb.LocalTypeFloat64 + "float64": { + Type: "double", + }, + // gdb.LocalTypeBytes + "[]byte": { + Type: "bytes", + }, + // gdb.LocalTypeBool + "bool": { + Type: "bool", + }, + // gdb.LocalTypeJson + // "json": { + // Type: "google.protobuf.Value", + // Import: "google/protobuf/struct.proto", + // }, + // gdb.LocalTypeJsonb + // "jsonb": { + // Type: "google.protobuf.Value", + // Import: "google/protobuf/struct.proto", + // }, +} + func init() { gtag.Sets(g.MapStrStr{ `CGenPbEntityConfig`: CGenPbEntityConfig, @@ -129,15 +241,19 @@ func init() { `CGenPbEntityAd`: CGenPbEntityAd, `CGenPbEntityBriefPath`: CGenPbEntityBriefPath, `CGenPbEntityBriefPackage`: CGenPbEntityBriefPackage, + `CGenPbEntityBriefGoPackage`: CGenPbEntityBriefGoPackage, `CGenPbEntityBriefLink`: CGenPbEntityBriefLink, `CGenPbEntityBriefTables`: CGenPbEntityBriefTables, `CGenPbEntityBriefPrefix`: CGenPbEntityBriefPrefix, `CGenPbEntityBriefRemovePrefix`: CGenPbEntityBriefRemovePrefix, + `CGenPbEntityBriefTablesEx`: CGenPbEntityBriefTablesEx, `CGenPbEntityBriefRemoveFieldPrefix`: CGenPbEntityBriefRemoveFieldPrefix, `CGenPbEntityBriefGroup`: CGenPbEntityBriefGroup, `CGenPbEntityBriefNameCase`: CGenPbEntityBriefNameCase, `CGenPbEntityBriefJsonCase`: CGenPbEntityBriefJsonCase, `CGenPbEntityBriefOption`: CGenPbEntityBriefOption, + `CGenPbEntityBriefTypeMapping`: CGenPbEntityBriefTypeMapping, + `CGenPbEntityBriefFieldMapping`: CGenPbEntityBriefFieldMapping, }) } @@ -181,6 +297,9 @@ func doGenPbEntityForArray(ctx context.Context, index int, in CGenPbEntityInput) in.Package = modName + "/" + defaultPackageSuffix } removePrefixArray := gstr.SplitAndTrim(in.RemovePrefix, ",") + + excludeTables := gset.NewStrSetFrom(gstr.SplitAndTrim(in.TablesEx, ",")) + // It uses user passed database configuration. if in.Link != "" { var ( @@ -210,8 +329,21 @@ func doGenPbEntityForArray(ctx context.Context, index int, in CGenPbEntityInput) mlog.Fatalf("fetching tables failed: \n %v", err) } } + // merge default typeMapping to input typeMapping. + if in.TypeMapping == nil { + in.TypeMapping = defaultTypeMapping + } else { + for key, typeMapping := range defaultTypeMapping { + if _, ok := in.TypeMapping[key]; !ok { + in.TypeMapping[key] = typeMapping + } + } + } for _, tableName := range tableNames { + if excludeTables.Contains(tableName) { + continue + } newTableName := tableName for _, v := range removePrefixArray { newTableName = gstr.TrimLeftStr(newTableName, v, 1) @@ -234,20 +366,29 @@ func generatePbEntityContentFile(ctx context.Context, in CGenPbEntityInternalInp // Change the `newTableName` if `Prefix` is given. newTableName := in.Prefix + in.NewTableName var ( - imports string - tableNameCamelCase = gstr.CaseCamel(newTableName) - tableNameSnakeCase = gstr.CaseSnake(newTableName) - entityMessageDefine = generateEntityMessageDefinition(tableNameCamelCase, fieldMap, in) - fileName = gstr.Trim(tableNameSnakeCase, "-_.") - path = filepath.FromSlash(gfile.Join(in.Path, fileName+".proto")) + tableNameCamelCase = gstr.CaseCamel(newTableName) + tableNameSnakeCase = gstr.CaseSnake(newTableName) + entityMessageDefine, appendImports = generateEntityMessageDefinition(tableNameCamelCase, fieldMap, in) + fileName = gstr.Trim(tableNameSnakeCase, "-_.") + path = filepath.FromSlash(gfile.Join(in.Path, fileName+".proto")) ) - if gstr.Contains(entityMessageDefine, "google.protobuf.Timestamp") { - imports = `import "google/protobuf/timestamp.proto";` + packageImportStr := "" + var packageImportsArray = garray.NewStrArray() + if len(appendImports) > 0 { + for _, appendImport := range appendImports { + packageImportStr = fmt.Sprintf(`import "%s";`, appendImport) + if packageImportsArray.Search(packageImportStr) == -1 { + packageImportsArray.Append(packageImportStr) + } + } + } + if in.GoPackage == "" { + in.GoPackage = in.Package } entityContent := gstr.ReplaceByMap(getTplPbEntityContent(""), g.MapStrStr{ - "{Imports}": imports, + "{Imports}": packageImportsArray.Join("\n"), "{PackageName}": gfile.Basename(in.Package), - "{GoPackage}": in.Package, + "{GoPackage}": in.GoPackage, "{OptionContent}": in.Option, "{EntityMessage}": entityMessageDefine, }) @@ -259,14 +400,19 @@ func generatePbEntityContentFile(ctx context.Context, in CGenPbEntityInternalInp } // generateEntityMessageDefinition generates and returns the message definition for specified table. -func generateEntityMessageDefinition(entityName string, fieldMap map[string]*gdb.TableField, in CGenPbEntityInternalInput) string { +func generateEntityMessageDefinition(entityName string, fieldMap map[string]*gdb.TableField, in CGenPbEntityInternalInput) (string, []string) { var ( - buffer = bytes.NewBuffer(nil) - array = make([][]string, len(fieldMap)) - names = sortFieldKeyForPbEntity(fieldMap) + appendImports []string + buffer = bytes.NewBuffer(nil) + array = make([][]string, len(fieldMap)) + names = sortFieldKeyForPbEntity(fieldMap) ) for index, name := range names { - array[index] = generateMessageFieldForPbEntity(index+1, fieldMap[name], in) + var imports string + array[index], imports = generateMessageFieldForPbEntity(index+1, fieldMap[name], in) + if imports != "" { + appendImports = append(appendImports, imports) + } } tw := tablewriter.NewWriter(buffer) tw.SetBorder(false) @@ -277,48 +423,38 @@ func generateEntityMessageDefinition(entityName string, fieldMap map[string]*gdb tw.Render() stContent := buffer.String() // Let's do this hack of table writer for indent! - stContent = gstr.Replace(stContent, " #", "") + stContent = regexp.MustCompile(`\s+\n`).ReplaceAllString(gstr.Replace(stContent, " #", ""), "\n") buffer.Reset() buffer.WriteString(fmt.Sprintf("message %s {\n", entityName)) buffer.WriteString(stContent) buffer.WriteString("}") - return buffer.String() + return buffer.String(), appendImports } // generateMessageFieldForPbEntity generates and returns the message definition for specified field. -func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPbEntityInternalInput) []string { +func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPbEntityInternalInput) (attrLines []string, appendImport string) { var ( - localTypeName gdb.LocalType - comment string - jsonTagStr string - err error - ctx = gctx.GetInitCtx() + localTypeNameStr string + localTypeName gdb.LocalType + comment string + jsonTagStr string + err error + ctx = gctx.GetInitCtx() ) - localTypeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil) - if err != nil { - panic(err) + + if in.TypeMapping != nil && len(in.TypeMapping) > 0 { + localTypeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil) + if err != nil { + panic(err) + } + if localTypeName != "" { + if typeMapping, ok := in.TypeMapping[strings.ToLower(string(localTypeName))]; ok { + localTypeNameStr = typeMapping.Type + appendImport = typeMapping.Import + } + } } - var typeMapping = map[gdb.LocalType]string{ - gdb.LocalTypeString: "string", - gdb.LocalTypeDate: "google.protobuf.Timestamp", - gdb.LocalTypeDatetime: "google.protobuf.Timestamp", - gdb.LocalTypeInt: "int32", - gdb.LocalTypeUint: "uint32", - gdb.LocalTypeInt64: "int64", - gdb.LocalTypeUint64: "uint64", - gdb.LocalTypeIntSlice: "repeated int32", - gdb.LocalTypeInt64Slice: "repeated int64", - gdb.LocalTypeUint64Slice: "repeated uint64", - gdb.LocalTypeInt64Bytes: "repeated int64", - gdb.LocalTypeUint64Bytes: "repeated uint64", - gdb.LocalTypeFloat32: "float", - gdb.LocalTypeFloat64: "double", - gdb.LocalTypeBytes: "bytes", - gdb.LocalTypeBool: "bool", - gdb.LocalTypeJson: "string", - gdb.LocalTypeJsonb: "string", - } - localTypeNameStr := typeMapping[localTypeName] + if localTypeNameStr == "" { localTypeNameStr = "string" } @@ -351,12 +487,19 @@ func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPb newFiledName = gstr.TrimLeftStr(newFiledName, v, 1) } + if in.FieldMapping != nil && len(in.FieldMapping) > 0 { + if typeMapping, ok := in.FieldMapping[fmt.Sprintf("%s.%s", in.TableName, newFiledName)]; ok { + localTypeNameStr = typeMapping.Type + appendImport = typeMapping.Import + } + } + return []string{ " #" + localTypeNameStr, " #" + formatCase(newFiledName, in.NameCase), " #= " + gconv.String(index) + jsonTagStr + ";", " #" + fmt.Sprintf(`// %s`, comment), - } + }, appendImport } func getTplPbEntityContent(tplEntityPath string) string { diff --git a/server/internal/library/hggen/internal/cmd/genservice/genservice.go b/server/internal/library/hggen/internal/cmd/genservice/genservice.go index fad6326..f412c06 100644 --- a/server/internal/library/hggen/internal/cmd/genservice/genservice.go +++ b/server/internal/library/hggen/internal/cmd/genservice/genservice.go @@ -94,6 +94,20 @@ const ( genServiceFileLockSeconds = 10 ) +type fileInfo struct { + PkgItems []pkgItem + FuncItems []funcItem +} + +type folderInfo struct { + SrcPackageName string + SrcImportedPackages *garray.SortedStrArray + SrcStructFunctions *gmap.ListMap + DstFilePath string + + FileInfos []*fileInfo +} + func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGenServiceOutput, err error) { in.SrcFolder = filepath.ToSlash(in.SrcFolder) in.SrcFolder = gstr.TrimRight(in.SrcFolder, `/`) @@ -163,7 +177,12 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe return nil, err } // it will use goroutine to generate service files for each package. - var wg = sync.WaitGroup{} + var ( + folderInfos []folderInfo + wg = sync.WaitGroup{} + allStructItems = make(map[string][]string) + ) + for _, srcFolderPath := range srcFolderPaths { if !gfile.IsDir(srcFolderPath) { continue @@ -175,7 +194,7 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe if len(files) == 0 { continue } - // Parse single logic package folder. + var ( srcPackageName = gfile.Basename(srcFolderPath) srcImportedPackages = garray.NewSortedStrArray().SetUnique(true) @@ -184,14 +203,46 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe c.getDstFileNameCase(srcPackageName, in.DstFileNameCase)+".go", ) ) - generatedDstFilePathSet.Add(dstFilePath) - // if it were to use goroutine, - // it would cause the order of the generated functions in the file to be disordered. + + folder := folderInfo{ + SrcPackageName: srcPackageName, + SrcImportedPackages: srcImportedPackages, + SrcStructFunctions: srcStructFunctions, + DstFilePath: dstFilePath, + } + for _, file := range files { - pkgItems, funcItems, err := c.parseItemsInSrc(file) + pkgItems, structItems, funcItems, err := c.parseItemsInSrc(file) if err != nil { return nil, err } + for k, v := range structItems { + allStructItems[k] = v + } + folder.FileInfos = append(folder.FileInfos, &fileInfo{ + PkgItems: pkgItems, + FuncItems: funcItems, + }) + } + + folderInfos = append(folderInfos, folder) + } + + folderInfos = c.calculateStructEmbeddedFuncInfos(folderInfos, allStructItems) + + for _, folder := range folderInfos { + // Parse single logic package folder. + var ( + srcPackageName = folder.SrcPackageName + srcImportedPackages = folder.SrcImportedPackages + srcStructFunctions = folder.SrcStructFunctions + dstFilePath = folder.DstFilePath + ) + generatedDstFilePathSet.Add(dstFilePath) + // if it were to use goroutine, + // it would cause the order of the generated functions in the file to be disordered. + for _, file := range folder.FileInfos { + pkgItems, funcItems := file.PkgItems, file.FuncItems // Calculate imported packages for service generating. err = c.calculateImportedItems(in, pkgItems, funcItems, srcImportedPackages) diff --git a/server/internal/library/hggen/internal/cmd/genservice/genservice_ast_parse.go b/server/internal/library/hggen/internal/cmd/genservice/genservice_ast_parse.go index c4205cc..974ec7e 100644 --- a/server/internal/library/hggen/internal/cmd/genservice/genservice_ast_parse.go +++ b/server/internal/library/hggen/internal/cmd/genservice/genservice_ast_parse.go @@ -10,8 +10,10 @@ import ( "go/ast" "go/parser" "go/token" + "strings" "github.com/gogf/gf/v2/os/gfile" + "github.com/gogf/gf/v2/os/gstructs" "github.com/gogf/gf/v2/text/gstr" ) @@ -32,7 +34,7 @@ type funcItem struct { // parseItemsInSrc parses the pkgItem and funcItem from the specified file. // It can't skip the private methods. // It can't skip the imported packages of import alias equal to `_`. -func (c CGenService) parseItemsInSrc(filePath string) (pkgItems []pkgItem, funcItems []funcItem, err error) { +func (c CGenService) parseItemsInSrc(filePath string) (pkgItems []pkgItem, structItems map[string][]string, funcItems []funcItem, err error) { var ( fileContent = gfile.GetContents(filePath) fileSet = token.NewFileSet() @@ -43,11 +45,107 @@ func (c CGenService) parseItemsInSrc(filePath string) (pkgItems []pkgItem, funcI return } + structItems = make(map[string][]string) + pkg := node.Name.Name + pkgAliasMap := make(map[string]string) ast.Inspect(node, func(n ast.Node) bool { switch x := n.(type) { case *ast.ImportSpec: // parse the imported packages. - pkgItems = append(pkgItems, c.parseImportPackages(x)) + pkgItem := c.parseImportPackages(x) + pkgItems = append(pkgItems, pkgItem) + pkgPath := strings.Trim(pkgItem.Path, "\"") + pkgPath = strings.ReplaceAll(pkgPath, "\\", "/") + tmp := strings.Split(pkgPath, "/") + srcPkg := tmp[len(tmp)-1] + if srcPkg != pkgItem.Alias { + pkgAliasMap[pkgItem.Alias] = srcPkg + } + case *ast.TypeSpec: // type define + switch xType := x.Type.(type) { + case *ast.StructType: // define struct + // parse the struct declaration. + var structName = pkg + "." + x.Name.Name + var structEmbeddedStruct []string + for _, field := range xType.Fields.List { + if len(field.Names) > 0 || field.Tag == nil { // not anonymous field + continue + } + + tagValue := strings.Trim(field.Tag.Value, "`") + tagValue = strings.TrimSpace(tagValue) + if len(tagValue) == 0 { // not set tag + continue + } + tags := gstructs.ParseTag(tagValue) + + if v, ok := tags["gen"]; !ok || v != "extend" { + continue + } + + var embeddedStruct string + switch v := field.Type.(type) { + case *ast.Ident: + if embeddedStruct, err = c.astExprToString(v); err != nil { + embeddedStruct = "" + break + } + embeddedStruct = pkg + "." + embeddedStruct + case *ast.StarExpr: + if embeddedStruct, err = c.astExprToString(v.X); err != nil { + embeddedStruct = "" + break + } + embeddedStruct = pkg + "." + embeddedStruct + case *ast.SelectorExpr: + var pkg string + if pkg, err = c.astExprToString(v.X); err != nil { + embeddedStruct = "" + break + } + if v, ok := pkgAliasMap[pkg]; ok { + pkg = v + } + if embeddedStruct, err = c.astExprToString(v.Sel); err != nil { + embeddedStruct = "" + break + } + embeddedStruct = pkg + "." + embeddedStruct + } + + if embeddedStruct == "" { + continue + } + structEmbeddedStruct = append(structEmbeddedStruct, embeddedStruct) + + } + if len(structEmbeddedStruct) > 0 { + structItems[structName] = structEmbeddedStruct + } + case *ast.Ident: // define ident + var ( + structName = pkg + "." + x.Name.Name + typeName = pkg + "." + xType.Name + ) + structItems[structName] = []string{typeName} + case *ast.SelectorExpr: // define selector + var ( + structName = pkg + "." + x.Name.Name + selecotrPkg string + typeName string + ) + if selecotrPkg, err = c.astExprToString(xType.X); err != nil { + break + } + if v, ok := pkgAliasMap[selecotrPkg]; ok { + selecotrPkg = v + } + if typeName, err = c.astExprToString(xType.Sel); err != nil { + break + } + typeName = selecotrPkg + "." + typeName + structItems[structName] = []string{typeName} + } case *ast.FuncDecl: // parse the function items. diff --git a/server/internal/library/hggen/internal/cmd/genservice/genservice_calculate.go b/server/internal/library/hggen/internal/cmd/genservice/genservice_calculate.go index 95b42da..4225fd9 100644 --- a/server/internal/library/hggen/internal/cmd/genservice/genservice_calculate.go +++ b/server/internal/library/hggen/internal/cmd/genservice/genservice_calculate.go @@ -15,6 +15,7 @@ import ( "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gstr" + "hotgo/internal/library/hggen/internal/utility/mlog" ) @@ -150,3 +151,78 @@ func (c CGenService) tidyResult(resultSlice []map[string]string) (resultStr stri } return } + +func (c CGenService) getStructFuncItems(structName string, allStructItems map[string][]string, funcItemsWithoutEmbed map[string][]*funcItem) (funcItems []*funcItem) { + funcItemNameSet := map[string]struct{}{} + + if items, ok := funcItemsWithoutEmbed[structName]; ok { + funcItems = append(funcItems, items...) + for _, item := range items { + funcItemNameSet[item.MethodName] = struct{}{} + } + } + + embeddedStructNames, ok := allStructItems[structName] + if !ok { + return + } + + for _, embeddedStructName := range embeddedStructNames { + items := c.getStructFuncItems(embeddedStructName, allStructItems, funcItemsWithoutEmbed) + + for _, item := range items { + if _, ok := funcItemNameSet[item.MethodName]; ok { + continue + } + funcItemNameSet[item.MethodName] = struct{}{} + funcItems = append(funcItems, item) + } + } + + return +} + +func (c CGenService) calculateStructEmbeddedFuncInfos(folderInfos []folderInfo, allStructItems map[string][]string) (newFolerInfos []folderInfo) { + funcItemsWithoutEmbed := make(map[string][]*funcItem) + funcItemMap := make(map[string]*([]funcItem)) + funcItemsWithoutEmbedMap := make(map[string]*funcItem) + + newFolerInfos = append(newFolerInfos, folderInfos...) + + for _, folder := range newFolerInfos { + for k := range folder.FileInfos { + fi := folder.FileInfos[k] + for k := range fi.FuncItems { + item := &fi.FuncItems[k] + receiver := folder.SrcPackageName + "." + strings.ReplaceAll(item.Receiver, "*", "") + funcItemMap[receiver] = &fi.FuncItems + funcItemsWithoutEmbed[receiver] = append(funcItemsWithoutEmbed[receiver], item) + funcItemsWithoutEmbedMap[fmt.Sprintf("%s:%s", receiver, item.MethodName)] = item + } + } + } + + for receiver, structItems := range allStructItems { + receiverName := strings.ReplaceAll(receiver, "*", "") + for _, structName := range structItems { + // Get the list of methods for the corresponding structName. + for _, funcItem := range c.getStructFuncItems(structName, allStructItems, funcItemsWithoutEmbed) { + if _, ok := funcItemsWithoutEmbedMap[fmt.Sprintf("%s:%s", receiverName, funcItem.MethodName)]; ok { + continue + } + if funcItemsPtr, ok := funcItemMap[receiverName]; ok { + newFuncItem := *funcItem + newFuncItem.Receiver = getReceiverName(receiver) + (*funcItemsPtr) = append((*funcItemsPtr), newFuncItem) + } + } + } + } + + return +} + +func getReceiverName(receiver string) string { + ss := strings.Split(receiver, ".") + return ss[len(ss)-1] +} diff --git a/server/internal/library/hggen/internal/cmd/genservice/genservice_generate.go b/server/internal/library/hggen/internal/cmd/genservice/genservice_generate.go index 8b50bc7..c18249a 100644 --- a/server/internal/library/hggen/internal/cmd/genservice/genservice_generate.go +++ b/server/internal/library/hggen/internal/cmd/genservice/genservice_generate.go @@ -14,6 +14,7 @@ import ( "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/text/gstr" + "hotgo/internal/library/hggen/internal/consts" "hotgo/internal/library/hggen/internal/utility/mlog" "hotgo/internal/library/hggen/internal/utility/utils" diff --git a/server/internal/library/hggen/internal/cmd/genservice/genservice_generate_template.go b/server/internal/library/hggen/internal/cmd/genservice/genservice_generate_template.go index 0e384cf..47ac06d 100644 --- a/server/internal/library/hggen/internal/cmd/genservice/genservice_generate_template.go +++ b/server/internal/library/hggen/internal/cmd/genservice/genservice_generate_template.go @@ -14,6 +14,7 @@ import ( "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gstr" + "hotgo/internal/library/hggen/internal/consts" ) diff --git a/server/internal/library/hggen/internal/consts/consts_gen_ctrl_template.go b/server/internal/library/hggen/internal/consts/consts_gen_ctrl_template.go index da0429e..ac6ee7d 100644 --- a/server/internal/library/hggen/internal/consts/consts_gen_ctrl_template.go +++ b/server/internal/library/hggen/internal/consts/consts_gen_ctrl_template.go @@ -45,7 +45,7 @@ import ( "{ImportPath}" ) - +{MethodComment} func (c *{CtrlName}) {MethodName}(ctx context.Context, req *{Version}.{MethodName}Req) (res *{Version}.{MethodName}Res, err error) { return nil, gerror.NewCode(gcode.CodeNotImplemented) } @@ -66,7 +66,7 @@ import ( ` const TemplateGenCtrlControllerMethodFuncMerge = ` - +{MethodComment} func (c *{CtrlName}) {MethodName}(ctx context.Context, req *{Version}.{MethodName}Req) (res *{Version}.{MethodName}Res, err error) { return nil, gerror.NewCode(gcode.CodeNotImplemented) } diff --git a/server/internal/library/hggen/internal/consts/consts_gen_ctrl_template_sdk.go b/server/internal/library/hggen/internal/consts/consts_gen_ctrl_template_sdk.go index 09f3795..f2c4670 100644 --- a/server/internal/library/hggen/internal/consts/consts_gen_ctrl_template_sdk.go +++ b/server/internal/library/hggen/internal/consts/consts_gen_ctrl_template_sdk.go @@ -81,7 +81,7 @@ func (i *implementer) {ImplementerName}() {Module}.I{ImplementerName} { ` -const TemplateGenCtrlSdkImplementerFunc = ` +const TemplateGenCtrlSdkImplementerFunc = `{MethodComment} func (i *implementer{ImplementerName}) {MethodName}(ctx context.Context, req *{Version}.{MethodName}Req) (res *{Version}.{MethodName}Res, err error) { err = i.Request(ctx, req, &res) return diff --git a/server/internal/library/hggen/internal/consts/consts_gen_dao_template_dao.go b/server/internal/library/hggen/internal/consts/consts_gen_dao_template_dao.go index 5af47e4..d1a82bc 100644 --- a/server/internal/library/hggen/internal/consts/consts_gen_dao_template_dao.go +++ b/server/internal/library/hggen/internal/consts/consts_gen_dao_template_dao.go @@ -8,38 +8,57 @@ package consts const TemplateGenDaoIndexContent = ` // ================================================================================= -// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. // ================================================================================= -package {TplPackageName} +package {{.TplPackageName}} import ( - "{TplImportPrefix}/internal" + "{{.TplImportPrefix}}/internal" ) -// internal{TplTableNameCamelCase}Dao is internal type for wrapping internal DAO implements. -type internal{TplTableNameCamelCase}Dao = *internal.{TplTableNameCamelCase}Dao - -// {TplTableNameCamelLowerCase}Dao is the data access object for table {TplTableName}. -// You can define custom methods on it to extend its functionality as you wish. -type {TplTableNameCamelLowerCase}Dao struct { - internal{TplTableNameCamelCase}Dao +// {{.TplTableNameCamelLowerCase}}Dao is the data access object for the table {{.TplTableName}}. +// You can define custom methods on it to extend its functionality as needed. +type {{.TplTableNameCamelLowerCase}}Dao struct { + *internal.{{.TplTableNameCamelCase}}Dao } var ( - // {TplTableNameCamelCase} is globally public accessible object for table {TplTableName} operations. - {TplTableNameCamelCase} = {TplTableNameCamelLowerCase}Dao{ - internal.New{TplTableNameCamelCase}Dao(), + // {{.TplTableNameCamelCase}} is a globally accessible object for table {{.TplTableName}} operations. + {{.TplTableNameCamelCase}} = {{.TplTableNameCamelLowerCase}}Dao{ +{{- if .TplTableSharding -}} + internal.New{{.TplTableNameCamelCase}}Dao(userShardingHandler), +{{- else -}} + internal.New{{.TplTableNameCamelCase}}Dao(), +{{- end -}} } ) -// Fill with you ideas below. +{{if .TplTableSharding -}} +// userShardingHandler is the handler for sharding operations. +// You can fill this sharding handler with your custom implementation. +func userShardingHandler(m *gdb.Model) *gdb.Model { + m = m.Sharding(gdb.ShardingConfig{ + Table: gdb.ShardingTableConfig{ + Enable: true, + Prefix: "", + // Replace Rule field with your custom sharding rule. + // Or you can use "&gdb.DefaultShardingRule{}" for default sharding rule. + Rule: nil, + }, + Schema: gdb.ShardingSchemaConfig{}, + }) + return m +} +{{- end}} + +// Add your custom methods and functionality below. ` const TemplateGenDaoInternalContent = ` // ========================================================================== -// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. {TplCreatedAtDatetimeStr} +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. {{.TplCreatedAtDatetimeStr}} // ========================================================================== package internal @@ -51,64 +70,70 @@ import ( "github.com/gogf/gf/v2/frame/g" ) -// {TplTableNameCamelCase}Dao is the data access object for table {TplTableName}. -type {TplTableNameCamelCase}Dao struct { +// {{.TplTableNameCamelCase}}Dao is the data access object for the table {{.TplTableName}}. +type {{.TplTableNameCamelCase}}Dao struct { table string // table is the underlying table name of the DAO. - group string // group is the database configuration group name of current DAO. - columns {TplTableNameCamelCase}Columns // columns contains all the column names of Table for convenient usage. + group string // group is the database configuration group name of the current DAO. + columns {{.TplTableNameCamelCase}}Columns // columns contains all the column names of Table for convenient usage. + handlers []gdb.ModelHandler // handlers for customized model modification. } -// {TplTableNameCamelCase}Columns defines and stores column names for table {TplTableName}. -type {TplTableNameCamelCase}Columns struct { - {TplColumnDefine} +// {{.TplTableNameCamelCase}}Columns defines and stores column names for the table {{.TplTableName}}. +type {{.TplTableNameCamelCase}}Columns struct { + {{.TplColumnDefine}} } -// {TplTableNameCamelLowerCase}Columns holds the columns for table {TplTableName}. -var {TplTableNameCamelLowerCase}Columns = {TplTableNameCamelCase}Columns{ - {TplColumnNames} +// {{.TplTableNameCamelLowerCase}}Columns holds the columns for the table {{.TplTableName}}. +var {{.TplTableNameCamelLowerCase}}Columns = {{.TplTableNameCamelCase}}Columns{ + {{.TplColumnNames}} } -// New{TplTableNameCamelCase}Dao creates and returns a new DAO object for table data access. -func New{TplTableNameCamelCase}Dao() *{TplTableNameCamelCase}Dao { - return &{TplTableNameCamelCase}Dao{ - group: "{TplGroupName}", - table: "{TplTableName}", - columns: {TplTableNameCamelLowerCase}Columns, +// New{{.TplTableNameCamelCase}}Dao creates and returns a new DAO object for table data access. +func New{{.TplTableNameCamelCase}}Dao(handlers ...gdb.ModelHandler) *{{.TplTableNameCamelCase}}Dao { + return &{{.TplTableNameCamelCase}}Dao{ + group: "{{.TplGroupName}}", + table: "{{.TplTableName}}", + columns: {{.TplTableNameCamelLowerCase}}Columns, + handlers: handlers, } } -// DB retrieves and returns the underlying raw database management object of current DAO. -func (dao *{TplTableNameCamelCase}Dao) DB() gdb.DB { +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *{{.TplTableNameCamelCase}}Dao) DB() gdb.DB { return g.DB(dao.group) } -// Table returns the table name of current dao. -func (dao *{TplTableNameCamelCase}Dao) Table() string { +// Table returns the table name of the current DAO. +func (dao *{{.TplTableNameCamelCase}}Dao) Table() string { return dao.table } -// Columns returns all column names of current dao. -func (dao *{TplTableNameCamelCase}Dao) Columns() {TplTableNameCamelCase}Columns { +// Columns returns all column names of the current DAO. +func (dao *{{.TplTableNameCamelCase}}Dao) Columns() {{.TplTableNameCamelCase}}Columns { return dao.columns } -// Group returns the configuration group name of database of current dao. -func (dao *{TplTableNameCamelCase}Dao) Group() string { +// Group returns the database configuration group name of the current DAO. +func (dao *{{.TplTableNameCamelCase}}Dao) Group() string { return dao.group } -// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. -func (dao *{TplTableNameCamelCase}Dao) Ctx(ctx context.Context) *gdb.Model { - return dao.DB().Model(dao.table).Safe().Ctx(ctx) +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *{{.TplTableNameCamelCase}}Dao) Ctx(ctx context.Context) *gdb.Model { + model := dao.DB().Model(dao.table) + for _, handler := range dao.handlers { + model = handler(model) + } + return model.Safe().Ctx(ctx) } // Transaction wraps the transaction logic using function f. -// It rollbacks the transaction and returns the error from function f if it returns non-nil error. +// It rolls back the transaction and returns the error if function f returns a non-nil error. // It commits the transaction and returns nil if function f returns nil. // -// Note that, you should not Commit or Rollback the transaction in function f +// Note: Do not commit or roll back the transaction in function f, // as it is automatically handled by this function. -func (dao *{TplTableNameCamelCase}Dao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { +func (dao *{{.TplTableNameCamelCase}}Dao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { return dao.Ctx(ctx).Transaction(ctx, f) } ` diff --git a/server/internal/library/hggen/internal/consts/consts_gen_dao_template_do.go b/server/internal/library/hggen/internal/consts/consts_gen_dao_template_do.go index 320aaa9..97a404e 100644 --- a/server/internal/library/hggen/internal/consts/consts_gen_dao_template_do.go +++ b/server/internal/library/hggen/internal/consts/consts_gen_dao_template_do.go @@ -8,13 +8,13 @@ package consts const TemplateGenDaoDoContent = ` // ================================================================================= -// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. {TplCreatedAtDatetimeStr} +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. {{.TplCreatedAtDatetimeStr}} // ================================================================================= -package {TplPackageName} +package {{.TplPackageName}} -{TplPackageImports} +{{.TplPackageImports}} -// {TplTableNameCamelCase} is the golang structure of table {TplTableName} for DAO operations like Where/Data. -{TplStructDefine} +// {{.TplTableNameCamelCase}} is the golang structure of table {{.TplTableName}} for DAO operations like Where/Data. +{{.TplStructDefine}} ` diff --git a/server/internal/library/hggen/internal/consts/consts_gen_dao_template_entity.go b/server/internal/library/hggen/internal/consts/consts_gen_dao_template_entity.go index 67a868e..c54713a 100644 --- a/server/internal/library/hggen/internal/consts/consts_gen_dao_template_entity.go +++ b/server/internal/library/hggen/internal/consts/consts_gen_dao_template_entity.go @@ -8,13 +8,13 @@ package consts const TemplateGenDaoEntityContent = ` // ================================================================================= -// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. {TplCreatedAtDatetimeStr} +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. {{.TplCreatedAtDatetimeStr}} // ================================================================================= -package {TplPackageName} +package {{.TplPackageName}} -{TplPackageImports} +{{.TplPackageImports}} -// {TplTableNameCamelCase} is the golang structure for table {TplTableName}. -{TplStructDefine} +// {{.TplTableNameCamelCase}} is the golang structure for table {{.TplTableName}}. +{{.TplStructDefine}} ` diff --git a/server/internal/library/hggen/internal/service/install.go b/server/internal/library/hggen/internal/service/install.go index ebda00e..0c901b1 100644 --- a/server/internal/library/hggen/internal/service/install.go +++ b/server/internal/library/hggen/internal/service/install.go @@ -162,8 +162,14 @@ func (s serviceInstall) getGoPathBin() string { func (s serviceInstall) getAvailablePaths() []serviceInstallAvailablePath { var ( folderPaths []serviceInstallAvailablePath - binaryFileName = "gf" + gfile.Ext(gfile.SelfPath()) + binaryFileName = "gf" ) + + // Windows binary file name suffix. + if runtime.GOOS == "windows" { + binaryFileName += ".exe" + } + // $GOPATH/bin if goPathBin := s.getGoPathBin(); goPathBin != "" { folderPaths = s.checkAndAppendToAvailablePath( diff --git a/server/internal/library/hggen/internal/utility/utils/utils_http_download.go b/server/internal/library/hggen/internal/utility/utils/utils_http_download.go index 3210d1d..ecedc00 100644 --- a/server/internal/library/hggen/internal/utility/utils/utils_http_download.go +++ b/server/internal/library/hggen/internal/utility/utils/utils_http_download.go @@ -7,13 +7,13 @@ package utils import ( - "fmt" "io" "net/http" "os" - "strconv" "time" + "github.com/schollz/progressbar/v3" + "github.com/gogf/gf/v2/errors/gerror" "hotgo/internal/library/hggen/internal/utility/mlog" @@ -34,26 +34,16 @@ func HTTPDownloadFileWithPercent(url string, localSaveFilePath string) error { } defer headResp.Body.Close() - size, err := strconv.Atoi(headResp.Header.Get("Content-Length")) - if err != nil { - return gerror.Wrap(err, "retrieve Content-Length failed") - } - doneCh := make(chan int64) - - go doPrintDownloadPercent(doneCh, localSaveFilePath, int64(size)) - resp, err := http.Get(url) if err != nil { return gerror.Wrapf(err, `download "%s" to "%s" failed`, url, localSaveFilePath) } defer resp.Body.Close() - wroteBytesCount, err := io.Copy(out, resp.Body) - if err != nil { - return gerror.Wrapf(err, `download "%s" to "%s" failed`, url, localSaveFilePath) - } + bar := progressbar.NewOptions(int(resp.ContentLength), progressbar.OptionShowBytes(true), progressbar.OptionShowCount()) + writer := io.MultiWriter(out, bar) + _, err = io.Copy(writer, resp.Body) - doneCh <- wroteBytesCount elapsed := time.Since(start) if elapsed > time.Minute { mlog.Printf(`download completed in %.0fm`, float64(elapsed)/float64(time.Minute)) @@ -63,45 +53,3 @@ func HTTPDownloadFileWithPercent(url string, localSaveFilePath string) error { return nil } - -func doPrintDownloadPercent(doneCh chan int64, localSaveFilePath string, total int64) { - var ( - stop = false - lastPercentFmt string - ) - file, err := os.Open(localSaveFilePath) - if err != nil { - mlog.Fatal(err) - } - defer file.Close() - - for { - select { - case <-doneCh: - stop = true - - default: - fi, err := file.Stat() - if err != nil { - mlog.Fatal(err) - } - size := fi.Size() - if size == 0 { - size = 1 - } - var ( - percent = float64(size) / float64(total) * 100 - percentFmt = fmt.Sprintf(`%.0f`, percent) + "%" - ) - if lastPercentFmt != percentFmt { - lastPercentFmt = percentFmt - mlog.Print(percentFmt) - } - } - - if stop { - break - } - time.Sleep(time.Second) - } -} diff --git a/server/internal/library/hggen/internal/utility/utils/utils_test.go b/server/internal/library/hggen/internal/utility/utils/utils_test.go index 6136870..eb20f4c 100644 --- a/server/internal/library/hggen/internal/utility/utils/utils_test.go +++ b/server/internal/library/hggen/internal/utility/utils/utils_test.go @@ -11,6 +11,7 @@ import ( "testing" "github.com/gogf/gf/v2/test/gtest" + "hotgo/internal/library/hggen/internal/utility/utils" ) diff --git a/server/internal/library/hggen/views/curd.go b/server/internal/library/hggen/views/curd.go index 697d919..2c81e66 100644 --- a/server/internal/library/hggen/views/curd.go +++ b/server/internal/library/hggen/views/curd.go @@ -403,7 +403,7 @@ func (l *gCurd) loadView(ctx context.Context, in *CurdPreviewInput) (err error) "importWebApi": in.options.ImportWebApi, // 导入webApi "apiPrefix": in.options.ApiPrefix, // api前缀 "componentPrefix": componentPrefix, // vue子组件前缀 - "in": in.In, // 在模版中使用`in`参数,如:插件目录名称 + "in": in.In, // 在模版中使用`in`参数,如:插件目录名称 }) in.view = view @@ -453,7 +453,7 @@ func (l *gCurd) DoBuild(ctx context.Context, in *CurdBuildInput) (err error) { // 导入失败,将sql文件删除 if err = ImportSql(ctx, vi.Path); err != nil { - _ = gfile.Remove(vi.Path) + _ = gfile.RemoveAll(vi.Path) } return } diff --git a/server/internal/library/hgorm/hook/member.go b/server/internal/library/hgorm/hook/member.go index 7d4b9d5..1cf99a8 100644 --- a/server/internal/library/hgorm/hook/member.go +++ b/server/internal/library/hgorm/hook/member.go @@ -109,7 +109,7 @@ var MemberSummary = gdb.HookHandler{ } var members []*MemberSumma - if err = g.Model("admin_member").Ctx(ctx).WhereIn("id", memberIds).Scan(&members); err != nil { + if err = g.Model("admin_member").Ctx(ctx).Fields(MemberSumma{}).WhereIn("id", memberIds).Scan(&members); err != nil { return nil, err } diff --git a/server/internal/library/storager/mime.go b/server/internal/library/storager/mime.go index ac77ebe..5d9ad57 100644 --- a/server/internal/library/storager/mime.go +++ b/server/internal/library/storager/mime.go @@ -158,26 +158,26 @@ func IsZipType(ext string) bool { // 如果文件类型没有加入系统映射类型,默认认为不是合法的文件类型。建议将常用的上传文件类型加入映射关系。 // 当然你也可以不做限制,可以上传任意文件。但需要谨慎处理和设置相应的安全措施。 // 获取任意扩展名的扩展类型:mime.TypeByExtension(".xls") -func GetFileMimeType(ext string) (string, error) { +func GetFileMimeType(ext string) string { if mime, ok := imgType[ext]; ok { - return mime, nil + return mime } if mime, ok := docType[ext]; ok { - return mime, nil + return mime } if mime, ok := audioType[ext]; ok { - return mime, nil + return mime } if mime, ok := videoType[ext]; ok { - return mime, nil + return mime } if mime, ok := zipType[ext]; ok { - return mime, nil + return mime } if mime, ok := otherType[ext]; ok { - return mime, nil + return mime } - return "", gerror.Newf("Invalid file type:%v", ext) + return "application/octet-stream" } // GetFileKind 获取文件上传类型 diff --git a/server/internal/library/storager/upload.go b/server/internal/library/storager/upload.go index a2683c9..b51def8 100644 --- a/server/internal/library/storager/upload.go +++ b/server/internal/library/storager/upload.go @@ -103,10 +103,6 @@ func DoUpload(ctx context.Context, typ string, file *ghttp.UploadFile) (result * // ValidateFileMeta 验证文件元数据 func ValidateFileMeta(typ string, meta *FileMeta) (err error) { - if _, err = GetFileMimeType(meta.Ext); err != nil { - return - } - switch typ { case KindImg: if !IsImgType(meta.Ext) { @@ -152,7 +148,7 @@ func ValidateFileMeta(typ string, meta *FileMeta) (err error) { } if len(config.FileType) > 0 && !validate.InSlice(strings.Split(config.FileType, `,`), meta.Ext) { - err = gerror.New("上传文件类型未经允许") + err = gerror.Newf("上传文件类型未经允许:%v", meta.Ext) return } } @@ -190,10 +186,7 @@ func GetFileMeta(file *ghttp.UploadFile) (meta *FileMeta, err error) { meta.Size = file.Size meta.Ext = Ext(file.Filename) meta.Kind = GetFileKind(meta.Ext) - meta.MimeType, err = GetFileMimeType(meta.Ext) - if err != nil { - return - } + meta.MimeType = GetFileMimeType(meta.Ext) // 兼容naiveUI naiveType := meta.MimeType @@ -272,10 +265,7 @@ func CheckMultipart(ctx context.Context, in *CheckMultipartParams) (res *CheckMu meta.Size = in.Size meta.Ext = Ext(in.FileName) meta.Kind = GetFileKind(meta.Ext) - meta.MimeType, err = GetFileMimeType(meta.Ext) - if err != nil { - return - } + meta.MimeType = GetFileMimeType(meta.Ext) // 兼容naiveUI naiveType := "text/plain" diff --git a/server/internal/logic/admin/cash.go b/server/internal/logic/admin/cash.go index 9e6faba..01b3b7b 100644 --- a/server/internal/logic/admin/cash.go +++ b/server/internal/logic/admin/cash.go @@ -17,6 +17,7 @@ import ( "hotgo/internal/consts" "hotgo/internal/dao" "hotgo/internal/library/contexts" + "hotgo/internal/library/hgorm/hook" "hotgo/internal/library/location" "hotgo/internal/model" "hotgo/internal/model/entity" @@ -80,6 +81,18 @@ func (s *sAdminCash) List(ctx context.Context, in *adminin.CashListInp) (list [] mod = mod.Where("member_id", in.MemberId) } + // 用户筛选 + if len(in.ComplexMemberId) == 2 && len(in.ComplexMemberId[0]) > 0 { + memberIds, err := service.AdminMember().GetComplexMemberIds(ctx, in.ComplexMemberId[0], in.ComplexMemberId[1]) + if err != nil { + return nil, 0, err + } + if len(memberIds) == 0 { + return nil, 0, nil + } + mod = mod.WhereIn(dao.AdminOrder.Columns().MemberId, memberIds) + } + if len(in.CreatedAt) == 2 { mod = mod.WhereBetween("created_at", gtime.New(in.CreatedAt[0]), gtime.New(in.CreatedAt[1])) } @@ -93,6 +106,9 @@ func (s *sAdminCash) List(ctx context.Context, in *adminin.CashListInp) (list [] mod = mod.Where("member_id", opMemberId) } + // 申请人摘要信息 + mod = mod.Hook(hook.MemberSummary) + totalCount, err = mod.Count() if err != nil { err = gerror.Wrap(err, consts.ErrorORM) @@ -107,19 +123,6 @@ func (s *sAdminCash) List(ctx context.Context, in *adminin.CashListInp) (list [] err = gerror.Wrap(err, consts.ErrorORM) return } - - for _, v := range list { - var member *entity.AdminMember - if err = dao.AdminMember.Ctx(ctx).Fields("real_name", "username").Where("id", v.MemberId).Scan(&member); err != nil { - err = gerror.Wrap(err, consts.ErrorORM) - return list, totalCount, err - } - - if member != nil { - v.MemberName = member.RealName - v.MemberUser = member.Username - } - } return } diff --git a/server/internal/logic/admin/credits_log.go b/server/internal/logic/admin/credits_log.go index 3f5c61f..d06b66c 100644 --- a/server/internal/logic/admin/credits_log.go +++ b/server/internal/logic/admin/credits_log.go @@ -14,6 +14,7 @@ import ( "hotgo/internal/consts" "hotgo/internal/dao" "hotgo/internal/library/hgorm/handler" + "hotgo/internal/library/hgorm/hook" "hotgo/internal/model/entity" "hotgo/internal/model/input/adminin" "hotgo/internal/model/input/form" @@ -174,6 +175,18 @@ func (s *sAdminCreditsLog) List(ctx context.Context, in *adminin.CreditsLogListI mod = mod.Where(dao.AdminCreditsLog.Columns().MemberId, in.MemberId) } + // 用户筛选 + if len(in.ComplexMemberId) == 2 && len(in.ComplexMemberId[0]) > 0 { + memberIds, err := service.AdminMember().GetComplexMemberIds(ctx, in.ComplexMemberId[0], in.ComplexMemberId[1]) + if err != nil { + return nil, 0, err + } + if len(memberIds) == 0 { + return nil, 0, nil + } + mod = mod.WhereIn(dao.AdminOrder.Columns().MemberId, memberIds) + } + // 查询应用id if in.AppId != "" { mod = mod.WhereLike(dao.AdminCreditsLog.Columns().AppId, in.AppId) @@ -209,7 +222,10 @@ func (s *sAdminCreditsLog) List(ctx context.Context, in *adminin.CreditsLogListI mod = mod.WhereBetween(dao.AdminCreditsLog.Columns().CreatedAt, in.CreatedAt[0], in.CreatedAt[1]) } - totalCount, err = mod.Clone().Count(1) + // 操作人摘要信息 + mod = mod.Hook(hook.MemberSummary) + + totalCount, err = mod.Clone().Count() if err != nil { return } diff --git a/server/internal/logic/admin/member.go b/server/internal/logic/admin/member.go index d4b7977..1efcd0a 100644 --- a/server/internal/logic/admin/member.go +++ b/server/internal/logic/admin/member.go @@ -16,6 +16,7 @@ import ( "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/text/gstr" + "github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/grand" "hotgo/internal/consts" "hotgo/internal/dao" @@ -28,6 +29,7 @@ import ( "hotgo/internal/model/input/adminin" "hotgo/internal/model/input/sysin" "hotgo/internal/service" + "hotgo/utility/convert" "hotgo/utility/tree" "hotgo/utility/validate" "sync" @@ -764,6 +766,52 @@ func (s *sAdminMember) Select(ctx context.Context, in *adminin.MemberSelectInp) return } +// GetLowerIds 获取指定用户的所有下级ID集合 +func (s *sAdminMember) GetLowerIds(ctx context.Context, memberId int64) (ids []int64, err error) { + array, err := dao.AdminMember.Ctx(ctx). + Fields("id"). + WhereLike("tree", "%"+tree.GenLabel("", memberId)+"%"). + Array() + if err != nil { + return nil, err + } + + for _, v := range array { + ids = append(ids, v.Int64()) + } + return +} + +// GetComplexMemberIds 组合查找符合条件的用户ID +func (s *sAdminMember) GetComplexMemberIds(ctx context.Context, memberIdx, opt string) (ids []int64, err error) { + memberId := gconv.Int64(memberIdx) + count, err := s.FilterAuthModel(ctx, contexts.GetUserId(ctx)).WherePri(memberId).Count() + if err != nil { + return nil, err + } + if count == 0 { + return + } + + switch opt { + case "1": // 仅查自己 + ids = append(ids, memberId) + case "2": // 仅查下级 + ids, err = s.GetLowerIds(ctx, memberId) + if err != nil { + return nil, err + } + default: // 查全部 + ids, err = s.GetLowerIds(ctx, memberId) + if err != nil { + return nil, err + } + ids = append(ids, memberId) + } + ids = convert.UniqueSlice(ids) + return +} + // GetIdsByKeyword 根据关键词查找符合条件的用户ID func (s *sAdminMember) GetIdsByKeyword(ctx context.Context, ks string) (res []int64, err error) { ks = gstr.Trim(ks) diff --git a/server/internal/logic/admin/order.go b/server/internal/logic/admin/order.go index e0edd5e..f77dadf 100644 --- a/server/internal/logic/admin/order.go +++ b/server/internal/logic/admin/order.go @@ -13,6 +13,7 @@ import ( "hotgo/internal/library/contexts" "hotgo/internal/library/hgorm" "hotgo/internal/library/hgorm/handler" + "hotgo/internal/library/hgorm/hook" "hotgo/internal/library/payment" "hotgo/internal/model/entity" "hotgo/internal/model/input/adminin" @@ -276,11 +277,26 @@ func (s *sAdminOrder) List(ctx context.Context, in *adminin.OrderListInp) (list mod = mod.Where(dao.AdminOrder.Columns().MemberId, in.MemberId) } + // 下单用户筛选 + if len(in.ComplexMemberId) == 2 && len(in.ComplexMemberId[0]) > 0 { + memberIds, err := service.AdminMember().GetComplexMemberIds(ctx, in.ComplexMemberId[0], in.ComplexMemberId[1]) + if err != nil { + return nil, 0, err + } + if len(memberIds) == 0 { + return nil, 0, nil + } + mod = mod.WhereIn(dao.AdminOrder.Columns().MemberId, memberIds) + } + mod = mod.LeftJoin(hgorm.GenJoinOnRelation( dao.AdminOrder.Table(), dao.AdminOrder.Columns().OrderSn, // 主表表名,关联条件 dao.PayLog.Table(), "payLog", dao.PayLog.Columns().OrderSn, // 关联表表名,别名,关联条件 )...) + // 操作人摘要信息 + mod = mod.Hook(hook.MemberSummary) + totalCount, err = mod.Clone().Count(1) if err != nil { return diff --git a/server/internal/logic/sys/log.go b/server/internal/logic/sys/log.go index 2288df4..4b71578 100644 --- a/server/internal/logic/sys/log.go +++ b/server/internal/logic/sys/log.go @@ -357,6 +357,18 @@ func (s *sSysLog) List(ctx context.Context, in *sysin.LogListInp) (list []*sysin mod = mod.Where("member_id", in.MemberId) } + // 操作人筛选 + if len(in.ComplexMemberId) == 2 && len(in.ComplexMemberId[0]) > 0 { + memberIds, err := service.AdminMember().GetComplexMemberIds(ctx, in.ComplexMemberId[0], in.ComplexMemberId[1]) + if err != nil { + return nil, 0, err + } + if len(memberIds) == 0 { + return nil, 0, nil + } + mod = mod.WhereIn("member_id", memberIds) + } + // 访问IP if in.Ip != "" { mod = mod.Where("ip", in.Ip) diff --git a/server/internal/model/input/adminin/cash.go b/server/internal/model/input/adminin/cash.go index 4b7e25d..bb8dfee 100644 --- a/server/internal/model/input/adminin/cash.go +++ b/server/internal/model/input/adminin/cash.go @@ -6,6 +6,7 @@ package adminin import ( + "hotgo/internal/library/hgorm/hook" "hotgo/internal/model/entity" "hotgo/internal/model/input/form" ) @@ -24,13 +25,13 @@ type CashViewModel struct { type CashListInp struct { form.PageReq form.StatusReq - MemberId int64 `json:"memberId"` - CreatedAt []int64 `json:"created_at"` + MemberId int64 `json:"memberId"` + CreatedAt []int64 `json:"created_at"` + ComplexMemberId []string `json:"complexMemberId" dc:"申请人"` } type CashListModel struct { - MemberUser string `json:"memberUser"` - MemberName string `json:"memberName"` + MemberBySumma *hook.MemberSumma `json:"memberBySumma" dc:"申请人信息"` entity.AdminCash } diff --git a/server/internal/model/input/adminin/credits_log.go b/server/internal/model/input/adminin/credits_log.go index ef13558..bf69297 100644 --- a/server/internal/model/input/adminin/credits_log.go +++ b/server/internal/model/input/adminin/credits_log.go @@ -13,6 +13,7 @@ import ( "github.com/gogf/gf/v2/net/ghttp" "hotgo/internal/consts" "hotgo/internal/library/contexts" + "hotgo/internal/library/hgorm/hook" "hotgo/internal/library/location" "hotgo/internal/model/input/form" @@ -98,15 +99,16 @@ type CreditsLogSaveIntegralModel struct { // CreditsLogListInp 获取资产变动列表 type CreditsLogListInp struct { form.PageReq - Id int64 `json:"id" dc:"变动ID"` - MemberId int64 `json:"memberId" dc:"管理员ID"` - AppId string `json:"appId" dc:"应用id"` - CreditType string `json:"creditType" dc:"变动类型"` - CreditGroup string `json:"creditGroup" dc:"变动的组别"` - Remark string `json:"remark" dc:"备注"` - Ip string `json:"ip" dc:"操作人IP"` - Status int `json:"status" dc:"状态"` - CreatedAt []*gtime.Time `json:"createdAt" dc:"创建时间"` + Id int64 `json:"id" dc:"变动ID"` + MemberId int64 `json:"memberId" dc:"管理员ID"` + AppId string `json:"appId" dc:"应用id"` + CreditType string `json:"creditType" dc:"变动类型"` + CreditGroup string `json:"creditGroup" dc:"变动的组别"` + Remark string `json:"remark" dc:"备注"` + Ip string `json:"ip" dc:"操作人IP"` + Status int `json:"status" dc:"状态"` + CreatedAt []*gtime.Time `json:"createdAt" dc:"创建时间"` + ComplexMemberId []string `json:"complexMemberId" dc:"用户"` } func (in *CreditsLogListInp) Filter(ctx context.Context) (err error) { @@ -114,21 +116,22 @@ func (in *CreditsLogListInp) Filter(ctx context.Context) (err error) { } type CreditsLogListModel struct { - Id int64 `json:"id" dc:"变动ID"` - MemberId int64 `json:"memberId" dc:"管理员ID"` - AppId string `json:"appId" dc:"应用id"` - AddonsName string `json:"addonsName" dc:"插件名称"` - CreditType string `json:"creditType" dc:"变动类型"` - CreditGroup string `json:"creditGroup" dc:"变动的组别"` - BeforeNum float64 `json:"beforeNum" dc:"变动前"` - Num float64 `json:"num" dc:"变动数据"` - AfterNum float64 `json:"afterNum" dc:"变动后"` - Remark string `json:"remark" dc:"备注"` - Ip string `json:"ip" dc:"操作人IP"` - MapId int64 `json:"mapId" dc:"关联ID"` - Status int `json:"status" dc:"状态"` - CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"` - UpdatedAt *gtime.Time `json:"updatedAt" dc:"修改时间"` + Id int64 `json:"id" dc:"变动ID"` + MemberId int64 `json:"memberId" dc:"管理员ID"` + AppId string `json:"appId" dc:"应用id"` + AddonsName string `json:"addonsName" dc:"插件名称"` + CreditType string `json:"creditType" dc:"变动类型"` + CreditGroup string `json:"creditGroup" dc:"变动的组别"` + BeforeNum float64 `json:"beforeNum" dc:"变动前"` + Num float64 `json:"num" dc:"变动数据"` + AfterNum float64 `json:"afterNum" dc:"变动后"` + Remark string `json:"remark" dc:"备注"` + Ip string `json:"ip" dc:"操作人IP"` + MapId int64 `json:"mapId" dc:"关联ID"` + Status int `json:"status" dc:"状态"` + CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"` + UpdatedAt *gtime.Time `json:"updatedAt" dc:"修改时间"` + MemberBySumma *hook.MemberSumma `json:"memberBySumma" dc:"用户信息"` } // CreditsLogExportModel 导出资产变动 diff --git a/server/internal/model/input/adminin/order.go b/server/internal/model/input/adminin/order.go index d8ed5b3..bbc2763 100644 --- a/server/internal/model/input/adminin/order.go +++ b/server/internal/model/input/adminin/order.go @@ -11,6 +11,7 @@ import ( "github.com/gogf/gf/v2/os/gtime" "hotgo/internal/consts" "hotgo/internal/library/dict" + "hotgo/internal/library/hgorm/hook" "hotgo/internal/model/entity" "hotgo/internal/model/input/form" "hotgo/internal/model/input/payin" @@ -114,6 +115,7 @@ type OrderListInp struct { Status int `json:"status" dc:"状态"` CreatedAt []*gtime.Time `json:"createdAt" dc:"创建时间"` PayLogOutTradeNo string `json:"payLogOutTradeNo" dc:"商户订单号"` + ComplexMemberId []string `json:"complexMemberId" dc:"下单用户"` } func (in *OrderListInp) Filter(ctx context.Context) (err error) { @@ -122,8 +124,9 @@ func (in *OrderListInp) Filter(ctx context.Context) (err error) { type OrderListModel struct { entity.AdminOrder - OutTradeNo string `json:"payLogOutTradeNo" dc:"商户订单号"` - PayType string `json:"payLogPayType" dc:"支付类型"` + OutTradeNo string `json:"payLogOutTradeNo" dc:"商户订单号"` + PayType string `json:"payLogPayType" dc:"支付类型"` + MemberBySumma *hook.MemberSumma `json:"memberBySumma" dc:"下单用户信息"` } // OrderExportModel 导出充值订单 diff --git a/server/internal/model/input/sysin/log.go b/server/internal/model/input/sysin/log.go index 6f222d7..6dd318e 100644 --- a/server/internal/model/input/sysin/log.go +++ b/server/internal/model/input/sysin/log.go @@ -14,16 +14,17 @@ import ( type LogListInp struct { form.PageReq form.StatusReq - ReqId string `json:"reqId" dc:"对外ID"` - Module string `json:"module" dc:"应用端口"` - MemberId int `json:"memberId" dc:"用户ID"` - TakeUpTime string `json:"takeUpTime" dc:"请求耗时"` - Method string `json:"method" dc:"请求方式"` - Url string `json:"url" dc:"请求路径"` - Ip string `json:"ip" dc:"访问IP"` - ErrorCode string `json:"errorCode" dc:"状态码"` - CreatedAt []int64 `json:"createdAt" dc:"创建时间"` - Keyword string `json:"keyword" dc:"关键词"` + ReqId string `json:"reqId" dc:"对外ID"` + Module string `json:"module" dc:"应用端口"` + MemberId int `json:"memberId" dc:"用户ID"` + TakeUpTime string `json:"takeUpTime" dc:"请求耗时"` + Method string `json:"method" dc:"请求方式"` + Url string `json:"url" dc:"请求路径"` + Ip string `json:"ip" dc:"访问IP"` + ErrorCode string `json:"errorCode" dc:"状态码"` + CreatedAt []int64 `json:"createdAt" dc:"创建时间"` + Keyword string `json:"keyword" dc:"关键词"` + ComplexMemberId []string `json:"complexMemberId" dc:"操作人筛选"` } type LogListModel struct { diff --git a/server/internal/service/admin.go b/server/internal/service/admin.go index 93bd730..b025d33 100644 --- a/server/internal/service/admin.go +++ b/server/internal/service/admin.go @@ -106,6 +106,10 @@ type ( GetIdByCode(ctx context.Context, in *adminin.GetIdByCodeInp) (res *adminin.GetIdByCodeModel, err error) // Select 获取可选的用户选项 Select(ctx context.Context, in *adminin.MemberSelectInp) (res []*adminin.MemberSelectModel, err error) + // GetLowerIds 获取指定用户的所有下级ID集合 + GetLowerIds(ctx context.Context, memberId int64) (ids []int64, err error) + // GetComplexMemberIds 组合查找符合条件的用户ID + GetComplexMemberIds(ctx context.Context, memberIdx string, opt string) (ids []int64, err error) // GetIdsByKeyword 根据关键词查找符合条件的用户ID GetIdsByKeyword(ctx context.Context, ks string) (res []int64, err error) // VerifySuperId 验证是否为超管 diff --git a/server/resource/generate/default/curd/logic.go.template b/server/resource/generate/default/curd/logic.go.template index 5fd823f..8cf4ad4 100644 --- a/server/resource/generate/default/curd/logic.go.template +++ b/server/resource/generate/default/curd/logic.go.template @@ -31,7 +31,8 @@ import ( @{ if eq .options.Step.IsAddon true }isc "hotgo/internal/service"@{end} @{ if eq .options.Step.IsTreeTable true }"hotgo/utility/tree"@{end} @{ if eq .options.Step.HasFuncDict true }"hotgo/internal/library/dict"@{end} - @{ if eq .options.Step.HasFuncDict true }"hotgo/internal/model"@{end} + @{ if and (eq .options.Step.HasFuncDict true) (eq .options.Step.IsAddon false) }"hotgo/internal/model"@{end} + @{ if and (eq .options.Step.HasFuncDict true) (eq .options.Step.IsAddon true) }imodel "hotgo/internal/model"@{end} ) type s@{.servFunName} struct{} @@ -238,7 +239,7 @@ func (s *s@{.servFunName}) TreeOption(ctx context.Context) (nodes []tree.Node, e @{ if eq .options.Step.HasFuncDict true } // Option 获取@{.tableComment}选项 -func (s *s@{.servFunName}) Option(ctx context.Context) (opts []*model.Option, err error) { +func (s *s@{.servFunName}) Option(ctx context.Context) (opts []*@{ if eq .options.Step.IsAddon false }model@{end}@{ if eq .options.Step.IsAddon true }imodel@{end}.Option, err error) { var models []*entity.@{.daoName} if err = s.Model(ctx@{ if eq .options.Step.HasNotFilterAuth true } ,&handler.Option{FilterAuth: false}@{end}).Fields(dao.@{.daoName}.Columns().@{.options.FuncDict.Value.GoName},dao.@{.daoName}.Columns().@{.options.FuncDict.Label.GoName}). @{.listOrder}.Scan(&models); err != nil { @@ -246,7 +247,7 @@ func (s *s@{.servFunName}) Option(ctx context.Context) (opts []*model.Option, er return } - opts = make([]*model.Option, len(models)) + opts = make([]*@{ if eq .options.Step.IsAddon false }model@{end}@{ if eq .options.Step.IsAddon true }imodel@{end}.Option, len(models)) for k, v := range models { opts[k] = dict.GenHashOption(v.@{.options.FuncDict.Value.GoName}, gconv.String(v.@{.options.FuncDict.Label.GoName})) } diff --git a/server/storage/data/hotgo.sql b/server/storage/data/hotgo.sql index 7f629c5..1e8e4ba 100644 --- a/server/storage/data/hotgo.sql +++ b/server/storage/data/hotgo.sql @@ -248,7 +248,7 @@ CREATE TABLE IF NOT EXISTS `hg_admin_member` ( INSERT INTO `hg_admin_member` (`id`, `dept_id`, `role_id`, `real_name`, `username`, `password_hash`, `salt`, `password_reset_token`, `integral`, `balance`, `avatar`, `sex`, `qq`, `email`, `mobile`, `birthday`, `city_id`, `address`, `pid`, `level`, `tree`, `invite_code`, `cash`, `last_active_at`, `remark`, `status`, `created_at`, `updated_at`) VALUES (1, 100, 1, '孟帅', 'admin', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '', '88.00', '99289.78', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '133814250', '133814250@qq.com', '15303830571', '2016-04-16', 410172, '莲花街001号', 0, 1, '', '111', '{"name": "孟帅", "account": "15303830571", "payeeCode": "http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8mqal5isvcb58g.jpg"}', '2024-08-27 19:02:49', NULL, 1, '2021-02-12 17:59:45', '2024-08-27 19:02:49'), -(3, 100, 2, '测试管理员', 'test', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '', '0.00', '4.00', 'http://alioss.qvnidaye.com//images/2021/03/12/image_1615529198_vMK4kwq2.jpg', 1, '', 'c@qq.cc', '15303888888', '2016-04-13', 371100, '大潮街道666号', 1, 2, 'tr_1 ', '222', NULL, '2024-04-24 11:47:48', '', 1, '2022-02-11 17:59:45', '2024-04-24 11:47:48'), +(3, 100, 2, '测试管理员', 'test', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '', '0.00', '4.00', '', 1, '', 'c@qq.cc', '15303888888', '2016-04-13', 371100, '大潮街道666号', 1, 2, 'tr_1 ', '222', NULL, '2024-04-24 11:47:48', '', 1, '2022-02-11 17:59:45', '2024-04-24 11:47:48'), (8, 102, 200, '阿萌', 'ameng', '382df3b083a27886edb94e669a857c33', 'hfuUEb', '', '11.00', '4.22', '', 2, '', '', '', NULL, 0, '', 1, 2, 'tr_1 ', '333', NULL, '2024-04-16 18:56:00', '', 1, '2023-02-03 17:34:31', '2024-04-16 18:56:00'), (9, 100, 206, '黄敏', 'test_finance', '151f5f6bb8b223fc7b589a32effb6f91', 'FhShzw', '', '0.00', '0.00', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '', '', '', NULL, 0, '', 1, 2, 'tr_1 ', '5jZUI3uWLfcj', NULL, NULL, '', 1, '2023-08-02 11:30:45', '2023-08-02 11:31:09'), (11, 111, 209, '刘芳', 'abai', '5787c7a121190011fac8376b1d3e0396', 'puUFvx', '', '0.00', '0.00', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '', '', '', NULL, 0, '', 8, 3, 'tr_1 tr_8 ', 'SH5akjqInb2p', NULL, '2024-04-16 18:56:02', '', 1, '2023-08-02 14:24:50', '2024-04-16 18:56:02'), @@ -1460,8 +1460,8 @@ INSERT INTO `hg_sys_config` (`id`, `group`, `name`, `type`, `key`, `value`, `def (51, 'smtp', '最小发送间隔', 'int', 'smtpMinInterval', '60', '', 150, '同地址', 1, 1, '2021-01-30 13:27:43', '2023-02-04 16:59:13'), (52, 'smtp', 'IP最大发送次数', 'int', 'smtpMaxIpLimit', '10', '', 160, '同IP每天最大允许发送次数', 1, 1, '2021-01-30 13:27:43', '2023-02-04 16:59:13'), (53, 'smtp', '验证码有效期', 'int', 'smtpCodeExpire', '600', '', 170, '单位:秒', 1, 1, '2021-01-30 13:27:43', '2023-02-04 16:59:13'), -(54, 'basic', '网站域名', 'string', 'basicDomain', 'https://hotgo.facms.cn', 'https://hotgo.facms.cn', 45, '', 1, 1, '2021-01-30 13:27:43', '2024-04-21 22:58:30'), -(55, 'basic', 'websocket地址', 'string', 'basicWsAddr', 'wss://hotgo.facms.cn/socket', 'wss://hotgo.facms.cn/socket', 48, '', 1, 1, '2021-01-30 13:27:43', '2024-04-21 22:58:30'), +(54, 'basic', '网站域名', 'string', 'basicDomain', 'http://127.0.0.1:8000', 'http://127.0.0.1:8000', 45, '', 1, 1, '2021-01-30 13:27:43', '2024-04-21 22:58:30'), +(55, 'basic', 'websocket地址', 'string', 'basicWsAddr', 'ws://127.0.0.1:8000/socket', 'ws://127.0.0.1:8000/socket', 48, '', 1, 1, '2021-01-30 13:27:43', '2024-04-21 22:58:30'), (56, 'upload', 'COS存储路径', 'string', 'uploadCosPath', 'hotgo/attachment/', 'hotgo/attachment/', 450, 'COS对象存储中的相对路径', 1, 1, '2021-01-30 13:27:43', '2024-02-28 16:56:35'), (57, 'upload', 'COS秘钥ID', 'string', 'uploadCosSecretId', '', '', 460, '子账号密钥获取可参考 https://cloud.tencent.com/document/product/598/37140', 1, 1, '2021-01-30 13:27:43', '2024-02-28 16:56:35'), (58, 'upload', 'COS秘钥', 'string', 'uploadCosSecretKey', '', '', 470, '', 1, 1, '2021-01-30 13:27:43', '2024-02-28 16:56:35'), diff --git a/server/storage/data/sqlite/data.sql b/server/storage/data/sqlite/data.sql index 0dada1d..e19855f 100644 --- a/server/storage/data/sqlite/data.sql +++ b/server/storage/data/sqlite/data.sql @@ -36,7 +36,7 @@ INSERT INTO `hg_admin_dept` (`id`, `pid`, `name`, `code`, `type`, `leader`, `pho INSERT INTO `hg_admin_member` (`id`, `dept_id`, `role_id`, `real_name`, `username`, `password_hash`, `salt`, `password_reset_token`, `integral`, `balance`, `avatar`, `sex`, `qq`, `email`, `mobile`, `birthday`, `city_id`, `address`, `pid`, `level`, `tree`, `invite_code`, `cash`, `last_active_at`, `remark`, `status`, `created_at`, `updated_at`) VALUES (1, 100, 1, '孟帅', 'admin', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '', 89.00, 99290.78, 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '133814250', '133814250@qq.com', '15303830571', '2016-04-16', 410172, '莲花街001号', 0, 1, '', '111', '{\"name\": \"孟帅\", \"account\": \"15303830571\", \"payeeCode\": \"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8mqal5isvcb58g.jpg\"}', '2024-04-21 22:58:56', NULL, 1, '2021-02-12 17:59:45', '2024-04-21 22:58:56'), -(3, 100, 2, '测试管理员', 'test', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '', 0.00, 4.00, 'http://alioss.qvnidaye.com//images/2021/03/12/image_1615529198_vMK4kwq2.jpg', 1, '', 'c@qq.cc', '15303888888', '2016-04-13', 371100, '大潮街道666号', 1, 2, 'tr_1 ', '222', NULL, '2024-04-12 12:44:18', '', 1, '2022-02-11 17:59:45', '2024-04-12 12:44:18'), +(3, 100, 2, '测试管理员', 'test', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '', 0.00, 4.00, '', 1, '', 'c@qq.cc', '15303888888', '2016-04-13', 371100, '大潮街道666号', 1, 2, 'tr_1 ', '222', NULL, '2024-04-12 12:44:18', '', 1, '2022-02-11 17:59:45', '2024-04-12 12:44:18'), (8, 102, 200, '阿萌', 'ameng', '382df3b083a27886edb94e669a857c33', 'hfuUEb', '', 11.00, 4.22, '', 2, '', '', '', NULL, 0, '', 1, 2, 'tr_1 ', '333', NULL, '2024-04-16 18:56:00', '', 1, '2023-02-03 17:34:31', '2024-04-16 18:56:00'), (9, 100, 206, '黄敏', 'test_finance', '151f5f6bb8b223fc7b589a32effb6f91', 'FhShzw', '', 0.00, 0.00, 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '', '', '', NULL, 0, '', 1, 2, 'tr_1 ', '5jZUI3uWLfcj', NULL, NULL, '', 1, '2023-08-02 11:30:45', '2023-08-02 11:31:09'), (11, 111, 209, '刘芳', 'abai', '5787c7a121190011fac8376b1d3e0396', 'puUFvx', '', 0.00, 0.00, 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '', '', '', NULL, 0, '', 8, 3, 'tr_1 tr_8 ', 'SH5akjqInb2p', NULL, '2024-04-16 18:56:02', '', 1, '2023-08-02 14:24:50', '2024-04-16 18:56:02'), diff --git a/web/package.json b/web/package.json index 9630be0..688136a 100644 --- a/web/package.json +++ b/web/package.json @@ -1,7 +1,7 @@ { "name": "hotgo", "type": "module", - "version": "2.15.11", + "version": "2.16.10", "author": { "name": "MengShuai", "email": "133814250@qq.com", @@ -44,7 +44,7 @@ "lodash-es": "^4.17.21", "mint-filter": "^4.0.3", "mitt": "^3.0.1", - "naive-ui": "^2.39.0", + "naive-ui": "^2.41.0", "pinia": "^2.2.2", "pinyin-pro": "^3.24.2", "print-js": "^1.6.0", diff --git a/web/src/components/ComplexMemberPicker/index.vue b/web/src/components/ComplexMemberPicker/index.vue new file mode 100644 index 0000000..ca9a58f --- /dev/null +++ b/web/src/components/ComplexMemberPicker/index.vue @@ -0,0 +1,144 @@ + + + + + diff --git a/web/src/components/ComplexMemberPicker/props.ts b/web/src/components/ComplexMemberPicker/props.ts new file mode 100644 index 0000000..727c266 --- /dev/null +++ b/web/src/components/ComplexMemberPicker/props.ts @@ -0,0 +1,13 @@ +import { NSelect } from 'naive-ui'; + +export const basicProps = { + ...NSelect.props, + defaultValue: { + type: [Array], + default: null, + }, + value: { + type: [Array], + default: null, + }, +}; diff --git a/web/src/components/Form/src/BasicForm.vue b/web/src/components/Form/src/BasicForm.vue index c4b3867..783ea60 100644 --- a/web/src/components/Form/src/BasicForm.vue +++ b/web/src/components/Form/src/BasicForm.vue @@ -66,6 +66,13 @@ v-bind="getComponentProps(schema)" /> + ({ ...attrs, ...props, ...unref(getProps) } as Recordable) + () => ({ ...attrs, ...props, ...unref(getProps) }) as Recordable ); const getSchema = computed((): FormSchema[] => { diff --git a/web/src/components/Form/src/types/index.ts b/web/src/components/Form/src/types/index.ts index 5cb0baa..6a12ff7 100644 --- a/web/src/components/Form/src/types/index.ts +++ b/web/src/components/Form/src/types/index.ts @@ -25,4 +25,5 @@ export type ComponentType = | 'NIconPicker' | 'NRender' | 'NSlider' - | 'NRate'; + | 'NRate' + | 'ComplexMemberPicker'; diff --git a/web/src/router/base.ts b/web/src/router/base.ts index a4683ff..4e5e8c4 100644 --- a/web/src/router/base.ts +++ b/web/src/router/base.ts @@ -34,7 +34,7 @@ export const RedirectRoute: AppRouteRecordRaw = { children: [ { path: '/redirect/:path(.*)', - name: RedirectName, + name: `${RedirectName}Son`, component: () => import('@/views/redirect/index.vue'), meta: { title: RedirectName, diff --git a/web/src/utils/index.ts b/web/src/utils/index.ts index 6b64692..15507b5 100644 --- a/web/src/utils/index.ts +++ b/web/src/utils/index.ts @@ -183,7 +183,6 @@ export const renderPopoverMemberSumma = (member: MemberSumma | null | undefined) h( NButton, { - strong: true, size: 'small', text: true, iconPlacement: 'right', diff --git a/web/src/utils/is/index.ts b/web/src/utils/is/index.ts index f4fa400..49ff4cf 100644 --- a/web/src/utils/is/index.ts +++ b/web/src/utils/is/index.ts @@ -146,6 +146,10 @@ export function isNullOrUnDef(val: unknown): val is null | undefined { return isUnDef(val) || isNull(val); } +export function isEmpty(value: any): boolean { + return value === undefined || value === null || value === ''; +} + // 判断字串符是否以字母开头 export function isLetterBegin(str) { return /^[A-z]/.test(str); diff --git a/web/src/utils/websocket/index.ts b/web/src/utils/websocket/index.ts index 4ecd535..ca8b1e2 100644 --- a/web/src/utils/websocket/index.ts +++ b/web/src/utils/websocket/index.ts @@ -81,7 +81,7 @@ export default () => { clearTimeout(timer); timer = setTimeout(() => { createSocket(); - }, 2000); + }, 1000 * 10); }; const init = () => { diff --git a/web/src/views/apply/attachment/columns.ts b/web/src/views/apply/attachment/columns.ts index 4337d38..ead166c 100644 --- a/web/src/views/apply/attachment/columns.ts +++ b/web/src/views/apply/attachment/columns.ts @@ -106,7 +106,7 @@ export const columns = [ { title: '文件名称', key: 'name', - width: 120, + width: 150, }, { title: '文件', @@ -157,7 +157,7 @@ export const columns = [ { title: '扩展类型', key: 'mimeType', - width: 120, + width: 200, }, { title: '上传时间', diff --git a/web/src/views/apply/attachment/index.vue b/web/src/views/apply/attachment/index.vue index 2436937..94483db 100644 --- a/web/src/views/apply/attachment/index.vue +++ b/web/src/views/apply/attachment/index.vue @@ -21,7 +21,7 @@ ref="actionRef" :actionColumn="actionColumn" @update:checked-row-keys="onCheckedRow" - :scroll-x="1280" + :scroll-x="scrollX" :resizeHeightOffset="-20000" > + + diff --git a/web/src/views/apply/notice/index.vue b/web/src/views/apply/notice/index.vue index ef2e1d1..4308969 100644 --- a/web/src/views/apply/notice/index.vue +++ b/web/src/views/apply/notice/index.vue @@ -26,7 +26,7 @@ ref="actionRef" :actionColumn="actionColumn" @update:checked-row-keys="onCheckedRow" - :scroll-x="1280" + :scroll-x="scrollX" :resizeHeightOffset="-20000" > - - - - 消息发送成功后如果接收人在线会立即收到一条消息通知,编辑已发送的消息不会再次通知 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -198,117 +97,25 @@ import { computed, h, onMounted, reactive, ref } from 'vue'; import { useDialog, useMessage } from 'naive-ui'; import { BasicTable, TableAction } from '@/components/Table'; - import { BasicForm, FormSchema, useForm } from '@/components/Form/index'; - import { - Delete, - EditNotify, - EditLetter, - EditNotice, - List, - MaxSort, - Status, - } from '@/api/apply/notice'; - import { columns, loadOptions } from './columns'; + import { BasicForm, useForm } from '@/components/Form/index'; + import { Delete, List, Status } from '@/api/apply/notice'; import { BellOutlined, DeleteOutlined, NotificationOutlined, SendOutlined } from '@vicons/antd'; - import { statusOptions } from '@/enums/optionsiEnum'; - import { personOption, renderLabel, renderMultipleSelectTag } from '@/enums/systemMessageEnum'; - import { adaModalWidth } from '@/utils/hotgo'; - import { renderTag } from '@/utils'; - import Editor from '@/components/Editor/editor.vue'; - import { cloneDeep } from 'lodash-es'; - import { GetMemberOption } from '@/api/org/user'; + import { adaTableScrollX } from '@/utils/hotgo'; import { usePermission } from '@/hooks/web/usePermission'; import { useDictStore } from '@/store/modules/dict'; - - const dict = useDictStore(); - const rules = { - title: { - required: true, - trigger: ['blur', 'input'], - message: '请输入消息标题', - }, - }; - - const schemas: FormSchema[] = [ - { - field: 'type', - component: 'NSelect', - label: '消息类型', - defaultValue: null, - componentProps: { - placeholder: '请选择消息类型', - options: dict.getOption('noticeTypeOptions'), - onUpdateValue: (e: any) => { - console.log(e); - }, - }, - }, - { - field: 'title', - component: 'NInput', - label: '消息标题', - componentProps: { - placeholder: '请输入消息标题', - onUpdateValue: (e: any) => { - console.log(e); - }, - }, - rules: [{ message: '请输入消息标题', trigger: ['blur'] }], - }, - { - field: 'content', - component: 'NInput', - label: '消息内容', - componentProps: { - placeholder: '请输入消息内容关键词', - showButton: false, - onUpdateValue: (e: any) => { - console.log(e); - }, - }, - }, - { - field: 'status', - component: 'NSelect', - label: '状态', - defaultValue: null, - componentProps: { - placeholder: '请选择类型', - options: dict.getOption('sys_normal_disable'), - onUpdateValue: (e: any) => { - console.log(e); - }, - }, - }, - ]; + import { columns } from './columns'; + import { schemas, loadOptions } from './model'; + import Edit from './edit.vue'; const { hasPermission } = usePermission(); const message = useMessage(); + const dict = useDictStore(); const actionRef = ref(); const dialog = useDialog(); - const showModal = ref(false); - const formBtnLoading = ref(false); const searchFormRef = ref({}); - const formRef = ref({}); + const editRef = ref(); const batchDeleteDisabled = ref(true); const checkedIds = ref([]); - const options = ref(); - const dialogWidth = computed(() => { - return adaModalWidth(); - }); - - const resetFormParams = { - id: 0, - title: '', - type: 1, - tag: 0, - content: '', - receiver: null, - remark: '', - sort: 0, - status: 1, - }; - let formParams = ref(cloneDeep(resetFormParams)); const actionColumn = reactive({ width: 200, @@ -351,6 +158,10 @@ }, }); + const scrollX = computed(() => { + return adaTableScrollX(columns, actionColumn.width); + }); + const [register, {}] = useForm({ gridProps: { cols: '1 s:1 m:2 l:3 xl:4 2xl:4' }, labelWidth: 80, @@ -358,12 +169,7 @@ }); function addTable(type) { - showModal.value = true; - formParams.value = cloneDeep(resetFormParams); - formParams.value.type = type; - MaxSort().then((res) => { - formParams.value.sort = res.sort; - }); + editRef.value.openModal(null, type); } const loadDataTable = async (res) => { @@ -379,52 +185,8 @@ actionRef.value.reload(); } - function confirmForm(e) { - e.preventDefault(); - formBtnLoading.value = true; - formRef.value.validate((errors) => { - if (!errors) { - switch (formParams.value.type) { - case 1: - EditNotify(formParams.value).then((_res) => { - message.success('操作成功'); - setTimeout(() => { - showModal.value = false; - reloadTable(); - }); - }); - break; - case 2: - EditNotice(formParams.value).then((_res) => { - message.success('操作成功'); - setTimeout(() => { - showModal.value = false; - reloadTable(); - }); - }); - break; - case 3: - EditLetter(formParams.value).then((_res) => { - message.success('操作成功'); - setTimeout(() => { - showModal.value = false; - reloadTable(); - }); - }); - break; - default: - message.error('公告类型不支持'); - } - } else { - message.error('请填写完整信息'); - } - formBtnLoading.value = false; - }); - } - function handleEdit(record: Recordable) { - showModal.value = true; - formParams.value = cloneDeep(record); + editRef.value.openModal(record, record.type); } function handleDelete(record: Recordable) { @@ -474,13 +236,8 @@ }); } - async function getMemberOption() { - options.value = await GetMemberOption(); - } - - onMounted(async () => { + onMounted(() => { loadOptions(); - await getMemberOption(); }); diff --git a/web/src/views/apply/notice/model.ts b/web/src/views/apply/notice/model.ts new file mode 100644 index 0000000..a5a1c5f --- /dev/null +++ b/web/src/views/apply/notice/model.ts @@ -0,0 +1,113 @@ +import { cloneDeep } from 'lodash-es'; +import { FormSchema } from '@/components/Form'; +import { useDictStore } from '@/store/modules/dict'; + +const dict = useDictStore(); + +export class State { + id: number; + title: string; + type: number; + tag: number = 1; + content: string; + receiver: number[]; + remark: string; + sort: number; + status: number = 1; + createdBy: number; + updatedBy: number; + createdAt: string; + updatedAt: string; + deletedAt: string | null; + readCount: number; + receiverGroup: Receiver[]; + + constructor(state?: Partial) { + if (state) { + Object.assign(this, state); + } + } +} + +export class Receiver { + name: string; + src: string; +} + +export function newState(state: State | Record | null): State { + if (state !== null) { + if (state instanceof State) { + return cloneDeep(state); + } + return new State(state); + } + return new State(); +} + +// 表单验证规则 +export const rules = { + title: { + required: true, + trigger: ['blur', 'input'], + message: '请输入消息标题', + }, +}; + +// 表格搜索表单 +export const schemas: FormSchema[] = [ + { + field: 'type', + component: 'NSelect', + label: '消息类型', + defaultValue: null, + componentProps: { + placeholder: '请选择消息类型', + options: dict.getOption('noticeTypeOptions'), + onUpdateValue: (e: any) => { + console.log(e); + }, + }, + }, + { + field: 'title', + component: 'NInput', + label: '消息标题', + componentProps: { + placeholder: '请输入消息标题', + onUpdateValue: (e: any) => { + console.log(e); + }, + }, + rules: [{ message: '请输入消息标题', trigger: ['blur'] }], + }, + { + field: 'content', + component: 'NInput', + label: '消息内容', + componentProps: { + placeholder: '请输入消息内容关键词', + showButton: false, + onUpdateValue: (e: any) => { + console.log(e); + }, + }, + }, + { + field: 'status', + component: 'NSelect', + label: '状态', + defaultValue: null, + componentProps: { + placeholder: '请选择类型', + options: dict.getOption('sys_normal_disable'), + onUpdateValue: (e: any) => { + console.log(e); + }, + }, + }, +]; + +// 加载字典数据选项 +export function loadOptions() { + dict.loadOptions(['sys_normal_disable']); +} diff --git a/web/src/views/asset/cash/columns.ts b/web/src/views/asset/cash/columns.ts index babd68d..2c4b30d 100644 --- a/web/src/views/asset/cash/columns.ts +++ b/web/src/views/asset/cash/columns.ts @@ -1,5 +1,6 @@ import { h } from 'vue'; import { NTag } from 'naive-ui'; +import { renderPopoverMemberSumma } from '@/utils'; const msgMap = { 1: '处理中', @@ -29,20 +30,12 @@ export const columns = [ width: 100, }, { - title: '用户名', - key: 'memberUser', - render(row) { - return row.memberUser; - }, + title: '申请人', + key: 'memberId', width: 100, - }, - { - title: '姓名', - key: 'memberName', render(row) { - return row.memberName; + return renderPopoverMemberSumma(row.memberBySumma); }, - width: 100, }, { title: '提现金额', diff --git a/web/src/views/asset/cash/list.vue b/web/src/views/asset/cash/list.vue index b5f7829..0629239 100644 --- a/web/src/views/asset/cash/list.vue +++ b/web/src/views/asset/cash/list.vue @@ -118,7 +118,7 @@ - + { + placeholder: '请选择申请人', + onInput: (e: any) => { console.log(e); }, }, - rules: [{ message: '请输入管理员ID', trigger: ['blur'] }], }, { field: 'ip', diff --git a/web/src/views/asset/creditsLog/model.ts b/web/src/views/asset/creditsLog/model.ts index 406f987..093d923 100644 --- a/web/src/views/asset/creditsLog/model.ts +++ b/web/src/views/asset/creditsLog/model.ts @@ -2,18 +2,18 @@ import { ref } from 'vue'; import { FormSchema } from '@/components/Form'; import { defRangeShortcuts } from '@/utils/dateUtil'; import { useDictStore } from '@/store/modules/dict'; -import { renderOptionTag } from '@/utils'; +import { renderOptionTag, renderPopoverMemberSumma } from '@/utils'; const dict = useDictStore(); export const schemas = ref([ { - field: 'memberId', - component: 'NInput', - label: '管理员ID', + field: 'complexMemberId', + component: 'ComplexMemberPicker', + label: '选择用户', componentProps: { - placeholder: '请输入管理员ID', - onUpdateValue: (e: any) => { + placeholder: '请选择用户', + onInput: (e: any) => { console.log(e); }, }, @@ -21,10 +21,10 @@ export const schemas = ref([ { field: 'creditGroup', component: 'NSelect', - label: '组别', + label: '变动组别', defaultValue: null, componentProps: { - placeholder: '请选择变动的组别', + placeholder: '请选择变动组别', options: dict.getOption('creditGroup'), onUpdateValue: (e: any) => { console.log(e); @@ -86,9 +86,12 @@ export const columns = [ width: 100, }, { - title: '管理员ID', + title: '用户', key: 'memberId', width: 100, + render(row) { + return renderPopoverMemberSumma(row.memberBySumma); + }, }, { title: '变动类型', @@ -99,7 +102,7 @@ export const columns = [ width: 150, }, { - title: '组别', + title: '变动组别', key: 'creditGroup', render(row) { return renderOptionTag('creditGroup', row.creditGroup); diff --git a/web/src/views/asset/rechargeLog/applyRefund.vue b/web/src/views/asset/rechargeLog/applyRefund.vue index 2f44095..79fc4af 100644 --- a/web/src/views/asset/rechargeLog/applyRefund.vue +++ b/web/src/views/asset/rechargeLog/applyRefund.vue @@ -58,7 +58,6 @@ } const emit = defineEmits(['reloadTable', 'updateShowModal']); - const props = withDefaults(defineProps(), { showModal: false, formParams: () => { diff --git a/web/src/views/asset/rechargeLog/model.ts b/web/src/views/asset/rechargeLog/model.ts index 3147b7b..209b7cc 100644 --- a/web/src/views/asset/rechargeLog/model.ts +++ b/web/src/views/asset/rechargeLog/model.ts @@ -3,7 +3,7 @@ import { cloneDeep } from 'lodash-es'; import { FormSchema } from '@/components/Form'; import { defRangeShortcuts } from '@/utils/dateUtil'; import { useDictStore } from '@/store/modules/dict'; -import { renderOptionTag } from '@/utils'; +import { MemberSumma, renderOptionTag, renderPopoverMemberSumma } from '@/utils'; export interface State { id: number; @@ -20,6 +20,7 @@ export interface State { refundReason: string; rejectRefundReason: string; payLogPayType: string; + memberBySumma?: null | MemberSumma; } export const defaultState = { @@ -51,12 +52,12 @@ export const rules = {}; export const schemas = ref([ { - field: 'memberId', - component: 'NInput', - label: '管理员ID', + field: 'complexMemberId', + component: 'ComplexMemberPicker', + label: '下单用户', componentProps: { - placeholder: '请输入管理员ID', - onUpdateValue: (e: any) => { + placeholder: '请选择下单用户', + onInput: (e: any) => { console.log(e); }, }, @@ -99,25 +100,18 @@ export const schemas = ref([ ]); export const columns = [ - { - title: '订单ID', - key: 'id', - width: 100, - }, - { - title: '管理员ID', - key: 'memberId', - width: 100, - }, { title: '业务订单号', key: 'orderSn', - width: 260, + width: 220, }, { - title: '商户订单号', - key: 'payLogOutTradeNo', - width: 260, + title: '下单用户', + key: 'memberId', + width: 100, + render(row: State) { + return renderPopoverMemberSumma(row.memberBySumma); + }, }, { title: '支付方式', @@ -143,6 +137,11 @@ export const columns = [ }, width: 150, }, + { + title: '商户订单号', + key: 'payLogOutTradeNo', + width: 220, + }, { title: '创建时间', key: 'createdAt', diff --git a/web/src/views/log/log/columns.ts b/web/src/views/log/log/columns.ts index a21e230..560439f 100644 --- a/web/src/views/log/log/columns.ts +++ b/web/src/views/log/log/columns.ts @@ -1,7 +1,5 @@ import { h } from 'vue'; -import { NTag, NEllipsis, NSpace } from 'naive-ui'; -import { timestampToTime } from '@/utils/dateUtil'; -import { renderHtmlTooltip } from '@/utils'; +import Column from './components/Column.vue'; export const columns = [ { @@ -14,49 +12,10 @@ export const columns = [ key: 'name', width: 180, render(row) { - const operator = - row.memberId === 0 ? row.memberName : row.memberName + '(' + row.memberId + ')'; - - return h( - NEllipsis, - { - style: { - maxWidth: '180px', - }, - }, - { - default: () => - h( - NSpace, - { vertical: true }, - { - default: () => [ - h('div', { - innerHTML: '

' + operator + '

', - }), - h('div', { - innerHTML: '

IP:' + row.ip + '

', - }), - row.cityLabel != '' - ? h( - NTag, - { - style: { - marginRight: '6px', - }, - type: 'primary', - bordered: false, - }, - { - default: () => row.cityLabel, - } - ) - : null, - ], - } - ), - } - ); + return h(Column, { + state: row, + column: 'visitor', + }); }, }, { @@ -64,43 +23,10 @@ export const columns = [ key: 'name', width: 260, render(row) { - return h( - NEllipsis, - { - style: { - maxWidth: '260px', - }, - }, - { - default: () => - h( - NSpace, - { vertical: true }, - { - default: () => [ - h( - NTag, - { - style: { - marginRight: '6px', - }, - bordered: false, - }, - { - default: () => row.method, - } - ), - h('div', { - innerHTML: '

接口:' + row.url + '

', - }), - h('div', { - innerHTML: '

名称:' + row.tags + ' / ' + row.summary + '

', - }), - ], - } - ), - } - ); + return h(Column, { + state: row, + column: 'request', + }); }, }, { @@ -108,39 +34,10 @@ export const columns = [ key: 'name', width: 260, render(row) { - return h( - NEllipsis, - { - style: { - maxWidth: '260px', - }, - }, - { - default: () => - h( - NSpace, - { vertical: true }, - { - default: () => [ - renderHtmlTooltip( - '

状态码:' + - row.errorMsg + - '(' + - row.errorCode + - ')' + - '

' - ), - h('div', { - innerHTML: '

处理耗时:' + row.takeUpTime + 'ms

', - }), - h('div', { - innerHTML: '

响应时间:' + timestampToTime(row.timestamp) + '

', - }), - ], - } - ), - } - ); + return h(Column, { + state: row, + column: 'response', + }); }, }, { diff --git a/web/src/views/log/log/components/Column.vue b/web/src/views/log/log/components/Column.vue new file mode 100644 index 0000000..e07a58c --- /dev/null +++ b/web/src/views/log/log/components/Column.vue @@ -0,0 +1,77 @@ + + + + + diff --git a/web/src/views/log/log/components/props.ts b/web/src/views/log/log/components/props.ts new file mode 100644 index 0000000..0221c96 --- /dev/null +++ b/web/src/views/log/log/components/props.ts @@ -0,0 +1,12 @@ +import { State } from '@/views/log/log/model'; + +export const basicProps = { + state: { + type: State, + default: null, + }, + column: { + type: String, + default: '', + }, +}; diff --git a/web/src/views/log/log/index.vue b/web/src/views/log/log/index.vue index 5172646..b972905 100644 --- a/web/src/views/log/log/index.vue +++ b/web/src/views/log/log/index.vue @@ -53,7 +53,6 @@ const dialog = useDialog(); const batchDeleteDisabled = ref(true); const checkedIds = ref([]); - const router = useRouter(); const message = useMessage(); const actionRef = ref(); diff --git a/web/src/views/log/log/model.ts b/web/src/views/log/log/model.ts index 739c259..de23bb6 100644 --- a/web/src/views/log/log/model.ts +++ b/web/src/views/log/log/model.ts @@ -48,16 +48,15 @@ export const schemas = ref([ }, }, { - field: 'memberId', - component: 'NInput', + field: 'complexMemberId', + component: 'ComplexMemberPicker', label: '操作人', componentProps: { - placeholder: '请输入操作人ID', + placeholder: '请选择操作人', onInput: (e: any) => { console.log(e); }, }, - rules: [{ trigger: ['blur'] }], }, { field: 'url', diff --git a/web/src/views/permission/menu/editForm.vue b/web/src/views/permission/menu/editForm.vue index 3fc245e..efa31b5 100644 --- a/web/src/views/permission/menu/editForm.vue +++ b/web/src/views/permission/menu/editForm.vue @@ -129,18 +129,12 @@ - 请填写API路径地址,可同时作用于server端接口鉴权和web端细粒度权限。一次添加多个权限用,分割 + 请填写API路径地址,可同时作用于server端接口鉴权和web端细粒度权限 分配权限 - - - - - - diff --git a/web/src/views/system/config/UploadSetting.vue b/web/src/views/system/config/UploadSetting.vue index 48fcefb..2ad5573 100644 --- a/web/src/views/system/config/UploadSetting.vue +++ b/web/src/views/system/config/UploadSetting.vue @@ -8,7 +8,6 @@ ref="formRef" label-placement="top" > - 基础设置 - - - - - - - - - - - - - - - - - - - - - 本地存储 + - - - 阿里云OSS存储 + - - - 腾讯云COS存储 +