Compare commits

...
Author SHA1 Message Date
zhangwenjian 9914373d45 test🧪: run the assertion through the function it is about
Review caught that this reissued getByRoleName's query instead of
calling it, so it passed whether or not the production line still said
what it was supposed to — a test named for a change it did not touch.

It calls getByRoleName now, and restoring the hand-written clause fails
it for exactly the reason this PR exists: with the marker non-null,
"deleted_at is null" matches nothing and the query returns an empty
list.
2026-08-22 11:40:38 +08:00
zhangwenjian 4911730012 fix🐛: give the natural keys a constraint the database can keep
sys_user.username, sys_role.role_key and sys_dict_type.dict_type had no
unique index. Uniqueness was a SELECT COUNT followed by an INSERT, which
two concurrent requests both pass — and login resolves a username with
First, so which of the two accounts answers is whichever the database
returns.

The index cannot be on the key alone, because a soft-deleted row keeps
occupying the name and a deleted user's username could never be used
again. It has to include the delete marker, and the marker has to be
non-null: two live rows are (alice, NULL) and (alice, NULL), and NULL is
not equal to NULL, so an index over a nullable marker admits both. That
is the worst of the three states — a constraint that reads as protection
and binds nothing — and there is a test that demonstrates it rather than
asserting it.

ModelTime.DeletedAt is milliseconds since the epoch now, zero while the
row is live. Sixteen tables carry it; the migration converts each one,
preserving when each deleted row was deleted, then adds the three
indexes.

Written to be re-runnable rather than transactional, because DDL does not
roll back on MySQL and an operator whose first attempt failed halfway
should have nothing to do but run it again. It refuses before altering
anything if a table already holds duplicates, naming them, rather than
letting the index fail and leaving the operator to guess.

The timestamp conversion happens in Go: turning a timestamp into epoch
milliseconds is spelled differently by every dialect this supports, and
these row counts do not justify four versions of it.
2026-08-22 11:27:22 +08:00
zhangwenjian 88bab51056 fix🐛: stop hand-writing the soft-delete condition, and check the count
Two things in front of the unique-index work, both safe on their own.

getSysMenuByRoleName carried "deleted_at is null" in its where clause.
GORM adds that condition itself for a model with a DeletedAt field, so
it was a duplicate — and one phrased as a column being null, which stops
being true the moment the column stops being nullable. A schema that
moves to a non-null delete marker would have turned this query into one
that matches nothing, silently, for admin users only.

SysDictType.Insert dropped the error from its duplicate check: a query
that failed left the count at zero and the insert went ahead as though
the name were free.

The test pins what the removed clause was there for. Its counter-proof
is Unscoped rather than deleting the field — taking ModelTime off the
model fails to compile, which proves nothing.
2026-08-22 11:11:03 +08:00
wenjianzhang 0fd4f68b6c Merge pull request #861 from go-admin-team/docs/fix-stale-queue-redis-sample
fix: correct the commented-out queue.redis sample in settings.yml
2026-08-20 11:01:03 +08:00
zhangwenjian c66cb5c6a8 fix: correct the commented-out queue.redis sample in settings.yml
The sample had producer/consumer nested keys (streamMaxLength,
approximateMaxLength, visibilityTimeout, bufferSize, concurrency,
blockingTimeout, reclaimInterval) that don't exist on config.RedisQueue —
checked against sdk/config/queue.go, which only reads addr, password, and the
embedded RedisOptions fields, plus group, key_prefix and max_attempts. Filling
in the old sample as written would compile and start fine, since it's YAML
under a key the struct doesn't declare, and every one of those settings would
be silently ignored.

Replaced with the fields the struct actually has. Still commented out —
redis stays opt-in, this only fixes what filling it in would produce.
2026-08-20 10:54:53 +08:00
wenjianzhang b16ec0af77 Merge pull request #860 from go-admin-team/chore/upgrade-core
chore🔧: upgrade go-admin-core and route the queue through configuration
2026-08-18 22:48:00 +08:00
zhangwenjian 82ea8539eb chore🔧: upgrade go-admin-core and route the queue through configuration
The pinned core dated from April, before sdk stopped being a separate module,
so the build resolved sdk packages from the old module and core packages from
the new one. Dropping the separate requirement is what makes the two agree
again.

Most of the diff is renames that came with that: the tenant accessors gained a
ByTenant suffix, GetDb now returns one database and GetAllDb the map, and
casbin moved to v3.

The change that matters is four call sites moving from GetMemoryQueue to
GetQueuePrefix. GetMemoryQueue returns a queue fixed at construction, so the
login log, the operate log and the api check ran in process no matter what the
settings file selected — a second instance saw none of it. GetQueuePrefix
returns whatever the configuration built, which is the point of being able to
configure a queue at all.

Verified against core at main: build and vet clean. The two file_store failures
are unchanged from before this branch; they need cloud credentials.
2026-08-18 22:14:08 +08:00
wenjianzhang d17d5c1206 Merge pull request #859 from go-admin-team/docs/clarify-demo-sites
docs📝: 标注 antd 演示站对应 go-admin-pro
2026-08-16 19:31:25 +08:00
zhangwenjian 041d22d0d2 docs📝: 标注 antd 演示站对应 go-admin-pro
README 中两个演示地址并排列出、格式与账号密码完全相同,看不出 antd 站对应
的是另一个产品。用户在该站遇到问题时会认为是本仓库的缺陷(见 #857:登录
返回的错误码在本仓库中并不存在)。

仅在链接文字中补充产品名,不改变呈现方式。
2026-08-16 12:04:26 +08:00
wenjianzhang 5864058a81 Merge pull request #858 from go-admin-team/chore/bump-version-2.4.0
chore🔧: 版本号升至 2.4.0
2026-08-16 11:17:51 +08:00
zhangwenjian 45035a16e4 chore🔧: 版本号升至 2.4.0 2026-08-16 11:14:28 +08:00
wenjianzhang f4d0108d49 Merge pull request #855 from go-admin-team/fix/remove-refresh-token-endpoint
fix🐛: 移除 refresh_token 接口,修复 token 可无限续期问题
2026-08-16 11:08:41 +08:00
zhangwenjian b81611ba72 chore🔧: 清理 refresh_token 的残留权限数据
接口移除后,库中仍留有三类记录:sys_api 的接口登记、sys_menu_api_rule 的
菜单绑定、casbin_rule 的策略。留着会让「接口管理」列出一个不存在的端点,
角色配置里也仍可勾选。

- 新装:从 db.sql 与 db-sqlserver.sql 的种子数据中删除该接口
- 已有部署:新增迁移清理,按 path 匹配而非固定 id,因为执行过
  `server -a` 重新注册接口的库中 id 会与官方种子数据不同
2026-08-14 21:42:59 +08:00
zhangwenjian bb34108831 fix🐛: 移除 refresh_token 接口,修复 token 可无限续期问题
close #820

GET /api/v1/refresh_token 用业务 token 即可换取新 token,而续期上限
MaxRefresh 依据的 orig_iat 在每次续期时被一并重置,上限永远无法到达 ——
token 一旦泄露即等同于永久访问权,且无任何吊销手段。

该路由此前还位于 CasbinExclude 中,不受 Casbin 约束,任何角色的已登录用户
都可调用。

官方前端从未使用它:store 中虽有 refreshToken action,但全仓库无一处
dispatch,属死代码。移除不影响正常登录与鉴权流程。

破坏性变更:自行调用该端点实现续期的使用者需改为重新登录。正确的无感续期
应在 go-admin-core 中区分 access token 与 refresh token 后重新实现,不应
沿用此路由。
2026-08-14 21:42:52 +08:00
wenjianzhang b7fd92f39b Merge pull request #854 from go-admin-team/docs/agents-and-demo-module
feat✨: 新增 app/demo 参照模块与 AGENTS.md 规范文档
2026-08-14 21:37:57 +08:00
zhangwenjian 63b800a3ba docs📝: 补充 sqlite3 构建标签与迁移目录说明
driver 配置为 sqlite3 时不带 -tags sqlite3 会在 nil 函数上 panic,
报错不提及构建标签,容易误判为环境损坏;同时说明 version/ 与
version-local/ 的区别,后者已被 gitignore,提交到本仓库的迁移必须放 version/。
2026-08-14 21:17:37 +08:00
zhangwenjian ed9450a2d5 feat✨: 补充 demo 模块的菜单与权限种子数据
一个业务模块要在界面上可用,需要四类数据协同:

  sys_api           后端路由登记,Casbin 据此判定
  sys_menu          侧边栏菜单,含目录 M、菜单 C、按钮 F 三级
  sys_menu_api_rule 菜单与接口的关联,角色保存时据此生成策略
  casbin_rule       实际生效的权限策略

菜单的 menu_name 与前端组件 name 保持一致(DemoProduct),按钮的
permission 与前端 v-permisaction 标识一致(demo:product:add 等)。

策略写入 casbin_rule 而非 sys_casbin_rule:后者对应的 models.CasbinRule
是历史遗留,其 7 列 size:512 唯一索引在 MySQL 下会超出索引长度限制,实际
生效的是 adapter 创建的 casbin_rule 表。

所有写入均为存在则更新、不存在则插入,迁移可安全地在已有数据的库上执行。
实测:在含 67 条菜单、121 条接口的库上执行后各表数据正确;清除版本记录重
跑一次,各表行数不变,确认幂等。
2026-08-14 16:57:55 +08:00
zhangwenjian 1d551a10ab docs📝: 新增 AGENTS.md 与架构说明
AGENTS.md 是给 AI 编码工具与新贡献者的约定,只记录「不遵守就会出错」的
规则,技术栈版本与命令交由 go.mod 和 Makefile 表达,避免文档与代码脱节。
标准写法指向 app/demo/——那是可编译、有测试的参照物,文档与它冲突时以它
为准。

docs/architecture.md 承载不易从代码直接读出的语义:DataScope 五档的过滤
方式、定时任务的 JobExec 接口、多数据源约束、迁移目录的分工。

内容整理自此前未纳入版本控制的 CLAUDE.md,撰写时逐条对照代码核实,修正
了其中两处失效描述(构建工具已非 Vue CLI;JobExec 的方法是 Exec(interface{})
而非 Run(string))。CLAUDE.md 现改为指向 AGENTS.md 的软链,两者不再各自
漂移。
2026-08-14 16:49:48 +08:00
zhangwenjian 4d7c9e5a12 feat✨: 补充 demo 模块的建表迁移
放在 version/ 而非 version-local/:后者已被 .gitignore 忽略,是留给使用
者存放自身迁移脚本的位置,示例迁移需随框架一起分发。文件注释中说明了这
一区分。
2026-08-14 16:46:53 +08:00
zhangwenjian d1f5fe5681 feat✨: 新增 app/demo 标准 CRUD 参照模块
作为编码约定的可执行参照物:文档会滞后,而这个模块过时会导致构建或测试
失败,因此以它为准。

目录骨架与自动注册文件由项目自带的脚手架生成:

  go run main.go app -n demo

它同时产出 cmd/api/demo.go,其中的 init() 将路由追加进 AppRouters,
无需在任何中心文件手工登记。

模块本身演示了单表 CRUD 的推荐写法——直接使用 common/actions 提供的五个
通用 Action,因此只有 model、dto、router 三个业务文件,没有 apis 与
service。手写 Handler 的场景仅在业务超出单表 CRUD 时才需要。

DTO 中详情/删除入参内嵌 dto.ObjectById 以复用其 Bind 与 GetId,不重复
实现 uri 绑定与批量 ids 合并逻辑。

补充 8 项测试锁定通用 Action 的接口约束,其中最关键的是 Generate() 必须
返回副本——Action 在并发请求间复用实例,就地返回会串数据。反向验证:将
Generate 改为就地返回,测试立即失败。
2026-08-14 16:46:09 +08:00
zhangwenjian e8c2e0a966 chore🔧: 修正 .DS_Store 忽略规则
原规则 `*/.DS_Store` 只匹配子目录一层,仓库根目录下的 .DS_Store 不在其
中。改为 `.DS_Store`,匹配任意层级。
2026-08-14 16:45:55 +08:00
wenjianzhang cef0a19a9c Merge pull request #853 from go-admin-team/fix/community-pr-batch
fix🐛: 处理社区 PR 中仍然成立的四项修复
2026-08-14 15:46:43 +08:00
zhangwenjian c0e81363dc docs📝: 修正 Makefile 注释错别字
「实际决对路径」→「实际绝对路径」。

问题由 PR #847 指出。
2026-08-14 15:35:55 +08:00
zhangwenjian df2e4a2b48 fix🐛: 修正欢迎页 iframe 高度塌陷
页面通过 JS 计算并设置 iframe 高度,但 html 与 body 未声明高度,
百分比高度失去参照,iframe 在部分场景下塌陷为 0。

补充 html,body{height:100%} 与 iframe 的 height:100%,并为原先缺失的
overflow-y 声明补上分号。

问题由 PR #829 指出。
2026-08-14 15:35:55 +08:00
zhangwenjian 9088ebc2e1 refactor🎨: 修正文件名拼写 int_router.go → init_router.go
该文件内容为 init() 函数中的路由注册,原文件名少了一个字母。

问题由 PR #787 指出。
2026-08-14 15:35:55 +08:00
zhangwenjian 9f2dec3036 fix🐛: 修正 GeneralDelDto.GetIds 重复追加 Id
该方法先在开头追加了 Id,随后 else 分支中又追加一次:仅传 Id 时返回
[5 5],删除接口会对同一条记录执行两次 DELETE。

  if g.Id != 0 { ids = append(ids, g.Id) }
  if len(g.Ids) > 0 { ... } else {
      if g.Id > 0 { ids = append(ids, g.Id) }   // 重复
  }

去掉冗余分支,同时将首个判断由 != 0 收紧为 > 0,与 Ids 中逐个元素的
过滤条件保持一致(负数 Id 无意义)。

补充单元测试,覆盖仅 Id、仅 Ids、二者并存、含非正数、全空回退等场景。

问题由 PR #848 指出。
2026-08-14 15:35:55 +08:00
wenjianzhang ea049f9b06 Merge pull request #852 from go-admin-team/fix/ci-deploy-guard
fix🐛: 限制部署步骤仅在 master 收到 push 时执行
2026-08-12 15:41:26 +08:00
zhangwenjian 1f1349a685 docs📝: 更新在线体验地址
Element UI vue2 演示站已升级为 Element Plus + Vue 3,域名同步更换为
vue.go-admin.pro。

Arco Design vue3 演示站(vue3.go-admin.dev)已下线,移除对应条目。
2026-08-12 12:27:41 +08:00
zhangwenjian dcef2df38e fix🐛: 限制部署步骤仅在 master 收到 push 时执行
本工作流同时由 push 与 pull_request 触发,而推送镜像与重启服务两步没有
任何事件限制。其后果是:任何指向 master 的 PR 一经创建,就会把 PR 分支
构建出的镜像推送到镜像仓库,并 docker rm -f 掉线上容器、用该镜像重新启
动 API 服务——发生在代码被审查和合并之前。

同仓库分支发起的 PR 可以取到 secrets,因此该路径实际可达;历史运行记录
中已多次出现由 pull_request 事件触发的成功部署。

为两步加上 event_name 与 ref 双重判断。额外判断 ref 是考虑到日后若有人
向 on.push.branches 追加分支,部署不会随之扩散。

Tidy 与 Build 不受影响,PR 仍会执行编译校验。
2026-08-12 12:27:33 +08:00
zhangwenjian 92834d6e39 publish🚀: 版本号更新至 2.3.0 2026-08-12 00:22:31 +08:00
zhangwenjian f06540883b fix🐛: 修复 Docker 镜像发布的 tag 条件失效问题
if 表达式中不应使用 ${{ }} 包裹:startsWith(${{github.ref}}, 'refs/tags/')
会先将 github.ref 替换为裸字符串再参与表达式求值,导致条件判断失效,
使得每次 push 到 master 都会构建并推送镜像至 ghcr.io,而非仅在打 tag 时发布。

同时 on.push 缺少 tags 配置,打 tag 实际不会触发该工作流。

修正后:push 分支仅执行 Go 构建,打 tag 才发布镜像。
2026-08-11 11:09:39 +08:00
zhangwenjian 3c9ce5b6b0 chore🔧: 升级 x/image 修复 TIFF 解码漏洞 2026-08-10 22:17:28 +08:00
zhangwenjian ff8a59550a fix🐛: 修复镜像同步因浅克隆被拒绝的问题 2026-08-10 21:21:01 +08:00
zhangwenjian 7cddef33a2 git🙈: 将 go.sum 纳入版本控制 2026-08-10 20:51:00 +08:00
zhangwenjian 7013c2fa4a chore🔧: 移除依赖已封禁 action 的 issue 自动化流程 2026-08-10 20:51:00 +08:00
zhangwenjian 65bacacb38 docs📝: 更新 README 环境要求版本说明 2026-08-10 20:45:39 +08:00
zhangwenjian 45587028c3 config🔧: CI 升级 Go 版本并更新 Actions 至最新 2026-08-10 20:45:39 +08:00
zhangwenjian 887c9cca4b chore🔧: 升级 Go 至 1.26.5 并同步升级依赖 2026-08-10 20:45:36 +08:00
wenjianzhang a6ddb113fc Update LICENSE.md 2026-08-08 13:55:08 +08:00
wenjianzhang b83eef8670 Fix image source in README.md
Updated image source in README.md for go-admin.
2026-05-22 11:20:39 +08:00
zhangwenjian 43dcd61c51 config🔧: update go-version to 1.24 in build workflow
go.mod requires go 1.24, go mod tidy fails when runner uses 1.18.
2026-05-15 17:52:12 +08:00
zhangwenjian 1bd64d4562 config🔧: pin all GitHub Actions to full-length commit SHAs
Replace version tags (@v1/@v2/@v3/@master) with pinned commit SHAs
across all workflow files to satisfy go-admin-team organization
security policy requiring immutable action references.
2026-05-15 17:48:41 +08:00
zhangwenjian 44e81bc72f git🙈: 补充忽略本地开发配置文件
- 新增忽略 config/settings.local.dev.yml
2026-05-15 17:37:42 +08:00
zhangwenjian 3312f8b7b9 chore🔧: 升级依赖 mergo 模块路径
- 替换 github.com/imdario/mergo 为上游迁移后的 dario.cat/mergo v1.0.1
2026-05-15 17:37:42 +08:00
zhangwenjian d6a2272f9d git🙈: 完善 .gitignore 忽略规则
- 新增忽略编译产物 go-admin-server
- 新增忽略本地工具配置目录
2026-05-15 17:37:42 +08:00
wenjianzhang a5cc0a9e29 Add read and write timeout to HTTP server 2025-09-10 09:39:54 +08:00
wenjianzhang 3f995735e9 Merge pull request #834 from hosea3000/edit-no-confirm
点击编辑的时候不需要弹框确认,交互不太友好
2025-05-20 11:41:02 +08:00
wenjianzhang b65b74dee5 Merge pull request #832 from hosea3000/fix-number-input
fix🐛: 修复自动生成代码时选择字段类型为int64, 前端提交还是string 导致报错的问题
2025-05-20 11:40:21 +08:00
Hosea 98cf3ad95a fix🐛: 点击编辑的时候不需要弹框确认,交互不友好 2025-05-20 10:57:36 +08:00
Hosea 8649d8d791 fix🐛: 修复自动生成代码时选择字段类型为int64, 前端提交还是string 导致报错的问题 2025-05-13 15:48:45 +08:00
wenjianzhang 817e34c6aa refactor🎨: 重构文件上传逻辑,拆分处理函数以提高可读性和维护性 2025-04-13 22:20:06 +08:00
wenjianzhang 952cd92648 refactor🎨: 清理 sys_server_monitor.go 文件,移除未使用的导入并格式化代码 2025-04-13 22:17:17 +08:00
wenjianzhang 6b1e961a7f refactor🎨: 重构系统监控代码,拆分功能为多个函数以提高可读性和维护性 2025-04-13 22:15:10 +08:00
wenjianzhang 762eba5af7 refactor🎨: 重构 Setup 函数,拆分为多个子函数以提高可读性和维护性 2025-04-13 22:04:12 +08:00
wenjianzhang e82128f679 refactor🎨: 优化获取客户端 IP 的逻辑,增加对 X-Forwarded-For 和 X-Real-IP 的处理 2025-04-13 22:00:04 +08:00
wenjianzhang 8f8a197db1 delete🎉: 移除示例代码 run.go 2025-04-08 20:49:36 +08:00
wenjianzhang 364854eda0 docs📝: 更新 go-admin 版本号至 2.2.0 2025-04-08 20:49:29 +08:00
wenjianzhang b259e91f4d Merge remote-tracking branch 'origin/master'
# Conflicts:
#	go.mod
2025-04-08 20:45:25 +08:00
wenjianzhang 76411f80bc refactor🎨: 优化日志记录方式,统一使用 log.Info 替代 log.Println 2025-04-08 20:30:35 +08:00
wenjianzhang 5494353229 fix🐛: 修复获取本地主机IP的函数调用错误 2025-04-08 20:30:24 +08:00
wenjianzhang afe5efbe36 refactor🎨: remove unused distributed lock setup code in initialize.go 2025-04-08 20:30:05 +08:00
wenjianzhang db422785fc fix🐛: include captcha answer in GenerateCaptchaHandler for improved logging 2025-04-08 20:29:38 +08:00
wenjianzhang 4ac68323da fix: improve error logging in jobbase.go for better clarity 2025-04-08 20:23:23 +08:00
wenjianzhang 44002fcb11 chore: update dependencies in go.mod to latest versions 2025-04-08 20:22:59 +08:00
wenjianzhang 5bbd919745 chore: update dependencies in go.mod to latest versions 2025-03-25 17:16:40 +08:00
wenjianzhang 54dd3de5b6 chore: update dependencies in go.mod to latest versions 2025-03-25 16:48:47 +08:00
wenjianzhang 9540fdfc30 refactor: remove unused GetMenuIDS function and clean up code 2025-03-25 16:44:31 +08:00
wenjianzhang 937775e2a7 chore: update Go version from 1.21 to 1.24 in build configuration 2025-03-25 08:53:39 +08:00
wenjianzhang 84721265dd fix: simplify error handling in GenerateCaptchaHandler 2025-03-24 22:41:02 +08:00
wenjianzhang 3ab67dfa7d chore: update Go version from 1.21 to 1.24 2025-03-24 20:53:09 +08:00
wenjianzhang 6a1941a820 Merge pull request #814 from keemozhang/master
fix🐛: declaration of new local variable causes transactions to be ign…
2025-03-21 15:36:16 +08:00
wenjianzhang 3ae7c44585 Merge pull request #816 from Tiper-In-Github/patch-1
Fix:err is never used
2025-03-21 15:35:23 +08:00
wenjianzhang 9d809f6392 Merge pull request #821 from pigwantacat/master
fix:修复定时任务的日志打印
2024-12-18 00:11:54 +08:00
pigwantacat 4b477b3103 fix:修复定时任务的日志打印 2024-11-01 14:14:30 +08:00
wenjianzhang e7ae2fe019 更新 go_admin.go 2024-10-30 22:12:17 +08:00
wenjianzhang d5ba3d9770 更新 READMEN.md 2024-10-30 22:10:06 +08:00
Akiraka f3d744f6f5 修复获取getinfo时候,userName 事件结果为 nickName 问题 2024-10-24 09:30:15 +08:00
无别 0315631b53 Fix:err is never used
Fix the problem that err is overwritten and becomes invalid
2024-09-29 15:32:36 +08:00
wenjianzhang 48e7ce88ff perf👌: rollback base64Captcha 2024-09-09 15:46:05 +08:00
wenjianzhang 357db6b1c9 Merge remote-tracking branch 'origin/master' 2024-09-08 22:04:20 +08:00
wenjianzhang 83e0531f43 perf👌: format 2024-09-08 22:04:08 +08:00
wenjianzhang 898ba7d8eb Update README.Zh-cn.md 2024-09-06 23:11:48 +08:00
wenjianzhang 8751f34539 perf👌: correct attribute definition 2024-09-05 18:33:11 +08:00
wenjianzhang 4aa0068d2d perf👌: update SysDept Get First to FirstOrInit 2024-09-05 18:29:50 +08:00
keemozhang b954a2f092 fix🐛: declaration of new local variable causes transactions to be ignored 2024-09-05 15:46:20 +08:00
wenjianzhang 9227bd2be1 perf👌: format code 2024-09-04 20:25:02 +08:00
wenjianzhang e70a0b1314 perf👌: update SysConfig Get First to FirstOrInit 2024-09-04 20:22:49 +08:00
wenjianzhang 21c262a31e perf👌: update build file 2024-09-03 22:17:11 +08:00
wenjianzhang f30889bd19 perf👌: update SysApi Get Func First to FirstOrInit 2024-09-03 21:22:09 +08:00
wenjianzhang 23e519999e perf👌: update go mod 2024-08-30 16:00:29 +08:00
wenjianzhang bedf064ace Merge pull request #802 from zhanluxianshen/drop-base-model
replace basemodel by common.model
2024-08-29 16:26:22 +08:00
wenjianzhang 9a8e0cddde Merge pull request #803 from zhanluxianshen/clean-err-use-in-method
clean err define in methods.
2024-08-29 16:23:54 +08:00
wenjianzhang c0c16036d3 Merge pull request #811 from wangle201210/fix/logger
fix🐛: reset default logger fields
2024-08-29 16:17:18 +08:00
wanna dd905a2bed fix🐛: reset default logger fields 2024-08-23 16:49:21 +08:00
zhanluxianshen 2d76430f89 clean err define in methods.
Signed-off-by: zhanluxianshen <zhanluxianshen@163.com>
2024-07-10 15:03:33 +08:00
zhanluxianshen 5dde1d2a00 replace basemodel by common.model
Signed-off-by: zhanluxianshen <zhanluxianshen@163.com>
2024-07-10 11:26:52 +08:00
lwnmengjing 93f25c6cdf Add mss-boot-io link 2023-11-07 23:28:52 +08:00
wenjianzhang d366df372d feat✨: Log file size control and retention days control 2023-11-03 18:59:20 +08:00
wenjianzhang 7281d05efc fix🐛: Fixed system startup Network output problem 2023-11-03 17:42:01 +08:00
wenjianzhang e6d6a65267 Merge remote-tracking branch 'origin/master' 2023-11-03 17:36:21 +08:00
wenjianzhang 9ff094b6f5 fix🐛: Fixed data migration issue during multi-tenant configuration 2023-11-03 17:36:04 +08:00
wenjianzhang fc9c253a9f tag📌: Upgrade go1.21 2023-11-03 17:35:01 +08:00
wenjianzhang 9d735ed5aa docs📝: Update README.md 2023-11-02 17:42:40 +08:00
wenjianzhang d782b00117 tag📌: Change version 2023-11-02 17:10:52 +08:00
wenjianzhang 239159dd2a fix🐛: Fix the problem that el-popconfirm does not take effect 2023-11-02 17:08:58 +08:00
wenjianzhang 0c1e91c3b5 Add files via upload 2023-10-11 21:25:01 -05:00
wenjianzhang c09347b387 Merge pull request #768 from majiayu000/fix-pgerror
[BugFix] 修复一个``引发的bug
2023-10-11 21:18:42 -05:00
lif e49e47c7a1 Delete go.mod 2023-09-22 14:02:38 +08:00
wenjianzhang 98b46535aa Merge pull request #767 from zgxme/fix-gen-0909
[fix](gen) ignore default time type columns in table
2023-09-21 22:00:57 +08:00
lif 014a23aac3 [BugFix] Fix pgsql error with 2023-09-14 16:35:41 +08:00
zgxme f1dfba79e0 [fix](gen) ignore default time type columns in table 2023-09-09 22:59:45 +08:00
wenjianzhang a282e44b1d Merge pull request #753 from Vingurzhou/master
-installsuffix 参数没有指定后缀字符串。它被设定为空,这可能导致一些问题
2023-08-02 09:24:48 +08:00
wenjianzhang d1279e67fb Merge pull request #757 from NipGeihou/master
fix: 修复go generate命令不更新Swagger文档问题
2023-08-02 09:22:25 +08:00
wenjianzhang 37a5963cd6 perf👌: Optimize go warnings 2023-08-01 22:38:41 +08:00
wenjianzhang 69df1b3d34 perf👌: Remove unused attributes 2023-08-01 22:12:18 +08:00
wenjianzhang eae97f7a15 perf👌: update version 2023-08-01 22:08:47 +08:00
wenjianzhang ce0b5ff7bf perf👌: update version 2023-08-01 22:08:43 +08:00
NipGeihou 73118e49b9 fix: 修复go generate命令不更新Swagger文档问题
修复go generate不更新Swagger文档问题,并更新生成后文档文件
2023-06-20 00:37:59 +08:00
Vingurzhou 7b43982595 Update Makefile
fix(makefile): -installsuffix 参数没有指定后缀字符串。它被设定为空,这可能导致一些问题
2023-06-10 15:57:18 +08:00
wenjianzhang 31cd1ee768 Merge pull request #741 from wwhai/patch-2
fix: change 'os.Signal' channel to buffered
2023-05-14 11:04:04 +08:00
wenjianzhang 8df7551946 Merge pull request #740 from llussy/patch
fix setting.yml spelling
2023-05-14 11:03:47 +08:00
wenjianzhang 79c1295a70 Merge pull request #749 from sincatter/master_fix_pg_migrate
处理postgres迁移时insert提示类型不匹配问题
2023-05-14 11:03:07 +08:00
wenjianzhang 26d9a2e9e4 Merge pull request #747 from go-admin-team/dependabot/go_modules/golang.org/x/net-0.7.0
build(deps): bump golang.org/x/net from 0.0.0-20220722155237-a158d28d115b to 0.7.0
2023-05-13 15:38:46 +08:00
wenjianzhang b09b7b6ccc Merge pull request #729 from go-admin-team/dependabot/go_modules/github.com/prometheus/client_golang-1.11.1
build(deps): bump github.com/prometheus/client_golang from 1.11.0 to 1.11.1
2023-05-13 15:38:13 +08:00
dependabot[bot] ef6fdaa221 build(deps): bump golang.org/x/net
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20220722155237-a158d28d115b to 0.7.0.
- [Commits](https://github.com/golang/net/commits/v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-13 07:38:07 +00:00
wenjianzhang 23c80f0217 Merge pull request #735 from go-admin-team/dependabot/go_modules/golang.org/x/text-0.3.8
build(deps): bump golang.org/x/text from 0.3.7 to 0.3.8
2023-05-13 15:37:14 +08:00
wenjianzhang 95dc699e2e Merge pull request #746 from haimait/fix_edit_master_role模块添加注释
fix_edit_master_role模块添加注释
2023-05-13 15:36:29 +08:00
wenjianzhang 74b7d62c75 处理postgres迁移时insert提示类型不匹配问题 2023-05-13 00:00:35 +08:00
wanghaima 68accd5448 fix_edit_master_role模块添加注释 2023-05-07 19:33:00 +08:00
wenjianzhang 3edbef8696 Merge pull request #745 from haimait/fix_edit_master_优化api筛选
优化API管理筛选
2023-05-07 19:22:23 +08:00
wanghaima 5527f6386a 优化API管理筛选 2023-05-07 18:47:36 +08:00
wwhai c48f70a7c6 fix: change 'os.Signal' channel to buffered 2023-05-04 23:25:43 +08:00
llussy a078e31664 fix setting.yml 2023-04-26 15:59:19 +08:00
wenjianzhang 04d2d7dde1 format🥚: Exclude empty permission identification 2023-04-19 18:50:35 +08:00
Akiraka b846053bea 恢复 common/middleware/demo.go 2023-04-14 19:51:48 +08:00
Akiraka a1a5634c4e 恢复修改 2023-04-14 19:51:22 +08:00
Akiraka 6036c6e4e3 接受参数位置错误 2023-04-14 19:07:01 +08:00
wenjianzhang 7d74e6f325 Merge pull request #732 from wenyoufu/master
【bug】修复普通用户只用查询权限时,无法修改个人信息(昵称、用户密码)的bug
2023-03-14 01:14:43 +08:00
dependabot[bot] 1bf9f74bdf build(deps): bump golang.org/x/text from 0.3.7 to 0.3.8
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.3.7 to 0.3.8.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.3.7...v0.3.8)

---
updated-dependencies:
- dependency-name: golang.org/x/text
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-23 00:08:28 +00:00
ford f61de5beeb 【bug】修复普通用户只用查询权限时,无法修改个人信息(昵称、用户密码)的bug 2023-02-17 19:24:50 +08:00
dependabot[bot] 79fb2d0bee build(deps): bump github.com/prometheus/client_golang
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.11.0 to 1.11.1.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.11.0...v1.11.1)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-15 01:38:52 +00:00
wenjianzhang c973d6819c docs📝: update readme 2022-12-13 11:47:04 +08:00
wenjianzhang 3d8b879e64 docs📝: update readme 2022-12-13 11:45:28 +08:00
wenjianzhang ac971bda4b fix🐛: 忽略pkg包 2022-12-08 18:00:33 +08:00
wenjianzhang 44f62abbca fix🐛: 添加引用 2022-11-16 16:47:32 +08:00
wenjianzhang 7d7d8484d4 fix🐛: demo中间件添加环境判断 2022-11-16 12:05:33 +08:00
zhangwenjian c8b27492eb fix🐛: update sqlite3 configuration 2022-11-09 17:36:04 +08:00
zhangwenjian 783f79dcb6 Merge remote-tracking branch 'origin/master' 2022-11-09 17:35:31 +08:00
zhangwenjian ddd97d5a9e fix🐛: Adjust the demo environment configuration 2022-11-09 17:35:16 +08:00
wenjianzhang fa73c3d6b1 patch🚑: update restart 2022-11-03 14:55:02 +08:00
wenjianzhang 5b2f3e9316 Merge pull request #720 from ruishawn/dev
Docs: update README
2022-11-03 14:03:35 +08:00
zhangwenjian 42f3025217 fix🐛: Fix the problem that api saving fails when creating a new menu 2022-11-03 14:00:48 +08:00
wenjianzhang 5df43b4d11 docs📝: update readme 2022-11-02 10:18:32 +08:00
wenjianzhang eac1bf197e docs📝: update readme 2022-11-01 19:16:01 +08:00
wenjianzhang 5c834939af docs📝: update readme 2022-11-01 19:13:37 +08:00
zhangwenjian 642e86951b Merge branch 'master' of github.com:go-admin-team/go-admin 2022-11-01 16:58:11 +08:00
zhangwenjian bc42412e92 perf👌: 更新logo 2022-11-01 16:57:28 +08:00
wenjianzhang d9122d29cb docs📝: update readme 2022-11-01 16:54:19 +08:00
wenjianzhang b532ad994c docs📝: update readme 2022-11-01 16:53:42 +08:00
zhangwenjian b62fbc803c perf👌: 更新演示环境数据库名称 2022-11-01 15:02:36 +08:00
zhangwenjian ed8bac8a1b perf👌: 更新ci脚本 2022-11-01 15:00:41 +08:00
zhangwenjian d56142463a perf👌: 添加演示环境配置项 2022-11-01 14:58:18 +08:00
zhangwenjian f795a356e7 perf👌: 更新CI脚本中的分支 2022-11-01 14:14:27 +08:00
zhangwenjian a359c25e36 perf👌: 添加CI脚本 2022-11-01 14:13:53 +08:00
xiaobo 0ef422d309 fix: update README
Update README file: update dependencies before build.
2022-10-27 16:12:50 +08:00
wenjianzhang e0519a4d7e docs📝: update antd view url 2022-10-26 23:38:18 +08:00
wenjianzhang 5043ce5411 docs📝: update antd view url 2022-10-26 23:37:16 +08:00
wenjianzhang cc0cdc7d0e Merge pull request #710 from zyd/master
fix🐛:e.Log.Errorf("db error:%s", err)输出的err没有被赋值
2022-10-08 15:00:33 +08:00
zhaodongdong c004b3d333 fix🐛:e.Log.Errorf("db error:%s", err)输出的err没有被赋值 2022-09-14 17:42:09 +08:00
wenjianzhang 453dd65cb1 docs📝: update readme zh 2022-09-14 12:24:02 +08:00
wenjianzhang b55cbe1992 docs📝: Update readme 2022-09-14 12:23:06 +08:00
wenjianzhang b6e1b7b210 Merge pull request #708 from zyd/master
fix🐛:模板Update方法,err没有被赋值,返回的err永远是nil
2022-09-12 11:50:41 +08:00
zhaoyidong 3685510d25 fix🐛:模板Update方法,err没有被赋值,返回的err永远是nil 2022-09-07 20:08:17 +08:00
wenjianzhang d7e685536c Merge pull request #707 from zyd/master
fix🐛:排序参数必须用string接收
2022-09-07 09:53:24 +08:00
zhaoyidong 4df859a0ea fix🐛:排序参数必须用string接收
优化了代码生成的格式,最后的空行无法删除,删除之后}前面会增加空格
2022-09-06 14:10:27 +08:00
wenjianzhang 7d1b84e837 Merge pull request #706 from haimait/master-test
1. 修复日志创建时间筛选报错的bug.
2022-09-05 19:58:06 +08:00
wenjianzhang be1f0be9b2 Merge pull request #703 from quanbisen/master
修复优雅重启不生效
2022-09-05 19:56:46 +08:00
wanghaima 0f742900f5 1. 修复日志创建时间筛选报错的bug.
2. 修复日志里操作人,修改人,userAgent为空的bug.
3. 迁移表时,日志表添加字段注释.
4. sys_opera_log表oper_param字段类型改为text,解决字段长度报错的问题
2022-09-04 10:02:26 +08:00
quanbisen e6f4fac859 修复优雅重启不生效 2022-08-31 18:14:33 +08:00
wenjianzhang d39faa1aca docs📝: update readme zh 2022-08-25 14:25:07 +08:00
wenjianzhang c3fe13d9dd docs📝: Update readme 2022-08-25 14:24:05 +08:00
wenjianzhang 90db381b5a fix🐛: 修复侧边栏菜单排序问题 (690) 2022-08-25 14:18:02 +08:00
wenjianzhang 508137da4b docs📝: update README.md 2022-08-25 13:56:14 +08:00
wenjianzhang 695ac7b29b docs📝: Update README.Zh-cn.md 2022-08-25 13:55:11 +08:00
wenjianzhang c06df13a75 docs📝: update readme zh 2022-08-25 13:44:59 +08:00
wenjianzhang e663de3697 docs📝: update readme 2022-08-25 13:44:24 +08:00
wenjianzhang 10b4f03ff5 Merge pull request #701 from NaturalGao/natural
feat ✨:update swag && add swag commond ssh
2022-08-25 13:42:42 +08:00
wenjianzhang c7a4434a0e docs📝: update readme 2022-08-25 13:40:24 +08:00
NaturalGao 1f8babd9e7 fix: fix sys_router && add swag commond 2022-08-25 01:19:55 +08:00
NaturalGao 8e8fe906fd perf: update swag 2022-08-25 01:00:57 +08:00
wenjianzhang 386d08a03f feat✨: update issue-labeled.yml 2022-08-24 16:27:19 +08:00
wenjianzhang af38e1694b feat✨: pr_cn.md 2022-08-24 11:26:01 +08:00
wenjianzhang 5609e004cc feat✨: PULL_REQUEST_TEMPLATE.md 2022-08-24 11:24:53 +08:00
wenjianzhang 5be468308a feat✨: update issue-labeled.yml 2022-08-23 11:55:03 +08:00
wenjianzhang 39702abfba feat✨: add issue-labeled.yml 2022-08-23 11:48:35 +08:00
wenjianzhang a97d86e801 feat✨: add issue-check-inactive.yml 2022-08-23 11:40:29 +08:00
wenjianzhang 75582539fe feat✨: add issue-close-require.yml 2022-08-23 11:39:19 +08:00
wenjianzhang 466723c55e Merge pull request #606 from npmmirror/master
Update https://registry.npm.taobao.org to https://registry.npmmirror.com
2022-08-23 11:30:20 +08:00
wenjianzhang 6b3b2125df docs📝: update README 2022-08-22 15:52:19 +08:00
wenjianzhang 8c8d268708 docs📝 update README 2022-08-22 15:51:33 +08:00
wenjianzhang 73ac7273a0 Merge pull request #695 from zyd/master
fix🐛:去除模板中的多余空格
2022-08-22 15:23:17 +08:00
wenjianzhang dcafcdc6ce Merge pull request #694 from infnan/master
处理postgre启动报错问题
2022-08-22 15:22:49 +08:00
zhaoyidong 5b1405391e fix🐛:去除模板中的多余空格 2022-08-18 18:36:50 +08:00
infnan 0993173b1f 处理postgre启动报错问题
Signed-off-by: infnan <38274826+infnan@users.noreply.github.com>
2022-08-18 16:50:54 +08:00
wenjianzhang 483ec2bf3e Create config.yml 2022-08-18 13:02:42 +08:00
wenjianzhang 60fe272ba0 refactor🎨: catch exception return error message
捕获runtime.Error异常,否则接口报错不返回任何信息
2022-08-18 10:14:12 +08:00
zhaoyidong 8df2e8190e 捕获runtime.Error异常,否则接口报错不返回任何信息
报错细节不应该隐藏,方便debug。500错误应该由前端统一处理,返回用户可读信息。
2022-08-18 10:02:00 +08:00
zhangwenjian 66c8eb5ee8 fix🐛: Fix create when creating a new create_by Problem with by value of 0 (#688) 2022-08-18 07:26:56 +08:00
zhangwenjian bb65e76219 fix🐛: Repair role creation prompt empty slice found (#687) 2022-08-18 07:19:24 +08:00
zhangwenjian a585e29073 Merge remote-tracking branch 'origin/master' 2022-08-18 06:57:20 +08:00
zhangwenjian 7655d0fd38 fix🐛: Repair document address (#692) 2022-08-18 06:57:02 +08:00
wenjianzhang 5bec640f20 fix🐛: Merge pull request #689 from zyd/master
修复模板get update delete错误
2022-08-16 11:58:33 +08:00
zhaoyidong 62d9084ee8 修复模板get update delete错误 2022-08-16 11:41:28 +08:00
wenjianzhang df8ab39aa0 config🔧: Merge pull request #685 from zyd/master
删除模板中间件重复初始化代码
2022-08-15 11:15:22 +08:00
wenjianzhang a7d3666811 config🔧: Merge pull request #686 from haimait/master_dev
编写dockerfile启动脚本
2022-08-15 11:15:07 +08:00
wanghaima ea9e3d2fe1 编写dockerfile启动脚本
编辑shell启动脚本
2022-08-14 23:32:58 +08:00
zhaoyidong f14085f3ee Merge pull request #1 from zyd/zyd-patch-1
删除模板中间件重复初始化代码
2022-08-13 17:39:14 +08:00
zhaoyidong e8b9db1df5 删除模板中间件重复初始化代码
go-admin app -n 创建目录,重复初始化会导致获取不到body中的参数
2022-08-13 17:37:55 +08:00
wenjianzhang dc625997c4 docs📝: Update README.Zh-cn.md 2022-08-10 01:00:34 +08:00
wenjianzhang 4f458591e8 docs📝: Update README.md 2022-08-10 00:47:42 +08:00
zhangwenjian 7a074d93cd config🔧: Modify the system default logo URL 2022-08-10 00:18:15 +08:00
wenjianzhang 9d1e1f6482 docs📝: Update README.Zh-cn.md 2022-08-09 23:24:35 +08:00
wenjianzhang 19153170bb docs📝: Update README.md 2022-08-09 23:23:18 +08:00
wenjianzhang 6bf774c463 fix🐛: fix rolemenu
fix🐛: fix rolemenu
2022-08-09 23:14:56 +08:00
wenjianzhang 0de5ba77aa docs📝: Update README.Zh-cn.md 2022-08-09 21:22:27 +08:00
wenjianzhang f4c0134d9c docs📝: Update Readme.md 2022-08-09 21:20:49 +08:00
wenjianzhang 2c5c1b69b4 docs📝: update readme 2022-08-09 20:46:37 +08:00
zhangwenjian d34a33b691 perf👌: update sqlite3 file 2022-08-09 18:21:40 +08:00
zhangwenjian 869394c898 perf👌: Remove caspin table from data migration 2022-08-09 18:21:00 +08:00
zhangwenjian b97bde11b2 perf👌: upgrade gorm,casbin,gin,uuid version 2022-08-09 18:19:02 +08:00
zhangwenjian 852cfa66e8 perf👌: remove casbin sys_ 2022-08-09 18:17:42 +08:00
zhangwenjian 289fbba8e0 perf👌: update casbin gorm adapter 2022-08-09 18:17:06 +08:00
zhangwenjian a6ffac657e fix🐛: Add MySQL judgment in data migration 2022-08-09 15:20:45 +08:00
zhangzhenlun 096663ac91 fix🐛: fix rolemenu 2022-08-09 14:26:43 +08:00
zhangwenjian d40a0c0837 fix🐛: fix github.com/alibaba/sentinel-golang middleware(#679) 2022-08-09 13:00:32 +08:00
zhangwenjian f94b437852 fix🐛: fix github.com/alibaba/sentinel-golang middleware 2022-08-09 12:59:31 +08:00
wenjianzhang 7e571b038f fix🐛: fix rolemenu 2022-08-09 10:18:21 +08:00
zhangwenjian 56968c0bd2 Merge remote-tracking branch 'origin/master' 2022-08-08 18:03:04 +08:00
zhangwenjian ef6b85faec config🔧: Modify the instruction createapp to app 2022-08-08 18:02:50 +08:00
zhangwenjian 0d47fb4e68 Merge branch 'master' of github.com:go-admin-team/go-admin 2022-08-08 16:28:34 +08:00
zhangwenjian 8bfee8af16 refactor🎨: 添加菜单paths默认数据 2022-08-08 16:28:26 +08:00
wenjianzhang 0fc7276ccd refactor🎨: set DB CHARSET utf8mb4 2022-08-08 11:39:11 +08:00
Vingurzhou 9a596397ca Update 1599190683659_tables.go 2022-08-08 11:28:55 +08:00
zhangwenjian 1bea64bb6d config🔧: set DB CHARSET utf8mb4(#674) 2022-08-08 10:16:43 +08:00
zhangwenjian 09bfdc3d39 config🔧: set DB CHARSET utf8mb4 2022-08-08 10:15:29 +08:00
wenjianzhang fe8b39691b patch🚑: go1.18 2022-08-08 10:00:24 +08:00
wenjianzhang 1465bfdf15 Merge branch 'master' into dev1.18 2022-08-08 09:59:57 +08:00
zhangwenjian bccbd67450 config🔧: update README 2022-08-08 09:42:31 +08:00
zhangwenjian 50a3b39666 config🔧: Modify the client IP acquisition method 2022-08-08 09:26:14 +08:00
zhangwenjian 087ba38c24 config🔧: update README.md 2022-08-08 09:22:36 +08:00
zhangwenjian 8a3c50ea1a config🔧: 修改actions配置文件 2022-08-07 21:52:02 +08:00
zhangwenjian 86187e4c79 fix🐛: 修复获取菜单接口menurole,数据不完整 (#676) 2022-08-07 21:49:24 +08:00
zhangwenjian 98c495abb1 refactor🎨: update readme 2022-08-07 20:43:34 +08:00
zhangwenjian c53c4fd9f8 refactor🎨: update readme 2022-08-07 20:42:24 +08:00
zhangwenjian b231705a67 Merge remote-tracking branch 'origin/master' 2022-08-04 17:25:17 +08:00
zhangwenjian 86f94a2cb9 refactor🎨: errors 添加go mod 2022-08-04 17:24:53 +08:00
zhangwenjian ef41e07550 docs📝: 添加开发环境要求 2022-08-04 17:24:07 +08:00
zhangwenjian 255c72d3f1 refactor🎨: update version 2022-07-29 18:51:55 +08:00
zhangwenjian 260eedfcc6 refactor🎨: 移除失效文档链接 2022-07-29 18:50:46 +08:00
zhangwenjian f43cd117e3 refactor🎨: 角色创建和更新后重新load policy策略 2022-07-29 18:47:12 +08:00
zhangwenjian 83b219458f fix🐛: 菜单中paths未设置问题修复 2022-07-29 18:44:22 +08:00
zhangwenjian 0f1b9369df fix🐛: 自定义错误中间件bug修复 2022-07-29 18:43:38 +08:00
zhangwenjian b31e1c0d58 feat✨: 升级go1.18 2022-07-27 22:27:38 +08:00
zhangwenjian 0122024789 feat✨: 修改版本号 2022-07-27 21:55:59 +08:00
zhangwenjian f469536174 fix🐛: 添加bcrypt包的引用 2022-07-27 21:49:24 +08:00
wenjianzhang 70bd8b26ad Merge pull request #673 from go-admin-team/dev
Dev
2022-07-27 21:36:11 +08:00
zhangwenjian dabc4d88b3 Merge remote-tracking branch 'origin/master' 2022-07-27 21:34:07 +08:00
wenjianzhang 214f90b366 Merge pull request #661 from wxxiong6/patch-1
fix UpdatePwd error
2022-07-27 21:20:07 +08:00
wenjianzhang 3c4cc054df Merge pull request #671 from Silicon-He/fix-readme-cgo-url
Fix readme cgo url
2022-07-27 21:19:29 +08:00
wenjianzhang 4d329287ce Merge pull request #664 from zhouxixi-dev/dev
bugfix: https://github.com/go-admin-team/go-admin/issues/539
2022-07-27 21:17:43 +08:00
siliconhe 866714d75e update doc url of cgo-issue 2022-07-17 21:14:26 +08:00
lwnmengjing b268d03e30 💚 update workflow 2022-07-12 11:54:24 +08:00
lwnmengjing 953d3b4135 🐛 fix: delete pkg error package 2022-07-12 10:55:05 +08:00
zhouxixi-dev 0d6b347d7e bugfix: https://github.com/go-admin-team/go-admin/issues/539 修复角色新增、修改时,sys_casbin_rule表drop,然后重新create的问题 2022-06-23 15:47:55 +08:00
wxxiong6 a19622f6ac fix UpdatePwd error
fix UpdatePwd error
2022-06-13 23:36:12 +08:00
zhangwenjian 45c8737601 refactor🎨: 引入github.com/pkg/errors 2022-06-05 11:12:19 +08:00
wenjianzhang 4925383f5e Merge pull request #593 from ziux/ziux
fix bug
2022-06-05 11:08:09 +08:00
wenjianzhang 62ab985050 Merge pull request #552 from wkf928592/wkf928592-patch-1
fix: arm32位系统环境下使用migrate迁移功能时,版本号作为整型处理会出现内存溢出的问题
2022-06-05 10:36:27 +08:00
wenjianzhang 50f14f7658 Merge branch 'dev' into wkf928592-patch-1 2022-06-05 10:36:20 +08:00
wenjianzhang 1cd31079d7 Merge pull request #634 from defool/bugfix/throw_error_on_migrate
Throw error if migrate failed
2022-06-05 10:33:08 +08:00
wenjianzhang 46b62a9809 Merge pull request #655 from stephenzhang0713/dev
Fix: Unable to load config file to Docker container
2022-06-05 10:31:54 +08:00
Han Zhang 8f70a1dca4 fix🐛: Fix Dockerfile to load config file
fix🐛: Fix Dockerfile to load config file
2022-06-03 20:38:54 +08:00
zhangwenjian 937b62e641 添加errors包 2022-05-29 12:58:53 +08:00
wenjianzhang 3873342f6c Merge pull request #650 from go-admin-team/dev
refactor🎨: 修复问题
2022-05-28 00:40:06 +08:00
zhangwenjian 717903a2b6 fix🐛: 修复关闭中的job能够启动问题(#638) 2022-05-28 00:34:08 +08:00
zhangwenjian 88030e301a patch🚑: 更新版本信息 2022-05-28 00:17:35 +08:00
zhangwenjian cd0792e3d2 refactor🎨: 更新readme(#623) 2022-05-28 00:14:12 +08:00
zhangwenjian 6ed2fcbf6c fix🐛: 添加roleKey验证(#649) 2022-05-27 22:47:57 +08:00
kaiyuan eb33515e29 throw error if migrate failed 2022-04-08 10:32:07 +08:00
wenjianzhang bf93b86bd0 Merge pull request #629 from go-admin-team/dev
docs📝: update readme
2022-04-01 14:14:01 +08:00
wenjianzhang c41672c21a docs📝: update readme 2022-03-31 15:08:49 +08:00
wenjianzhang 8716b073df Merge pull request #628 from go-admin-team/dev
docs📝:  update readme
2022-03-31 14:13:26 +08:00
wenjianzhang 638bab3c9d docs📝: update readme 2022-03-31 14:01:15 +08:00
wenjianzhang c5d7a8c740 fix🐛: Fix password reset
fix🐛: Fix password reset
2022-03-15 11:33:21 +08:00
wenjianzhang b030be8f80 fix🐛: Fix password reset 2022-03-12 13:00:19 +08:00
wenjianzhang 1fe19d1c3b patch🚑: dev merge
patch🚑:  dev merge
2022-03-05 11:54:10 +08:00
wenjianzhang 1508e850fe Merge branch 'master' into dev 2022-03-05 11:52:44 +08:00
zhangwenjian 81bc15d77c config🔧: go-admin version info 2022-03-05 11:49:56 +08:00
zhangwenjian 24adca55e4 feat✨: added file update sdk;kodo、obs 2022-03-05 11:44:23 +08:00
wenjianzhang 9c8974a26e fix🐛: 修复前端设置数据权限不生效问题
fix🐛: 修复前端设置数据权限不生效问题
2022-03-05 11:23:41 +08:00
wenjianzhang 01e8984b79 fix🐛: Fix readme 404 link.
fix🐛:  Fix readme 404 link.
2022-03-05 11:13:08 +08:00
wenjianzhang 7f1aa89539 fix🐛: Fix the newline problem in time package in code generation
Fix gen code problem
2022-03-05 11:11:34 +08:00
zhangwenjian 4876fc0aa1 fix🐛: Fix password reset caused by modifying user information 2022-03-05 11:00:52 +08:00
zhangwenjian f998d20a86 feat✨: added obs,kodo 2022-02-21 18:07:37 +08:00
zhangwenjian cdb5faf043 refactor🎨: upgrade OXS interface 2022-02-21 18:06:11 +08:00
zhangwenjian dfaa2ff51e test✅: added oss test 2022-02-21 18:04:46 +08:00
zhangwenjian 8754ff8147 refactor🎨: upgrade oss 2022-02-21 18:04:18 +08:00
zhangwenjian cca84c3c21 docs📝: update License Copyright 2022-02-21 17:56:12 +08:00
wenjianzhang 72391f0201 Merge pull request #598 from go-admin-team/dev
fix🐛: fix monitor macos env error (#605)
2022-02-13 00:54:52 +08:00
zhangwenjian 39e26d738c docs📝: update version 2.0.9 2022-02-13 00:31:46 +08:00
zhangwenjian f114424079 fix🐛: fix monitor macos env error 2022-02-13 00:23:20 +08:00
NPM Mirror Bot 98b60f0564 update https://registry.npm.taobao.org to https://registry.npmmirror.com 2022-02-12 05:56:42 +00:00
wenjianzhang d02b52f383 feat✨: 添加sqlserver支持 2022-02-08 18:41:09 +08:00
horizonzy b52da434bb fix code gen problem. 2022-01-31 13:00:21 +08:00
horizonzy 3cfa7a2767 fix code gen problem. 2022-01-31 12:00:26 +08:00
horizonzy 054199d1e4 fix 404 link. 2022-01-30 17:19:50 +08:00
zhangwenjian 02b62a288d refactor🎨: 删除历史的sqlite文件 2022-01-22 23:05:38 +08:00
zhangwenjian 24908a8732 refactor🎨: 添加error判断返回 2022-01-22 23:03:01 +08:00
wenjianzhang 26ee7b7985 refactor🎨: 清空sqlite数据库文件 2022-01-22 21:49:42 +08:00
wenjianzhang b76db48112 refactor🎨: 修正针对sqlite3的事务问题 2022-01-22 21:49:11 +08:00
wenjianzhang e2c5075319 v2.0.8
1、修改sqplite的支持
2、修正已知问题
2022-01-22 20:03:21 +08:00
wenjianzhang e9f36e74ca refactor🎨: 修改版本号 2022-01-22 19:44:36 +08:00
wenjianzhang 0b73bd7b25 refactor🎨: 修改sqplite的支持 2022-01-22 19:37:56 +08:00
yangyu ccccab3104 fix bug 2022-01-12 17:10:52 +08:00
wenjianzhang ae8e32d806 Update README.Zh-cn.md 2022-01-10 13:18:59 +08:00
wenjianzhang fd2709affa Update README.md 2022-01-10 13:18:23 +08:00
wenjianzhang 34b3395d15 Update README.md 2022-01-10 13:17:28 +08:00
inits abdc80b756 修复前端设置数据权限不生效问题 2022-01-10 10:21:10 +08:00
lwnmengjing 492ac31973 Merge pull request #580 from go-admin-team/dev
push docker
2021-12-08 11:09:01 +08:00
linwenxiang 3ac1878c3c perf ⚡ performance docker build 2021-12-07 23:37:33 +08:00
linwenxiang 0cc27355f7 fix 🐛 push to gihub 2021-12-07 23:24:19 +08:00
linwenxiang 562f761807 feat ✨ add dev to ci 2021-12-07 22:47:44 +08:00
linwenxiang 88e4b37c03 feat ✨ push docker to github 2021-12-07 22:44:39 +08:00
wenjianzhang b73d88d6cf Merge pull request #564 from go-admin-team/dev
merge: 修正数据初始化的部分问题
2021-10-22 12:15:05 +08:00
wenjianzhang 443c30d48c Update 1599190683659_tables.go 2021-10-22 12:05:39 +08:00
wenjianzhang 64cbf31184 Update db.sql 2021-10-22 12:04:48 +08:00
wkf928592 ce9d9bd3ec fix:在32位系统中做迁移时,版本号作为整型处理会造成内存溢出的问题
修改版本号作为字符串处理
2021-09-10 10:19:33 +08:00
linwenxiang 57330784ac feat ✨ mirror to gitlab 2021-09-07 21:45:25 +08:00
lwnmengjing 85e1c6fe54 Merge branch 'dev' 2021-09-07 11:21:33 +08:00
lwnmengjing 7ca776bfab 💚 修复流水线CI bug 2021-09-07 11:20:55 +08:00
linwenxiang 082c369d41 feat ✨ 同步代码到gitee 2021-09-06 21:51:07 +08:00
lwnmengjing 0ac9f41e1a Merge pull request #549 from go-admin-team/dev
fix 🐛 gcc强依赖问题修复
2021-09-02 20:38:36 +08:00
linwenxiang 16701d38a6 feat ✨ 增加release pipeline 2021-09-02 20:31:00 +08:00
linwenxiang 30eb280698 fix 🐛 gcc强依赖问题修复 2021-09-02 20:21:18 +08:00
wenjianzhang 974a8096ca Merge pull request #546 from go-admin-team/dev
Dev
2021-08-21 14:20:26 +08:00
wenjianzhang bb83a97613 refactor🎨: 修改post接口文档 2021-08-20 18:28:04 +08:00
wenjianzhang 8baae5e712 fix🐛: 修复jwt密钥引用错误问题(#545) 2021-08-20 18:27:29 +08:00
wenjianzhang 49e4c19cbb Merge pull request #544 from go-admin-team/dev
Dev
2021-08-19 19:36:42 +08:00
wenjianzhang 6f67628012 Merge branch 'dev' of github.com:go-admin-team/go-admin into dev 2021-08-19 19:28:04 +08:00
wenjianzhang 8a1573cc14 docs📝: 更新2.0.6 2021-08-19 19:27:55 +08:00
wenjianzhang 03b916ef8a Merge pull request #543 from go-admin-team/dev
Dev
2021-08-19 19:26:31 +08:00
wenjianzhang 9d25648c1f Merge pull request #540 from ninstein/patch-8
BUGFIX:角色状态修改异常修复
2021-08-19 19:13:16 +08:00
wenjianzhang aa6c3df892 Merge pull request #542 from go-admin-team/dev
Dev
2021-08-19 19:12:32 +08:00
wenjianzhang bdaa6e0db0 refactor🎨: 升级包go-admin-core v1.3.7和go-admin-core/sdk v1.3.7至v1.3.8 2021-08-19 19:10:32 +08:00
wenjianzhang 4740a39808 refactor🎨: 删除移除功能的数据初始化 2021-08-19 19:08:47 +08:00
wenjianzhang 386c620b48 refactor🎨: 优化角色修改时循环AddNamedPolicy 2021-08-19 19:04:03 +08:00
wenjianzhang 2441412714 fix🐛: 修复参数验证信息 2021-08-19 19:03:19 +08:00
ninstein 9db940150a BUGFIX:角色状态修改异常修复
切换角色状态时参数传递丢失,导致切换异常新增了一条空记录
2021-08-18 14:45:22 +08:00
wenjianzhang 8c5639af53 Merge pull request #535 from go-admin-team/dev
Dev
2021-08-13 21:17:00 +08:00
wenjianzhang b4a6f82f5f Merge pull request #534 from appleboy/patch
chore: upgrade gin to v1.7.3
2021-08-13 21:15:58 +08:00
Bo-Yi Wu 7dd62a4cf8 chore: upgrade gin to v1.7.3
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2021-08-13 20:53:37 +08:00
wenjianzhang 095ed7c2fd Merge pull request #529 from go-admin-team/dev
Dev
2021-08-10 16:39:54 +08:00
zhangwenjian 76567eea84 docs📝: 更新2.0.5 2021-08-10 14:58:55 +08:00
zhangwenjian 5a65fcd477 fix🐛: 修复菜单树 2021-08-10 14:58:04 +08:00
wenjianzhang 27b0e1a07a Merge pull request #528 from go-admin-team/dev
Dev
2021-08-10 03:55:34 +08:00
zhangwenjian 3e20e93797 fix🐛: 修复菜单编辑未赋权接口列表 2021-08-10 03:47:31 +08:00
zhangwenjian 5d3b1c3d0f docs📝: 更新2.0.4 2021-08-10 03:37:02 +08:00
zhangwenjian b5a57e6dd9 refactor🎨: 优化生成功能的修改和删除询问提示 2021-08-10 03:36:20 +08:00
zhangwenjian 2decf43b4c fix🐛: 统一生成后的路由 2021-08-10 03:35:36 +08:00
wenjianzhang 7dd3e2b27e Merge pull request #525 from go-admin-team/dev
Dev
2021-08-06 10:49:41 +08:00
zhangwenjian 325c91989c refactor🎨: api自动添加不设置默认类型 2021-08-06 10:35:09 +08:00
wenjianzhang 96250bafb1 Merge pull request #521 from qliang/master
完善:接口检查新增记录-根据接口注释补充接口名称信息
2021-08-06 10:28:07 +08:00
wenjianzhang fff795ce5a Merge pull request #524 from go-admin-team/dev
fix🐛: 修复代码生成字典的问题 (#523  #517)
2021-08-06 10:27:32 +08:00
zhangwenjian 9887250407 docs📝: 更新2.0.3 2021-08-06 10:03:44 +08:00
zhangwenjian e42191c6af fix🐛: 修复代码生成字典的问题 (#523 #517) 2021-08-06 10:00:17 +08:00
lq adce44dc1f 完善:接口检查新增记录-根据接口注释补充接口名称信息 2021-08-03 17:24:58 +08:00
wenjianzhang a70ee44466 Merge pull request #511 from go-admin-team/dev
patch🚑:  merge dev
2021-07-28 10:00:12 +08:00
zhangwenjian fd0fa49f1c docs📝: 更新2.0.2 2021-07-28 09:06:23 +08:00
zhangwenjian 10491f9745 fix🐛: 修复删除部门的问题 (#510) 2021-07-28 08:53:18 +08:00
zhangwenjian 981313c0e2 fix🐛: 修复创建用户时的问题 ( #506) 2021-07-28 08:45:39 +08:00
zhangwenjian 6b88c9a004 fix🐛: 更新接口文档注释 (#507) 2021-07-27 19:16:47 +08:00
wenjianzhang 25395b5006 Merge pull request #504 from go-admin-team/dev
1. 修复菜单的目录(#500)
1. 调整字段判断逻辑
2021-07-23 00:43:34 +08:00
zhangwenjian 2f516b49cf refactor🎨: 调整字段判断逻辑 2021-07-23 00:33:39 +08:00
zhangwenjian 41ff26edc8 fix🐛: 修复菜单的目录(#500) 2021-07-23 00:33:00 +08:00
wenjianzhang a1c6f586cf Merge pull request #503 from go-admin-team/dev
fix🐛: 修复createapp时的问题(#493)
2021-07-22 23:11:56 +08:00
zhangwenjian 8b01126e0f fix🐛: 修复createapp时的问题(#493) 2021-07-22 23:03:44 +08:00
wenjianzhang e59d40af21 Merge pull request #495 from go-admin-team/dev
Dev
2021-07-22 22:22:20 +08:00
wenjianzhang 6b476bfab7 Update go.mod 2021-07-18 22:29:34 +08:00
wenjianzhang 12429d4585 Merge pull request #489 from Cassuis/dev
fix:修复createapp未初始化导致无法创建app以及修改资本资料导致密码重复加密问题
2021-07-16 20:52:40 +08:00
Vincent 6fe2edbe89 fix:修复修改基本资料导致密码重复加密问题 2021-07-15 11:13:37 +08:00
Vincent cee6bd6abd fix:修复createapp未初始化导致无法创建app的问题 2021-07-15 10:21:26 +08:00
zhangwenjian 4ac3350920 refactor🎨: 部分函数名称优化 2021-07-15 00:53:43 +08:00
zhangwenjian a45113258c refactor🎨: update request mode name 2021-07-15 00:43:06 +08:00
zhangwenjian 4a2659573b docs📝: 用户接口文档 2021-07-14 22:36:03 +08:00
zhangwenjian c74080664f refactor🎨: update version 2021-07-14 22:24:26 +08:00
wenjianzhang 84e06395a5 Merge pull request #487 from go-admin-team/dev
Dev
2021-07-14 16:24:46 +08:00
zhangwenjian 411b85afcd publish🚀: 2.0.0 2021-07-14 11:49:54 +08:00
zhangwenjian 57d128144d feat✨: Add the createapp command 2021-07-14 11:48:40 +08:00
wenjianzhang a7fa7e079b Merge pull request #486 from go-admin-team/dev
Dev
2021-07-14 11:40:05 +08:00
zhangwenjian 2781e413dc refactor🎨: 修改版本号 2021-07-14 11:16:27 +08:00
zhangwenjian 41d8daac97 fix🐛: 修改用户其它信息导致密码被置空,数据权限 #484 2021-07-14 11:13:26 +08:00
zhangwenjian dd22d55ee7 refactor🎨: request name cancel 2021-07-14 09:14:44 +08:00
zhangwenjian 32a1bd2511 refactor🎨: 升级gin和gorm版本 2021-07-05 00:31:31 +08:00
zhangwenjian 1130d20f14 refactor🎨: dto》request 2021-07-05 00:03:38 +08:00
wenjianzhang 90b17e995a Merge pull request #478 from go-admin-team/dev
Dev
2021-07-04 23:33:55 +08:00
zhangwenjian 1c41b0ec72 refactor🎨: 操作log dto模型名称修改 2021-07-04 23:26:43 +08:00
zhangwenjian 3f90605589 refactor🎨: 操作log添加字符限制 2021-07-04 23:13:14 +08:00
zhangwenjian c1347fbb5d refactor🎨: 升级依赖关系 2021-07-04 23:12:21 +08:00
zhangwenjian 0d1cb2ee33 docs📝: 升级qq群至2000人 2021-07-04 23:11:58 +08:00
zhangwenjian b6be297a1e refactor🎨: 添加默认demo代码生成表 2021-07-04 13:43:32 +08:00
zhangwenjian b9b3cbee93 refactor🎨: 调整登陆日志和api和操作日志模块 2021-07-04 13:43:11 +08:00
zhangwenjian 37d318b4d9 feat✨: vue-cli@3 升级为 vue-cli@4、Change Node Sass to Dart Sass、代码生成工具
1. vue-cli@3 升级为 vue-cli@4
2. Change Node Sass to Dart Sass
3. 代码生成工具
2021-07-04 05:46:20 +08:00
wenjianzhang 5368cfbcb8 Merge pull request #475 from G-Akiraka/patch-4
增加磁盘列表主机名称与当前时间
2021-07-02 22:26:09 +08:00
wenjianzhang 72a4ba077c Merge pull request #472 from G-Akiraka/patch-1
Update settings.yml
2021-07-02 22:25:53 +08:00
wenjianzhang fba03625d0 Merge pull request #473 from G-Akiraka/patch-2
翻译错误,管理员管理应该是用户管理
2021-07-02 22:24:25 +08:00
G-Akiraka 007807e776 增加磁盘列表主机名称与当前时间
上一个pr提交作废
2021-07-02 10:06:48 +08:00
G-Akiraka f2ae95d932 翻译错误,管理员管理应该是用户管理 2021-07-02 09:09:20 +08:00
G-Akiraka 25d7323ed1 Update settings.yml 2021-07-02 09:05:25 +08:00
178 changed files with 7278 additions and 2370 deletions
+8
View File
@@ -0,0 +1,8 @@
blank_issues_enabled: true
contact_links:
- name: 🆕 Create new issue
url: http://new-issue.go-admin.dev
about: The issue which is not created via http://new-issue.go-admin.dev will be closed immediately.
- name: 🆕 创建一个新 Issue
url: http://new-issue.go-admin.dev
about: 不是用 http://new-issue.go-admin.dev 创建的 issue 会被机器人自动关闭。
+66
View File
@@ -0,0 +1,66 @@
<!--
First of all, thank you for your contribution! 😄
For requesting to pull a new feature or bugfix, please send it from a feature/bugfix branch based on the `master` branch.
Before submitting your pull request, please make sure the checklist below is confirmed.
Your pull requests will be merged after one of the collaborators approve.
Thank you!
-->
[[中文版模板 / Chinese template](https://github.com/go-admin-team/go-admin/blob/master/.github/PULL_REQUEST_TEMPLATE/pr_cn.md)]
### 🤔 This is a ...
- [ ] New feature
- [ ] Bug fix
- [ ] Site / documentation update
- [ ] Demo update
- [ ] Component style update
- [ ] TypeScript definition update
- [ ] Bundle size optimization
- [ ] Performance optimization
- [ ] Enhancement feature
- [ ] Internationalization
- [ ] Refactoring
- [ ] Code style optimization
- [ ] Test Case
- [ ] Branch merge
- [ ] Other (about what?)
### 🔗 Related issue link
<!--
1. Put the related issue or discussion links here.
-->
### 💡 Background and solution
<!--
1. Describe the problem and the scenario.
2. GIF or snapshot should be provided if includes UI/interactive modification.
3. How to fix the problem, and list the final API implementation and usage sample if that is a new feature.
-->
### 📝 Changelog
<!--
Describe changes from the user side, and list all potential break changes or other risks.
--->
| Language | Changelog |
| ---------- | --------- |
| 🇺🇸 English | |
| 🇨🇳 Chinese | |
### ☑️ Self-Check before Merge
⚠️ Please check all items below before review. ⚠️
- [ ] Doc is updated/provided or not needed
- [ ] Demo is updated/provided or not needed
- [ ] TypeScript's definition is updated/provided or not needed
- [ ] Changelog is provided or not needed
+61
View File
@@ -0,0 +1,61 @@
<!--
首先,感谢你的贡献!😄
新特性请提交至 feature 分支,其余可提交至 master 分支。
在维护者审核通过后会合并。
请确保填写以下 pull request 的信息,谢谢!~
-->
[[English Template / 英文模板](https://github.com/go-admin-team/go-admin/blob/master/.github/PULL_REQUEST_TEMPLATE.md)]
### 🤔 这个变动的性质是?
- [ ] 新特性提交
- [ ] 日常 bug 修复
- [ ] 站点、文档改进
- [ ] 演示代码改进
- [ ] 组件样式/交互改进
- [ ] TypeScript 定义更新
- [ ] 包体积优化
- [ ] 性能优化
- [ ] 功能增强
- [ ] 国际化改进
- [ ] 重构
- [ ] 代码风格优化
- [ ] 测试用例
- [ ] 分支合并
- [ ] 其他改动(是关于什么的改动?)
### 🔗 相关 Issue
<!--
1. 描述相关需求的来源,如相关的 issue 讨论链接。
-->
### 💡 需求背景和解决方案
<!--
1. 要解决的具体问题。
2. 列出最终的 API 实现和用法。
3. 涉及UI/交互变动需要有截图或 GIF。
-->
### 📝 更新日志
<!--
从用户角度描述具体变化,以及可能的 breaking change 和其他风险。
-->
| 语言 | 更新描述 |
| ------- | -------- |
| 🇺🇸 英文 | |
| 🇨🇳 中文 | |
### ☑️ 请求合并前的自查清单
⚠️ 请自检并全部**勾选全部选项**。⚠️
- [ ] 文档已补充或无须补充
- [ ] 代码演示已提供或无须提供
- [ ] TypeScript 定义已补充或无须补充
- [ ] Changelog 已提供或无须提供
+63
View File
@@ -0,0 +1,63 @@
name: Build
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
env:
IMAGE_NAME: registry.ap-northeast-1.aliyuncs.com/go-admin/go-admin-api # 镜像名称
TAG: ${{ github.sha }}
IMAGE_NAME_TAG: registry.ap-northeast-1.aliyuncs.com/go-admin/go-admin-api:${{ github.sha }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: 1.26.5
- name: Tidy
run: go mod tidy
- name: Build
run: env CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -tags "sqlite3,json1" --ldflags "-extldflags -static" -o main .
# 以下推镜像与重启步骤仅在 master 收到 push 时执行。
# pull_request 事件同样会触发本工作流,若不加限制,任何指向 master 的
# PR 一经创建就会把 PR 分支的镜像推上仓库,并直接重启线上 API 服务,
# 且发生在合并之前。构建与编译校验不受影响,PR 仍会执行。
- name: Build the Docker image and push
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
run: |
docker login --username=${{ secrets.DOCKER_USERNAME }} registry.ap-northeast-1.aliyuncs.com --password=${{ secrets.DOCKER_PASSWORD }}
echo "************ docker login end"
docker build -t go-admin-api:latest .
echo "************ docker build end"
docker tag go-admin-api ${{ env.IMAGE_NAME_TAG }}
echo "************ docker tag end"
docker images
echo "************ docker images end"
docker push ${{ env.IMAGE_NAME_TAG }} # 推送
echo "************ docker push end"
- name: Restart server # 第五步,重启服务
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5
env:
GITHUB_SHA_X: ${GITHUB_SHA}
with:
host: ${{ secrets.SSH_HOST }} # 下面三个配置与上一步类似
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.DEPLOY_KEY }}
# 重启的脚本,根据自身情况做相应改动,一般要做的是migrate数据库以及重启服务器
script: |
sudo docker rm -f go-admin-api
sudo docker login --username=${{ secrets.DOCKER_USERNAME }} registry.ap-northeast-1.aliyuncs.com --password=${{ secrets.DOCKER_PASSWORD }}
sudo docker run -d -p 8000:8000 --name go-admin-api ${{ env.IMAGE_NAME_TAG }}
+4 -4
View File
@@ -19,11 +19,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@24c7eb380a2dc368f2d129e4c65e51d172983a1e # v4
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -34,7 +34,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@24c7eb380a2dc368f2d129e4c65e51d172983a1e # v4
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -48,4 +48,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@24c7eb380a2dc368f2d129e4c65e51d172983a1e # v4
-60
View File
@@ -1,60 +0,0 @@
name: build
on:
push:
branches: [ dev-lwx ]
pull_request:
branches: [ dev-lwx ]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.15
uses: actions/setup-go@v1
with:
go-version: 1.15
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Get dependencies
run: |
go get -v -t -d ./...
if [ -f Gopkg.toml ]; then
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
dep ensure
fi
- name: Build
run: |
CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -installsuffix cgo -o go-admin .
mv go-admin ./scripts
- uses: Azure/docker-login@v1
with:
login-server: registry.cn-shanghai.aliyuncs.com
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- run: |
docker build ./scripts -t registry.cn-shanghai.aliyuncs.com/go-admin-team/go-admin:${{ github.sha }}
docker push registry.cn-shanghai.aliyuncs.com/go-admin-team/go-admin:${{ github.sha }}
- uses: Azure/k8s-set-context@v1
with:
kubeconfig: ${{ secrets.KUBE_CONFIG }}
- uses: Azure/k8s-create-secret@v1
with:
namespace: 'go-admin'
container-registry-url: registry.cn-shanghai.aliyuncs.com
container-registry-username: ${{ secrets.REGISTRY_USERNAME }}
container-registry-password: ${{ secrets.REGISTRY_PASSWORD }}
secret-name: aliyuncs-k8s-secret
- uses: Azure/k8s-deploy@v1
with:
namespace: 'go-admin'
manifests: 'scripts/k8s/deploy.yml'
images: 'registry.cn-shanghai.aliyuncs.com/go-admin-team/go-admin:${{ github.sha }}'
imagepullsecrets: 'aliyuncs-k8s-secret'
kubectl-version: 'latest'
+46 -13
View File
@@ -2,9 +2,13 @@ name: build
on:
push:
branches: [ master ]
branches: [ master, dev ]
tags: [ 'v*', '[0-9]*' ]
pull_request:
branches: [ master ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
@@ -13,22 +17,51 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.14
uses: actions/setup-go@v1
- name: Set up Go 1.26
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: 1.14
go-version: 1.26.5
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Get dependencies
run: |
go get -v -t -d ./...
if [ -f Gopkg.toml ]; then
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
dep ensure
fi
run: go mod tidy
- name: Build
run: go build -v .
run: make build
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
if: startsWith(github.ref, 'refs/tags/')
- name: Log in to the Container registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
if: startsWith(github.ref, 'refs/tags/')
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
if: startsWith(github.ref, 'refs/tags/')
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
flavor: |
latest=auto
tags: |
type=schedule
type=ref,event=tag
type=sha,prefix=,format=long,enable=true,priority=100
- name: Build and push Docker image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
if: startsWith(github.ref, 'refs/tags/')
with:
context: .
file: scripts/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+33
View File
@@ -0,0 +1,33 @@
name: 'GitHub Actions Mirror'
on: [push, delete]
jobs:
mirror_to_gitee:
runs-on: ubuntu-latest
steps:
- name: 'Checkout'
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: 'Mirror to gitee'
uses: pixta-dev/repository-mirroring-action@674e65a7d483ca28dafaacba0d07351bdcc8bd75 # v1
with:
target_repo_url:
git@gitee.com:go-admin-team/go-admin.git
ssh_private_key:
${{ secrets.GITEE_KEY }}
mirror_to_gitlab:
runs-on: ubuntu-latest
steps:
- name: 'Checkout'
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: 'Mirror to gitlab'
uses: pixta-dev/repository-mirroring-action@674e65a7d483ca28dafaacba0d07351bdcc8bd75 # v1
with:
target_repo_url:
git@gitlab.com:go-admin-team/go-admin.git
ssh_private_key:
${{ secrets.GITLAB_KEY }}
+7 -6
View File
@@ -1,15 +1,15 @@
.idea
.vscode
*/.DS_Store
.DS_Store
static/uploadfile
main.exe
*.exe
go-admin
go-admin.exe
temp/
!temp
vendor
config/settings.dev.yml
go-admin
common/middleware/demo.go
config/settings.dev.*.yml
config/settings.dev.*.yml.log
temp/logs
@@ -17,8 +17,9 @@ config/settings.dev.yml.log
config/settings.b.dev.yml
cmd/migrate/migration/version-local/*
!cmd/migrate/migration/version-local/doc.go
*/.DS_Store
# go sum
go.sum
config/settings.deva.yml
go-admin-server
CLAUDE.md
.claude/
config/settings.local.dev.yml
+206
View File
@@ -0,0 +1,206 @@
# AGENTS.md — go-admin 后端
> 给 AI 编码工具与新贡献者的约定。**只写"不遵守就会出错"的规则**;技术栈版本以
> `go.mod` 为准,命令以 `Makefile` 为准,此处不复述,避免与代码脱节。
>
> 标准 CRUD 模块的完整写法见 **`app/demo/`** —— 那是可编译、有测试、CI 会跑的参照物。
> 本文与它冲突时,以 `app/demo/` 为准。
## 分层
```
Router → Api → Service → Model
路由注册 参数绑定 业务逻辑 GORM 结构体
中间件链 调用 Service 操作数据库 TableName()
```
对应目录:`app/{模块}/router|apis|service|models`,DTO 位于 `service/dto`。
**不可跨层**:Api 不直接操作 `Orm`,Service 不接触 `gin.Context`。
## 优先使用通用 Action
单表 CRUD **不要手写 Handler 与 Service**。`common/actions` 提供的五个
Action 已覆盖参数绑定、数据权限过滤、操作人注入、分页与错误响应:
```go
r := v1.Group("/demo-product").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
{
m := &models.DemoProduct{}
r.GET("", actions.PermissionAction(), actions.IndexAction(m, new(dto.DemoProductSearch), func() interface{} {
list := make([]models.DemoProduct, 0); return &list
}))
r.GET("/:id", actions.PermissionAction(), actions.ViewAction(new(dto.DemoProductById), func() interface{} {
return &models.DemoProduct{}
}))
r.POST("", actions.CreateAction(new(dto.DemoProductControl)))
r.PUT("/:id", actions.PermissionAction(), actions.UpdateAction(new(dto.DemoProductControl)))
r.DELETE("", actions.PermissionAction(), actions.DeleteAction(new(dto.DemoProductById)))
}
```
这样一个模块只需 **model + dto + router** 三个文件,完整示例见 `app/demo/`。
使用通用 Action 的前提:
- Model 实现 `models.ActiveRecord`(`Generate` / `GetId` / `TableName`)
- 列表 DTO 实现 `dto.Index`,增改删 DTO 实现 `dto.Control`
- **所有 `Generate()` 必须返回副本** —— Action 在并发请求间复用实例,
就地返回会串数据(`app/demo` 的测试锁定了这一点)
- 详情/删除 DTO 内嵌 `dto.ObjectById` 即可继承 `Bind` 与 `GetId`,无需重写
仅当业务超出单表 CRUD(跨表事务、外部调用、复杂校验)时才自行编写 Handler
与 Service,写法见下。
## Api 层(仅在通用 Action 不适用时)
结构体嵌入 `api.Api`,链式初始化后**必须检查 `Errors`**:
```go
func (e SysPost) GetPage(c *gin.Context) {
s := service.SysPost{}
req := dto.SysPostPageReq{}
err := e.MakeContext(c).MakeOrm().Bind(&req, binding.Form).MakeService(&s.Service).Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
// ... 调用 s.GetPage(...)
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
}
```
响应一律走 `e.OK` / `e.PageOK` / `e.Error`,不要自行 `c.JSON`。
## Service 层(仅在通用 Action 不适用时)
结构体嵌入 `service.Service`(持有 `Orm` 与 `Log`)。查询通过 Scopes 组合:
```go
err = e.Orm.Model(&data).Scopes(
cDto.MakeCondition(c.GetNeedSearch()), // 由 search tag 生成 WHERE
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
actions.Permission(data.TableName(), p), // 数据权限,列表/详情必须带
).Find(list).Limit(-1).Offset(-1).Count(count).Error
```
**遗漏 `actions.Permission` 会使数据权限配置静默失效** —— 这是最容易出的错。
错误一律 `return err` 向上传递,日志用 `e.Log.Errorf`,不使用 `panic`。
## DTO
搜索条件由 tag 声明,`MakeCondition` 据此拼 SQL:
```go
type SysPostPageReq struct {
dto.Pagination `search:"-"`
PostName string `form:"postName" search:"type:contains;column:post_name;table:sys_post"`
}
func (m *SysPostPageReq) GetNeedSearch() interface{} { return *m }
```
`type` 可选:`exact` `iexact` `contains` `gt` `gte` `lt` `lte` `order` `left`(联表)。
## Model
```go
type SysPost struct {
PostId int `gorm:"primaryKey;autoIncrement" json:"postId"`
// ... 业务字段
models.ControlBy // CreateBy / UpdateBy
models.ModelTime // CreatedAt / UpdatedAt / DeletedAt
}
func (SysPost) TableName() string { return "sys_post" }
```
`TableName()` 必须显式声明(GORM 配置了 `SingularTable`,不会自动推导复数)。
## 路由注册
通过 `init()` 自注册,不在中心文件手工添加:
```go
func init() { routerCheckRole = append(routerCheckRole, registerSysPostRouter) }
func registerSysPostRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
api := apis.SysPost{}
r := v1.Group("/post").
Use(authMiddleware.MiddlewareFunc()).
Use(middleware.AuthCheckRole()). // Casbin 鉴权
Use(actions.PermissionAction()) // 注入数据权限
{ r.GET("", api.GetPage); r.POST("", api.Insert); /* ... */ }
}
```
新增路由文件后,需确认 `cmd/api/` 中已用 `_` 导入该包。
## 命名
| 对象 | 规则 | 示例 |
|---|---|---|
| 数据表 | `sys_` 前缀 + 下划线 | `sys_post` |
| API 路径 | `/api/v1/` + kebab-case | `/api/v1/sys-user` |
| DTO | `{Model}{Action}Req` | `SysPostPageReq` |
| 权限标识 | `模块:资源:操作` | `admin:sysPost:add` |
权限标识需与前端 `v-permisaction` 一致,并写入 `sys_menu` 种子数据。
## Swagger
Handler 必须带完整注解,`go generate` 会据此生成文档:
```go
// @Summary 岗位列表
// @Tags 岗位
// @Success 200 {object} response.Response
// @Router /api/v1/post [get]
// @Security Bearer
```
## 本地运行
**配置 `driver: sqlite3` 时必须带构建标签**,否则启动即 panic:
```bash
go run -tags sqlite3 . migrate -c config/settings.sqlite.yml
go run -tags sqlite3 . server -c config/settings.sqlite.yml
```
原因:`common/database/open.go` 带 `//go:build !sqlite3`,不加标签时编进的是
不含 sqlite3 的版本,`opens["sqlite3"]` 为 nil,调用时在 nil 函数上崩溃。
报错信息不会提到构建标签,容易误判成环境损坏。MySQL / PostgreSQL 无此问题。
对应 `Makefile` 的 `build-sqlite` 目标。
## 数据库迁移
文件名前 13 位为时间戳版本号。**已执行过的迁移文件不可修改** ——
`sys_migration` 表按版本号去重,改动不会重跑,只能新增一个迁移来修正。
放哪个目录取决于身份:
| 目录 | 用途 | 是否入库 |
|---|---|---|
| `version/` | 框架自带迁移,随仓库分发给所有使用者 | 是 |
| `version-local/` | 使用者自己项目的迁移 | 否(已在 `.gitignore`) |
**向本仓库提交迁移必须放 `version/`** —— 放进 `version-local/` 会被忽略掉,
`git status` 看不到,PR 里也不会出现。两个目录的包名分别是 `version` 与
`version_local`(后者与目录名不一致,因为标识符不能含连字符)。
## 提交规范
格式 `type+emoji: 描述`:
`feat✨` `fix🐛` `style💄` `docs📝` `perf👌` `test✅` `refactor🎨` `chore🔧`
一个提交只做一件事。改动跨越多个语义时拆分提交,不要混在一起。
## 红线
- 不使用全局 DB 变量,一律用 `e.Orm`(来自请求上下文,多租户依赖它)
- 不在 Service 中引用 `gin.Context`
- 生产部署前确认 `mode: prod` 且已修改 `jwt.secret`(dev 模式下 token 几乎不过期)
- 不提交 `config/settings.yml` 中的真实凭据
+6 -2
View File
@@ -1,14 +1,18 @@
FROM alpine
ENV GOPROXY https://goproxy.cn/
# ENV GOPROXY https://goproxy.cn/
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
RUN apk update --no-cache
RUN apk add --update gcc g++ libc6-compat
RUN apk add --no-cache ca-certificates
RUN apk add --no-cache tzdata
ENV TZ Asia/Shanghai
COPY ./main /main
COPY ./config/settings.prod.yml /config/settings.yml
COPY ./config/settings.demo.yml /config/settings.yml
COPY ./go-admin-db.db /go-admin-db.db
EXPOSE 8000
RUN chmod +x /main
CMD ["/main","server","-c", "/config/settings.yml"]
+28
View File
@@ -0,0 +1,28 @@
FROM golang:alpine as builder
MAINTAINER lwnmengjing
ENV GOPROXY https://goproxy.cn/
WORKDIR /go/release
#RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk update && apk add tzdata
COPY go.mod ./go.mod
RUN go mod tidy
COPY . .
RUN pwd && ls
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -installsuffix cgo -o go-admin .
FROM alpine
COPY --from=builder /go/release/go-admin /
COPY --from=builder /go/release/config/settings.yml /config/settings.yml
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
EXPOSE 8000
CMD ["/go-admin","server","-c", "/config/settings.yml"]
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2020 wenjianzhang
Copyright (c) 2026 go-admin-team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+42 -2
View File
@@ -2,9 +2,41 @@ PROJECT:=go-admin
.PHONY: build
build:
CGO_ENABLED=0 go build -o go-admin main.go
CGO_ENABLED=0 go build -ldflags="-w -s" -a -installsuffix "" -o go-admin .
# make build-linux
build-linux:
@docker build -t go-admin:latest .
@echo "build successful"
build-sqlite:
go build -tags sqlite3 -o go-admin main.go
go build -tags sqlite3 -ldflags="-w -s" -a -installsuffix -o go-admin .
# make run
run:
# delete go-admin-api container
@if [ $(shell docker ps -aq --filter name=go-admin --filter publish=8000) ]; then docker rm -f go-admin; fi
# 启动方法一 run go-admin-api container docker-compose 启动方式
# 进入到项目根目录 执行 make run 命令
@docker-compose up -d
# 启动方式二 docker run 这里注意-v挂载的宿主机的地址改为部署时的实际绝对路径
#@docker run --name=go-admin -p 8000:8000 -v /home/code/go/src/go-admin/go-admin/config:/go-admin-api/config -v /home/code/go/src/go-admin/go-admin-api/static:/go-admin/static -v /home/code/go/src/go-admin/go-admin/temp:/go-admin-api/temp -d --restart=always go-admin:latest
@echo "go-admin service is running..."
# delete Tag=<none> 的镜像
@docker image prune -f
@docker ps -a | grep "go-admin"
stop:
# delete go-admin-api container
@if [ $(shell docker ps -aq --filter name=go-admin --filter publish=8000) ]; then docker-compose down; fi
#@if [ $(shell docker ps -aq --filter name=go-admin --filter publish=8000) ]; then docker rm -f go-admin; fi
#@echo "go-admin stop success"
#.PHONY: test
#test:
# go test -v ./... -cover
@@ -12,3 +44,11 @@ build-sqlite:
#.PHONY: docker
#docker:
# docker build . -t go-admin:latest
# make deploy
deploy:
#@git checkout master
#@git pull origin master
make build-linux
make run
+110 -45
View File
@@ -1,6 +1,6 @@
# go-admin
<img align="right" width="320" src="https://gitee.com/mydearzwj/image/raw/master/img/go-admin.svg">
<img align="right" width="320" src="https://doc-image.zhangwj.com/img/go-admin.svg">
[![Build Status](https://github.com/wenjianzhang/go-admin/workflows/build/badge.svg)](https://github.com/go-admin-team/go-admin)
@@ -9,18 +9,22 @@
[English](https://github.com/go-admin-team/go-admin/blob/master/README.md) | 简体中文
基于Gin + Vue + Element UI的前后端分离权限管理系统,系统初始化极度简单,只需要配置文件中,修改数据库连接,系统支持多指令操作,迁移指令可以让初始化数据库信息变得更简单,服务指令可以很简单的启动api服务
基于Gin + Vue + Element UI OR Arco Design OR Ant Design的前后端分离权限管理系统,系统初始化极度简单,只需要配置文件中,修改数据库连接,系统支持多指令操作,迁移指令可以让初始化数据库信息变得更简单,服务指令可以很简单的启动api服务
[在线文档](https://doc.go-admin.dev)
[github在线文档](https://wenjianzhang.github.io)
[gitee在线文档](http://mydearzwj.gitee.io/go-admin-doc/)
[在线文档](https://www.go-admin.pro)
[前端项目](https://github.com/go-admin-team/go-admin-ui)
[视频教程](https://space.bilibili.com/565616721/channel/detail?cid=125737)
## 🎬 在线体验
Element Plus vue3 体验:[https://vue.go-admin.pro](https://vue.go-admin.pro/#/login)
> ⚠️⚠️⚠️ 账号 / 密码: admin / 123456
antd 体验(go-admin-pro):[https://antd.go-admin.pro](https://antd.go-admin.pro/)
> ⚠️⚠️⚠️ 账号 / 密码: admin / 123456
## ✨ 特性
- 遵循 RESTful API 设计规范
@@ -74,9 +78,9 @@
### 轻松实现go-admin写出第一个应用 - 文档教程
[步骤一 - 基础内容介绍](http://doc.zhangwj.com/go-admin-site/guide/intro/tutorial01.html)
[步骤一 - 基础内容介绍](https://doc.zhangwj.com/guide/intro/tutorial01.html)
[步骤二 - 实际应用 - 编写增删改查](http://doc.zhangwj.com/go-admin-site/guide/intro/tutorial02.html)
[步骤二 - 实际应用 - 编写增删改查](https://doc.zhangwj.com/guide/intro/tutorial02.html)
### 手把手教你从入门到放弃 - 视频教程
@@ -100,6 +104,14 @@
## 📦 本地开发
### 环境要求
go 1.26.5
node版本: v22+(推荐 v24 LTS)
包管理器: pnpm v9+(UI 项目使用 pnpm)
### 开发目录创建
```bash
@@ -130,19 +142,22 @@ git clone https://github.com/go-admin-team/go-admin-ui.git
# 进入 go-admin 后端项目
cd ./go-admin
# 更新整理依赖
go mod tidy
# 编译项目
go build
# 修改配置
# 文件路径 go-admin/config/settings.yml
vi ./config/setting.yml
vi ./config/settings.yml
# 1. 配置文件中修改数据库信息
# 注意: settings.database 下对应的配置数据
# 2. 确认log路径
```
:::tip ⚠️注意 在windows环境如果没有安装中CGO,会出现这个问题;
⚠️注意 在windows环境如果没有安装中CGO,会出现这个问题;
```bash
E:\go-admin>go build
@@ -158,19 +173,18 @@ D:\Code\go-admin>go build
cgo: exec gcc: exec: "gcc": executable file not found in %PATH%
```
[解决cgo问题进入](https://doc.go-admin.dev/guide/other/faq.html#_5-cgo-exec-missing-cc-exec-missing-cc-file-does-not-exist)
[解决cgo问题进入](https://doc.go-admin.dev/zh-CN/guide/faq#cgo-%E7%9A%84%E9%97%AE%E9%A2%98)
:::
#### 初始化数据库,以及服务启动
``` bash
# 首次配置需要初始化数据库资源信息
# macOS or linux 下使用
$ ./go-admin migrate -c=config/settings.dev.yml
$ ./go-admin migrate -c config/settings.dev.yml
# ⚠️注意:windows 下使用
$ go-admin.exe migrate -c=config/settings.dev.yml
$ go-admin.exe migrate -c config/settings.dev.yml
# 启动项目,也可以用IDE进行调试
@@ -182,6 +196,13 @@ $ ./go-admin server -c config/settings.yml
$ go-admin.exe server -c config/settings.yml
```
#### sys_api 表的数据如何添加
在项目启动时,使用`-a true` 系统会自动添加缺少的接口数据
```bash
./go-admin server -c config/settings.yml -a true
```
#### 使用docker 编译启动
```shell
@@ -213,43 +234,83 @@ env GOOS=linux GOARCH=amd64 go build main.go
### UI交互端启动说明
```bash
# 安装依赖
npm install
# 安装 pnpm(若未安装)
npm install -g pnpm
# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
npm install --registry=https://registry.npm.taobao.org
# 安装依赖
pnpm install
# 国内网络可指定镜像源加速
pnpm install --registry=https://registry.npmmirror.com
# 启动服务
npm run dev
pnpm dev
```
## 🎬 在线体验
> admin / 123456
演示地址:[http://www.go-admin.dev](http://www.go-admin.dev/#/login)
## 📨 互动
<table>
<tr>
<tr>
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/wx.png" width="180px"></td>
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/qq.png" width="200px"></td>
<td><img src="https://doc-image.zhangwj.com/img/qrcode_for_gh_b798dc7db30c_258.jpg" width="180px"></td>
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/qq2.png" width="200px"></td>
<td><a href="https://space.bilibili.com/565616721">wenjianzhang</a></td>
</tr>
<tr>
<td>微信</td>
<td>此群已满</td>
<td>公众号🔥🔥🔥</td>
<td><a target="_blank" href="https://shang.qq.com/wpa/qunwpa?idkey=0f2bf59f5f2edec6a4550c364242c0641f870aa328e468c4ee4b7dbfb392627b"><img border="0" src="https://pub.idqqimg.com/wpa/images/group.png" alt="go-admin技术交流乙号" title="go-admin技术交流乙号"></a></td>
<td>哔哩哔哩🔥🔥🔥</td>
</tr>
</table>
## 💎 主要成员
## 💎 贡献者
<a href="https://github.com/wenjianzhang"> <img src="https://avatars.githubusercontent.com/u/3890175?s=460&u=20eac63daef81588fbac611da676b99859319251&v=4" width="80px"></a>
<a href="https://github.com/lwnmengjing"> <img src="https://avatars.githubusercontent.com/u/12806223?s=400&u=a89272dce50100b77b4c0d5c81c718bf78ebb580&v=4" width="80px"></a>
<a href="https://github.com/chengxiao"> <img src="https://avatars.githubusercontent.com/u/1379545?s=460&u=557da5503d0ac4a8628df6b4075b17853d5edcd9&v=4" width="80px"></a>
<a href="https://github.com/bing127"> <img src="https://avatars.githubusercontent.com/u/31166183?s=460&u=c085bff88df10bb7676c8c0351ba9dcd031d1fb3&v=4" width="80px"></a>
<span style="margin: 0 5px;" ><a href="https://github.com/wenjianzhang" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/3890175?v=4&h=60&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/G-Akiraka" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/45746659?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/lwnmengjing" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/12806223?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/bing127" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/31166183?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/chengxiao" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/1379545?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/NightFire0307" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/19854086?v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/appleboy" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/21979?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/ninstein" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/580303?v=4&h=60&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/kikiyou" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/17959053?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/horizonzy" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/22524871?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/Cassuis" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/48005724?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/hqcchina" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/5179057?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/nodece" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/16235121?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/stephenzhang0713" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/18169290?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/zhouxixi-dev" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/100399679?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/Jalins" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/31172582?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/wkf928592" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/6063351?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/wxxiong6" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/6983441?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/Silicon-He" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/52478309?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/GizmoOAO" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/20385106?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/bestgopher" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/36840497?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/wxb1207" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/20775558?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/misakichan" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/16569274?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/zhuxuyang" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/19301024?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/mss-boot" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/109259065?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/AuroraV" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/37330199?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/Vingurzhou" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/57127283?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/haimait" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/40926384?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/zyd" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/3446278?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/infnan" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/38274826?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/d1y" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/45585937?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/qlijin" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/515900?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/logtous
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/88697234?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/stepway
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/9927079?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/NaturalGao
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/43291304?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/DemoLiang
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/23476007?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/jfcg
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/1410597?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/Nicole0724
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/10487328?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
## JetBrains 开源证书支持
@@ -259,16 +320,20 @@ npm run dev
## 🤝 特别感谢
1. [chengxiao](https://github.com/chengxiao)
2. [gin](https://github.com/gin-gonic/gin)
2. [casbin](https://github.com/casbin/casbin)
2. [spf13/viper](https://github.com/spf13/viper)
2. [gorm](https://github.com/jinzhu/gorm)
2. [gin-swagger](https://github.com/swaggo/gin-swagger)
2. [jwt-go](https://github.com/dgrijalva/jwt-go)
2. [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
2. [ruoyi-vue](https://gitee.com/y_project/RuoYi-Vue)
2. [form-generator](https://github.com/JakHuang/form-generator)
1. [ant-design](https://github.com/ant-design/ant-design)
2. [ant-design-pro](https://github.com/ant-design/ant-design-pro)
2. [arco-design](https://github.com/arco-design/arco-design)
2. [arco-design-pro](https://github.com/arco-design/arco-design-pro)
4. [gin](https://github.com/gin-gonic/gin)
5. [casbin](https://github.com/casbin/casbin)
6. [spf13/viper](https://github.com/spf13/viper)
7. [gorm](https://github.com/jinzhu/gorm)
8. [gin-swagger](https://github.com/swaggo/gin-swagger)
9. [jwt-go](https://github.com/dgrijalva/jwt-go)
10. [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
11. [ruoyi-vue](https://gitee.com/y_project/RuoYi-Vue)
12. [form-generator](https://github.com/JakHuang/form-generator)
## 🤟 打赏
@@ -284,4 +349,4 @@ npm run dev
[MIT](https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md)
Copyright (c) 2020 wenjianzhang
Copyright (c) 2024 wenjianzhang
+91 -26
View File
@@ -1,7 +1,7 @@
# go-admin
<img align="right" width="320" src="https://gitee.com/mydearzwj/image/raw/master/img/go-admin.svg">
<img align="right" width="320" src="https://raw.githubusercontent.com/wenjianzhang/image/203c5930b9ed08d5cf2fcb4516b85e412f8e0e60/img/go-admin.svg">
[![Build Status](https://github.com/wenjianzhang/go-admin/workflows/build/badge.svg)](https://github.com/go-admin-team/go-admin)
@@ -10,14 +10,22 @@
English | [简体中文](https://github.com/go-admin-team/go-admin/blob/master/README.Zh-cn.md)
The front-end and back-end separation authority management system based on Gin + Vue + Element UI is extremely simple to initialize the system. You only need to modify the database connection in the configuration file. The system supports multi-instruction operations. Migration instructions can make it easier to initialize database information. Service instructions It's easy to start the api service.
The front-end and back-end separation authority management system based on Gin + Vue + Element UI OR Arco Design is extremely simple to initialize the system. You only need to modify the database connection in the configuration file. The system supports multi-instruction operations. Migration instructions can make it easier to initialize database information. Service instructions It's easy to start the api service.
[documentation](https://doc.go-admin.dev)
[documentation](https://www.go-admin.dev)
[Front-end project](https://github.com/go-admin-team/go-admin-ui)
[Video tutorial](https://space.bilibili.com/565616721/channel/detail?cid=125737)
## 🎬 Online Demo
Element Plus vue3 demo:[https://vue.go-admin.pro](https://vue.go-admin.pro/#/login)
> 账号 / 密码: admin / 123456
antd demo (go-admin-pro):[https://antd.go-admin.pro](https://antd.go-admin.pro/)
> 账号 / 密码: admin / 123456
>
## ✨ Feature
- Follow RESTful API design specifications
@@ -68,9 +76,9 @@ At the same time, a series of tutorials including videos and documents are provi
### Easily implement go-admin to write the first application-documentation tutorial
[Step 1 - basic content introduction](http://doc.zhangwj.com/go-admin-site/guide/intro/tutorial01.html)
[Step 1 - basic content introduction](https://doc.zhangwj.com/guide/intro/tutorial01.html)
[Step 2 - Practical application - writing database operations](http://doc.zhangwj.com/go-admin-site/guide/intro/tutorial02.html)
[Step 2 - Practical application - writing database operations](https://doc.zhangwj.com/guide/intro/tutorial02.html)
### Teach you from getting started to giving up-video tutorial
@@ -94,6 +102,14 @@ At the same time, a series of tutorials including videos and documents are provi
## 📦 Local development
### Environmental requirements
go 1.26.5
nodejs: v22+ (v24 LTS recommended)
package manager: pnpm v9+ (the UI project uses pnpm)
### Development directory creation
```bash
@@ -124,19 +140,22 @@ git clone https://github.com/go-admin-team/go-admin-ui.git
# Enter the go-admin backend project
cd ./go-admin
# Update dependencies
go mod tidy
# Compile the project
go build
# Change setting
# File path go-admin/config/settings.yml
vi ./config/setting.yml
vi ./config/settings.yml
# 1. Modify the database information in the configuration file
# Note: The corresponding configuration data under settings.database
# 2. Confirm the log path
```
:::tip ⚠️Note that this problem will occur if CGO is not installed in the windows environment;
:::tip ⚠️Note that this problem will occur if CGO is not installed in the windows10+ environment;
```bash
E:\go-admin>go build
@@ -152,7 +171,7 @@ D:\Code\go-admin>go build
cgo: exec gcc: exec: "gcc": executable file not found in %PATH%
```
[Solve the cgo problem and enter](https://doc.go-admin.dev/guide/other/faq.html#_5-cgo-exec-missing-cc-exec-missing-cc-file-does-not-exist)
[Solve the cgo problem and enter](https://doc.go-admin.dev/guide/faq#cgo-%E7%9A%84%E9%97%AE%E9%A2%98)
:::
@@ -161,10 +180,10 @@ cgo: exec gcc: exec: "gcc": executable file not found in %PATH%
``` bash
# The first configuration needs to initialize the database resource information
# Use under macOS or linux
$ ./go-admin migrate -c=config/settings.dev.yml
$ ./go-admin migrate -c config/settings.dev.yml
# ⚠️Note: Use under windows
$ go-admin.exe migrate -c=config/settings.dev.yml
$ go-admin.exe migrate -c config/settings.dev.yml
# Start the project, you can also use the IDE for debugging
# Use under macOS or linux
@@ -207,38 +226,79 @@ env GOOS=linux GOARCH=amd64 go build main.go
### UI interactive terminal startup instructions
```bash
# Install pnpm if you don't have it
npm install -g pnpm
# Installation dependencies
npm install # or cnpm install
pnpm install
# Start service
npm run dev
pnpm dev
```
## 🎬 Online Demo
> admin / 123456
演示地址:[http://www.go-admin.dev](http://www.go-admin.dev/#/login)
## 📨 Interactive
<table>
<tr>
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/wx.png" width="180px"></td>
<td><img src="https://doc-image.zhangwj.com/img/qrcode_for_gh_b798dc7db30c_258.jpg" width="180px"></td>
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/qq2.png" width="200px"></td>
<td><a href="https://space.bilibili.com/565616721">wenjianzhang</a></td>
</tr>
<tr>
<td>Wechat</td>
<td>Wechat公众号🔥🔥🔥</td>
<td><a target="_blank" href="https://shang.qq.com/wpa/qunwpa?idkey=0f2bf59f5f2edec6a4550c364242c0641f870aa328e468c4ee4b7dbfb392627b"><img border="0" src="https://pub.idqqimg.com/wpa/images/group.png" alt="go-admin技术交流乙号" title="go-admin技术交流乙号"></a></td>
<td>bilibili🔥🔥🔥</td>
</tr>
</table>
## 💎 Members
## 💎 Contributors
<a href="https://github.com/wenjianzhang"> <img src="https://avatars.githubusercontent.com/u/3890175?s=460&u=20eac63daef81588fbac611da676b99859319251&v=4" width="80px"></a>
<a href="https://github.com/lwnmengjing"> <img src="https://avatars.githubusercontent.com/u/12806223?s=400&u=a89272dce50100b77b4c0d5c81c718bf78ebb580&v=4" width="80px"></a>
<a href="https://github.com/chengxiao"> <img src="https://avatars.githubusercontent.com/u/1379545?s=460&u=557da5503d0ac4a8628df6b4075b17853d5edcd9&v=4" width="80px"></a>
<a href="https://github.com/bing127"> <img src="https://avatars.githubusercontent.com/u/31166183?s=460&u=c085bff88df10bb7676c8c0351ba9dcd031d1fb3&v=4" width="80px"></a>
<span style="margin: 0 5px;" ><a href="https://github.com/wenjianzhang" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/3890175?v=4&h=60&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/G-Akiraka" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/45746659?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/lwnmengjing" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/12806223?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/bing127" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/31166183?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/chengxiao" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/1379545?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/NightFire0307" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/19854086?v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/appleboy" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/21979?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/ninstein" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/580303?v=4&h=60&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/kikiyou" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/17959053?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/horizonzy" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/22524871?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/Cassuis" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/48005724?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/hqcchina" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/5179057?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/nodece" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/16235121?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/stephenzhang0713" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/18169290?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/zhouxixi-dev" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/100399679?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/Jalins" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/31172582?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/wkf928592" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/6063351?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/wxxiong6" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/6983441?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/Silicon-He" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/52478309?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/GizmoOAO" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/20385106?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/bestgopher" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/36840497?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/wxb1207" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/20775558?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/misakichan" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/16569274?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/zhuxuyang" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/19301024?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/mss-boot" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/109259065?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/AuroraV" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/37330199?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/Vingurzhou" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/57127283?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/haimait" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/40926384?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/zyd" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/3446278?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/infnan" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/38274826?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/d1y" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/45585937?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/qlijin" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/515900?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/logtous
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/88697234?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/stepway
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/9927079?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/NaturalGao
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/43291304?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/DemoLiang
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/23476007?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/jfcg
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/1410597?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
<span style="margin: 0 5px;" ><a href="https://github.com/Nicole0724
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/10487328?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
@@ -250,7 +310,11 @@ The `go-admin` project has always been developed in the GoLand integrated develo
## 🤝 Thanks
1. [chengxiao](https://github.com/chengxiao)
1. [ant-design](https://github.com/ant-design/ant-design)
2. [ant-design-pro](https://github.com/ant-design/ant-design-pro)
2. [arco-design](https://github.com/arco-design/arco-design)
2. [arco-design-pro](https://github.com/arco-design/arco-design-pro)
2. [gin](https://github.com/gin-gonic/gin)
2. [casbin](https://github.com/casbin/casbin)
2. [spf13/viper](https://github.com/spf13/viper)
@@ -268,10 +332,11 @@ The `go-admin` project has always been developed in the GoLand integrated develo
<img class="no-margin" src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/pay.png" height="200px" >
## 🤝 Link
[Go developer growth roadmap](http://www.golangroadmap.com/)
- [Go developer growth roadmap](http://www.golangroadmap.com/)
- [mss-boot-io](https://docs.mss-boot-io.top/)
## 🔑 License
[MIT](https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md)
Copyright (c) 2020 wenjianzhang
Copyright (c) 2022 wenjianzhang
+3 -3
View File
@@ -17,17 +17,17 @@ type System struct {
// @Success 200 {object} response.Response{data=string,id=string,msg=string} "{"code": 200, "data": [...]}"
// @Router /api/v1/captcha [get]
func (e System) GenerateCaptchaHandler(c *gin.Context) {
err := e.MakeContext(c).Errors
if err != nil {
if err := e.MakeContext(c).Errors; err != nil {
e.Error(500, err, "服务初始化失败!")
return
}
id, b64s, err := captcha.DriverDigitFunc()
id, b64s, answer, err := captcha.DriverDigitFunc()
if err != nil {
e.Logger.Errorf("DriverDigitFunc error, %s", err.Error())
e.Error(500, err, "验证码获取失败")
return
}
e.Logger.Infof("DriverDigitFunc answer: %s", answer)
e.Custom(gin.H{
"code": 200,
"data": b64s,
+7 -6
View File
@@ -11,13 +11,14 @@ const INDEX = `
<meta charset="utf-8">
<title>GO-ADMIN欢迎您</title>
<style>
body{
margin:0;
padding:0;
overflow-y:hidden
html,body{
margin:0;
padding:0;
height:100%;
overflow-y:hidden;
}
</style>
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
<script src="https://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
<script type="text/javascript">
window.onerror=function(){return true;}
$(function(){
@@ -28,7 +29,7 @@ $(function(){
</script>
</head>
<body>
<iframe id="iframe" frameborder="0" src="https://doc.go-admin.dev" style="width:100%;"></iframe>
<iframe id="iframe" frameborder="0" src="https://www.go-admin.pro" style="width:100%;height:100%;"></iframe>
</body>
</html>
`
+2 -2
View File
@@ -92,7 +92,7 @@ func (e SysApi) Get(c *gin.Context) {
// @Tags 接口管理
// @Accept application/json
// @Product application/json
// @Param data body dto.SysApiControl true "body"
// @Param data body dto.SysApiUpdateReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}"
// @Router /api/v1/sys-api/{id} [put]
// @Security Bearer
@@ -122,7 +122,7 @@ func (e SysApi) Update(c *gin.Context) {
// @Summary 删除接口管理
// @Description 删除接口管理
// @Tags 接口管理
// @Param ids body []int false "ids"
// @Param data body dto.SysApiDeleteReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}"
// @Router /api/v1/sys-api [delete]
// @Security Bearer
+8 -8
View File
@@ -30,7 +30,7 @@ type SysConfig struct {
// @Security Bearer
func (e SysConfig) GetPage(c *gin.Context) {
s := service.SysConfig{}
req := dto.SysConfigSearch{}
req := dto.SysConfigGetPageReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.Form).
@@ -60,7 +60,7 @@ func (e SysConfig) GetPage(c *gin.Context) {
// @Router /api/v1/sys-config/{id} [get]
// @Security Bearer
func (e SysConfig) Get(c *gin.Context) {
req := dto.SysConfigById{}
req := dto.SysConfigGetReq{}
s := service.SysConfig{}
err := e.MakeContext(c).
MakeOrm().
@@ -158,7 +158,7 @@ func (e SysConfig) Update(c *gin.Context) {
// @Security Bearer
func (e SysConfig) Delete(c *gin.Context) {
s := service.SysConfig{}
req := dto.SysConfigById{}
req := dto.SysConfigDeleteReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON, nil).
@@ -179,14 +179,14 @@ func (e SysConfig) Delete(c *gin.Context) {
e.OK(req.GetId(), "删除成功")
}
// GetSysConfigBySysApp 获取系统配置信息
// Get2SysApp 获取系统配置信息
// @Summary 获取系统前台配置信息,主要注意这里不在验证权限
// @Description 获取系统配置信息,主要注意这里不在验证权限
// @Tags 配置管理
// @Success 200 {object} response.Response{data=map[string]string} "{"code": 200, "data": [...]}"
// @Router /api/v1/app-config [get]
func (e SysConfig) GetSysConfigBySysApp(c *gin.Context) {
req := dto.SysConfigSearch{}
func (e SysConfig) Get2SysApp(c *gin.Context) {
req := dto.SysConfigGetToSysAppReq{}
s := service.SysConfig{}
err := e.MakeContext(c).
MakeOrm().
@@ -198,7 +198,7 @@ func (e SysConfig) GetSysConfigBySysApp(c *gin.Context) {
return
}
// 控制只读前台的数据
req.IsFrontend = 1
req.IsFrontend = "1"
list := make([]models.SysConfig, 0)
err = s.GetWithKeyList(&req, &list)
if err != nil {
@@ -310,4 +310,4 @@ func (e SysConfig) GetSysConfigByKEYForService(c *gin.Context) {
return
}
e.OK(resp, s.Msg)
}
}
+12 -13
View File
@@ -29,7 +29,7 @@ type SysDept struct {
// @Security Bearer
func (e SysDept) GetPage(c *gin.Context) {
s := service.SysDept{}
req := dto.SysDeptSearch{}
req := dto.SysDeptGetPageReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
@@ -50,17 +50,16 @@ func (e SysDept) GetPage(c *gin.Context) {
}
// Get
// @Summary 部门列表数据
// @Summary 获取部门数据
// @Description 获取JSON
// @Tags 部门
// @Param deptId path string false "deptId"
// @Param position query string false "position"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/dept/{deptId} [get]
// @Security Bearer
func (e SysDept) Get(c *gin.Context) {
s := service.SysDept{}
req := dto.SysDeptById{}
req := dto.SysDeptGetReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON, nil).
@@ -88,14 +87,14 @@ func (e SysDept) Get(c *gin.Context) {
// @Tags 部门
// @Accept application/json
// @Product application/json
// @Param data body dto.SysDeptControl true "data"
// @Param data body dto.SysDeptInsertReq true "data"
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
// @Router /api/v1/dept [post]
// @Security Bearer
func (e SysDept) Insert(c *gin.Context) {
s := service.SysDept{}
req := dto.SysDeptControl{}
req := dto.SysDeptInsertReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON).
@@ -124,14 +123,14 @@ func (e SysDept) Insert(c *gin.Context) {
// @Accept application/json
// @Product application/json
// @Param id path int true "id"
// @Param data body dto.SysDeptControl true "body"
// @Param data body dto.SysDeptUpdateReq true "body"
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
// @Router /api/v1/dept/{deptId} [put]
// @Security Bearer
func (e SysDept) Update(c *gin.Context) {
s := service.SysDept{}
req := dto.SysDeptControl{}
req := dto.SysDeptUpdateReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
@@ -155,14 +154,14 @@ func (e SysDept) Update(c *gin.Context) {
// @Summary 删除部门
// @Description 删除数据
// @Tags 部门
// @Param data body dto.SysDeptById true "body"
// @Param data body dto.SysDeptDeleteReq true "body"
// @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
// @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
// @Router /api/v1/dept [delete]
// @Security Bearer
func (e SysDept) Delete(c *gin.Context) {
s := service.SysDept{}
req := dto.SysDeptById{}
req := dto.SysDeptDeleteReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON, nil).
@@ -185,10 +184,10 @@ func (e SysDept) Delete(c *gin.Context) {
// Get2Tree 用户管理 左侧部门树
func (e SysDept) Get2Tree(c *gin.Context) {
s := service.SysDept{}
req := dto.SysDeptSearch{}
req := dto.SysDeptGetPageReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req,binding.Form).
Bind(&req, binding.Form).
MakeService(&s.Service).
Errors
if err != nil {
@@ -236,4 +235,4 @@ func (e SysDept) GetDeptTreeRoleSelect(c *gin.Context) {
"depts": result,
"checkedKeys": menuIds,
}, "")
}
}
+25 -22
View File
@@ -30,7 +30,7 @@ type SysDictData struct {
// @Security Bearer
func (e SysDictData) GetPage(c *gin.Context) {
s := service.SysDictData{}
req := dto.SysDictDataSearch{}
req := dto.SysDictDataGetPageReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.Form).
@@ -63,7 +63,7 @@ func (e SysDictData) GetPage(c *gin.Context) {
// @Security Bearer
func (e SysDictData) Get(c *gin.Context) {
s := service.SysDictData{}
req := dto.SysDictDataById{}
req := dto.SysDictDataGetReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, nil).
@@ -93,14 +93,13 @@ func (e SysDictData) Get(c *gin.Context) {
// @Tags 字典数据
// @Accept application/json
// @Product application/json
// @Param data body dto.SysDictDataControl true "data"
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
// @Param data body dto.SysDictDataInsertReq true "data"
// @Success 200 {object} response.Response "{"code": 200, "message": "添加成功"}"
// @Router /api/v1/dict/data [post]
// @Security Bearer
func (e SysDictData) Insert(c *gin.Context) {
s := service.SysDictData{}
req := dto.SysDictDataControl{}
req := dto.SysDictDataInsertReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON).
@@ -127,14 +126,13 @@ func (e SysDictData) Insert(c *gin.Context) {
// @Tags 字典数据
// @Accept application/json
// @Product application/json
// @Param data body dto.SysDictDataControl true "body"
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
// @Param data body dto.SysDictDataUpdateReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}"
// @Router /api/v1/dict/data/{dictCode} [put]
// @Security Bearer
func (e SysDictData) Update(c *gin.Context) {
s := service.SysDictData{}
req := dto.SysDictDataControl{}
req := dto.SysDictDataUpdateReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON, nil).
@@ -158,14 +156,13 @@ func (e SysDictData) Update(c *gin.Context) {
// @Summary 删除字典数据
// @Description 删除数据
// @Tags 字典数据
// @Param dictCode body dto.SysDictDataById true "body"
// @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
// @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
// @Param dictCode body dto.SysDictDataDeleteReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}"
// @Router /api/v1/dict/data [delete]
// @Security Bearer
func (e SysDictData) Delete(c *gin.Context) {
s := service.SysDictData{}
req := dto.SysDictDataById{}
req := dto.SysDictDataDeleteReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON, nil).
@@ -185,21 +182,20 @@ func (e SysDictData) Delete(c *gin.Context) {
e.OK(req.GetId(), "删除成功")
}
// GetSysDictDataAll 数据字典根据key获取 业务页面使用
// GetAll 数据字典根据key获取 业务页面使用
// @Summary 数据字典根据key获取
// @Description 数据字典根据key获取
// @Tags 字典数据
// @Param dictType query int true "dictType"
// @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
// @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
// @Success 200 {object} response.Response{data=[]dto.SysDictDataGetAllResp} "{"code": 200, "data": [...]}"
// @Router /api/v1/dict-data/option-select [get]
// @Security Bearer
func (e SysDictData) GetSysDictDataAll(c *gin.Context) {
func (e SysDictData) GetAll(c *gin.Context) {
s := service.SysDictData{}
req := dto.SysDictDataSearch{}
req := dto.SysDictDataGetPageReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.Form).
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
@@ -213,5 +209,12 @@ func (e SysDictData) GetSysDictDataAll(c *gin.Context) {
e.Error(500, err, "查询失败")
return
}
e.OK(list, "查询成功")
}
l := make([]dto.SysDictDataGetAllResp, 0)
for _, i := range list {
d := dto.SysDictDataGetAllResp{}
e.Translate(i, &d)
l = append(l, d)
}
e.OK(l,"查询成功")
}
+12 -15
View File
@@ -31,7 +31,7 @@ type SysDictType struct {
// @Security Bearer
func (e SysDictType) GetPage(c *gin.Context) {
s := service.SysDictType{}
req := dto.SysDictTypeSearch{}
req :=dto.SysDictTypeGetPageReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.Form).
@@ -62,7 +62,7 @@ func (e SysDictType) GetPage(c *gin.Context) {
// @Security Bearer
func (e SysDictType) Get(c *gin.Context) {
s := service.SysDictType{}
req := dto.SysDictTypeById{}
req :=dto.SysDictTypeGetReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, nil).
@@ -88,14 +88,13 @@ func (e SysDictType) Get(c *gin.Context) {
// @Tags 字典类型
// @Accept application/json
// @Product application/json
// @Param data body dto.SysDictTypeControl true "data"
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
// @Param data body dto.SysDictTypeInsertReq true "data"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/dict/type [post]
// @Security Bearer
func (e SysDictType) Insert(c *gin.Context) {
s := service.SysDictType{}
req := dto.SysDictTypeControl{}
req :=dto.SysDictTypeInsertReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON).
@@ -122,14 +121,13 @@ func (e SysDictType) Insert(c *gin.Context) {
// @Tags 字典类型
// @Accept application/json
// @Product application/json
// @Param data body dto.SysDictTypeControl true "body"
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
// @Param data body dto.SysDictTypeUpdateReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/dict/type/{dictId} [put]
// @Security Bearer
func (e SysDictType) Update(c *gin.Context) {
s := service.SysDictType{}
req := dto.SysDictTypeControl{}
req :=dto.SysDictTypeUpdateReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON, nil).
@@ -153,14 +151,13 @@ func (e SysDictType) Update(c *gin.Context) {
// @Summary 删除字典类型
// @Description 删除数据
// @Tags 字典类型
// @Param dictId path int true "dictId"
// @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
// @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
// @Param dictCode body dto.SysDictTypeDeleteReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/dict/type [delete]
// @Security Bearer
func (e SysDictType) Delete(c *gin.Context) {
s := service.SysDictType{}
req := dto.SysDictTypeById{}
req :=dto.SysDictTypeDeleteReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON, nil).
@@ -192,7 +189,7 @@ func (e SysDictType) Delete(c *gin.Context) {
// @Security Bearer
func (e SysDictType) GetAll(c *gin.Context) {
s := service.SysDictType{}
req := dto.SysDictTypeSearch{}
req :=dto.SysDictTypeGetPageReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.Form).
+5 -7
View File
@@ -4,7 +4,6 @@ import (
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-admin-team/go-admin-core/sdk/api"
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
"go-admin/app/admin/models"
"go-admin/app/admin/service"
@@ -30,7 +29,7 @@ type SysLoginLog struct {
// @Security Bearer
func (e SysLoginLog) GetPage(c *gin.Context) {
s := service.SysLoginLog{}
req := dto.SysLoginLogSearch {}
req :=dto.SysLoginLogGetPageReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.Form).
@@ -61,10 +60,10 @@ func (e SysLoginLog) GetPage(c *gin.Context) {
// @Security Bearer
func (e SysLoginLog) Get(c *gin.Context) {
s := service.SysLoginLog{}
req := dto.SysLoginLogById{}
req :=dto.SysLoginLogGetReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON, nil).
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
@@ -85,13 +84,13 @@ func (e SysLoginLog) Get(c *gin.Context) {
// @Summary 登录日志删除
// @Description 登录日志删除
// @Tags 登录日志
// @Param data body dto.SysLoginLogById true "body"
// @Param data body dto.SysLoginLogDeleteReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/sys-login-log [delete]
// @Security Bearer
func (e SysLoginLog) Delete(c *gin.Context) {
s := service.SysLoginLog{}
req := dto.SysLoginLogById{}
req :=dto.SysLoginLogDeleteReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON, nil).
@@ -102,7 +101,6 @@ func (e SysLoginLog) Delete(c *gin.Context) {
e.Error(500, err, err.Error())
return
}
req.SetUpdateBy(user.GetUserId(c))
err = s.Remove(&req)
if err != nil {
e.Error(500, err, "删除失败")
+9 -48
View File
@@ -20,13 +20,12 @@ type SysMenu struct {
// @Description 获取JSON
// @Tags 菜单
// @Param menuName query string false "menuName"
// @Param menuName query string false "menuName"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/menu [get]
// @Security Bearer
func (e SysMenu) GetPage(c *gin.Context) {
s := service.SysMenu{}
req := dto.SysMenuSearch{}
req := dto.SysMenuGetPageReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.Form).
@@ -55,7 +54,7 @@ func (e SysMenu) GetPage(c *gin.Context) {
// @Router /api/v1/menu/{id} [get]
// @Security Bearer
func (e SysMenu) Get(c *gin.Context) {
req := dto.SysMenuById{}
req := dto.SysMenuGetReq{}
s := new(service.SysMenu)
err := e.MakeContext(c).
MakeOrm().
@@ -83,12 +82,12 @@ func (e SysMenu) Get(c *gin.Context) {
// @Tags 菜单
// @Accept application/json
// @Product application/json
// @Param data body dto.SysMenuControl true "data"
// @Param data body dto.SysMenuInsertReq true "data"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/menu [post]
// @Security Bearer
func (e SysMenu) Insert(c *gin.Context) {
req := dto.SysMenuControl{}
req := dto.SysMenuInsertReq{}
s := new(service.SysMenu)
err := e.MakeContext(c).
MakeOrm().
@@ -117,12 +116,12 @@ func (e SysMenu) Insert(c *gin.Context) {
// @Accept application/json
// @Product application/json
// @Param id path int true "id"
// @Param data body dto.SysMenuControl true "body"
// @Param data body dto.SysMenuUpdateReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/menu/{id} [put]
// @Security Bearer
func (e SysMenu) Update(c *gin.Context) {
req := dto.SysMenuControl{}
req := dto.SysMenuUpdateReq{}
s := new(service.SysMenu)
err := e.MakeContext(c).
MakeOrm().
@@ -148,12 +147,12 @@ func (e SysMenu) Update(c *gin.Context) {
// @Summary 删除菜单
// @Description 删除数据
// @Tags 菜单
// @Param data body dto.SysMenuById true "body"
// @Param data body dto.SysMenuDeleteReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/menu [delete]
// @Security Bearer
func (e SysMenu) Delete(c *gin.Context) {
control := new(dto.SysMenuById)
control := new(dto.SysMenuDeleteReq)
s := new(service.SysMenu)
err := e.MakeContext(c).
MakeOrm().
@@ -203,44 +202,6 @@ func (e SysMenu) GetMenuRole(c *gin.Context) {
e.OK(result, "")
}
//// GetMenuIDS 获取角色对应的菜单id数组
//// @Summary 获取角色对应的菜单id数组,设置角色权限使用
//// @Description 获取JSON
//// @Tags 菜单
//// @Param id path int true "id"
//// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
//// @Router /api/v1/menuids/{id} [get]
//// @Security Bearer
//func (e SysMenu) GetMenuIDS(c *gin.Context) {
// s := new(service.SysMenu)
// r := service.SysRole{}
// m := dto.SysRoleByName{}
// err := e.MakeContext(c).
// MakeOrm().
// Bind(&m, binding.JSON).
// MakeService(&s.Service).
// MakeService(&r.Service).
// Errors
// if err != nil {
// e.Logger.Error(err)
// e.Error(500, err, err.Error())
// return
// }
// var data models.SysRole
// err = r.GetWithName(&m, &data).Error
//
// //data.RoleName = c.GetString("role")
// //data.UpdateBy = user.GetUserId(c)
// //result, err := data.GetIDS(s.Orm)
//
// if err != nil {
// e.Logger.Errorf("GetIDS error, %s", err.Error())
// e.Error(500, err, "获取失败")
// return
// }
// e.OK(result, "")
//}
// GetMenuTreeSelect 根据角色ID查询菜单下拉树结构
// @Summary 角色修改使用的菜单列表
// @Description 获取JSON
@@ -285,4 +246,4 @@ func (e SysMenu) GetMenuTreeSelect(c *gin.Context) {
"menus": result,
"checkedKeys": menuIds,
}, "获取成功")
}
}
+3 -3
View File
@@ -65,7 +65,7 @@ func (e SysOperaLog) GetPage(c *gin.Context) {
// @Security Bearer
func (e SysOperaLog) Get(c *gin.Context) {
s := new(service.SysOperaLog)
req := dto.SysOperaLogById{}
req :=dto.SysOperaLogGetReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, nil).
@@ -90,13 +90,13 @@ func (e SysOperaLog) Get(c *gin.Context) {
// @Summary 删除操作日志
// @Description 删除数据
// @Tags 操作日志
// @Param data body dto.SysOperaLogById true "body"
// @Param data body dto.SysOperaLogDeleteReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/sys-opera-log [delete]
// @Security Bearer
func (e SysOperaLog) Delete(c *gin.Context) {
s := new(service.SysOperaLog)
req := dto.SysOperaLogById{}
req :=dto.SysOperaLogDeleteReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON).
+10 -12
View File
@@ -2,6 +2,7 @@ package apis
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-admin-team/go-admin-core/sdk/api"
@@ -30,7 +31,7 @@ type SysPost struct {
// @Security Bearer
func (e SysPost) GetPage(c *gin.Context) {
s := service.SysPost{}
req := dto.SysPostPageReq{}
req :=dto.SysPostPageReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.Form).
@@ -64,7 +65,7 @@ func (e SysPost) GetPage(c *gin.Context) {
// @Security Bearer
func (e SysPost) Get(c *gin.Context) {
s := service.SysPost{}
req := dto.SysPostGetReq{}
req :=dto.SysPostGetReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, nil).
@@ -93,13 +94,12 @@ func (e SysPost) Get(c *gin.Context) {
// @Accept application/json
// @Product application/json
// @Param data body dto.SysPostInsertReq true "data"
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/post [post]
// @Security Bearer
func (e SysPost) Insert(c *gin.Context) {
s := service.SysPost{}
req := dto.SysPostInsertReq{}
req :=dto.SysPostInsertReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON).
@@ -126,13 +126,12 @@ func (e SysPost) Insert(c *gin.Context) {
// @Accept application/json
// @Product application/json
// @Param data body dto.SysPostUpdateReq true "body"
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/post/{id} [put]
// @Security Bearer
func (e SysPost) Update(c *gin.Context) {
s := service.SysPost{}
req := dto.SysPostUpdateReq{}
req :=dto.SysPostUpdateReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON, nil).
@@ -159,13 +158,12 @@ func (e SysPost) Update(c *gin.Context) {
// @Description 删除数据
// @Tags 岗位
// @Param id body dto.SysPostDeleteReq true "请求参数"
// @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
// @Success 500 {string} string "{"code": 500, "message": "删除失败"}"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/post [delete]
// @Security Bearer
func (e SysPost) Delete(c *gin.Context) {
s := service.SysPost{}
req := dto.SysPostDeleteReq{}
req :=dto.SysPostDeleteReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON).
@@ -183,4 +181,4 @@ func (e SysPost) Delete(c *gin.Context) {
return
}
e.OK(req.GetId(), "删除成功")
}
}
+25 -23
View File
@@ -2,10 +2,12 @@ package apis
import (
"fmt"
"go-admin/common/global"
"net/http"
"github.com/gin-gonic/gin/binding"
"github.com/go-admin-team/go-admin-core/sdk"
"go-admin/app/admin/models"
"net/http"
"github.com/gin-gonic/gin"
"github.com/go-admin-team/go-admin-core/sdk/api"
@@ -14,7 +16,6 @@ import (
"go-admin/app/admin/service"
"go-admin/app/admin/service/dto"
"go-admin/common/global"
)
type SysRole struct {
@@ -35,7 +36,7 @@ type SysRole struct {
// @Security Bearer
func (e SysRole) GetPage(c *gin.Context) {
s := service.SysRole{}
req := dto.SysRoleSearch{}
req := dto.SysRoleGetPageReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.Form).
@@ -69,7 +70,7 @@ func (e SysRole) GetPage(c *gin.Context) {
// @Security Bearer
func (e SysRole) Get(c *gin.Context) {
s := service.SysRole{}
req := dto.SysRoleById{}
req := dto.SysRoleGetReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, nil).
@@ -98,13 +99,13 @@ func (e SysRole) Get(c *gin.Context) {
// @Tags 角色/Role
// @Accept application/json
// @Product application/json
// @Param data body dto.SysRoleControl true "data"
// @Param data body dto.SysRoleInsertReq true "data"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/role [post]
// @Security Bearer
func (e SysRole) Insert(c *gin.Context) {
s := service.SysRole{}
req := dto.SysRoleControl{}
req := dto.SysRoleInsertReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON).
@@ -121,16 +122,17 @@ func (e SysRole) Insert(c *gin.Context) {
if req.Status == "" {
req.Status = "2"
}
cb := sdk.Runtime.GetCasbinKey(c.Request.Host)
cb := sdk.Runtime.GetCasbinByTenant(c.Request.Host)
err = s.Insert(&req, cb)
if err != nil {
e.Logger.Error(err)
e.Error(500, err, "创建失败")
e.Error(500, err, "创建失败,"+err.Error())
return
}
_, err = global.LoadPolicy(c)
if err != nil {
e.Error(500, err, "")
e.Logger.Error(err)
e.Error(500, err, "创建失败,"+err.Error())
return
}
e.OK(req.GetId(), "创建成功")
@@ -142,13 +144,13 @@ func (e SysRole) Insert(c *gin.Context) {
// @Tags 角色/Role
// @Accept application/json
// @Product application/json
// @Param data body dto.SysRoleControl true "body"
// @Param data body dto.SysRoleUpdateReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/role/{id} [put]
// @Security Bearer
func (e SysRole) Update(c *gin.Context) {
s := service.SysRole{}
req := dto.SysRoleControl{}
req := dto.SysRoleUpdateReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, nil, binding.JSON).
@@ -159,7 +161,7 @@ func (e SysRole) Update(c *gin.Context) {
e.Error(500, err, err.Error())
return
}
cb := sdk.Runtime.GetCasbinKey(c.Request.Host)
cb := sdk.Runtime.GetCasbinByTenant(c.Request.Host)
req.SetUpdateBy(user.GetUserId(c))
@@ -168,11 +170,14 @@ func (e SysRole) Update(c *gin.Context) {
e.Logger.Error(err)
return
}
_, err = global.LoadPolicy(c)
if err != nil {
e.Error(500, err, "")
e.Logger.Error(err)
e.Error(500, err, "更新失败,"+err.Error())
return
}
e.OK(req.GetId(), "更新成功")
}
@@ -180,13 +185,13 @@ func (e SysRole) Update(c *gin.Context) {
// @Summary 删除用户角色
// @Description 删除数据
// @Tags 角色/Role
// @Param data body dto.SysRoleById true "body"
// @Param data body dto.SysRoleDeleteReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/role [delete]
// @Security Bearer
func (e SysRole) Delete(c *gin.Context) {
s := new(service.SysRole)
req := dto.SysRoleById{}
req := dto.SysRoleDeleteReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON).
@@ -198,17 +203,14 @@ func (e SysRole) Delete(c *gin.Context) {
return
}
err = s.Remove(&req)
cb := sdk.Runtime.GetCasbinByTenant(c.Request.Host)
err = s.Remove(&req, cb)
if err != nil {
e.Logger.Error(err)
e.Error(500, err, "")
return
}
_, err = global.LoadPolicy(c)
if err != nil {
e.Error(500, err, fmt.Sprintf("删除角色 %v 失败,失败信息 %s", req.Id, err.Error()))
return
}
e.OK(req.GetId(), fmt.Sprintf("删除角色角色 %v 状态成功!", req.GetId()))
}
@@ -227,7 +229,7 @@ func (e SysRole) Update2Status(c *gin.Context) {
req := dto.UpdateStatusReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
Bind(&req, binding.JSON, nil).
MakeService(&s.Service).
Errors
if err != nil {
@@ -279,4 +281,4 @@ func (e SysRole) Update2DataScope(c *gin.Context) {
return
}
e.OK(nil, "操作成功")
}
}
+19 -12
View File
@@ -3,6 +3,7 @@ package apis
import (
"github.com/gin-gonic/gin/binding"
"go-admin/app/admin/models"
"golang.org/x/crypto/bcrypt"
"net/http"
"github.com/gin-gonic/gin"
@@ -95,13 +96,13 @@ func (e SysUser) Get(c *gin.Context) {
// @Tags 用户
// @Accept application/json
// @Product application/json
// @Param data body dto.SysUserControl true "用户数据"
// @Param data body dto.SysUserInsertReq true "用户数据"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/sys-user [post]
// @Security Bearer
func (e SysUser) Insert(c *gin.Context) {
s := service.SysUser{}
req := dto.SysUserControl{}
req := dto.SysUserInsertReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON).
@@ -130,13 +131,13 @@ func (e SysUser) Insert(c *gin.Context) {
// @Tags 用户
// @Accept application/json
// @Product application/json
// @Param data body dto.SysUserControl true "body"
// @Param data body dto.SysUserUpdateReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/sys-user/{userId} [put]
// @Security Bearer
func (e SysUser) Update(c *gin.Context) {
s := service.SysUser{}
req := dto.SysUserControl{}
req := dto.SysUserUpdateReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
@@ -237,7 +238,7 @@ func (e SysUser) InsetAvatar(c *gin.Context) {
req.UserId = p.UserId
req.Avatar = "/" + filPath
err = s.UpdateSysUserAvatar(&req, p)
err = s.UpdateAvatar(&req, p)
if err != nil {
e.Logger.Error(err)
return
@@ -274,7 +275,7 @@ func (e SysUser) UpdateStatus(c *gin.Context) {
//数据权限检查
p := actions.GetPermissionFromContext(c)
err = s.UpdateSysUserStatus(&req, p)
err = s.UpdateStatus(&req, p)
if err != nil {
e.Logger.Error(err)
return
@@ -311,7 +312,7 @@ func (e SysUser) ResetPwd(c *gin.Context) {
//数据权限检查
p := actions.GetPermissionFromContext(c)
err = s.ResetSysUserPwd(&req, p)
err = s.ResetPwd(&req, p)
if err != nil {
e.Logger.Error(err)
return
@@ -320,7 +321,7 @@ func (e SysUser) ResetPwd(c *gin.Context) {
}
// UpdatePwd
// @Summary 重置密码
// @Summary 修改密码
// @Description 获取JSON
// @Tags 用户
// @Accept application/json
@@ -345,13 +346,18 @@ func (e SysUser) UpdatePwd(c *gin.Context) {
// 数据权限检查
p := actions.GetPermissionFromContext(c)
var hash []byte
if hash, err = bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost); err != nil {
req.NewPassword = string(hash)
}
err = s.UpdateSysUserPwd(user.GetUserId(c), req.OldPassword, req.NewPassword, p)
err = s.UpdatePwd(user.GetUserId(c), req.OldPassword, req.NewPassword, p)
if err != nil {
e.Logger.Error(err)
e.Error(http.StatusForbidden, err, "密码修改失败")
return
}
e.OK(nil, "密码修改成功")
}
@@ -380,7 +386,7 @@ func (e SysUser) GetProfile(c *gin.Context) {
sysUser := models.SysUser{}
roles := make([]models.SysRole, 0)
posts := make([]models.SysPost, 0)
err = s.GetSysUserProfile(&req, &sysUser, &roles, &posts)
err = s.GetProfile(&req, &sysUser, &roles, &posts)
if err != nil {
e.Logger.Errorf("get user profile error, %s", err.Error())
e.Error(500, err, "获取用户信息失败")
@@ -444,9 +450,10 @@ func (e SysUser) GetInfo(c *gin.Context) {
if sysUser.Avatar != "" {
mp["avatar"] = sysUser.Avatar
}
mp["userName"] = sysUser.NickName
mp["userName"] = sysUser.Username
mp["userId"] = sysUser.UserId
mp["deptId"] = sysUser.DeptId
mp["name"] = sysUser.NickName
mp["code"] = 200
e.OK(mp, "")
}
}
+8 -8
View File
@@ -1,14 +1,14 @@
package models
//sys_casbin_rule
type CasbinRule struct {
PType string `json:"p_type" gorm:"size:100;"`
V0 string `json:"v0" gorm:"size:100;"`
V1 string `json:"v1" gorm:"size:100;"`
V2 string `json:"v2" gorm:"size:100;"`
V3 string `json:"v3" gorm:"size:100;"`
V4 string `json:"v4" gorm:"size:100;"`
V5 string `json:"v5" gorm:"size:100;"`
ID uint `gorm:"primaryKey;autoIncrement"`
Ptype string `gorm:"size:512;uniqueIndex:unique_index"`
V0 string `gorm:"size:512;uniqueIndex:unique_index"`
V1 string `gorm:"size:512;uniqueIndex:unique_index"`
V2 string `gorm:"size:512;uniqueIndex:unique_index"`
V3 string `gorm:"size:512;uniqueIndex:unique_index"`
V4 string `gorm:"size:512;uniqueIndex:unique_index"`
V5 string `gorm:"size:512;uniqueIndex:unique_index"`
}
func (CasbinRule) TableName() string {
+1 -1
View File
@@ -31,7 +31,7 @@ func ExecSql(db *gorm.DB, filePath string) error {
fmt.Println(sqlList[i])
continue
}
sql := strings.Replace(sqlList[i]+";", "\n", "", 0)
sql := strings.Replace(sqlList[i]+";", "\n", "", -1)
sql = strings.TrimSpace(sql)
if err = db.Exec(sql).Error; err != nil {
log.Printf("error sql: %s", sql)
-11
View File
@@ -1,11 +0,0 @@
package models
import (
"time"
)
type BaseModel struct {
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
DeletedAt *time.Time `json:"deletedAt"`
}
+22 -5
View File
@@ -1,10 +1,14 @@
package models
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"regexp"
"strings"
"github.com/bitly/go-simplejson"
"github.com/go-admin-team/go-admin-core/sdk"
"github.com/go-admin-team/go-admin-core/sdk/runtime"
"github.com/go-admin-team/go-admin-core/storage"
@@ -23,7 +27,7 @@ type SysApi struct {
models.ControlBy
}
func (SysApi) TableName() string {
func (*SysApi) TableName() string {
return "sys_api"
}
@@ -40,17 +44,17 @@ func SaveSysApi(message storage.Messager) (err error) {
var rb []byte
rb, err = json.Marshal(message.GetValues())
if err != nil {
fmt.Errorf("json Marshal error, %s", err.Error())
err = fmt.Errorf("json Marshal error, %v", err.Error())
return err
}
var l runtime.Routers
err = json.Unmarshal(rb, &l)
if err != nil {
fmt.Errorf("json Unmarshal error, %s", err.Error())
err = fmt.Errorf("json Unmarshal error, %s", err.Error())
return err
}
dbList := sdk.Runtime.GetDb()
dbList := sdk.Runtime.GetAllDb()
for _, d := range dbList {
for _, v := range l.List {
if v.HttpMethod != "HEAD" ||
@@ -58,8 +62,21 @@ func SaveSysApi(message storage.Messager) (err error) {
strings.Contains(v.RelativePath, "/static/") ||
strings.Contains(v.RelativePath, "/form-generator/") ||
strings.Contains(v.RelativePath, "/sys/tables") {
// 根据接口方法注释里的@Summary填充接口名称,适用于代码生成器
// 可在此处增加配置路径前缀的if判断,只对代码生成的自建应用进行定向的接口名称填充
jsonFile, _ := ioutil.ReadFile("docs/swagger.json")
jsonData, _ := simplejson.NewFromReader(bytes.NewReader(jsonFile))
urlPath := v.RelativePath
idPatten := "(.*)/:(\\w+)" // 正则替换,把:id换成{id}
reg, _ := regexp.Compile(idPatten)
if reg.MatchString(urlPath) {
urlPath = reg.ReplaceAllString(v.RelativePath, "${1}/{${2}}") // 把:id换成{id}
}
apiTitle, _ := jsonData.Get("paths").Get(urlPath).Get(strings.ToLower(v.HttpMethod)).Get("summary").String()
err := d.Debug().Where(SysApi{Path: v.RelativePath, Action: v.HttpMethod}).
Attrs(SysApi{Handle: v.Handler}).
Attrs(SysApi{Handle: v.Handler, Title: apiTitle}).
FirstOrCreate(&SysApi{}).
//Update("handle", v.Handler).
Error
+2 -2
View File
@@ -10,13 +10,13 @@ type SysConfig struct {
ConfigKey string `json:"configKey" gorm:"size:128;comment:ConfigKey"` //
ConfigValue string `json:"configValue" gorm:"size:255;comment:ConfigValue"` //
ConfigType string `json:"configType" gorm:"size:64;comment:ConfigType"`
IsFrontend int `json:"isFrontend" gorm:"size:64;comment:是否前台"` //
IsFrontend string `json:"isFrontend" gorm:"size:64;comment:是否前台"` //
Remark string `json:"remark" gorm:"size:128;comment:Remark"` //
models.ControlBy
models.ModelTime
}
func (SysConfig) TableName() string {
func (*SysConfig) TableName() string {
return "sys_config"
}
+2 -2
View File
@@ -7,7 +7,7 @@ type SysDept struct {
ParentId int `json:"parentId" gorm:""` //上级部门
DeptPath string `json:"deptPath" gorm:"size:255;"` //
DeptName string `json:"deptName" gorm:"size:128;"` //部门名称
Sort int `json:"sort" gorm:"size:4;"` //排序
Sort int `json:"sort" gorm:"size:4;"` //排序
Leader string `json:"leader" gorm:"size:128;"` //负责人
Phone string `json:"phone" gorm:"size:11;"` //手机
Email string `json:"email" gorm:"size:64;"` //邮箱
@@ -19,7 +19,7 @@ type SysDept struct {
Children []SysDept `json:"children" gorm:"-"`
}
func (SysDept) TableName() string {
func (*SysDept) TableName() string {
return "sys_dept"
}
+1 -1
View File
@@ -20,7 +20,7 @@ type SysDictData struct {
models.ModelTime
}
func (SysDictData) TableName() string {
func (*SysDictData) TableName() string {
return "sys_dict_data"
}
+1 -1
View File
@@ -14,7 +14,7 @@ type SysDictType struct {
models.ModelTime
}
func (SysDictType) TableName() string {
func (*SysDictType) TableName() string {
return "sys_dict_type"
}
+2 -2
View File
@@ -29,7 +29,7 @@ type SysLoginLog struct {
models.ControlBy
}
func (SysLoginLog) TableName() string {
func (*SysLoginLog) TableName() string {
return "sys_login_log"
}
@@ -45,7 +45,7 @@ func (e *SysLoginLog) GetId() interface{} {
// SaveLoginLog 从队列中获取登录日志
func SaveLoginLog(message storage.Messager) (err error) {
//准备db
db := sdk.Runtime.GetDbByKey(message.GetPrefix())
db := sdk.Runtime.GetDbByTenant(message.GetPrefix())
if db == nil {
err = errors.New("db not exist")
log.Errorf("host[%s]'s %s", message.GetPrefix(), err.Error())
+8 -2
View File
@@ -30,7 +30,13 @@ type SysMenu struct {
models.ModelTime
}
func (SysMenu) TableName() string {
type SysMenuSlice []SysMenu
func (x SysMenuSlice) Len() int { return len(x) }
func (x SysMenuSlice) Less(i, j int) bool { return x[i].Sort < x[j].Sort }
func (x SysMenuSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (*SysMenu) TableName() string {
return "sys_menu"
}
@@ -41,4 +47,4 @@ func (e *SysMenu) Generate() models.ActiveRecord {
func (e *SysMenu) GetId() interface{} {
return e.MenuId
}
}
+9 -5
View File
@@ -18,15 +18,15 @@ type SysOperaLog struct {
BusinessType string `json:"businessType" gorm:"size:128;comment:操作类型"`
BusinessTypes string `json:"businessTypes" gorm:"size:128;comment:BusinessTypes"`
Method string `json:"method" gorm:"size:128;comment:函数"`
RequestMethod string `json:"requestMethod" gorm:"size:128;comment:请求方式"`
RequestMethod string `json:"requestMethod" gorm:"size:128;comment:请求方式 GET POST PUT DELETE"`
OperatorType string `json:"operatorType" gorm:"size:128;comment:操作类型"`
OperName string `json:"operName" gorm:"size:128;comment:操作者"`
DeptName string `json:"deptName" gorm:"size:128;comment:部门名称"`
OperUrl string `json:"operUrl" gorm:"size:255;comment:访问地址"`
OperIp string `json:"operIp" gorm:"size:128;comment:客户端ip"`
OperLocation string `json:"operLocation" gorm:"size:128;comment:访问位置"`
OperParam string `json:"operParam" gorm:"size:255;comment:请求参数"`
Status string `json:"status" gorm:"size:4;comment:操作状态"`
OperParam string `json:"operParam" gorm:"text;comment:请求参数"`
Status string `json:"status" gorm:"size:4;comment:操作状态 1:正常 2:关闭"`
OperTime time.Time `json:"operTime" gorm:"comment:操作时间"`
JsonResult string `json:"jsonResult" gorm:"size:255;comment:返回数据"`
Remark string `json:"remark" gorm:"size:255;comment:备注"`
@@ -37,7 +37,7 @@ type SysOperaLog struct {
models.ControlBy
}
func (SysOperaLog) TableName() string {
func (*SysOperaLog) TableName() string {
return "sys_opera_log"
}
@@ -53,7 +53,7 @@ func (e *SysOperaLog) GetId() interface{} {
// SaveOperaLog 从队列中获取操作日志
func SaveOperaLog(message storage.Messager) (err error) {
//准备db
db := sdk.Runtime.GetDbByKey(message.GetPrefix())
db := sdk.Runtime.GetDbByTenant(message.GetPrefix())
if db == nil {
err = errors.New("db not exist")
log.Errorf("host[%s]'s %s", message.GetPrefix(), err.Error())
@@ -74,6 +74,10 @@ func SaveOperaLog(message storage.Messager) (err error) {
// Log writing to the database ignores error
return nil
}
// 超出100个字符返回值截断
if len(l.JsonResult) > 100 {
l.JsonResult = l.JsonResult[:100]
}
err = db.Create(&l).Error
if err != nil {
log.Errorf("db create error, %s", err.Error())
+2 -2
View File
@@ -16,7 +16,7 @@ type SysPost struct {
Params string `gorm:"-" json:"params"`
}
func (SysPost) TableName() string {
func (*SysPost) TableName() string {
return "sys_post"
}
@@ -27,4 +27,4 @@ func (e *SysPost) Generate() models.ActiveRecord {
func (e *SysPost) GetId() interface{} {
return e.PostId
}
}
+15 -15
View File
@@ -3,25 +3,25 @@ package models
import "go-admin/common/models"
type SysRole struct {
RoleId int `json:"roleId" gorm:"primaryKey;autoIncrement"` // 角色编码
RoleName string `json:"roleName" gorm:"size:128;"` // 角色名称
Status string `json:"status" gorm:"size:4;"` //
RoleKey string `json:"roleKey" gorm:"size:128;"` //角色代码
RoleSort int `json:"roleSort" gorm:""` //角色排序
Flag string `json:"flag" gorm:"size:128;"` //
Remark string `json:"remark" gorm:"size:255;"` //备注
Admin bool `json:"admin" gorm:"size:4;"`
DataScope string `json:"dataScope" gorm:"size:128;"`
Params string `json:"params" gorm:"-"`
MenuIds []int `json:"menuIds" gorm:"-"`
DeptIds []int `json:"deptIds" gorm:"-"`
SysDept []SysDept `json:"sysDept" gorm:"many2many:sys_role_dept;foreignKey:RoleId;joinForeignKey:role_id;references:DeptId;joinReferences:dept_id;"`
RoleId int `json:"roleId" gorm:"primaryKey;autoIncrement"` // 角色编码
RoleName string `json:"roleName" gorm:"size:128;"` // 角色名称
Status string `json:"status" gorm:"size:4;"` // 状态 1禁用 2正常
RoleKey string `json:"roleKey" gorm:"size:128;"` //角色代码
RoleSort int `json:"roleSort" gorm:""` //角色排序
Flag string `json:"flag" gorm:"size:128;"` //
Remark string `json:"remark" gorm:"size:255;"` //备注
Admin bool `json:"admin" gorm:"size:4;"`
DataScope string `json:"dataScope" gorm:"size:128;"`
Params string `json:"params" gorm:"-"`
MenuIds []int `json:"menuIds" gorm:"-"`
DeptIds []int `json:"deptIds" gorm:"-"`
SysDept []SysDept `json:"sysDept" gorm:"many2many:sys_role_dept;foreignKey:RoleId;joinForeignKey:role_id;references:DeptId;joinReferences:dept_id;"`
SysMenu *[]SysMenu `json:"sysMenu" gorm:"many2many:sys_role_menu;foreignKey:RoleId;joinForeignKey:role_id;references:MenuId;joinReferences:menu_id;"`
models.ControlBy
models.ModelTime
}
func (SysRole) TableName() string {
func (*SysRole) TableName() string {
return "sys_role"
}
@@ -32,4 +32,4 @@ func (e *SysRole) Generate() models.ActiveRecord {
func (e *SysRole) GetId() interface{} {
return e.RoleId
}
}
+2 -2
View File
@@ -29,7 +29,7 @@ type SysUser struct {
models.ModelTime
}
func (SysUser) TableName() string {
func (*SysUser) TableName() string {
return "sys_user"
}
@@ -42,7 +42,7 @@ func (e *SysUser) GetId() interface{} {
return e.UserId
}
//加密
// Encrypt 加密
func (e *SysUser) Encrypt() (err error) {
if e.Password == "" {
return
+1 -2
View File
@@ -12,7 +12,6 @@ var (
routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0)
)
// 路由示例
func InitExamplesRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine {
// 无需认证的路由
@@ -39,4 +38,4 @@ func examplesCheckRoleRouter(r *gin.Engine, authMiddleware *jwtauth.GinJWTMiddle
for _, f := range routerCheckRole {
f(v1, authMiddleware)
}
}
}
+1 -1
View File
@@ -31,7 +31,7 @@ func registerSysConfigRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMidd
r2 := v1.Group("/app-config")
{
r2.GET("", api.GetSysConfigBySysApp)
r2.GET("", api.Get2SysApp)
}
r3 := v1.Group("/set-config").Use(authMiddleware.MiddlewareFunc())
+1 -1
View File
@@ -21,7 +21,7 @@ func registerSysDeptRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle
r.GET("/:id", api.Get)
r.POST("", api.Insert)
r.PUT("/:id", api.Update)
r.DELETE("/:id", api.Delete)
r.DELETE("", api.Delete)
}
r1 := v1.Group("").Use(authMiddleware.MiddlewareFunc())
+1 -1
View File
@@ -32,6 +32,6 @@ func registerDictRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddlewar
}
opSelect := v1.Group("/dict-data").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
{
opSelect.GET("/option-select", dataApi.GetSysDictDataAll)
opSelect.GET("/option-select", dataApi.GetAll)
}
}
+16 -7
View File
@@ -1,19 +1,21 @@
package router
import (
"github.com/go-admin-team/go-admin-core/sdk/config"
"go-admin/app/admin/apis"
"mime"
"github.com/go-admin-team/go-admin-core/sdk/config"
"github.com/gin-gonic/gin"
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
"github.com/go-admin-team/go-admin-core/sdk/pkg/ws"
ginSwagger "github.com/swaggo/gin-swagger"
"github.com/swaggo/gin-swagger/swaggerFiles"
swaggerfiles "github.com/swaggo/files"
"go-admin/common/middleware"
"go-admin/common/middleware/handler"
_ "go-admin/docs"
_ "go-admin/docs/admin"
)
func InitSysRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.RouterGroup {
@@ -54,11 +56,11 @@ func sysStaticFileRouter(r *gin.RouterGroup) {
}
func sysSwaggerRouter(r *gin.RouterGroup) {
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
r.GET("/swagger/admin/*any", ginSwagger.WrapHandler(swaggerfiles.NewHandler(), ginSwagger.InstanceName("admin")))
}
func sysCheckRoleRouterInit(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
wss:=r.Group("").Use(authMiddleware.MiddlewareFunc())
wss := r.Group("").Use(authMiddleware.MiddlewareFunc())
{
wss.GET("/ws/:id/:channel", ws.WebsocketManager.WsClient)
wss.GET("/wslogout/:id/:channel", ws.WebsocketManager.UnWsClient)
@@ -67,8 +69,15 @@ func sysCheckRoleRouterInit(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle
v1 := r.Group("/api/v1")
{
v1.POST("/login", authMiddleware.LoginHandler)
// Refresh time can be longer than token timeout
v1.GET("/refresh_token", authMiddleware.RefreshHandler)
// GET /api/v1/refresh_token 已移除,原因见 issue #820:
// 该接口用业务 token 即可换取新 token,而续期上限 MaxRefresh 依据的
// orig_iat 在每次续期时被一并重置,上限永远无法到达 —— token 一旦泄
// 露即等同于永久访问权。它此前还位于 CasbinExclude 中,任何角色的已
// 登录用户都能调用,不受权限约束。
//
// 官方前端从未调用该接口(store 中的 refreshToken action 无人 dispatch),
// 移除不影响正常使用。若确需无感续期,应在 go-admin-core 中区分
// access token 与 refresh token 后重新实现,而非沿用此路由。
}
registerBaseRouter(v1, authMiddleware)
}
+12 -3
View File
@@ -11,8 +11,9 @@ type SysApiGetPageReq struct {
dto.Pagination `search:"-"`
Title string `form:"title" search:"type:contains;column:title;table:sys_api" comment:"标题"`
Path string `form:"path" search:"type:contains;column:path;table:sys_api" comment:"地址"`
Action string `form:"action" search:"type:exact;column:action;table:sys_api" comment:"类型"`
Action string `form:"action" search:"type:exact;column:action;table:sys_api" comment:"请求方式"`
ParentId string `form:"parentId" search:"type:exact;column:parent_id;table:sys_api" comment:"按钮id"`
Type string `form:"type" search:"-" comment:"类型"`
SysApiOrder
}
@@ -77,10 +78,18 @@ func (s *SysApiUpdateReq) GetId() interface{} {
// SysApiGetReq 功能获取请求参数
type SysApiGetReq struct {
dto.ObjectGetReq
Id int `uri:"id"`
}
func (s *SysApiGetReq) GetId() interface{} {
return s.Id
}
// SysApiDeleteReq 功能删除请求参数
type SysApiDeleteReq struct {
dto.ObjectDeleteReq
Ids []int `json:"ids"`
}
func (s *SysApiDeleteReq) GetId() interface{} {
return s.Ids
}
+24 -19
View File
@@ -6,13 +6,13 @@ import (
common "go-admin/common/models"
)
// SysConfigSearch 列表或者搜索使用结构体
type SysConfigSearch struct {
// SysConfigGetPageReq 列表或者搜索使用结构体
type SysConfigGetPageReq struct {
dto.Pagination `search:"-"`
ConfigName string `form:"configName" search:"type:contains;column:config_name;table:sys_config"`
ConfigKey string `form:"configKey" search:"type:contains;column:config_key;table:sys_config"`
ConfigType string `form:"configType" search:"type:exact;column:config_type;table:sys_config"`
IsFrontend int `form:"isFrontend" search:"type:exact;column:is_frontend;table:sys_config"`
IsFrontend string `form:"isFrontend" search:"type:exact;column:is_frontend;table:sys_config"`
SysConfigOrder
}
@@ -24,7 +24,15 @@ type SysConfigOrder struct {
CreatedAtOrder string `search:"type:order;column:created_at;table:sys_config" form:"createdAtOrder"`
}
func (m *SysConfigSearch) GetNeedSearch() interface{} {
func (m *SysConfigGetPageReq) GetNeedSearch() interface{} {
return *m
}
type SysConfigGetToSysAppReq struct {
IsFrontend string `form:"isFrontend" search:"type:exact;column:is_frontend;table:sys_config"`
}
func (m *SysConfigGetToSysAppReq) GetNeedSearch() interface{} {
return *m
}
@@ -35,7 +43,7 @@ type SysConfigControl struct {
ConfigKey string `uri:"configKey" json:"configKey" comment:""`
ConfigValue string `json:"configValue" comment:""`
ConfigType string `json:"configType" comment:""`
IsFrontend int `json:"isFrontend"`
IsFrontend string `json:"isFrontend"`
Remark string `json:"remark" comment:""`
common.ControlBy
}
@@ -86,22 +94,19 @@ type GetSysConfigByKEYForServiceResp struct {
ConfigValue string `json:"configValue" comment:""`
}
// SysConfigById 获取单个或者删除的结构体
type SysConfigById struct {
Id int `uri:"id"`
type SysConfigGetReq struct {
Id int `uri:"id"`
}
func (s *SysConfigGetReq) GetId() interface{} {
return s.Id
}
type SysConfigDeleteReq struct {
Ids []int `json:"ids"`
common.ControlBy
}
func (s *SysConfigById) Generate() *SysConfigById {
cp := *s
return &cp
}
func (s *SysConfigById) GetId() interface{} {
if len(s.Ids) > 0 {
s.Ids = append(s.Ids, s.Id)
return s.Ids
}
return s.Id
func (s *SysConfigDeleteReq) GetId() interface{} {
return s.Ids
}
+56 -35
View File
@@ -3,13 +3,10 @@ package dto
import (
"go-admin/app/admin/models"
common "go-admin/common/models"
"go-admin/common/dto"
)
// SysDeptSearch 列表或者搜索使用结构体
type SysDeptSearch struct {
dto.Pagination `search:"-"`
// SysDeptGetPageReq 列表或者搜索使用结构体
type SysDeptGetPageReq struct {
DeptId int `form:"deptId" search:"type:exact;column:dept_id;table:sys_dept" comment:"id"` //id
ParentId int `form:"parentId" search:"type:exact;column:parent_id;table:sys_dept" comment:"上级部门"` //上级部门
DeptPath string `form:"deptPath" search:"type:exact;column:dept_path;table:sys_dept" comment:""` //路径
@@ -21,26 +18,24 @@ type SysDeptSearch struct {
Status string `form:"status" search:"type:exact;column:status;table:sys_dept" comment:"状态"` //状态
}
func (m *SysDeptSearch) GetNeedSearch() interface{} {
func (m *SysDeptGetPageReq) GetNeedSearch() interface{} {
return *m
}
// SysDeptControl 增、改使用的结构体
type SysDeptControl struct {
DeptId int `uri:"id" comment:"编码"` // 编码
ParentId int `json:"parentId" comment:"上级部门" vd:"?"` //上级部门
DeptPath string `json:"deptPath" comment:""` //路径
DeptName string `json:"deptName" comment:"部门名称" vd:"len($)>0"` //部门名称
Sort int `json:"sort" comment:"排序" vd:"?"` //排序
Leader string `json:"leader" comment:"负责人" vd:"@:len($)>0; msg:'leader不能为空'"` //负责人
Phone string `json:"phone" comment:"手机" vd:"?"` //手机
Email string `json:"email" comment:"邮箱" vd:"?"` //邮箱
Status int `json:"status" comment:"状态" vd:"$>0"` //状态
type SysDeptInsertReq struct {
DeptId int `uri:"id" comment:"编码"` // 编码
ParentId int `json:"parentId" comment:"上级部门" vd:"?"` //上级部门
DeptPath string `json:"deptPath" comment:""` //路径
DeptName string `json:"deptName" comment:"部门名称" vd:"len($)>0"` //部门名称
Sort int `json:"sort" comment:"排序" vd:"?"` //排序
Leader string `json:"leader" comment:"负责人" vd:"@:len($)>0; msg:'leader不能为空'"` //负责人
Phone string `json:"phone" comment:"手机" vd:"?"` //手机
Email string `json:"email" comment:"邮箱" vd:"?"` //邮箱
Status int `json:"status" comment:"状态" vd:"$>0"` //状态
common.ControlBy
}
// Generate 结构体数据转化 从 SysDeptControl 至 SysDept 对应的模型
func (s *SysDeptControl) Generate(model *models.SysDept) {
func (s *SysDeptInsertReq) Generate(model *models.SysDept) {
if s.DeptId != 0 {
model.DeptId = s.DeptId
}
@@ -55,31 +50,57 @@ func (s *SysDeptControl) Generate(model *models.SysDept) {
}
// GetId 获取数据对应的ID
func (s *SysDeptControl) GetId() interface{} {
func (s *SysDeptInsertReq) GetId() interface{} {
return s.DeptId
}
// SysDeptById 获取单个或者删除的结构体
type SysDeptById struct {
Id int `uri:"id"`
Ids []int `json:"ids"`
type SysDeptUpdateReq struct {
DeptId int `uri:"id" comment:"编码"` // 编码
ParentId int `json:"parentId" comment:"上级部门" vd:"?"` //上级部门
DeptPath string `json:"deptPath" comment:""` //路径
DeptName string `json:"deptName" comment:"部门名称" vd:"len($)>0"` //部门名称
Sort int `json:"sort" comment:"排序" vd:"?"` //排序
Leader string `json:"leader" comment:"负责人" vd:"@:len($)>0; msg:'leader不能为空'"` //负责人
Phone string `json:"phone" comment:"手机" vd:"?"` //手机
Email string `json:"email" comment:"邮箱" vd:"?"` //邮箱
Status int `json:"status" comment:"状态" vd:"$>0"` //状态
common.ControlBy
}
func (s *SysDeptById) Generate() *SysDeptById {
cp := *s
return &cp
}
func (s *SysDeptById) GetId() interface{} {
if len(s.Ids) > 0 {
s.Ids = append(s.Ids, s.Id)
return s.Ids
// Generate 结构体数据转化 从 SysDeptControl 至 SysDept 对应的模型
func (s *SysDeptUpdateReq) Generate(model *models.SysDept) {
if s.DeptId != 0 {
model.DeptId = s.DeptId
}
model.DeptName = s.DeptName
model.ParentId = s.ParentId
model.DeptPath = s.DeptPath
model.Sort = s.Sort
model.Leader = s.Leader
model.Phone = s.Phone
model.Email = s.Email
model.Status = s.Status
}
// GetId 获取数据对应的ID
func (s *SysDeptUpdateReq) GetId() interface{} {
return s.DeptId
}
type SysDeptGetReq struct {
Id int `uri:"id"`
}
func (s *SysDeptGetReq) GetId() interface{} {
return s.Id
}
func (s *SysDeptById) GenerateM() (*models.SysDept, error) {
return &models.SysDept{}, nil
type SysDeptDeleteReq struct {
Ids []int `json:"ids"`
}
func (s *SysDeptDeleteReq) GetId() interface{} {
return s.Ids
}
type DeptLabel struct {
+57 -21
View File
@@ -6,7 +6,7 @@ import (
common "go-admin/common/models"
)
type SysDictDataSearch struct {
type SysDictDataGetPageReq struct {
dto.Pagination `search:"-"`
Id int `form:"id" search:"type:exact;column:dict_code;table:sys_dict_data" comment:""`
DictLabel string `form:"dictLabel" search:"type:contains;column:dict_label;table:sys_dict_data" comment:""`
@@ -15,12 +15,17 @@ type SysDictDataSearch struct {
Status string `form:"status" search:"type:exact;column:status;table:sys_dict_data" comment:""`
}
func (m *SysDictDataSearch) GetNeedSearch() interface{} {
func (m *SysDictDataGetPageReq) GetNeedSearch() interface{} {
return *m
}
type SysDictDataControl struct {
Id int `uri:"dictCode" comment:""`
type SysDictDataGetAllResp struct {
DictLabel string `json:"label"`
DictValue string `json:"value"`
}
type SysDictDataInsertReq struct {
Id int `json:"-" comment:""`
DictSort int `json:"dictSort" comment:""`
DictLabel string `json:"dictLabel" comment:""`
DictValue string `json:"dictValue" comment:""`
@@ -28,14 +33,13 @@ type SysDictDataControl struct {
CssClass string `json:"cssClass" comment:""`
ListClass string `json:"listClass" comment:""`
IsDefault string `json:"isDefault" comment:""`
Status int `json:"status" comment:""`
Status int `json:"status" comment:""`
Default string `json:"default" comment:""`
Remark string `json:"remark" comment:""`
common.ControlBy
}
func (s *SysDictDataControl) Generate(model *models.SysDictData) {
func (s *SysDictDataInsertReq) Generate(model *models.SysDictData) {
model.DictCode = s.Id
model.DictSort = s.DictSort
model.DictLabel = s.DictLabel
@@ -49,24 +53,56 @@ func (s *SysDictDataControl) Generate(model *models.SysDictData) {
model.Remark = s.Remark
}
func (s *SysDictDataControl) GetId() interface{} {
func (s *SysDictDataInsertReq) GetId() interface{} {
return s.Id
}
type SysDictDataById struct {
Id int `uri:"dictCode"`
Ids []int `json:"ids"`
type SysDictDataUpdateReq struct {
Id int `uri:"dictCode" comment:""`
DictSort int `json:"dictSort" comment:""`
DictLabel string `json:"dictLabel" comment:""`
DictValue string `json:"dictValue" comment:""`
DictType string `json:"dictType" comment:""`
CssClass string `json:"cssClass" comment:""`
ListClass string `json:"listClass" comment:""`
IsDefault string `json:"isDefault" comment:""`
Status int `json:"status" comment:""`
Default string `json:"default" comment:""`
Remark string `json:"remark" comment:""`
common.ControlBy
}
func (s *SysDictDataUpdateReq) Generate(model *models.SysDictData) {
model.DictCode = s.Id
model.DictSort = s.DictSort
model.DictLabel = s.DictLabel
model.DictValue = s.DictValue
model.DictType = s.DictType
model.CssClass = s.CssClass
model.ListClass = s.ListClass
model.IsDefault = s.IsDefault
model.Status = s.Status
model.Default = s.Default
model.Remark = s.Remark
}
func (s *SysDictDataUpdateReq) GetId() interface{} {
return s.Id
}
type SysDictDataGetReq struct {
Id int `uri:"dictCode"`
}
func (s *SysDictDataGetReq) GetId() interface{} {
return s.Id
}
type SysDictDataDeleteReq struct {
Ids []int `json:"ids"`
common.ControlBy `json:"-"`
}
func (s *SysDictDataById) GetId() interface{} {
if len(s.Ids) > 0 {
s.Ids = append(s.Ids, s.Id)
return s.Ids
}
return s.Id
}
func (s *SysDictDataById) GenerateM() (common.ActiveRecord, error) {
return &models.SysDictData{}, nil
func (s *SysDictDataDeleteReq) GetId() interface{} {
return s.Ids
}
+36 -17
View File
@@ -7,7 +7,7 @@ import (
common "go-admin/common/models"
)
type SysDictTypeSearch struct {
type SysDictTypeGetPageReq struct {
dto.Pagination `search:"-"`
DictId []int `form:"dictId" search:"type:in;column:dict_id;table:sys_dict_type"`
DictName string `form:"dictName" search:"type:icontains;column:dict_name;table:sys_dict_type"`
@@ -19,11 +19,11 @@ type SysDictTypeOrder struct {
DictIdOrder string `search:"type:order;column:dict_id;table:sys_dict_type" form:"dictIdOrder"`
}
func (m *SysDictTypeSearch) GetNeedSearch() interface{} {
func (m *SysDictTypeGetPageReq) GetNeedSearch() interface{} {
return *m
}
type SysDictTypeControl struct {
type SysDictTypeInsertReq struct {
Id int `uri:"id"`
DictName string `json:"dictName"`
DictType string `json:"dictType"`
@@ -32,7 +32,7 @@ type SysDictTypeControl struct {
common.ControlBy
}
func (s *SysDictTypeControl) Generate(model *models.SysDictType) {
func (s *SysDictTypeInsertReq) Generate(model *models.SysDictType) {
if s.Id != 0 {
model.ID = s.Id
}
@@ -43,28 +43,47 @@ func (s *SysDictTypeControl) Generate(model *models.SysDictType) {
}
func (s *SysDictTypeControl) GetId() interface{} {
func (s *SysDictTypeInsertReq) GetId() interface{} {
return s.Id
}
type SysDictTypeById struct {
dto.ObjectById
type SysDictTypeUpdateReq struct {
Id int `uri:"id"`
DictName string `json:"dictName"`
DictType string `json:"dictType"`
Status int `json:"status"`
Remark string `json:"remark"`
common.ControlBy
}
func (s *SysDictTypeById) Generate() dto.Control {
cp := *s
return &cp
func (s *SysDictTypeUpdateReq) Generate(model *models.SysDictType) {
if s.Id != 0 {
model.ID = s.Id
}
model.DictName = s.DictName
model.DictType = s.DictType
model.Status = s.Status
model.Remark = s.Remark
}
func (s *SysDictTypeById) GetId() interface{} {
if len(s.Ids) > 0 {
s.Ids = append(s.Ids, s.Id)
return s.Ids
}
func (s *SysDictTypeUpdateReq) GetId() interface{} {
return s.Id
}
func (s *SysDictTypeById) GenerateM() (common.ActiveRecord, error) {
return &models.SysDictType{}, nil
type SysDictTypeGetReq struct {
Id int `uri:"id"`
}
func (s *SysDictTypeGetReq) GetId() interface{} {
return s.Id
}
type SysDictTypeDeleteReq struct {
Ids []int `json:"ids"`
common.ControlBy
}
func (s *SysDictTypeDeleteReq) GetId() interface{} {
return s.Ids
}
+10 -34
View File
@@ -1,14 +1,12 @@
package dto
import (
"go-admin/app/admin/models"
"time"
"go-admin/common/dto"
common "go-admin/common/models"
)
type SysLoginLogSearch struct {
type SysLoginLogGetPageReq struct {
dto.Pagination `search:"-"`
Username string `form:"username" search:"type:exact;column:username;table:sys_login_log" comment:"用户名"`
Status string `form:"status" search:"type:exact;column:status;table:sys_login_log" comment:"状态"`
@@ -23,7 +21,7 @@ type SysLoginLogOrder struct {
CreatedAtOrder string `search:"type:order;column:created_at;table:sys_login_log" form:"createdAtOrder"`
}
func (m *SysLoginLogSearch) GetNeedSearch() interface{} {
func (m *SysLoginLogGetPageReq) GetNeedSearch() interface{} {
return *m
}
@@ -41,41 +39,19 @@ type SysLoginLogControl struct {
Msg string `json:"msg" comment:"信息"`
}
func (s *SysLoginLogControl) Generate() (*models.SysLoginLog, error) {
return &models.SysLoginLog{
Model: common.Model{Id: s.ID},
Username: s.Username,
Status: s.Status,
Ipaddr: s.Ipaddr,
LoginLocation: s.LoginLocation,
Browser: s.Browser,
Os: s.Os,
Platform: s.Platform,
LoginTime: s.LoginTime,
Remark: s.Remark,
Msg: s.Msg,
}, nil
type SysLoginLogGetReq struct {
Id int `uri:"id"`
}
func (s *SysLoginLogControl) GetId() interface{} {
return s.ID
}
type SysLoginLogById struct {
Id int `uri:"id"`
Ids []int `json:"ids"`
common.ControlBy
}
func (s *SysLoginLogById) GetId() interface{} {
func (s *SysLoginLogGetReq) GetId() interface{} {
return s.Id
}
func (s *SysLoginLogById) Generate() *SysLoginLogById {
cp := *s
return &cp
// SysLoginLogDeleteReq 功能删除请求参数
type SysLoginLogDeleteReq struct {
Ids []int `json:"ids"`
}
func (s *SysLoginLogById) GenerateM() (*models.SysLoginLog, error) {
return &models.SysLoginLog{}, nil
func (s *SysLoginLogDeleteReq) GetId() interface{} {
return s.Ids
}
+72 -36
View File
@@ -7,19 +7,18 @@ import (
"go-admin/common/dto"
)
// SysMenuSearch 列表或者搜索使用结构体
type SysMenuSearch struct {
// SysMenuGetPageReq 列表或者搜索使用结构体
type SysMenuGetPageReq struct {
dto.Pagination `search:"-"`
Title string `form:"title" search:"type:contains;column:title;table:sys_menu" comment:"菜单名称"` // 菜单名称
Visible int `form:"visible" search:"type:exact;column:visible;table:sys_menu" comment:"显示状态"` // 显示状态
}
func (m *SysMenuSearch) GetNeedSearch() interface{} {
func (m *SysMenuGetPageReq) GetNeedSearch() interface{} {
return *m
}
// SysMenuControl 增、改使用的结构体
type SysMenuControl struct {
type SysMenuInsertReq struct {
MenuId int `uri:"id" comment:"编码"` // 编码
MenuName string `form:"menuName" comment:"菜单name"` //菜单name
Title string `form:"title" comment:"显示名称"` //显示名称
@@ -41,16 +40,7 @@ type SysMenuControl struct {
common.ControlBy
}
func (s *SysMenuControl) SetCreateBy(id int) {
s.CreateBy = id
}
func (s *SysMenuControl) SetUpdateBy(id int) {
s.UpdateBy = id
}
// Generate 结构体数据转化 从 Control 至 model 对应的模型
func (s *SysMenuControl) Generate(model *models.SysMenu) {
func (s *SysMenuInsertReq) Generate(model *models.SysMenu) {
if s.MenuId != 0 {
model.MenuId = s.MenuId
}
@@ -78,33 +68,79 @@ func (s *SysMenuControl) Generate(model *models.SysMenu) {
}
}
// GetId 获取数据对应的ID
func (s *SysMenuControl) GetId() interface{} {
func (s *SysMenuInsertReq) GetId() interface{} {
return s.MenuId
}
// SysMenuById 获取单个或者删除的结构体
type SysMenuById struct {
Id int `uri:"id"`
type SysMenuUpdateReq struct {
MenuId int `uri:"id" comment:"编码"` // 编码
MenuName string `form:"menuName" comment:"菜单name"` //菜单name
Title string `form:"title" comment:"显示名称"` //显示名称
Icon string `form:"icon" comment:"图标"` //图标
Path string `form:"path" comment:"路径"` //路径
Paths string `form:"paths" comment:"id路径"` //id路径
MenuType string `form:"menuType" comment:"菜单类型"` //菜单类型
SysApi []models.SysApi `form:"sysApi"`
Apis []int `form:"apis"`
Action string `form:"action" comment:"请求方式"` //请求方式
Permission string `form:"permission" comment:"权限编码"` //权限编码
ParentId int `form:"parentId" comment:"上级菜单"` //上级菜单
NoCache bool `form:"noCache" comment:"是否缓存"` //是否缓存
Breadcrumb string `form:"breadcrumb" comment:"是否面包屑"` //是否面包屑
Component string `form:"component" comment:"组件"` //组件
Sort int `form:"sort" comment:"排序"` //排序
Visible string `form:"visible" comment:"是否显示"` //是否显示
IsFrame string `form:"isFrame" comment:"是否frame"` //是否frame
common.ControlBy
}
func (s *SysMenuUpdateReq) Generate(model *models.SysMenu) {
if s.MenuId != 0 {
model.MenuId = s.MenuId
}
model.MenuName = s.MenuName
model.Title = s.Title
model.Icon = s.Icon
model.Path = s.Path
model.Paths = s.Paths
model.MenuType = s.MenuType
model.Action = s.Action
model.SysApi = s.SysApi
model.Permission = s.Permission
model.ParentId = s.ParentId
model.NoCache = s.NoCache
model.Breadcrumb = s.Breadcrumb
model.Component = s.Component
model.Sort = s.Sort
model.Visible = s.Visible
model.IsFrame = s.IsFrame
if s.CreateBy != 0 {
model.CreateBy = s.CreateBy
}
if s.UpdateBy != 0 {
model.UpdateBy = s.UpdateBy
}
}
func (s *SysMenuUpdateReq) GetId() interface{} {
return s.MenuId
}
type SysMenuGetReq struct {
Id int `uri:"id"`
}
func (s *SysMenuGetReq) GetId() interface{} {
return s.Id
}
type SysMenuDeleteReq struct {
Ids []int `json:"ids"`
common.ControlBy
}
func (s *SysMenuById) Generate() *SysMenuById {
cp := *s
return &cp
}
func (s *SysMenuById) GetId() interface{} {
if len(s.Ids) > 0 {
s.Ids = append(s.Ids, s.Id)
return s.Ids
}
return s.Id
}
func (s *SysMenuById) GenerateM() (*models.SysMenu, error) {
return &models.SysMenu{}, nil
func (s *SysMenuDeleteReq) GetId() interface{} {
return s.Ids
}
type MenuLabel struct {
@@ -120,4 +156,4 @@ type MenuRole struct {
type SelectRole struct {
RoleId int `uri:"roleId"`
}
}
+18 -13
View File
@@ -8,16 +8,21 @@ import (
common "go-admin/common/models"
)
const (
OperaStatusEnabel = "1" // 状态-正常
OperaStatusDisable = "2" // 状态-关闭
)
type SysOperaLogGetPageReq struct {
dto.Pagination `search:"-"`
Title string `form:"title" search:"type:contains;column:title;table:sys_opera_log" comment:"操作模块"`
Method string `form:"method" search:"type:contains;column:method;table:sys_opera_log" comment:"函数"`
RequestMethod string `form:"requestMethod" search:"type:contains;column:request_method;table:sys_opera_log" comment:"请求方式"`
RequestMethod string `form:"requestMethod" search:"type:contains;column:request_method;table:sys_opera_log" comment:"请求方式: GET POST PUT DELETE"`
OperUrl string `form:"operUrl" search:"type:contains;column:oper_url;table:sys_opera_log" comment:"访问地址"`
OperIp string `form:"operIp" search:"type:exact;column:oper_ip;table:sys_opera_log" comment:"客户端ip"`
Status int `form:"status" search:"type:exact;column:status;table:sys_opera_log" comment:"状态"`
BeginTime string `form:"beginTime" search:"type:gte;column:ctime;table:sys_opera_log" comment:"创建时间"`
EndTime string `form:"endTime" search:"type:lte;column:ctime;table:sys_opera_log" comment:"创建时间"`
Status int `form:"status" search:"type:exact;column:status;table:sys_opera_log" comment:"状态 1:正常 2:关闭"`
BeginTime string `form:"beginTime" search:"type:gte;column:created_at;table:sys_opera_log" comment:"创建时间"`
EndTime string `form:"endTime" search:"type:lte;column:created_at;table:sys_opera_log" comment:"更新时间"`
SysOperaLogOrder
}
@@ -79,19 +84,19 @@ func (s *SysOperaLogControl) GetId() interface{} {
return s.ID
}
type SysOperaLogById struct {
Id int `uri:"id"`
Ids []int `json:"ids"`
type SysOperaLogGetReq struct {
Id int `uri:"id"`
}
func (s *SysOperaLogById) GetId() interface{} {
if len(s.Ids) > 0 {
s.Ids = append(s.Ids, s.Id)
return s.Ids
}
func (s *SysOperaLogGetReq) GetId() interface{} {
return s.Id
}
func (s *SysOperaLogById) SetUpdateBy(id int) {
// SysOperaLogDeleteReq 功能删除请求参数
type SysOperaLogDeleteReq struct {
Ids []int `json:"ids"`
}
func (s *SysOperaLogDeleteReq) GetId() interface{} {
return s.Ids
}
+52 -33
View File
@@ -7,8 +7,7 @@ import (
"go-admin/common/dto"
)
// SysRoleSearch 列表或者搜索使用结构体
type SysRoleSearch struct {
type SysRoleGetPageReq struct {
dto.Pagination `search:"-"`
RoleId int `form:"roleId" search:"type:exact;column:role_id;table:sys_role" comment:"角色编码"` // 角色编码
@@ -30,11 +29,48 @@ type SysRoleOrder struct {
CreatedAtOrder string `search:"type:order;column:created_at;table:sys_role" form:"createdAtOrder"`
}
func (m *SysRoleSearch) GetNeedSearch() interface{} {
func (m *SysRoleGetPageReq) GetNeedSearch() interface{} {
return *m
}
type SysRoleControl struct {
type SysRoleInsertReq struct {
RoleId int `uri:"id" comment:"角色编码"` // 角色编码
RoleName string `form:"roleName" comment:"角色名称"` // 角色名称
Status string `form:"status" comment:"状态"` // 状态 1禁用 2正常
RoleKey string `form:"roleKey" comment:"角色代码"` // 角色代码
RoleSort int `form:"roleSort" comment:"角色排序"` // 角色排序
Flag string `form:"flag" comment:"标记"` // 标记
Remark string `form:"remark" comment:"备注"` // 备注
Admin bool `form:"admin" comment:"是否管理员"`
DataScope string `form:"dataScope"`
SysMenu []models.SysMenu `form:"sysMenu"`
MenuIds []int `form:"menuIds"`
SysDept []models.SysDept `form:"sysDept"`
DeptIds []int `form:"deptIds"`
common.ControlBy
}
func (s *SysRoleInsertReq) Generate(model *models.SysRole) {
if s.RoleId != 0 {
model.RoleId = s.RoleId
}
model.RoleName = s.RoleName
model.Status = s.Status
model.RoleKey = s.RoleKey
model.RoleSort = s.RoleSort
model.Flag = s.Flag
model.Remark = s.Remark
model.Admin = s.Admin
model.DataScope = s.DataScope
model.SysMenu = &s.SysMenu
model.SysDept = s.SysDept
}
func (s *SysRoleInsertReq) GetId() interface{} {
return s.RoleId
}
type SysRoleUpdateReq struct {
RoleId int `uri:"id" comment:"角色编码"` // 角色编码
RoleName string `form:"roleName" comment:"角色名称"` // 角色名称
Status string `form:"status" comment:"状态"` // 状态
@@ -51,16 +87,7 @@ type SysRoleControl struct {
common.ControlBy
}
func (s *SysRoleControl) SetCreateBy(id int) {
s.CreateBy = id
}
func (s *SysRoleControl) SetUpdateBy(id int) {
s.UpdateBy = id
}
// Generate 结构体数据转化
func (s *SysRoleControl) Generate(model *models.SysRole) {
func (s *SysRoleUpdateReq) Generate(model *models.SysRole) {
if s.RoleId != 0 {
model.RoleId = s.RoleId
}
@@ -74,11 +101,9 @@ func (s *SysRoleControl) Generate(model *models.SysRole) {
model.DataScope = s.DataScope
model.SysMenu = &s.SysMenu
model.SysDept = s.SysDept
}
// GetId 获取数据对应的ID
func (s *SysRoleControl) GetId() interface{} {
func (s *SysRoleUpdateReq) GetId() interface{} {
return s.RoleId
}
@@ -103,26 +128,20 @@ type SysRoleByName struct {
RoleName string `form:"role"` // 角色编码
}
// SysRoleById 获取单个或者删除的结构体
type SysRoleById struct {
dto.ObjectById
type SysRoleGetReq struct {
Id int `uri:"id"`
}
func (s *SysRoleById) Generate() *SysRoleById {
cp := *s
return &cp
}
func (s *SysRoleById) GetId() interface{} {
if len(s.Ids) > 0 {
s.Ids = append(s.Ids, s.Id)
return s.Ids
}
func (s *SysRoleGetReq) GetId() interface{} {
return s.Id
}
func (s *SysRoleById) GenerateM() (*models.SysRole, error) {
return &models.SysRole{}, nil
type SysRoleDeleteReq struct {
Ids []int `json:"ids"`
}
func (s *SysRoleDeleteReq) GetId() interface{} {
return s.Ids
}
// RoleDataScopeReq 角色数据权限修改
@@ -142,4 +161,4 @@ func (s *RoleDataScopeReq) Generate(model *models.SysRole) {
type DeptIdList struct {
DeptId int `json:"DeptId"`
}
}
+55 -17
View File
@@ -38,8 +38,8 @@ func (m *SysUserGetPageReq) GetNeedSearch() interface{} {
}
type ResetSysUserPwdReq struct {
UserId int `json:"userId" comment:"用户ID" binding:"required"` // 用户ID
Password string `json:"password" comment:"密码" binding:"required"`
UserId int `json:"userId" comment:"用户ID" vd:"$>0"` // 用户ID
Password string `json:"password" comment:"密码" vd:"len($)>0"`
common.ControlBy
}
@@ -55,8 +55,8 @@ func (s *ResetSysUserPwdReq) Generate(model *models.SysUser) {
}
type UpdateSysUserAvatarReq struct {
UserId int `json:"userId" comment:"用户ID" vd:"required"` // 用户ID
Avatar string `json:"avatar" comment:"头像" vd:"required"`
UserId int `json:"userId" comment:"用户ID" vd:"len($)>0"` // 用户ID
Avatar string `json:"avatar" comment:"头像" vd:"len($)>0"`
common.ControlBy
}
@@ -72,8 +72,8 @@ func (s *UpdateSysUserAvatarReq) Generate(model *models.SysUser) {
}
type UpdateSysUserStatusReq struct {
UserId int `json:"userId" comment:"用户ID" binding:"required"` // 用户ID
Status string `json:"status" comment:"状态" binding:"required"`
UserId int `json:"userId" comment:"用户ID" vd:"$>0"` // 用户ID
Status string `json:"status" comment:"状态" vd:"len($)>0"`
common.ControlBy
}
@@ -88,24 +88,24 @@ func (s *UpdateSysUserStatusReq) Generate(model *models.SysUser) {
model.Status = s.Status
}
type SysUserControl struct {
type SysUserInsertReq struct {
UserId int `json:"userId" comment:"用户ID"` // 用户ID
Username string `json:"username" comment:"用户名" binding:"required"`
Username string `json:"username" comment:"用户名" vd:"len($)>0"`
Password string `json:"password" comment:"密码"`
NickName string `json:"nickName" comment:"昵称" binding:"required"`
Phone string `json:"phone" comment:"手机号" binding:"required"`
NickName string `json:"nickName" comment:"昵称" vd:"len($)>0"`
Phone string `json:"phone" comment:"手机号" vd:"len($)>0"`
RoleId int `json:"roleId" comment:"角色ID"`
Avatar string `json:"avatar" comment:"头像"`
Sex string `json:"sex" comment:"性别"`
Email string `json:"email" comment:"邮箱" binding:"required,email"`
DeptId int `json:"deptId" comment:"部门" binding:"required"`
Email string `json:"email" comment:"邮箱" vd:"len($)>0,email"`
DeptId int `json:"deptId" comment:"部门" vd:"$>0"`
PostId int `json:"postId" comment:"岗位"`
Remark string `json:"remark" comment:"备注"`
Status string `json:"status" comment:"状态" binding:"required" default:"1"`
Status string `json:"status" comment:"状态" vd:"len($)>0" default:"1"`
common.ControlBy
}
func (s *SysUserControl) Generate(model *models.SysUser) {
func (s *SysUserInsertReq) Generate(model *models.SysUser) {
if s.UserId != 0 {
model.UserId = s.UserId
}
@@ -121,9 +121,47 @@ func (s *SysUserControl) Generate(model *models.SysUser) {
model.PostId = s.PostId
model.Remark = s.Remark
model.Status = s.Status
model.CreateBy = s.CreateBy
}
func (s *SysUserControl) GetId() interface{} {
func (s *SysUserInsertReq) GetId() interface{} {
return s.UserId
}
type SysUserUpdateReq struct {
UserId int `json:"userId" comment:"用户ID"` // 用户ID
Username string `json:"username" comment:"用户名" vd:"len($)>0"`
NickName string `json:"nickName" comment:"昵称" vd:"len($)>0"`
Phone string `json:"phone" comment:"手机号" vd:"len($)>0"`
RoleId int `json:"roleId" comment:"角色ID"`
Avatar string `json:"avatar" comment:"头像"`
Sex string `json:"sex" comment:"性别"`
Email string `json:"email" comment:"邮箱" vd:"len($)>0,email"`
DeptId int `json:"deptId" comment:"部门" vd:"$>0"`
PostId int `json:"postId" comment:"岗位"`
Remark string `json:"remark" comment:"备注"`
Status string `json:"status" comment:"状态" default:"1"`
common.ControlBy
}
func (s *SysUserUpdateReq) Generate(model *models.SysUser) {
if s.UserId != 0 {
model.UserId = s.UserId
}
model.Username = s.Username
model.NickName = s.NickName
model.Phone = s.Phone
model.RoleId = s.RoleId
model.Avatar = s.Avatar
model.Sex = s.Sex
model.Email = s.Email
model.DeptId = s.DeptId
model.PostId = s.PostId
model.Remark = s.Remark
model.Status = s.Status
}
func (s *SysUserUpdateReq) GetId() interface{} {
return s.UserId
}
@@ -146,6 +184,6 @@ func (s *SysUserById) GenerateM() (common.ActiveRecord, error) {
// PassWord 密码
type PassWord struct {
NewPassword string `json:"newPassword" binding:"required"`
OldPassword string `json:"oldPassword" binding:"required"`
NewPassword string `json:"newPassword" vd:"len($)>0"`
OldPassword string `json:"oldPassword" vd:"len($)>0"`
}
+22 -11
View File
@@ -6,12 +6,11 @@ import (
"github.com/go-admin-team/go-admin-core/sdk/runtime"
"github.com/go-admin-team/go-admin-core/sdk/service"
"gorm.io/gorm"
"go-admin/app/admin/models"
"go-admin/app/admin/service/dto"
"go-admin/common/actions"
cDto "go-admin/common/dto"
"go-admin/common/global"
)
type SysApi struct {
@@ -23,13 +22,25 @@ func (e *SysApi) GetPage(c *dto.SysApiGetPageReq, p *actions.DataPermission, lis
var err error
var data models.SysApi
err = e.Orm.Debug().Model(&data).
orm := e.Orm.Debug().Model(&data).
Scopes(
cDto.MakeCondition(c.GetNeedSearch()),
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
actions.Permission(data.TableName(), p),
).
Find(list).Limit(-1).Offset(-1).
)
if c.Type != "" {
qType := c.Type
if qType == "暂无" {
qType = ""
}
if global.Driver == "postgres" {
orm = orm.Where("type = ?", qType)
} else {
orm = orm.Where("`type` = ?", qType)
}
}
err = orm.Find(list).Limit(-1).Offset(-1).
Count(count).Error
if err != nil {
e.Log.Errorf("Service GetSysApiPage error:%s", err)
@@ -45,15 +56,15 @@ func (e *SysApi) Get(d *dto.SysApiGetReq, p *actions.DataPermission, model *mode
Scopes(
actions.Permission(data.TableName(), p),
).
First(model, d.GetId()).Error
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
err = errors.New("查看对象不存在或无权查看")
e.Log.Errorf("Service GetSysApi error:%s", err)
FirstOrInit(model, d.GetId()).Error
if err != nil {
e.Log.Errorf("db error:%s", err)
_ = e.AddError(err)
return e
}
if err != nil {
e.Log.Errorf("db error:%s", err)
if model.Id == 0 {
err = errors.New("查看对象不存在或无权查看")
e.Log.Errorf("Service GetSysApi error: %s", err)
_ = e.AddError(err)
return e
}
+16 -15
View File
@@ -8,7 +8,6 @@ import (
cDto "go-admin/common/dto"
"github.com/go-admin-team/go-admin-core/sdk/service"
"gorm.io/gorm"
)
type SysConfig struct {
@@ -16,7 +15,7 @@ type SysConfig struct {
}
// GetPage 获取SysConfig列表
func (e *SysConfig) GetPage(c *dto.SysConfigSearch, list *[]models.SysConfig, count *int64) error {
func (e *SysConfig) GetPage(c *dto.SysConfigGetPageReq, list *[]models.SysConfig, count *int64) error {
err := e.Orm.
Scopes(
cDto.MakeCondition(c.GetNeedSearch()),
@@ -32,15 +31,19 @@ func (e *SysConfig) GetPage(c *dto.SysConfigSearch, list *[]models.SysConfig, co
}
// Get 获取SysConfig对象
func (e *SysConfig) Get(d *dto.SysConfigById, model *models.SysConfig) error {
err := e.Orm.First(model, d.GetId()).Error
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
err = errors.New("查看对象不存在或无权查看")
e.Log.Errorf("Service GetSysConfigPage error:%s", err)
func (e *SysConfig) Get(d *dto.SysConfigGetReq, model *models.SysConfig) error {
err := e.Orm.
FirstOrInit(model, d.GetId()).
Error
if err != nil {
e.Log.Errorf("db error:%s", err)
_ = e.AddError(err)
return err
}
if err != nil {
e.Log.Errorf("Service GetSysConfig error:%s", err)
if model.Id == 0 {
err = errors.New("查看对象不存在或无权查看")
e.Log.Errorf("Service GetSysApi error: %s", err)
_ = e.AddError(err)
return err
}
return nil
@@ -137,13 +140,12 @@ func (e *SysConfig) UpdateForSet(c *[]dto.GetSetSysConfigReq) error {
}
// Remove 删除SysConfig
func (e *SysConfig) Remove(d *dto.SysConfigById) error {
func (e *SysConfig) Remove(d *dto.SysConfigDeleteReq) error {
var err error
var data models.SysConfig
db := e.Orm.Delete(&data, d.Ids)
if db.Error != nil {
err = db.Error
if err = db.Error; err != nil {
e.Log.Errorf("Service RemoveSysConfig error:%s", err)
return err
}
@@ -167,9 +169,8 @@ func (e *SysConfig) GetWithKey(c *dto.SysConfigByKeyReq, resp *dto.GetSysConfigB
return nil
}
func (e *SysConfig) GetWithKeyList(c *dto.SysConfigSearch, list *[]models.SysConfig) error {
var err error
err = e.Orm.
func (e *SysConfig) GetWithKeyList(c *dto.SysConfigGetToSysAppReq, list *[]models.SysConfig) error {
err := e.Orm.
Scopes(
cDto.MakeCondition(c.GetNeedSearch()),
).
+43 -44
View File
@@ -7,8 +7,6 @@ import (
log "github.com/go-admin-team/go-admin-core/logger"
"github.com/go-admin-team/go-admin-core/sdk/pkg"
"gorm.io/gorm"
"go-admin/app/admin/service/dto"
cDto "go-admin/common/dto"
@@ -20,44 +18,46 @@ type SysDept struct {
}
// GetPage 获取SysDept列表
func (e *SysDept) GetPage(c *dto.SysDeptSearch, list *[]models.SysDept) error {
//func (e *SysDept) GetPage(c *dto.SysDeptGetPageReq, list *[]models.SysDept) error {
// var err error
// var data models.SysDept
//
// err = e.Orm.Model(&data).
// Scopes(
// cDto.MakeCondition(c.GetNeedSearch()),
// ).
// Find(list).Error
// if err != nil {
// e.Log.Errorf("db error:%s", err)
// return err
// }
// return nil
//}
// Get 获取SysDept对象
func (e *SysDept) Get(d *dto.SysDeptGetReq, model *models.SysDept) error {
var err error
var data models.SysDept
err = e.Orm.Model(&data).
Scopes(
cDto.MakeCondition(c.GetNeedSearch()),
).
Find(list).Error
FirstOrInit(model, d.GetId()).
Error
if err != nil {
e.Log.Errorf("db error:%s", err)
_ = e.AddError(err)
return err
}
return nil
}
// Get 获取SysDept对象
func (e *SysDept) Get(d *dto.SysDeptById, model *models.SysDept) error {
var err error
var data models.SysDept
db := e.Orm.Model(&data).
First(model, d.GetId())
err = db.Error
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
if model.DeptId == 0 {
err = errors.New("查看对象不存在或无权查看")
e.Log.Errorf("db error:%s", err)
return err
}
if db.Error != nil {
e.Log.Errorf("db error:%s", err)
e.Log.Errorf("Service GetSysApi error: %s", err)
_ = e.AddError(err)
return err
}
return nil
}
// Insert 创建SysDept对象
func (e *SysDept) Insert(c *dto.SysDeptControl) error {
func (e *SysDept) Insert(c *dto.SysDeptInsertReq) error {
var err error
var data models.SysDept
c.Generate(&data)
@@ -84,7 +84,7 @@ func (e *SysDept) Insert(c *dto.SysDeptControl) error {
}
var mp = map[string]string{}
mp["dept_path"] = deptPath
if err := tx.Model(&data).Update("dept_path", deptPath).Error; err != nil {
if err = tx.Model(&data).Update("dept_path", deptPath).Error; err != nil {
e.Log.Errorf("db error:%s", err)
return err
}
@@ -92,7 +92,7 @@ func (e *SysDept) Insert(c *dto.SysDeptControl) error {
}
// Update 修改SysDept对象
func (e *SysDept) Update(c *dto.SysDeptControl) error {
func (e *SysDept) Update(c *dto.SysDeptUpdateReq) error {
var err error
var model = models.SysDept{}
tx := e.Orm.Debug().Begin()
@@ -116,7 +116,7 @@ func (e *SysDept) Update(c *dto.SysDeptControl) error {
}
model.DeptPath = deptPath
db := tx.Save(&model)
if db.Error != nil {
if err = db.Error; err != nil {
e.Log.Errorf("UpdateSysDept error:%s", err)
return err
}
@@ -127,13 +127,12 @@ func (e *SysDept) Update(c *dto.SysDeptControl) error {
}
// Remove 删除SysDept
func (e *SysDept) Remove(d *dto.SysDeptById) error {
func (e *SysDept) Remove(d *dto.SysDeptDeleteReq) error {
var err error
var data models.SysDept
db := e.Orm.Model(&data).Delete(&data, d.GetId())
if db.Error != nil {
err = db.Error
if err = db.Error; err != nil {
e.Log.Errorf("Delete error: %s", err)
return err
}
@@ -145,7 +144,7 @@ func (e *SysDept) Remove(d *dto.SysDeptById) error {
}
// GetSysDeptList 获取组织数据
func (e *SysDept) getList(c *dto.SysDeptSearch, list *[]models.SysDept) error {
func (e *SysDept) getList(c *dto.SysDeptGetPageReq, list *[]models.SysDept) error {
var err error
var data models.SysDept
@@ -162,7 +161,7 @@ func (e *SysDept) getList(c *dto.SysDeptSearch, list *[]models.SysDept) error {
}
// SetDeptTree 设置组织数据
func (e *SysDept) SetDeptTree(c *dto.SysDeptSearch) (m []dto.DeptLabel, err error) {
func (e *SysDept) SetDeptTree(c *dto.SysDeptGetPageReq) (m []dto.DeptLabel, err error) {
var list []models.SysDept
err = e.getList(c, &list)
@@ -184,21 +183,21 @@ func (e *SysDept) SetDeptTree(c *dto.SysDeptSearch) (m []dto.DeptLabel, err erro
// Call 递归构造组织数据
func deptTreeCall(deptList *[]models.SysDept, dept dto.DeptLabel) dto.DeptLabel {
list := *deptList
min := make([]dto.DeptLabel, 0)
childrenList := make([]dto.DeptLabel, 0)
for j := 0; j < len(list); j++ {
if dept.Id != list[j].ParentId {
continue
}
mi := dto.DeptLabel{Id: list[j].DeptId, Label: list[j].DeptName, Children: []dto.DeptLabel{}}
ms := deptTreeCall(deptList, mi)
min = append(min, ms)
childrenList = append(childrenList, ms)
}
dept.Children = min
dept.Children = childrenList
return dept
}
// SetDeptPage 设置dept页面数据
func (e *SysDept) SetDeptPage(c *dto.SysDeptSearch) (m []models.SysDept, err error) {
func (e *SysDept) SetDeptPage(c *dto.SysDeptGetPageReq) (m []models.SysDept, err error) {
var list []models.SysDept
err = e.getList(c, &list)
for i := 0; i < len(list); i++ {
@@ -213,7 +212,7 @@ func (e *SysDept) SetDeptPage(c *dto.SysDeptSearch) (m []models.SysDept, err err
func (e *SysDept) deptPageCall(deptlist *[]models.SysDept, menu models.SysDept) models.SysDept {
list := *deptlist
min := make([]models.SysDept, 0)
childrenList := make([]models.SysDept, 0)
for j := 0; j < len(list); j++ {
if menu.DeptId != list[j].ParentId {
continue
@@ -231,13 +230,13 @@ func (e *SysDept) deptPageCall(deptlist *[]models.SysDept, menu models.SysDept)
mi.CreatedAt = list[j].CreatedAt
mi.Children = []models.SysDept{}
ms := e.deptPageCall(deptlist, mi)
min = append(min, ms)
childrenList = append(childrenList, ms)
}
menu.Children = min
menu.Children = childrenList
return menu
}
// GetRoleDeptId 获取角色的部门ID集合
// GetWithRoleId 获取角色的部门ID集合
func (e *SysDept) GetWithRoleId(roleId int) ([]int, error) {
deptIds := make([]int, 0)
deptList := make([]dto.DeptIdList, 0)
@@ -281,15 +280,15 @@ func (e *SysDept) SetDeptLabel() (m []dto.DeptLabel, err error) {
func deptLabelCall(deptList *[]models.SysDept, dept dto.DeptLabel) dto.DeptLabel {
list := *deptList
var mi dto.DeptLabel
min := make([]dto.DeptLabel, 0)
childrenList := make([]dto.DeptLabel, 0)
for j := 0; j < len(list); j++ {
if dept.Id != list[j].ParentId {
continue
}
mi = dto.DeptLabel{Id: list[j].DeptId, Label: list[j].DeptName, Children: []dto.DeptLabel{}}
ms := deptLabelCall(deptList, mi)
min = append(min, ms)
childrenList = append(childrenList, ms)
}
dept.Children = min
dept.Children = childrenList
return dept
}
+8 -9
View File
@@ -16,7 +16,7 @@ type SysDictData struct {
}
// GetPage 获取列表
func (e *SysDictData) GetPage(c *dto.SysDictDataSearch, list *[]models.SysDictData, count *int64) error {
func (e *SysDictData) GetPage(c *dto.SysDictDataGetPageReq, list *[]models.SysDictData, count *int64) error {
var err error
var data models.SysDictData
@@ -35,7 +35,7 @@ func (e *SysDictData) GetPage(c *dto.SysDictDataSearch, list *[]models.SysDictDa
}
// Get 获取对象
func (e *SysDictData) Get(d *dto.SysDictDataById, model *models.SysDictData) error {
func (e *SysDictData) Get(d *dto.SysDictDataGetReq, model *models.SysDictData) error {
var err error
var data models.SysDictData
@@ -47,7 +47,7 @@ func (e *SysDictData) Get(d *dto.SysDictDataById, model *models.SysDictData) err
e.Log.Errorf("db error: %s", err)
return err
}
if db.Error != nil {
if err = db.Error; err != nil {
e.Log.Errorf("db error: %s", err)
return err
}
@@ -55,7 +55,7 @@ func (e *SysDictData) Get(d *dto.SysDictDataById, model *models.SysDictData) err
}
// Insert 创建对象
func (e *SysDictData) Insert(c *dto.SysDictDataControl) error {
func (e *SysDictData) Insert(c *dto.SysDictDataInsertReq) error {
var err error
var data = new(models.SysDictData)
c.Generate(data)
@@ -68,7 +68,7 @@ func (e *SysDictData) Insert(c *dto.SysDictDataControl) error {
}
// Update 修改对象
func (e *SysDictData) Update(c *dto.SysDictDataControl) error {
func (e *SysDictData) Update(c *dto.SysDictDataUpdateReq) error {
var err error
var model = models.SysDictData{}
e.Orm.First(&model, c.GetId())
@@ -86,13 +86,12 @@ func (e *SysDictData) Update(c *dto.SysDictDataControl) error {
}
// Remove 删除
func (e *SysDictData) Remove(c *dto.SysDictDataById) error {
func (e *SysDictData) Remove(c *dto.SysDictDataDeleteReq) error {
var err error
var data models.SysDictData
db := e.Orm.Delete(&data, c.GetId())
if db.Error != nil {
err = db.Error
if err = db.Error; err != nil {
e.Log.Errorf("Delete error: %s", err)
return err
}
@@ -104,7 +103,7 @@ func (e *SysDictData) Remove(c *dto.SysDictDataById) error {
}
// GetAll 获取所有
func (e *SysDictData) GetAll(c *dto.SysDictDataSearch, list *[]models.SysDictData) error {
func (e *SysDictData) GetAll(c *dto.SysDictDataGetPageReq, list *[]models.SysDictData) error {
var err error
var data models.SysDictData
+17 -12
View File
@@ -3,6 +3,7 @@ package service
import (
"errors"
"fmt"
"github.com/go-admin-team/go-admin-core/sdk/service"
"gorm.io/gorm"
@@ -16,7 +17,7 @@ type SysDictType struct {
}
// GetPage 获取列表
func (e *SysDictType) GetPage(c *dto.SysDictTypeSearch, list *[]models.SysDictType, count *int64) error {
func (e *SysDictType) GetPage(c *dto.SysDictTypeGetPageReq, list *[]models.SysDictType, count *int64) error {
var err error
var data models.SysDictType
@@ -35,7 +36,7 @@ func (e *SysDictType) GetPage(c *dto.SysDictTypeSearch, list *[]models.SysDictTy
}
// Get 获取对象
func (e *SysDictType) Get(d *dto.SysDictTypeById, model *models.SysDictType) error {
func (e *SysDictType) Get(d *dto.SysDictTypeGetReq, model *models.SysDictType) error {
var err error
db := e.Orm.First(model, d.GetId())
@@ -45,7 +46,7 @@ func (e *SysDictType) Get(d *dto.SysDictTypeById, model *models.SysDictType) err
e.Log.Errorf("db error: %s", err)
return err
}
if db.Error != nil {
if err = db.Error; err != nil {
e.Log.Errorf("db error: %s", err)
return err
}
@@ -53,14 +54,19 @@ func (e *SysDictType) Get(d *dto.SysDictTypeById, model *models.SysDictType) err
}
// Insert 创建对象
func (e *SysDictType) Insert(c *dto.SysDictTypeControl) error {
func (e *SysDictType) Insert(c *dto.SysDictTypeInsertReq) error {
var err error
var data models.SysDictType
c.Generate(&data)
var count int64
e.Orm.Model(&data).Where("dict_type = ?", data.DictType).Count(&count)
// The error was dropped, so a query that failed left count at zero and the
// insert went ahead as though the name were free.
if err = e.Orm.Model(&data).Where("dict_type = ?", data.DictType).Count(&count).Error; err != nil {
e.Log.Errorf("db error: %s", err)
return err
}
if count > 0 {
return errors.New(fmt.Sprintf("当前字典类型[%s]已经存在!", data.DictType))
return fmt.Errorf("当前字典类型[%s]已经存在!", data.DictType)
}
err = e.Orm.Create(&data).Error
if err != nil {
@@ -71,13 +77,13 @@ func (e *SysDictType) Insert(c *dto.SysDictTypeControl) error {
}
// Update 修改对象
func (e *SysDictType) Update(c *dto.SysDictTypeControl) error {
func (e *SysDictType) Update(c *dto.SysDictTypeUpdateReq) error {
var err error
var model = models.SysDictType{}
e.Orm.First(&model, c.GetId())
c.Generate(&model)
db := e.Orm.Save(&model)
if db.Error != nil {
if err = db.Error; err != nil {
e.Log.Errorf("db error: %s", err)
return err
}
@@ -89,13 +95,12 @@ func (e *SysDictType) Update(c *dto.SysDictTypeControl) error {
}
// Remove 删除
func (e *SysDictType) Remove(d *dto.SysDictTypeById) error {
func (e *SysDictType) Remove(d *dto.SysDictTypeDeleteReq) error {
var err error
var data models.SysDictType
db := e.Orm.Delete(&data, d.GetId())
if db.Error != nil {
err = db.Error
if err = db.Error; err != nil {
e.Log.Errorf("Delete error: %s", err)
return err
}
@@ -107,7 +112,7 @@ func (e *SysDictType) Remove(d *dto.SysDictTypeById) error {
}
// GetAll 获取所有
func (e *SysDictType) GetAll(c *dto.SysDictTypeSearch, list *[]models.SysDictType) error {
func (e *SysDictType) GetAll(c *dto.SysDictTypeGetPageReq, list *[]models.SysDictType) error {
var err error
var data models.SysDictType
+7 -8
View File
@@ -15,8 +15,8 @@ type SysLoginLog struct {
service.Service
}
// GetSysLoginLogPage 获取SysLoginLog列表
func (e *SysLoginLog) GetPage(c *dto.SysLoginLogSearch, list *[]models.SysLoginLog, count *int64) error {
// GetPage 获取SysLoginLog列表
func (e *SysLoginLog) GetPage(c *dto.SysLoginLogGetPageReq, list *[]models.SysLoginLog, count *int64) error {
var err error
var data models.SysLoginLog
@@ -34,8 +34,8 @@ func (e *SysLoginLog) GetPage(c *dto.SysLoginLogSearch, list *[]models.SysLoginL
return nil
}
// GetSysLoginLog 获取SysLoginLog对象
func (e *SysLoginLog) Get(d *dto.SysLoginLogById, model *models.SysLoginLog) error {
// Get 获取SysLoginLog对象
func (e *SysLoginLog) Get(d *dto.SysLoginLogGetReq, model *models.SysLoginLog) error {
var err error
db := e.Orm.First(model, d.GetId())
err = db.Error
@@ -44,7 +44,7 @@ func (e *SysLoginLog) Get(d *dto.SysLoginLogById, model *models.SysLoginLog) err
e.Log.Errorf("db error:%s", err)
return err
}
if db.Error != nil {
if err = db.Error; err != nil {
e.Log.Errorf("db error:%s", err)
return err
}
@@ -52,13 +52,12 @@ func (e *SysLoginLog) Get(d *dto.SysLoginLogById, model *models.SysLoginLog) err
}
// Remove 删除SysLoginLog
func (e *SysLoginLog) Remove(c *dto.SysLoginLogById) error {
func (e *SysLoginLog) Remove(c *dto.SysLoginLogDeleteReq) error {
var err error
var data models.SysLoginLog
db := e.Orm.Delete(&data, c.GetId())
if db.Error != nil {
err = db.Error
if err = db.Error; err != nil {
e.Log.Errorf("Delete error: %s", err)
return err
}
+107 -28
View File
@@ -1,9 +1,12 @@
package service
import (
"errors"
"fmt"
"sort"
"strings"
"github.com/go-admin-team/go-admin-core/sdk/pkg"
"github.com/pkg/errors"
"gorm.io/gorm"
"go-admin/app/admin/models"
@@ -19,7 +22,7 @@ type SysMenu struct {
}
// GetPage 获取SysMenu列表
func (e *SysMenu) GetPage(c *dto.SysMenuSearch, menus *[]models.SysMenu) *SysMenu {
func (e *SysMenu) GetPage(c *dto.SysMenuGetPageReq, menus *[]models.SysMenu) *SysMenu {
var menu = make([]models.SysMenu, 0)
err := e.getPage(c, &menu).Error
if err != nil {
@@ -37,7 +40,7 @@ func (e *SysMenu) GetPage(c *dto.SysMenuSearch, menus *[]models.SysMenu) *SysMen
}
// getPage 菜单分页列表
func (e *SysMenu) getPage(c *dto.SysMenuSearch, list *[]models.SysMenu) *SysMenu {
func (e *SysMenu) getPage(c *dto.SysMenuGetPageReq, list *[]models.SysMenu) *SysMenu {
var err error
var data models.SysMenu
@@ -56,7 +59,7 @@ func (e *SysMenu) getPage(c *dto.SysMenuSearch, list *[]models.SysMenu) *SysMenu
}
// Get 获取SysMenu对象
func (e *SysMenu) Get(d *dto.SysMenuById, model *models.SysMenu) *SysMenu {
func (e *SysMenu) Get(d *dto.SysMenuGetReq, model *models.SysMenu) *SysMenu {
var err error
var data models.SysMenu
@@ -83,25 +86,50 @@ func (e *SysMenu) Get(d *dto.SysMenuById, model *models.SysMenu) *SysMenu {
}
// Insert 创建SysMenu对象
func (e *SysMenu) Insert(c *dto.SysMenuControl) *SysMenu {
func (e *SysMenu) Insert(c *dto.SysMenuInsertReq) *SysMenu {
var err error
var data models.SysMenu
c.Generate(&data)
err = e.Orm.Create(&data).Error
tx := e.Orm.Debug().Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
err = tx.Where("id in ?", c.Apis).Find(&data.SysApi).Error
if err != nil {
tx.Rollback()
e.Log.Errorf("db error:%s", err)
_ = e.AddError(err)
}
err = tx.Create(&data).Error
if err != nil {
tx.Rollback()
e.Log.Errorf("db error:%s", err)
_ = e.AddError(err)
}
c.MenuId = data.MenuId
err = e.initPaths(tx, &data)
if err != nil {
tx.Rollback()
e.Log.Errorf("db error:%s", err)
_ = e.AddError(err)
}
tx.Commit()
return e
}
func (e *SysMenu) initPaths(menu *models.SysMenu) error {
func (e *SysMenu) initPaths(tx *gorm.DB, menu *models.SysMenu) error {
var err error
var data models.SysMenu
parentMenu := new(models.SysMenu)
if menu.ParentId != 0 {
e.Orm.Model(&data).First(parentMenu, menu.ParentId)
err = tx.Model(&data).First(parentMenu, menu.ParentId).Error
if err != nil {
return err
}
if parentMenu.Paths == "" {
err = errors.New("父级paths异常,请尝试对当前节点父级菜单进行更新操作!")
return err
@@ -110,12 +138,12 @@ func (e *SysMenu) initPaths(menu *models.SysMenu) error {
} else {
menu.Paths = "/0/" + pkg.IntToString(menu.MenuId)
}
e.Orm.Model(&data).Where("menu_id = ?", menu.MenuId).Update("paths", menu.Paths)
err = tx.Model(&data).Where("menu_id = ?", menu.MenuId).Update("paths", menu.Paths).Error
return err
}
// Update 修改SysMenu对象
func (e *SysMenu) Update(c *dto.SysMenuControl) *SysMenu {
func (e *SysMenu) Update(c *dto.SysMenuUpdateReq) *SysMenu {
var err error
tx := e.Orm.Debug().Begin()
defer func() {
@@ -128,6 +156,7 @@ func (e *SysMenu) Update(c *dto.SysMenuControl) *SysMenu {
var alist = make([]models.SysApi, 0)
var model = models.SysMenu{}
tx.Preload("SysApi").First(&model, c.GetId())
oldPath := model.Paths
tx.Where("id in ?", c.Apis).Find(&alist)
err = tx.Model(&model).Association("SysApi").Delete(model.SysApi)
if err != nil {
@@ -138,7 +167,7 @@ func (e *SysMenu) Update(c *dto.SysMenuControl) *SysMenu {
c.Generate(&model)
model.SysApi = alist
db := tx.Model(&model).Session(&gorm.Session{FullSaveAssociations: true}).Debug().Save(&model)
if db.Error != nil {
if err = db.Error; err != nil {
e.Log.Errorf("db error:%s", err)
_ = e.AddError(err)
return e
@@ -147,17 +176,22 @@ func (e *SysMenu) Update(c *dto.SysMenuControl) *SysMenu {
_ = e.AddError(errors.New("无权更新该数据"))
return e
}
var menuList []models.SysMenu
tx.Where("paths like ?", oldPath+"%").Find(&menuList)
for _, v := range menuList {
v.Paths = strings.Replace(v.Paths, oldPath, model.Paths, 1)
tx.Model(&v).Update("paths", v.Paths)
}
return e
}
// Remove 删除SysMenu
func (e *SysMenu) Remove(d *dto.SysMenuById) *SysMenu {
func (e *SysMenu) Remove(d *dto.SysMenuDeleteReq) *SysMenu {
var err error
var data models.SysMenu
db := e.Orm.Model(&data).Delete(&data, d.Ids)
if db.Error != nil {
err = db.Error
if err = db.Error; err != nil {
e.Log.Errorf("Delete error: %s", err)
_ = e.AddError(err)
}
@@ -169,7 +203,7 @@ func (e *SysMenu) Remove(d *dto.SysMenuById) *SysMenu {
}
// GetList 获取菜单数据
func (e *SysMenu) GetList(c *dto.SysMenuSearch, list *[]models.SysMenu) error {
func (e *SysMenu) GetList(c *dto.SysMenuGetPageReq, list *[]models.SysMenu) error {
var err error
var data models.SysMenu
@@ -188,7 +222,7 @@ func (e *SysMenu) GetList(c *dto.SysMenuSearch, list *[]models.SysMenu) error {
// SetLabel 修改角色中 设置菜单基础数据
func (e *SysMenu) SetLabel() (m []dto.MenuLabel, err error) {
var list []models.SysMenu
err = e.GetList(&dto.SysMenuSearch{}, &list)
err = e.GetList(&dto.SysMenuGetPageReq{}, &list)
m = make([]dto.MenuLabel, 0)
for i := 0; i < len(list); i++ {
@@ -307,6 +341,40 @@ func menuCall(menuList *[]models.SysMenu, menu models.SysMenu) models.SysMenu {
return menu
}
func menuDistinct(menuList []models.SysMenu) (result []models.SysMenu) {
distinctMap := make(map[int]struct{}, len(menuList))
for _, menu := range menuList {
if _, ok := distinctMap[menu.MenuId]; !ok {
distinctMap[menu.MenuId] = struct{}{}
result = append(result, menu)
}
}
return result
}
func recursiveSetMenu(orm *gorm.DB, mIds []int, menus *[]models.SysMenu) error {
if len(mIds) == 0 || menus == nil {
return nil
}
var subMenus []models.SysMenu
err := orm.Where(fmt.Sprintf(" menu_type in ('%s', '%s', '%s') and menu_id in ?",
cModels.Directory, cModels.Menu, cModels.Button), mIds).Order("sort").Find(&subMenus).Error
if err != nil {
return err
}
subIds := make([]int, 0)
for _, menu := range subMenus {
if menu.ParentId != 0 {
subIds = append(subIds, menu.ParentId)
}
if menu.MenuType != cModels.Button {
*menus = append(*menus, menu)
}
}
return recursiveSetMenu(orm, subIds, menus)
}
// SetMenuRole 获取左侧菜单树使用
func (e *SysMenu) SetMenuRole(roleName string) (m []models.SysMenu, err error) {
menus, err := e.getByRoleName(roleName)
@@ -322,26 +390,37 @@ func (e *SysMenu) SetMenuRole(roleName string) (m []models.SysMenu, err error) {
}
func (e *SysMenu) getByRoleName(roleName string) ([]models.SysMenu, error) {
var MenuList []models.SysMenu
var role models.SysRole
var err error
data := make([]models.SysMenu, 0)
if roleName == "admin" {
var data []models.SysMenu
err = e.Orm.Where(" menu_type in ('M','C')").Order("sort").Find(&data).Error
MenuList = data
// The soft-delete condition is GORM's to add: it appends one for the
// model's DeletedAt field on every query. Writing it by hand duplicates
// that and hard-codes what "deleted" looks like — a column that stops
// being nullable turns this clause into one that matches nothing.
err = e.Orm.Where("menu_type in ('M','C')").
Order("sort").
Find(&data).
Error
err = errors.WithStack(err)
} else {
role.RoleKey = roleName
err = e.Orm.Debug().Model(&role).Where("role_key = ? ", roleName).Preload("SysMenu", func(db *gorm.DB) *gorm.DB {
return db.Where(" menu_type in ('M','C')").Order("sort")
}).Find(&role).Error
err = e.Orm.Model(&role).Where("role_key = ? ", roleName).Preload("SysMenu").First(&role).Error
if role.SysMenu != nil {
MenuList = *role.SysMenu
mIds := make([]int, 0)
for _, menu := range *role.SysMenu {
mIds = append(mIds, menu.MenuId)
}
if err := recursiveSetMenu(e.Orm, mIds, &data); err != nil {
return nil, err
}
data = menuDistinct(data)
}
}
if err != nil {
e.Log.Errorf("db error:%s", err)
}
return MenuList, err
sort.Sort(models.SysMenuSlice(data))
return data, err
}
@@ -0,0 +1,55 @@
package service
import (
"testing"
"github.com/glebarez/sqlite"
"gorm.io/gorm"
"go-admin/app/admin/models"
)
// The admin branch of getSysMenuByRoleName carried "deleted_at is null" in its
// where clause. GORM adds that condition itself for a model with a DeletedAt
// field, so the clause was a duplicate — and one written in terms of a column
// being null, which stops being true the moment the column stops being
// nullable. This pins the behaviour the clause was there for.
func TestSoftDeletedMenusAreNotReturned(t *testing.T) {
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
if err != nil {
t.Fatalf("open: %v", err)
}
if err := db.AutoMigrate(&models.SysMenu{}); err != nil {
t.Fatalf("migrate: %v", err)
}
live := models.SysMenu{MenuName: "live", MenuType: "M"}
gone := models.SysMenu{MenuName: "gone", MenuType: "M"}
if err := db.Create(&live).Error; err != nil {
t.Fatalf("create: %v", err)
}
if err := db.Create(&gone).Error; err != nil {
t.Fatalf("create: %v", err)
}
if err := db.Delete(&gone).Error; err != nil {
t.Fatalf("delete: %v", err)
}
// Through getByRoleName rather than a copy of its query: a test that
// reissues the statement passes whether or not the production line still
// says what it is supposed to, which is what the first version of this
// test did.
e := &SysMenu{}
e.Orm = db
got, err := e.getByRoleName("admin")
if err != nil {
t.Fatalf("getByRoleName: %v", err)
}
if len(got) != 1 {
t.Fatalf("got %d rows, want 1", len(got))
}
if got[0].MenuName != "live" {
t.Errorf("got %q, want the row that was not deleted", got[0].MenuName)
}
}
+2 -2
View File
@@ -35,7 +35,7 @@ func (e *SysOperaLog) GetPage(c *dto.SysOperaLogGetPageReq, list *[]models.SysOp
}
// Get 获取SysOperaLog对象
func (e *SysOperaLog) Get(d *dto.SysOperaLogById, model *models.SysOperaLog) error {
func (e *SysOperaLog) Get(d *dto.SysOperaLogGetReq, model *models.SysOperaLog) error {
var data models.SysOperaLog
err := e.Orm.Model(&data).
@@ -67,7 +67,7 @@ func (e *SysOperaLog) Insert(model *models.SysOperaLog) error {
}
// Remove 删除SysOperaLog
func (e *SysOperaLog) Remove(d *dto.SysOperaLogById) error {
func (e *SysOperaLog) Remove(d *dto.SysOperaLogDeleteReq) error {
var err error
var data models.SysOperaLog
+4 -5
View File
@@ -47,7 +47,7 @@ func (e *SysPost) Get(d *dto.SysPostGetReq, model *models.SysPost) error {
e.Log.Errorf("db error:%s", err)
return err
}
if db.Error != nil {
if err != nil {
e.Log.Errorf("db error:%s", err)
return err
}
@@ -75,7 +75,7 @@ func (e *SysPost) Update(c *dto.SysPostUpdateReq) error {
c.Generate(&model)
db := e.Orm.Save(&model)
if db.Error != nil {
if err = db.Error; err != nil {
e.Log.Errorf("db error:%s", err)
return err
}
@@ -92,8 +92,7 @@ func (e *SysPost) Remove(d *dto.SysPostDeleteReq) error {
var data models.SysPost
db := e.Orm.Model(&data).Delete(&data, d.GetId())
if db.Error != nil {
err = db.Error
if err = db.Error; err != nil {
e.Log.Errorf("Delete error: %s", err)
return err
}
@@ -102,4 +101,4 @@ func (e *SysPost) Remove(d *dto.SysPostDeleteReq) error {
return err
}
return nil
}
}
+127 -68
View File
@@ -2,9 +2,11 @@ package service
import (
"errors"
"github.com/go-admin-team/go-admin-core/sdk/config"
"gorm.io/gorm/clause"
"github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v3"
"github.com/go-admin-team/go-admin-core/sdk/service"
"gorm.io/gorm"
@@ -19,7 +21,7 @@ type SysRole struct {
}
// GetPage 获取SysRole列表
func (e *SysRole) GetPage(c *dto.SysRoleSearch, list *[]models.SysRole, count *int64) error {
func (e *SysRole) GetPage(c *dto.SysRoleGetPageReq, list *[]models.SysRole, count *int64) error {
var err error
var data models.SysRole
@@ -38,7 +40,7 @@ func (e *SysRole) GetPage(c *dto.SysRoleSearch, list *[]models.SysRole, count *i
}
// Get 获取SysRole对象
func (e *SysRole) Get(d *dto.SysRoleById, model *models.SysRole) error {
func (e *SysRole) Get(d *dto.SysRoleGetReq, model *models.SysRole) error {
var err error
db := e.Orm.First(model, d.GetId())
err = db.Error
@@ -60,7 +62,7 @@ func (e *SysRole) Get(d *dto.SysRoleById, model *models.SysRole) error {
}
// Insert 创建SysRole对象
func (e *SysRole) Insert(c *dto.SysRoleControl, cb *casbin.SyncedEnforcer) error {
func (e *SysRole) Insert(c *dto.SysRoleInsertReq, cb *casbin.SyncedEnforcer) error {
var err error
var data models.SysRole
var dataMenu []models.SysMenu
@@ -71,14 +73,29 @@ func (e *SysRole) Insert(c *dto.SysRoleControl, cb *casbin.SyncedEnforcer) error
}
c.SysMenu = dataMenu
c.Generate(&data)
tx := e.Orm.Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
tx := e.Orm
if config.DatabaseConfig.Driver != "sqlite3" {
tx = e.Orm.Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
}
var count int64
err = tx.Model(&data).Where("role_key = ?", c.RoleKey).Count(&count).Error
if err != nil {
e.Log.Errorf("db error:%s", err)
return err
}
if count > 0 {
err = errors.New("roleKey已存在,需更换在提交!")
e.Log.Errorf("db error:%s", err)
return err
}
err = tx.Create(&data).Error
if err != nil {
@@ -86,36 +103,44 @@ func (e *SysRole) Insert(c *dto.SysRoleControl, cb *casbin.SyncedEnforcer) error
return err
}
mp := make(map[string]interface{}, 0)
polices := make([][]string, 0)
for _, menu := range dataMenu {
for _, api := range menu.SysApi {
_, err = cb.AddNamedPolicy("p", data.RoleKey, api.Path, api.Action)
if mp[data.RoleKey+"-"+api.Path+"-"+api.Action] != "" {
mp[data.RoleKey+"-"+api.Path+"-"+api.Action] = ""
polices = append(polices, []string{data.RoleKey, api.Path, api.Action})
}
}
}
_ = cb.SavePolicy()
//if len(c.MenuIds) > 0 {
// s := SysRoleMenu{}
// s.Orm = e.Orm
// s.Log = e.Log
// err = s.ReloadRule(tx, c.RoleId, c.MenuIds)
// if err != nil {
// e.Log.Errorf("reload casbin rule error, %", err.Error())
// return err
// }
//}
if len(polices) <= 0 {
return nil
}
// 写入 sys_casbin_rule 权限表里 当前角色数据的记录
_, err = cb.AddNamedPolicies("p", polices)
if err != nil {
return err
}
return nil
}
// Update 修改SysRole对象
func (e *SysRole) Update(c *dto.SysRoleControl, cb *casbin.SyncedEnforcer) error {
func (e *SysRole) Update(c *dto.SysRoleUpdateReq, cb *casbin.SyncedEnforcer) error {
var err error
tx := e.Orm.Debug().Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
tx := e.Orm
if config.DatabaseConfig.Driver != "sqlite3" {
tx = e.Orm.Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
}
var model = models.SysRole{}
var mlist = make([]models.SysMenu, 0)
tx.Preload("SysMenu").First(&model, c.GetId())
@@ -127,9 +152,10 @@ func (e *SysRole) Update(c *dto.SysRoleControl, cb *casbin.SyncedEnforcer) error
}
c.Generate(&model)
model.SysMenu = &mlist
// 更新关联的数据,使用 FullSaveAssociations 模式
db := tx.Session(&gorm.Session{FullSaveAssociations: true}).Debug().Save(&model)
if db.Error != nil {
if err = db.Error; err != nil {
e.Log.Errorf("db error:%s", err)
return err
}
@@ -137,43 +163,65 @@ func (e *SysRole) Update(c *dto.SysRoleControl, cb *casbin.SyncedEnforcer) error
return errors.New("无权更新该数据")
}
// 清除 sys_casbin_rule 权限表里 当前角色的所有记录
_, err = cb.RemoveFilteredPolicy(0, model.RoleKey)
if err != nil {
e.Log.Errorf("delete policy error:%s", err)
return err
}
mp := make(map[string]interface{}, 0)
polices := make([][]string, 0)
for _, menu := range mlist {
for _, api := range menu.SysApi {
_, err = cb.AddNamedPolicy("p", model.RoleKey, api.Path, api.Action)
if mp[model.RoleKey+"-"+api.Path+"-"+api.Action] != "" {
mp[model.RoleKey+"-"+api.Path+"-"+api.Action] = ""
//_, err = cb.AddNamedPolicy("p", model.RoleKey, api.Path, api.Action)
polices = append(polices, []string{model.RoleKey, api.Path, api.Action})
}
}
}
_ = cb.SavePolicy()
if len(polices) <= 0 {
return nil
}
// 写入 sys_casbin_rule 权限表里 当前角色数据的记录
_, err = cb.AddNamedPolicies("p", polices)
if err != nil {
return err
}
return nil
}
// Remove 删除SysRole
func (e *SysRole) Remove(c *dto.SysRoleById) error {
func (e *SysRole) Remove(c *dto.SysRoleDeleteReq, cb *casbin.SyncedEnforcer) error {
var err error
tx := e.Orm.Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
tx := e.Orm
if config.DatabaseConfig.Driver != "sqlite3" {
tx = e.Orm.Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
}
var model = models.SysRole{}
tx.Preload("SysMenu").Preload("SysDept").First(&model, c.GetId())
//删除 SysRole 时,同时删除角色所有 关联其它表 记录 (SysMenu 和 SysMenu)
db := tx.Select(clause.Associations).Delete(&model)
if db.Error != nil {
if err = db.Error; err != nil {
e.Log.Errorf("db error:%s", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权更新该数据")
}
// 清除 sys_casbin_rule 权限表里 当前角色的所有记录
_, _ = cb.RemoveFilteredPolicy(0, model.RoleKey)
return nil
}
@@ -194,18 +242,22 @@ func (e *SysRole) GetRoleMenuId(roleId int) ([]int, error) {
func (e *SysRole) UpdateDataScope(c *dto.RoleDataScopeReq) *SysRole {
var err error
tx := e.Orm.Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
tx := e.Orm
if config.DatabaseConfig.Driver != "sqlite3" {
tx = e.Orm.Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
}
var dlist = make([]models.SysDept, 0)
var model = models.SysRole{}
tx.Preload("SysDept").First(&model, c.RoleId)
tx.Where("id in ?", c.DeptIds).Find(&dlist)
tx.Where("dept_id in ?", c.DeptIds).Find(&dlist)
// 删除SysRole 和 SysDept 的关联关系
err = tx.Model(&model).Association("SysDept").Delete(model.SysDept)
if err != nil {
e.Log.Errorf("delete SysDept error:%s", err)
@@ -214,8 +266,9 @@ func (e *SysRole) UpdateDataScope(c *dto.RoleDataScopeReq) *SysRole {
}
c.Generate(&model)
model.SysDept = dlist
// 更新关联的数据,使用 FullSaveAssociations 模式
db := tx.Model(&model).Session(&gorm.Session{FullSaveAssociations: true}).Debug().Save(&model)
if db.Error != nil {
if err = db.Error; err != nil {
e.Log.Errorf("db error:%s", err)
_ = e.AddError(err)
return e
@@ -230,19 +283,23 @@ func (e *SysRole) UpdateDataScope(c *dto.RoleDataScopeReq) *SysRole {
// UpdateStatus 修改SysRole对象status
func (e *SysRole) UpdateStatus(c *dto.UpdateStatusReq) error {
var err error
tx := e.Orm.Debug().Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
tx := e.Orm
if config.DatabaseConfig.Driver != "sqlite3" {
tx = e.Orm.Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
}
var model = models.SysRole{}
tx.First(&model, c.GetId())
c.Generate(&model)
// 更新关联的数据,使用 FullSaveAssociations 模式
db := tx.Session(&gorm.Session{FullSaveAssociations: true}).Debug().Save(&model)
if db.Error != nil {
if err = db.Error; err != nil {
e.Log.Errorf("db error:%s", err)
return err
}
@@ -287,7 +344,9 @@ func (e *SysRole) GetById(roleId int) ([]string, error) {
}
l := *model.SysMenu
for i := 0; i < len(l); i++ {
permissions = append(permissions, l[i].Permission)
if l[i].Permission != "" {
permissions = append(permissions, l[i].Permission)
}
}
return permissions, nil
}
}
+25 -20
View File
@@ -60,7 +60,7 @@ func (e *SysUser) Get(d *dto.SysUserById, p *actions.DataPermission, model *mode
}
// Insert 创建SysUser对象
func (e *SysUser) Insert(c *dto.SysUserControl) error {
func (e *SysUser) Insert(c *dto.SysUserInsertReq) error {
var err error
var data models.SysUser
var i int64
@@ -84,7 +84,7 @@ func (e *SysUser) Insert(c *dto.SysUserControl) error {
}
// Update 修改SysUser对象
func (e *SysUser) Update(c *dto.SysUserControl, p *actions.DataPermission) error {
func (e *SysUser) Update(c *dto.SysUserUpdateReq, p *actions.DataPermission) error {
var err error
var model models.SysUser
db := e.Orm.Scopes(
@@ -99,16 +99,21 @@ func (e *SysUser) Update(c *dto.SysUserControl, p *actions.DataPermission) error
}
c.Generate(&model)
err = e.Orm.Save(&model).Error
if err != nil {
e.Log.Errorf("Service UpdateSysUser error: %s", err)
update := e.Orm.Model(&model).Where("user_id = ?", &model.UserId).Omit("password", "salt").Updates(&model)
if err = update.Error; err != nil {
e.Log.Errorf("db error: %s", err)
return err
}
if update.RowsAffected == 0 {
err = errors.New("update userinfo error")
log.Warnf("db update error")
return err
}
return nil
}
// UpdateSysUserAvatar 更新用户头像
func (e *SysUser) UpdateSysUserAvatar(c *dto.UpdateSysUserAvatarReq, p *actions.DataPermission) error {
// UpdateAvatar 更新用户头像
func (e *SysUser) UpdateAvatar(c *dto.UpdateSysUserAvatarReq, p *actions.DataPermission) error {
var err error
var model models.SysUser
db := e.Orm.Scopes(
@@ -122,8 +127,7 @@ func (e *SysUser) UpdateSysUserAvatar(c *dto.UpdateSysUserAvatarReq, p *actions.
return errors.New("无权更新该数据")
}
c.Generate(&model)
err = e.Orm.Save(&model).Error
err = e.Orm.Table(model.TableName()).Where("user_id =? ", c.UserId).Updates(c).Error
if err != nil {
e.Log.Errorf("Service UpdateSysUser error: %s", err)
return err
@@ -131,8 +135,8 @@ func (e *SysUser) UpdateSysUserAvatar(c *dto.UpdateSysUserAvatarReq, p *actions.
return nil
}
// UpdateSysUserStatus 更新用户状态
func (e *SysUser) UpdateSysUserStatus(c *dto.UpdateSysUserStatusReq, p *actions.DataPermission) error {
// UpdateStatus 更新用户状态
func (e *SysUser) UpdateStatus(c *dto.UpdateSysUserStatusReq, p *actions.DataPermission) error {
var err error
var model models.SysUser
db := e.Orm.Scopes(
@@ -146,8 +150,7 @@ func (e *SysUser) UpdateSysUserStatus(c *dto.UpdateSysUserStatusReq, p *actions.
return errors.New("无权更新该数据")
}
c.Generate(&model)
err = e.Orm.Save(&model).Error
err = e.Orm.Table(model.TableName()).Where("user_id =? ", c.UserId).Updates(c).Error
if err != nil {
e.Log.Errorf("Service UpdateSysUser error: %s", err)
return err
@@ -155,8 +158,8 @@ func (e *SysUser) UpdateSysUserStatus(c *dto.UpdateSysUserStatusReq, p *actions.
return nil
}
// ResetSysUserPwd 重置用户密码
func (e *SysUser) ResetSysUserPwd(c *dto.ResetSysUserPwdReq, p *actions.DataPermission) error {
// ResetPwd 重置用户密码
func (e *SysUser) ResetPwd(c *dto.ResetSysUserPwdReq, p *actions.DataPermission) error {
var err error
var model models.SysUser
db := e.Orm.Scopes(
@@ -170,7 +173,7 @@ func (e *SysUser) ResetSysUserPwd(c *dto.ResetSysUserPwdReq, p *actions.DataPerm
return errors.New("无权更新该数据")
}
c.Generate(&model)
err = e.Orm.Save(&model).Error
err = e.Orm.Omit("username", "nick_name", "phone", "role_id", "avatar", "sex").Save(&model).Error
if err != nil {
e.Log.Errorf("At Service ResetSysUserPwd error: %s", err)
return err
@@ -197,8 +200,8 @@ func (e *SysUser) Remove(c *dto.SysUserById, p *actions.DataPermission) error {
return nil
}
// UpdateSysUserPwd 修改SysUser对象密码
func (e *SysUser) UpdateSysUserPwd(id int, oldPassword, newPassword string, p *actions.DataPermission) error {
// UpdatePwd 修改SysUser对象密码
func (e *SysUser) UpdatePwd(id int, oldPassword, newPassword string, p *actions.DataPermission) error {
var err error
if newPassword == "" {
@@ -230,7 +233,9 @@ func (e *SysUser) UpdateSysUserPwd(id int, oldPassword, newPassword string, p *a
return err
}
c.Password = newPassword
db := e.Orm.Model(c).Where("user_id = ?", id).Select("Password", "Salt").Updates(c)
db := e.Orm.Model(c).Where("user_id = ?", id).
Select("Password", "Salt").
Updates(c)
if err = db.Error; err != nil {
e.Log.Errorf("db error: %s", err)
return err
@@ -243,7 +248,7 @@ func (e *SysUser) UpdateSysUserPwd(id int, oldPassword, newPassword string, p *a
return nil
}
func (e *SysUser) GetSysUserProfile(c *dto.SysUserById, user *models.SysUser, roles *[]models.SysRole, posts *[]models.SysPost) error {
func (e *SysUser) GetProfile(c *dto.SysUserById, user *models.SysUser, roles *[]models.SysRole, posts *[]models.SysPost) error {
err := e.Orm.Preload("Dept").First(user, c.GetId()).Error
if err != nil {
return err
+37
View File
@@ -0,0 +1,37 @@
package models
import (
"go-admin/common/models"
)
// DemoProduct 示例模型
//
// 内嵌 ControlBy 与 ModelTime 后,创建人/更新人与时间戳由框架自动维护;
// 数据权限(actions.Permission)正是按 create_by 过滤,缺少 ControlBy 会使其失效。
type DemoProduct struct {
models.Model
Name string `json:"name" gorm:"size:128;comment:名称"`
Code string `json:"code" gorm:"size:64;comment:编码"`
Price float64 `json:"price" gorm:"comment:单价"`
Status string `json:"status" gorm:"size:4;comment:状态"`
Remark string `json:"remark" gorm:"size:255;comment:备注"`
models.ControlBy
models.ModelTime
}
func (DemoProduct) TableName() string {
return "demo_product"
}
// Generate 返回副本,供通用 Action 使用。
// 必须返回新实例:Action 在并发请求间复用同一个模型指针,就地返回会串数据。
func (e *DemoProduct) Generate() models.ActiveRecord {
o := *e
return &o
}
func (e *DemoProduct) GetId() interface{} {
return e.Id
}
+49
View File
@@ -0,0 +1,49 @@
package router
import (
"github.com/gin-gonic/gin"
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
"go-admin/app/demo/models"
"go-admin/app/demo/service/dto"
"go-admin/common/actions"
"go-admin/common/middleware"
)
// 路由通过 init 自注册,无需在任何中心文件登记。
// 新建应用时用 `go run main.go app -n <名称>` 生成骨架,
// 它会同时产出 cmd/api/<名称>.go 完成注册。
func init() {
routerCheckRole = append(routerCheckRole, registerDemoProductRouter)
}
// registerDemoProductRouter 标准 CRUD 的推荐写法。
//
// 五个通用 Action 覆盖了增删改查的全部样板逻辑——参数绑定、数据权限过滤、
// 操作人注入、分页、错误响应,因此本模块没有 apis 与 service 文件。
//
// 仅当业务逻辑超出单表 CRUD(如跨表事务、外部调用、复杂校验)时,才需要
// 自行编写 Handler 与 Service,写法参照 app/admin/apis/sys_post.go。
func registerDemoProductRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
r := v1.Group("/demo-product").
Use(authMiddleware.MiddlewareFunc()). // JWT 认证
Use(middleware.AuthCheckRole()) // Casbin 鉴权
{
m := &models.DemoProduct{}
// actions.PermissionAction() 注入数据权限上下文,
// 列表与详情缺少它会绕过 DataScope 过滤
r.GET("", actions.PermissionAction(), actions.IndexAction(m, new(dto.DemoProductSearch), func() interface{} {
list := make([]models.DemoProduct, 0)
return &list
}))
r.GET("/:id", actions.PermissionAction(), actions.ViewAction(new(dto.DemoProductById), func() interface{} {
return &models.DemoProduct{}
}))
r.POST("", actions.CreateAction(new(dto.DemoProductControl)))
r.PUT("/:id", actions.PermissionAction(), actions.UpdateAction(new(dto.DemoProductControl)))
r.DELETE("", actions.PermissionAction(), actions.DeleteAction(new(dto.DemoProductById)))
}
}
+74
View File
@@ -0,0 +1,74 @@
package router
import (
"github.com/gin-gonic/gin"
_ "github.com/gin-gonic/gin"
log "github.com/go-admin-team/go-admin-core/logger"
"github.com/go-admin-team/go-admin-core/sdk"
// "github.com/go-admin-team/go-admin-core/sdk/pkg"
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
common "go-admin/common/middleware"
"os"
)
var (
routerNoCheckRole = make([]func(*gin.RouterGroup), 0)
routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0)
)
// InitRouter 路由初始化
func InitRouter() {
var r *gin.Engine
h := sdk.Runtime.GetEngine()
if h == nil {
h = gin.New()
sdk.Runtime.SetEngine(h)
}
switch h.(type) {
case *gin.Engine:
r = h.(*gin.Engine)
default:
log.Fatal("not support other engine")
os.Exit(-1)
}
// the jwt middleware
authMiddleware, err := common.AuthInit()
if err != nil {
log.Fatalf("JWT Init Error, %s", err.Error())
}
// 注册业务路由
InitBusinessRouter(r, authMiddleware)
}
func InitBusinessRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine {
// 无需认证的路由
noCheckRoleRouter(r)
// 需要认证的路由
checkRoleRouter(r, authMiddleware)
return r
}
// noCheckRoleRouter 无需认证的路由
func noCheckRoleRouter(r *gin.Engine) {
// 可根据业务需求来设置接口版本
v := r.Group("/api/v1")
for _, f := range routerNoCheckRole {
f(v)
}
}
// checkRoleRouter 需要认证的路由
func checkRoleRouter(r *gin.Engine, authMiddleware *jwtauth.GinJWTMiddleware) {
// 可根据业务需求来设置接口版本
v := r.Group("/api/v1")
for _, f := range routerCheckRole {
f(v, authMiddleware)
}
}
+96
View File
@@ -0,0 +1,96 @@
package dto
import (
"github.com/gin-gonic/gin"
"go-admin/app/demo/models"
"go-admin/common/dto"
common "go-admin/common/models"
)
// DemoProductSearch 列表查询条件
//
// search tag 决定 MakeCondition 拼出的 WHERE:
//
// exact 精确匹配 / icontains 忽略大小写模糊 / gte 大于等于 …
//
// 未打 search tag 的字段不参与查询,可避免无意间开放过滤维度。
type DemoProductSearch struct {
dto.Pagination `search:"-"`
Name string `form:"name" search:"type:icontains;column:name;table:demo_product"`
Code string `form:"code" search:"type:exact;column:code;table:demo_product"`
Status string `form:"status" search:"type:exact;column:status;table:demo_product"`
DemoProductOrder
}
// DemoProductOrder 排序字段单独成组,避免与查询字段混在一起
type DemoProductOrder struct {
CreatedAtOrder string `form:"createdAtOrder" search:"type:order;column:created_at;table:demo_product"`
}
func (m *DemoProductSearch) GetNeedSearch() interface{} { return *m }
func (m *DemoProductSearch) Bind(ctx *gin.Context) error {
return ctx.ShouldBind(m)
}
func (m *DemoProductSearch) Generate() dto.Index {
o := *m
return &o
}
// DemoProductControl 新增与修改共用的入参
//
// 通用 Action(Create / Update)通过 GenerateM 拿到落库对象,
// 因此这里不直接暴露 Model,字段校验用 validate tag 声明。
type DemoProductControl struct {
Id int `json:"id" comment:"主键"`
Name string `json:"name" comment:"名称" validate:"required"`
Code string `json:"code" comment:"编码" validate:"required"`
Price float64 `json:"price" comment:"单价" validate:"gte=0"`
Status string `json:"status" comment:"状态"`
Remark string `json:"remark" comment:"备注"`
}
func (s *DemoProductControl) Bind(ctx *gin.Context) error {
return ctx.ShouldBind(s)
}
func (s *DemoProductControl) Generate() dto.Control {
o := *s
return &o
}
func (s *DemoProductControl) GetId() interface{} { return s.Id }
// GenerateM 组装落库对象。CreateBy / UpdateBy 由通用 Action 在此之后注入,
// 此处不要手动赋值。
func (s *DemoProductControl) GenerateM() (common.ActiveRecord, error) {
return &models.DemoProduct{
Model: common.Model{Id: s.Id},
Name: s.Name,
Code: s.Code,
Price: s.Price,
Status: s.Status,
Remark: s.Remark,
}, nil
}
// DemoProductById 详情与删除共用,支持单个 id 与批量 ids
type DemoProductById struct {
dto.ObjectById
}
// Bind 与 GetId 由内嵌的 dto.ObjectById 提供:它已处理好 uri 绑定、
// DELETE 时的批量 ids 合并与参数校验,无需在此重复实现。
func (s *DemoProductById) Generate() dto.Control {
o := *s
return &o
}
func (s *DemoProductById) GenerateM() (common.ActiveRecord, error) {
return &models.DemoProduct{}, nil
}
+91
View File
@@ -0,0 +1,91 @@
package dto
import (
"testing"
"go-admin/app/demo/models"
"go-admin/common/dto"
common "go-admin/common/models"
)
// 通用 Action 依赖 DTO 与 Model 实现一组接口。这些约束在编译期无法完全覆盖
// (接口是在路由注册处才被要求的),因此用测试锁定,避免改动后在运行时才暴露。
func TestImplementsIndexInterface(t *testing.T) {
var _ dto.Index = (*DemoProductSearch)(nil)
}
func TestImplementsControlInterface(t *testing.T) {
var _ dto.Control = (*DemoProductControl)(nil)
var _ dto.Control = (*DemoProductById)(nil)
}
func TestModelImplementsActiveRecord(t *testing.T) {
var _ common.ActiveRecord = (*models.DemoProduct)(nil)
}
// Generate 必须返回副本:通用 Action 在并发请求间复用同一个实例,
// 就地返回会导致请求之间串数据。
func TestGenerateReturnsCopy(t *testing.T) {
src := &DemoProductControl{Id: 1, Name: "原始"}
got := src.Generate().(*DemoProductControl)
if got == src {
t.Fatal("Generate 返回了同一指针,应返回副本")
}
got.Name = "被修改"
if src.Name != "原始" {
t.Errorf("修改副本影响了原对象:src.Name = %q", src.Name)
}
}
func TestSearchGenerateReturnsCopy(t *testing.T) {
src := &DemoProductSearch{Name: "原始"}
got := src.Generate().(*DemoProductSearch)
if got == src {
t.Fatal("Generate 返回了同一指针,应返回副本")
}
got.Name = "被修改"
if src.Name != "原始" {
t.Errorf("修改副本影响了原对象:src.Name = %q", src.Name)
}
}
func TestModelGenerateReturnsCopy(t *testing.T) {
src := &models.DemoProduct{Name: "原始"}
got := src.Generate().(*models.DemoProduct)
if got == src {
t.Fatal("Generate 返回了同一指针,应返回副本")
}
got.Name = "被修改"
if src.Name != "原始" {
t.Errorf("修改副本影响了原对象:src.Name = %q", src.Name)
}
}
// GenerateM 组装落库对象,主键需正确传递,否则更新会退化成插入。
func TestGenerateMCarriesId(t *testing.T) {
c := &DemoProductControl{Id: 42, Name: "示例", Code: "P-42", Price: 9.9}
m, err := c.GenerateM()
if err != nil {
t.Fatalf("GenerateM 返回错误: %v", err)
}
p, ok := m.(*models.DemoProduct)
if !ok {
t.Fatalf("GenerateM 返回类型错误: %T", m)
}
if p.Id != 42 {
t.Errorf("主键未传递: got %d, want 42", p.Id)
}
if p.Name != "示例" || p.Code != "P-42" || p.Price != 9.9 {
t.Errorf("字段映射有误: %+v", p)
}
}
func TestTableName(t *testing.T) {
if got := (models.DemoProduct{}).TableName(); got != "demo_product" {
t.Errorf("TableName() = %q, want %q", got, "demo_product")
}
}
+3 -3
View File
@@ -29,7 +29,7 @@ func (e SysJob) RemoveJobForService(c *gin.Context) {
return
}
s.Cron = sdk.Runtime.GetCrontabKey(c.Request.Host)
s.Cron = sdk.Runtime.GetCrontabByTenant(c.Request.Host)
err = s.RemoveJob(&v)
if err != nil {
e.Logger.Errorf("RemoveJob error, %s", err.Error())
@@ -58,11 +58,11 @@ func (e SysJob) StartJobForService(c *gin.Context) {
s := service.SysJob{}
s.Orm = db
s.Log = log
s.Cron = sdk.Runtime.GetCrontabKey(c.Request.Host)
s.Cron = sdk.Runtime.GetCrontabByTenant(c.Request.Host)
err = s.StartJob(&v)
if err != nil {
log.Errorf("GetCrontabKey error, %s", err.Error())
e.Error(500, err, "")
e.Error(500, err, err.Error())
return
}
e.OK(nil, s.Msg)
+3 -1
View File
@@ -5,15 +5,17 @@ import (
"time"
)
// InitJob
// 需要将定义的struct 添加到字典中;
// 字典 key 可以配置到 自动任务 调用目标 中;
func InitJob() {
jobList = map[string]JobsExec{
jobList = map[string]JobExec{
"ExamplesOne": ExamplesOne{},
// ...
}
}
// ExamplesOne
// 新添加的job 必须按照以下格式定义,并实现Exec函数
type ExamplesOne struct {
}
+16 -16
View File
@@ -6,7 +6,6 @@ import (
"github.com/go-admin-team/go-admin-core/sdk"
models2 "go-admin/app/jobs/models"
"gorm.io/gorm"
"sync"
"time"
"github.com/robfig/cron/v3"
@@ -18,8 +17,9 @@ import (
var timeFormat = "2006-01-02 15:04:05"
var retryCount = 3
var jobList map[string]JobsExec
var lock sync.Mutex
var jobList map[string]JobExec
//var lock sync.Mutex
type JobCore struct {
InvokeTarget string
@@ -30,7 +30,7 @@ type JobCore struct {
Args string
}
// 任务类型 http
// HttpJob 任务类型 http
type HttpJob struct {
JobCore
}
@@ -46,7 +46,7 @@ func (e *ExecJob) Run() {
log.Warn("[Job] ExecJob Run job nil")
return
}
err := CallExec(obj.(JobsExec), e.Args)
err := CallExec(obj.(JobExec), e.Args)
if err != nil {
// 如果失败暂停一段时间重试
fmt.Println(time.Now().Format(timeFormat), " [ERROR] mission failed! ", err)
@@ -59,11 +59,11 @@ func (e *ExecJob) Run() {
//TODO: 待完善部分
//str := time.Now().Format(timeFormat) + " [INFO] JobCore " + string(e.EntryId) + "exec success , spend :" + latencyTime.String()
//ws.SendAll(str)
log.Info("[Job] JobCore %s exec success , spend :%v", e.Name, latencyTime)
log.Infof("[Job] JobCore %s exec success , spend :%v", e.Name, latencyTime)
return
}
//http 任务接口
// Run http 任务接口
func (h *HttpJob) Run() {
startTime := time.Now()
@@ -77,8 +77,8 @@ LOOP:
str, err = pkg.Get(h.InvokeTarget)
if err != nil {
// 如果失败暂停一段时间重试
fmt.Println(time.Now().Format(timeFormat), " [ERROR] mission failed! ", err)
fmt.Printf(time.Now().Format(timeFormat)+" [INFO] Retry after the task fails %d seconds! %s \n", (count+1)*5, str)
log.Warnf("[Job] mission failed! %v", err)
log.Warnf("[Job] Retry after the task fails %d seconds! %s \n", (count+1)*5, str)
time.Sleep(time.Duration(count+1) * 5 * time.Second)
count = count + 1
goto LOOP
@@ -95,19 +95,19 @@ LOOP:
return
}
// 初始化
// Setup 初始化
func Setup(dbs map[string]*gorm.DB) {
fmt.Println(time.Now().Format(timeFormat), " [INFO] JobCore Starting...")
for k, db := range dbs {
sdk.Runtime.SetCrontab(k, cronjob.NewWithSeconds())
sdk.Runtime.SetCrontabByTenant(k, cronjob.NewWithSeconds())
setup(k, db)
}
}
func setup(key string, db *gorm.DB) {
crontab := sdk.Runtime.GetCrontabKey(key)
crontab := sdk.Runtime.GetCrontabByTenant(key)
sysJob := models2.SysJob{}
jobList := make([]models2.SysJob, 0)
err := sysJob.GetList(db, &jobList)
@@ -152,7 +152,7 @@ func setup(key string, db *gorm.DB) {
select {}
}
// 添加任务 AddJob(invokeTarget string, jobId int, jobName string, cronExpression string)
// AddJob 添加任务 AddJob(invokeTarget string, jobId int, jobName string, cronExpression string)
func AddJob(c *cron.Cron, job Job) (int, error) {
if job == nil {
fmt.Println("unknown")
@@ -171,8 +171,8 @@ func (h *HttpJob) addJob(c *cron.Cron) (int, error) {
return EntryId, nil
}
func (h *ExecJob) addJob(c *cron.Cron) (int, error) {
id, err := c.AddJob(h.CronExpression, h)
func (e *ExecJob) addJob(c *cron.Cron) (int, error) {
id, err := c.AddJob(e.CronExpression, e)
if err != nil {
fmt.Println(time.Now().Format(timeFormat), " [ERROR] JobCore AddJob error", err)
return 0, err
@@ -181,7 +181,7 @@ func (h *ExecJob) addJob(c *cron.Cron) (int, error) {
return EntryId, nil
}
// 移除任务
// Remove 移除任务
func Remove(c *cron.Cron, entryID int) chan bool {
ch := make(chan bool)
go func() {
+2 -2
View File
@@ -23,7 +23,7 @@ type SysJob struct {
DataScope string `json:"dataScope" gorm:"-"`
}
func (SysJob) TableName() string {
func (*SysJob) TableName() string {
return "sys_job"
}
@@ -48,7 +48,7 @@ func (e *SysJob) GetList(tx *gorm.DB, list interface{}) (err error) {
return tx.Table(e.TableName()).Where("status = ?", 2).Find(list).Error
}
// 更新SysJob
// Update 更新SysJob
func (e *SysJob) Update(tx *gorm.DB, id interface{}) (err error) {
return tx.Table(e.TableName()).Where(id).Updates(&e).Error
}
+7
View File
@@ -1,6 +1,7 @@
package service
import (
"errors"
"time"
"github.com/go-admin-team/go-admin-core/sdk/service"
@@ -52,6 +53,12 @@ func (e *SysJob) StartJob(c *dto.GeneralGetDto) error {
e.Log.Errorf("db error: %s", err)
return err
}
if data.Status == 1 {
err = errors.New("当前Job是关闭状态不能被启动,请先启用。")
return err
}
if data.JobType == 1 {
var j = &jobs.HttpJob{}
j.InvokeTarget = data.InvokeTarget
+2 -2
View File
@@ -7,10 +7,10 @@ type Job interface {
addJob(*cron.Cron) (int, error)
}
type JobsExec interface {
type JobExec interface {
Exec(arg interface{}) error
}
func CallExec(e JobsExec, arg interface{}) error {
func CallExec(e JobExec, arg interface{}) error {
return e.Exec(arg)
}
+80 -87
View File
@@ -44,63 +44,61 @@ type File struct {
func (e File) UploadFile(c *gin.Context) {
e.MakeContext(c)
tag, _ := c.GetPostForm("type")
urlPrefix := fmt.Sprintf("http://%s/", c.Request.Host)
var fileResponse FileResponse
urlPrefix := fmt.Sprintf("%s://%s/", "http", c.Request.Host)
switch tag {
case "1": // 单图
var done bool
fileResponse, done = e.singleFile(c, fileResponse, urlPrefix)
if done {
return
}
e.OK(fileResponse, "上传成功")
return
e.handleSingleFile(c, urlPrefix)
case "2": // 多图
multipartFile := e.multipleFile(c, urlPrefix)
e.OK(multipartFile, "上传成功")
return
e.handleMultipleFiles(c, urlPrefix)
case "3": // base64
fileResponse = e.baseImg(c, fileResponse, urlPrefix)
e.OK(fileResponse, "上传成功")
e.handleBase64File(c, urlPrefix)
default:
var done bool
fileResponse, done = e.singleFile(c, fileResponse, urlPrefix)
if done {
return
}
e.OK(fileResponse, "上传成功")
return
e.handleSingleFile(c, urlPrefix)
}
}
func (e File) baseImg(c *gin.Context, fileResponse FileResponse, urlPerfix string) FileResponse {
func (e File) handleSingleFile(c *gin.Context, urlPrefix string) {
fileResponse, done := e.singleFile(c, FileResponse{}, urlPrefix)
if done {
return
}
e.OK(fileResponse, "上传成功")
}
func (e File) handleMultipleFiles(c *gin.Context, urlPrefix string) {
multipartFile := e.multipleFile(c, urlPrefix)
e.OK(multipartFile, "上传成功")
}
func (e File) handleBase64File(c *gin.Context, urlPrefix string) {
fileResponse := e.baseImg(c, FileResponse{}, urlPrefix)
e.OK(fileResponse, "上传成功")
}
func (e File) baseImg(c *gin.Context, fileResponse FileResponse, urlPrefix string) FileResponse {
files, _ := c.GetPostForm("file")
file2list := strings.Split(files, ",")
ddd, _ := base64.StdEncoding.DecodeString(file2list[1])
guid := uuid.New().String()
fileName := guid + ".jpg"
err := utils.IsNotExistMkDir(path)
if err != nil {
decodedData, _ := base64.StdEncoding.DecodeString(file2list[1])
fileName := uuid.New().String() + ".jpg"
if err := utils.IsNotExistMkDir(path); err != nil {
e.Error(500, errors.New(""), "初始化文件路径失败")
return fileResponse
}
base64File := path + fileName
_ = ioutil.WriteFile(base64File, ddd, 0666)
_ = ioutil.WriteFile(base64File, decodedData, 0666)
typeStr := strings.Replace(strings.Replace(file2list[0], "data:", "", -1), ";base64", "", -1)
fileResponse = FileResponse{
Size: pkg.GetFileSize(base64File),
Path: base64File,
FullPath: urlPerfix + base64File,
Name: "",
Type: typeStr,
}
fileResponse = e.buildFileResponse(base64File, urlPrefix, "", typeStr)
source, _ := c.GetPostForm("source")
err = thirdUpload(source, fileName, base64File)
if err != nil {
if err := thirdUpload(source, fileName, base64File); err != nil {
e.Error(200, errors.New(""), "上传第三方失败")
return fileResponse
}
if source != "1" {
fileResponse.Path = "/static/uploadfile/" + fileName
fileResponse.FullPath = "/static/uploadfile/" + fileName
@@ -108,81 +106,76 @@ func (e File) baseImg(c *gin.Context, fileResponse FileResponse, urlPerfix strin
return fileResponse
}
func (e File) multipleFile(c *gin.Context, urlPerfix string) []FileResponse {
func (e File) multipleFile(c *gin.Context, urlPrefix string) []FileResponse {
files := c.Request.MultipartForm.File["file"]
source, _ := c.GetPostForm("source")
var multipartFile []FileResponse
for _, f := range files {
guid := uuid.New().String()
fileName := guid + utils.GetExt(f.Filename)
err := utils.IsNotExistMkDir(path)
if err != nil {
for _, f := range files {
fileName := uuid.New().String() + utils.GetExt(f.Filename)
if err := utils.IsNotExistMkDir(path); err != nil {
e.Error(500, errors.New(""), "初始化文件路径失败")
continue
}
multipartFileName := path + fileName
err1 := c.SaveUploadedFile(f, multipartFileName)
fileType, _ := utils.GetType(multipartFileName)
if err1 == nil {
err := thirdUpload(source, fileName, multipartFileName)
if err != nil {
e.Error(500, errors.New(""), "上传第三方失败")
} else {
fileResponse := FileResponse{
Size: pkg.GetFileSize(multipartFileName),
Path: multipartFileName,
FullPath: urlPerfix + multipartFileName,
Name: f.Filename,
Type: fileType,
}
if source != "1" {
fileResponse.Path = "/static/uploadfile/" + fileName
fileResponse.FullPath = "/static/uploadfile/" + fileName
}
multipartFile = append(multipartFile, fileResponse)
}
if err := c.SaveUploadedFile(f, multipartFileName); err != nil {
continue
}
fileType, _ := utils.GetType(multipartFileName)
if err := thirdUpload(source, fileName, multipartFileName); err != nil {
e.Error(500, errors.New(""), "上传第三方失败")
continue
}
fileResponse := e.buildFileResponse(multipartFileName, urlPrefix, f.Filename, fileType)
if source != "1" {
fileResponse.Path = "/static/uploadfile/" + fileName
fileResponse.FullPath = "/static/uploadfile/" + fileName
}
multipartFile = append(multipartFile, fileResponse)
}
return multipartFile
}
func (e File) singleFile(c *gin.Context, fileResponse FileResponse, urlPerfix string) (FileResponse, bool) {
func (e File) singleFile(c *gin.Context, fileResponse FileResponse, urlPrefix string) (FileResponse, bool) {
files, err := c.FormFile("file")
if err != nil {
e.Error(200, errors.New(""), "图片不能为空")
return FileResponse{}, true
}
// 上传文件至指定目录
guid := uuid.New().String()
fileName := guid + utils.GetExt(files.Filename)
err = utils.IsNotExistMkDir(path)
if err != nil {
fileName := uuid.New().String() + utils.GetExt(files.Filename)
if err := utils.IsNotExistMkDir(path); err != nil {
e.Error(500, errors.New(""), "初始化文件路径失败")
return FileResponse{}, true
}
singleFile := path + fileName
_ = c.SaveUploadedFile(files, singleFile)
fileType, _ := utils.GetType(singleFile)
fileResponse = FileResponse{
Size: pkg.GetFileSize(singleFile),
Path: singleFile,
FullPath: urlPerfix + singleFile,
Name: files.Filename,
Type: fileType,
if err := c.SaveUploadedFile(files, singleFile); err != nil {
e.Error(500, errors.New(""), "文件保存失败")
return FileResponse{}, true
}
//source, _ := c.GetPostForm("source")
//err = thirdUpload(source, fileName, singleFile)
//if err != nil {
// e.Error(200, errors.New(""), "上传第三方失败")
// return FileResponse{}, true
//}
fileType, _ := utils.GetType(singleFile)
fileResponse = e.buildFileResponse(singleFile, urlPrefix, files.Filename, fileType)
fileResponse.Path = "/static/uploadfile/" + fileName
fileResponse.FullPath = "/static/uploadfile/" + fileName
return fileResponse, false
}
func (e File) buildFileResponse(filePath, urlPrefix, fileName, fileType string) FileResponse {
return FileResponse{
Size: pkg.GetFileSize(filePath),
Path: filePath,
FullPath: urlPrefix + filePath,
Name: fileName,
Type: fileType,
}
}
func thirdUpload(source string, name string, path string) error {
switch source {
case "2":
@@ -201,4 +194,4 @@ func ossUpload(name string, path string) error {
func qiniuUpload(name string, path string) error {
oss := file_store.ALiYunOSS{}
return oss.UpLoad(name, path)
}
}
+153 -47
View File
@@ -1,15 +1,20 @@
package apis
import (
"fmt"
"github.com/shirou/gopsutil/v3/net"
"runtime"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/go-admin-team/go-admin-core/sdk/api"
"github.com/go-admin-team/go-admin-core/sdk/pkg"
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/disk"
"github.com/shirou/gopsutil/mem"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/host"
"github.com/shirou/gopsutil/v3/mem"
)
const (
@@ -19,59 +24,160 @@ const (
GB = 1024 * MB
)
var excludeNetInterfaces = []string{
"lo", "tun", "docker", "veth", "br-", "vmbr", "vnet", "kube",
}
type ServerMonitor struct {
api.Api
}
// GetHourDiffer 获取相差时间
func GetHourDiffer(startTime, endTime string) int64 {
t1, err1 := time.ParseInLocation("2006-01-02 15:04:05", startTime, time.Local)
t2, err2 := time.ParseInLocation("2006-01-02 15:04:05", endTime, time.Local)
if err1 != nil || err2 != nil || !t1.Before(t2) {
return 0
}
return (t2.Unix() - t1.Unix()) / 3600
}
// ServerInfo 获取系统信息
// @Summary 系统信息
// @Description 获取JSON
// @Tags 系统信息
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/server-monitor [get]
// @Security Bearer
func (e ServerMonitor) ServerInfo(c *gin.Context) {
e.Context = c
osDic := make(map[string]interface{}, 0)
osDic["goOs"] = runtime.GOOS
osDic["arch"] = runtime.GOARCH
osDic["mem"] = runtime.MemProfileRate
osDic["compiler"] = runtime.Compiler
osDic["version"] = runtime.Version()
osDic["numGoroutine"] = runtime.NumGoroutine()
osDic["ip"] = pkg.GetLocaHonst()
osDic["projectDir"] = pkg.GetCurrentPath()
osInfo := getOSInfo()
memInfo := getMemoryInfo()
swapInfo := getSwapInfo()
cpuInfo := getCPUInfo()
diskInfo := getDiskInfo()
netInfo := getNetworkInfo()
dis, _ := disk.Usage("/")
diskTotalGB := int(dis.Total) / GB
diskFreeGB := int(dis.Free) / GB
diskDic := make(map[string]interface{}, 0)
diskDic["total"] = diskTotalGB
diskDic["free"] = diskFreeGB
mem, _ := mem.VirtualMemory()
memUsedMB := int(mem.Used) / GB
memTotalMB := int(mem.Total) / GB
memFreeMB := int(mem.Free) / GB
memUsedPercent := int(mem.UsedPercent)
memDic := make(map[string]interface{}, 0)
memDic["total"] = memTotalMB
memDic["used"] = memUsedMB
memDic["free"] = memFreeMB
memDic["usage"] = memUsedPercent
cpuDic := make(map[string]interface{}, 0)
cpuDic["cpuInfo"], _ = cpu.Info()
percent, _ := cpu.Percent(0, false)
cpuDic["Percent"] = pkg.Round(percent[0], 2)
cpuDic["cpuNum"], _ = cpu.Counts(false)
bootTime, _ := host.BootTime()
cachedBootTime := time.Unix(int64(bootTime), 0)
e.Custom(gin.H{
"code": 200,
"os": osDic,
"mem": memDic,
"cpu": cpuDic,
"disk": diskDic,
"code": 200,
"os": osInfo,
"mem": memInfo,
"cpu": cpuInfo,
"disk": diskInfo,
"net": netInfo,
"swap": swapInfo,
"location": "Aliyun",
"bootTime": GetHourDiffer(cachedBootTime.Format("2006-01-02 15:04:05"), time.Now().Format("2006-01-02 15:04:05")),
})
}
func getOSInfo() map[string]interface{} {
sysInfo, _ := host.Info()
return map[string]interface{}{
"goOs": runtime.GOOS,
"arch": runtime.GOARCH,
"mem": runtime.MemProfileRate,
"compiler": runtime.Compiler,
"version": runtime.Version(),
"numGoroutine": runtime.NumGoroutine(),
"ip": pkg.GetLocalHost(),
"projectDir": pkg.GetCurrentPath(),
"hostName": sysInfo.Hostname,
"time": time.Now().Format("2006-01-02 15:04:05"),
}
}
func getMemoryInfo() map[string]interface{} {
memory, _ := mem.VirtualMemory()
return map[string]interface{}{
"used": memory.Used / MB,
"total": memory.Total / MB,
"percent": pkg.Round(memory.UsedPercent, 2),
}
}
func getSwapInfo() map[string]interface{} {
memory, _ := mem.VirtualMemory()
return map[string]interface{}{
"used": memory.SwapTotal - memory.SwapFree,
"total": memory.SwapTotal,
}
}
func getCPUInfo() map[string]interface{} {
cpuInfo, _ := cpu.Info()
percent, _ := cpu.Percent(0, false)
cpuNum, _ := cpu.Counts(false)
return map[string]interface{}{
"cpuInfo": cpuInfo,
"percent": pkg.Round(percent[0], 2),
"cpuNum": cpuNum,
}
}
func getDiskInfo() map[string]interface{} {
var diskTotal, diskUsed, diskUsedPercent float64
diskList := make([]disk.UsageStat, 0)
diskInfo, err := disk.Partitions(true)
if err == nil {
for _, p := range diskInfo {
diskDetail, err := disk.Usage(p.Mountpoint)
if err == nil {
diskDetail.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", diskDetail.UsedPercent), 64)
diskDetail.Total /= MB
diskDetail.Used /= MB
diskDetail.Free /= MB
diskList = append(diskList, *diskDetail)
}
}
}
d, _ := disk.Usage("/")
diskTotal = float64(d.Total / GB)
diskUsed = float64(d.Used / GB)
diskUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", d.UsedPercent), 64)
return map[string]interface{}{
"total": diskTotal,
"used": diskUsed,
"percent": diskUsedPercent,
}
}
func getNetworkInfo() map[string]interface{} {
netInSpeed, netOutSpeed := trackNetworkSpeed()
return map[string]interface{}{
"in": pkg.Round(float64(netInSpeed/KB), 2),
"out": pkg.Round(float64(netOutSpeed/KB), 2),
}
}
func trackNetworkSpeed() (uint64, uint64) {
var netInSpeed, netOutSpeed, netInTransfer, netOutTransfer, lastUpdateNetStats uint64
nc, err := net.IOCounters(true)
if err == nil {
for _, v := range nc {
if isListContainsStr(excludeNetInterfaces, v.Name) {
continue
}
netInTransfer += v.BytesRecv
netOutTransfer += v.BytesSent
}
now := uint64(time.Now().Unix())
diff := now - lastUpdateNetStats
if diff > 0 {
netInSpeed = (netInTransfer - netInTransfer) / diff
netOutSpeed = (netOutTransfer - netOutTransfer) / diff
}
lastUpdateNetStats = now
}
return netInSpeed, netOutSpeed
}
func isListContainsStr(list []string, str string) bool {
for _, item := range list {
if strings.Contains(str, item) {
return true
}
}
return false
}
+1 -1
View File
@@ -17,7 +17,7 @@ import (
// @Param pageIndex query int false "pageIndex / 页码"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/db/columns/page [get]
func (e *Gen) GetDBColumnList(c *gin.Context) {
func (e Gen) GetDBColumnList(c *gin.Context) {
e.Context = c
log := e.GetLogger()
var data tools.DBColumns
+1 -1
View File
@@ -19,7 +19,7 @@ import (
// @Param pageIndex query int false "pageIndex / 页码"
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
// @Router /api/v1/db/tables/page [get]
func (e *Gen) GetDBTableList(c *gin.Context) {
func (e Gen) GetDBTableList(c *gin.Context) {
//var res response.Response
var data tools.DBTables
var err error
+19 -95
View File
@@ -83,7 +83,7 @@ func (e Gen) Preview(c *gin.Context) {
return
}
tab, _ := table.Get(db)
tab, _ := table.Get(db,false)
var b1 bytes.Buffer
err = t1.Execute(&b1, tab)
var b2 bytes.Buffer
@@ -129,13 +129,9 @@ func (e Gen) GenCode(c *gin.Context) {
}
table.TableId = id
tab, _ := table.Get(db)
tab, _ := table.Get(db,false)
if tab.IsActions == 1 {
e.ActionsGen(c, tab)
} else {
e.NOActionsGen(c, tab)
}
e.NOActionsGen(c, tab)
e.OK("", "Code generated successfully!")
}
@@ -159,7 +155,7 @@ func (e Gen) GenApiToFile(c *gin.Context) {
}
table.TableId = id
tab, _ := table.Get(db)
tab, _ := table.Get(db,false)
e.genApiToFile(c, tab)
e.OK("", "Code generated successfully!")
@@ -224,8 +220,8 @@ func (e Gen) NOActionsGen(c *gin.Context, tab tools.SysTables) {
_ = pkg.PathCreate("./app/" + tab.PackageName + "/models/")
_ = pkg.PathCreate("./app/" + tab.PackageName + "/router/")
_ = pkg.PathCreate("./app/" + tab.PackageName + "/service/dto/")
_ = pkg.PathCreate(config.GenConfig.FrontPath + "/api/" + tab.PackageName+ "/")
err = pkg.PathCreate(config.GenConfig.FrontPath + "/views/" + tab.PackageName + "/" + tab.MLTBName+ "/")
_ = pkg.PathCreate(config.GenConfig.FrontPath + "/api/" + tab.PackageName + "/")
err = pkg.PathCreate(config.GenConfig.FrontPath + "/views/" + tab.PackageName + "/" + tab.MLTBName + "/")
if err != nil {
log.Error(err)
e.Error(500, err, fmt.Sprintf("views目录创建失败!错误详情:%s", err.Error()))
@@ -285,78 +281,6 @@ func (e Gen) genApiToFile(c *gin.Context, tab tools.SysTables) {
}
func (e Gen) ActionsGen(c *gin.Context, tab tools.SysTables) {
err := e.MakeContext(c).
MakeOrm().
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
basePath := "template/v4/"
routerFile := basePath + "actions/router_check_role.go.template"
if tab.IsAuth == 2 {
routerFile = basePath + "actions/router_no_check_role.go.template"
}
t1, err := template.ParseFiles(basePath + "model.go.template")
if err != nil {
e.Logger.Error(err)
e.Error(500, err, fmt.Sprintf("model模版解析失败!错误详情:%s", err.Error()))
return
}
t3, err := template.ParseFiles(routerFile)
if err != nil {
e.Logger.Error(err)
e.Error(500, err, fmt.Sprintf("路由模版解析失败!错误详情:%s", err.Error()))
return
}
t4, err := template.ParseFiles(basePath + "js.go.template")
if err != nil {
e.Logger.Error(err)
e.Error(500, err, fmt.Sprintf("js模版解析失败!错误详情:%s", err.Error()))
return
}
t5, err := template.ParseFiles(basePath + "vue.go.template")
if err != nil {
e.Logger.Error(err)
e.Error(500, err, fmt.Sprintf("vue模版解析失败!错误详情:%s", err.Error()))
return
}
t6, err := template.ParseFiles(basePath + "dto.go.template")
if err != nil {
e.Logger.Error(err)
e.Error(500, err, fmt.Sprintf("dto模版解析失败!错误详情:%s", err.Error()))
return
}
_ = pkg.PathCreate("./app/" + tab.PackageName + "/models/")
_ = pkg.PathCreate("./app/" + tab.PackageName + "/router/")
_ = pkg.PathCreate("./app/" + tab.PackageName + "/service/dto/")
_ = pkg.PathCreate(config.GenConfig.FrontPath + "/api/")
_ = pkg.PathCreate(config.GenConfig.FrontPath + "/views/" + tab.ModuleFrontName)
var b1 bytes.Buffer
err = t1.Execute(&b1, tab)
var b3 bytes.Buffer
err = t3.Execute(&b3, tab)
var b4 bytes.Buffer
err = t4.Execute(&b4, tab)
var b5 bytes.Buffer
err = t5.Execute(&b5, tab)
var b6 bytes.Buffer
err = t6.Execute(&b6, tab)
pkg.FileCreate(b1, "./app/"+tab.PackageName+"/models/"+tab.ModuleName+".go")
pkg.FileCreate(b3, "./app/"+tab.PackageName+"/router/"+tab.ModuleName+".go")
pkg.FileCreate(b4, config.GenConfig.FrontPath+"/api/"+tab.ModuleFrontName+".js")
pkg.FileCreate(b5, config.GenConfig.FrontPath+"/views/"+tab.ModuleFrontName+"/index.vue")
pkg.FileCreate(b6, "./app/"+tab.PackageName+"/service/dto/"+tab.ModuleName+".go")
}
func (e Gen) GenMenuAndApi(c *gin.Context) {
s := service.SysMenu{}
err := e.MakeContext(c).
@@ -378,13 +302,13 @@ func (e Gen) GenMenuAndApi(c *gin.Context) {
}
table.TableId = id
tab, _ := table.Get(e.Orm)
tab, _ := table.Get(e.Orm,true)
tab.MLTBName = strings.Replace(tab.TBName, "_", "-", -1)
Mmenu := dto.SysMenuControl{}
Mmenu := dto.SysMenuInsertReq{}
Mmenu.Title = tab.TableComment
Mmenu.Icon = "pass"
Mmenu.Path = "/" +tab.MLTBName
Mmenu.Path = "/" + tab.MLTBName
Mmenu.MenuType = "M"
Mmenu.Action = "无"
Mmenu.ParentId = 0
@@ -396,14 +320,14 @@ func (e Gen) GenMenuAndApi(c *gin.Context) {
Mmenu.CreateBy = 1
s.Insert(&Mmenu)
Cmenu := dto.SysMenuControl{}
Cmenu := dto.SysMenuInsertReq{}
Cmenu.MenuName = tab.ClassName + "Manage"
Cmenu.Title = tab.TableComment
Cmenu.Icon = "pass"
Cmenu.Path = "/" + tab.PackageName + "/" + tab.MLTBName
Cmenu.MenuType = "C"
Cmenu.Action = "无"
Cmenu.Permission = tab.PackageName + ":" + tab.ModuleFrontName + ":list"
Cmenu.Permission = tab.PackageName + ":" + tab.BusinessName + ":list"
Cmenu.ParentId = Mmenu.MenuId
Cmenu.NoCache = false
Cmenu.Component = "/" + tab.PackageName + "/" + tab.MLTBName + "/index"
@@ -414,14 +338,14 @@ func (e Gen) GenMenuAndApi(c *gin.Context) {
Cmenu.UpdateBy = 1
s.Insert(&Cmenu)
MList := dto.SysMenuControl{}
MList := dto.SysMenuInsertReq{}
MList.MenuName = ""
MList.Title = "分页获取" + tab.TableComment
MList.Icon = ""
MList.Path = tab.TBName
MList.MenuType = "F"
MList.Action = "无"
MList.Permission = tab.PackageName + ":" + tab.ModuleFrontName + ":query"
MList.Permission = tab.PackageName + ":" + tab.BusinessName + ":query"
MList.ParentId = Cmenu.MenuId
MList.NoCache = false
MList.Sort = 0
@@ -431,14 +355,14 @@ func (e Gen) GenMenuAndApi(c *gin.Context) {
MList.UpdateBy = 1
s.Insert(&MList)
MCreate := dto.SysMenuControl{}
MCreate := dto.SysMenuInsertReq{}
MCreate.MenuName = ""
MCreate.Title = "创建" + tab.TableComment
MCreate.Icon = ""
MCreate.Path = tab.TBName
MCreate.MenuType = "F"
MCreate.Action = "无"
MCreate.Permission = tab.PackageName + ":" + tab.ModuleFrontName + ":add"
MCreate.Permission = tab.PackageName + ":" + tab.BusinessName + ":add"
MCreate.ParentId = Cmenu.MenuId
MCreate.NoCache = false
MCreate.Sort = 0
@@ -448,14 +372,14 @@ func (e Gen) GenMenuAndApi(c *gin.Context) {
MCreate.UpdateBy = 1
s.Insert(&MCreate)
MUpdate := dto.SysMenuControl{}
MUpdate := dto.SysMenuInsertReq{}
MUpdate.MenuName = ""
MUpdate.Title = "修改" + tab.TableComment
MUpdate.Icon = ""
MUpdate.Path = tab.TBName
MUpdate.MenuType = "F"
MUpdate.Action = "无"
MUpdate.Permission = tab.PackageName + ":" + tab.ModuleFrontName + ":edit"
MUpdate.Permission = tab.PackageName + ":" + tab.BusinessName + ":edit"
MUpdate.ParentId = Cmenu.MenuId
MUpdate.NoCache = false
MUpdate.Sort = 0
@@ -465,14 +389,14 @@ func (e Gen) GenMenuAndApi(c *gin.Context) {
MUpdate.UpdateBy = 1
s.Insert(&MUpdate)
MDelete := dto.SysMenuControl{}
MDelete := dto.SysMenuInsertReq{}
MDelete.MenuName = ""
MDelete.Title = "删除" + tab.TableComment
MDelete.Icon = ""
MDelete.Path = tab.TBName
MDelete.MenuType = "F"
MDelete.Action = "无"
MDelete.Permission = tab.PackageName + ":" + tab.ModuleFrontName + ":remove"
MDelete.Permission = tab.PackageName + ":" + tab.BusinessName + ":remove"
MDelete.ParentId = Cmenu.MenuId
MDelete.NoCache = false
MDelete.Sort = 0
+15 -7
View File
@@ -79,7 +79,7 @@ func (e SysTable) Get(c *gin.Context) {
var data tools.SysTables
data.TableId, _ = pkg.StringToInt(c.Param("tableId"))
result, err := data.Get(db)
result, err := data.Get(db,true)
if err != nil {
log.Errorf("Get error, %s", err.Error())
e.Error(500, err, "")
@@ -106,7 +106,7 @@ func (e SysTable) GetSysTablesInfo(c *gin.Context) {
if c.Request.FormValue("tableName") != "" {
data.TBName = c.Request.FormValue("tableName")
}
result, err := data.Get(db)
result, err := data.Get(db,true)
if err != nil {
log.Errorf("Get error, %s", err.Error())
e.Error(500, err, "抱歉未找到相关信息")
@@ -202,15 +202,23 @@ func genTableInit(tx *gorm.DB, tablesList []string, i int, c *gin.Context) (tool
for i := 0; i < len(tablenamelist); i++ {
strStart := string([]byte(tablenamelist[i])[:1])
strend := string([]byte(tablenamelist[i])[1:])
// 大驼峰表名 结构体使用
data.ClassName += strings.ToUpper(strStart) + strend
// 小驼峰表名 js函数名和权限标识使用
if i == 0 {
data.BusinessName += strings.ToLower(strStart) + strend
} else {
data.BusinessName += strings.ToUpper(strStart) + strend
}
//data.PackageName += strings.ToLower(strStart) + strings.ToLower(strend)
data.ModuleName += strings.ToLower(strStart) + strings.ToLower(strend)
//data.ModuleName += strings.ToLower(strStart) + strings.ToLower(strend)
}
data.ModuleFrontName = strings.ReplaceAll(data.ModuleName, "_", "-")
//data.ModuleFrontName = strings.ReplaceAll(data.ModuleName, "_", "-")
data.PackageName = "admin"
data.TplCategory = "crud"
data.Crud = true
// 中横线表名称,接口路径、前端文件夹名称和js名称使用
data.ModuleName = strings.Replace(data.TBName, "_", "-", -1)
dbcolumn, err := dbColumn.GetList(tx)
data.CreateBy = 0
data.TableComment = dbtable.TableComment
@@ -219,7 +227,7 @@ func genTableInit(tx *gorm.DB, tablesList []string, i int, c *gin.Context) (tool
}
data.FunctionName = data.TableComment
data.BusinessName = data.ModuleName
//data.BusinessName = data.ModuleName
data.IsLogicalDelete = "1"
data.LogicalDelete = true
data.LogicalDeleteColumn = "is_del"
@@ -350,4 +358,4 @@ func (e SysTable) Delete(c *gin.Context) {
return
}
e.OK(nil, "删除成功")
}
}
+53 -44
View File
@@ -1,62 +1,71 @@
package tools
import (
"go-admin/app/admin/models"
common "go-admin/common/models"
"gorm.io/gorm"
)
type SysColumns struct {
ColumnId int `gorm:"primaryKey;autoIncrement" json:"columnId"`
TableId int `gorm:"" json:"tableId"`
ColumnName string `gorm:"size:128;" json:"columnName"`
ColumnComment string `gorm:"column:column_comment;size:128;" json:"columnComment"`
ColumnType string `gorm:"column:column_type;size:128;" json:"columnType"`
GoType string `gorm:"column:go_type;size:128;" json:"goType"`
GoField string `gorm:"column:go_field;size:128;" json:"goField"`
JsonField string `gorm:"column:json_field;size:128;" json:"jsonField"`
IsPk string `gorm:"column:is_pk;size:4;" json:"isPk"`
IsIncrement string `gorm:"column:is_increment;size:4;" json:"isIncrement"`
IsRequired string `gorm:"column:is_required;size:4;" json:"isRequired"`
IsInsert string `gorm:"column:is_insert;size:4;" json:"isInsert"`
IsEdit string `gorm:"column:is_edit;size:4;" json:"isEdit"`
IsList string `gorm:"column:is_list;size:4;" json:"isList"`
IsQuery string `gorm:"column:is_query;size:4;" json:"isQuery"`
QueryType string `gorm:"column:query_type;size:128;" json:"queryType"`
HtmlType string `gorm:"column:html_type;size:128;" json:"htmlType"`
DictType string `gorm:"column:dict_type;size:128;" json:"dictType"`
Sort int `gorm:"column:sort;" json:"sort"`
List string `gorm:"column:list;size:1;" json:"list"`
Pk bool `gorm:"column:pk;size:1;" json:"pk"`
Required bool `gorm:"column:required;size:1;" json:"required"`
SuperColumn bool `gorm:"column:super_column;size:1;" json:"superColumn"`
UsableColumn bool `gorm:"column:usable_column;size:1;" json:"usableColumn"`
Increment bool `gorm:"column:increment;size:1;" json:"increment"`
Insert bool `gorm:"column:insert;size:1;" json:"insert"`
Edit bool `gorm:"column:edit;size:1;" json:"edit"`
Query bool `gorm:"column:query;size:1;" json:"query"`
Remark string `gorm:"column:remark;size:255;" json:"remark"`
FkTableName string `gorm:"" json:"fkTableName"`
FkTableNameClass string `gorm:"" json:"fkTableNameClass"`
FkTableNamePackage string `gorm:"" json:"fkTableNamePackage"`
FkCol []SysColumns `gorm:"-" json:"fkCol"`
FkLabelId string `gorm:"" json:"fkLabelId"`
FkLabelName string `gorm:"size:255;" json:"fkLabelName"`
CreateBy int `gorm:"column:create_by;size:20;" json:"createBy"`
UpdateBy int `gorm:"column:update_By;size:20;" json:"updateBy"`
ColumnId int `gorm:"primaryKey;autoIncrement" json:"columnId"`
TableId int `gorm:"" json:"tableId"`
ColumnName string `gorm:"size:128;" json:"columnName"`
ColumnComment string `gorm:"column:column_comment;size:128;" json:"columnComment"`
ColumnType string `gorm:"column:column_type;size:128;" json:"columnType"`
GoType string `gorm:"column:go_type;size:128;" json:"goType"`
GoField string `gorm:"column:go_field;size:128;" json:"goField"`
JsonField string `gorm:"column:json_field;size:128;" json:"jsonField"`
IsPk string `gorm:"column:is_pk;size:4;" json:"isPk"`
IsIncrement string `gorm:"column:is_increment;size:4;" json:"isIncrement"`
IsRequired string `gorm:"column:is_required;size:4;" json:"isRequired"`
IsInsert string `gorm:"column:is_insert;size:4;" json:"isInsert"`
IsEdit string `gorm:"column:is_edit;size:4;" json:"isEdit"`
IsList string `gorm:"column:is_list;size:4;" json:"isList"`
IsQuery string `gorm:"column:is_query;size:4;" json:"isQuery"`
QueryType string `gorm:"column:query_type;size:128;" json:"queryType"`
HtmlType string `gorm:"column:html_type;size:128;" json:"htmlType"`
DictType string `gorm:"column:dict_type;size:128;" json:"dictType"`
Sort int `gorm:"column:sort;" json:"sort"`
List string `gorm:"column:list;size:1;" json:"list"`
Pk bool `gorm:"column:pk;size:1;" json:"pk"`
Required bool `gorm:"column:required;size:1;" json:"required"`
SuperColumn bool `gorm:"column:super_column;size:1;" json:"superColumn"`
UsableColumn bool `gorm:"column:usable_column;size:1;" json:"usableColumn"`
Increment bool `gorm:"column:increment;size:1;" json:"increment"`
Insert bool `gorm:"column:insert;size:1;" json:"insert"`
Edit bool `gorm:"column:edit;size:1;" json:"edit"`
Query bool `gorm:"column:query;size:1;" json:"query"`
Remark string `gorm:"column:remark;size:255;" json:"remark"`
FkTableName string `gorm:"" json:"fkTableName"`
FkTableNameClass string `gorm:"" json:"fkTableNameClass"`
FkTableNamePackage string `gorm:"" json:"fkTableNamePackage"`
FkCol []SysColumns `gorm:"-" json:"fkCol"`
FkLabelId string `gorm:"" json:"fkLabelId"`
FkLabelName string `gorm:"size:255;" json:"fkLabelName"`
CreateBy int `gorm:"column:create_by;size:20;" json:"createBy"`
UpdateBy int `gorm:"column:update_By;size:20;" json:"updateBy"`
models.BaseModel
common.ModelTime
}
func (SysColumns) TableName() string {
func (*SysColumns) TableName() string {
return "sys_columns"
}
func (e *SysColumns) GetList(tx *gorm.DB) ([]SysColumns, error) {
func (e *SysColumns) GetList(tx *gorm.DB, exclude bool) ([]SysColumns, error) {
var doc []SysColumns
table := tx.Table("sys_columns")
table = table.Where("table_id = ?", e.TableId)
table = table.Where("table_id = ? ", e.TableId)
if exclude {
notIn := make([]string, 0, 6)
notIn = append(notIn, "id")
notIn = append(notIn, "create_by")
notIn = append(notIn, "update_by")
notIn = append(notIn, "created_at")
notIn = append(notIn, "updated_at")
notIn = append(notIn, "deleted_at")
table = table.Where(" column_name not in(?)", notIn)
}
if err := table.Find(&doc).Error; err != nil {
return nil, err
+4 -8
View File
@@ -5,8 +5,6 @@ import (
"strings"
"gorm.io/gorm"
"go-admin/app/admin/models"
)
type SysTables struct {
@@ -43,11 +41,9 @@ type SysTables struct {
DataScope string `gorm:"-" json:"dataScope"`
Params Params `gorm:"-" json:"params"`
Columns []SysColumns `gorm:"-" json:"columns"`
models.BaseModel
}
func (SysTables) TableName() string {
func (*SysTables) TableName() string {
return "sys_tables"
}
@@ -78,7 +74,7 @@ func (e *SysTables) GetPage(tx *gorm.DB, pageSize int, pageIndex int) ([]SysTabl
return doc, int(count), nil
}
func (e *SysTables) Get(tx *gorm.DB) (SysTables, error) {
func (e *SysTables) Get(tx *gorm.DB, exclude bool) (SysTables, error) {
var doc SysTables
var err error
table := tx.Table("sys_tables")
@@ -98,7 +94,7 @@ func (e *SysTables) Get(tx *gorm.DB) (SysTables, error) {
}
var col SysColumns
col.TableId = doc.TableId
if doc.Columns, err = col.GetList(tx); err != nil {
if doc.Columns, err = col.GetList(tx, exclude); err != nil {
return doc, err
}
@@ -127,7 +123,7 @@ func (e *SysTables) GetTree(tx *gorm.DB) ([]SysTables, error) {
var col SysColumns
//col.FkCol = append(col.FkCol, SysColumns{ColumnId: 0, ColumnName: "请选择"})
col.TableId = doc[i].TableId
if doc[i].Columns, err = col.GetList(tx); err != nil {
if doc[i].Columns, err = col.GetList(tx, false); err != nil {
return doc, err
}
+8
View File
@@ -0,0 +1,8 @@
package api
import "go-admin/app/demo/router"
func init() {
//注册路由 fixme 其他应用的路由,在本目录新建文件放在init方法
AppRouters = append(AppRouters, router.InitRouter)
}
+25 -22
View File
@@ -3,7 +3,6 @@ package api
import (
"context"
"fmt"
"log"
"net/http"
"os"
"os/signal"
@@ -11,11 +10,12 @@ import (
"github.com/gin-gonic/gin"
"github.com/go-admin-team/go-admin-core/config/source/file"
log "github.com/go-admin-team/go-admin-core/logger"
"github.com/go-admin-team/go-admin-core/sdk"
"github.com/go-admin-team/go-admin-core/sdk/api"
"github.com/go-admin-team/go-admin-core/sdk/config"
"github.com/go-admin-team/go-admin-core/sdk/pkg"
"github.com/go-admin-team/go-admin-core/sdk/runtime"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"go-admin/app/admin/models"
@@ -66,14 +66,14 @@ func setup() {
storage.Setup,
)
//注册监听函数
queue := sdk.Runtime.GetMemoryQueue("")
queue := sdk.Runtime.GetQueuePrefix("")
queue.Register(global.LoginLog, models.SaveLoginLog)
queue.Register(global.OperateLog, models.SaveOperaLog)
queue.Register(global.ApiCheck, models.SaveSysApi)
go queue.Run()
usageStr := `starting api server...`
log.Println(usageStr)
log.Info(usageStr)
}
func run() error {
@@ -89,41 +89,41 @@ func run() error {
srv := &http.Server{
Addr: fmt.Sprintf("%s:%d", config.ApplicationConfig.Host, config.ApplicationConfig.Port),
Handler: sdk.Runtime.GetEngine(),
ReadTimeout: time.Duration(config.ApplicationConfig.ReadTimeout) * time.Second,
WriteTimeout: time.Duration(config.ApplicationConfig.WriterTimeout) * time.Second,
}
go func() {
jobs.InitJob()
jobs.Setup(sdk.Runtime.GetDb())
jobs.Setup(sdk.Runtime.GetAllDb())
}()
if apiCheck {
var routers = sdk.Runtime.GetRouter()
q := sdk.Runtime.GetMemoryQueue("")
mp := make(map[string]interface{}, 0)
q := sdk.Runtime.GetQueuePrefix("")
mp := make(map[string]interface{})
mp["List"] = routers
message, err := sdk.Runtime.GetStreamMessage("", global.ApiCheck, mp)
if err != nil {
log.Printf("GetStreamMessage error, %s \n", err.Error())
log.Infof("GetStreamMessage error, %s \n", err.Error())
//日志报错错误,不中断请求
} else {
err = q.Append(message)
if err != nil {
log.Printf("Append message error, %s \n", err.Error())
log.Infof("Append message error, %s \n", err.Error())
}
}
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
go func() {
// 服务连接
if config.SslConfig.Enable {
if err := srv.ListenAndServeTLS(config.SslConfig.Pem, config.SslConfig.KeyStr); err != nil && err != http.ErrServerClosed {
if err := srv.ListenAndServeTLS(config.SslConfig.Pem, config.SslConfig.KeyStr); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal("listen: ", err)
}
} else {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal("listen: ", err)
}
}
@@ -131,27 +131,30 @@ func run() error {
fmt.Println(pkg.Red(string(global.LogoContent)))
tip()
fmt.Println(pkg.Green("Server run at:"))
fmt.Printf("- Local: http://localhost:%d/ \r\n", config.ApplicationConfig.Port)
fmt.Printf("- Network: http://%s:%d/ \r\n", pkg.GetLocaHonst(), config.ApplicationConfig.Port)
fmt.Printf("- Local: %s://localhost:%d/ \r\n", "http", config.ApplicationConfig.Port)
fmt.Printf("- Network: %s://%s:%d/ \r\n", "http", pkg.GetLocalHost(), config.ApplicationConfig.Port)
fmt.Println(pkg.Green("Swagger run at:"))
fmt.Printf("- Local: http://localhost:%d/swagger/index.html \r\n", config.ApplicationConfig.Port)
fmt.Printf("- Network: http://%s:%d/swagger/index.html \r\n", pkg.GetLocaHonst(), config.ApplicationConfig.Port)
fmt.Printf("- Local: http://localhost:%d/swagger/admin/index.html \r\n", config.ApplicationConfig.Port)
fmt.Printf("- Network: %s://%s:%d/swagger/admin/index.html \r\n", "http", pkg.GetLocalHost(), config.ApplicationConfig.Port)
fmt.Printf("%s Enter Control + C Shutdown Server \r\n", pkg.GetCurrentTimeStr())
// 等待中断信号以优雅地关闭服务器(设置 5 秒的超时时间)
quit := make(chan os.Signal)
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)
<-quit
fmt.Printf("%s Shutdown Server ... \r\n", pkg.GetCurrentTimeStr())
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
log.Info("Shutdown Server ... ")
if err := srv.Shutdown(ctx); err != nil {
log.Fatal("Server Shutdown:", err)
}
log.Println("Server exiting")
log.Info("Server exiting")
return nil
}
var Router runtime.Router
//var Router runtime.Router
func tip() {
usageStr := `欢迎使用 ` + pkg.Green(`go-admin `+global.Version) + ` 可以使用 ` + pkg.Red(`-h`) + ` 查看命令`
@@ -170,7 +173,7 @@ func initRouter() {
r = h.(*gin.Engine)
default:
log.Fatal("not support other engine")
os.Exit(-1)
//os.Exit(-1)
}
if config.SslConfig.Enable {
r.Use(handler.TlsHandler())
+90
View File
@@ -0,0 +1,90 @@
package app
import (
"bytes"
"errors"
"fmt"
"github.com/go-admin-team/go-admin-core/sdk/pkg"
"github.com/go-admin-team/go-admin-core/sdk/pkg/utils"
"github.com/spf13/cobra"
"text/template"
)
var (
appName string
StartCmd = &cobra.Command{
Use: "app",
Short: "Create a new app",
Long: "Use when you need to create a new app",
Example: "go-admin app -n admin",
Run: func(cmd *cobra.Command, args []string) {
run()
},
}
)
func init() {
StartCmd.PersistentFlags().StringVarP(&appName, "name", "n", "", "Start server with provided configuration file")
}
func run() {
fmt.Println(`start init`)
//1. 读取配置
fmt.Println(`generate migration file`)
_ = genFile()
}
func genFile() error {
if appName == "" {
return errors.New("arg `name` invalid :name is empty")
}
path := "app/"
appPath := path + appName
err := utils.IsNotExistMkDir(appPath)
if err != nil {
return err
}
apiPath := appPath + "/apis/"
err = utils.IsNotExistMkDir(apiPath)
if err != nil {
return err
}
modelsPath := appPath + "/models/"
err = utils.IsNotExistMkDir(modelsPath)
if err != nil {
return err
}
routerPath := appPath + "/router/"
err = utils.IsNotExistMkDir(routerPath)
if err != nil {
return err
}
servicePath := appPath + "/service/"
err = utils.IsNotExistMkDir(servicePath)
if err != nil {
return err
}
dtoPath := appPath + "/service/dto/"
err = utils.IsNotExistMkDir(dtoPath)
if err != nil {
return err
}
t1, err := template.ParseFiles("template/cmd_api.template")
if err != nil {
return err
}
m := map[string]string{}
m["appName"] = appName
var b1 bytes.Buffer
err = t1.Execute(&b1, m)
pkg.FileCreate(b1, "./cmd/api/"+appName+".go")
t2, err := template.ParseFiles("template/router.template")
var b2 bytes.Buffer
err = t2.Execute(&b2, nil)
pkg.FileCreate(b2, appPath+"/router/router.go")
return nil
}
+3 -1
View File
@@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"github.com/go-admin-team/go-admin-core/sdk/pkg"
"go-admin/cmd/app"
"go-admin/common/global"
"os"
@@ -35,7 +36,7 @@ var rootCmd = &cobra.Command{
func tip() {
usageStr := `欢迎使用 ` + pkg.Green(`go-admin `+global.Version) + ` 可以使用 ` + pkg.Red(`-h`) + ` 查看命令`
usageStr1 := `也可以参考 https://doc.go-admin.dev/guide/ksks.html 里边的【启动】章节`
usageStr1 := `也可以参考 https://doc.go-admin.dev/guide/ksks 的相关内容`
fmt.Printf("%s\n", usageStr)
fmt.Printf("%s\n", usageStr1)
}
@@ -45,6 +46,7 @@ func init() {
rootCmd.AddCommand(migrate.StartCmd)
rootCmd.AddCommand(version.StartCmd)
rootCmd.AddCommand(config.StartCmd)
rootCmd.AddCommand(app.StartCmd)
}
//Execute : apply commands
+10 -12
View File
@@ -4,20 +4,18 @@ import (
"log"
"path/filepath"
"sort"
"strconv"
"sync"
"github.com/spf13/cast"
"gorm.io/gorm"
)
var Migrate = &Migration{
version: make(map[int]func(db *gorm.DB, version string) error),
version: make(map[string]func(db *gorm.DB, version string) error),
}
type Migration struct {
db *gorm.DB
version map[int]func(db *gorm.DB, version string) error
version map[string]func(db *gorm.DB, version string) error
mutex sync.Mutex
}
@@ -29,24 +27,24 @@ func (e *Migration) SetDb(db *gorm.DB) {
e.db = db
}
func (e *Migration) SetVersion(k int, f func(db *gorm.DB, version string) error) {
func (e *Migration) SetVersion(k string, f func(db *gorm.DB, version string) error) {
e.mutex.Lock()
defer e.mutex.Unlock()
e.version[k] = f
}
func (e *Migration) Migrate() {
versions := make([]int, 0)
versions := make([]string, 0)
for k := range e.version {
versions = append(versions, k)
}
if !sort.IntsAreSorted(versions) {
sort.Ints(versions)
if !sort.StringsAreSorted(versions) {
sort.Strings(versions)
}
var err error
var count int64
for _, v := range versions {
err = e.db.Debug().Table("sys_migration").Where("version = ?", v).Count(&count).Error
err = e.db.Table("sys_migration").Where("version = ?", v).Count(&count).Error
if err != nil {
log.Fatalln(err)
}
@@ -55,14 +53,14 @@ func (e *Migration) Migrate() {
count = 0
continue
}
err = (e.version[v])(e.db.Debug(), strconv.Itoa(v))
err = (e.version[v])(e.db.Debug(), v)
if err != nil {
log.Fatalln(err)
}
}
}
func GetFilename(s string) int {
func GetFilename(s string) string {
s = filepath.Base(s)
return cast.ToInt(s[:13])
return s[:13]
}
+9 -8
View File
@@ -1,14 +1,15 @@
package models
//sys_casbin_rule
// CasbinRule sys_casbin_rule
type CasbinRule struct {
PType string `json:"p_type" gorm:"size:100;"`
V0 string `json:"v0" gorm:"size:100;"`
V1 string `json:"v1" gorm:"size:100;"`
V2 string `json:"v2" gorm:"size:100;"`
V3 string `json:"v3" gorm:"size:100;"`
V4 string `json:"v4" gorm:"size:100;"`
V5 string `json:"v5" gorm:"size:100;"`
ID uint `gorm:"primaryKey;autoIncrement"`
Ptype string `gorm:"size:512;uniqueIndex:unique_index"`
V0 string `gorm:"size:512;uniqueIndex:unique_index"`
V1 string `gorm:"size:512;uniqueIndex:unique_index"`
V2 string `gorm:"size:512;uniqueIndex:unique_index"`
V3 string `gorm:"size:512;uniqueIndex:unique_index"`
V4 string `gorm:"size:512;uniqueIndex:unique_index"`
V5 string `gorm:"size:512;uniqueIndex:unique_index"`
}
func (CasbinRule) TableName() string {
+20 -3
View File
@@ -3,18 +3,35 @@ package models
import (
"fmt"
"go-admin/common/global"
"gorm.io/gorm"
"io/ioutil"
"log"
"strings"
"gorm.io/gorm"
)
func InitDb(db *gorm.DB) (err error) {
filePath := "config/db.sql"
err = ExecSql(db, filePath)
if global.Driver == "postgres" {
filePath := "config/db.sql"
if err = ExecSql(db, filePath); err != nil {
return err
}
filePath = "config/pg.sql"
err = ExecSql(db, filePath)
} else if global.Driver == "mysql" {
filePath = "config/db-begin-mysql.sql"
if err = ExecSql(db, filePath); err != nil {
return err
}
filePath = "config/db.sql"
if err = ExecSql(db, filePath); err != nil {
return err
}
filePath = "config/db-end-mysql.sql"
err = ExecSql(db, filePath)
} else {
err = ExecSql(db, filePath)
}
return err
}
@@ -31,7 +48,7 @@ func ExecSql(db *gorm.DB, filePath string) error {
fmt.Println(sqlList[i])
continue
}
sql := strings.Replace(sqlList[i]+";", "\n", "", 0)
sql := strings.Replace(sqlList[i]+";", "\n", "", -1)
sql = strings.TrimSpace(sql)
if err = db.Exec(sql).Error; err != nil {
log.Printf("error sql: %s", sql)
@@ -1,6 +1,5 @@
package models
//sys_role_dept
type SysRoleDept struct {
RoleId int `gorm:"size:11;primaryKey"`
DeptId int `gorm:"size:11;primaryKey"`
@@ -10,15 +10,15 @@ type SysOperaLog struct {
BusinessType string `json:"businessType" gorm:"type:varchar(128);comment:操作类型"`
BusinessTypes string `json:"businessTypes" gorm:"type:varchar(128);comment:BusinessTypes"`
Method string `json:"method" gorm:"type:varchar(128);comment:函数"`
RequestMethod string `json:"requestMethod" gorm:"type:varchar(128);comment:请求方式"`
RequestMethod string `json:"requestMethod" gorm:"type:varchar(128);comment:请求方式: GET POST PUT DELETE"`
OperatorType string `json:"operatorType" gorm:"type:varchar(128);comment:操作类型"`
OperName string `json:"operName" gorm:"type:varchar(128);comment:操作者"`
DeptName string `json:"deptName" gorm:"type:varchar(128);comment:部门名称"`
OperUrl string `json:"operUrl" gorm:"type:varchar(255);comment:访问地址"`
OperIp string `json:"operIp" gorm:"type:varchar(128);comment:客户端ip"`
OperLocation string `json:"operLocation" gorm:"type:varchar(128);comment:访问位置"`
OperParam string `json:"operParam" gorm:"type:varchar(255);comment:请求参数"`
Status string `json:"status" gorm:"type:varchar(4);comment:操作状态"`
OperParam string `json:"operParam" gorm:"type:text;comment:请求参数"`
Status string `json:"status" gorm:"type:varchar(4);comment:操作状态 1:正常 2:关闭"`
OperTime time.Time `json:"operTime" gorm:"type:timestamp;comment:操作时间"`
JsonResult string `json:"jsonResult" gorm:"type:varchar(255);comment:返回数据"`
Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"`
+5 -5
View File
@@ -11,20 +11,20 @@ type SysUser struct {
Password string `json:"-" gorm:"type:varchar(128);comment:密码"`
NickName string `json:"nickName" gorm:"type:varchar(128);comment:昵称"`
Phone string `json:"phone" gorm:"type:varchar(11);comment:手机号"`
RoleId int `json:"roleId" gorm:"type:bigint(20);comment:角色ID"`
RoleId int `json:"roleId" gorm:"type:bigint;comment:角色ID"`
Salt string `json:"-" gorm:"type:varchar(255);comment:加盐"`
Avatar string `json:"avatar" gorm:"type:varchar(255);comment:头像"`
Sex string `json:"sex" gorm:"type:varchar(255);comment:性别"`
Email string `json:"email" gorm:"type:varchar(128);comment:邮箱"`
DeptId int `json:"deptId" gorm:"type:bigint(20);comment:部门"`
PostId int `json:"postId" gorm:"type:bigint(20);comment:岗位"`
DeptId int `json:"deptId" gorm:"type:bigint;comment:部门"`
PostId int `json:"postId" gorm:"type:bigint;comment:岗位"`
Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"`
Status string `json:"status" gorm:"type:varchar(4);comment:状态"`
ControlBy
ModelTime
}
func (SysUser) TableName() string {
func (*SysUser) TableName() string {
return "sys_user"
}
@@ -45,4 +45,4 @@ func (e *SysUser) Encrypt() (err error) {
func (e *SysUser) BeforeCreate(_ *gorm.DB) error {
return e.Encrypt()
}
}

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