From 49828f2766f7208804e6d556be6a22f444b4a2cb Mon Sep 17 00:00:00 2001
From: wserver/wangdisen <1065498738@qq.com>
Date: Wed, 23 Nov 2022 16:58:19 +0800
Subject: [PATCH] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E6=AC=A1=E6=8F=90=E4=BA=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 26 +
LICENSE | 201 ++++
README.MD | 166 +++
api/v1/common/captcha.go | 19 +
api/v1/common/req.go | 22 +
api/v1/common/upload.go | 38 +
api/v1/demo/demo.go | 18 +
api/v1/system/sys_auth_rule.go | 111 ++
api/v1/system/sys_config.go | 71 ++
api/v1/system/sys_dept.go | 71 ++
api/v1/system/sys_dict_data.go | 93 ++
api/v1/system/sys_dict_type.go | 70 ++
api/v1/system/sys_init.go | 66 ++
api/v1/system/sys_login.go | 37 +
api/v1/system/sys_login_log.go | 47 +
api/v1/system/sys_monitor.go | 11 +
api/v1/system/sys_post.go | 61 +
api/v1/system/sys_role.go | 81 ++
api/v1/system/sys_user.go | 121 ++
go.mod | 54 +
go.sum | 230 ++++
internal/cmd/cmd.go | 44 +
internal/consts/cache.go | 42 +
internal/consts/consts.go | 5 +
internal/consts/consts_openapi.go | 8 +
internal/consts/context.go | 13 +
internal/consts/upload.go | 19 +
internal/consts/version.go | 12 +
internal/controller/base.go | 19 +
internal/controller/captcha.go | 32 +
internal/controller/demo.go | 24 +
internal/controller/sys_auth_rule.go | 79 ++
internal/controller/sys_config.go | 50 +
internal/controller/sys_dept.go | 60 +
internal/controller/sys_dict_data.go | 54 +
internal/controller/sys_dict_type.go | 49 +
internal/controller/sys_init.go | 73 ++
internal/controller/sys_login.go | 101 ++
internal/controller/sys_login_log.go | 35 +
internal/controller/sys_monitor.go | 142 +++
internal/controller/sys_post.go | 44 +
internal/controller/sys_role.go | 62 +
internal/controller/sys_user.go | 95 ++
internal/controller/upload.go | 87 ++
internal/dao/casbin_rule.go | 27 +
internal/dao/internal/casbin_rule.go | 85 ++
internal/dao/internal/sys_auth_rule.go | 115 ++
internal/dao/internal/sys_config.go | 91 ++
internal/dao/internal/sys_dept.go | 99 ++
internal/dao/internal/sys_dict_data.go | 99 ++
internal/dao/internal/sys_dict_type.go | 89 ++
internal/dao/internal/sys_login_log.go | 91 ++
internal/dao/internal/sys_oper_log.go | 103 ++
internal/dao/internal/sys_post.go | 93 ++
internal/dao/internal/sys_role.go | 87 ++
internal/dao/internal/sys_role_dept.go | 75 ++
internal/dao/internal/sys_user.go | 113 ++
internal/dao/internal/sys_user_online.go | 87 ++
internal/dao/internal/sys_user_post.go | 75 ++
internal/dao/sys_auth_rule.go | 27 +
internal/dao/sys_config.go | 27 +
internal/dao/sys_dept.go | 27 +
internal/dao/sys_dict_data.go | 27 +
internal/dao/sys_dict_type.go | 27 +
internal/dao/sys_login_log.go | 27 +
internal/dao/sys_oper_log.go | 27 +
internal/dao/sys_post.go | 27 +
internal/dao/sys_role.go | 27 +
internal/dao/sys_role_dept.go | 27 +
internal/dao/sys_user.go | 27 +
internal/dao/sys_user_online.go | 27 +
internal/dao/sys_user_post.go | 27 +
internal/model/context.go | 16 +
internal/model/do/casbin_rule.go | 21 +
internal/model/do/sys_auth_rule.go | 37 +
internal/model/do/sys_config.go | 25 +
internal/model/do/sys_dept.go | 29 +
internal/model/do/sys_dict_data.go | 29 +
internal/model/do/sys_dict_type.go | 24 +
internal/model/do/sys_login_log.go | 25 +
internal/model/do/sys_oper_log.go | 31 +
internal/model/do/sys_post.go | 26 +
internal/model/do/sys_role.go | 23 +
internal/model/do/sys_role_dept.go | 16 +
internal/model/do/sys_user.go | 36 +
internal/model/do/sys_user_online.go | 23 +
internal/model/do/sys_user_post.go | 16 +
internal/model/entity/casbin_rule.go | 16 +
internal/model/entity/sys_auth_rule.go | 35 +
internal/model/entity/sys_config.go | 23 +
internal/model/entity/sys_dept.go | 27 +
internal/model/entity/sys_dict_data.go | 27 +
internal/model/entity/sys_dict_type.go | 22 +
internal/model/entity/sys_login_log.go | 23 +
internal/model/entity/sys_oper_log.go | 29 +
internal/model/entity/sys_post.go | 24 +
internal/model/entity/sys_role.go | 21 +
internal/model/entity/sys_role_dept.go | 11 +
internal/model/entity/sys_user.go | 34 +
internal/model/entity/sys_user_online.go | 21 +
internal/model/entity/sys_user_post.go | 11 +
internal/model/sys_auth_rule.go | 59 +
internal/model/sys_config.go | 8 +
internal/model/sys_dept.go | 15 +
internal/model/sys_dict_data.go | 21 +
internal/model/sys_dict_type.go | 19 +
internal/model/sys_init.go | 39 +
internal/model/sys_role.go | 8 +
internal/model/sys_user.go | 41 +
internal/model/sys_user_login.go | 18 +
internal/model/token.go | 32 +
internal/packed/packed.go | 1 +
internal/router/router.go | 86 ++
internal/service/cache.go | 55 +
internal/service/captcha.go | 51 +
internal/service/casbin.go | 238 ++++
internal/service/context.go | 72 ++
internal/service/middleware.go | 137 +++
internal/service/sys_auth_rule.go | 325 ++++++
internal/service/sys_config.go | 184 +++
internal/service/sys_dept.go | 169 +++
internal/service/sys_dict_data.go | 178 +++
internal/service/sys_dict_type.go | 172 +++
internal/service/sys_init.go | 239 ++++
internal/service/sys_login_log.go | 109 ++
internal/service/sys_post.go | 116 ++
internal/service/sys_role.go | 197 ++++
internal/service/sys_user.go | 626 ++++++++++
internal/service/token.go | 82 ++
internal/service/upload.go | 306 +++++
library/libResponse/response.go | 107 ++
library/libUtils/utils.go | 173 +++
library/liberr/err.go | 30 +
main.go | 27 +
manifest/config/config.yaml.bak | 93 ++
manifest/config/initialize.yaml | 4 +
.../deploy/kustomize/base/deployment.yaml | 21 +
.../deploy/kustomize/base/kustomization.yaml | 8 +
manifest/deploy/kustomize/base/service.yaml | 12 +
.../kustomize/overlays/develop/configmap.yaml | 14 +
.../overlays/develop/deployment.yaml | 10 +
.../overlays/develop/kustomization.yaml | 14 +
manifest/docker/Dockerfile | 19 +
manifest/docker/docker.sh | 8 +
resource/casbin/rbac_model.conf | 14 +
resource/casbin/rbac_policy.csv | 5 +
resource/data/.gitkeep | 0
resource/data/gfast-v3.sql | 1025 +++++++++++++++++
resource/i18n/.gitkeep | 0
resource/public/html/.gitkeep | 0
resource/public/plugin/.gitkeep | 0
resource/public/resource/css/.gitkeep | 0
resource/public/resource/demo.html | 10 +
resource/public/resource/image/.gitkeep | 0
resource/public/resource/js/.gitkeep | 0
resource/scripts/.gitkeep | 0
resource/template/.gitkeep | 0
utility/.gitkeep | 0
158 files changed, 10341 insertions(+)
create mode 100644 .gitignore
create mode 100644 LICENSE
create mode 100644 README.MD
create mode 100644 api/v1/common/captcha.go
create mode 100644 api/v1/common/req.go
create mode 100644 api/v1/common/upload.go
create mode 100644 api/v1/demo/demo.go
create mode 100644 api/v1/system/sys_auth_rule.go
create mode 100644 api/v1/system/sys_config.go
create mode 100644 api/v1/system/sys_dept.go
create mode 100644 api/v1/system/sys_dict_data.go
create mode 100644 api/v1/system/sys_dict_type.go
create mode 100644 api/v1/system/sys_init.go
create mode 100644 api/v1/system/sys_login.go
create mode 100644 api/v1/system/sys_login_log.go
create mode 100644 api/v1/system/sys_monitor.go
create mode 100644 api/v1/system/sys_post.go
create mode 100644 api/v1/system/sys_role.go
create mode 100644 api/v1/system/sys_user.go
create mode 100644 go.mod
create mode 100644 go.sum
create mode 100644 internal/cmd/cmd.go
create mode 100644 internal/consts/cache.go
create mode 100644 internal/consts/consts.go
create mode 100644 internal/consts/consts_openapi.go
create mode 100644 internal/consts/context.go
create mode 100644 internal/consts/upload.go
create mode 100644 internal/consts/version.go
create mode 100644 internal/controller/base.go
create mode 100644 internal/controller/captcha.go
create mode 100644 internal/controller/demo.go
create mode 100644 internal/controller/sys_auth_rule.go
create mode 100644 internal/controller/sys_config.go
create mode 100644 internal/controller/sys_dept.go
create mode 100644 internal/controller/sys_dict_data.go
create mode 100644 internal/controller/sys_dict_type.go
create mode 100644 internal/controller/sys_init.go
create mode 100644 internal/controller/sys_login.go
create mode 100644 internal/controller/sys_login_log.go
create mode 100644 internal/controller/sys_monitor.go
create mode 100644 internal/controller/sys_post.go
create mode 100644 internal/controller/sys_role.go
create mode 100644 internal/controller/sys_user.go
create mode 100644 internal/controller/upload.go
create mode 100644 internal/dao/casbin_rule.go
create mode 100644 internal/dao/internal/casbin_rule.go
create mode 100644 internal/dao/internal/sys_auth_rule.go
create mode 100644 internal/dao/internal/sys_config.go
create mode 100644 internal/dao/internal/sys_dept.go
create mode 100644 internal/dao/internal/sys_dict_data.go
create mode 100644 internal/dao/internal/sys_dict_type.go
create mode 100644 internal/dao/internal/sys_login_log.go
create mode 100644 internal/dao/internal/sys_oper_log.go
create mode 100644 internal/dao/internal/sys_post.go
create mode 100644 internal/dao/internal/sys_role.go
create mode 100644 internal/dao/internal/sys_role_dept.go
create mode 100644 internal/dao/internal/sys_user.go
create mode 100644 internal/dao/internal/sys_user_online.go
create mode 100644 internal/dao/internal/sys_user_post.go
create mode 100644 internal/dao/sys_auth_rule.go
create mode 100644 internal/dao/sys_config.go
create mode 100644 internal/dao/sys_dept.go
create mode 100644 internal/dao/sys_dict_data.go
create mode 100644 internal/dao/sys_dict_type.go
create mode 100644 internal/dao/sys_login_log.go
create mode 100644 internal/dao/sys_oper_log.go
create mode 100644 internal/dao/sys_post.go
create mode 100644 internal/dao/sys_role.go
create mode 100644 internal/dao/sys_role_dept.go
create mode 100644 internal/dao/sys_user.go
create mode 100644 internal/dao/sys_user_online.go
create mode 100644 internal/dao/sys_user_post.go
create mode 100644 internal/model/context.go
create mode 100644 internal/model/do/casbin_rule.go
create mode 100644 internal/model/do/sys_auth_rule.go
create mode 100644 internal/model/do/sys_config.go
create mode 100644 internal/model/do/sys_dept.go
create mode 100644 internal/model/do/sys_dict_data.go
create mode 100644 internal/model/do/sys_dict_type.go
create mode 100644 internal/model/do/sys_login_log.go
create mode 100644 internal/model/do/sys_oper_log.go
create mode 100644 internal/model/do/sys_post.go
create mode 100644 internal/model/do/sys_role.go
create mode 100644 internal/model/do/sys_role_dept.go
create mode 100644 internal/model/do/sys_user.go
create mode 100644 internal/model/do/sys_user_online.go
create mode 100644 internal/model/do/sys_user_post.go
create mode 100644 internal/model/entity/casbin_rule.go
create mode 100644 internal/model/entity/sys_auth_rule.go
create mode 100644 internal/model/entity/sys_config.go
create mode 100644 internal/model/entity/sys_dept.go
create mode 100644 internal/model/entity/sys_dict_data.go
create mode 100644 internal/model/entity/sys_dict_type.go
create mode 100644 internal/model/entity/sys_login_log.go
create mode 100644 internal/model/entity/sys_oper_log.go
create mode 100644 internal/model/entity/sys_post.go
create mode 100644 internal/model/entity/sys_role.go
create mode 100644 internal/model/entity/sys_role_dept.go
create mode 100644 internal/model/entity/sys_user.go
create mode 100644 internal/model/entity/sys_user_online.go
create mode 100644 internal/model/entity/sys_user_post.go
create mode 100644 internal/model/sys_auth_rule.go
create mode 100644 internal/model/sys_config.go
create mode 100644 internal/model/sys_dept.go
create mode 100644 internal/model/sys_dict_data.go
create mode 100644 internal/model/sys_dict_type.go
create mode 100644 internal/model/sys_init.go
create mode 100644 internal/model/sys_role.go
create mode 100644 internal/model/sys_user.go
create mode 100644 internal/model/sys_user_login.go
create mode 100644 internal/model/token.go
create mode 100644 internal/packed/packed.go
create mode 100644 internal/router/router.go
create mode 100644 internal/service/cache.go
create mode 100644 internal/service/captcha.go
create mode 100644 internal/service/casbin.go
create mode 100644 internal/service/context.go
create mode 100644 internal/service/middleware.go
create mode 100644 internal/service/sys_auth_rule.go
create mode 100644 internal/service/sys_config.go
create mode 100644 internal/service/sys_dept.go
create mode 100644 internal/service/sys_dict_data.go
create mode 100644 internal/service/sys_dict_type.go
create mode 100644 internal/service/sys_init.go
create mode 100644 internal/service/sys_login_log.go
create mode 100644 internal/service/sys_post.go
create mode 100644 internal/service/sys_role.go
create mode 100644 internal/service/sys_user.go
create mode 100644 internal/service/token.go
create mode 100644 internal/service/upload.go
create mode 100644 library/libResponse/response.go
create mode 100644 library/libUtils/utils.go
create mode 100644 library/liberr/err.go
create mode 100644 main.go
create mode 100644 manifest/config/config.yaml.bak
create mode 100644 manifest/config/initialize.yaml
create mode 100644 manifest/deploy/kustomize/base/deployment.yaml
create mode 100644 manifest/deploy/kustomize/base/kustomization.yaml
create mode 100644 manifest/deploy/kustomize/base/service.yaml
create mode 100644 manifest/deploy/kustomize/overlays/develop/configmap.yaml
create mode 100644 manifest/deploy/kustomize/overlays/develop/deployment.yaml
create mode 100644 manifest/deploy/kustomize/overlays/develop/kustomization.yaml
create mode 100644 manifest/docker/Dockerfile
create mode 100644 manifest/docker/docker.sh
create mode 100644 resource/casbin/rbac_model.conf
create mode 100644 resource/casbin/rbac_policy.csv
create mode 100644 resource/data/.gitkeep
create mode 100644 resource/data/gfast-v3.sql
create mode 100644 resource/i18n/.gitkeep
create mode 100644 resource/public/html/.gitkeep
create mode 100644 resource/public/plugin/.gitkeep
create mode 100644 resource/public/resource/css/.gitkeep
create mode 100644 resource/public/resource/demo.html
create mode 100644 resource/public/resource/image/.gitkeep
create mode 100644 resource/public/resource/js/.gitkeep
create mode 100644 resource/scripts/.gitkeep
create mode 100644 resource/template/.gitkeep
create mode 100644 utility/.gitkeep
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4db9fe4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,26 @@
+.buildpath
+.hgignore.swp
+.project
+.orig
+.swp
+.idea/
+.settings/
+.vscode/
+vendor/
+composer.lock
+gitpush.sh
+pkg/
+bin/
+cbuild
+**/.DS_Store
+.vscode/
+.test/
+main
+output/
+manifest/output/
+*.exe
+tmp/
+resource/log/
+manifest/config/config.yaml
+GFastV3
+/manifest/config/db.yaml
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.MD b/README.MD
new file mode 100644
index 0000000..6abf245
--- /dev/null
+++ b/README.MD
@@ -0,0 +1,166 @@
+# GFast-V3
+
+
+
+
+## 平台简介
+* 基于全新Go Frame 2.0+Vue3+Element Plus开发的全栈前后端分离的管理系统
+* 前端采用vue-next-admin 、Vue、Element UI。
+* 本项目由奇讯科技团队开发。
+* 如您想购买云服务器请先领取阿里云优惠券:[点我进入](https://www.aliyun.com/minisite/goods?userCode=fcor2omk ),腾讯云优惠券:[点我领取](https://cloud.tencent.com/act/cps/redirect?redirect=1062&cps_key=20b1c3842f74986b2894e2c5fcde7ea2&from=console )
+
+## 特征
+* 高生产率:几分钟即可搭建一个后台管理系统
+* 模块化:单应用多系统的模式,将一个完整的应用拆分为多个系统,后续扩展更加便捷,增加代码复用性。
+* 插件化: 可通过插件的方式扩展系统功能
+* 认证机制:采用gtoken的用户状态认证及casbin的权限认证
+* 路由模式:得利于goframe2.0提供了规范化的路由注册方式,无需注解自动生成api文档
+* 面向接口开发
+
+
+## 内置功能
+
+1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
+2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
+3. 岗位管理:配置系统用户所属担任职务。
+4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。
+5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
+6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
+7. 参数管理:对系统动态配置常用参数。
+8. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
+9. 登录日志:系统登录日志记录查询包含登录异常。
+10. 在线用户:当前系统中活跃用户状态监控。
+11. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
+12. 代码生成:前后端代码的生成。
+13. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
+14. 在线构建器:拖动表单元素生成相应的HTML代码。
+15. 文件上传,缓存标签等。
+
+> 项目使用模块化与插件化的方式开发,目前正在升级的插件有:cms系统、万能模型、微信管理、工单系统、问答系统、工作流引擎...,同时也欢迎大家把写好的插件上传到商城,我们来帮您实现技术变现,获取收益!
+
+> GFast开源以来得到了大家的很多支持,如果您愿意为GFast贡献代码或提供建议,请加微信:qixun007(备注:gfast)
+
+## 演示地址
+[http://v3.g-fast.cn/sys](http://v3.g-fast.cn/sys)
+账号:demo 密码:123456
+## 配置
+项目数据库文件 `resource/data/db.sql` 创建数据库导入后修改配置 `manifest/config/config.yaml.bak` 复制改为`manifest/config/config.yaml`
+
+其中gfToken配置
+```yaml
+gfToken:
+ cacheKey: "gfToken_" #缓存前缀
+ timeOut: 10800 #token超时时间(秒)
+ maxRefresh: 5400 #token自动刷新时间(秒)
+ multiLogin: true #是否允许一个账号多人同时登录
+ encryptKey: "49c54195e750b04e74a8429b17896586" #加密key (32位)
+ cacheModel: "redis" #存储引擎 (memory使用内存|redis使用redis)
+ excludePaths: #排除不做登录验证的路由地址
+ - "/api/v1/system/login"
+```
+
+项目为前后端分离,前端地址:
+
+github地址:[https://tyj_admin-ui](https://tyj_admin-ui)
+
+gitee地址:[https://gitee.com/tiger1103/gfast-ui](https://gitee.com/tiger1103/gfast-ui)
+
+## 文档地址
+> 文档正在书写中,请耐心等一等。
+
+## 相关视频
+[https://space.bilibili.com/254192571/channel/seriesdetail?sid=223204](https://space.bilibili.com/254192571/channel/seriesdetail?sid=223204)
+
+## 演示图
+
+
+
+  |
+  |
+
+
+  |
+  |
+
+
+  |
+  |
+
+
+  |
+  |
+
+
+
+## 感谢(排名不分先后)
+> gf框架 [https://github.com/gogf/gf](https://github.com/gogf/gf)
+>
+> vue-next-admin [https://gitee.com/lyt-top/vue-next-admin](https://gitee.com/lyt-top/vue-next-admin)
+>
+> swaggo [https://github.com/swaggo/swag](https://github.com/swaggo/swag)
+>
+>gtoken [https://github.com/goflyfox/gtoken](https://github.com/goflyfox/gtoken)
+>
+>casbin [https://github.com/casbin/casbin](https://github.com/casbin/casbin)
+
+
+PHP开源工作流引擎tpflow [https://gitee.com/ntdgg/tpflow](https://gitee.com/ntdgg/tpflow)
+
+CCflow 国内最优秀的开源流程引擎 [https://gitee.com/opencc/ccflow](https://gitee.com/opencc/ccflow)
+
+## 交流QQ群
+
+>
+
+> 感谢你使用GFast,公司团队精力时间有限,因此我们不再提供免费的技术服务,目前Gfast QQ交流群有部分用户进行了捐赠,捐赠后请联系作者进vip用户群,vip群中问题将得到优先解答,同时也会根据您的需求进行分析和优先安排,vip群也会提供Gfast的其它福利。
+> 同时您也可以联系我们,雇佣我们团队为您干活,谢谢合作!
+>快来加入群聊【Gfast框架交流群】(1群:865697297-已满,2群:444129379),发现精彩内容,记得备注加群来意。
+
+## 免责声明:
+> 1、Gfast仅限自己学习使用,一切商业行为与Gfast无关。
+
+> 2、用户不得利用Gfast从事非法行为,用户应当合法合规的使用,发现用户在使用产品时有任何的非法行为,Gfast有权配合有关机关进行调查或向政府部门举报,Gfast不承担用户因非法行为造成的任何法律责任,一切法律责任由用户自行承担,如因用户使用造成第三方损害的,用户应当依法予以赔偿。
+
+> 3、所有与使用Gfast相关的资源直接风险均由用户承担。
+
+
+## 商用说明
+> 商用注意事项
+如果您将此项目用于商业用途,请遵守Apache2.0协议并保留作者技术支持声明。
+
+* GFast快速开发平台采用Apache-2.0技术协议
+* 二次开发如用于商业性质或开源竞品请不要删除和修改GFast源码头部的版权与作者声明及出处
+* 允许进行商用,但是不允许二次开源出来并进行收费
+* 我们已经申请了相关的软件著作权和相关登记(证书号:软著登字第7511736号)
+* 如果您在自己的项目中使用了我们项目中的扩展或模块,请在项目介绍中进行明确说明
+
+## 支持开源
+如果您喜爱gfast,请给常熬夜的作者来杯咖啡吧! 点我送咖啡
+
+## [感谢JetBrains提供的免费GoLand](https://jb.gg/OpenSource)
+[](https://jb.gg/OpenSource)
diff --git a/api/v1/common/captcha.go b/api/v1/common/captcha.go
new file mode 100644
index 0000000..8f8061d
--- /dev/null
+++ b/api/v1/common/captcha.go
@@ -0,0 +1,19 @@
+/*
+* @desc:验证码参数
+*
+*
+* @Date: 2022/3/2 17:47
+ */
+
+package common
+
+import "github.com/gogf/gf/v2/frame/g"
+
+type CaptchaReq struct {
+ g.Meta `path:"/get" tags:"验证码" method:"get" summary:"获取验证码"`
+}
+type CaptchaRes struct {
+ g.Meta `mime:"application/json"`
+ Key string `json:"key"`
+ Img string `json:"img"`
+}
diff --git a/api/v1/common/req.go b/api/v1/common/req.go
new file mode 100644
index 0000000..22d392b
--- /dev/null
+++ b/api/v1/common/req.go
@@ -0,0 +1,22 @@
+/*
+* @desc:公共接口相关
+*
+*
+* @Date: 2022/3/30 9:28
+ */
+
+package common
+
+// PageReq 公共请求参数
+type PageReq struct {
+ DateRange []string `p:"dateRange"` //日期范围
+ PageNum int `p:"pageNum"` //当前页码
+ PageSize int `p:"pageSize"` //每页数
+ OrderBy string //排序方式
+}
+
+// ListRes 列表公共返回
+type ListRes struct {
+ CurrentPage int `json:"currentPage"`
+ Total int `json:"total"`
+}
diff --git a/api/v1/common/upload.go b/api/v1/common/upload.go
new file mode 100644
index 0000000..9925364
--- /dev/null
+++ b/api/v1/common/upload.go
@@ -0,0 +1,38 @@
+package common
+
+import "github.com/gogf/gf/v2/frame/g"
+
+// 单图上传
+type UploadSingleImgReq struct {
+ g.Meta `path:"/singleImg" tags:"上传图片" method:"post" summary:"上传图片"`
+}
+
+// 单文件上传
+type UploadSingleFileReq struct {
+ g.Meta `path:"/singleFile" tags:"上传文件" method:"post" summary:"上传文件"`
+}
+
+type UploadSingleRes struct {
+ g.Meta `mime:"application/json"`
+ UploadResponse
+}
+
+// 多图上传
+type UploadMultipleImgReq struct {
+ g.Meta `path:"/multipleImg" tags:"上传多图片" method:"post" summary:"上传多图片"`
+}
+
+// 多文件上传
+type UploadMultipleFileReq struct {
+ g.Meta `path:"/multipleFile" tags:"上传多文件" method:"post" summary:"上传多文件"`
+}
+
+type UploadMultipleRes []*UploadResponse
+
+type UploadResponse struct {
+ Size int64 `json:"size"`
+ Path string `json:"path"`
+ FullPath string `json:"full_path"`
+ Name string `json:"name"`
+ Type string `json:"type"`
+}
diff --git a/api/v1/demo/demo.go b/api/v1/demo/demo.go
new file mode 100644
index 0000000..29d905d
--- /dev/null
+++ b/api/v1/demo/demo.go
@@ -0,0 +1,18 @@
+/*
+* @desc:demo
+*
+*
+* @Date: 2022/3/2 15:25
+ */
+
+package demo
+
+import "github.com/gogf/gf/v2/frame/g"
+
+type DmReq struct {
+ g.Meta `path:"/demo" tags:"Demo" method:"get" summary:"demo api"`
+}
+type DmRes struct {
+ g.Meta `mime:"text/html"`
+ Name string `json:"name"`
+}
diff --git a/api/v1/system/sys_auth_rule.go b/api/v1/system/sys_auth_rule.go
new file mode 100644
index 0000000..d614525
--- /dev/null
+++ b/api/v1/system/sys_auth_rule.go
@@ -0,0 +1,111 @@
+/*
+* @desc:菜单api
+*
+*
+* @Date: 2022/3/18 10:27
+ */
+
+package system
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "tyj_admin/internal/model/entity"
+ "tyj_admin/internal/model"
+)
+
+type RuleSearchReq struct {
+ g.Meta `path:"/menu/list" tags:"菜单管理" method:"get" summary:"菜单列表"`
+ Authorization string `p:"Authorization" in:"header" dc:"Bearer {{token}}"`
+ Title string `p:"menuName" `
+ Component string `p:"component"`
+}
+
+type RuleListRes struct {
+ g.Meta `mime:"application/json"`
+ Rules []*model.SysAuthRuleTreeRes `json:"rules"`
+}
+
+type RuleAddReq struct {
+ g.Meta `path:"/menu/add" tags:"菜单管理" method:"post" summary:"添加菜单"`
+ Authorization string `p:"Authorization" in:"header" dc:"Bearer {{token}}"`
+ MenuType uint `p:"menuType" v:"min:0|max:2#菜单类型最小值为:min|菜单类型最大值为:max"`
+ Pid uint `p:"parentId" v:"min:0"`
+ Name string `p:"name" v:"required#请填写规则名称"`
+ Title string `p:"menuName" v:"required|length:1,100#请填写标题|标题长度在:min到:max位"`
+ Icon string `p:"icon"`
+ Weigh int `p:"menuSort" `
+ Condition string `p:"condition" `
+ Remark string `p:"remark" `
+ IsHide uint `p:"isHide"`
+ Path string `p:"path"`
+ Redirect string `p:"redirect"` // 路由重定向
+ Roles []uint `p:"roles"` // 角色ids
+ Component string `p:"component" v:"required-if:menuType,1#组件路径不能为空"`
+ IsLink uint `p:"isLink"`
+ IsIframe uint `p:"isIframe"`
+ IsCached uint `p:"isKeepAlive"`
+ IsAffix uint `p:"isAffix"`
+ LinkUrl string `p:"linkUrl"`
+}
+
+type RuleAddRes struct {
+}
+
+type RuleGetParamsReq struct {
+ g.Meta `path:"/menu/getParams" tags:"菜单管理" method:"get" summary:"获取添加、编辑菜单相关参数"`
+ Authorization string `p:"Authorization" in:"header" dc:"Bearer {{token}}"`
+}
+
+type RuleGetParamsRes struct {
+ g.Meta `mime:"application/json"`
+ Roles []*entity.SysRole `json:"roles"`
+ Menus []*model.SysAuthRuleInfoRes `json:"menus"`
+}
+
+type RuleInfoReq struct {
+ g.Meta `path:"/menu/get" tags:"菜单管理" method:"get" summary:"获取菜单信息"`
+ Authorization string `p:"Authorization" in:"header" dc:"Bearer {{token}}"`
+ Id uint `p:"required#菜单id必须"`
+}
+
+type RuleInfoRes struct {
+ g.Meta `mime:"application/json"`
+ Rule *entity.SysAuthRule `json:"rule"`
+ RoleIds []uint `json:"roleIds"`
+}
+
+type RuleUpdateReq struct {
+ g.Meta `path:"/menu/update" tags:"菜单管理" method:"put" summary:"修改菜单"`
+ Authorization string `p:"Authorization" in:"header" dc:"Bearer {{token}}"`
+ Id uint `p:"id" v:"required#id必须"`
+ MenuType uint `p:"menuType" v:"min:0|max:2#菜单类型最小值为:min|菜单类型最大值为:max"`
+ Pid uint `p:"parentId" v:"min:0"`
+ Name string `p:"name" v:"required#请填写规则名称"`
+ Title string `p:"menuName" v:"required|length:1,100#请填写标题|标题长度在:min到:max位"`
+ Icon string `p:"icon"`
+ Weigh int `p:"menuSort" `
+ Condition string `p:"condition" `
+ Remark string `p:"remark" `
+ IsHide uint `p:"isHide"`
+ Path string `p:"path"`
+ Redirect string `p:"redirect"` // 路由重定向
+ Roles []uint `p:"roles"` // 角色ids
+ Component string `p:"component" v:"required-if:menuType,1#组件路径不能为空"`
+ IsLink uint `p:"isLink"`
+ IsIframe uint `p:"isIframe"`
+ IsCached uint `p:"isKeepAlive"`
+ IsAffix uint `p:"isAffix"`
+ LinkUrl string `p:"linkUrl"`
+}
+
+type RuleUpdateRes struct {
+}
+
+type RuleDeleteReq struct {
+ g.Meta `path:"/menu/delete" tags:"菜单管理" method:"delete" summary:"删除菜单"`
+ Authorization string `p:"Authorization" in:"header" dc:"Bearer {{token}}"`
+ Ids []int `p:"ids" v:"required#菜单id必须"`
+}
+
+type RuleDeleteRes struct {
+}
diff --git a/api/v1/system/sys_config.go b/api/v1/system/sys_config.go
new file mode 100644
index 0000000..2c7a15c
--- /dev/null
+++ b/api/v1/system/sys_config.go
@@ -0,0 +1,71 @@
+/*
+* @desc:系统参数配置
+*
+*
+* @Date: 2022/4/18 21:11
+ */
+
+package system
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ commonApi "tyj_admin/api/v1/common"
+ "tyj_admin/internal/model/entity"
+)
+
+type ConfigSearchReq struct {
+ g.Meta `path:"/config/list" tags:"系统参数管理" method:"get" summary:"系统参数列表"`
+ ConfigName string `p:"configName"` //参数名称
+ ConfigKey string `p:"configKey"` //参数键名
+ ConfigType string `p:"configType"` //状态
+ commonApi.PageReq
+}
+
+type ConfigSearchRes struct {
+ g.Meta `mime:"application/json"`
+ List []*entity.SysConfig `json:"list"`
+ commonApi.ListRes
+}
+
+type ConfigReq struct {
+ ConfigName string `p:"configName" v:"required#参数名称不能为空"`
+ ConfigKey string `p:"configKey" v:"required#参数键名不能为空"`
+ ConfigValue string `p:"configValue" v:"required#参数键值不能为空"`
+ ConfigType int `p:"configType" v:"required|in:0,1#系统内置不能为空|系统内置类型只能为0或1"`
+ Remark string `p:"remark"`
+}
+
+type ConfigAddReq struct {
+ g.Meta `path:"/config/add" tags:"系统参数管理" method:"post" summary:"添加系统参数"`
+ *ConfigReq
+}
+
+type ConfigAddRes struct {
+}
+
+type ConfigGetReq struct {
+ g.Meta `path:"/config/get" tags:"系统参数管理" method:"get" summary:"获取系统参数"`
+ Id int `p:"id"`
+}
+
+type ConfigGetRes struct {
+ g.Meta `mime:"application/json"`
+ Data *entity.SysConfig `json:"data"`
+}
+
+type ConfigEditReq struct {
+ g.Meta `path:"/config/edit" tags:"系统参数管理" method:"put" summary:"修改系统参数"`
+ ConfigId int64 `p:"configId" v:"required|min:1#主键ID不能为空|主键ID参数错误"`
+ *ConfigReq
+}
+
+type ConfigEditRes struct {
+}
+
+type ConfigDeleteReq struct {
+ g.Meta `path:"/config/delete" tags:"系统参数管理" method:"delete" summary:"删除系统参数"`
+ Ids []int `p:"ids"`
+}
+
+type ConfigDeleteRes struct {
+}
diff --git a/api/v1/system/sys_dept.go b/api/v1/system/sys_dept.go
new file mode 100644
index 0000000..eee0ab9
--- /dev/null
+++ b/api/v1/system/sys_dept.go
@@ -0,0 +1,71 @@
+/*
+* @desc:部门管理参数
+*
+*
+* @Date: 2022/4/6 15:07
+ */
+
+package system
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "tyj_admin/internal/model"
+ "tyj_admin/internal/model/entity"
+)
+
+type DeptSearchReq struct {
+ g.Meta `path:"/dept/list" tags:"部门管理" method:"get" summary:"部门列表"`
+ DeptName string `p:"deptName"`
+ Status string `p:"status"`
+}
+
+type DeptSearchRes struct {
+ g.Meta `mime:"application/json"`
+ DeptList []*entity.SysDept `json:"deptList"`
+}
+
+type DeptAddReq struct {
+ g.Meta `path:"/dept/add" tags:"部门管理" method:"post" summary:"添加部门"`
+ ParentID int `p:"parentId" v:"required#父级不能为空"`
+ DeptName string `p:"deptName" v:"required#部门名称不能为空"`
+ OrderNum int `p:"orderNum" v:"required#排序不能为空"`
+ Leader string `p:"leader"`
+ Phone string `p:"phone"`
+ Email string `p:"email" v:"email#邮箱格式不正确"`
+ Status uint `p:"status" v:"required#状态必须"`
+}
+
+type DeptAddRes struct {
+}
+
+type DeptEditReq struct {
+ g.Meta `path:"/dept/edit" tags:"部门管理" method:"put" summary:"修改部门"`
+ DeptId int `p:"deptId" v:"required#deptId不能为空"`
+ ParentID int `p:"parentId" v:"required#父级不能为空"`
+ DeptName string `p:"deptName" v:"required#部门名称不能为空"`
+ OrderNum int `p:"orderNum" v:"required#排序不能为空"`
+ Leader string `p:"leader"`
+ Phone string `p:"phone"`
+ Email string `p:"email" v:"email#邮箱格式不正确"`
+ Status uint `p:"status" v:"required#状态必须"`
+}
+
+type DeptEditRes struct {
+}
+
+type DeptDeleteReq struct {
+ g.Meta `path:"/dept/delete" tags:"部门管理" method:"delete" summary:"删除部门"`
+ Id int64 `p:"id" v:"required#id不能为空"`
+}
+
+type DeptDeleteRes struct {
+}
+
+type DeptTreeSelectReq struct {
+ g.Meta `path:"/dept/treeSelect" tags:"部门管理" method:"get" summary:"获取部门树形菜单"`
+}
+
+type DeptTreeSelectRes struct {
+ g.Meta `mime:"application/json"`
+ Deps []*model.SysDeptTreeRes `json:"deps"`
+}
diff --git a/api/v1/system/sys_dict_data.go b/api/v1/system/sys_dict_data.go
new file mode 100644
index 0000000..76225fe
--- /dev/null
+++ b/api/v1/system/sys_dict_data.go
@@ -0,0 +1,93 @@
+/*
+* @desc:字典数据api
+*
+*
+* @Date: 2022/3/18 11:59
+ */
+
+package system
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ commonApi "tyj_admin/api/v1/common"
+ "tyj_admin/internal/model"
+ "tyj_admin/internal/model/entity"
+)
+
+// GetDictReq 获取字典信息请求参数
+type GetDictReq struct {
+ g.Meta `path:"/dict/data/getDictData" tags:"字典管理" method:"get" summary:"获取字典数据公共方法"`
+ Authorization string `p:"Authorization" in:"header" dc:"Bearer {{token}}"`
+ DictType string `p:"dictType" v:"required#字典类型不能为空"`
+ DefaultValue string `p:"defaultValue"`
+}
+
+// GetDictRes 完整的一个字典信息
+type GetDictRes struct {
+ g.Meta `mime:"application/json"`
+ Info *model.DictTypeRes `json:"info"`
+ Values []*model.DictDataRes `json:"values"`
+}
+
+// DictDataSearchReq 分页请求参数
+type DictDataSearchReq struct {
+ g.Meta `path:"/dict/data/list" tags:"字典管理" method:"get" summary:"字典数据列表"`
+ DictType string `p:"dictType"` //字典类型
+ DictLabel string `p:"dictLabel"` //字典标签
+ Status string `p:"status"` //状态
+ commonApi.PageReq
+}
+
+// DictDataSearchRes 字典数据结果
+type DictDataSearchRes struct {
+ g.Meta `mime:"application/json"`
+ List []*entity.SysDictData `json:"list"`
+ commonApi.ListRes
+}
+
+type DictDataReq struct {
+ DictLabel string `p:"dictLabel" v:"required#字典标签不能为空"`
+ DictValue string `p:"dictValue" v:"required#字典键值不能为空"`
+ DictType string `p:"dictType" v:"required#字典类型不能为空"`
+ DictSort int `p:"dictSort" v:"integer#排序只能为整数"`
+ CssClass string `p:"cssClass"`
+ ListClass string `p:"listClass"`
+ IsDefault int `p:"isDefault" v:"required|in:0,1#系统默认不能为空|默认值只能为0或1"`
+ Status int `p:"status" v:"required|in:0,1#状态不能为空|状态只能为0或1"`
+ Remark string `p:"remark"`
+}
+
+type DictDataAddReq struct {
+ g.Meta `path:"/dict/data/add" tags:"字典管理" method:"post" summary:"添加字典数据"`
+ *DictDataReq
+}
+
+type DictDataAddRes struct {
+}
+
+type DictDataGetReq struct {
+ g.Meta `path:"/dict/data/get" tags:"字典管理" method:"get" summary:"获取字典数据"`
+ DictCode uint `p:"dictCode"`
+}
+
+type DictDataGetRes struct {
+ g.Meta `mime:"application/json"`
+ Dict *entity.SysDictData `json:"dict"`
+}
+
+type DictDataEditReq struct {
+ g.Meta `path:"/dict/data/edit" tags:"字典管理" method:"put" summary:"修改字典数据"`
+ DictCode int `p:"dictCode" v:"required|min:1#主键ID不能为空|主键ID不能小于1"`
+ *DictDataReq
+}
+
+type DictDataEditRes struct {
+}
+
+type DictDataDeleteReq struct {
+ g.Meta `path:"/dict/data/delete" tags:"字典管理" method:"delete" summary:"删除字典数据"`
+ Ids []int `p:"ids"`
+}
+
+type DictDataDeleteRes struct {
+}
diff --git a/api/v1/system/sys_dict_type.go b/api/v1/system/sys_dict_type.go
new file mode 100644
index 0000000..4164508
--- /dev/null
+++ b/api/v1/system/sys_dict_type.go
@@ -0,0 +1,70 @@
+/*
+* @desc:字典类型
+*
+*
+* @Date: 2022/4/14 21:30
+ */
+
+package system
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ commonApi "tyj_admin/api/v1/common"
+ "tyj_admin/internal/model"
+ "tyj_admin/internal/model/entity"
+)
+
+type DictTypeSearchReq struct {
+ g.Meta `path:"/dict/type/list" tags:"字典管理" method:"get" summary:"字典类型列表"`
+ DictName string `p:"dictName"` //字典名称
+ DictType string `p:"dictType"` //字典类型
+ Status string `p:"status"` //字典状态
+ commonApi.PageReq
+}
+
+type DictTypeSearchRes struct {
+ g.Meta `mime:"application/json"`
+ DictTypeList []*model.SysDictTypeInfoRes `json:"dictTypeList"`
+ commonApi.ListRes
+}
+
+type DictTypeAddReq struct {
+ g.Meta `path:"/dict/type/add" tags:"字典管理" method:"post" summary:"添加字典类型"`
+ DictName string `p:"dictName" v:"required#字典名称不能为空"`
+ DictType string `p:"dictType" v:"required#字典类型不能为空"`
+ Status uint `p:"status" v:"required|in:0,1#状态不能为空|状态只能为0或1"`
+ Remark string `p:"remark"`
+}
+
+type DictTypeAddRes struct {
+}
+
+type DictTypeGetReq struct {
+ g.Meta `path:"/dict/type/get" tags:"字典管理" method:"get" summary:"获取字典类型"`
+ DictId uint `p:"dictId" v:"required#类型id不能为空"`
+}
+
+type DictTypeGetRes struct {
+ g.Meta `mime:"application/json"`
+ DictType *entity.SysDictType `json:"dictType"`
+}
+
+type DictTypeEditReq struct {
+ g.Meta `path:"/dict/type/edit" tags:"字典管理" method:"put" summary:"修改字典类型"`
+ DictId int64 `p:"dictId" v:"required|min:1#主键ID不能为空|主键ID必须为大于0的值"`
+ DictName string `p:"dictName" v:"required#字典名称不能为空"`
+ DictType string `p:"dictType" v:"required#字典类型不能为空"`
+ Status uint `p:"status" v:"required|in:0,1#状态不能为空|状态只能为0或1"`
+ Remark string `p:"remark"`
+}
+
+type DictTypeEditRes struct {
+}
+
+type DictTypeDeleteReq struct {
+ g.Meta `path:"/dict/type/delete" tags:"字典管理" method:"delete" summary:"删除字典类型"`
+ DictIds []int `p:"dictIds" v:"required#字典类型id不能为空"`
+}
+
+type DictTypeDeleteRes struct {
+}
diff --git a/api/v1/system/sys_init.go b/api/v1/system/sys_init.go
new file mode 100644
index 0000000..1e2eba3
--- /dev/null
+++ b/api/v1/system/sys_init.go
@@ -0,0 +1,66 @@
+package system
+
+import (
+ "fmt"
+ "github.com/gogf/gf/v2/frame/g"
+ "tyj_admin/internal/model"
+)
+
+type DbInitIsInitReq struct {
+ g.Meta `path:"/dbInit/isInit" tags:"系统初始化" method:"get" summary:"系统初始化"`
+}
+
+type DbInitIsInitRes bool
+
+type DbInitGetEnvInfoReq struct {
+ g.Meta `path:"/dbInit/getEnvInfo" tags:"系统初始化" method:"get" summary:"获取环境信息"`
+}
+
+type DbInitGetEnvInfoRes g.Map
+
+type DbInitCreateDbReq struct {
+ g.Meta `path:"/dbInit/createDb" tags:"系统初始化" method:"post" summary:"创建配置文件"`
+ DbHost string `json:"dbHost" p:"dbHost" v:"required#数据库地址必须"`
+ DbPort int `json:"dbPort" p:"dbPort" v:"required#数据库端口必须"`
+ DbUser string `json:"dbUser" p:"dbUser" v:"required#数据库用户名称必须"`
+ DbPass string `json:"dbPass"`
+ DbName string `json:"dbName" p:"dbName" v:"required#数据库名称必须"`
+ DbCharset string `json:"dbCharset" p:"dbCharset" v:"required#数据库编码必须"`
+ RedisAddress string `json:"redisAddress" p:"redisAddress" v:"required#Redis地址必须"`
+ RedisPort int `json:"redisPort" p:"redisPort" v:"required#Redis端口必须"`
+ RedisDb int `json:"redisDb" p:"redisDb" v:"required#Redis索引必须"`
+ RedisPass string `json:"redisPass"`
+}
+
+type DbInitCreateDbRes bool
+
+func (req *DbInitCreateDbReq) ToDbInitConfig() *model.DbInitConfig {
+ return &model.DbInitConfig{
+ Database: model.Database{
+ Default: model.DbDefault{
+ Host: req.DbHost,
+ Port: req.DbPort,
+ User: req.DbUser,
+ Pass: req.DbPass,
+ Name: req.DbName,
+ Type: "mysql",
+ Role: "master",
+ Debug: true,
+ Charset: req.DbCharset,
+ DryRun: false,
+ MaxIdle: 10,
+ MaxOpen: 10,
+ MaxLifetime: 10,
+ },
+ },
+ Redis: model.Redis{
+ Default: model.RedisDefault{
+ Address: fmt.Sprintf("%s:%d", req.RedisAddress, req.RedisPort),
+ Db: req.RedisDb,
+ Pass: req.RedisPass,
+ IdleTimeout: 600,
+ MaxActive: 100,
+ },
+ },
+ }
+}
diff --git a/api/v1/system/sys_login.go b/api/v1/system/sys_login.go
new file mode 100644
index 0000000..eee9db0
--- /dev/null
+++ b/api/v1/system/sys_login.go
@@ -0,0 +1,37 @@
+/*
+* @desc:登录
+*
+*
+* @Date: 2022/4/27 21:51
+ */
+
+package system
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ model2 "tyj_admin/internal/model"
+)
+
+type UserLoginReq struct {
+ g.Meta `path:"/login" tags:"登录" method:"post" summary:"用户登录"`
+ Username string `p:"username" v:"required#用户名不能为空"`
+ Password string `p:"password" v:"required#密码不能为空"`
+ VerifyCode string `p:"verifyCode" v:"required#验证码不能为空"`
+ VerifyKey string `p:"verifyKey"`
+}
+
+type UserLoginRes struct {
+ g.Meta `mime:"application/json"`
+ UserInfo *model2.LoginUserRes `json:"userInfo"`
+ Token string `json:"token"`
+ MenuList []*model2.UserMenus `json:"menuList"`
+ Permissions []string `json:"permissions"`
+}
+
+type UserLoginOutReq struct {
+ g.Meta `path:"/loginOut" tags:"登录" method:"delete" summary:"退出登录"`
+ Authorization string `p:"Authorization" in:"header" dc:"Bearer {{token}}"`
+}
+
+type UserLoginOutRes struct {
+}
diff --git a/api/v1/system/sys_login_log.go b/api/v1/system/sys_login_log.go
new file mode 100644
index 0000000..8ecf56e
--- /dev/null
+++ b/api/v1/system/sys_login_log.go
@@ -0,0 +1,47 @@
+/*
+* @desc:登录日志
+*
+*
+* @Date: 2022/4/24 22:09
+ */
+
+package system
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ commonApi "tyj_admin/api/v1/common"
+ "tyj_admin/internal/model/entity"
+)
+
+// LoginLogSearchReq 查询列表请求参数
+type LoginLogSearchReq struct {
+ g.Meta `path:"/loginLog/list" tags:"登录日志管理" method:"get" summary:"日志列表"`
+ LoginName string `p:"userName"` //登陆名
+ Status string `p:"status"` //状态
+ Ipaddr string `p:"ipaddr"` //登录地址
+ SortName string `p:"orderByColumn"` //排序字段
+ SortOrder string `p:"isAsc"` //排序方式
+ LoginLocation string `p:"loginLocation"` //登录地点
+ commonApi.PageReq
+}
+
+type LoginLogSearchRes struct {
+ g.Meta `mime:"application/json"`
+ commonApi.ListRes
+ List []*entity.SysLoginLog `json:"list"`
+}
+
+type LoginLogDelReq struct {
+ g.Meta `path:"/loginLog/delete" tags:"登录日志管理" method:"delete" summary:"删除日志"`
+ Ids []int `p:"ids" v:"required#ids必须"`
+}
+
+type LoginLogDelRes struct {
+}
+
+type LoginLogClearReq struct {
+ g.Meta `path:"/loginLog/clear" tags:"登录日志管理" method:"delete" summary:"清除日志"`
+}
+
+type LoginLogClearRes struct {
+}
diff --git a/api/v1/system/sys_monitor.go b/api/v1/system/sys_monitor.go
new file mode 100644
index 0000000..d22ee1c
--- /dev/null
+++ b/api/v1/system/sys_monitor.go
@@ -0,0 +1,11 @@
+package system
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+type MonitorSearchReq struct {
+ g.Meta `path:"/monitor/server" tags:"服务监控" method:"get" summary:"服务监控"`
+}
+
+type MonitorSearchRes g.Map
diff --git a/api/v1/system/sys_post.go b/api/v1/system/sys_post.go
new file mode 100644
index 0000000..5bd424d
--- /dev/null
+++ b/api/v1/system/sys_post.go
@@ -0,0 +1,61 @@
+/*
+* @desc:岗位相关参数
+*
+*
+* @Date: 2022/4/7 23:09
+ */
+
+package system
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ commonApi "tyj_admin/api/v1/common"
+ "tyj_admin/internal/model/entity"
+)
+
+type PostSearchReq struct {
+ g.Meta `path:"/post/list" tags:"岗位管理" method:"get" summary:"岗位列表"`
+ PostCode string `p:"postCode"` //岗位编码
+ PostName string `p:"postName"` //岗位名称
+ Status string `p:"status"` //状态
+ commonApi.PageReq
+}
+
+type PostSearchRes struct {
+ g.Meta `mime:"application/json"`
+ commonApi.ListRes
+ PostList []*entity.SysPost `json:"postList"`
+}
+
+type PostAddReq struct {
+ g.Meta `path:"/post/add" tags:"岗位管理" method:"post" summary:"添加岗位"`
+ PostCode string `p:"postCode" v:"required#岗位编码不能为空"`
+ PostName string `p:"postName" v:"required#岗位名称不能为空"`
+ PostSort int `p:"postSort" v:"required#岗位排序不能为空"`
+ Status uint `p:"status" v:"required#状态不能为空"`
+ Remark string `p:"remark"`
+}
+
+type PostAddRes struct {
+}
+
+type PostEditReq struct {
+ g.Meta `path:"/post/edit" tags:"岗位管理" method:"put" summary:"修改岗位"`
+ PostId int64 `p:"postId" v:"required#id必须"`
+ PostCode string `p:"postCode" v:"required#岗位编码不能为空"`
+ PostName string `p:"postName" v:"required#岗位名称不能为空"`
+ PostSort int `p:"postSort" v:"required#岗位排序不能为空"`
+ Status uint `p:"status" v:"required#状态不能为空"`
+ Remark string `p:"remark"`
+}
+
+type PostEditRes struct {
+}
+
+type PostDeleteReq struct {
+ g.Meta `path:"/post/delete" tags:"岗位管理" method:"delete" summary:"删除岗位"`
+ Ids []int `p:"ids"`
+}
+
+type PostDeleteRes struct {
+}
diff --git a/api/v1/system/sys_role.go b/api/v1/system/sys_role.go
new file mode 100644
index 0000000..97327f7
--- /dev/null
+++ b/api/v1/system/sys_role.go
@@ -0,0 +1,81 @@
+/*
+* @desc:角色api
+*
+*
+* @Date: 2022/3/30 9:16
+ */
+
+package system
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ commonApi "tyj_admin/api/v1/common"
+ "tyj_admin/internal/model"
+ "tyj_admin/internal/model/entity"
+)
+
+type RoleListReq struct {
+ g.Meta `path:"/role/list" tags:"角色管理" method:"get" summary:"角色列表"`
+ RoleName string `p:"roleName"` //参数名称
+ Status string `p:"roleStatus"` //状态
+ commonApi.PageReq
+}
+
+type RoleListRes struct {
+ g.Meta `mime:"application/json"`
+ commonApi.ListRes
+ List []*entity.SysRole `json:"list"`
+}
+
+type RoleGetParamsReq struct {
+ g.Meta `path:"/role/getParams" tags:"角色管理" method:"get" summary:"角色编辑参数"`
+}
+
+type RoleGetParamsRes struct {
+ g.Meta `mime:"application/json"`
+ Menu []*model.SysAuthRuleInfoRes `json:"menu"`
+}
+
+type RoleAddReq struct {
+ g.Meta `path:"/role/add" tags:"角色管理" method:"post" summary:"添加角色"`
+ Name string `p:"name" v:"required#角色名称不能为空"`
+ Status uint `p:"status" `
+ ListOrder uint `p:"listOrder" `
+ Remark string `p:"remark" `
+ MenuIds []uint `p:"menuIds"`
+}
+
+type RoleAddRes struct {
+}
+
+type RoleGetReq struct {
+ g.Meta `path:"/role/get" tags:"角色管理" method:"get" summary:"获取角色信息"`
+ Id uint `p:"id" v:"required#角色id不能为空""`
+}
+
+type RoleGetRes struct {
+ g.Meta `mime:"application/json"`
+ Role *entity.SysRole `json:"role"`
+ MenuIds []int `json:"menuIds"`
+}
+
+type RoleEditReq struct {
+ g.Meta `path:"/role/edit" tags:"角色管理" method:"put" summary:"修改角色"`
+ Id int64 `p:"id" v:"required#角色id必须"`
+ Name string `p:"name" v:"required#角色名称不能为空"`
+ Status uint `p:"status" `
+ ListOrder uint `p:"listOrder" `
+ Remark string `p:"remark" `
+ MenuIds []uint `p:"menuIds"`
+}
+
+type RoleEditRes struct {
+}
+
+type RoleDeleteReq struct {
+ g.Meta `path:"/role/delete" tags:"角色管理" method:"delete" summary:"删除角色"`
+ Ids []int64 `p:"ids" v:"required#角色id不能为空"`
+}
+
+type RoleDeleteRes struct {
+}
diff --git a/api/v1/system/sys_user.go b/api/v1/system/sys_user.go
new file mode 100644
index 0000000..134ac0f
--- /dev/null
+++ b/api/v1/system/sys_user.go
@@ -0,0 +1,121 @@
+package system
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ commonApi "tyj_admin/api/v1/common"
+ "tyj_admin/internal/model"
+ "tyj_admin/internal/model/entity"
+)
+
+type UserMenusReq struct {
+ g.Meta `path:"/user/getUserMenus" tags:"用户管理" method:"get" summary:"获取用户菜单"`
+ Authorization string `p:"Authorization" in:"header" dc:"Bearer {{token}}"`
+}
+
+type UserMenusRes struct {
+ g.Meta `mime:"application/json"`
+ MenuList []*model.UserMenus `json:"menuList"`
+ Permissions []string `json:"permissions"`
+}
+
+// UserSearchReq 用户搜索请求参数
+type UserSearchReq struct {
+ g.Meta `path:"/user/list" tags:"用户管理" method:"get" summary:"用户列表"`
+ DeptId string `p:"deptId"` //部门id
+ Mobile string `p:"mobile"`
+ Status string `p:"status"`
+ KeyWords string `p:"keyWords"`
+ commonApi.PageReq
+}
+
+type UserSearchRes struct {
+ g.Meta `mime:"application/json"`
+ UserList []*model.SysUserRoleDeptRes `json:"userList"`
+ commonApi.ListRes
+}
+
+type UserGetParamsReq struct {
+ g.Meta `path:"/user/params" tags:"用户管理" method:"get" summary:"用户维护参数获取"`
+}
+
+type UserGetParamsRes struct {
+ g.Meta `mime:"application/json"`
+ RoleList []*entity.SysRole `json:"roleList"`
+ Posts []*entity.SysPost `json:"posts"`
+}
+
+// SetUserReq 添加修改用户公用请求字段
+type SetUserReq struct {
+ DeptId uint64 `p:"deptId" v:"required#用户部门不能为空"` //所属部门
+ Email string `p:"email" v:"email#邮箱格式错误"` //邮箱
+ NickName string `p:"nickName" v:"required#用户昵称不能为空"`
+ Mobile string `p:"mobile" v:"required|phone#手机号不能为空|手机号格式错误"`
+ PostIds []int64 `p:"postIds"`
+ Remark string `p:"remark"`
+ RoleIds []int64 `p:"roleIds"`
+ Sex int `p:"sex"`
+ Status uint `p:"status"`
+ IsAdmin int `p:"isAdmin"` // 是否后台管理员 1 是 0 否
+}
+
+// UserAddReq 添加用户参数
+type UserAddReq struct {
+ g.Meta `path:"/user/add" tags:"用户管理" method:"post" summary:"添加用户"`
+ *SetUserReq
+ UserName string `p:"userName" v:"required#用户账号不能为空"`
+ Password string `p:"password" v:"required|password#密码不能为空|密码以字母开头,只能包含字母、数字和下划线,长度在6~18之间"`
+ UserSalt string
+}
+
+type UserAddRes struct {
+}
+
+// UserEditReq 修改用户参数
+type UserEditReq struct {
+ g.Meta `path:"/user/edit" tags:"用户管理" method:"put" summary:"修改用户"`
+ *SetUserReq
+ UserId int64 `p:"userId" v:"required#用户id不能为空"`
+}
+
+type UserEditRes struct {
+}
+
+type UserGetEditReq struct {
+ g.Meta `path:"/user/getEdit" tags:"用户管理" method:"get" summary:"获取用户信息"`
+ Id uint64 `p:"id"`
+}
+
+type UserGetEditRes struct {
+ g.Meta `mime:"application/json"`
+ User *entity.SysUser `json:"user"`
+ CheckedRoleIds []uint `json:"checkedRoleIds"`
+ CheckedPosts []int64 `json:"checkedPosts"`
+}
+
+// UserResetPwdReq 重置用户密码状态参数
+type UserResetPwdReq struct {
+ g.Meta `path:"/user/resetPwd" tags:"用户管理" method:"put" summary:"重置用户密码"`
+ Id uint64 `p:"userId" v:"required#用户id不能为空"`
+ Password string `p:"password" v:"required|password#密码不能为空|密码以字母开头,只能包含字母、数字和下划线,长度在6~18之间"`
+}
+
+type UserResetPwdRes struct {
+}
+
+// UserStatusReq 设置用户状态参数
+type UserStatusReq struct {
+ g.Meta `path:"/user/setStatus" tags:"用户管理" method:"put" summary:"设置用户状态"`
+ Id uint64 `p:"userId" v:"required#用户id不能为空"`
+ UserStatus uint `p:"status" v:"required#用户状态不能为空"`
+}
+
+type UserStatusRes struct {
+}
+
+type UserDeleteReq struct {
+ g.Meta `path:"/user/delete" tags:"用户管理" method:"delete" summary:"删除用户"`
+ Ids []int `p:"ids"`
+}
+
+type UserDeleteRes struct {
+}
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..c33dea8
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,54 @@
+module tyj_admin
+
+go 1.19
+
+require (
+ github.com/casbin/casbin/v2 v2.57.0
+ github.com/gogf/gf/contrib/drivers/mysql/v2 v2.2.4
+ github.com/gogf/gf/v2 v2.2.4
+ github.com/mojocn/base64Captcha v1.3.5
+ github.com/mssola/user_agent v0.5.3
+ github.com/shirou/gopsutil v2.21.11+incompatible
+ github.com/tencentyun/cos-go-sdk-v5 v0.7.40
+ github.com/tiger1103/gfast-cache v0.1.1
+ github.com/tiger1103/gfast-token v1.0.1
+ gopkg.in/yaml.v3 v3.0.1
+)
+
+require (
+ github.com/BurntSushi/toml v1.1.0 // indirect
+ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect
+ github.com/cespare/xxhash/v2 v2.1.2 // indirect
+ github.com/clbanning/mxj v1.8.4 // indirect
+ github.com/clbanning/mxj/v2 v2.5.5 // indirect
+ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
+ github.com/fatih/color v1.13.0 // indirect
+ github.com/fsnotify/fsnotify v1.5.4 // indirect
+ github.com/go-logr/logr v1.2.3 // indirect
+ github.com/go-logr/stdr v1.2.2 // indirect
+ github.com/go-ole/go-ole v1.2.6 // indirect
+ github.com/go-redis/redis/v8 v8.11.5 // indirect
+ github.com/go-sql-driver/mysql v1.6.0 // indirect
+ github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
+ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
+ github.com/google/go-querystring v1.0.0 // indirect
+ github.com/gorilla/websocket v1.5.0 // indirect
+ github.com/grokify/html-strip-tags-go v0.0.1 // indirect
+ github.com/magiconair/properties v1.8.6 // indirect
+ github.com/mattn/go-colorable v0.1.9 // indirect
+ github.com/mattn/go-isatty v0.0.14 // indirect
+ github.com/mattn/go-runewidth v0.0.9 // indirect
+ github.com/mitchellh/mapstructure v1.4.3 // indirect
+ github.com/mozillazg/go-httpheader v0.2.1 // indirect
+ github.com/olekukonko/tablewriter v0.0.5 // indirect
+ github.com/tklauser/go-sysconf v0.3.11 // indirect
+ github.com/tklauser/numcpus v0.6.0 // indirect
+ github.com/yusufpapurcu/wmi v1.2.2 // indirect
+ go.opentelemetry.io/otel v1.7.0 // indirect
+ go.opentelemetry.io/otel/sdk v1.7.0 // indirect
+ go.opentelemetry.io/otel/trace v1.7.0 // indirect
+ golang.org/x/image v0.0.0-20190501045829-6d32002ffd75 // indirect
+ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
+ golang.org/x/sys v0.2.0 // indirect
+ golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 // indirect
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..678a394
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,230 @@
+github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
+github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
+github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
+github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
+github.com/casbin/casbin/v2 v2.57.0 h1:J7PTgUe13Ag5WzwZe2l/hpj0/hRKuQlqyO8+1+FAWug=
+github.com/casbin/casbin/v2 v2.57.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
+github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
+github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I=
+github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
+github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
+github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
+github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
+github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
+github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
+github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
+github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
+github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
+github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
+github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
+github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
+github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
+github.com/gogf/gf/contrib/drivers/mysql/v2 v2.2.4 h1:dUT1BbQ6RRiEDiBLj57jBx0y/WkD9KiDbmcCp9vE0w8=
+github.com/gogf/gf/contrib/drivers/mysql/v2 v2.2.4/go.mod h1:z+/0qiOwMroAnj5ESuobTv0l5P83rf+XR3r6Fj8WJyk=
+github.com/gogf/gf/v2 v2.0.0/go.mod h1:apktt6TleWtCIwpz63vBqUnw8MX8gWKoZyxgDpXFtgM=
+github.com/gogf/gf/v2 v2.2.4 h1:Y2c0F4dDDYlQswHPtoGJ0l9kvQjE0a9jmM02qCAZoqo=
+github.com/gogf/gf/v2 v2.2.4/go.mod h1:thvkyb43RWUu/m05sRm4CbH9r7t7/FrW2M56L9Ystwk=
+github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
+github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
+github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
+github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
+github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
+github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
+github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
+github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
+github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
+github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
+github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
+github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
+github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
+github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
+github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
+github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
+github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mojocn/base64Captcha v1.3.5 h1:Qeilr7Ta6eDtG4S+tQuZ5+hO+QHbiGAJdi4PfoagaA0=
+github.com/mojocn/base64Captcha v1.3.5/go.mod h1:/tTTXn4WTpX9CfrmipqRytCpJ27Uw3G6I7NcP2WwcmY=
+github.com/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSrwhe88TQQ=
+github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60=
+github.com/mssola/user_agent v0.5.3 h1:lBRPML9mdFuIZgI2cmlQ+atbpJdLdeVl2IDodjBR578=
+github.com/mssola/user_agent v0.5.3/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw=
+github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
+github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
+github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
+github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
+github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
+github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
+github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
+github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
+github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
+github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
+github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
+github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
+github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/shirou/gopsutil v2.21.11+incompatible h1:lOGOyCG67a5dv2hq5Z1BLDUqqKp3HkbjPcz5j6XMS0U=
+github.com/shirou/gopsutil v2.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.194/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.194/go.mod h1:yrBKWhChnDqNz1xuXdSbWXG56XawEq0G5j1lg4VwBD4=
+github.com/tencentyun/cos-go-sdk-v5 v0.7.40 h1:W6vDGKCHe4wBACI1d2UgE6+50sJFhRWU4O8IB2ozzxM=
+github.com/tencentyun/cos-go-sdk-v5 v0.7.40/go.mod h1:4dCEtLHGh8QPxHEkgq+nFaky7yZxQuYwgSJM87icDaw=
+github.com/tiger1103/gfast-cache v0.1.1 h1:qwhw0VUyr539lLmiJCNCoU2dDdHZxozHMuXlvaTPm5Q=
+github.com/tiger1103/gfast-cache v0.1.1/go.mod h1:jAmIERI//MmLpUcOI3+7axmSir+t/ufpVc2N3Ryw6VE=
+github.com/tiger1103/gfast-token v1.0.1 h1:507HTgEmq+dZ+TnFndy+hC+Ezj/jTQR74qhM85Szw/E=
+github.com/tiger1103/gfast-token v1.0.1/go.mod h1:TE1qxSWuEbFeBme5hM0x0EIoBNoxGi3J4yUAyKotRSA=
+github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
+github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
+github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
+github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
+github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM=
+go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
+go.opentelemetry.io/otel/sdk v1.7.0 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1B0=
+go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
+go.opentelemetry.io/otel/trace v1.7.0 h1:O37Iogk1lEkMRXewVtZ1BBTVn5JEp8GrJvP92bJqC6o=
+go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/image v0.0.0-20190501045829-6d32002ffd75 h1:TbGuee8sSq15Iguxu4deQ7+Bqq/d2rsQejGcEtADAMQ=
+golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
+golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
+golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y=
+golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go
new file mode 100644
index 0000000..50e270e
--- /dev/null
+++ b/internal/cmd/cmd.go
@@ -0,0 +1,44 @@
+package cmd
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/net/ghttp"
+ "github.com/gogf/gf/v2/net/goai"
+ "github.com/gogf/gf/v2/os/gcmd"
+ "tyj_admin/internal/consts"
+ "tyj_admin/internal/router"
+)
+
+var (
+ Main = gcmd.Command{
+ Name: "main",
+ Usage: "main",
+ Brief: "start http server",
+ Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
+ s := g.Server()
+ s.Group("/", func(group *ghttp.RouterGroup) {
+ router.BindController(group)
+ })
+ enhanceOpenAPIDoc(s)
+ s.Run()
+ return nil
+ },
+ }
+)
+
+func enhanceOpenAPIDoc(s *ghttp.Server) {
+ openapi := s.GetOpenApi()
+ openapi.Config.CommonResponse = ghttp.DefaultHandlerResponse{}
+ openapi.Config.CommonResponseDataField = `Data`
+
+ // API description.
+ openapi.Info = goai.Info{
+ Title: consts.OpenAPITitle,
+ Description: consts.OpenAPIDescription,
+ Contact: &goai.Contact{
+ Name: consts.OpenAPIContactName,
+ URL: consts.OpenAPIContactUrl,
+ },
+ }
+}
diff --git a/internal/consts/cache.go b/internal/consts/cache.go
new file mode 100644
index 0000000..ff71504
--- /dev/null
+++ b/internal/consts/cache.go
@@ -0,0 +1,42 @@
+/*
+* @desc:缓存键
+*
+*
+* @Date: 2022/3/9 12:06
+ */
+
+package consts
+
+const (
+ // CacheSysAuthMenu 缓存菜单key
+ CacheSysAuthMenu = "sysAuthMenu"
+ // CacheSysDept 缓存部门key
+ CacheSysDept = "sysDept"
+
+ // CacheSysRole 角色缓存key
+ CacheSysRole = "sysRole"
+ // CacheSysWebSet 站点配置缓存key
+ CacheSysWebSet = "sysWebSet"
+ // CacheSysCmsMenu cms缓存key
+ CacheSysCmsMenu = "sysCmsMenu"
+
+ // CacheSysAuthTag 权限缓存TAG标签
+ CacheSysAuthTag = "sysAuthTag"
+ // CacheSysModelTag 模型缓存标签
+ CacheSysModelTag = "sysModelTag"
+ // CacheSysCmsTag cms缓存标签
+ CacheSysCmsTag = "sysCmsTag"
+)
+
+const (
+ CacheModelMem = "memory"
+ CacheModelRedis = "redis"
+
+ // CacheSysDict 字典缓存菜单KEY
+ CacheSysDict = "sysDict"
+
+ // CacheSysDictTag 字典缓存标签
+ CacheSysDictTag = "sysDictTag"
+ // CacheSysConfigTag 系统参数配置
+ CacheSysConfigTag = "sysConfigTag"
+)
diff --git a/internal/consts/consts.go b/internal/consts/consts.go
new file mode 100644
index 0000000..c0c0da5
--- /dev/null
+++ b/internal/consts/consts.go
@@ -0,0 +1,5 @@
+package consts
+
+const (
+ PageSize = 10 //分页长度
+)
diff --git a/internal/consts/consts_openapi.go b/internal/consts/consts_openapi.go
new file mode 100644
index 0000000..0b1663b
--- /dev/null
+++ b/internal/consts/consts_openapi.go
@@ -0,0 +1,8 @@
+package consts
+
+const (
+ OpenAPITitle = `GFast-v3`
+ OpenAPIDescription = `基于 GoFrame2.0的后台管理系统。 Enjoy 💖 `
+ OpenAPIContactName = "GFast"
+ OpenAPIContactUrl = "http://www.g-fast.cn"
+)
diff --git a/internal/consts/context.go b/internal/consts/context.go
new file mode 100644
index 0000000..3a48d0b
--- /dev/null
+++ b/internal/consts/context.go
@@ -0,0 +1,13 @@
+/*
+* @desc:context 相关常量
+*
+*
+* @Date: 2022/3/16 14:52
+ */
+
+package consts
+
+const (
+ // CtxKey 上下文变量存储键名,前后端系统共享
+ CtxKey = "GFastContext"
+)
diff --git a/internal/consts/upload.go b/internal/consts/upload.go
new file mode 100644
index 0000000..af4f580
--- /dev/null
+++ b/internal/consts/upload.go
@@ -0,0 +1,19 @@
+package consts
+
+const (
+ UploadPath = "upload_file"
+ ImgTypeKey = "sys.uploadFile.imageType"
+ ImgSizeKey = "sys.uploadFile.imageSize"
+ FileTypeKey = "sys.uploadFile.fileType"
+ FileSizeKey = "sys.uploadFile.fileSize"
+ CheckFileTypeImg = "img" // 文件类型(图片)
+ CheckFileTypeFile = "file" // 文件类型(任意)
+)
+
+const (
+ SourceLocal = iota // 上传到本地
+ SourceTencent // 上传至腾讯云
+ SourceAli // 上传到阿里云
+ SourceQiniu // 上传到七牛云
+ //...................
+)
diff --git a/internal/consts/version.go b/internal/consts/version.go
new file mode 100644
index 0000000..8c24e97
--- /dev/null
+++ b/internal/consts/version.go
@@ -0,0 +1,12 @@
+/*
+* @desc:版本号
+*
+*
+* @Date: 2022/3/11 11:24
+ */
+
+package consts
+
+const (
+ Version = "3.0.0"
+)
diff --git a/internal/controller/base.go b/internal/controller/base.go
new file mode 100644
index 0000000..05da051
--- /dev/null
+++ b/internal/controller/base.go
@@ -0,0 +1,19 @@
+/*
+* @desc:system base controller
+*
+*
+* @Date: 2022/3/4 18:12
+ */
+
+package controller
+
+import (
+ "github.com/gogf/gf/v2/net/ghttp"
+)
+
+type BaseController struct {
+}
+
+// Init 自动执行的初始化方法
+func (c *BaseController) Init(r *ghttp.Request) {
+}
diff --git a/internal/controller/captcha.go b/internal/controller/captcha.go
new file mode 100644
index 0000000..0e1e4e6
--- /dev/null
+++ b/internal/controller/captcha.go
@@ -0,0 +1,32 @@
+/*
+* @desc:验证码获取
+*
+*
+* @Date: 2022/3/2 17:45
+ */
+
+package controller
+
+import (
+ "context"
+ "tyj_admin/api/v1/common"
+ "tyj_admin/internal/service"
+)
+
+var Captcha = captchaController{}
+
+type captchaController struct {
+}
+
+// Get 获取验证码
+func (c *captchaController) Get(ctx context.Context, req *common.CaptchaReq) (res *common.CaptchaRes, err error) {
+ var (
+ idKeyC, base64stringC string
+ )
+ idKeyC, base64stringC, err = service.Captcha().GetVerifyImgString(ctx)
+ res = &common.CaptchaRes{
+ Key: idKeyC,
+ Img: base64stringC,
+ }
+ return
+}
diff --git a/internal/controller/demo.go b/internal/controller/demo.go
new file mode 100644
index 0000000..4e7a8c2
--- /dev/null
+++ b/internal/controller/demo.go
@@ -0,0 +1,24 @@
+/*
+* @desc:demo
+*
+*
+* @Date: 2022/3/2 15:24
+ */
+
+package controller
+
+import (
+ "context"
+ "tyj_admin/api/v1/demo"
+)
+
+var Demo = cDemo{}
+
+type cDemo struct {
+}
+
+func (c *cDemo) Demo(ctx context.Context, req *demo.DmReq) (res *demo.DmRes, err error) {
+ res = &demo.DmRes{Name: "赵四"}
+ panic("demo wrong")
+ return
+}
diff --git a/internal/controller/sys_auth_rule.go b/internal/controller/sys_auth_rule.go
new file mode 100644
index 0000000..008503a
--- /dev/null
+++ b/internal/controller/sys_auth_rule.go
@@ -0,0 +1,79 @@
+/*
+* @desc:菜单
+*
+*
+* @Date: 2022/3/16 10:36
+ */
+
+package controller
+
+import (
+ "context"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/model"
+ "tyj_admin/internal/service"
+)
+
+var Menu = menuController{}
+
+type menuController struct {
+ BaseController
+}
+
+func (c *menuController) List(ctx context.Context, req *system.RuleSearchReq) (res *system.RuleListRes, err error) {
+ var list []*model.SysAuthRuleInfoRes
+ res = &system.RuleListRes{
+ Rules: make([]*model.SysAuthRuleTreeRes, 0),
+ }
+ list, err = service.Rule().GetMenuListSearch(ctx, req)
+ if req.Title != "" || req.Component != "" {
+ for _, menu := range list {
+ res.Rules = append(res.Rules, &model.SysAuthRuleTreeRes{
+ SysAuthRuleInfoRes: menu,
+ })
+ }
+ } else {
+ res.Rules = service.Rule().GetMenuListTree(0, list)
+ }
+ return
+}
+
+func (c *menuController) Add(ctx context.Context, req *system.RuleAddReq) (res *system.RuleAddRes, err error) {
+ err = service.Rule().Add(ctx, req)
+ return
+}
+
+// GetAddParams 获取菜单添加及编辑相关参数
+func (c *menuController) GetAddParams(ctx context.Context, req *system.RuleGetParamsReq) (res *system.RuleGetParamsRes, err error) {
+ // 获取角色列表
+ res = new(system.RuleGetParamsRes)
+ res.Roles, err = service.Role().GetRoleList(ctx)
+ if err != nil {
+ return
+ }
+ res.Menus, err = service.Rule().GetIsMenuList(ctx)
+ return
+}
+
+// Get 获取菜单信息
+func (c *menuController) Get(ctx context.Context, req *system.RuleInfoReq) (res *system.RuleInfoRes, err error) {
+ res = new(system.RuleInfoRes)
+ res.Rule, err = service.Rule().Get(ctx, req.Id)
+ if err != nil {
+ return
+ }
+ res.RoleIds, err = service.Rule().GetMenuRoles(ctx, req.Id)
+ return
+}
+
+// Update 菜单修改
+func (c *menuController) Update(ctx context.Context, req *system.RuleUpdateReq) (res *system.RuleUpdateRes, err error) {
+ err = service.Rule().Update(ctx, req)
+ return
+}
+
+// Delete 删除菜单
+func (c *menuController) Delete(ctx context.Context, req *system.RuleDeleteReq) (res *system.RuleDeleteRes, err error) {
+ err = service.Rule().DeleteMenuByIds(ctx, req.Ids)
+ return
+}
diff --git a/internal/controller/sys_config.go b/internal/controller/sys_config.go
new file mode 100644
index 0000000..ed3de7d
--- /dev/null
+++ b/internal/controller/sys_config.go
@@ -0,0 +1,50 @@
+/*
+* @desc:系统参数配置
+*
+*
+* @Date: 2022/4/18 21:17
+ */
+
+package controller
+
+import (
+ "context"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/service"
+)
+
+var Config = configController{}
+
+type configController struct {
+ BaseController
+}
+
+// List 系统参数列表
+func (c *configController) List(ctx context.Context, req *system.ConfigSearchReq) (res *system.ConfigSearchRes, err error) {
+ res, err = service.Config().List(ctx, req)
+ return
+}
+
+// Add 添加系统参数
+func (c *configController) Add(ctx context.Context, req *system.ConfigAddReq) (res *system.ConfigAddRes, err error) {
+ err = service.Config().Add(ctx, req, service.Context().GetUserId(ctx))
+ return
+}
+
+// Get 获取系统参数
+func (c *configController) Get(ctx context.Context, req *system.ConfigGetReq) (res *system.ConfigGetRes, err error) {
+ res, err = service.Config().Get(ctx, req.Id)
+ return
+}
+
+// Edit 修改系统参数
+func (c *configController) Edit(ctx context.Context, req *system.ConfigEditReq) (res *system.ConfigEditRes, err error) {
+ err = service.Config().Edit(ctx, req, service.Context().GetUserId(ctx))
+ return
+}
+
+// Delete 删除系统参数
+func (c *configController) Delete(ctx context.Context, req *system.ConfigDeleteReq) (res *system.ConfigDeleteRes, err error) {
+ err = service.Config().Delete(ctx, req.Ids)
+ return
+}
diff --git a/internal/controller/sys_dept.go b/internal/controller/sys_dept.go
new file mode 100644
index 0000000..82bf2d8
--- /dev/null
+++ b/internal/controller/sys_dept.go
@@ -0,0 +1,60 @@
+/*
+* @desc:部门管理
+*
+*
+* @Date: 2022/4/6 15:15
+ */
+
+package controller
+
+import (
+ "context"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/model/entity"
+ "tyj_admin/internal/service"
+)
+
+var Dept = sysDeptController{}
+
+type sysDeptController struct {
+ BaseController
+}
+
+// List 部门列表
+func (c *sysDeptController) List(ctx context.Context, req *system.DeptSearchReq) (res *system.DeptSearchRes, err error) {
+ res = new(system.DeptSearchRes)
+ res.DeptList, err = service.Dept().GetList(ctx, req)
+ return
+}
+
+// Add 添加部门
+func (c *sysDeptController) Add(ctx context.Context, req *system.DeptAddReq) (res *system.DeptAddRes, err error) {
+ err = service.Dept().Add(ctx, req)
+ return
+}
+
+// Edit 修改部门
+func (c *sysDeptController) Edit(ctx context.Context, req *system.DeptEditReq) (res *system.DeptEditRes, err error) {
+ err = service.Dept().Edit(ctx, req)
+ return
+}
+
+// Delete 删除部门
+func (c *sysDeptController) Delete(ctx context.Context, req *system.DeptDeleteReq) (res *system.DeptDeleteRes, err error) {
+ err = service.Dept().Delete(ctx, req.Id)
+ return
+}
+
+// TreeSelect 获取部门数据结构数据
+func (c *sysDeptController) TreeSelect(ctx context.Context, req *system.DeptTreeSelectReq) (res *system.DeptTreeSelectRes, err error) {
+ var deptList []*entity.SysDept
+ deptList, err = service.Dept().GetList(ctx, &system.DeptSearchReq{
+ Status: "1", //正常状态数据
+ })
+ if err != nil {
+ return
+ }
+ res = new(system.DeptTreeSelectRes)
+ res.Deps = service.Dept().GetListTree(0, deptList)
+ return
+}
diff --git a/internal/controller/sys_dict_data.go b/internal/controller/sys_dict_data.go
new file mode 100644
index 0000000..70aa872
--- /dev/null
+++ b/internal/controller/sys_dict_data.go
@@ -0,0 +1,54 @@
+/*
+* @desc:字典数据管理
+*
+*
+* @Date: 2022/3/18 11:57
+ */
+
+package controller
+
+import (
+ "context"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/service"
+)
+
+var DictData = dictDataController{}
+
+type dictDataController struct {
+}
+
+// GetDictData 获取字典数据
+func (c *dictDataController) GetDictData(ctx context.Context, req *system.GetDictReq) (res *system.GetDictRes, err error) {
+ res, err = service.DictData().GetDictWithDataByType(ctx, req)
+ return
+}
+
+// List 获取字典数据列表
+func (c *dictDataController) List(ctx context.Context, req *system.DictDataSearchReq) (res *system.DictDataSearchRes, err error) {
+ res, err = service.DictData().List(ctx, req)
+ return
+}
+
+// Add 添加字典数据
+func (c *dictDataController) Add(ctx context.Context, req *system.DictDataAddReq) (res *system.DictDataAddRes, err error) {
+ err = service.DictData().Add(ctx, req, service.Context().GetUserId(ctx))
+ return
+}
+
+// Get 获取对应的字典数据
+func (c *dictDataController) Get(ctx context.Context, req *system.DictDataGetReq) (res *system.DictDataGetRes, err error) {
+ res, err = service.DictData().Get(ctx, req.DictCode)
+ return
+}
+
+// Edit 修改字典数据
+func (c *dictDataController) Edit(ctx context.Context, req *system.DictDataEditReq) (res *system.DictDataEditRes, err error) {
+ err = service.DictData().Edit(ctx, req, service.Context().GetUserId(ctx))
+ return
+}
+
+func (c *dictDataController) Delete(ctx context.Context, req *system.DictDataDeleteReq) (res *system.DictDataDeleteRes, err error) {
+ err = service.DictData().Delete(ctx, req.Ids)
+ return
+}
diff --git a/internal/controller/sys_dict_type.go b/internal/controller/sys_dict_type.go
new file mode 100644
index 0000000..ba57929
--- /dev/null
+++ b/internal/controller/sys_dict_type.go
@@ -0,0 +1,49 @@
+/*
+* @desc:字典类型
+*
+*
+* @Date: 2022/3/18 11:57
+ */
+
+package controller
+
+import (
+ "context"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/service"
+)
+
+var DictType = &SysDictTypeController{}
+
+type SysDictTypeController struct {
+}
+
+// List 字典类型列表
+func (c *SysDictTypeController) List(ctx context.Context, req *system.DictTypeSearchReq) (res *system.DictTypeSearchRes, err error) {
+ res, err = service.DictType().List(ctx, req)
+ return
+}
+
+// Add 添加字典类型
+func (c *SysDictTypeController) Add(ctx context.Context, req *system.DictTypeAddReq) (res *system.DictTypeAddRes, err error) {
+ err = service.DictType().Add(ctx, req, service.Context().GetUserId(ctx))
+ return
+}
+
+// Get 获取字典类型
+func (c *SysDictTypeController) Get(ctx context.Context, req *system.DictTypeGetReq) (res *system.DictTypeGetRes, err error) {
+ res = new(system.DictTypeGetRes)
+ res.DictType, err = service.DictType().Get(ctx, req)
+ return
+}
+
+// Edit 修改字典数据
+func (c *SysDictTypeController) Edit(ctx context.Context, req *system.DictTypeEditReq) (res *system.DictTypeEditRes, err error) {
+ err = service.DictType().Edit(ctx, req, service.Context().GetUserId(ctx))
+ return
+}
+
+func (c *SysDictTypeController) Delete(ctx context.Context, req *system.DictTypeDeleteReq) (res *system.DictTypeDeleteRes, err error) {
+ err = service.DictType().Delete(ctx, req.DictIds)
+ return
+}
diff --git a/internal/controller/sys_init.go b/internal/controller/sys_init.go
new file mode 100644
index 0000000..70fa474
--- /dev/null
+++ b/internal/controller/sys_init.go
@@ -0,0 +1,73 @@
+package controller
+
+import (
+ "context"
+ "github.com/shirou/gopsutil/host"
+ "runtime"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/service"
+)
+
+var DbInit = sysDbInitController{}
+
+type sysDbInitController struct {
+ BaseController
+}
+
+// 系统是否已经初始化
+func (c *sysDbInitController) IsInit(ctx context.Context, req *system.DbInitIsInitReq) (res *system.DbInitIsInitRes, err error) {
+ res = new(system.DbInitIsInitRes)
+ // autoInit=false则前端将不走自动初始化的流程
+ if service.SysInitConfig["autoInit"].Bool() == false {
+ *res = system.DbInitIsInitRes(true)
+ return
+ }
+ // 判断是否已经生成配置文件
+ *res = system.DbInitIsInitRes(service.SysInit().IsCreateConfigFile())
+ return
+}
+
+// 获取环境检测信息
+func (c *sysDbInitController) GetEnvInfo(ctx context.Context, req *system.DbInitGetEnvInfoReq) (res *system.DbInitGetEnvInfoRes, err error) {
+ sysInfo, err := host.Info()
+ if err != nil {
+ return
+ }
+ res = new(system.DbInitGetEnvInfoRes)
+ *res = system.DbInitGetEnvInfoRes{
+ "sysOsName": sysInfo.OS,
+ "goVersion": runtime.Version(),
+ }
+ return
+}
+
+// 创建配置文件及数据库等
+func (c *sysDbInitController) CreateDb(ctx context.Context, req *system.DbInitCreateDbReq) (res *system.DbInitCreateDbRes, err error) {
+ // 生成数据库
+ err = service.SysInit().CreateDataBaseByName(ctx, req)
+ if err != nil {
+ return
+ }
+
+ // 生成配置文件
+ err = service.SysInit().CreateConfigFile(ctx, req)
+ if err != nil {
+ return
+ }
+
+ // 加载配置文件
+ err = service.SysInit().LoadConfigFile()
+ if err != nil {
+ return
+ }
+
+ // 生成数据库表机构及数据
+ err = service.SysInit().CreateDataBase(ctx, req.DbName)
+ if err != nil {
+ return
+ }
+
+ res = new(system.DbInitCreateDbRes)
+ *res = true
+ return
+}
diff --git a/internal/controller/sys_login.go b/internal/controller/sys_login.go
new file mode 100644
index 0000000..91d5771
--- /dev/null
+++ b/internal/controller/sys_login.go
@@ -0,0 +1,101 @@
+/*
+* @desc:登录
+*
+*
+* @Date: 2022/4/27 21:52
+ */
+
+package controller
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/crypto/gmd5"
+ "github.com/gogf/gf/v2/errors/gerror"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/util/gconv"
+ "github.com/gogf/gf/v2/util/gmode"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/model"
+ "tyj_admin/internal/service"
+ "tyj_admin/library/libUtils"
+)
+
+var (
+ Login = loginController{}
+)
+
+type loginController struct {
+ BaseController
+}
+
+func (c *loginController) Login(ctx context.Context, req *system.UserLoginReq) (res *system.UserLoginRes, err error) {
+ var (
+ user *model.LoginUserRes
+ token string
+ permissions []string
+ menuList []*model.UserMenus
+ )
+ //判断验证码是否正确
+ debug := gmode.IsDevelop()
+ if !debug {
+ if !service.Captcha().VerifyString(req.VerifyKey, req.VerifyCode) {
+ err = gerror.New("验证码输入错误")
+ return
+ }
+ }
+ ip := libUtils.GetClientIp(ctx)
+ userAgent := libUtils.GetUserAgent(ctx)
+ user, err = service.User().GetAdminUserByUsernamePassword(ctx, req)
+ if err != nil {
+ // 保存登录失败的日志信息
+ service.SysLoginLog().Invoke(ctx, &model.LoginLogParams{
+ Status: 0,
+ Username: req.Username,
+ Ip: ip,
+ UserAgent: userAgent,
+ Msg: err.Error(),
+ Module: "系统后台",
+ })
+ return
+ }
+ err = service.User().UpdateLoginInfo(ctx, user.Id, ip)
+ if err != nil {
+ return
+ }
+ // 报存登录成功的日志信息
+ service.SysLoginLog().Invoke(ctx, &model.LoginLogParams{
+ Status: 1,
+ Username: req.Username,
+ Ip: ip,
+ UserAgent: userAgent,
+ Msg: "登录成功",
+ Module: "系统后台",
+ })
+ key := gconv.String(user.Id) + "-" + gmd5.MustEncryptString(user.UserName) + gmd5.MustEncryptString(user.UserPassword)
+ if g.Cfg().MustGet(ctx, "gfToken.multiLogin").Bool() {
+ key = gconv.String(user.Id) + "-" + gmd5.MustEncryptString(user.UserName) + gmd5.MustEncryptString(user.UserPassword+ip+userAgent)
+ }
+ user.UserPassword = ""
+ token, err = service.SysGfToken().GenerateToken(ctx, key, user)
+ if err != nil {
+ return
+ }
+ //获取用户菜单数据
+ menuList, permissions, err = service.User().GetAdminRules(ctx, user.Id)
+ if err != nil {
+ return
+ }
+ res = &system.UserLoginRes{
+ UserInfo: user,
+ Token: token,
+ MenuList: menuList,
+ Permissions: permissions,
+ }
+ return
+}
+
+// LoginOut 退出登录
+func (c *loginController) LoginOut(ctx context.Context, req *system.UserLoginOutReq) (res *system.UserLoginOutRes, err error) {
+ err = service.SysGfToken().RemoveToken(ctx, service.SysGfToken().GetRequestToken(g.RequestFromCtx(ctx)))
+ return
+}
diff --git a/internal/controller/sys_login_log.go b/internal/controller/sys_login_log.go
new file mode 100644
index 0000000..03e5307
--- /dev/null
+++ b/internal/controller/sys_login_log.go
@@ -0,0 +1,35 @@
+/*
+* @desc:登录日志管理
+*
+*
+* @Date: 2022/4/24 22:14
+ */
+
+package controller
+
+import (
+ "context"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/service"
+)
+
+var LoginLog = loginLogController{}
+
+type loginLogController struct {
+ BaseController
+}
+
+func (c *loginLogController) List(ctx context.Context, req *system.LoginLogSearchReq) (res *system.LoginLogSearchRes, err error) {
+ res, err = service.SysLoginLog().List(ctx, req)
+ return
+}
+
+func (c *loginLogController) Delete(ctx context.Context, req *system.LoginLogDelReq) (res *system.LoginLogDelRes, err error) {
+ err = service.SysLoginLog().DeleteLoginLogByIds(ctx, req.Ids)
+ return
+}
+
+func (c *loginLogController) Clear(ctx context.Context, req *system.LoginLogClearReq) (res *system.LoginLogClearRes, err error) {
+ err = service.SysLoginLog().ClearLoginLog(ctx)
+ return
+}
diff --git a/internal/controller/sys_monitor.go b/internal/controller/sys_monitor.go
new file mode 100644
index 0000000..5ab4a86
--- /dev/null
+++ b/internal/controller/sys_monitor.go
@@ -0,0 +1,142 @@
+package controller
+
+import (
+ "context"
+ "fmt"
+ "github.com/gogf/gf/v2/os/gtime"
+ "github.com/gogf/gf/v2/util/gconv"
+ "github.com/shirou/gopsutil/cpu"
+ "github.com/shirou/gopsutil/disk"
+ "github.com/shirou/gopsutil/host"
+ "github.com/shirou/gopsutil/load"
+ "github.com/shirou/gopsutil/mem"
+ "os"
+ "runtime"
+ "strconv"
+ "time"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/library/libUtils"
+)
+
+var Monitor = sysMonitorController{
+ startTime: gtime.Now(),
+}
+
+type sysMonitorController struct {
+ BaseController
+ startTime *gtime.Time
+}
+
+func (c *sysMonitorController) List(ctx context.Context, req *system.MonitorSearchReq) (res *system.MonitorSearchRes, err error) {
+ cpuNum := runtime.NumCPU() //核心数
+ var cpuUsed float64 = 0 //用户使用率
+ var cpuAvg5 float64 = 0 //CPU负载5
+ var cpuAvg15 float64 = 0 //当前空闲率
+
+ cpuInfo, err := cpu.Percent(time.Duration(time.Second), false)
+ if err == nil {
+ cpuUsed, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", cpuInfo[0]), 64)
+ }
+
+ loadInfo, err := load.Avg()
+ if err == nil {
+ cpuAvg5, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", loadInfo.Load5), 64)
+ cpuAvg15, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", loadInfo.Load5), 64)
+ }
+
+ var memTotal uint64 = 0 //总内存
+ var memUsed uint64 = 0 //总内存 := 0 //已用内存
+ var memFree uint64 = 0 //剩余内存
+ var memUsage float64 = 0 //使用率
+
+ v, err := mem.VirtualMemory()
+ if err == nil {
+ memTotal = v.Total
+ memUsed = v.Used
+ memFree = memTotal - memUsed
+ memUsage, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", v.UsedPercent), 64)
+ }
+
+ var goTotal uint64 = 0 //go分配的总内存数
+ var goUsed uint64 = 0 //go使用的内存数
+ var goFree uint64 = 0 //go剩余的内存数
+ var goUsage float64 = 0 //使用率
+
+ var gomem runtime.MemStats
+ runtime.ReadMemStats(&gomem)
+ goUsed = gomem.Sys
+ goUsage = gconv.Float64(fmt.Sprintf("%.2f", gconv.Float64(goUsed)/gconv.Float64(memTotal)*100))
+ sysComputerIp := "" //服务器IP
+
+ ip, err := libUtils.GetLocalIP()
+ if err == nil {
+ sysComputerIp = ip
+ }
+
+ sysComputerName := "" //服务器名称
+ sysOsName := "" //操作系统
+ sysOsArch := "" //系统架构
+
+ sysInfo, err := host.Info()
+
+ if err == nil {
+ sysComputerName = sysInfo.Hostname
+ sysOsName = sysInfo.OS
+ sysOsArch = sysInfo.KernelArch
+ }
+
+ goName := "GoLang" //语言环境
+ goVersion := runtime.Version() //版本
+ gtime.Date()
+ goStartTime := c.startTime //启动时间
+
+ goRunTime := gtime.Now().Timestamp() - c.startTime.Timestamp() //运行时长(秒)
+ goHome := runtime.GOROOT() //安装路径
+ goUserDir := "" //项目路径
+
+ curDir, err := os.Getwd()
+
+ if err == nil {
+ goUserDir = curDir
+ }
+
+ //服务器磁盘信息
+ 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)
+ diskList = append(diskList, *diskDetail)
+ }
+ }
+ }
+ res = new(system.MonitorSearchRes)
+ res = &system.MonitorSearchRes{
+ "cpuNum": cpuNum,
+ "cpuUsed": cpuUsed,
+ "cpuAvg5": gconv.String(cpuAvg5),
+ "cpuAvg15": gconv.String(cpuAvg15),
+ "memTotal": memTotal,
+ "goTotal": goTotal,
+ "memUsed": memUsed,
+ "goUsed": goUsed,
+ "memFree": memFree,
+ "goFree": goFree,
+ "memUsage": memUsage,
+ "goUsage": goUsage,
+ "sysComputerName": sysComputerName,
+ "sysOsName": sysOsName,
+ "sysComputerIp": sysComputerIp,
+ "sysOsArch": sysOsArch,
+ "goName": goName,
+ "goVersion": goVersion,
+ "goStartTime": goStartTime,
+ "goRunTime": goRunTime,
+ "goHome": goHome,
+ "goUserDir": goUserDir,
+ "diskList": diskList,
+ }
+ return
+}
diff --git a/internal/controller/sys_post.go b/internal/controller/sys_post.go
new file mode 100644
index 0000000..ac05380
--- /dev/null
+++ b/internal/controller/sys_post.go
@@ -0,0 +1,44 @@
+/*
+* @desc:岗位管理
+*
+*
+* @Date: 2022/4/7 23:12
+ */
+
+package controller
+
+import (
+ "context"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/service"
+)
+
+var Post = postController{}
+
+type postController struct {
+ BaseController
+}
+
+// List 岗位列表
+func (c *postController) List(ctx context.Context, req *system.PostSearchReq) (res *system.PostSearchRes, err error) {
+ res, err = service.Post().List(ctx, req)
+ return
+}
+
+// Add 添加岗位
+func (c *postController) Add(ctx context.Context, req *system.PostAddReq) (res *system.PostAddRes, err error) {
+ err = service.Post().Add(ctx, req)
+ return
+}
+
+// Edit 修改岗位
+func (c *postController) Edit(ctx context.Context, req *system.PostEditReq) (res *system.PostEditRes, err error) {
+ err = service.Post().Edit(ctx, req)
+ return
+}
+
+// Delete 删除岗位
+func (c *postController) Delete(ctx context.Context, req *system.PostDeleteReq) (res *system.PostDeleteRes, err error) {
+ err = service.Post().Delete(ctx, req.Ids)
+ return
+}
diff --git a/internal/controller/sys_role.go b/internal/controller/sys_role.go
new file mode 100644
index 0000000..f432b0f
--- /dev/null
+++ b/internal/controller/sys_role.go
@@ -0,0 +1,62 @@
+/*
+* @desc:角色管理
+*
+*
+* @Date: 2022/3/30 9:08
+ */
+
+package controller
+
+import (
+ "context"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/service"
+)
+
+var Role = roleController{}
+
+type roleController struct {
+ BaseController
+}
+
+// List 角色列表
+func (c *roleController) List(ctx context.Context, req *system.RoleListReq) (res *system.RoleListRes, err error) {
+ res, err = service.Role().GetRoleListSearch(ctx, req)
+ return
+}
+
+// GetParams 获取角色表单参数
+func (c *roleController) GetParams(ctx context.Context, req *system.RoleGetParamsReq) (res *system.RoleGetParamsRes, err error) {
+ res = new(system.RoleGetParamsRes)
+ res.Menu, err = service.Rule().GetMenuList(ctx)
+ return
+}
+
+// Add 添加角色信息
+func (c *roleController) Add(ctx context.Context, req *system.RoleAddReq) (res *system.RoleAddRes, err error) {
+ err = service.Role().AddRole(ctx, req)
+ return
+}
+
+// Get 获取角色信息
+func (c *roleController) Get(ctx context.Context, req *system.RoleGetReq) (res *system.RoleGetRes, err error) {
+ res = new(system.RoleGetRes)
+ res.Role, err = service.Role().Get(ctx, req.Id)
+ if err != nil {
+ return
+ }
+ res.MenuIds, err = service.Role().GetFilteredNamedPolicy(ctx, req.Id)
+ return
+}
+
+// Edit 修改角色信息
+func (c *roleController) Edit(ctx context.Context, req *system.RoleEditReq) (res *system.RoleEditRes, err error) {
+ err = service.Role().EditRole(ctx, req)
+ return
+}
+
+// Delete 删除角色
+func (c *roleController) Delete(ctx context.Context, req *system.RoleDeleteReq) (res *system.RoleDeleteRes, err error) {
+ err = service.Role().DeleteByIds(ctx, req.Ids)
+ return
+}
diff --git a/internal/controller/sys_user.go b/internal/controller/sys_user.go
new file mode 100644
index 0000000..21172d8
--- /dev/null
+++ b/internal/controller/sys_user.go
@@ -0,0 +1,95 @@
+package controller
+
+import (
+ "context"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/model"
+ "tyj_admin/internal/model/entity"
+ "tyj_admin/internal/service"
+)
+
+var (
+ User = userController{}
+)
+
+type userController struct {
+ BaseController
+}
+
+// GetUserMenus 获取用户菜单及按钮权限
+func (c *userController) GetUserMenus(ctx context.Context, req *system.UserMenusReq) (res *system.UserMenusRes, err error) {
+ var (
+ permissions []string
+ menuList []*model.UserMenus
+ )
+ userId := service.Context().GetUserId(ctx)
+ menuList, permissions, err = service.User().GetAdminRules(ctx, userId)
+ res = &system.UserMenusRes{
+ MenuList: menuList,
+ Permissions: permissions,
+ }
+ return
+}
+
+// List 用户列表
+func (c *userController) List(ctx context.Context, req *system.UserSearchReq) (res *system.UserSearchRes, err error) {
+ var (
+ total int
+ userList []*entity.SysUser
+ )
+ res = new(system.UserSearchRes)
+ total, userList, err = service.User().List(ctx, req)
+ if err != nil || total == 0 {
+ return
+ }
+ res.Total = total
+ res.UserList, err = service.User().GetUsersRoleDept(ctx, userList)
+ return
+}
+
+// GetParams 获取用户维护相关参数
+func (c *userController) GetParams(ctx context.Context, req *system.UserGetParamsReq) (res *system.UserGetParamsRes, err error) {
+ res = new(system.UserGetParamsRes)
+ res.RoleList, err = service.Role().GetRoleList(ctx)
+ if err != nil {
+ return
+ }
+ res.Posts, err = service.Post().GetUsedPost(ctx)
+ return
+}
+
+// Add 添加用户
+func (c *userController) Add(ctx context.Context, req *system.UserAddReq) (res *system.UserAddRes, err error) {
+ err = service.User().Add(ctx, req)
+ return
+}
+
+// GetEditUser 获取修改用户信息
+func (c *userController) GetEditUser(ctx context.Context, req *system.UserGetEditReq) (res *system.UserGetEditRes, err error) {
+ res, err = service.User().GetEditUser(ctx, req.Id)
+ return
+}
+
+// Edit 修改用户
+func (c *userController) Edit(ctx context.Context, req *system.UserEditReq) (res *system.UserEditRes, err error) {
+ err = service.User().Edit(ctx, req)
+ return
+}
+
+// ResetPwd 重置密码
+func (c *userController) ResetPwd(ctx context.Context, req *system.UserResetPwdReq) (res *system.UserResetPwdRes, err error) {
+ err = service.User().ResetUserPwd(ctx, req)
+ return
+}
+
+// SetStatus 修改用户状态
+func (c *userController) SetStatus(ctx context.Context, req *system.UserStatusReq) (res *system.UserStatusRes, err error) {
+ err = service.User().ChangeUserStatus(ctx, req)
+ return
+}
+
+// Delete 删除用户
+func (c *userController) Delete(ctx context.Context, req *system.UserDeleteReq) (res *system.UserDeleteRes, err error) {
+ err = service.User().Delete(ctx, req.Ids)
+ return
+}
diff --git a/internal/controller/upload.go b/internal/controller/upload.go
new file mode 100644
index 0000000..0b10240
--- /dev/null
+++ b/internal/controller/upload.go
@@ -0,0 +1,87 @@
+package controller
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/errors/gerror"
+ "github.com/gogf/gf/v2/frame/g"
+ "tyj_admin/api/v1/common"
+ "tyj_admin/internal/consts"
+ "tyj_admin/internal/service"
+)
+
+var Upload = new(uploadController)
+
+type uploadController struct{}
+
+// 上传单图
+func (c *uploadController) SingleImg(ctx context.Context, req *common.UploadSingleImgReq) (res *common.UploadSingleRes, err error) {
+ r := g.RequestFromCtx(ctx)
+ file := r.GetUploadFile("file")
+ if file == nil {
+ err = gerror.New("上传文件必须")
+ return
+ }
+ v, _ := g.Cfg().Get(ctx, "upload.default")
+ response, err := service.Upload().UploadFile(ctx, file, consts.CheckFileTypeImg, v.Int())
+ if err != nil {
+ return
+ }
+ res = &common.UploadSingleRes{
+ UploadResponse: response,
+ }
+ // 上传第三方
+ return
+}
+
+// 上传多图
+func (c *uploadController) MultipleImg(ctx context.Context, req *common.UploadMultipleImgReq) (res *common.UploadMultipleRes, err error) {
+ r := g.RequestFromCtx(ctx)
+ files := r.GetUploadFiles("file")
+ if len(files) == 0 {
+ err = gerror.New("上传文件必须")
+ return
+ }
+ v, _ := g.Cfg().Get(ctx, "upload.default")
+ mf, err := service.Upload().UploadFiles(ctx, files, consts.CheckFileTypeImg, v.Int())
+ if err != nil {
+ return
+ }
+ res = &mf
+ return
+}
+
+// 上传单文件
+func (c *uploadController) SingleFile(ctx context.Context, req *common.UploadSingleFileReq) (res *common.UploadSingleRes, err error) {
+ r := g.RequestFromCtx(ctx)
+ file := r.GetUploadFile("file")
+ if file == nil {
+ err = gerror.New("上传文件必须")
+ return
+ }
+ v, _ := g.Cfg().Get(ctx, "upload.default")
+ response, err := service.Upload().UploadFile(ctx, file, consts.CheckFileTypeFile, v.Int())
+ if err != nil {
+ return
+ }
+ res = &common.UploadSingleRes{
+ UploadResponse: response,
+ }
+ return
+}
+
+// 上传多文件
+func (c *uploadController) MultipleFile(ctx context.Context, req *common.UploadMultipleFileReq) (res *common.UploadMultipleRes, err error) {
+ r := g.RequestFromCtx(ctx)
+ files := r.GetUploadFiles("file")
+ if len(files) == 0 {
+ err = gerror.New("上传文件必须")
+ return
+ }
+ v, _ := g.Cfg().Get(ctx, "upload.default")
+ mf, err := service.Upload().UploadFiles(ctx, files, consts.CheckFileTypeFile, v.Int())
+ if err != nil {
+ return
+ }
+ res = &mf
+ return
+}
diff --git a/internal/dao/casbin_rule.go b/internal/dao/casbin_rule.go
new file mode 100644
index 0000000..22efd73
--- /dev/null
+++ b/internal/dao/casbin_rule.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+ "tyj_admin/internal/dao/internal"
+)
+
+// internalCasbinRuleDao is internal type for wrapping internal DAO implements.
+type internalCasbinRuleDao = *internal.CasbinRuleDao
+
+// casbinRuleDao is the data access object for table casbin_rule.
+// You can define custom methods on it to extend its functionality as you wish.
+type casbinRuleDao struct {
+ internalCasbinRuleDao
+}
+
+var (
+ // CasbinRule is globally public accessible object for table casbin_rule operations.
+ CasbinRule = casbinRuleDao{
+ internal.NewCasbinRuleDao(),
+ }
+)
+
+// Fill with you ideas below.
diff --git a/internal/dao/internal/casbin_rule.go b/internal/dao/internal/casbin_rule.go
new file mode 100644
index 0000000..1de410f
--- /dev/null
+++ b/internal/dao/internal/casbin_rule.go
@@ -0,0 +1,85 @@
+// ==========================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+ "context"
+
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// CasbinRuleDao is the data access object for table casbin_rule.
+type CasbinRuleDao struct {
+ table string // table is the underlying table name of the DAO.
+ group string // group is the database configuration group name of current DAO.
+ columns CasbinRuleColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// CasbinRuleColumns defines and stores column names for table casbin_rule.
+type CasbinRuleColumns struct {
+ Ptype string //
+ V0 string //
+ V1 string //
+ V2 string //
+ V3 string //
+ V4 string //
+ V5 string //
+}
+
+// casbinRuleColumns holds the columns for table casbin_rule.
+var casbinRuleColumns = CasbinRuleColumns{
+ Ptype: "ptype",
+ V0: "v0",
+ V1: "v1",
+ V2: "v2",
+ V3: "v3",
+ V4: "v4",
+ V5: "v5",
+}
+
+// NewCasbinRuleDao creates and returns a new DAO object for table data access.
+func NewCasbinRuleDao() *CasbinRuleDao {
+ return &CasbinRuleDao{
+ group: "default",
+ table: "casbin_rule",
+ columns: casbinRuleColumns,
+ }
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *CasbinRuleDao) DB() gdb.DB {
+ return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *CasbinRuleDao) Table() string {
+ return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *CasbinRuleDao) Columns() CasbinRuleColumns {
+ return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *CasbinRuleDao) Group() string {
+ return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *CasbinRuleDao) Ctx(ctx context.Context) *gdb.Model {
+ return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *CasbinRuleDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
+ return dao.Ctx(ctx).Transaction(ctx, f)
+}
diff --git a/internal/dao/internal/sys_auth_rule.go b/internal/dao/internal/sys_auth_rule.go
new file mode 100644
index 0000000..ba9c811
--- /dev/null
+++ b/internal/dao/internal/sys_auth_rule.go
@@ -0,0 +1,115 @@
+// ==========================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+ "context"
+
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// SysAuthRuleDao is the data access object for table sys_auth_rule.
+type SysAuthRuleDao struct {
+ table string // table is the underlying table name of the DAO.
+ group string // group is the database configuration group name of current DAO.
+ columns SysAuthRuleColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// SysAuthRuleColumns defines and stores column names for table sys_auth_rule.
+type SysAuthRuleColumns struct {
+ Id string //
+ Pid string // 父ID
+ Name string // 规则名称
+ Title string // 规则名称
+ Icon string // 图标
+ Condition string // 条件
+ Remark string // 备注
+ MenuType string // 类型 0目录 1菜单 2按钮
+ Weigh string // 权重
+ IsHide string // 显示状态
+ Path string // 路由地址
+ Component string // 组件路径
+ IsLink string // 是否外链 1是 0否
+ ModuleType string // 所属模块
+ ModelId string // 模型ID
+ IsIframe string // 是否内嵌iframe
+ IsCached string // 是否缓存
+ Redirect string // 路由重定向地址
+ IsAffix string // 是否固定
+ LinkUrl string // 链接地址
+ CreatedAt string // 创建日期
+ UpdatedAt string // 修改日期
+}
+
+// sysAuthRuleColumns holds the columns for table sys_auth_rule.
+var sysAuthRuleColumns = SysAuthRuleColumns{
+ Id: "id",
+ Pid: "pid",
+ Name: "name",
+ Title: "title",
+ Icon: "icon",
+ Condition: "condition",
+ Remark: "remark",
+ MenuType: "menu_type",
+ Weigh: "weigh",
+ IsHide: "is_hide",
+ Path: "path",
+ Component: "component",
+ IsLink: "is_link",
+ ModuleType: "module_type",
+ ModelId: "model_id",
+ IsIframe: "is_iframe",
+ IsCached: "is_cached",
+ Redirect: "redirect",
+ IsAffix: "is_affix",
+ LinkUrl: "link_url",
+ CreatedAt: "created_at",
+ UpdatedAt: "updated_at",
+}
+
+// NewSysAuthRuleDao creates and returns a new DAO object for table data access.
+func NewSysAuthRuleDao() *SysAuthRuleDao {
+ return &SysAuthRuleDao{
+ group: "default",
+ table: "sys_auth_rule",
+ columns: sysAuthRuleColumns,
+ }
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *SysAuthRuleDao) DB() gdb.DB {
+ return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *SysAuthRuleDao) Table() string {
+ return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *SysAuthRuleDao) Columns() SysAuthRuleColumns {
+ return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *SysAuthRuleDao) Group() string {
+ return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *SysAuthRuleDao) Ctx(ctx context.Context) *gdb.Model {
+ return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *SysAuthRuleDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
+ return dao.Ctx(ctx).Transaction(ctx, f)
+}
diff --git a/internal/dao/internal/sys_config.go b/internal/dao/internal/sys_config.go
new file mode 100644
index 0000000..4e64e31
--- /dev/null
+++ b/internal/dao/internal/sys_config.go
@@ -0,0 +1,91 @@
+// ==========================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+ "context"
+
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// SysConfigDao is the data access object for table sys_config.
+type SysConfigDao struct {
+ table string // table is the underlying table name of the DAO.
+ group string // group is the database configuration group name of current DAO.
+ columns SysConfigColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// SysConfigColumns defines and stores column names for table sys_config.
+type SysConfigColumns struct {
+ ConfigId string // 参数主键
+ ConfigName string // 参数名称
+ ConfigKey string // 参数键名
+ ConfigValue string // 参数键值
+ ConfigType string // 系统内置(Y是 N否)
+ CreateBy string // 创建者
+ UpdateBy string // 更新者
+ Remark string // 备注
+ CreatedAt string // 创建时间
+ UpdatedAt string // 修改时间
+}
+
+// sysConfigColumns holds the columns for table sys_config.
+var sysConfigColumns = SysConfigColumns{
+ ConfigId: "config_id",
+ ConfigName: "config_name",
+ ConfigKey: "config_key",
+ ConfigValue: "config_value",
+ ConfigType: "config_type",
+ CreateBy: "create_by",
+ UpdateBy: "update_by",
+ Remark: "remark",
+ CreatedAt: "created_at",
+ UpdatedAt: "updated_at",
+}
+
+// NewSysConfigDao creates and returns a new DAO object for table data access.
+func NewSysConfigDao() *SysConfigDao {
+ return &SysConfigDao{
+ group: "default",
+ table: "sys_config",
+ columns: sysConfigColumns,
+ }
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *SysConfigDao) DB() gdb.DB {
+ return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *SysConfigDao) Table() string {
+ return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *SysConfigDao) Columns() SysConfigColumns {
+ return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *SysConfigDao) Group() string {
+ return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *SysConfigDao) Ctx(ctx context.Context) *gdb.Model {
+ return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *SysConfigDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
+ return dao.Ctx(ctx).Transaction(ctx, f)
+}
diff --git a/internal/dao/internal/sys_dept.go b/internal/dao/internal/sys_dept.go
new file mode 100644
index 0000000..5d43885
--- /dev/null
+++ b/internal/dao/internal/sys_dept.go
@@ -0,0 +1,99 @@
+// ==========================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+ "context"
+
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// SysDeptDao is the data access object for table sys_dept.
+type SysDeptDao struct {
+ table string // table is the underlying table name of the DAO.
+ group string // group is the database configuration group name of current DAO.
+ columns SysDeptColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// SysDeptColumns defines and stores column names for table sys_dept.
+type SysDeptColumns struct {
+ DeptId string // 部门id
+ ParentId string // 父部门id
+ Ancestors string // 祖级列表
+ DeptName string // 部门名称
+ OrderNum string // 显示顺序
+ Leader string // 负责人
+ Phone string // 联系电话
+ Email string // 邮箱
+ Status string // 部门状态(0正常 1停用)
+ CreatedBy string // 创建人
+ UpdatedBy string // 修改人
+ CreatedAt string // 创建时间
+ UpdatedAt string // 修改时间
+ DeletedAt string // 删除时间
+}
+
+// sysDeptColumns holds the columns for table sys_dept.
+var sysDeptColumns = SysDeptColumns{
+ DeptId: "dept_id",
+ ParentId: "parent_id",
+ Ancestors: "ancestors",
+ DeptName: "dept_name",
+ OrderNum: "order_num",
+ Leader: "leader",
+ Phone: "phone",
+ Email: "email",
+ Status: "status",
+ CreatedBy: "created_by",
+ UpdatedBy: "updated_by",
+ CreatedAt: "created_at",
+ UpdatedAt: "updated_at",
+ DeletedAt: "deleted_at",
+}
+
+// NewSysDeptDao creates and returns a new DAO object for table data access.
+func NewSysDeptDao() *SysDeptDao {
+ return &SysDeptDao{
+ group: "default",
+ table: "sys_dept",
+ columns: sysDeptColumns,
+ }
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *SysDeptDao) DB() gdb.DB {
+ return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *SysDeptDao) Table() string {
+ return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *SysDeptDao) Columns() SysDeptColumns {
+ return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *SysDeptDao) Group() string {
+ return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *SysDeptDao) Ctx(ctx context.Context) *gdb.Model {
+ return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *SysDeptDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
+ return dao.Ctx(ctx).Transaction(ctx, f)
+}
diff --git a/internal/dao/internal/sys_dict_data.go b/internal/dao/internal/sys_dict_data.go
new file mode 100644
index 0000000..a853755
--- /dev/null
+++ b/internal/dao/internal/sys_dict_data.go
@@ -0,0 +1,99 @@
+// ==========================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+ "context"
+
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// SysDictDataDao is the data access object for table sys_dict_data.
+type SysDictDataDao struct {
+ table string // table is the underlying table name of the DAO.
+ group string // group is the database configuration group name of current DAO.
+ columns SysDictDataColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// SysDictDataColumns defines and stores column names for table sys_dict_data.
+type SysDictDataColumns struct {
+ DictCode string // 字典编码
+ DictSort string // 字典排序
+ DictLabel string // 字典标签
+ DictValue string // 字典键值
+ DictType string // 字典类型
+ CssClass string // 样式属性(其他样式扩展)
+ ListClass string // 表格回显样式
+ IsDefault string // 是否默认(1是 0否)
+ Status string // 状态(0正常 1停用)
+ CreateBy string // 创建者
+ UpdateBy string // 更新者
+ Remark string // 备注
+ CreatedAt string // 创建时间
+ UpdatedAt string // 修改时间
+}
+
+// sysDictDataColumns holds the columns for table sys_dict_data.
+var sysDictDataColumns = SysDictDataColumns{
+ DictCode: "dict_code",
+ DictSort: "dict_sort",
+ DictLabel: "dict_label",
+ DictValue: "dict_value",
+ DictType: "dict_type",
+ CssClass: "css_class",
+ ListClass: "list_class",
+ IsDefault: "is_default",
+ Status: "status",
+ CreateBy: "create_by",
+ UpdateBy: "update_by",
+ Remark: "remark",
+ CreatedAt: "created_at",
+ UpdatedAt: "updated_at",
+}
+
+// NewSysDictDataDao creates and returns a new DAO object for table data access.
+func NewSysDictDataDao() *SysDictDataDao {
+ return &SysDictDataDao{
+ group: "default",
+ table: "sys_dict_data",
+ columns: sysDictDataColumns,
+ }
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *SysDictDataDao) DB() gdb.DB {
+ return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *SysDictDataDao) Table() string {
+ return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *SysDictDataDao) Columns() SysDictDataColumns {
+ return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *SysDictDataDao) Group() string {
+ return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *SysDictDataDao) Ctx(ctx context.Context) *gdb.Model {
+ return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *SysDictDataDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
+ return dao.Ctx(ctx).Transaction(ctx, f)
+}
diff --git a/internal/dao/internal/sys_dict_type.go b/internal/dao/internal/sys_dict_type.go
new file mode 100644
index 0000000..32a680f
--- /dev/null
+++ b/internal/dao/internal/sys_dict_type.go
@@ -0,0 +1,89 @@
+// ==========================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+ "context"
+
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// SysDictTypeDao is the data access object for table sys_dict_type.
+type SysDictTypeDao struct {
+ table string // table is the underlying table name of the DAO.
+ group string // group is the database configuration group name of current DAO.
+ columns SysDictTypeColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// SysDictTypeColumns defines and stores column names for table sys_dict_type.
+type SysDictTypeColumns struct {
+ DictId string // 字典主键
+ DictName string // 字典名称
+ DictType string // 字典类型
+ Status string // 状态(0正常 1停用)
+ CreateBy string // 创建者
+ UpdateBy string // 更新者
+ Remark string // 备注
+ CreatedAt string // 创建日期
+ UpdatedAt string // 修改日期
+}
+
+// sysDictTypeColumns holds the columns for table sys_dict_type.
+var sysDictTypeColumns = SysDictTypeColumns{
+ DictId: "dict_id",
+ DictName: "dict_name",
+ DictType: "dict_type",
+ Status: "status",
+ CreateBy: "create_by",
+ UpdateBy: "update_by",
+ Remark: "remark",
+ CreatedAt: "created_at",
+ UpdatedAt: "updated_at",
+}
+
+// NewSysDictTypeDao creates and returns a new DAO object for table data access.
+func NewSysDictTypeDao() *SysDictTypeDao {
+ return &SysDictTypeDao{
+ group: "default",
+ table: "sys_dict_type",
+ columns: sysDictTypeColumns,
+ }
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *SysDictTypeDao) DB() gdb.DB {
+ return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *SysDictTypeDao) Table() string {
+ return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *SysDictTypeDao) Columns() SysDictTypeColumns {
+ return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *SysDictTypeDao) Group() string {
+ return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *SysDictTypeDao) Ctx(ctx context.Context) *gdb.Model {
+ return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *SysDictTypeDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
+ return dao.Ctx(ctx).Transaction(ctx, f)
+}
diff --git a/internal/dao/internal/sys_login_log.go b/internal/dao/internal/sys_login_log.go
new file mode 100644
index 0000000..abc22b6
--- /dev/null
+++ b/internal/dao/internal/sys_login_log.go
@@ -0,0 +1,91 @@
+// ==========================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+ "context"
+
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// SysLoginLogDao is the data access object for table sys_login_log.
+type SysLoginLogDao struct {
+ table string // table is the underlying table name of the DAO.
+ group string // group is the database configuration group name of current DAO.
+ columns SysLoginLogColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// SysLoginLogColumns defines and stores column names for table sys_login_log.
+type SysLoginLogColumns struct {
+ InfoId string // 访问ID
+ LoginName string // 登录账号
+ Ipaddr string // 登录IP地址
+ LoginLocation string // 登录地点
+ Browser string // 浏览器类型
+ Os string // 操作系统
+ Status string // 登录状态(0成功 1失败)
+ Msg string // 提示消息
+ LoginTime string // 登录时间
+ Module string // 登录模块
+}
+
+// sysLoginLogColumns holds the columns for table sys_login_log.
+var sysLoginLogColumns = SysLoginLogColumns{
+ InfoId: "info_id",
+ LoginName: "login_name",
+ Ipaddr: "ipaddr",
+ LoginLocation: "login_location",
+ Browser: "browser",
+ Os: "os",
+ Status: "status",
+ Msg: "msg",
+ LoginTime: "login_time",
+ Module: "module",
+}
+
+// NewSysLoginLogDao creates and returns a new DAO object for table data access.
+func NewSysLoginLogDao() *SysLoginLogDao {
+ return &SysLoginLogDao{
+ group: "default",
+ table: "sys_login_log",
+ columns: sysLoginLogColumns,
+ }
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *SysLoginLogDao) DB() gdb.DB {
+ return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *SysLoginLogDao) Table() string {
+ return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *SysLoginLogDao) Columns() SysLoginLogColumns {
+ return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *SysLoginLogDao) Group() string {
+ return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *SysLoginLogDao) Ctx(ctx context.Context) *gdb.Model {
+ return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *SysLoginLogDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
+ return dao.Ctx(ctx).Transaction(ctx, f)
+}
diff --git a/internal/dao/internal/sys_oper_log.go b/internal/dao/internal/sys_oper_log.go
new file mode 100644
index 0000000..7d790f3
--- /dev/null
+++ b/internal/dao/internal/sys_oper_log.go
@@ -0,0 +1,103 @@
+// ==========================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+ "context"
+
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// SysOperLogDao is the data access object for table sys_oper_log.
+type SysOperLogDao struct {
+ table string // table is the underlying table name of the DAO.
+ group string // group is the database configuration group name of current DAO.
+ columns SysOperLogColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// SysOperLogColumns defines and stores column names for table sys_oper_log.
+type SysOperLogColumns struct {
+ OperId string // 日志主键
+ Title string // 模块标题
+ BusinessType string // 业务类型(0其它 1新增 2修改 3删除)
+ Method string // 方法名称
+ RequestMethod string // 请求方式
+ OperatorType string // 操作类别(0其它 1后台用户 2手机端用户)
+ OperName string // 操作人员
+ DeptName string // 部门名称
+ OperUrl string // 请求URL
+ OperIp string // 主机地址
+ OperLocation string // 操作地点
+ OperParam string // 请求参数
+ JsonResult string // 返回参数
+ Status string // 操作状态(0正常 1异常)
+ ErrorMsg string // 错误消息
+ OperTime string // 操作时间
+}
+
+// sysOperLogColumns holds the columns for table sys_oper_log.
+var sysOperLogColumns = SysOperLogColumns{
+ OperId: "oper_id",
+ Title: "title",
+ BusinessType: "business_type",
+ Method: "method",
+ RequestMethod: "request_method",
+ OperatorType: "operator_type",
+ OperName: "oper_name",
+ DeptName: "dept_name",
+ OperUrl: "oper_url",
+ OperIp: "oper_ip",
+ OperLocation: "oper_location",
+ OperParam: "oper_param",
+ JsonResult: "json_result",
+ Status: "status",
+ ErrorMsg: "error_msg",
+ OperTime: "oper_time",
+}
+
+// NewSysOperLogDao creates and returns a new DAO object for table data access.
+func NewSysOperLogDao() *SysOperLogDao {
+ return &SysOperLogDao{
+ group: "default",
+ table: "sys_oper_log",
+ columns: sysOperLogColumns,
+ }
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *SysOperLogDao) DB() gdb.DB {
+ return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *SysOperLogDao) Table() string {
+ return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *SysOperLogDao) Columns() SysOperLogColumns {
+ return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *SysOperLogDao) Group() string {
+ return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *SysOperLogDao) Ctx(ctx context.Context) *gdb.Model {
+ return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *SysOperLogDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
+ return dao.Ctx(ctx).Transaction(ctx, f)
+}
diff --git a/internal/dao/internal/sys_post.go b/internal/dao/internal/sys_post.go
new file mode 100644
index 0000000..c7ec214
--- /dev/null
+++ b/internal/dao/internal/sys_post.go
@@ -0,0 +1,93 @@
+// ==========================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+ "context"
+
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// SysPostDao is the data access object for table sys_post.
+type SysPostDao struct {
+ table string // table is the underlying table name of the DAO.
+ group string // group is the database configuration group name of current DAO.
+ columns SysPostColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// SysPostColumns defines and stores column names for table sys_post.
+type SysPostColumns struct {
+ PostId string // 岗位ID
+ PostCode string // 岗位编码
+ PostName string // 岗位名称
+ PostSort string // 显示顺序
+ Status string // 状态(0正常 1停用)
+ Remark string // 备注
+ CreatedBy string // 创建人
+ UpdatedBy string // 修改人
+ CreatedAt string // 创建时间
+ UpdatedAt string // 修改时间
+ DeletedAt string // 删除时间
+}
+
+// sysPostColumns holds the columns for table sys_post.
+var sysPostColumns = SysPostColumns{
+ PostId: "post_id",
+ PostCode: "post_code",
+ PostName: "post_name",
+ PostSort: "post_sort",
+ Status: "status",
+ Remark: "remark",
+ CreatedBy: "created_by",
+ UpdatedBy: "updated_by",
+ CreatedAt: "created_at",
+ UpdatedAt: "updated_at",
+ DeletedAt: "deleted_at",
+}
+
+// NewSysPostDao creates and returns a new DAO object for table data access.
+func NewSysPostDao() *SysPostDao {
+ return &SysPostDao{
+ group: "default",
+ table: "sys_post",
+ columns: sysPostColumns,
+ }
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *SysPostDao) DB() gdb.DB {
+ return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *SysPostDao) Table() string {
+ return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *SysPostDao) Columns() SysPostColumns {
+ return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *SysPostDao) Group() string {
+ return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *SysPostDao) Ctx(ctx context.Context) *gdb.Model {
+ return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *SysPostDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
+ return dao.Ctx(ctx).Transaction(ctx, f)
+}
diff --git a/internal/dao/internal/sys_role.go b/internal/dao/internal/sys_role.go
new file mode 100644
index 0000000..e009ff7
--- /dev/null
+++ b/internal/dao/internal/sys_role.go
@@ -0,0 +1,87 @@
+// ==========================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+ "context"
+
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// SysRoleDao is the data access object for table sys_role.
+type SysRoleDao struct {
+ table string // table is the underlying table name of the DAO.
+ group string // group is the database configuration group name of current DAO.
+ columns SysRoleColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// SysRoleColumns defines and stores column names for table sys_role.
+type SysRoleColumns struct {
+ Id string //
+ Status string // 状态;0:禁用;1:正常
+ ListOrder string // 排序
+ Name string // 角色名称
+ Remark string // 备注
+ DataScope string // 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)
+ CreatedAt string // 创建时间
+ UpdatedAt string // 更新时间
+}
+
+// sysRoleColumns holds the columns for table sys_role.
+var sysRoleColumns = SysRoleColumns{
+ Id: "id",
+ Status: "status",
+ ListOrder: "list_order",
+ Name: "name",
+ Remark: "remark",
+ DataScope: "data_scope",
+ CreatedAt: "created_at",
+ UpdatedAt: "updated_at",
+}
+
+// NewSysRoleDao creates and returns a new DAO object for table data access.
+func NewSysRoleDao() *SysRoleDao {
+ return &SysRoleDao{
+ group: "default",
+ table: "sys_role",
+ columns: sysRoleColumns,
+ }
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *SysRoleDao) DB() gdb.DB {
+ return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *SysRoleDao) Table() string {
+ return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *SysRoleDao) Columns() SysRoleColumns {
+ return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *SysRoleDao) Group() string {
+ return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *SysRoleDao) Ctx(ctx context.Context) *gdb.Model {
+ return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *SysRoleDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
+ return dao.Ctx(ctx).Transaction(ctx, f)
+}
diff --git a/internal/dao/internal/sys_role_dept.go b/internal/dao/internal/sys_role_dept.go
new file mode 100644
index 0000000..a2a7e5c
--- /dev/null
+++ b/internal/dao/internal/sys_role_dept.go
@@ -0,0 +1,75 @@
+// ==========================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+ "context"
+
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// SysRoleDeptDao is the data access object for table sys_role_dept.
+type SysRoleDeptDao struct {
+ table string // table is the underlying table name of the DAO.
+ group string // group is the database configuration group name of current DAO.
+ columns SysRoleDeptColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// SysRoleDeptColumns defines and stores column names for table sys_role_dept.
+type SysRoleDeptColumns struct {
+ RoleId string // 角色ID
+ DeptId string // 部门ID
+}
+
+// sysRoleDeptColumns holds the columns for table sys_role_dept.
+var sysRoleDeptColumns = SysRoleDeptColumns{
+ RoleId: "role_id",
+ DeptId: "dept_id",
+}
+
+// NewSysRoleDeptDao creates and returns a new DAO object for table data access.
+func NewSysRoleDeptDao() *SysRoleDeptDao {
+ return &SysRoleDeptDao{
+ group: "default",
+ table: "sys_role_dept",
+ columns: sysRoleDeptColumns,
+ }
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *SysRoleDeptDao) DB() gdb.DB {
+ return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *SysRoleDeptDao) Table() string {
+ return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *SysRoleDeptDao) Columns() SysRoleDeptColumns {
+ return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *SysRoleDeptDao) Group() string {
+ return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *SysRoleDeptDao) Ctx(ctx context.Context) *gdb.Model {
+ return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *SysRoleDeptDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
+ return dao.Ctx(ctx).Transaction(ctx, f)
+}
diff --git a/internal/dao/internal/sys_user.go b/internal/dao/internal/sys_user.go
new file mode 100644
index 0000000..e85461c
--- /dev/null
+++ b/internal/dao/internal/sys_user.go
@@ -0,0 +1,113 @@
+// ==========================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+ "context"
+
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// SysUserDao is the data access object for table sys_user.
+type SysUserDao struct {
+ table string // table is the underlying table name of the DAO.
+ group string // group is the database configuration group name of current DAO.
+ columns SysUserColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// SysUserColumns defines and stores column names for table sys_user.
+type SysUserColumns struct {
+ Id string //
+ UserName string // 用户名
+ Mobile string // 中国手机不带国家代码,国际手机号格式为:国家代码-手机号
+ UserNickname string // 用户昵称
+ Birthday string // 生日
+ UserPassword string // 登录密码;cmf_password加密
+ UserSalt string // 加密盐
+ UserStatus string // 用户状态;0:禁用,1:正常,2:未验证
+ UserEmail string // 用户登录邮箱
+ Sex string // 性别;0:保密,1:男,2:女
+ Avatar string // 用户头像
+ DeptId string // 部门id
+ Remark string // 备注
+ IsAdmin string // 是否后台管理员 1 是 0 否
+ Address string // 联系地址
+ Describe string // 描述信息
+ LastLoginIp string // 最后登录ip
+ LastLoginTime string // 最后登录时间
+ CreatedAt string // 创建时间
+ UpdatedAt string // 更新时间
+ DeletedAt string // 删除时间
+}
+
+// sysUserColumns holds the columns for table sys_user.
+var sysUserColumns = SysUserColumns{
+ Id: "id",
+ UserName: "user_name",
+ Mobile: "mobile",
+ UserNickname: "user_nickname",
+ Birthday: "birthday",
+ UserPassword: "user_password",
+ UserSalt: "user_salt",
+ UserStatus: "user_status",
+ UserEmail: "user_email",
+ Sex: "sex",
+ Avatar: "avatar",
+ DeptId: "dept_id",
+ Remark: "remark",
+ IsAdmin: "is_admin",
+ Address: "address",
+ Describe: "describe",
+ LastLoginIp: "last_login_ip",
+ LastLoginTime: "last_login_time",
+ CreatedAt: "created_at",
+ UpdatedAt: "updated_at",
+ DeletedAt: "deleted_at",
+}
+
+// NewSysUserDao creates and returns a new DAO object for table data access.
+func NewSysUserDao() *SysUserDao {
+ return &SysUserDao{
+ group: "default",
+ table: "sys_user",
+ columns: sysUserColumns,
+ }
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *SysUserDao) DB() gdb.DB {
+ return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *SysUserDao) Table() string {
+ return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *SysUserDao) Columns() SysUserColumns {
+ return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *SysUserDao) Group() string {
+ return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *SysUserDao) Ctx(ctx context.Context) *gdb.Model {
+ return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *SysUserDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
+ return dao.Ctx(ctx).Transaction(ctx, f)
+}
diff --git a/internal/dao/internal/sys_user_online.go b/internal/dao/internal/sys_user_online.go
new file mode 100644
index 0000000..290beb2
--- /dev/null
+++ b/internal/dao/internal/sys_user_online.go
@@ -0,0 +1,87 @@
+// ==========================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+ "context"
+
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// SysUserOnlineDao is the data access object for table sys_user_online.
+type SysUserOnlineDao struct {
+ table string // table is the underlying table name of the DAO.
+ group string // group is the database configuration group name of current DAO.
+ columns SysUserOnlineColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// SysUserOnlineColumns defines and stores column names for table sys_user_online.
+type SysUserOnlineColumns struct {
+ Id string //
+ Uuid string // 用户标识
+ Token string // 用户token
+ CreateTime string // 登录时间
+ UserName string // 用户名
+ Ip string // 登录ip
+ Explorer string // 浏览器
+ Os string // 操作系统
+}
+
+// sysUserOnlineColumns holds the columns for table sys_user_online.
+var sysUserOnlineColumns = SysUserOnlineColumns{
+ Id: "id",
+ Uuid: "uuid",
+ Token: "token",
+ CreateTime: "create_time",
+ UserName: "user_name",
+ Ip: "ip",
+ Explorer: "explorer",
+ Os: "os",
+}
+
+// NewSysUserOnlineDao creates and returns a new DAO object for table data access.
+func NewSysUserOnlineDao() *SysUserOnlineDao {
+ return &SysUserOnlineDao{
+ group: "default",
+ table: "sys_user_online",
+ columns: sysUserOnlineColumns,
+ }
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *SysUserOnlineDao) DB() gdb.DB {
+ return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *SysUserOnlineDao) Table() string {
+ return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *SysUserOnlineDao) Columns() SysUserOnlineColumns {
+ return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *SysUserOnlineDao) Group() string {
+ return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *SysUserOnlineDao) Ctx(ctx context.Context) *gdb.Model {
+ return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *SysUserOnlineDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
+ return dao.Ctx(ctx).Transaction(ctx, f)
+}
diff --git a/internal/dao/internal/sys_user_post.go b/internal/dao/internal/sys_user_post.go
new file mode 100644
index 0000000..40b57ac
--- /dev/null
+++ b/internal/dao/internal/sys_user_post.go
@@ -0,0 +1,75 @@
+// ==========================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+ "context"
+
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// SysUserPostDao is the data access object for table sys_user_post.
+type SysUserPostDao struct {
+ table string // table is the underlying table name of the DAO.
+ group string // group is the database configuration group name of current DAO.
+ columns SysUserPostColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// SysUserPostColumns defines and stores column names for table sys_user_post.
+type SysUserPostColumns struct {
+ UserId string // 用户ID
+ PostId string // 岗位ID
+}
+
+// sysUserPostColumns holds the columns for table sys_user_post.
+var sysUserPostColumns = SysUserPostColumns{
+ UserId: "user_id",
+ PostId: "post_id",
+}
+
+// NewSysUserPostDao creates and returns a new DAO object for table data access.
+func NewSysUserPostDao() *SysUserPostDao {
+ return &SysUserPostDao{
+ group: "default",
+ table: "sys_user_post",
+ columns: sysUserPostColumns,
+ }
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *SysUserPostDao) DB() gdb.DB {
+ return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *SysUserPostDao) Table() string {
+ return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *SysUserPostDao) Columns() SysUserPostColumns {
+ return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *SysUserPostDao) Group() string {
+ return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *SysUserPostDao) Ctx(ctx context.Context) *gdb.Model {
+ return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *SysUserPostDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
+ return dao.Ctx(ctx).Transaction(ctx, f)
+}
diff --git a/internal/dao/sys_auth_rule.go b/internal/dao/sys_auth_rule.go
new file mode 100644
index 0000000..de20cbf
--- /dev/null
+++ b/internal/dao/sys_auth_rule.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+ "tyj_admin/internal/dao/internal"
+)
+
+// internalSysAuthRuleDao is internal type for wrapping internal DAO implements.
+type internalSysAuthRuleDao = *internal.SysAuthRuleDao
+
+// sysAuthRuleDao is the data access object for table sys_auth_rule.
+// You can define custom methods on it to extend its functionality as you wish.
+type sysAuthRuleDao struct {
+ internalSysAuthRuleDao
+}
+
+var (
+ // SysAuthRule is globally public accessible object for table sys_auth_rule operations.
+ SysAuthRule = sysAuthRuleDao{
+ internal.NewSysAuthRuleDao(),
+ }
+)
+
+// Fill with you ideas below.
diff --git a/internal/dao/sys_config.go b/internal/dao/sys_config.go
new file mode 100644
index 0000000..4b1af76
--- /dev/null
+++ b/internal/dao/sys_config.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+ "tyj_admin/internal/dao/internal"
+)
+
+// internalSysConfigDao is internal type for wrapping internal DAO implements.
+type internalSysConfigDao = *internal.SysConfigDao
+
+// sysConfigDao is the data access object for table sys_config.
+// You can define custom methods on it to extend its functionality as you wish.
+type sysConfigDao struct {
+ internalSysConfigDao
+}
+
+var (
+ // SysConfig is globally public accessible object for table sys_config operations.
+ SysConfig = sysConfigDao{
+ internal.NewSysConfigDao(),
+ }
+)
+
+// Fill with you ideas below.
diff --git a/internal/dao/sys_dept.go b/internal/dao/sys_dept.go
new file mode 100644
index 0000000..df642af
--- /dev/null
+++ b/internal/dao/sys_dept.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+ "tyj_admin/internal/dao/internal"
+)
+
+// internalSysDeptDao is internal type for wrapping internal DAO implements.
+type internalSysDeptDao = *internal.SysDeptDao
+
+// sysDeptDao is the data access object for table sys_dept.
+// You can define custom methods on it to extend its functionality as you wish.
+type sysDeptDao struct {
+ internalSysDeptDao
+}
+
+var (
+ // SysDept is globally public accessible object for table sys_dept operations.
+ SysDept = sysDeptDao{
+ internal.NewSysDeptDao(),
+ }
+)
+
+// Fill with you ideas below.
diff --git a/internal/dao/sys_dict_data.go b/internal/dao/sys_dict_data.go
new file mode 100644
index 0000000..94cb9e4
--- /dev/null
+++ b/internal/dao/sys_dict_data.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+ "tyj_admin/internal/dao/internal"
+)
+
+// internalSysDictDataDao is internal type for wrapping internal DAO implements.
+type internalSysDictDataDao = *internal.SysDictDataDao
+
+// sysDictDataDao is the data access object for table sys_dict_data.
+// You can define custom methods on it to extend its functionality as you wish.
+type sysDictDataDao struct {
+ internalSysDictDataDao
+}
+
+var (
+ // SysDictData is globally public accessible object for table sys_dict_data operations.
+ SysDictData = sysDictDataDao{
+ internal.NewSysDictDataDao(),
+ }
+)
+
+// Fill with you ideas below.
diff --git a/internal/dao/sys_dict_type.go b/internal/dao/sys_dict_type.go
new file mode 100644
index 0000000..5212da9
--- /dev/null
+++ b/internal/dao/sys_dict_type.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+ "tyj_admin/internal/dao/internal"
+)
+
+// internalSysDictTypeDao is internal type for wrapping internal DAO implements.
+type internalSysDictTypeDao = *internal.SysDictTypeDao
+
+// sysDictTypeDao is the data access object for table sys_dict_type.
+// You can define custom methods on it to extend its functionality as you wish.
+type sysDictTypeDao struct {
+ internalSysDictTypeDao
+}
+
+var (
+ // SysDictType is globally public accessible object for table sys_dict_type operations.
+ SysDictType = sysDictTypeDao{
+ internal.NewSysDictTypeDao(),
+ }
+)
+
+// Fill with you ideas below.
diff --git a/internal/dao/sys_login_log.go b/internal/dao/sys_login_log.go
new file mode 100644
index 0000000..0eabe29
--- /dev/null
+++ b/internal/dao/sys_login_log.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+ "tyj_admin/internal/dao/internal"
+)
+
+// internalSysLoginLogDao is internal type for wrapping internal DAO implements.
+type internalSysLoginLogDao = *internal.SysLoginLogDao
+
+// sysLoginLogDao is the data access object for table sys_login_log.
+// You can define custom methods on it to extend its functionality as you wish.
+type sysLoginLogDao struct {
+ internalSysLoginLogDao
+}
+
+var (
+ // SysLoginLog is globally public accessible object for table sys_login_log operations.
+ SysLoginLog = sysLoginLogDao{
+ internal.NewSysLoginLogDao(),
+ }
+)
+
+// Fill with you ideas below.
diff --git a/internal/dao/sys_oper_log.go b/internal/dao/sys_oper_log.go
new file mode 100644
index 0000000..300d0a2
--- /dev/null
+++ b/internal/dao/sys_oper_log.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+ "tyj_admin/internal/dao/internal"
+)
+
+// internalSysOperLogDao is internal type for wrapping internal DAO implements.
+type internalSysOperLogDao = *internal.SysOperLogDao
+
+// sysOperLogDao is the data access object for table sys_oper_log.
+// You can define custom methods on it to extend its functionality as you wish.
+type sysOperLogDao struct {
+ internalSysOperLogDao
+}
+
+var (
+ // SysOperLog is globally public accessible object for table sys_oper_log operations.
+ SysOperLog = sysOperLogDao{
+ internal.NewSysOperLogDao(),
+ }
+)
+
+// Fill with you ideas below.
diff --git a/internal/dao/sys_post.go b/internal/dao/sys_post.go
new file mode 100644
index 0000000..2d16dec
--- /dev/null
+++ b/internal/dao/sys_post.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+ "tyj_admin/internal/dao/internal"
+)
+
+// internalSysPostDao is internal type for wrapping internal DAO implements.
+type internalSysPostDao = *internal.SysPostDao
+
+// sysPostDao is the data access object for table sys_post.
+// You can define custom methods on it to extend its functionality as you wish.
+type sysPostDao struct {
+ internalSysPostDao
+}
+
+var (
+ // SysPost is globally public accessible object for table sys_post operations.
+ SysPost = sysPostDao{
+ internal.NewSysPostDao(),
+ }
+)
+
+// Fill with you ideas below.
diff --git a/internal/dao/sys_role.go b/internal/dao/sys_role.go
new file mode 100644
index 0000000..1789d26
--- /dev/null
+++ b/internal/dao/sys_role.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+ "tyj_admin/internal/dao/internal"
+)
+
+// internalSysRoleDao is internal type for wrapping internal DAO implements.
+type internalSysRoleDao = *internal.SysRoleDao
+
+// sysRoleDao is the data access object for table sys_role.
+// You can define custom methods on it to extend its functionality as you wish.
+type sysRoleDao struct {
+ internalSysRoleDao
+}
+
+var (
+ // SysRole is globally public accessible object for table sys_role operations.
+ SysRole = sysRoleDao{
+ internal.NewSysRoleDao(),
+ }
+)
+
+// Fill with you ideas below.
diff --git a/internal/dao/sys_role_dept.go b/internal/dao/sys_role_dept.go
new file mode 100644
index 0000000..3b5dde0
--- /dev/null
+++ b/internal/dao/sys_role_dept.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+ "tyj_admin/internal/dao/internal"
+)
+
+// internalSysRoleDeptDao is internal type for wrapping internal DAO implements.
+type internalSysRoleDeptDao = *internal.SysRoleDeptDao
+
+// sysRoleDeptDao is the data access object for table sys_role_dept.
+// You can define custom methods on it to extend its functionality as you wish.
+type sysRoleDeptDao struct {
+ internalSysRoleDeptDao
+}
+
+var (
+ // SysRoleDept is globally public accessible object for table sys_role_dept operations.
+ SysRoleDept = sysRoleDeptDao{
+ internal.NewSysRoleDeptDao(),
+ }
+)
+
+// Fill with you ideas below.
diff --git a/internal/dao/sys_user.go b/internal/dao/sys_user.go
new file mode 100644
index 0000000..c1f2566
--- /dev/null
+++ b/internal/dao/sys_user.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+ "tyj_admin/internal/dao/internal"
+)
+
+// internalSysUserDao is internal type for wrapping internal DAO implements.
+type internalSysUserDao = *internal.SysUserDao
+
+// sysUserDao is the data access object for table sys_user.
+// You can define custom methods on it to extend its functionality as you wish.
+type sysUserDao struct {
+ internalSysUserDao
+}
+
+var (
+ // SysUser is globally public accessible object for table sys_user operations.
+ SysUser = sysUserDao{
+ internal.NewSysUserDao(),
+ }
+)
+
+// Fill with you ideas below.
diff --git a/internal/dao/sys_user_online.go b/internal/dao/sys_user_online.go
new file mode 100644
index 0000000..e7504e1
--- /dev/null
+++ b/internal/dao/sys_user_online.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+ "tyj_admin/internal/dao/internal"
+)
+
+// internalSysUserOnlineDao is internal type for wrapping internal DAO implements.
+type internalSysUserOnlineDao = *internal.SysUserOnlineDao
+
+// sysUserOnlineDao is the data access object for table sys_user_online.
+// You can define custom methods on it to extend its functionality as you wish.
+type sysUserOnlineDao struct {
+ internalSysUserOnlineDao
+}
+
+var (
+ // SysUserOnline is globally public accessible object for table sys_user_online operations.
+ SysUserOnline = sysUserOnlineDao{
+ internal.NewSysUserOnlineDao(),
+ }
+)
+
+// Fill with you ideas below.
diff --git a/internal/dao/sys_user_post.go b/internal/dao/sys_user_post.go
new file mode 100644
index 0000000..7339a77
--- /dev/null
+++ b/internal/dao/sys_user_post.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+ "tyj_admin/internal/dao/internal"
+)
+
+// internalSysUserPostDao is internal type for wrapping internal DAO implements.
+type internalSysUserPostDao = *internal.SysUserPostDao
+
+// sysUserPostDao is the data access object for table sys_user_post.
+// You can define custom methods on it to extend its functionality as you wish.
+type sysUserPostDao struct {
+ internalSysUserPostDao
+}
+
+var (
+ // SysUserPost is globally public accessible object for table sys_user_post operations.
+ SysUserPost = sysUserPostDao{
+ internal.NewSysUserPostDao(),
+ }
+)
+
+// Fill with you ideas below.
diff --git a/internal/model/context.go b/internal/model/context.go
new file mode 100644
index 0000000..6007206
--- /dev/null
+++ b/internal/model/context.go
@@ -0,0 +1,16 @@
+/*
+* @desc:context-model
+* @company:云南奇讯科技有限公司
+* @Author: yixiaohu
+* @Date: 2022/3/16 14:45
+ */
+
+package model
+
+type Context struct {
+ User *ContextUser // User in context.
+}
+
+type ContextUser struct {
+ *LoginUserRes
+}
diff --git a/internal/model/do/casbin_rule.go b/internal/model/do/casbin_rule.go
new file mode 100644
index 0000000..3e9ec42
--- /dev/null
+++ b/internal/model/do/casbin_rule.go
@@ -0,0 +1,21 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// CasbinRule is the golang structure of table casbin_rule for DAO operations like Where/Data.
+type CasbinRule struct {
+ g.Meta `orm:"table:casbin_rule, do:true"`
+ Ptype interface{} //
+ V0 interface{} //
+ V1 interface{} //
+ V2 interface{} //
+ V3 interface{} //
+ V4 interface{} //
+ V5 interface{} //
+}
diff --git a/internal/model/do/sys_auth_rule.go b/internal/model/do/sys_auth_rule.go
new file mode 100644
index 0000000..3efd7af
--- /dev/null
+++ b/internal/model/do/sys_auth_rule.go
@@ -0,0 +1,37 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysAuthRule is the golang structure of table sys_auth_rule for DAO operations like Where/Data.
+type SysAuthRule struct {
+ g.Meta `orm:"table:sys_auth_rule, do:true"`
+ Id interface{} //
+ Pid interface{} // 父ID
+ Name interface{} // 规则名称
+ Title interface{} // 规则名称
+ Icon interface{} // 图标
+ Condition interface{} // 条件
+ Remark interface{} // 备注
+ MenuType interface{} // 类型 0目录 1菜单 2按钮
+ Weigh interface{} // 权重
+ IsHide interface{} // 显示状态
+ Path interface{} // 路由地址
+ Component interface{} // 组件路径
+ IsLink interface{} // 是否外链 1是 0否
+ ModuleType interface{} // 所属模块
+ ModelId interface{} // 模型ID
+ IsIframe interface{} // 是否内嵌iframe
+ IsCached interface{} // 是否缓存
+ Redirect interface{} // 路由重定向地址
+ IsAffix interface{} // 是否固定
+ LinkUrl interface{} // 链接地址
+ CreatedAt *gtime.Time // 创建日期
+ UpdatedAt *gtime.Time // 修改日期
+}
diff --git a/internal/model/do/sys_config.go b/internal/model/do/sys_config.go
new file mode 100644
index 0000000..caa8e08
--- /dev/null
+++ b/internal/model/do/sys_config.go
@@ -0,0 +1,25 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysConfig is the golang structure of table sys_config for DAO operations like Where/Data.
+type SysConfig struct {
+ g.Meta `orm:"table:sys_config, do:true"`
+ ConfigId interface{} // 参数主键
+ ConfigName interface{} // 参数名称
+ ConfigKey interface{} // 参数键名
+ ConfigValue interface{} // 参数键值
+ ConfigType interface{} // 系统内置(Y是 N否)
+ CreateBy interface{} // 创建者
+ UpdateBy interface{} // 更新者
+ Remark interface{} // 备注
+ CreatedAt *gtime.Time // 创建时间
+ UpdatedAt *gtime.Time // 修改时间
+}
diff --git a/internal/model/do/sys_dept.go b/internal/model/do/sys_dept.go
new file mode 100644
index 0000000..6139fbc
--- /dev/null
+++ b/internal/model/do/sys_dept.go
@@ -0,0 +1,29 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysDept is the golang structure of table sys_dept for DAO operations like Where/Data.
+type SysDept struct {
+ g.Meta `orm:"table:sys_dept, do:true"`
+ DeptId interface{} // 部门id
+ ParentId interface{} // 父部门id
+ Ancestors interface{} // 祖级列表
+ DeptName interface{} // 部门名称
+ OrderNum interface{} // 显示顺序
+ Leader interface{} // 负责人
+ Phone interface{} // 联系电话
+ Email interface{} // 邮箱
+ Status interface{} // 部门状态(0正常 1停用)
+ CreatedBy interface{} // 创建人
+ UpdatedBy interface{} // 修改人
+ CreatedAt *gtime.Time // 创建时间
+ UpdatedAt *gtime.Time // 修改时间
+ DeletedAt *gtime.Time // 删除时间
+}
diff --git a/internal/model/do/sys_dict_data.go b/internal/model/do/sys_dict_data.go
new file mode 100644
index 0000000..8f81b0b
--- /dev/null
+++ b/internal/model/do/sys_dict_data.go
@@ -0,0 +1,29 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysDictData is the golang structure of table sys_dict_data for DAO operations like Where/Data.
+type SysDictData struct {
+ g.Meta `orm:"table:sys_dict_data, do:true"`
+ DictCode interface{} // 字典编码
+ DictSort interface{} // 字典排序
+ DictLabel interface{} // 字典标签
+ DictValue interface{} // 字典键值
+ DictType interface{} // 字典类型
+ CssClass interface{} // 样式属性(其他样式扩展)
+ ListClass interface{} // 表格回显样式
+ IsDefault interface{} // 是否默认(1是 0否)
+ Status interface{} // 状态(0正常 1停用)
+ CreateBy interface{} // 创建者
+ UpdateBy interface{} // 更新者
+ Remark interface{} // 备注
+ CreatedAt *gtime.Time // 创建时间
+ UpdatedAt *gtime.Time // 修改时间
+}
diff --git a/internal/model/do/sys_dict_type.go b/internal/model/do/sys_dict_type.go
new file mode 100644
index 0000000..7522b84
--- /dev/null
+++ b/internal/model/do/sys_dict_type.go
@@ -0,0 +1,24 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysDictType is the golang structure of table sys_dict_type for DAO operations like Where/Data.
+type SysDictType struct {
+ g.Meta `orm:"table:sys_dict_type, do:true"`
+ DictId interface{} // 字典主键
+ DictName interface{} // 字典名称
+ DictType interface{} // 字典类型
+ Status interface{} // 状态(0正常 1停用)
+ CreateBy interface{} // 创建者
+ UpdateBy interface{} // 更新者
+ Remark interface{} // 备注
+ CreatedAt *gtime.Time // 创建日期
+ UpdatedAt *gtime.Time // 修改日期
+}
diff --git a/internal/model/do/sys_login_log.go b/internal/model/do/sys_login_log.go
new file mode 100644
index 0000000..8fd6538
--- /dev/null
+++ b/internal/model/do/sys_login_log.go
@@ -0,0 +1,25 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysLoginLog is the golang structure of table sys_login_log for DAO operations like Where/Data.
+type SysLoginLog struct {
+ g.Meta `orm:"table:sys_login_log, do:true"`
+ InfoId interface{} // 访问ID
+ LoginName interface{} // 登录账号
+ Ipaddr interface{} // 登录IP地址
+ LoginLocation interface{} // 登录地点
+ Browser interface{} // 浏览器类型
+ Os interface{} // 操作系统
+ Status interface{} // 登录状态(0成功 1失败)
+ Msg interface{} // 提示消息
+ LoginTime *gtime.Time // 登录时间
+ Module interface{} // 登录模块
+}
diff --git a/internal/model/do/sys_oper_log.go b/internal/model/do/sys_oper_log.go
new file mode 100644
index 0000000..d8180e6
--- /dev/null
+++ b/internal/model/do/sys_oper_log.go
@@ -0,0 +1,31 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysOperLog is the golang structure of table sys_oper_log for DAO operations like Where/Data.
+type SysOperLog struct {
+ g.Meta `orm:"table:sys_oper_log, do:true"`
+ OperId interface{} // 日志主键
+ Title interface{} // 模块标题
+ BusinessType interface{} // 业务类型(0其它 1新增 2修改 3删除)
+ Method interface{} // 方法名称
+ RequestMethod interface{} // 请求方式
+ OperatorType interface{} // 操作类别(0其它 1后台用户 2手机端用户)
+ OperName interface{} // 操作人员
+ DeptName interface{} // 部门名称
+ OperUrl interface{} // 请求URL
+ OperIp interface{} // 主机地址
+ OperLocation interface{} // 操作地点
+ OperParam interface{} // 请求参数
+ JsonResult interface{} // 返回参数
+ Status interface{} // 操作状态(0正常 1异常)
+ ErrorMsg interface{} // 错误消息
+ OperTime *gtime.Time // 操作时间
+}
diff --git a/internal/model/do/sys_post.go b/internal/model/do/sys_post.go
new file mode 100644
index 0000000..a8e067d
--- /dev/null
+++ b/internal/model/do/sys_post.go
@@ -0,0 +1,26 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysPost is the golang structure of table sys_post for DAO operations like Where/Data.
+type SysPost struct {
+ g.Meta `orm:"table:sys_post, do:true"`
+ PostId interface{} // 岗位ID
+ PostCode interface{} // 岗位编码
+ PostName interface{} // 岗位名称
+ PostSort interface{} // 显示顺序
+ Status interface{} // 状态(0正常 1停用)
+ Remark interface{} // 备注
+ CreatedBy interface{} // 创建人
+ UpdatedBy interface{} // 修改人
+ CreatedAt *gtime.Time // 创建时间
+ UpdatedAt *gtime.Time // 修改时间
+ DeletedAt *gtime.Time // 删除时间
+}
diff --git a/internal/model/do/sys_role.go b/internal/model/do/sys_role.go
new file mode 100644
index 0000000..47e9599
--- /dev/null
+++ b/internal/model/do/sys_role.go
@@ -0,0 +1,23 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysRole is the golang structure of table sys_role for DAO operations like Where/Data.
+type SysRole struct {
+ g.Meta `orm:"table:sys_role, do:true"`
+ Id interface{} //
+ Status interface{} // 状态;0:禁用;1:正常
+ ListOrder interface{} // 排序
+ Name interface{} // 角色名称
+ Remark interface{} // 备注
+ DataScope interface{} // 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)
+ CreatedAt *gtime.Time // 创建时间
+ UpdatedAt *gtime.Time // 更新时间
+}
diff --git a/internal/model/do/sys_role_dept.go b/internal/model/do/sys_role_dept.go
new file mode 100644
index 0000000..df1a1ad
--- /dev/null
+++ b/internal/model/do/sys_role_dept.go
@@ -0,0 +1,16 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// SysRoleDept is the golang structure of table sys_role_dept for DAO operations like Where/Data.
+type SysRoleDept struct {
+ g.Meta `orm:"table:sys_role_dept, do:true"`
+ RoleId interface{} // 角色ID
+ DeptId interface{} // 部门ID
+}
diff --git a/internal/model/do/sys_user.go b/internal/model/do/sys_user.go
new file mode 100644
index 0000000..d4934ee
--- /dev/null
+++ b/internal/model/do/sys_user.go
@@ -0,0 +1,36 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysUser is the golang structure of table sys_user for DAO operations like Where/Data.
+type SysUser struct {
+ g.Meta `orm:"table:sys_user, do:true"`
+ Id interface{} //
+ UserName interface{} // 用户名
+ Mobile interface{} // 中国手机不带国家代码,国际手机号格式为:国家代码-手机号
+ UserNickname interface{} // 用户昵称
+ Birthday interface{} // 生日
+ UserPassword interface{} // 登录密码;cmf_password加密
+ UserSalt interface{} // 加密盐
+ UserStatus interface{} // 用户状态;0:禁用,1:正常,2:未验证
+ UserEmail interface{} // 用户登录邮箱
+ Sex interface{} // 性别;0:保密,1:男,2:女
+ Avatar interface{} // 用户头像
+ DeptId interface{} // 部门id
+ Remark interface{} // 备注
+ IsAdmin interface{} // 是否后台管理员 1 是 0 否
+ Address interface{} // 联系地址
+ Describe interface{} // 描述信息
+ LastLoginIp interface{} // 最后登录ip
+ LastLoginTime *gtime.Time // 最后登录时间
+ CreatedAt *gtime.Time // 创建时间
+ UpdatedAt *gtime.Time // 更新时间
+ DeletedAt *gtime.Time // 删除时间
+}
diff --git a/internal/model/do/sys_user_online.go b/internal/model/do/sys_user_online.go
new file mode 100644
index 0000000..f47ec4b
--- /dev/null
+++ b/internal/model/do/sys_user_online.go
@@ -0,0 +1,23 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysUserOnline is the golang structure of table sys_user_online for DAO operations like Where/Data.
+type SysUserOnline struct {
+ g.Meta `orm:"table:sys_user_online, do:true"`
+ Id interface{} //
+ Uuid interface{} // 用户标识
+ Token interface{} // 用户token
+ CreateTime *gtime.Time // 登录时间
+ UserName interface{} // 用户名
+ Ip interface{} // 登录ip
+ Explorer interface{} // 浏览器
+ Os interface{} // 操作系统
+}
diff --git a/internal/model/do/sys_user_post.go b/internal/model/do/sys_user_post.go
new file mode 100644
index 0000000..a06c02d
--- /dev/null
+++ b/internal/model/do/sys_user_post.go
@@ -0,0 +1,16 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// SysUserPost is the golang structure of table sys_user_post for DAO operations like Where/Data.
+type SysUserPost struct {
+ g.Meta `orm:"table:sys_user_post, do:true"`
+ UserId interface{} // 用户ID
+ PostId interface{} // 岗位ID
+}
diff --git a/internal/model/entity/casbin_rule.go b/internal/model/entity/casbin_rule.go
new file mode 100644
index 0000000..99ad458
--- /dev/null
+++ b/internal/model/entity/casbin_rule.go
@@ -0,0 +1,16 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+// CasbinRule is the golang structure for table casbin_rule.
+type CasbinRule struct {
+ Ptype string `json:"ptype" description:""`
+ V0 string `json:"v0" description:""`
+ V1 string `json:"v1" description:""`
+ V2 string `json:"v2" description:""`
+ V3 string `json:"v3" description:""`
+ V4 string `json:"v4" description:""`
+ V5 string `json:"v5" description:""`
+}
diff --git a/internal/model/entity/sys_auth_rule.go b/internal/model/entity/sys_auth_rule.go
new file mode 100644
index 0000000..b4d8197
--- /dev/null
+++ b/internal/model/entity/sys_auth_rule.go
@@ -0,0 +1,35 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+import (
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysAuthRule is the golang structure for table sys_auth_rule.
+type SysAuthRule struct {
+ Id uint `json:"id" description:""`
+ Pid uint `json:"pid" description:"父ID"`
+ Name string `json:"name" description:"规则名称"`
+ Title string `json:"title" description:"规则名称"`
+ Icon string `json:"icon" description:"图标"`
+ Condition string `json:"condition" description:"条件"`
+ Remark string `json:"remark" description:"备注"`
+ MenuType uint `json:"menuType" description:"类型 0目录 1菜单 2按钮"`
+ Weigh int `json:"weigh" description:"权重"`
+ IsHide uint `json:"isHide" description:"显示状态"`
+ Path string `json:"path" description:"路由地址"`
+ Component string `json:"component" description:"组件路径"`
+ IsLink uint `json:"isLink" description:"是否外链 1是 0否"`
+ ModuleType string `json:"moduleType" description:"所属模块"`
+ ModelId uint `json:"modelId" description:"模型ID"`
+ IsIframe uint `json:"isIframe" description:"是否内嵌iframe"`
+ IsCached uint `json:"isCached" description:"是否缓存"`
+ Redirect string `json:"redirect" description:"路由重定向地址"`
+ IsAffix uint `json:"isAffix" description:"是否固定"`
+ LinkUrl string `json:"linkUrl" description:"链接地址"`
+ CreatedAt *gtime.Time `json:"createdAt" description:"创建日期"`
+ UpdatedAt *gtime.Time `json:"updatedAt" description:"修改日期"`
+}
diff --git a/internal/model/entity/sys_config.go b/internal/model/entity/sys_config.go
new file mode 100644
index 0000000..fd49bcb
--- /dev/null
+++ b/internal/model/entity/sys_config.go
@@ -0,0 +1,23 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+import (
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysConfig is the golang structure for table sys_config.
+type SysConfig struct {
+ ConfigId uint `json:"configId" description:"参数主键"`
+ ConfigName string `json:"configName" description:"参数名称"`
+ ConfigKey string `json:"configKey" description:"参数键名"`
+ ConfigValue string `json:"configValue" description:"参数键值"`
+ ConfigType int `json:"configType" description:"系统内置(Y是 N否)"`
+ CreateBy uint `json:"createBy" description:"创建者"`
+ UpdateBy uint `json:"updateBy" description:"更新者"`
+ Remark string `json:"remark" description:"备注"`
+ CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
+ UpdatedAt *gtime.Time `json:"updatedAt" description:"修改时间"`
+}
diff --git a/internal/model/entity/sys_dept.go b/internal/model/entity/sys_dept.go
new file mode 100644
index 0000000..acbc258
--- /dev/null
+++ b/internal/model/entity/sys_dept.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+import (
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysDept is the golang structure for table sys_dept.
+type SysDept struct {
+ DeptId int64 `json:"deptId" description:"部门id"`
+ ParentId int64 `json:"parentId" description:"父部门id"`
+ Ancestors string `json:"ancestors" description:"祖级列表"`
+ DeptName string `json:"deptName" description:"部门名称"`
+ OrderNum int `json:"orderNum" description:"显示顺序"`
+ Leader string `json:"leader" description:"负责人"`
+ Phone string `json:"phone" description:"联系电话"`
+ Email string `json:"email" description:"邮箱"`
+ Status uint `json:"status" description:"部门状态(0正常 1停用)"`
+ CreatedBy uint64 `json:"createdBy" description:"创建人"`
+ UpdatedBy int64 `json:"updatedBy" description:"修改人"`
+ CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
+ UpdatedAt *gtime.Time `json:"updatedAt" description:"修改时间"`
+ DeletedAt *gtime.Time `json:"deletedAt" description:"删除时间"`
+}
diff --git a/internal/model/entity/sys_dict_data.go b/internal/model/entity/sys_dict_data.go
new file mode 100644
index 0000000..e5363fc
--- /dev/null
+++ b/internal/model/entity/sys_dict_data.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+import (
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysDictData is the golang structure for table sys_dict_data.
+type SysDictData struct {
+ DictCode int64 `json:"dictCode" description:"字典编码"`
+ DictSort int `json:"dictSort" description:"字典排序"`
+ DictLabel string `json:"dictLabel" description:"字典标签"`
+ DictValue string `json:"dictValue" description:"字典键值"`
+ DictType string `json:"dictType" description:"字典类型"`
+ CssClass string `json:"cssClass" description:"样式属性(其他样式扩展)"`
+ ListClass string `json:"listClass" description:"表格回显样式"`
+ IsDefault int `json:"isDefault" description:"是否默认(1是 0否)"`
+ Status int `json:"status" description:"状态(0正常 1停用)"`
+ CreateBy uint64 `json:"createBy" description:"创建者"`
+ UpdateBy uint64 `json:"updateBy" description:"更新者"`
+ Remark string `json:"remark" description:"备注"`
+ CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
+ UpdatedAt *gtime.Time `json:"updatedAt" description:"修改时间"`
+}
diff --git a/internal/model/entity/sys_dict_type.go b/internal/model/entity/sys_dict_type.go
new file mode 100644
index 0000000..1556460
--- /dev/null
+++ b/internal/model/entity/sys_dict_type.go
@@ -0,0 +1,22 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+import (
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysDictType is the golang structure for table sys_dict_type.
+type SysDictType struct {
+ DictId uint64 `json:"dictId" description:"字典主键"`
+ DictName string `json:"dictName" description:"字典名称"`
+ DictType string `json:"dictType" description:"字典类型"`
+ Status uint `json:"status" description:"状态(0正常 1停用)"`
+ CreateBy uint `json:"createBy" description:"创建者"`
+ UpdateBy uint `json:"updateBy" description:"更新者"`
+ Remark string `json:"remark" description:"备注"`
+ CreatedAt *gtime.Time `json:"createdAt" description:"创建日期"`
+ UpdatedAt *gtime.Time `json:"updatedAt" description:"修改日期"`
+}
diff --git a/internal/model/entity/sys_login_log.go b/internal/model/entity/sys_login_log.go
new file mode 100644
index 0000000..3a7b961
--- /dev/null
+++ b/internal/model/entity/sys_login_log.go
@@ -0,0 +1,23 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+import (
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysLoginLog is the golang structure for table sys_login_log.
+type SysLoginLog struct {
+ InfoId int64 `json:"infoId" description:"访问ID"`
+ LoginName string `json:"loginName" description:"登录账号"`
+ Ipaddr string `json:"ipaddr" description:"登录IP地址"`
+ LoginLocation string `json:"loginLocation" description:"登录地点"`
+ Browser string `json:"browser" description:"浏览器类型"`
+ Os string `json:"os" description:"操作系统"`
+ Status int `json:"status" description:"登录状态(0成功 1失败)"`
+ Msg string `json:"msg" description:"提示消息"`
+ LoginTime *gtime.Time `json:"loginTime" description:"登录时间"`
+ Module string `json:"module" description:"登录模块"`
+}
diff --git a/internal/model/entity/sys_oper_log.go b/internal/model/entity/sys_oper_log.go
new file mode 100644
index 0000000..c68385d
--- /dev/null
+++ b/internal/model/entity/sys_oper_log.go
@@ -0,0 +1,29 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+import (
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysOperLog is the golang structure for table sys_oper_log.
+type SysOperLog struct {
+ OperId uint64 `json:"operId" description:"日志主键"`
+ Title string `json:"title" description:"模块标题"`
+ BusinessType int `json:"businessType" description:"业务类型(0其它 1新增 2修改 3删除)"`
+ Method string `json:"method" description:"方法名称"`
+ RequestMethod string `json:"requestMethod" description:"请求方式"`
+ OperatorType int `json:"operatorType" description:"操作类别(0其它 1后台用户 2手机端用户)"`
+ OperName string `json:"operName" description:"操作人员"`
+ DeptName string `json:"deptName" description:"部门名称"`
+ OperUrl string `json:"operUrl" description:"请求URL"`
+ OperIp string `json:"operIp" description:"主机地址"`
+ OperLocation string `json:"operLocation" description:"操作地点"`
+ OperParam string `json:"operParam" description:"请求参数"`
+ JsonResult string `json:"jsonResult" description:"返回参数"`
+ Status int `json:"status" description:"操作状态(0正常 1异常)"`
+ ErrorMsg string `json:"errorMsg" description:"错误消息"`
+ OperTime *gtime.Time `json:"operTime" description:"操作时间"`
+}
diff --git a/internal/model/entity/sys_post.go b/internal/model/entity/sys_post.go
new file mode 100644
index 0000000..8301eb8
--- /dev/null
+++ b/internal/model/entity/sys_post.go
@@ -0,0 +1,24 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+import (
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysPost is the golang structure for table sys_post.
+type SysPost struct {
+ PostId uint64 `json:"postId" description:"岗位ID"`
+ PostCode string `json:"postCode" description:"岗位编码"`
+ PostName string `json:"postName" description:"岗位名称"`
+ PostSort int `json:"postSort" description:"显示顺序"`
+ Status uint `json:"status" description:"状态(0正常 1停用)"`
+ Remark string `json:"remark" description:"备注"`
+ CreatedBy uint64 `json:"createdBy" description:"创建人"`
+ UpdatedBy uint64 `json:"updatedBy" description:"修改人"`
+ CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
+ UpdatedAt *gtime.Time `json:"updatedAt" description:"修改时间"`
+ DeletedAt *gtime.Time `json:"deletedAt" description:"删除时间"`
+}
diff --git a/internal/model/entity/sys_role.go b/internal/model/entity/sys_role.go
new file mode 100644
index 0000000..c98e802
--- /dev/null
+++ b/internal/model/entity/sys_role.go
@@ -0,0 +1,21 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+import (
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysRole is the golang structure for table sys_role.
+type SysRole struct {
+ Id uint `json:"id" description:""`
+ Status uint `json:"status" description:"状态;0:禁用;1:正常"`
+ ListOrder uint `json:"listOrder" description:"排序"`
+ Name string `json:"name" description:"角色名称"`
+ Remark string `json:"remark" description:"备注"`
+ DataScope uint `json:"dataScope" description:"数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)"`
+ CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
+ UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"`
+}
diff --git a/internal/model/entity/sys_role_dept.go b/internal/model/entity/sys_role_dept.go
new file mode 100644
index 0000000..c795ca0
--- /dev/null
+++ b/internal/model/entity/sys_role_dept.go
@@ -0,0 +1,11 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+// SysRoleDept is the golang structure for table sys_role_dept.
+type SysRoleDept struct {
+ RoleId int64 `json:"roleId" description:"角色ID"`
+ DeptId int64 `json:"deptId" description:"部门ID"`
+}
diff --git a/internal/model/entity/sys_user.go b/internal/model/entity/sys_user.go
new file mode 100644
index 0000000..bd87afd
--- /dev/null
+++ b/internal/model/entity/sys_user.go
@@ -0,0 +1,34 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+import (
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysUser is the golang structure for table sys_user.
+type SysUser struct {
+ Id uint64 `json:"id" description:""`
+ UserName string `json:"userName" description:"用户名"`
+ Mobile string `json:"mobile" description:"中国手机不带国家代码,国际手机号格式为:国家代码-手机号"`
+ UserNickname string `json:"userNickname" description:"用户昵称"`
+ Birthday int `json:"birthday" description:"生日"`
+ UserPassword string `json:"userPassword" description:"登录密码;cmf_password加密"`
+ UserSalt string `json:"userSalt" description:"加密盐"`
+ UserStatus uint `json:"userStatus" description:"用户状态;0:禁用,1:正常,2:未验证"`
+ UserEmail string `json:"userEmail" description:"用户登录邮箱"`
+ Sex int `json:"sex" description:"性别;0:保密,1:男,2:女"`
+ Avatar string `json:"avatar" description:"用户头像"`
+ DeptId uint64 `json:"deptId" description:"部门id"`
+ Remark string `json:"remark" description:"备注"`
+ IsAdmin int `json:"isAdmin" description:"是否后台管理员 1 是 0 否"`
+ Address string `json:"address" description:"联系地址"`
+ Describe string `json:"describe" description:"描述信息"`
+ LastLoginIp string `json:"lastLoginIp" description:"最后登录ip"`
+ LastLoginTime *gtime.Time `json:"lastLoginTime" description:"最后登录时间"`
+ CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
+ UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"`
+ DeletedAt *gtime.Time `json:"deletedAt" description:"删除时间"`
+}
diff --git a/internal/model/entity/sys_user_online.go b/internal/model/entity/sys_user_online.go
new file mode 100644
index 0000000..a286995
--- /dev/null
+++ b/internal/model/entity/sys_user_online.go
@@ -0,0 +1,21 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+import (
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysUserOnline is the golang structure for table sys_user_online.
+type SysUserOnline struct {
+ Id uint64 `json:"id" description:""`
+ Uuid string `json:"uuid" description:"用户标识"`
+ Token string `json:"token" description:"用户token"`
+ CreateTime *gtime.Time `json:"createTime" description:"登录时间"`
+ UserName string `json:"userName" description:"用户名"`
+ Ip string `json:"ip" description:"登录ip"`
+ Explorer string `json:"explorer" description:"浏览器"`
+ Os string `json:"os" description:"操作系统"`
+}
diff --git a/internal/model/entity/sys_user_post.go b/internal/model/entity/sys_user_post.go
new file mode 100644
index 0000000..8de724c
--- /dev/null
+++ b/internal/model/entity/sys_user_post.go
@@ -0,0 +1,11 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+// SysUserPost is the golang structure for table sys_user_post.
+type SysUserPost struct {
+ UserId int64 `json:"userId" description:"用户ID"`
+ PostId int64 `json:"postId" description:"岗位ID"`
+}
diff --git a/internal/model/sys_auth_rule.go b/internal/model/sys_auth_rule.go
new file mode 100644
index 0000000..f797156
--- /dev/null
+++ b/internal/model/sys_auth_rule.go
@@ -0,0 +1,59 @@
+/*
+* @desc:菜单model
+*
+*
+* @Date: 2022/3/11 14:53
+ */
+
+package model
+
+type SysAuthRuleInfoRes struct {
+ Id uint `orm:"id,primary" json:"id"` //
+ Pid uint `orm:"pid" json:"pid"` // 父ID
+ Name string `orm:"name,unique" json:"name"` // 规则名称
+ Title string `orm:"title" json:"title"` // 规则名称
+ Icon string `orm:"icon" json:"icon"` // 图标
+ Condition string `orm:"condition" json:"condition"` // 条件
+ Remark string `orm:"remark" json:"remark"` // 备注
+ MenuType uint `orm:"menu_type" json:"menuType"` // 类型 0目录 1菜单 2按钮
+ Weigh int `orm:"weigh" json:"weigh"` // 权重
+ IsHide uint `orm:"is_hide" json:"isHide"` // 显示状态
+ IsCached uint `orm:"is_cached" json:"isCached"` // 是否缓存
+ IsAffix uint `orm:"is_affix" json:"isAffix"` //是否固定
+ Path string `orm:"path" json:"path"` // 路由地址
+ Redirect string `orm:"redirect" json:"redirect"` // 跳转路由
+ Component string `orm:"component" json:"component"` // 组件路径
+ IsIframe uint `orm:"is_iframe" json:"isIframe"` // 是否iframe
+ IsLink uint `orm:"is_link" json:"isLink"` // 是否外链 1是 0否
+ LinkUrl string `orm:"link_url" json:"linkUrl"` //链接地址
+}
+
+// SysAuthRuleTreeRes 菜单树形结构
+type SysAuthRuleTreeRes struct {
+ *SysAuthRuleInfoRes
+ Children []*SysAuthRuleTreeRes `json:"children"`
+}
+
+type UserMenu struct {
+ Id uint `json:"id"`
+ Pid uint `json:"pid"`
+ Name string `json:"name"`
+ Component string `json:"component"`
+ Path string `json:"path"`
+ *MenuMeta `json:"meta"`
+}
+
+type UserMenus struct {
+ *UserMenu `json:""`
+ Children []*UserMenus `json:"children"`
+}
+
+type MenuMeta struct {
+ Icon string `json:"icon"`
+ Title string `json:"title"`
+ IsLink string `json:"isLink"`
+ IsHide bool `json:"isHide"`
+ IsKeepAlive bool `json:"isKeepAlive"`
+ IsAffix bool `json:"isAffix"`
+ IsIframe bool `json:"isIframe"`
+}
diff --git a/internal/model/sys_config.go b/internal/model/sys_config.go
new file mode 100644
index 0000000..bc132aa
--- /dev/null
+++ b/internal/model/sys_config.go
@@ -0,0 +1,8 @@
+/*
+* @desc:xxxx功能描述
+*
+*
+* @Date: 2022/3/18 11:56
+ */
+
+package model
diff --git a/internal/model/sys_dept.go b/internal/model/sys_dept.go
new file mode 100644
index 0000000..c349d48
--- /dev/null
+++ b/internal/model/sys_dept.go
@@ -0,0 +1,15 @@
+/*
+* @desc:部门model
+*
+*
+* @Date: 2022/4/11 9:07
+ */
+
+package model
+
+import "tyj_admin/internal/model/entity"
+
+type SysDeptTreeRes struct {
+ *entity.SysDept
+ Children []*SysDeptTreeRes `json:"children"`
+}
diff --git a/internal/model/sys_dict_data.go b/internal/model/sys_dict_data.go
new file mode 100644
index 0000000..3b124d0
--- /dev/null
+++ b/internal/model/sys_dict_data.go
@@ -0,0 +1,21 @@
+/*
+* @desc:字典数据
+*
+*
+* @Date: 2022/3/18 11:56
+ */
+
+package model
+
+type DictTypeRes struct {
+ DictName string `json:"name"`
+ Remark string `json:"remark"`
+}
+
+// DictDataRes 字典数据
+type DictDataRes struct {
+ DictValue string `json:"key"`
+ DictLabel string `json:"value"`
+ IsDefault int `json:"isDefault"`
+ Remark string `json:"remark"`
+}
diff --git a/internal/model/sys_dict_type.go b/internal/model/sys_dict_type.go
new file mode 100644
index 0000000..d487d50
--- /dev/null
+++ b/internal/model/sys_dict_type.go
@@ -0,0 +1,19 @@
+/*
+* @desc:字典类型
+*
+*
+* @Date: 2022/3/18 11:56
+ */
+
+package model
+
+import "github.com/gogf/gf/v2/os/gtime"
+
+type SysDictTypeInfoRes struct {
+ DictId uint64 `orm:"dict_id,primary" json:"dictId"` // 字典主键
+ DictName string `orm:"dict_name" json:"dictName"` // 字典名称
+ DictType string `orm:"dict_type,unique" json:"dictType"` // 字典类型
+ Status uint `orm:"status" json:"status"` // 状态(0正常 1停用)
+ Remark string `orm:"remark" json:"remark"` // 备注
+ CreatedAt *gtime.Time `orm:"created_at" json:"createdAt"` // 创建日期
+}
diff --git a/internal/model/sys_init.go b/internal/model/sys_init.go
new file mode 100644
index 0000000..91cb6ff
--- /dev/null
+++ b/internal/model/sys_init.go
@@ -0,0 +1,39 @@
+package model
+
+// 程序初始化yaml配置文件
+type DbInitConfig struct {
+ Database Database `json:"database" yaml:"database"`
+ Redis Redis `json:"redis" yaml:"redis"`
+}
+
+type Database struct {
+ Default DbDefault `json:"default" yaml:"default"`
+}
+
+type DbDefault struct {
+ Host string `json:"host" yaml:"host"`
+ Port int `json:"port" yaml:"port"`
+ User string `json:"user" yaml:"user"`
+ Pass string `json:"pass" yaml:"pass"`
+ Name string `json:"name" yaml:"name"`
+ Type string `json:"type" yaml:"type"`
+ Role string `json:"role" yaml:"role"`
+ Debug bool `json:"debug" yaml:"debug"`
+ Charset string `json:"charset" yaml:"charset"`
+ DryRun bool `json:"dryRun" yaml:"dryRun"`
+ MaxIdle int `json:"maxIdle" yaml:"maxIdle"`
+ MaxOpen int `json:"maxOpen" yaml:"maxOpen"`
+ MaxLifetime int `json:"maxLifetime" yaml:"maxLifetime"`
+}
+
+type Redis struct {
+ Default RedisDefault `json:"default" yaml:"default"`
+}
+
+type RedisDefault struct {
+ Address string `json:"address" yaml:"address"`
+ Db int `json:"db" yaml:"db"`
+ Pass string `json:"pass" yaml:"pass"`
+ IdleTimeout int `json:"idleTimeout" yaml:"idleTimeout"`
+ MaxActive int `json:"maxActive" yaml:"maxActive"`
+}
diff --git a/internal/model/sys_role.go b/internal/model/sys_role.go
new file mode 100644
index 0000000..d494d83
--- /dev/null
+++ b/internal/model/sys_role.go
@@ -0,0 +1,8 @@
+/*
+* @desc:角色
+*
+*
+* @Date: 2022/3/30 9:11
+ */
+
+package model
diff --git a/internal/model/sys_user.go b/internal/model/sys_user.go
new file mode 100644
index 0000000..b59ee20
--- /dev/null
+++ b/internal/model/sys_user.go
@@ -0,0 +1,41 @@
+/*
+* @desc:用户模型对象
+*
+*
+* @Date: 2022/3/7 11:47
+ */
+
+package model
+
+import "tyj_admin/internal/model/entity"
+
+// LoginUserRes 登录返回
+type LoginUserRes struct {
+ Id uint64 `orm:"id,primary" json:"id"` //
+ UserName string `orm:"user_name,unique" json:"userName"` // 用户名
+ UserNickname string `orm:"user_nickname" json:"userNickname"` // 用户昵称
+ UserPassword string `orm:"user_password" json:"userPassword"` // 登录密码;cmf_password加密
+ UserSalt string `orm:"user_salt" json:"userSalt"` // 加密盐
+ UserStatus uint `orm:"user_status" json:"userStatus"` // 用户状态;0:禁用,1:正常,2:未验证
+ IsAdmin int `orm:"is_admin" json:"isAdmin"` // 是否后台管理员 1 是 0 否
+ Avatar string `orm:"avatar" json:"avatar"` //头像
+ DeptId uint64 `orm:"dept_id" json:"deptId"` //部门id
+}
+
+// SysUserRoleDeptRes 带有部门、角色、岗位信息的用户数据
+type SysUserRoleDeptRes struct {
+ *entity.SysUser
+ Dept *entity.SysDept `json:"dept"`
+ RoleInfo []*SysUserRoleInfoRes `json:"roleInfo"`
+ Post []*SysUserPostInfoRes `json:"post"`
+}
+
+type SysUserRoleInfoRes struct {
+ RoleId uint `json:"roleId"`
+ Name string `json:"name"`
+}
+
+type SysUserPostInfoRes struct {
+ PostId int64 `json:"postId"`
+ PostName string `json:"postName"`
+}
diff --git a/internal/model/sys_user_login.go b/internal/model/sys_user_login.go
new file mode 100644
index 0000000..b794b48
--- /dev/null
+++ b/internal/model/sys_user_login.go
@@ -0,0 +1,18 @@
+/*
+* @desc:登录日志
+*
+*
+* @Date: 2022/3/8 11:43
+ */
+
+package model
+
+// LoginLogParams 登录日志写入参数
+type LoginLogParams struct {
+ Status int
+ Username string
+ Ip string
+ UserAgent string
+ Msg string
+ Module string
+}
diff --git a/internal/model/token.go b/internal/model/token.go
new file mode 100644
index 0000000..cb16f1a
--- /dev/null
+++ b/internal/model/token.go
@@ -0,0 +1,32 @@
+/*
+* @desc:token options
+*
+*
+* @Date: 2022/3/8 16:02
+ */
+
+package model
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+type TokenOptions struct {
+ // server name
+ ServerName string `json:"serverName"`
+ // 缓存key (每创建一个实例CacheKey必须不相同)
+ CacheKey string `json:"cacheKey"`
+ // 超时时间 默认10天(秒)
+ Timeout int64 `json:"timeout"`
+ // 缓存刷新时间 默认5天(秒)
+ // 处理携带token的请求时当前时间大于超时时间并小于缓存刷新时间时token将自动刷新即重置token存活时间
+ // MaxRefresh值为0时,token将不会自动刷新
+ MaxRefresh int64 `json:"maxRefresh"`
+ // 是否允许多点登录
+ MultiLogin bool `json:"multiLogin"`
+ // Token加密key 32位
+ EncryptKey []byte `json:"encryptKey"`
+ // 拦截排除地址
+ ExcludePaths g.SliceStr `json:"excludePaths"`
+ CacheModel string `json:"cacheModel"`
+}
diff --git a/internal/packed/packed.go b/internal/packed/packed.go
new file mode 100644
index 0000000..e20ab1e
--- /dev/null
+++ b/internal/packed/packed.go
@@ -0,0 +1 @@
+package packed
diff --git a/internal/router/router.go b/internal/router/router.go
new file mode 100644
index 0000000..8f0a162
--- /dev/null
+++ b/internal/router/router.go
@@ -0,0 +1,86 @@
+/*
+* @desc:路由绑定
+*
+*
+* @Date: 2022/2/18 16:23
+ */
+
+package router
+
+import (
+ "github.com/gogf/gf/v2/net/ghttp"
+
+ "tyj_admin/internal/controller"
+ "tyj_admin/internal/service"
+)
+
+func BindController(group *ghttp.RouterGroup) {
+ group.Group("/api/v1", func(group *ghttp.RouterGroup) {
+ group.Middleware(ghttp.MiddlewareHandlerResponse)
+ // 绑定后台路由
+ SystemBindController(group)
+ // 绑定测试路由
+ DemoBindController(group)
+ // 绑定公共路由
+ CommonBindController(group)
+ })
+
+}
+
+func CommonBindController(group *ghttp.RouterGroup) {
+ group.Group("/pub", func(group *ghttp.RouterGroup) {
+ group.Middleware(service.Middleware().MiddlewareCORS)
+ group.Group("/captcha", func(group *ghttp.RouterGroup) {
+ group.Bind(
+ controller.Captcha,
+ )
+ })
+
+ // 文件上传
+ group.Group("/upload", func(group *ghttp.RouterGroup) {
+ group.Bind(
+ controller.Upload,
+ )
+ })
+ })
+}
+
+func DemoBindController(group *ghttp.RouterGroup) {
+ group.Group("/demo", func(group *ghttp.RouterGroup) {
+ group.Middleware(service.Middleware().MiddlewareCORS)
+ group.Bind(
+ controller.Demo,
+ )
+ })
+
+}
+
+func SystemBindController(group *ghttp.RouterGroup) {
+ group.Group("/system", func(group *ghttp.RouterGroup) {
+ group.Middleware(service.Middleware().MiddlewareCORS)
+ // 系统初始化
+ group.Bind(
+ controller.DbInit,
+ )
+ group.Bind(
+ //登录
+ controller.Login,
+ )
+ //登录验证拦截
+ service.SysGfToken().Middleware(group)
+ //context拦截器
+ group.Middleware(service.Middleware().Ctx, service.Middleware().Auth)
+ group.Bind(
+ controller.User,
+ controller.Menu,
+ controller.Role,
+ controller.Dept,
+ controller.Post,
+ controller.DictType,
+ controller.DictData,
+ controller.Config,
+ controller.Monitor,
+ controller.LoginLog,
+ )
+ })
+}
diff --git a/internal/service/cache.go b/internal/service/cache.go
new file mode 100644
index 0000000..9f0a236
--- /dev/null
+++ b/internal/service/cache.go
@@ -0,0 +1,55 @@
+/*
+* @desc:缓存处理
+*
+*
+* @Date: 2022/3/9 11:15
+ */
+
+package service
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gctx"
+ "github.com/tiger1103/gfast-cache/cache"
+ "sync"
+ "tyj_admin/internal/consts"
+)
+
+type ICache interface {
+ cache.IGCache
+}
+
+type cacheImpl struct {
+ *cache.GfCache
+ prefix string
+}
+
+var (
+ c = cacheImpl{}
+ cacheContainer *cache.GfCache
+ lock = &sync.Mutex{}
+)
+
+func Cache() ICache {
+ var (
+ ch = c
+ ctx = gctx.New()
+ )
+ prefix := g.Cfg().MustGet(ctx, "system.cache.prefix").String()
+ model := g.Cfg().MustGet(ctx, "system.cache.model").String()
+ if cacheContainer == nil {
+ lock.Lock()
+ if cacheContainer == nil {
+ if model == consts.CacheModelRedis {
+ // redis
+ cacheContainer = cache.NewRedis(prefix)
+ } else {
+ // memory
+ cacheContainer = cache.New(prefix)
+ }
+ }
+ lock.Unlock()
+ }
+ ch.GfCache = cacheContainer
+ return &ch
+}
diff --git a/internal/service/captcha.go b/internal/service/captcha.go
new file mode 100644
index 0000000..d40f530
--- /dev/null
+++ b/internal/service/captcha.go
@@ -0,0 +1,51 @@
+package service
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/text/gstr"
+ "github.com/mojocn/base64Captcha"
+)
+
+type ICaptcha interface {
+ GetVerifyImgString(ctx context.Context) (idKeyC string, base64stringC string, err error)
+ VerifyString(id, answer string) bool
+}
+
+type captchaImpl struct {
+ driver *base64Captcha.DriverString
+ store base64Captcha.Store
+}
+
+var (
+ captcha = captchaImpl{
+ driver: &base64Captcha.DriverString{
+ Height: 80,
+ Width: 240,
+ NoiseCount: 50,
+ ShowLineOptions: 20,
+ Length: 4,
+ Source: "abcdefghjkmnpqrstuvwxyz23456789",
+ Fonts: []string{"chromohv.ttf"},
+ },
+ store: base64Captcha.DefaultMemStore,
+ }
+)
+
+func Captcha() ICaptcha {
+ return &captcha
+}
+
+// GetVerifyImgString 获取字母数字混合验证码
+func (s *captchaImpl) GetVerifyImgString(ctx context.Context) (idKeyC string, base64stringC string, err error) {
+ driver := s.driver.ConvertFonts()
+ c := base64Captcha.NewCaptcha(driver, s.store)
+ idKeyC, base64stringC, err = c.Generate()
+ return
+}
+
+// VerifyString 验证输入的验证码是否正确
+func (s *captchaImpl) VerifyString(id, answer string) bool {
+ c := base64Captcha.NewCaptcha(s.driver, s.store)
+ answer = gstr.ToLower(answer)
+ return c.Verify(id, answer, true)
+}
diff --git a/internal/service/casbin.go b/internal/service/casbin.go
new file mode 100644
index 0000000..1f9afa0
--- /dev/null
+++ b/internal/service/casbin.go
@@ -0,0 +1,238 @@
+package service
+
+import (
+ "context"
+ "github.com/casbin/casbin/v2"
+ "github.com/casbin/casbin/v2/model"
+ "github.com/casbin/casbin/v2/persist"
+ "github.com/gogf/gf/v2/frame/g"
+ "sync"
+ "tyj_admin/internal/dao"
+ "tyj_admin/internal/model/entity"
+)
+
+type cabinImpl struct{}
+
+type adapterCasbin struct {
+ Enforcer *casbin.SyncedEnforcer
+ EnforcerErr error
+ ctx context.Context
+}
+
+var (
+ cb = cabinImpl{}
+ once sync.Once
+ ac *adapterCasbin
+)
+
+// CasbinEnforcer 获取adapter单例对象
+func CasbinEnforcer(ctx context.Context) (enforcer *casbin.SyncedEnforcer, err error) {
+ once.Do(func() {
+ ac = cb.newAdapter(ctx)
+ })
+ enforcer = ac.Enforcer
+ err = ac.EnforcerErr
+ return
+}
+
+// 初始化adapter操作
+func (s *cabinImpl) newAdapter(ctx context.Context) (a *adapterCasbin) {
+ a = new(adapterCasbin)
+ a.initPolicy(ctx)
+ a.ctx = ctx
+ return
+}
+
+func (a *adapterCasbin) initPolicy(ctx context.Context) {
+ // Because the DB is empty at first,
+ // so we need to load the policy from the file adapter (.CSV) first.
+ e, err := casbin.NewSyncedEnforcer(g.Cfg().MustGet(ctx, "casbin.modelFile").String(), a)
+
+ if err != nil {
+ a.EnforcerErr = err
+ return
+ }
+
+ // This is a trick to save the current policy to the DB.
+ // We can't call e.SavePolicy() because the adapter in the enforcer is still the file adapter.
+ // The current policy means the policy in the Casbin enforcer (aka in memory).
+ //err = a.SavePolicy(e.GetModel())
+ //if err != nil {
+ // return err
+ //}
+ //set adapter
+ //e.SetAdapter(a)
+ // Clear the current policy.
+ e.ClearPolicy()
+ a.Enforcer = e
+ // Load the policy from DB.
+ err = a.LoadPolicy(e.GetModel())
+ if err != nil {
+ a.EnforcerErr = err
+ return
+ }
+}
+
+// SavePolicy saves policy to database.
+func (a *adapterCasbin) SavePolicy(model model.Model) (err error) {
+ err = a.dropTable()
+ if err != nil {
+ return
+ }
+ err = a.createTable()
+ if err != nil {
+ return
+ }
+ for ptype, ast := range model["p"] {
+ for _, rule := range ast.Policy {
+ line := savePolicyLine(ptype, rule)
+ _, err := dao.CasbinRule.Ctx(a.ctx).Data(line).Insert()
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ for ptype, ast := range model["g"] {
+ for _, rule := range ast.Policy {
+ line := savePolicyLine(ptype, rule)
+ _, err := dao.CasbinRule.Ctx(a.ctx).Data(line).Insert()
+ if err != nil {
+ return err
+ }
+ }
+ }
+ return
+}
+
+func (a *adapterCasbin) dropTable() (err error) {
+ return
+}
+
+func (a *adapterCasbin) createTable() (err error) {
+ return
+}
+
+// LoadPolicy loads policy from database.
+func (a *adapterCasbin) LoadPolicy(model model.Model) error {
+ var lines []*entity.CasbinRule
+ if err := dao.CasbinRule.Ctx(a.ctx).Scan(&lines); err != nil {
+ return err
+ }
+ for _, line := range lines {
+ loadPolicyLine(line, model)
+ }
+ return nil
+}
+
+// AddPolicy adds a policy rule to the storage.
+func (a *adapterCasbin) AddPolicy(sec string, ptype string, rule []string) error {
+ line := savePolicyLine(ptype, rule)
+ _, err := dao.CasbinRule.Ctx(a.ctx).Data(line).Insert()
+ return err
+}
+
+// RemovePolicy removes a policy rule from the storage.
+func (a *adapterCasbin) RemovePolicy(sec string, ptype string, rule []string) error {
+ line := savePolicyLine(ptype, rule)
+ err := rawDelete(a, line)
+ return err
+}
+
+// RemoveFilteredPolicy removes policy rules that match the filter from the storage.
+func (a *adapterCasbin) RemoveFilteredPolicy(sec string, ptype string,
+ fieldIndex int, fieldValues ...string) error {
+ line := &entity.CasbinRule{}
+ line.Ptype = ptype
+ if fieldIndex <= 0 && 0 < fieldIndex+len(fieldValues) {
+ line.V0 = fieldValues[0-fieldIndex]
+ }
+ if fieldIndex <= 1 && 1 < fieldIndex+len(fieldValues) {
+ line.V1 = fieldValues[1-fieldIndex]
+ }
+ if fieldIndex <= 2 && 2 < fieldIndex+len(fieldValues) {
+ line.V2 = fieldValues[2-fieldIndex]
+ }
+ if fieldIndex <= 3 && 3 < fieldIndex+len(fieldValues) {
+ line.V3 = fieldValues[3-fieldIndex]
+ }
+ if fieldIndex <= 4 && 4 < fieldIndex+len(fieldValues) {
+ line.V4 = fieldValues[4-fieldIndex]
+ }
+ if fieldIndex <= 5 && 5 < fieldIndex+len(fieldValues) {
+ line.V5 = fieldValues[5-fieldIndex]
+ }
+ err := rawDelete(a, line)
+ return err
+}
+
+func loadPolicyLine(line *entity.CasbinRule, model model.Model) {
+ lineText := line.Ptype
+ if line.V0 != "" {
+ lineText += ", " + line.V0
+ }
+ if line.V1 != "" {
+ lineText += ", " + line.V1
+ }
+ if line.V2 != "" {
+ lineText += ", " + line.V2
+ }
+ if line.V3 != "" {
+ lineText += ", " + line.V3
+ }
+ if line.V4 != "" {
+ lineText += ", " + line.V4
+ }
+ if line.V5 != "" {
+ lineText += ", " + line.V5
+ }
+ persist.LoadPolicyLine(lineText, model)
+}
+
+func savePolicyLine(ptype string, rule []string) *entity.CasbinRule {
+ line := &entity.CasbinRule{}
+ line.Ptype = ptype
+ if len(rule) > 0 {
+ line.V0 = rule[0]
+ }
+ if len(rule) > 1 {
+ line.V1 = rule[1]
+ }
+ if len(rule) > 2 {
+ line.V2 = rule[2]
+ }
+ if len(rule) > 3 {
+ line.V3 = rule[3]
+ }
+ if len(rule) > 4 {
+ line.V4 = rule[4]
+ }
+ if len(rule) > 5 {
+ line.V5 = rule[5]
+ }
+ return line
+}
+
+func rawDelete(a *adapterCasbin, line *entity.CasbinRule) error {
+ db := dao.CasbinRule.Ctx(a.ctx).Where("ptype = ?", line.Ptype)
+ if line.V0 != "" {
+ db = db.Where("v0 = ?", line.V0)
+ }
+ if line.V1 != "" {
+ db = db.Where("v1 = ?", line.V1)
+ }
+ if line.V2 != "" {
+ db = db.Where("v2 = ?", line.V2)
+ }
+ if line.V3 != "" {
+ db = db.Where("v3 = ?", line.V3)
+ }
+ if line.V4 != "" {
+ db = db.Where("v4 = ?", line.V4)
+ }
+ if line.V5 != "" {
+ db = db.Where("v5 = ?", line.V5)
+ }
+ _, err := db.Delete()
+ return err
+}
diff --git a/internal/service/context.go b/internal/service/context.go
new file mode 100644
index 0000000..443dd89
--- /dev/null
+++ b/internal/service/context.go
@@ -0,0 +1,72 @@
+/*
+* @desc:context-service
+* @company:云南奇讯科技有限公司
+* @Author: yixiaohu
+* @Date: 2022/3/16 14:46
+ */
+
+package service
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/net/ghttp"
+ "tyj_admin/internal/consts"
+ "tyj_admin/internal/model"
+)
+
+type IContext interface {
+ Init(r *ghttp.Request, customCtx *model.Context)
+ Get(ctx context.Context) *model.Context
+ SetUser(ctx context.Context, ctxUser *model.ContextUser)
+ GetLoginUser(ctx context.Context) *model.ContextUser
+ GetUserId(ctx context.Context) uint64
+}
+
+// Context 上下文管理服务
+var contextService = contextServiceImpl{}
+
+type contextServiceImpl struct{}
+
+func Context() IContext {
+ return &contextService
+}
+
+// Init 初始化上下文对象指针到上下文对象中,以便后续的请求流程中可以修改。
+func (s *contextServiceImpl) Init(r *ghttp.Request, customCtx *model.Context) {
+ r.SetCtxVar(consts.CtxKey, customCtx)
+}
+
+// Get 获得上下文变量,如果没有设置,那么返回nil
+func (s *contextServiceImpl) Get(ctx context.Context) *model.Context {
+ value := ctx.Value(consts.CtxKey)
+ if value == nil {
+ return nil
+ }
+ if localCtx, ok := value.(*model.Context); ok {
+ return localCtx
+ }
+ return nil
+}
+
+// SetUser 将上下文信息设置到上下文请求中,注意是完整覆盖
+func (s *contextServiceImpl) SetUser(ctx context.Context, ctxUser *model.ContextUser) {
+ s.Get(ctx).User = ctxUser
+}
+
+// GetLoginUser 获取当前登陆用户信息
+func (s *contextServiceImpl) GetLoginUser(ctx context.Context) *model.ContextUser {
+ context := s.Get(ctx)
+ if context == nil {
+ return nil
+ }
+ return context.User
+}
+
+// GetUserId 获取当前登录用户id
+func (s *contextServiceImpl) GetUserId(ctx context.Context) uint64 {
+ user := s.GetLoginUser(ctx)
+ if user != nil {
+ return user.Id
+ }
+ return 0
+}
diff --git a/internal/service/middleware.go b/internal/service/middleware.go
new file mode 100644
index 0000000..2339b4f
--- /dev/null
+++ b/internal/service/middleware.go
@@ -0,0 +1,137 @@
+/*
+* @desc:中间件处理
+*
+*
+* @Date: 2022/3/17 9:11
+ */
+
+package service
+
+import (
+ "fmt"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/net/ghttp"
+ "github.com/gogf/gf/v2/text/gstr"
+ "github.com/gogf/gf/v2/util/gconv"
+ "tyj_admin/internal/model"
+ "tyj_admin/library/libResponse"
+)
+
+type IMiddleware interface {
+ MiddlewareCORS(r *ghttp.Request)
+ Ctx(r *ghttp.Request)
+ Auth(r *ghttp.Request)
+}
+
+type middlewareImpl struct{}
+
+var middleService = middlewareImpl{}
+
+func Middleware() IMiddleware {
+ return &middleService
+}
+
+func (s *middlewareImpl) MiddlewareCORS(r *ghttp.Request) {
+ corsOptions := r.Response.DefaultCORSOptions()
+ // you can set options
+ //corsOptions.AllowDomain = []string{"goframe.org", "baidu.com"}
+ r.Response.CORS(corsOptions)
+ r.Middleware.Next()
+}
+
+// Ctx 自定义上下文对象
+func (s *middlewareImpl) Ctx(r *ghttp.Request) {
+ ctx := r.GetCtx()
+ // 初始化登录用户信息
+ data, err := SysGfToken().ParseToken(r)
+ if err != nil {
+ // 执行下一步请求逻辑
+ r.Middleware.Next()
+ }
+ if data != nil {
+ context := new(model.Context)
+ err = gconv.Struct(data.Data, &context.User)
+ if err != nil {
+ g.Log().Error(ctx, err)
+ // 执行下一步请求逻辑
+ r.Middleware.Next()
+ }
+ Context().Init(r, context)
+ }
+ // 执行下一步请求逻辑
+ r.Middleware.Next()
+}
+
+// Auth 权限判断处理中间件
+func (s *middlewareImpl) Auth(r *ghttp.Request) {
+ ctx := r.GetCtx()
+ //获取登陆用户id
+ adminId := Context().GetUserId(ctx)
+ accessParams := r.Get("accessParams").Strings()
+ accessParamsStr := ""
+ if len(accessParams) > 0 && accessParams[0] != "undefined" {
+ accessParamsStr = "?" + gstr.Join(accessParams, "&")
+ }
+ url := gstr.TrimLeft(r.Request.URL.Path, "/") + accessParamsStr
+ /*if r.Method != "GET" && adminId != 1 && url!="api/v1/system/login" {
+ libResponse.FailJson(true, r, "对不起!演示系统,不能删改数据!")
+ }*/
+ //获取无需验证权限的用户id
+ tagSuperAdmin := false
+ User().NotCheckAuthAdminIds(ctx).Iterator(func(v interface{}) bool {
+ if gconv.Uint64(v) == adminId {
+ tagSuperAdmin = true
+ return false
+ }
+ return true
+ })
+ if tagSuperAdmin {
+ r.Middleware.Next()
+ //不要再往后面执行
+ return
+ }
+ //获取地址对应的菜单id
+ menuList, err := Rule().GetMenuList(ctx)
+ if err != nil {
+ g.Log().Error(ctx, err)
+ libResponse.FailJson(true, r, "请求数据失败")
+ }
+ var menu *model.SysAuthRuleInfoRes
+ for _, m := range menuList {
+ ms := gstr.SubStr(m.Name, 0, gstr.Pos(m.Name, "?"))
+ if m.Name == url || ms == url {
+ menu = m
+ break
+ }
+ }
+ //只验证存在数据库中的规则
+ if menu != nil {
+ //若存在不需要验证的条件则跳过
+ if gstr.Equal(menu.Condition, "nocheck") {
+ r.Middleware.Next()
+ return
+ }
+ menuId := menu.Id
+ //菜单没存数据库不验证权限
+ if menuId != 0 {
+ //判断权限操作
+ enforcer, err := CasbinEnforcer(ctx)
+ if err != nil {
+ g.Log().Error(ctx, err)
+ libResponse.FailJson(true, r, "获取权限失败")
+ }
+ hasAccess := false
+ hasAccess, err = enforcer.Enforce(fmt.Sprintf("%s%d", userService.CasBinUserPrefix, adminId), gconv.String(menuId), "All")
+ if err != nil {
+ g.Log().Error(ctx, err)
+ libResponse.FailJson(true, r, "判断权限失败")
+ }
+ if !hasAccess {
+ libResponse.FailJson(true, r, "没有访问权限")
+ }
+ }
+ } else if menu == nil && accessParamsStr != "" {
+ libResponse.FailJson(true, r, "没有访问权限")
+ }
+ r.Middleware.Next()
+}
diff --git a/internal/service/sys_auth_rule.go b/internal/service/sys_auth_rule.go
new file mode 100644
index 0000000..c3a18c6
--- /dev/null
+++ b/internal/service/sys_auth_rule.go
@@ -0,0 +1,325 @@
+/*
+* @desc:菜单处理
+*
+*
+* @Date: 2022/3/11 15:07
+ */
+
+package service
+
+import (
+ "context"
+ "fmt"
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/errors/gerror"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/util/gconv"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/consts"
+ "tyj_admin/internal/dao"
+ "tyj_admin/internal/model"
+ "tyj_admin/internal/model/do"
+ "tyj_admin/internal/model/entity"
+ "tyj_admin/library/liberr"
+)
+
+type IRule interface {
+ GetIsMenuList(ctx context.Context) ([]*model.SysAuthRuleInfoRes, error)
+ GetMenuList(ctx context.Context) (list []*model.SysAuthRuleInfoRes, err error)
+ GetIsButtonList(ctx context.Context) ([]*model.SysAuthRuleInfoRes, error)
+ Add(ctx context.Context, req *system.RuleAddReq) (err error)
+ Get(ctx context.Context, id uint) (rule *entity.SysAuthRule, err error)
+ GetMenuRoles(ctx context.Context, id uint) (roleIds []uint, err error)
+ Update(ctx context.Context, req *system.RuleUpdateReq) (err error)
+ GetMenuListSearch(ctx context.Context, req *system.RuleSearchReq) (res []*model.SysAuthRuleInfoRes, err error)
+ GetMenuListTree(pid uint, list []*model.SysAuthRuleInfoRes) []*model.SysAuthRuleTreeRes
+ DeleteMenuByIds(ctx context.Context, ids []int) (err error)
+}
+
+type ruleImpl struct {
+}
+
+var ruleService = ruleImpl{}
+
+func Rule() IRule {
+ return &ruleService
+}
+
+func (s *ruleImpl) GetMenuListSearch(ctx context.Context, req *system.RuleSearchReq) (res []*model.SysAuthRuleInfoRes, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ m := dao.SysAuthRule.Ctx(ctx)
+ if req.Title != "" {
+ m = m.Where("title like ?", "%"+req.Title+"%")
+ }
+ if req.Component != "" {
+ m = m.Where("component like ?", "%"+req.Component+"%")
+ }
+ err = m.Fields(model.SysAuthRuleInfoRes{}).Order("weigh desc,id asc").Scan(&res)
+ liberr.ErrIsNil(ctx, err, "获取菜单失败")
+ })
+ return
+}
+
+// GetIsMenuList 获取isMenu=0|1
+func (s *ruleImpl) GetIsMenuList(ctx context.Context) ([]*model.SysAuthRuleInfoRes, error) {
+ list, err := s.GetMenuList(ctx)
+ if err != nil {
+ return nil, err
+ }
+ var gList = make([]*model.SysAuthRuleInfoRes, 0, len(list))
+ for _, v := range list {
+ if v.MenuType == 0 || v.MenuType == 1 {
+ gList = append(gList, v)
+ }
+ }
+ return gList, nil
+}
+
+// GetMenuList 获取所有菜单
+func (s *ruleImpl) GetMenuList(ctx context.Context) (list []*model.SysAuthRuleInfoRes, err error) {
+ cache := Cache()
+ //从缓存获取
+ iList := cache.GetOrSetFuncLock(ctx, consts.CacheSysAuthMenu, s.getMenuListFromDb, 0, consts.CacheSysAuthTag)
+ if iList != nil {
+ err = gconv.Struct(iList, &list)
+ liberr.ErrIsNil(ctx, err)
+ }
+ return
+}
+
+// 从数据库获取所有菜单
+func (s *ruleImpl) getMenuListFromDb(ctx context.Context) (value interface{}, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ var v []*model.SysAuthRuleInfoRes
+ //从数据库获取
+ err = dao.SysAuthRule.Ctx(ctx).
+ Fields(model.SysAuthRuleInfoRes{}).Order("weigh desc,id asc").Scan(&v)
+ liberr.ErrIsNil(ctx, err, "获取菜单数据失败")
+ value = v
+ })
+ return
+}
+
+// GetIsButtonList 获取所有按钮isMenu=2 菜单列表
+func (s *ruleImpl) GetIsButtonList(ctx context.Context) ([]*model.SysAuthRuleInfoRes, error) {
+ list, err := s.GetMenuList(ctx)
+ if err != nil {
+ return nil, err
+ }
+ var gList = make([]*model.SysAuthRuleInfoRes, 0, len(list))
+ for _, v := range list {
+ if v.MenuType == 2 {
+ gList = append(gList, v)
+ }
+ }
+ return gList, nil
+}
+
+// Add 添加菜单
+func (s *ruleImpl) Add(ctx context.Context, req *system.RuleAddReq) (err error) {
+ if s.menuNameExists(ctx, req.Name, 0) {
+ err = gerror.New("接口规则已经存在")
+ return
+ }
+ err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+ err = g.Try(ctx, func(ctx context.Context) {
+ //菜单数据
+ data := do.SysAuthRule{
+ Pid: req.Pid,
+ Name: req.Name,
+ Title: req.Title,
+ Icon: req.Icon,
+ Condition: req.Condition,
+ Remark: req.Remark,
+ MenuType: req.MenuType,
+ Weigh: req.Weigh,
+ IsHide: req.IsHide,
+ Path: req.Path,
+ Component: req.Component,
+ IsLink: req.IsLink,
+ IsIframe: req.IsIframe,
+ IsCached: req.IsCached,
+ Redirect: req.Redirect,
+ IsAffix: req.IsAffix,
+ LinkUrl: req.LinkUrl,
+ }
+ ruleId, e := dao.SysAuthRule.Ctx(ctx).TX(tx).InsertAndGetId(data)
+ liberr.ErrIsNil(ctx, e, "添加菜单失败")
+ e = s.BindRoleRule(ctx, ruleId, req.Roles)
+ liberr.ErrIsNil(ctx, e, "添加菜单失败")
+ })
+ return err
+ })
+ if err == nil {
+ // 删除相关缓存
+ Cache().Remove(ctx, consts.CacheSysAuthMenu)
+ }
+ return
+}
+
+// 检查菜单规则是否存在
+func (s *ruleImpl) menuNameExists(ctx context.Context, name string, id uint) bool {
+ m := dao.SysAuthRule.Ctx(ctx).Where("name=?", name)
+ if id != 0 {
+ m = m.Where("id!=?", id)
+ }
+ c, err := m.Fields(dao.SysAuthRule.Columns().Id).Limit(1).One()
+ if err != nil {
+ g.Log().Error(ctx, err)
+ return false
+ }
+ return !c.IsEmpty()
+}
+
+// BindRoleRule 绑定角色权限
+func (s *ruleImpl) BindRoleRule(ctx context.Context, ruleId interface{}, roleIds []uint) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ enforcer, e := CasbinEnforcer(ctx)
+ liberr.ErrIsNil(ctx, e)
+ for _, roleId := range roleIds {
+ _, err = enforcer.AddPolicy(fmt.Sprintf("%d", roleId), fmt.Sprintf("%d", ruleId), "All")
+ liberr.ErrIsNil(ctx, err)
+ }
+ })
+ return
+}
+
+func (s *ruleImpl) Get(ctx context.Context, id uint) (rule *entity.SysAuthRule, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ err = dao.SysAuthRule.Ctx(ctx).WherePri(id).Scan(&rule)
+ liberr.ErrIsNil(ctx, err, "获取菜单失败")
+ })
+ return
+}
+
+func (s *ruleImpl) GetMenuRoles(ctx context.Context, id uint) (roleIds []uint, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ enforcer, e := CasbinEnforcer(ctx)
+ liberr.ErrIsNil(ctx, e)
+ policies := enforcer.GetFilteredNamedPolicy("p", 1, gconv.String(id))
+ for _, policy := range policies {
+ roleIds = append(roleIds, gconv.Uint(policy[0]))
+ }
+ })
+ return
+}
+
+func (s *ruleImpl) Update(ctx context.Context, req *system.RuleUpdateReq) (err error) {
+ if s.menuNameExists(ctx, req.Name, req.Id) {
+ err = gerror.New("接口规则已经存在")
+ return
+ }
+ err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+ err = g.Try(ctx, func(ctx context.Context) {
+ //菜单数据
+ data := do.SysAuthRule{
+ Pid: req.Pid,
+ Name: req.Name,
+ Title: req.Title,
+ Icon: req.Icon,
+ Condition: req.Condition,
+ Remark: req.Remark,
+ MenuType: req.MenuType,
+ Weigh: req.Weigh,
+ IsHide: req.IsHide,
+ Path: req.Path,
+ Component: req.Component,
+ IsLink: req.IsLink,
+ IsIframe: req.IsIframe,
+ IsCached: req.IsCached,
+ Redirect: req.Redirect,
+ IsAffix: req.IsAffix,
+ LinkUrl: req.LinkUrl,
+ }
+ _, e := dao.SysAuthRule.Ctx(ctx).TX(tx).WherePri(req.Id).Update(data)
+ liberr.ErrIsNil(ctx, e, "添加菜单失败")
+ e = s.UpdateRoleRule(ctx, req.Id, req.Roles)
+ liberr.ErrIsNil(ctx, e, "添加菜单失败")
+ })
+ return err
+ })
+ if err == nil {
+ // 删除相关缓存
+ Cache().Remove(ctx, consts.CacheSysAuthMenu)
+ }
+ return
+}
+
+func (s *ruleImpl) UpdateRoleRule(ctx context.Context, ruleId uint, roleIds []uint) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ enforcer, e := CasbinEnforcer(ctx)
+ liberr.ErrIsNil(ctx, e)
+ //删除旧权限
+ _, e = enforcer.RemoveFilteredPolicy(1, gconv.String(ruleId))
+ liberr.ErrIsNil(ctx, e)
+ // 添加新权限
+ roleIdsStrArr := gconv.Strings(roleIds)
+ for _, v := range roleIdsStrArr {
+ _, e = enforcer.AddPolicy(v, gconv.String(ruleId), "All")
+ liberr.ErrIsNil(ctx, e)
+ }
+ })
+ return
+}
+
+func (s *ruleImpl) GetMenuListTree(pid uint, list []*model.SysAuthRuleInfoRes) []*model.SysAuthRuleTreeRes {
+ tree := make([]*model.SysAuthRuleTreeRes, 0, len(list))
+ for _, menu := range list {
+ if menu.Pid == pid {
+ t := &model.SysAuthRuleTreeRes{
+ SysAuthRuleInfoRes: menu,
+ }
+ child := s.GetMenuListTree(menu.Id, list)
+ if child != nil {
+ t.Children = child
+ }
+ tree = append(tree, t)
+ }
+ }
+ return tree
+}
+
+// DeleteMenuByIds 删除菜单
+func (s *ruleImpl) DeleteMenuByIds(ctx context.Context, ids []int) (err error) {
+ var list []*model.SysAuthRuleInfoRes
+ list, err = s.GetMenuList(ctx)
+ if err != nil {
+ return
+ }
+ childrenIds := make([]int, 0, len(list))
+ for _, id := range ids {
+ rules := s.FindSonByParentId(list, gconv.Uint(id))
+ for _, child := range rules {
+ childrenIds = append(childrenIds, gconv.Int(child.Id))
+ }
+ }
+ ids = append(ids, childrenIds...)
+ err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+ return g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysAuthRule.Ctx(ctx).Where("id in (?)", ids).Delete()
+ liberr.ErrIsNil(ctx, err, "删除失败")
+ //删除权限
+ enforcer, err := CasbinEnforcer(ctx)
+ liberr.ErrIsNil(ctx, err)
+ for _, v := range ids {
+ _, err = enforcer.RemoveFilteredPolicy(1, gconv.String(v))
+ liberr.ErrIsNil(ctx, err)
+ }
+ // 删除相关缓存
+ Cache().Remove(ctx, consts.CacheSysAuthMenu)
+ })
+ })
+ return
+}
+
+func (s *ruleImpl) FindSonByParentId(list []*model.SysAuthRuleInfoRes, pid uint) []*model.SysAuthRuleInfoRes {
+ children := make([]*model.SysAuthRuleInfoRes, 0, len(list))
+ for _, v := range list {
+ if v.Pid == pid {
+ children = append(children, v)
+ fChildren := s.FindSonByParentId(list, v.Id)
+ children = append(children, fChildren...)
+ }
+ }
+ return children
+}
diff --git a/internal/service/sys_config.go b/internal/service/sys_config.go
new file mode 100644
index 0000000..bf8a61b
--- /dev/null
+++ b/internal/service/sys_config.go
@@ -0,0 +1,184 @@
+/*
+* @desc:系统参数配置
+*
+*
+* @Date: 2022/3/18 11:55
+ */
+
+package service
+
+import (
+ "context"
+ "errors"
+ "github.com/gogf/gf/v2/errors/gerror"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/util/gconv"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/consts"
+ "tyj_admin/internal/dao"
+ "tyj_admin/internal/model/do"
+ "tyj_admin/internal/model/entity"
+ "tyj_admin/library/liberr"
+)
+
+type IConfig interface {
+ List(ctx context.Context, req *system.ConfigSearchReq) (res *system.ConfigSearchRes, err error)
+ Add(ctx context.Context, req *system.ConfigAddReq, userId uint64) (err error)
+ Get(ctx context.Context, id int) (res *system.ConfigGetRes, err error)
+ Edit(ctx context.Context, req *system.ConfigEditReq, userId uint64) (err error)
+ Delete(ctx context.Context, ids []int) (err error)
+ GetConfigByKey(ctx context.Context, key string) (config *entity.SysConfig, err error)
+ GetByKey(ctx context.Context, key string) (config *entity.SysConfig, err error)
+}
+
+type configTmpl struct {
+}
+
+var configService = configTmpl{}
+
+func Config() IConfig {
+ return &configService
+}
+
+// List 系统参数列表
+func (s *configTmpl) List(ctx context.Context, req *system.ConfigSearchReq) (res *system.ConfigSearchRes, err error) {
+ res = new(system.ConfigSearchRes)
+ err = g.Try(ctx, func(ctx context.Context) {
+ m := dao.SysConfig.Ctx(ctx)
+ if req != nil {
+ if req.ConfigName != "" {
+ m = m.Where("config_name like ?", "%"+req.ConfigName+"%")
+ }
+ if req.ConfigType != "" {
+ m = m.Where("config_type = ", gconv.Int(req.ConfigType))
+ }
+ if req.ConfigKey != "" {
+ m = m.Where("config_key like ?", "%"+req.ConfigKey+"%")
+ }
+ if len(req.DateRange) > 0 {
+ m = m.Where("created_at >= ? AND created_at<=?", req.DateRange[0], req.DateRange[1])
+ }
+ }
+ res.Total, err = m.Count()
+ liberr.ErrIsNil(ctx, err, "获取数据失败")
+ if req.PageNum == 0 {
+ req.PageNum = 1
+ }
+ res.CurrentPage = req.PageNum
+ if req.PageSize == 0 {
+ req.PageSize = consts.PageSize
+ }
+ err = m.Page(req.PageNum, req.PageSize).Order("config_id asc").Scan(&res.List)
+ liberr.ErrIsNil(ctx, err, "获取数据失败")
+ })
+ return
+}
+
+func (s *configTmpl) Add(ctx context.Context, req *system.ConfigAddReq, userId uint64) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ err = s.CheckConfigKeyUnique(ctx, req.ConfigKey)
+ liberr.ErrIsNil(ctx, err)
+ _, err = dao.SysConfig.Ctx(ctx).Insert(do.SysConfig{
+ ConfigName: req.ConfigName,
+ ConfigKey: req.ConfigKey,
+ ConfigValue: req.ConfigValue,
+ ConfigType: req.ConfigType,
+ CreateBy: userId,
+ Remark: req.Remark,
+ })
+ liberr.ErrIsNil(ctx, err, "添加系统参数失败")
+ //清除缓存
+ Cache().RemoveByTag(ctx, consts.CacheSysConfigTag)
+ })
+ return
+}
+
+// CheckConfigKeyUnique 验证参数键名是否存在
+func (s *configTmpl) CheckConfigKeyUnique(ctx context.Context, configKey string, configId ...int64) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ data := (*entity.SysConfig)(nil)
+ m := dao.SysConfig.Ctx(ctx).Fields(dao.SysConfig.Columns().ConfigId).Where(dao.SysConfig.Columns().ConfigKey, configKey)
+ if len(configId) > 0 {
+ m = m.Where(dao.SysConfig.Columns().ConfigId+" != ?", configId[0])
+ }
+ err = m.Scan(&data)
+ liberr.ErrIsNil(ctx, err, "校验失败")
+ if data != nil {
+ liberr.ErrIsNil(ctx, errors.New("参数键名重复"))
+ }
+ })
+ return
+}
+
+// Get 获取系统参数
+func (s *configTmpl) Get(ctx context.Context, id int) (res *system.ConfigGetRes, err error) {
+ res = new(system.ConfigGetRes)
+ err = g.Try(ctx, func(ctx context.Context) {
+ err = dao.SysConfig.Ctx(ctx).WherePri(id).Scan(&res.Data)
+ liberr.ErrIsNil(ctx, err, "获取系统参数失败")
+ })
+ return
+}
+
+// Edit 修改系统参数
+func (s *configTmpl) Edit(ctx context.Context, req *system.ConfigEditReq, userId uint64) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ err = s.CheckConfigKeyUnique(ctx, req.ConfigKey, req.ConfigId)
+ liberr.ErrIsNil(ctx, err)
+ _, err = dao.SysConfig.Ctx(ctx).WherePri(req.ConfigId).Update(do.SysConfig{
+ ConfigName: req.ConfigName,
+ ConfigKey: req.ConfigKey,
+ ConfigValue: req.ConfigValue,
+ ConfigType: req.ConfigType,
+ UpdateBy: userId,
+ Remark: req.Remark,
+ })
+ liberr.ErrIsNil(ctx, err, "修改系统参数失败")
+ //清除缓存
+ Cache().RemoveByTag(ctx, consts.CacheSysConfigTag)
+ })
+ return
+}
+
+// Delete 删除系统参数
+func (s *configTmpl) Delete(ctx context.Context, ids []int) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysConfig.Ctx(ctx).Delete(dao.SysConfig.Columns().ConfigId+" in (?)", ids)
+ liberr.ErrIsNil(ctx, err, "删除失败")
+ //清除缓存
+ Cache().RemoveByTag(ctx, consts.CacheSysConfigTag)
+ })
+ return
+}
+
+// GetConfigByKey 通过key获取参数(从缓存获取)
+func (s *configTmpl) GetConfigByKey(ctx context.Context, key string) (config *entity.SysConfig, err error) {
+ if key == "" {
+ err = gerror.New("参数key不能为空")
+ return
+ }
+ cache := Cache()
+ cf := cache.Get(ctx, consts.CacheSysConfigTag+key)
+ if cf != nil && !cf.IsEmpty() {
+ err = gconv.Struct(cf, &config)
+ return
+ }
+ config, err = s.GetByKey(ctx, key)
+ if err != nil {
+ return
+ }
+ if config != nil {
+ cache.Set(ctx, consts.CacheSysConfigTag+key, config, 0, consts.CacheSysConfigTag)
+ }
+ return
+}
+
+// GetByKey 通过key获取参数(从数据库获取)
+func (s *configTmpl) GetByKey(ctx context.Context, key string) (config *entity.SysConfig, err error) {
+ err = dao.SysConfig.Ctx(ctx).Where("config_key", key).Scan(&config)
+ if err != nil {
+ g.Log().Error(ctx, err)
+ err = gerror.New("获取配置失败")
+ }
+ return
+}
diff --git a/internal/service/sys_dept.go b/internal/service/sys_dept.go
new file mode 100644
index 0000000..c20e0aa
--- /dev/null
+++ b/internal/service/sys_dept.go
@@ -0,0 +1,169 @@
+/*
+* @desc:部门管理
+*
+*
+* @Date: 2022/4/6 15:19
+ */
+
+package service
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/text/gstr"
+ "github.com/gogf/gf/v2/util/gconv"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/consts"
+ "tyj_admin/internal/dao"
+ "tyj_admin/internal/model"
+ "tyj_admin/internal/model/do"
+ "tyj_admin/internal/model/entity"
+ "tyj_admin/library/liberr"
+)
+
+type IDept interface {
+ GetList(ctx context.Context, req *system.DeptSearchReq) (list []*entity.SysDept, err error)
+ Add(ctx context.Context, req *system.DeptAddReq) (err error)
+ Edit(ctx context.Context, req *system.DeptEditReq) (err error)
+ GetFromCache(ctx context.Context) (list []*entity.SysDept, err error)
+ Delete(ctx context.Context, id int64) (err error)
+ GetListTree(pid int64, list []*entity.SysDept) (deptTree []*model.SysDeptTreeRes)
+ FindSonByParentId(deptList []*entity.SysDept, deptId int64) []*entity.SysDept
+}
+
+var deptService = deptImpl{}
+
+func Dept() IDept {
+ return &deptService
+}
+
+type deptImpl struct {
+}
+
+func (s *deptImpl) GetList(ctx context.Context, req *system.DeptSearchReq) (list []*entity.SysDept, err error) {
+ list, err = s.GetFromCache(ctx)
+ if err != nil {
+ return
+ }
+ rList := make([]*entity.SysDept, 0, len(list))
+ if req.DeptName != "" || req.Status != "" {
+ for _, v := range list {
+ if req.DeptName != "" && !gstr.ContainsI(v.DeptName, req.DeptName) {
+ continue
+ }
+ if req.Status != "" && v.Status != gconv.Uint(req.Status) {
+ continue
+ }
+ rList = append(rList, v)
+ }
+ list = rList
+ }
+ return
+}
+
+func (s *deptImpl) GetFromCache(ctx context.Context) (list []*entity.SysDept, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ cache := Cache()
+ //从缓存获取
+ iList := cache.GetOrSetFuncLock(ctx, consts.CacheSysDept, func(ctx context.Context) (value interface{}, err error) {
+ err = dao.SysDept.Ctx(ctx).Scan(&list)
+ liberr.ErrIsNil(ctx, err, "获取部门列表失败")
+ value = list
+ return
+ }, 0, consts.CacheSysAuthTag)
+ if iList != nil {
+ err = gconv.Struct(iList, &list)
+ liberr.ErrIsNil(ctx, err)
+ }
+ })
+ return
+}
+
+// Add 添加部门
+func (s *deptImpl) Add(ctx context.Context, req *system.DeptAddReq) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysDept.Ctx(ctx).Insert(do.SysDept{
+ ParentId: req.ParentID,
+ DeptName: req.DeptName,
+ OrderNum: req.OrderNum,
+ Leader: req.Leader,
+ Phone: req.Phone,
+ Email: req.Email,
+ Status: req.Status,
+ CreatedBy: Context().GetUserId(ctx),
+ })
+ liberr.ErrIsNil(ctx, err, "添加部门失败")
+ // 删除缓存
+ Cache().Remove(ctx, consts.CacheSysDept)
+ })
+ return
+}
+
+// Edit 部门修改
+func (s *deptImpl) Edit(ctx context.Context, req *system.DeptEditReq) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysDept.Ctx(ctx).WherePri(req.DeptId).Update(do.SysDept{
+ ParentId: req.ParentID,
+ DeptName: req.DeptName,
+ OrderNum: req.OrderNum,
+ Leader: req.Leader,
+ Phone: req.Phone,
+ Email: req.Email,
+ Status: req.Status,
+ UpdatedBy: Context().GetUserId(ctx),
+ })
+ liberr.ErrIsNil(ctx, err, "修改部门失败")
+ // 删除缓存
+ Cache().Remove(ctx, consts.CacheSysDept)
+ })
+ return
+}
+
+func (s *deptImpl) Delete(ctx context.Context, id int64) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ var list []*entity.SysDept
+ err = dao.SysDept.Ctx(ctx).Scan(&list)
+ liberr.ErrIsNil(ctx, err, "不存在部门信息")
+ children := s.FindSonByParentId(list, id)
+ ids := make([]int64, 0, len(list))
+ for _, v := range children {
+ ids = append(ids, v.DeptId)
+ }
+ ids = append(ids, id)
+ _, err = dao.SysDept.Ctx(ctx).Where(dao.SysDept.Columns().DeptId+" in (?)", ids).Delete()
+ liberr.ErrIsNil(ctx, err, "删除部门失败")
+ // 删除缓存
+ Cache().Remove(ctx, consts.CacheSysDept)
+ })
+ return
+}
+
+func (s *deptImpl) FindSonByParentId(deptList []*entity.SysDept, deptId int64) []*entity.SysDept {
+ children := make([]*entity.SysDept, 0, len(deptList))
+ for _, v := range deptList {
+ if v.ParentId == deptId {
+ children = append(children, v)
+ fChildren := s.FindSonByParentId(deptList, v.DeptId)
+ children = append(children, fChildren...)
+ }
+ }
+ return children
+}
+
+// GetListTree 部门树形菜单
+func (s *deptImpl) GetListTree(pid int64, list []*entity.SysDept) (deptTree []*model.SysDeptTreeRes) {
+ deptTree = make([]*model.SysDeptTreeRes, 0, len(list))
+ for _, v := range list {
+ if v.ParentId == pid {
+ t := &model.SysDeptTreeRes{
+ SysDept: v,
+ }
+ child := s.GetListTree(v.DeptId, list)
+ if len(child) > 0 {
+ t.Children = child
+ }
+ deptTree = append(deptTree, t)
+ }
+ }
+ return
+}
diff --git a/internal/service/sys_dict_data.go b/internal/service/sys_dict_data.go
new file mode 100644
index 0000000..cc4424b
--- /dev/null
+++ b/internal/service/sys_dict_data.go
@@ -0,0 +1,178 @@
+/*
+* @desc:字典数据
+*
+*
+* @Date: 2022/3/18 11:55
+ */
+
+package service
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/text/gstr"
+ "github.com/gogf/gf/v2/util/gconv"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/consts"
+ "tyj_admin/internal/dao"
+ "tyj_admin/internal/model"
+ "tyj_admin/internal/model/do"
+ "tyj_admin/library/liberr"
+)
+
+type IDictData interface {
+ GetDictWithDataByType(ctx context.Context, req *system.GetDictReq) (dict *system.GetDictRes, err error)
+ List(ctx context.Context, req *system.DictDataSearchReq) (res *system.DictDataSearchRes, err error)
+ Add(ctx context.Context, req *system.DictDataAddReq, userId uint64) (err error)
+ Get(ctx context.Context, dictCode uint) (res *system.DictDataGetRes, err error)
+ Edit(ctx context.Context, req *system.DictDataEditReq, userId uint64) (err error)
+ Delete(ctx context.Context, ids []int) (err error)
+}
+
+type dictDataImpl struct {
+}
+
+var dictData = dictDataImpl{}
+
+func DictData() IDictData {
+ return &dictData
+}
+
+// GetDictWithDataByType 通过字典键类型获取选项
+func (s dictDataImpl) GetDictWithDataByType(ctx context.Context, req *system.GetDictReq) (dict *system.GetDictRes,
+ err error) {
+ cache := Cache()
+ cacheKey := consts.CacheSysDict + "_" + req.DictType
+ //从缓存获取
+ iDict := cache.GetOrSetFuncLock(ctx, cacheKey, func(ctx context.Context) (value interface{}, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ //从数据库获取
+ dict = &system.GetDictRes{}
+ //获取类型数据
+ err = dao.SysDictType.Ctx(ctx).Where(dao.SysDictType.Columns().DictType, req.DictType).
+ Where(dao.SysDictType.Columns().Status, 1).Fields(model.DictTypeRes{}).Scan(&dict.Info)
+ liberr.ErrIsNil(ctx, err, "获取字典类型失败")
+ err = dao.SysDictData.Ctx(ctx).Fields(model.DictDataRes{}).
+ Where(dao.SysDictData.Columns().DictType, req.DictType).
+ Order(dao.SysDictData.Columns().DictSort + " asc," +
+ dao.SysDictData.Columns().DictCode + " asc").
+ Scan(&dict.Values)
+ liberr.ErrIsNil(ctx, err, "获取字典数据失败")
+ })
+ value = dict
+ return
+ }, 0, consts.CacheSysDictTag)
+ if iDict != nil {
+ err = gconv.Struct(iDict, &dict)
+ if err != nil {
+ return
+ }
+ }
+ //设置给定的默认值
+ for _, v := range dict.Values {
+ if req.DefaultValue != "" {
+ if gstr.Equal(req.DefaultValue, v.DictValue) {
+ v.IsDefault = 1
+ } else {
+ v.IsDefault = 0
+ }
+ }
+ }
+ return
+}
+
+// List 获取字典数据
+func (s dictDataImpl) List(ctx context.Context, req *system.DictDataSearchReq) (res *system.DictDataSearchRes, err error) {
+ res = new(system.DictDataSearchRes)
+ err = g.Try(ctx, func(ctx context.Context) {
+ m := dao.SysDictData.Ctx(ctx)
+ if req != nil {
+ if req.DictLabel != "" {
+ m = m.Where(dao.SysDictData.Columns().DictLabel+" like ?", "%"+req.DictLabel+"%")
+ }
+ if req.Status != "" {
+ m = m.Where(dao.SysDictData.Columns().Status+" = ", gconv.Int(req.Status))
+ }
+ if req.DictType != "" {
+ m = m.Where(dao.SysDictData.Columns().DictType+" = ?", req.DictType)
+ }
+ res.Total, err = m.Count()
+ liberr.ErrIsNil(ctx, err, "获取字典数据失败")
+ if req.PageNum == 0 {
+ req.PageNum = 1
+ }
+ res.CurrentPage = req.PageNum
+ }
+ if req.PageSize == 0 {
+ req.PageSize = consts.PageSize
+ }
+ err = m.Page(req.PageNum, req.PageSize).Order(dao.SysDictData.Columns().DictSort + " asc," +
+ dao.SysDictData.Columns().DictCode + " asc").Scan(&res.List)
+ liberr.ErrIsNil(ctx, err, "获取字典数据失败")
+ })
+ return
+}
+
+func (s *dictDataImpl) Add(ctx context.Context, req *system.DictDataAddReq, userId uint64) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysDictData.Ctx(ctx).Insert(do.SysDictData{
+ DictSort: req.DictSort,
+ DictLabel: req.DictLabel,
+ DictValue: req.DictValue,
+ DictType: req.DictType,
+ CssClass: req.CssClass,
+ ListClass: req.ListClass,
+ IsDefault: req.IsDefault,
+ Status: req.Status,
+ CreateBy: userId,
+ Remark: req.Remark,
+ })
+ liberr.ErrIsNil(ctx, err, "添加字典数据失败")
+ //清除缓存
+ Cache().RemoveByTag(ctx, consts.CacheSysDictTag)
+ })
+ return
+}
+
+// Get 获取字典数据
+func (s *dictDataImpl) Get(ctx context.Context, dictCode uint) (res *system.DictDataGetRes, err error) {
+ res = new(system.DictDataGetRes)
+ err = g.Try(ctx, func(ctx context.Context) {
+ err = dao.SysDictData.Ctx(ctx).WherePri(dictCode).Scan(&res.Dict)
+ liberr.ErrIsNil(ctx, err, "获取字典数据失败")
+ })
+ return
+}
+
+// Edit 修改字典数据
+func (s *dictDataImpl) Edit(ctx context.Context, req *system.DictDataEditReq, userId uint64) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysDictData.Ctx(ctx).WherePri(req.DictCode).Update(do.SysDictData{
+ DictSort: req.DictSort,
+ DictLabel: req.DictLabel,
+ DictValue: req.DictValue,
+ DictType: req.DictType,
+ CssClass: req.CssClass,
+ ListClass: req.ListClass,
+ IsDefault: req.IsDefault,
+ Status: req.Status,
+ UpdateBy: userId,
+ Remark: req.Remark,
+ })
+ liberr.ErrIsNil(ctx, err, "修改字典数据失败")
+ //清除缓存
+ Cache().RemoveByTag(ctx, consts.CacheSysDictTag)
+ })
+ return
+}
+
+// Delete 删除字典数据
+func (s *dictDataImpl) Delete(ctx context.Context, ids []int) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysDictData.Ctx(ctx).Where(dao.SysDictData.Columns().DictCode+" in(?)", ids).Delete()
+ liberr.ErrIsNil(ctx, err, "删除字典数据失败")
+ //清除缓存
+ Cache().RemoveByTag(ctx, consts.CacheSysDictTag)
+ })
+ return
+}
diff --git a/internal/service/sys_dict_type.go b/internal/service/sys_dict_type.go
new file mode 100644
index 0000000..c1adcbb
--- /dev/null
+++ b/internal/service/sys_dict_type.go
@@ -0,0 +1,172 @@
+/*
+* @desc:字典类型
+*
+*
+* @Date: 2022/3/18 11:55
+ */
+
+package service
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/container/garray"
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/errors/gerror"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/util/gconv"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/consts"
+ "tyj_admin/internal/dao"
+ "tyj_admin/internal/model"
+ "tyj_admin/internal/model/do"
+ "tyj_admin/internal/model/entity"
+ "tyj_admin/library/liberr"
+)
+
+type IDictType interface {
+ List(ctx context.Context, req *system.DictTypeSearchReq) (res *system.DictTypeSearchRes, err error)
+ Add(ctx context.Context, req *system.DictTypeAddReq, userId uint64) (err error)
+ Get(ctx context.Context, req *system.DictTypeGetReq) (dictType *entity.SysDictType, err error)
+ Edit(ctx context.Context, req *system.DictTypeEditReq, userId uint64) (err error)
+ Delete(ctx context.Context, dictIds []int) (err error)
+}
+
+type dictTypeImpl struct {
+}
+
+var dictTypeService = dictTypeImpl{}
+
+func DictType() IDictType {
+ return &dictTypeService
+}
+
+// List 字典类型列表
+func (s *dictTypeImpl) List(ctx context.Context, req *system.DictTypeSearchReq) (res *system.DictTypeSearchRes, err error) {
+ res = new(system.DictTypeSearchRes)
+ err = g.Try(ctx, func(ctx context.Context) {
+ m := dao.SysDictType.Ctx(ctx)
+ if req.DictName != "" {
+ m = m.Where(dao.SysDictType.Columns().DictName+" like ?", "%"+req.DictName+"%")
+ }
+ if req.DictType != "" {
+ m = m.Where(dao.SysDictType.Columns().DictType+" like ?", "%"+req.DictType+"%")
+ }
+ if req.Status != "" {
+ m = m.Where(dao.SysDictType.Columns().Status+" = ", gconv.Int(req.Status))
+ }
+ res.Total, err = m.Count()
+ liberr.ErrIsNil(ctx, err, "获取字典类型失败")
+ if req.PageNum == 0 {
+ req.PageNum = 1
+ }
+ res.CurrentPage = req.PageNum
+ if req.PageSize == 0 {
+ req.PageSize = consts.PageSize
+ }
+ err = m.Fields(model.SysDictTypeInfoRes{}).Page(req.PageNum, req.PageSize).
+ Order(dao.SysDictType.Columns().DictId + " asc").Scan(&res.DictTypeList)
+ liberr.ErrIsNil(ctx, err, "获取字典类型失败")
+ })
+ return
+}
+
+// Add 添加字典类型
+func (s *dictTypeImpl) Add(ctx context.Context, req *system.DictTypeAddReq, userId uint64) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ err = s.ExistsDictType(ctx, req.DictType)
+ liberr.ErrIsNil(ctx, err)
+ _, err = dao.SysDictType.Ctx(ctx).Insert(do.SysDictType{
+ DictName: req.DictName,
+ DictType: req.DictType,
+ Status: req.Status,
+ CreateBy: userId,
+ Remark: req.Remark,
+ })
+ liberr.ErrIsNil(ctx, err, "添加字典类型失败")
+ //清除缓存
+ Cache().RemoveByTag(ctx, consts.CacheSysDictTag)
+ })
+ return
+}
+
+// Edit 修改字典类型
+func (s *dictTypeImpl) Edit(ctx context.Context, req *system.DictTypeEditReq, userId uint64) (err error) {
+ err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+ err = g.Try(ctx, func(ctx context.Context) {
+ err = s.ExistsDictType(ctx, req.DictType, req.DictId)
+ liberr.ErrIsNil(ctx, err)
+ dictType := (*entity.SysDictType)(nil)
+ e := dao.SysDictType.Ctx(ctx).Fields(dao.SysDictType.Columns().DictType).WherePri(req.DictId).Scan(&dictType)
+ liberr.ErrIsNil(ctx, e, "获取字典类型失败")
+ liberr.ValueIsNil(dictType, "字典类型不存在")
+ //修改字典类型
+ _, e = dao.SysDictType.Ctx(ctx).TX(tx).WherePri(req.DictId).Update(do.SysDictType{
+ DictName: req.DictName,
+ DictType: req.DictType,
+ Status: req.Status,
+ UpdateBy: userId,
+ Remark: req.Remark,
+ })
+ liberr.ErrIsNil(ctx, e, "修改字典类型失败")
+ //修改字典数据
+ _, e = dao.SysDictData.Ctx(ctx).TX(tx).Data(do.SysDictData{DictType: req.DictType}).
+ Where(dao.SysDictData.Columns().DictType, dictType.DictType).Update()
+ liberr.ErrIsNil(ctx, e, "修改字典数据失败")
+ //清除缓存
+ Cache().RemoveByTag(ctx, consts.CacheSysDictTag)
+ })
+ return err
+ })
+ return
+}
+
+func (s *dictTypeImpl) Get(ctx context.Context, req *system.DictTypeGetReq) (dictType *entity.SysDictType, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ err = dao.SysDictType.Ctx(ctx).Where(dao.SysDictType.Columns().DictId, req.DictId).Scan(&dictType)
+ liberr.ErrIsNil(ctx, err, "获取字典类型失败")
+ })
+ return
+}
+
+// ExistsDictType 检查类型是否已经存在
+func (s *dictTypeImpl) ExistsDictType(ctx context.Context, dictType string, dictId ...int64) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ m := dao.SysDictType.Ctx(ctx).Fields(dao.SysDictType.Columns().DictId).
+ Where(dao.SysDictType.Columns().DictType, dictType)
+ if len(dictId) > 0 {
+ m = m.Where(dao.SysDictType.Columns().DictId+" !=? ", dictId[0])
+ }
+ res, e := m.One()
+ liberr.ErrIsNil(ctx, e, "sql err")
+ if !res.IsEmpty() {
+ liberr.ErrIsNil(ctx, gerror.New("字典类型已存在"))
+ }
+ })
+ return
+}
+
+// Delete 删除字典类型
+func (s *dictTypeImpl) Delete(ctx context.Context, dictIds []int) (err error) {
+ err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+ err = g.Try(ctx, func(ctx context.Context) {
+ discs := ([]*entity.SysDictType)(nil)
+ err = dao.SysDictType.Ctx(ctx).Fields(dao.SysDictType.Columns().DictType).
+ Where(dao.SysDictType.Columns().DictId+" in (?) ", dictIds).Scan(&discs)
+ liberr.ErrIsNil(ctx, err, "删除失败")
+ types := garray.NewStrArray()
+ for _, dt := range discs {
+ types.Append(dt.DictType)
+ }
+ if types.Len() > 0 {
+ _, err = dao.SysDictType.Ctx(ctx).TX(tx).Delete(dao.SysDictType.Columns().DictId+" in (?) ", dictIds)
+ liberr.ErrIsNil(ctx, err, "删除类型失败")
+ _, err = dao.SysDictData.Ctx(ctx).TX(tx).Delete(dao.SysDictData.Columns().DictType+" in (?) ", types.Slice())
+ liberr.ErrIsNil(ctx, err, "删除字典数据失败")
+ }
+ //清除缓存
+ Cache().RemoveByTag(ctx, consts.CacheSysDictTag)
+ })
+ return err
+ })
+ return
+}
diff --git a/internal/service/sys_init.go b/internal/service/sys_init.go
new file mode 100644
index 0000000..94386bc
--- /dev/null
+++ b/internal/service/sys_init.go
@@ -0,0 +1,239 @@
+package service
+
+import (
+ "bufio"
+ "bytes"
+ "context"
+ "fmt"
+ "github.com/gogf/gf/v2/container/gvar"
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/database/gredis"
+ "github.com/gogf/gf/v2/frame/g"
+ "gopkg.in/yaml.v3"
+ "io"
+ "os"
+ "strings"
+ "time"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/library/libUtils"
+)
+
+type ISysInit interface {
+ // 生成配置文件
+ CreateConfigFile(ctx context.Context, req *system.DbInitCreateDbReq) (err error)
+ // 生成数据库
+ CreateDataBase(ctx context.Context, dbName string) (err error)
+ // 加载配置文件
+ LoadConfigFile() (err error)
+
+ // 是否已生成配置文件
+ IsCreateConfigFile() bool
+
+ //创建数据库
+ CreateDataBaseByName(ctx context.Context, req *system.DbInitCreateDbReq) (err error)
+}
+
+func SysInit() ISysInit {
+ return &sysInit{}
+}
+
+type sysInit struct{}
+
+var SysInitConfig map[string]*gvar.Var
+
+func init() {
+ ctx := context.TODO()
+ c, err := g.Cfg("initialize").Get(ctx, "initialize")
+ if err != nil {
+ g.Log().Panic(ctx, err)
+ }
+ SysInitConfig = make(map[string]*gvar.Var)
+ SysInitConfig = c.MapStrVar()
+}
+
+// 创建数据库
+func (s *sysInit) CreateDataBaseByName(ctx context.Context, req *system.DbInitCreateDbReq) (err error) {
+ db, err := gdb.New(gdb.ConfigNode{
+ Type: "mysql",
+ Host: req.DbHost,
+ Port: fmt.Sprintf("%d", req.DbPort),
+ User: req.DbUser,
+ Pass: req.DbPass,
+ })
+ if err != nil {
+ return
+ }
+ defer db.Close(ctx)
+
+ _, err = db.Exec(ctx, fmt.Sprintf("CREATE DATABASE IF NOT EXISTS `%s` DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci", req.DbName))
+ if err != nil {
+ return
+ }
+
+ return
+}
+
+// 是否已经生成配置文件
+func (s *sysInit) IsCreateConfigFile() bool {
+ return libUtils.FileIsExisted(SysInitConfig["configPath"].String())
+}
+
+// 加载配置文件
+func (s *sysInit) LoadConfigFile() (err error) {
+ var (
+ ctx = context.TODO()
+ )
+ fileName, _ := libUtils.ParseFilePath(SysInitConfig["configPath"].String())
+ // 加载数据库配置
+ c1, err := g.Cfg(fileName).Get(ctx, "database.default")
+ if err != nil {
+ return
+ }
+ dbConfig := c1.MapStrVar()
+ gdb.SetConfig(gdb.Config{
+ "default": gdb.ConfigGroup{
+ gdb.ConfigNode{
+ Host: dbConfig["host"].String(),
+ Port: dbConfig["port"].String(),
+ User: dbConfig["user"].String(),
+ Pass: dbConfig["pass"].String(),
+ Name: dbConfig["name"].String(),
+ Type: dbConfig["type"].String(),
+ Role: dbConfig["role"].String(),
+ Debug: dbConfig["debug"].Bool(),
+ Charset: dbConfig["charset"].String(),
+ DryRun: dbConfig["dryRun"].Bool(),
+ MaxIdleConnCount: dbConfig["maxIdle"].Int(),
+ MaxOpenConnCount: dbConfig["maxOpen"].Int(),
+ MaxConnLifeTime: dbConfig["maxLifetime"].Duration() * time.Second,
+ },
+ },
+ })
+
+ // 加载redis配置
+ c2, err := g.Cfg(fileName).Get(ctx, "redis.default")
+ if err != nil {
+ return
+ }
+ redisConfig := c2.Map()
+ err = gredis.SetConfigByMap(redisConfig)
+ if err != nil {
+ return
+ }
+ return
+}
+
+// 创建配置文件
+func (s *sysInit) CreateConfigFile(ctx context.Context, req *system.DbInitCreateDbReq) (err error) {
+ yamlConfig := req.ToDbInitConfig()
+ b, err := yaml.Marshal(yamlConfig)
+ if err != nil {
+ return
+ }
+ err = libUtils.WriteToFile(SysInitConfig["configPath"].String(), string(b))
+ return
+}
+
+// 读取sql文件
+func (s *sysInit) ReadSqlFile(path string) (sqlArr []string, err error) {
+
+ inputFile, inputError := os.Open(path)
+ if inputError != nil {
+ return nil, inputError
+ }
+ defer inputFile.Close()
+ inputReader := bufio.NewReader(inputFile)
+ var (
+ flag bool = true
+ buffer bytes.Buffer
+ )
+
+ for {
+ inputString, readerError := inputReader.ReadString('\n')
+ inputString = strings.TrimSpace(inputString)
+ if strings.HasPrefix(inputString, "--") {
+ flag = false
+ }
+ if strings.HasPrefix(inputString, "/*") {
+ flag = false
+ }
+
+ if flag && inputString != "" {
+ if strings.HasSuffix(inputString, ";") {
+ if buffer.Len() == 0 {
+ sqlArr = append(sqlArr, inputString)
+ } else {
+ buffer.WriteString(inputString)
+ sqlArr = append(sqlArr, buffer.String())
+ buffer.Reset()
+ }
+ } else {
+ buffer.WriteString(inputString + " ")
+ }
+ }
+
+ if !flag && strings.HasPrefix(inputString, "*/") {
+ flag = true
+ }
+
+ if !flag && strings.HasPrefix(inputString, "--") {
+ flag = true
+ }
+
+ if readerError == io.EOF {
+ break
+ }
+ }
+ return
+}
+
+// 创建数据库表
+func (s *sysInit) CreateDataBase(ctx context.Context, dbName string) (err error) {
+ sqlArr, err := s.ReadSqlFile(SysInitConfig["sqlFilePath"].String())
+ if err != nil {
+ return
+ }
+
+ if len(sqlArr) == 0 {
+ return
+ }
+ // newSqlArr := SqlArr(sqlArr).Split(10)
+ db := g.DB()
+ for _, item := range sqlArr {
+ _, err = db.Exec(ctx, item)
+ if err != nil {
+ return
+ }
+ }
+
+ return
+}
+
+type SqlArr []string
+
+func (arr SqlArr) Split(num int) (result SqlArr) {
+ if len(arr) == 0 {
+ return
+ }
+ var (
+ buffer bytes.Buffer
+ i int
+ )
+
+ for _, item := range arr {
+ buffer.WriteString(item)
+ i++
+ if i == num {
+ result = append(result, buffer.String())
+ buffer.Reset()
+ i = 0
+ }
+ }
+
+ if buffer.Len() > 0 {
+ result = append(result, buffer.String())
+ }
+
+ return
+
+}
diff --git a/internal/service/sys_login_log.go b/internal/service/sys_login_log.go
new file mode 100644
index 0000000..7c80829
--- /dev/null
+++ b/internal/service/sys_login_log.go
@@ -0,0 +1,109 @@
+/*
+* @desc:登录日志处理
+*
+*
+* @Date: 2022/3/8 11:42
+ */
+
+package service
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/grpool"
+ "github.com/gogf/gf/v2/util/gconv"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/consts"
+ "tyj_admin/internal/dao"
+ "tyj_admin/internal/model"
+ "tyj_admin/library/liberr"
+)
+
+type ISysLoginLog interface {
+ Invoke(ctx context.Context, data *model.LoginLogParams)
+ List(ctx context.Context, req *system.LoginLogSearchReq) (res *system.LoginLogSearchRes, err error)
+ DeleteLoginLogByIds(ctx context.Context, ids []int) (err error)
+ ClearLoginLog(ctx context.Context) (err error)
+}
+
+type sysLoginLogImpl struct {
+ Pool *grpool.Pool
+}
+
+var (
+ sysLoginLogService = sysLoginLogImpl{
+ Pool: grpool.New(100),
+ }
+)
+
+func SysLoginLog() ISysLoginLog {
+ return &sysLoginLogService
+}
+
+func (s *sysLoginLogImpl) Invoke(ctx context.Context, data *model.LoginLogParams) {
+ s.Pool.Add(
+ ctx,
+ func(ctx context.Context) {
+ //写入日志数据
+ User().LoginLog(ctx, data)
+ },
+ )
+}
+
+func (s *sysLoginLogImpl) List(ctx context.Context, req *system.LoginLogSearchReq) (res *system.LoginLogSearchRes, err error) {
+ res = new(system.LoginLogSearchRes)
+ if req.PageNum == 0 {
+ req.PageNum = 1
+ }
+ res.CurrentPage = req.PageNum
+ if req.PageSize == 0 {
+ req.PageSize = consts.PageSize
+ }
+ m := dao.SysLoginLog.Ctx(ctx)
+ order := "info_id DESC"
+ if req.LoginName != "" {
+ m = m.Where("login_name like ?", "%"+req.LoginName+"%")
+ }
+ if req.Status != "" {
+ m = m.Where("status", gconv.Int(req.Status))
+ }
+ if req.Ipaddr != "" {
+ m = m.Where("ipaddr like ?", "%"+req.Ipaddr+"%")
+ }
+ if req.LoginLocation != "" {
+ m = m.Where("login_location like ?", "%"+req.LoginLocation+"%")
+ }
+ if len(req.DateRange) != 0 {
+ m = m.Where("login_time >=? AND login_time <=?", req.DateRange[0], req.DateRange[1])
+ }
+ if req.SortName != "" {
+ if req.SortOrder != "" {
+ order = req.SortName + " " + req.SortOrder
+ } else {
+ order = req.SortName + " DESC"
+ }
+ }
+ err = g.Try(ctx, func(ctx context.Context) {
+ res.Total, err = m.Count()
+ liberr.ErrIsNil(ctx, err, "获取日志失败")
+ err = m.Page(req.PageNum, req.PageSize).Order(order).Scan(&res.List)
+ liberr.ErrIsNil(ctx, err, "获取日志数据失败")
+ })
+ return
+}
+
+func (s *sysLoginLogImpl) DeleteLoginLogByIds(ctx context.Context, ids []int) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysLoginLog.Ctx(ctx).Delete("info_id in (?)", ids)
+ liberr.ErrIsNil(ctx, err, "删除失败")
+ })
+ return
+}
+
+func (s *sysLoginLogImpl) ClearLoginLog(ctx context.Context) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, err = g.DB().Ctx(ctx).Exec(ctx, "truncate "+dao.SysLoginLog.Table())
+ liberr.ErrIsNil(ctx, err, "清除失败")
+ })
+ return
+}
diff --git a/internal/service/sys_post.go b/internal/service/sys_post.go
new file mode 100644
index 0000000..7e02210
--- /dev/null
+++ b/internal/service/sys_post.go
@@ -0,0 +1,116 @@
+/*
+* @desc:岗位处理
+*
+*
+* @Date: 2022/4/7 23:18
+ */
+
+package service
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/util/gconv"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/consts"
+ "tyj_admin/internal/dao"
+ "tyj_admin/internal/model/do"
+ "tyj_admin/internal/model/entity"
+ "tyj_admin/library/liberr"
+)
+
+type IPost interface {
+ List(ctx context.Context, req *system.PostSearchReq) (res *system.PostSearchRes, err error)
+ Add(ctx context.Context, req *system.PostAddReq) (err error)
+ Edit(ctx context.Context, req *system.PostEditReq) (err error)
+ Delete(ctx context.Context, ids []int) (err error)
+ GetUsedPost(ctx context.Context) (list []*entity.SysPost, err error)
+}
+
+type postImpl struct {
+}
+
+var postService = postImpl{}
+
+func Post() IPost {
+ return &postService
+}
+
+// List 岗位列表
+func (s *postImpl) List(ctx context.Context, req *system.PostSearchReq) (res *system.PostSearchRes, err error) {
+ res = new(system.PostSearchRes)
+ err = g.Try(ctx, func(ctx context.Context) {
+ m := dao.SysPost.Ctx(ctx)
+ if req != nil {
+ if req.PostCode != "" {
+ m = m.Where("post_code like ?", "%"+req.PostCode+"%")
+ }
+ if req.PostName != "" {
+ m = m.Where("post_name like ?", "%"+req.PostName+"%")
+ }
+ if req.Status != "" {
+ m = m.Where("status", gconv.Uint(req.Status))
+ }
+ }
+ res.Total, err = m.Count()
+ liberr.ErrIsNil(ctx, err, "获取岗位失败")
+ if req.PageNum == 0 {
+ req.PageNum = 1
+ }
+ if req.PageSize == 0 {
+ req.PageSize = consts.PageSize
+ }
+ res.CurrentPage = req.PageNum
+ err = m.Page(req.PageNum, req.PageSize).Order("post_sort asc,post_id asc").Scan(&res.PostList)
+ liberr.ErrIsNil(ctx, err, "获取岗位失败")
+ })
+ return
+}
+
+func (s *postImpl) Add(ctx context.Context, req *system.PostAddReq) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysPost.Ctx(ctx).Insert(do.SysPost{
+ PostCode: req.PostCode,
+ PostName: req.PostName,
+ PostSort: req.PostSort,
+ Status: req.Status,
+ Remark: req.Remark,
+ CreatedBy: Context().GetUserId(ctx),
+ })
+ liberr.ErrIsNil(ctx, err, "添加岗位失败")
+ })
+ return
+}
+
+func (s *postImpl) Edit(ctx context.Context, req *system.PostEditReq) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysPost.Ctx(ctx).WherePri(req.PostId).Update(do.SysPost{
+ PostCode: req.PostCode,
+ PostName: req.PostName,
+ PostSort: req.PostSort,
+ Status: req.Status,
+ Remark: req.Remark,
+ UpdatedBy: Context().GetUserId(ctx),
+ })
+ liberr.ErrIsNil(ctx, err, "修改岗位失败")
+ })
+ return
+}
+
+func (s *postImpl) Delete(ctx context.Context, ids []int) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysPost.Ctx(ctx).Where(dao.SysPost.Columns().PostId+" in(?)", ids).Delete()
+ liberr.ErrIsNil(ctx, err, "删除失败")
+ })
+ return
+}
+
+// GetUsedPost 获取正常状态的岗位
+func (s *postImpl) GetUsedPost(ctx context.Context) (list []*entity.SysPost, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ err = dao.SysPost.Ctx(ctx).Where(dao.SysPost.Columns().Status, 1).
+ Order(dao.SysPost.Columns().PostSort + " ASC, " + dao.SysPost.Columns().PostId + " ASC ").Scan(&list)
+ liberr.ErrIsNil(ctx, err, "获取岗位数据失败")
+ })
+ return
+}
diff --git a/internal/service/sys_role.go b/internal/service/sys_role.go
new file mode 100644
index 0000000..425f833
--- /dev/null
+++ b/internal/service/sys_role.go
@@ -0,0 +1,197 @@
+/*
+* @desc:角色处理
+*
+*
+* @Date: 2022/3/9 10:31
+ */
+
+package service
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/util/gconv"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/consts"
+ "tyj_admin/internal/dao"
+ "tyj_admin/internal/model/do"
+ "tyj_admin/internal/model/entity"
+ "tyj_admin/library/liberr"
+)
+
+type IRole interface {
+ GetRoleList(ctx context.Context) (list []*entity.SysRole, err error)
+ GetRoleListSearch(ctx context.Context, req *system.RoleListReq) (res *system.RoleListRes, err error)
+ AddRole(ctx context.Context, req *system.RoleAddReq) (err error)
+ Get(ctx context.Context, id uint) (res *entity.SysRole, err error)
+ GetFilteredNamedPolicy(ctx context.Context, id uint) (gpSlice []int, err error)
+ EditRole(ctx context.Context, req *system.RoleEditReq) error
+ DeleteByIds(ctx context.Context, ids []int64) (err error)
+}
+
+type roleImpl struct {
+}
+
+var roleService = roleImpl{}
+
+func Role() IRole {
+ return &roleService
+}
+
+func (s *roleImpl) GetRoleListSearch(ctx context.Context, req *system.RoleListReq) (res *system.RoleListRes, err error) {
+ res = new(system.RoleListRes)
+ g.Try(ctx, func(ctx context.Context) {
+ model := dao.SysRole.Ctx(ctx)
+ if req.RoleName != "" {
+ model = model.Where("name like ?", "%"+req.RoleName+"%")
+ }
+ if req.Status != "" {
+ model = model.Where("status", gconv.Int(req.Status))
+ }
+ res.Total, err = model.Count()
+ liberr.ErrIsNil(ctx, err, "获取角色数据失败")
+ if req.PageNum == 0 {
+ req.PageNum = 1
+ }
+ res.CurrentPage = req.PageNum
+ if req.PageSize == 0 {
+ req.PageSize = consts.PageSize
+ }
+ err = model.Page(res.CurrentPage, req.PageSize).Order("id asc").Scan(&res.List)
+ liberr.ErrIsNil(ctx, err, "获取数据失败")
+ })
+ return
+}
+
+// GetRoleList 获取角色列表
+func (s *roleImpl) GetRoleList(ctx context.Context) (list []*entity.SysRole, err error) {
+ cache := Cache()
+ //从缓存获取
+ iList := cache.GetOrSetFuncLock(ctx, consts.CacheSysRole, s.getRoleListFromDb, 0, consts.CacheSysAuthTag)
+ if iList != nil {
+ err = gconv.Struct(iList, &list)
+ }
+ return
+}
+
+// 从数据库获取所有角色
+func (s *roleImpl) getRoleListFromDb(ctx context.Context) (value interface{}, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ var v []*entity.SysRole
+ //从数据库获取
+ err = dao.SysRole.Ctx(ctx).
+ Order(dao.SysRole.Columns().ListOrder + " asc," + dao.SysRole.Columns().Id + " asc").
+ Scan(&v)
+ liberr.ErrIsNil(ctx, err, "获取角色数据失败")
+ value = v
+ })
+ return
+}
+
+// AddRoleRule 添加角色权限
+func (s *roleImpl) AddRoleRule(ctx context.Context, ruleIds []uint, roleId int64) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ enforcer, e := CasbinEnforcer(ctx)
+ liberr.ErrIsNil(ctx, e)
+ ruleIdsStr := gconv.Strings(ruleIds)
+ for _, v := range ruleIdsStr {
+ _, err = enforcer.AddPolicy(gconv.String(roleId), v, "All")
+ liberr.ErrIsNil(ctx, err)
+ }
+ })
+ return
+}
+
+// DelRoleRule 删除角色权限
+func (s *roleImpl) DelRoleRule(ctx context.Context, roleId int64) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ enforcer, e := CasbinEnforcer(ctx)
+ liberr.ErrIsNil(ctx, e)
+ _, err = enforcer.RemoveFilteredPolicy(0, gconv.String(roleId))
+ liberr.ErrIsNil(ctx, e)
+ })
+ return
+}
+
+func (s *roleImpl) AddRole(ctx context.Context, req *system.RoleAddReq) (err error) {
+ err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+ err = g.Try(ctx, func(ctx context.Context) {
+ roleId, e := dao.SysRole.Ctx(ctx).TX(tx).InsertAndGetId(req)
+ liberr.ErrIsNil(ctx, e, "添加角色失败")
+ //添加角色权限
+ e = s.AddRoleRule(ctx, req.MenuIds, roleId)
+ liberr.ErrIsNil(ctx, e)
+ //清除缓存
+ Cache().Remove(ctx, consts.CacheSysRole)
+ })
+ return err
+ })
+ return
+}
+
+func (s *roleImpl) Get(ctx context.Context, id uint) (res *entity.SysRole, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ err = dao.SysRole.Ctx(ctx).WherePri(id).Scan(&res)
+ liberr.ErrIsNil(ctx, err, "获取角色信息失败")
+ })
+ return
+}
+
+// GetFilteredNamedPolicy 获取角色关联的菜单规则
+func (s *roleImpl) GetFilteredNamedPolicy(ctx context.Context, id uint) (gpSlice []int, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ enforcer, e := CasbinEnforcer(ctx)
+ liberr.ErrIsNil(ctx, e)
+ gp := enforcer.GetFilteredNamedPolicy("p", 0, gconv.String(id))
+ gpSlice = make([]int, len(gp))
+ for k, v := range gp {
+ gpSlice[k] = gconv.Int(v[1])
+ }
+ })
+ return
+}
+
+// EditRole 修改角色
+func (s *roleImpl) EditRole(ctx context.Context, req *system.RoleEditReq) (err error) {
+ err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, e := dao.SysRole.Ctx(ctx).TX(tx).WherePri(req.Id).Data(&do.SysRole{
+ Status: req.Status,
+ ListOrder: req.ListOrder,
+ Name: req.Name,
+ Remark: req.Remark,
+ }).Update()
+ liberr.ErrIsNil(ctx, e, "修改角色失败")
+ //删除角色权限
+ e = s.DelRoleRule(ctx, req.Id)
+ liberr.ErrIsNil(ctx, e)
+ //添加角色权限
+ e = s.AddRoleRule(ctx, req.MenuIds, req.Id)
+ liberr.ErrIsNil(ctx, e)
+ //清除缓存
+ Cache().Remove(ctx, consts.CacheSysRole)
+ })
+ return err
+ })
+ return
+}
+
+// DeleteByIds 删除角色
+func (s *roleImpl) DeleteByIds(ctx context.Context, ids []int64) (err error) {
+ err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysRole.Ctx(ctx).TX(tx).Where(dao.SysRole.Columns().Id+" in(?)", ids).Delete()
+ liberr.ErrIsNil(ctx, err, "删除角色失败")
+ //删除角色权限
+ for _, v := range ids {
+ err = s.DelRoleRule(ctx, v)
+ liberr.ErrIsNil(ctx, err)
+ }
+ //清除缓存
+ Cache().Remove(ctx, consts.CacheSysRole)
+ })
+ return err
+ })
+ return
+}
diff --git a/internal/service/sys_user.go b/internal/service/sys_user.go
new file mode 100644
index 0000000..4501183
--- /dev/null
+++ b/internal/service/sys_user.go
@@ -0,0 +1,626 @@
+/*
+* @desc:用户处理
+*
+*
+* @Date: 2022/3/7 9:50
+ */
+
+package service
+
+import (
+ "context"
+ "fmt"
+ "github.com/gogf/gf/v2/container/gset"
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/errors/gerror"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gtime"
+ "github.com/gogf/gf/v2/text/gstr"
+ "github.com/gogf/gf/v2/util/gconv"
+ "github.com/gogf/gf/v2/util/grand"
+ "github.com/mssola/user_agent"
+ "tyj_admin/api/v1/system"
+ "tyj_admin/internal/consts"
+ "tyj_admin/internal/dao"
+ model2 "tyj_admin/internal/model"
+ "tyj_admin/internal/model/do"
+ "tyj_admin/internal/model/entity"
+ "tyj_admin/library/libUtils"
+ "tyj_admin/library/liberr"
+)
+
+type IUser interface {
+ GetAdminUserByUsernamePassword(ctx context.Context, req *system.UserLoginReq) (user *model2.LoginUserRes, err error)
+ LoginLog(ctx context.Context, params *model2.LoginLogParams)
+ UpdateLoginInfo(ctx context.Context, id uint64, ip string) (err error)
+ NotCheckAuthAdminIds(ctx context.Context) *gset.Set
+ GetAdminRules(ctx context.Context, userId uint64) (menuList []*model2.UserMenus, permissions []string, err error)
+ List(ctx context.Context, req *system.UserSearchReq) (total int, userList []*entity.SysUser, err error)
+ GetUsersRoleDept(ctx context.Context, userList []*entity.SysUser) (users []*model2.SysUserRoleDeptRes, err error)
+ Add(ctx context.Context, req *system.UserAddReq) (err error)
+ GetEditUser(ctx context.Context, id uint64) (res *system.UserGetEditRes, err error)
+ Edit(ctx context.Context, req *system.UserEditReq) (err error)
+ ResetUserPwd(ctx context.Context, req *system.UserResetPwdReq) (err error)
+ ChangeUserStatus(ctx context.Context, req *system.UserStatusReq) (err error)
+ Delete(ctx context.Context, ids []int) (err error)
+}
+
+type userImpl struct {
+ CasBinUserPrefix string //CasBin 用户id前缀
+}
+
+var (
+ notCheckAuthAdminIds *gset.Set //无需验证权限的用户id
+ userService = userImpl{
+ CasBinUserPrefix: "u_",
+ }
+)
+
+func User() IUser {
+ return &userService
+}
+
+func (s *userImpl) NotCheckAuthAdminIds(ctx context.Context) *gset.Set {
+ ids := g.Cfg().MustGet(ctx, "system.notCheckAuthAdminIds")
+ if !g.IsNil(ids) {
+ notCheckAuthAdminIds = gset.NewFrom(ids)
+ }
+ return notCheckAuthAdminIds
+}
+
+func (s *userImpl) GetAdminUserByUsernamePassword(ctx context.Context, req *system.UserLoginReq) (user *model2.LoginUserRes, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ user, err = s.GetUserByUsername(ctx, req.Username)
+ liberr.ErrIsNil(ctx, err)
+ liberr.ValueIsNil(user, "账号密码错误")
+ //验证密码
+ if libUtils.EncryptPassword(req.Password, user.UserSalt) != user.UserPassword {
+ liberr.ErrIsNil(ctx, gerror.New("账号密码错误"))
+ }
+ //账号状态
+ if user.UserStatus == 0 {
+ liberr.ErrIsNil(ctx, gerror.New("账号已被冻结"))
+ }
+ })
+ return
+}
+
+// GetUserByUsername 通过用户名获取用户信息
+func (s *userImpl) GetUserByUsername(ctx context.Context, userName string) (user *model2.LoginUserRes, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ user = &model2.LoginUserRes{}
+ err = dao.SysUser.Ctx(ctx).Fields(user).Where(dao.SysUser.Columns().UserName, userName).Scan(user)
+ liberr.ErrIsNil(ctx, err, "账号密码错误")
+ })
+ return
+}
+
+// LoginLog 记录登录日志
+func (s *userImpl) LoginLog(ctx context.Context, params *model2.LoginLogParams) {
+ ua := user_agent.New(params.UserAgent)
+ browser, _ := ua.Browser()
+ loginData := &do.SysLoginLog{
+ LoginName: params.Username,
+ Ipaddr: params.Ip,
+ LoginLocation: libUtils.GetCityByIp(params.Ip),
+ Browser: browser,
+ Os: ua.OS(),
+ Status: params.Status,
+ Msg: params.Msg,
+ LoginTime: gtime.Now(),
+ Module: params.Module,
+ }
+ _, err := dao.SysLoginLog.Ctx(ctx).Insert(loginData)
+ if err != nil {
+ g.Log().Error(ctx, err)
+ }
+}
+
+func (s *userImpl) UpdateLoginInfo(ctx context.Context, id uint64, ip string) (err error) {
+ g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysUser.Ctx(ctx).WherePri(id).Update(g.Map{
+ dao.SysUser.Columns().LastLoginIp: ip,
+ dao.SysUser.Columns().LastLoginTime: gtime.Now(),
+ })
+ liberr.ErrIsNil(ctx, err, "更新用户登录信息失败")
+ })
+ return
+}
+
+// GetAdminRules 获取用户菜单数据
+func (s *userImpl) GetAdminRules(ctx context.Context, userId uint64) (menuList []*model2.UserMenus, permissions []string, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ //是否超管
+ isSuperAdmin := false
+ //获取无需验证权限的用户id
+ s.NotCheckAuthAdminIds(ctx).Iterator(func(v interface{}) bool {
+ if gconv.Uint64(v) == userId {
+ isSuperAdmin = true
+ return false
+ }
+ return true
+ })
+ //获取用户菜单数据
+ allRoles, err := Role().GetRoleList(ctx)
+ liberr.ErrIsNil(ctx, err)
+ roles, err := s.GetAdminRole(ctx, userId, allRoles)
+ liberr.ErrIsNil(ctx, err)
+ name := make([]string, len(roles))
+ roleIds := make([]uint, len(roles))
+ for k, v := range roles {
+ name[k] = v.Name
+ roleIds[k] = v.Id
+ }
+ //获取菜单信息
+ if isSuperAdmin {
+ //超管获取所有菜单
+ permissions = []string{"*/*/*"}
+ menuList, err = s.GetAllMenus(ctx)
+ liberr.ErrIsNil(ctx, err)
+ } else {
+ menuList, err = s.GetAdminMenusByRoleIds(ctx, roleIds)
+ liberr.ErrIsNil(ctx, err)
+ permissions, err = s.GetPermissions(ctx, roleIds)
+ liberr.ErrIsNil(ctx, err)
+ }
+ })
+ return
+}
+
+// GetAdminRole 获取用户角色
+func (s *userImpl) GetAdminRole(ctx context.Context, userId uint64, allRoleList []*entity.SysRole) (roles []*entity.SysRole, err error) {
+ var roleIds []uint
+ roleIds, err = s.GetAdminRoleIds(ctx, userId)
+ if err != nil {
+ return
+ }
+ roles = make([]*entity.SysRole, 0, len(allRoleList))
+ for _, v := range allRoleList {
+ for _, id := range roleIds {
+ if id == v.Id {
+ roles = append(roles, v)
+ }
+ }
+ if len(roles) == len(roleIds) {
+ break
+ }
+ }
+ return
+}
+
+// GetAdminRoleIds 获取用户角色ids
+func (s *userImpl) GetAdminRoleIds(ctx context.Context, userId uint64) (roleIds []uint, err error) {
+ enforcer, e := CasbinEnforcer(ctx)
+ if e != nil {
+ err = e
+ return
+ }
+ //查询关联角色规则
+ groupPolicy := enforcer.GetFilteredGroupingPolicy(0, fmt.Sprintf("%s%d", s.CasBinUserPrefix, userId))
+ if len(groupPolicy) > 0 {
+ roleIds = make([]uint, len(groupPolicy))
+ //得到角色id的切片
+ for k, v := range groupPolicy {
+ roleIds[k] = gconv.Uint(v[1])
+ }
+ }
+ return
+}
+
+func (s *userImpl) GetAllMenus(ctx context.Context) (menus []*model2.UserMenus, err error) {
+ //获取所有开启的菜单
+ var allMenus []*model2.SysAuthRuleInfoRes
+ allMenus, err = Rule().GetIsMenuList(ctx)
+ if err != nil {
+ return
+ }
+ menus = make([]*model2.UserMenus, len(allMenus))
+ for k, v := range allMenus {
+ var menu *model2.UserMenu
+ menu = s.setMenuData(menu, v)
+ menus[k] = &model2.UserMenus{UserMenu: menu}
+ }
+ menus = s.GetMenusTree(menus, 0)
+ return
+}
+
+func (s *userImpl) GetAdminMenusByRoleIds(ctx context.Context, roleIds []uint) (menus []*model2.UserMenus, err error) {
+ //获取角色对应的菜单id
+ err = g.Try(ctx, func(ctx context.Context) {
+ enforcer, e := CasbinEnforcer(ctx)
+ liberr.ErrIsNil(ctx, e)
+ menuIds := map[int64]int64{}
+ for _, roleId := range roleIds {
+ //查询当前权限
+ gp := enforcer.GetFilteredPolicy(0, gconv.String(roleId))
+ for _, p := range gp {
+ mid := gconv.Int64(p[1])
+ menuIds[mid] = mid
+ }
+ }
+ //获取所有开启的菜单
+ allMenus, err := Rule().GetIsMenuList(ctx)
+ liberr.ErrIsNil(ctx, err)
+ menus = make([]*model2.UserMenus, 0, len(allMenus))
+ for _, v := range allMenus {
+ if _, ok := menuIds[gconv.Int64(v.Id)]; gstr.Equal(v.Condition, "nocheck") || ok {
+ var roleMenu *model2.UserMenu
+ roleMenu = s.setMenuData(roleMenu, v)
+ menus = append(menus, &model2.UserMenus{UserMenu: roleMenu})
+ }
+ }
+ menus = s.GetMenusTree(menus, 0)
+ })
+ return
+}
+
+func (s *userImpl) GetMenusTree(menus []*model2.UserMenus, pid uint) []*model2.UserMenus {
+ returnList := make([]*model2.UserMenus, 0, len(menus))
+ for _, menu := range menus {
+ if menu.Pid == pid {
+ menu.Children = s.GetMenusTree(menus, menu.Id)
+ returnList = append(returnList, menu)
+ }
+ }
+ return returnList
+}
+
+func (s *userImpl) setMenuData(menu *model2.UserMenu, entity *model2.SysAuthRuleInfoRes) *model2.UserMenu {
+ menu = &model2.UserMenu{
+ Id: entity.Id,
+ Pid: entity.Pid,
+ Name: gstr.CaseCamelLower(gstr.Replace(entity.Name, "/", "_")),
+ Component: entity.Component,
+ Path: entity.Path,
+ MenuMeta: &model2.MenuMeta{
+ Icon: entity.Icon,
+ Title: entity.Title,
+ IsLink: "",
+ IsHide: entity.IsHide == 1,
+ IsKeepAlive: entity.IsCached == 1,
+ IsAffix: entity.IsAffix == 1,
+ IsIframe: entity.IsIframe == 1,
+ },
+ }
+ if menu.MenuMeta.IsIframe || entity.IsLink == 1 {
+ menu.MenuMeta.IsLink = entity.LinkUrl
+ }
+ return menu
+}
+
+func (s *userImpl) GetPermissions(ctx context.Context, roleIds []uint) (userButtons []string, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ //获取角色对应的菜单id
+ enforcer, err := CasbinEnforcer(ctx)
+ liberr.ErrIsNil(ctx, err)
+ menuIds := map[int64]int64{}
+ for _, roleId := range roleIds {
+ //查询当前权限
+ gp := enforcer.GetFilteredPolicy(0, gconv.String(roleId))
+ for _, p := range gp {
+ mid := gconv.Int64(p[1])
+ menuIds[mid] = mid
+ }
+ }
+ //获取所有开启的按钮
+ allButtons, err := Rule().GetIsButtonList(ctx)
+ liberr.ErrIsNil(ctx, err)
+ userButtons = make([]string, 0, len(allButtons))
+ for _, button := range allButtons {
+ if _, ok := menuIds[gconv.Int64(button.Id)]; gstr.Equal(button.Condition, "nocheck") || ok {
+ userButtons = append(userButtons, button.Name)
+ }
+ }
+ })
+ return
+}
+
+// List 用户列表
+func (s *userImpl) List(ctx context.Context, req *system.UserSearchReq) (total int, userList []*entity.SysUser, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ m := dao.SysUser.Ctx(ctx)
+ if req.KeyWords != "" {
+ keyWords := "%" + req.KeyWords + "%"
+ m = m.Where("user_name like ? or user_nickname like ?", keyWords, keyWords)
+ }
+ if req.DeptId != "" {
+ deptIds, e := s.getSearchDeptIds(ctx, gconv.Int64(req.DeptId))
+ liberr.ErrIsNil(ctx, e)
+ m = m.Where("dept_id in (?)", deptIds)
+ }
+ if req.Status != "" {
+ m = m.Where("user_status", gconv.Int(req.Status))
+ }
+ if req.Mobile != "" {
+ m = m.Where("mobile like ?", "%"+req.Mobile+"%")
+ }
+ if len(req.DateRange) > 0 {
+ m = m.Where("created_at >=? AND created_at <=?", req.DateRange[0], req.DateRange[1])
+ }
+ if req.PageSize == 0 {
+ req.PageSize = consts.PageSize
+ }
+ if req.PageNum == 0 {
+ req.PageNum = 1
+ }
+ total, err = m.Count()
+ liberr.ErrIsNil(ctx, err, "获取用户数据失败")
+ err = m.FieldsEx(dao.SysUser.Columns().UserPassword, dao.SysUser.Columns().UserSalt).
+ Page(req.PageNum, req.PageSize).Order("id asc").Scan(&userList)
+ liberr.ErrIsNil(ctx, err, "获取用户列表失败")
+ })
+ return
+}
+
+// GetUsersRoleDept 获取多个用户角色 部门信息
+func (s *userImpl) GetUsersRoleDept(ctx context.Context, userList []*entity.SysUser) (users []*model2.SysUserRoleDeptRes, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ allRoles, e := Role().GetRoleList(ctx)
+ liberr.ErrIsNil(ctx, e)
+ depts, e := Dept().GetFromCache(ctx)
+ liberr.ErrIsNil(ctx, e)
+ users = make([]*model2.SysUserRoleDeptRes, len(userList))
+ for k, u := range userList {
+ var dept *entity.SysDept
+ users[k] = &model2.SysUserRoleDeptRes{
+ SysUser: u,
+ }
+ for _, d := range depts {
+ if u.DeptId == uint64(d.DeptId) {
+ dept = d
+ }
+ }
+ users[k].Dept = dept
+ roles, e := s.GetAdminRole(ctx, u.Id, allRoles)
+ liberr.ErrIsNil(ctx, e)
+ for _, r := range roles {
+ users[k].RoleInfo = append(users[k].RoleInfo, &model2.SysUserRoleInfoRes{RoleId: r.Id, Name: r.Name})
+ }
+ }
+ })
+ return
+}
+
+func (s *userImpl) getSearchDeptIds(ctx context.Context, deptId int64) (deptIds []int64, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ deptAll, e := Dept().GetFromCache(ctx)
+ liberr.ErrIsNil(ctx, e)
+ deptWithChildren := Dept().FindSonByParentId(deptAll, gconv.Int64(deptId))
+ deptIds = make([]int64, len(deptWithChildren))
+ for k, v := range deptWithChildren {
+ deptIds[k] = v.DeptId
+ }
+ deptIds = append(deptIds, deptId)
+ })
+ return
+}
+
+func (s *userImpl) Add(ctx context.Context, req *system.UserAddReq) (err error) {
+ err = s.userNameOrMobileExists(ctx, req.UserName, req.Mobile)
+ if err != nil {
+ return
+ }
+ req.UserSalt = grand.S(10)
+ req.Password = libUtils.EncryptPassword(req.Password, req.UserSalt)
+ err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+ err = g.Try(ctx, func(ctx context.Context) {
+ userId, e := dao.SysUser.Ctx(ctx).TX(tx).InsertAndGetId(do.SysUser{
+ UserName: req.UserName,
+ Mobile: req.Mobile,
+ UserNickname: req.NickName,
+ UserPassword: req.Password,
+ UserSalt: req.UserSalt,
+ UserStatus: req.Status,
+ UserEmail: req.Email,
+ Sex: req.Sex,
+ DeptId: req.DeptId,
+ Remark: req.Remark,
+ IsAdmin: req.IsAdmin,
+ })
+ liberr.ErrIsNil(ctx, e, "添加用户失败")
+ e = s.addUserRole(ctx, req.RoleIds, userId)
+ liberr.ErrIsNil(ctx, e, "设置用户权限失败")
+ e = s.AddUserPost(ctx, tx, req.PostIds, userId)
+ liberr.ErrIsNil(ctx, e)
+ })
+ return err
+ })
+ return
+}
+
+func (s *userImpl) Edit(ctx context.Context, req *system.UserEditReq) (err error) {
+ err = s.userNameOrMobileExists(ctx, "", req.Mobile, req.UserId)
+ if err != nil {
+ return
+ }
+ err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysUser.Ctx(ctx).TX(tx).WherePri(req.UserId).Update(do.SysUser{
+ Mobile: req.Mobile,
+ UserNickname: req.NickName,
+ UserStatus: req.Status,
+ UserEmail: req.Email,
+ Sex: req.Sex,
+ DeptId: req.DeptId,
+ Remark: req.Remark,
+ IsAdmin: req.IsAdmin,
+ })
+ liberr.ErrIsNil(ctx, err, "修改用户信息失败")
+ //设置用户所属角色信息
+ err = s.EditUserRole(ctx, req.RoleIds, req.UserId)
+ liberr.ErrIsNil(ctx, err, "设置用户权限失败")
+ err = s.AddUserPost(ctx, tx, req.PostIds, req.UserId)
+ liberr.ErrIsNil(ctx, err)
+ })
+ return err
+ })
+ return
+}
+
+// AddUserPost 添加用户岗位信息
+func (s *userImpl) AddUserPost(ctx context.Context, tx *gdb.TX, postIds []int64, userId int64) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ //删除旧岗位信息
+ _, err = dao.SysUserPost.Ctx(ctx).TX(tx).Where(dao.SysUserPost.Columns().UserId, userId).Delete()
+ liberr.ErrIsNil(ctx, err, "设置用户岗位失败")
+ if len(postIds) == 0 {
+ return
+ }
+ //添加用户岗位信息
+ data := g.List{}
+ for _, v := range postIds {
+ data = append(data, g.Map{
+ dao.SysUserPost.Columns().UserId: userId,
+ dao.SysUserPost.Columns().PostId: v,
+ })
+ }
+ _, err = dao.SysUserPost.Ctx(ctx).TX(tx).Data(data).Insert()
+ liberr.ErrIsNil(ctx, err, "设置用户岗位失败")
+ })
+ return
+}
+
+// AddUserRole 添加用户角色信息
+func (s *userImpl) addUserRole(ctx context.Context, roleIds []int64, userId int64) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ enforcer, e := CasbinEnforcer(ctx)
+ liberr.ErrIsNil(ctx, e)
+ for _, v := range roleIds {
+ _, e = enforcer.AddGroupingPolicy(fmt.Sprintf("%s%d", s.CasBinUserPrefix, userId), gconv.String(v))
+ liberr.ErrIsNil(ctx, e)
+ }
+ })
+ return
+}
+
+// EditUserRole 修改用户角色信息
+func (s *userImpl) EditUserRole(ctx context.Context, roleIds []int64, userId int64) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ enforcer, e := CasbinEnforcer(ctx)
+ liberr.ErrIsNil(ctx, e)
+
+ //删除用户旧角色信息
+ enforcer.RemoveFilteredGroupingPolicy(0, fmt.Sprintf("%s%d", s.CasBinUserPrefix, userId))
+ for _, v := range roleIds {
+ _, err = enforcer.AddGroupingPolicy(fmt.Sprintf("%s%d", s.CasBinUserPrefix, userId), gconv.String(v))
+ liberr.ErrIsNil(ctx, err)
+ }
+ })
+ return
+}
+
+func (s *userImpl) userNameOrMobileExists(ctx context.Context, userName, mobile string, id ...int64) error {
+ user := (*entity.SysUser)(nil)
+ err := g.Try(ctx, func(ctx context.Context) {
+ m := dao.SysUser.Ctx(ctx)
+ if len(id) > 0 {
+ m = m.Where(dao.SysUser.Columns().Id+" != ", id)
+ }
+ m = m.Where(fmt.Sprintf("%s='%s' OR %s='%s'",
+ dao.SysUser.Columns().UserName,
+ userName,
+ dao.SysUser.Columns().Mobile,
+ mobile))
+ err := m.Limit(1).Scan(&user)
+ liberr.ErrIsNil(ctx, err, "获取用户信息失败")
+ if user == nil {
+ return
+ }
+ if user.UserName == userName {
+ liberr.ErrIsNil(ctx, gerror.New("用户名已存在"))
+ }
+ if user.Mobile == mobile {
+ liberr.ErrIsNil(ctx, gerror.New("手机号已存在"))
+ }
+ })
+ return err
+}
+
+// GetEditUser 获取编辑用户信息
+func (s *userImpl) GetEditUser(ctx context.Context, id uint64) (res *system.UserGetEditRes, err error) {
+ res = new(system.UserGetEditRes)
+ err = g.Try(ctx, func(ctx context.Context) {
+ //获取用户信息
+ res.User, err = s.GetUserInfoById(ctx, id)
+ liberr.ErrIsNil(ctx, err)
+ //获取已选择的角色信息
+ res.CheckedRoleIds, err = s.GetAdminRoleIds(ctx, id)
+ liberr.ErrIsNil(ctx, err)
+ res.CheckedPosts, err = s.GetUserPostIds(ctx, id)
+ liberr.ErrIsNil(ctx, err)
+ })
+ return
+}
+
+// GetUserInfoById 通过Id获取用户信息
+func (s *userImpl) GetUserInfoById(ctx context.Context, id uint64, withPwd ...bool) (user *entity.SysUser, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ if len(withPwd) > 0 && withPwd[0] {
+ //用户用户信息
+ err = dao.SysUser.Ctx(ctx).Where(dao.SysUser.Columns().Id, id).Scan(&user)
+ } else {
+ //用户用户信息
+ err = dao.SysUser.Ctx(ctx).Where(dao.SysUser.Columns().Id, id).
+ FieldsEx(dao.SysUser.Columns().UserPassword, dao.SysUser.Columns().UserSalt).Scan(&user)
+ }
+ liberr.ErrIsNil(ctx, err, "获取用户数据失败")
+ })
+ return
+}
+
+// GetUserPostIds 获取用户岗位
+func (s *userImpl) GetUserPostIds(ctx context.Context, userId uint64) (postIds []int64, err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ var list []*entity.SysUserPost
+ err = dao.SysUserPost.Ctx(ctx).Where(dao.SysUserPost.Columns().UserId, userId).Scan(&list)
+ liberr.ErrIsNil(ctx, err, "获取用户岗位信息失败")
+ postIds = make([]int64, 0)
+ for _, entity := range list {
+ postIds = append(postIds, entity.PostId)
+ }
+ })
+ return
+}
+
+// ResetUserPwd 重置用户密码
+func (s *userImpl) ResetUserPwd(ctx context.Context, req *system.UserResetPwdReq) (err error) {
+ salt := grand.S(10)
+ password := libUtils.EncryptPassword(req.Password, salt)
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysUser.Ctx(ctx).WherePri(req.Id).Update(g.Map{
+ dao.SysUser.Columns().UserSalt: salt,
+ dao.SysUser.Columns().UserPassword: password,
+ })
+ liberr.ErrIsNil(ctx, err, "重置用户密码失败")
+ })
+ return
+}
+
+func (s *userImpl) ChangeUserStatus(ctx context.Context, req *system.UserStatusReq) (err error) {
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysUser.Ctx(ctx).WherePri(req.Id).Update(do.SysUser{UserStatus: req.UserStatus})
+ liberr.ErrIsNil(ctx, err, "设置用户状态失败")
+ })
+ return
+}
+
+// Delete 删除用户
+func (s *userImpl) Delete(ctx context.Context, ids []int) (err error) {
+ err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+ err = g.Try(ctx, func(ctx context.Context) {
+ _, err = dao.SysUser.Ctx(ctx).TX(tx).Where(dao.SysUser.Columns().Id+" in(?)", ids).Delete()
+ liberr.ErrIsNil(ctx, err, "删除用户失败")
+ //删除对应权限
+ enforcer, e := CasbinEnforcer(ctx)
+ liberr.ErrIsNil(ctx, e)
+ for _, v := range ids {
+ enforcer.RemoveFilteredGroupingPolicy(0, fmt.Sprintf("%s%d", s.CasBinUserPrefix, v))
+ }
+ //删除用户对应的岗位
+ _, err = dao.SysUserPost.Ctx(ctx).TX(tx).Delete(dao.SysUserPost.Columns().UserId+" in (?)", ids)
+ liberr.ErrIsNil(ctx, err, "删除用户的岗位失败")
+ })
+ return err
+ })
+ return
+}
diff --git a/internal/service/token.go b/internal/service/token.go
new file mode 100644
index 0000000..523b6ef
--- /dev/null
+++ b/internal/service/token.go
@@ -0,0 +1,82 @@
+/*
+* @desc:token功能
+*
+*
+* @Date: 2022/3/8 15:54
+ */
+
+package service
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/net/ghttp"
+ "github.com/gogf/gf/v2/os/gctx"
+ "github.com/tiger1103/gfast-token/gftoken"
+ "sync"
+ "tyj_admin/internal/consts"
+ "tyj_admin/internal/model"
+ "tyj_admin/library/liberr"
+)
+
+type IGfToken interface {
+ GenerateToken(ctx context.Context, key string, data interface{}) (keys string, err error)
+ Middleware(group *ghttp.RouterGroup) error
+ ParseToken(r *ghttp.Request) (*gftoken.CustomClaims, error)
+ IsLogin(r *ghttp.Request) (b bool, failed *gftoken.AuthFailed)
+ GetRequestToken(r *ghttp.Request) (token string)
+ RemoveToken(ctx context.Context, token string) (err error)
+}
+
+type gfTokenImpl struct {
+ *gftoken.GfToken
+}
+
+var gT = gfTokenImpl{
+ GfToken: gftoken.NewGfToken(),
+}
+
+func GfToken(options *model.TokenOptions) IGfToken {
+ var fun gftoken.OptionFunc
+ if options.CacheModel == consts.CacheModelRedis {
+ fun = gftoken.WithGRedis()
+ } else {
+ fun = gftoken.WithGCache()
+ }
+ gT.GfToken = gftoken.NewGfToken(
+ gftoken.WithCacheKey(options.CacheKey),
+ gftoken.WithTimeout(options.Timeout),
+ gftoken.WithMaxRefresh(options.MaxRefresh),
+ gftoken.WithMultiLogin(options.MultiLogin),
+ gftoken.WithExcludePaths(options.ExcludePaths),
+ fun,
+ )
+ return &gT
+}
+
+// =======================system==========================
+type gft struct {
+ options *model.TokenOptions
+ gT IGfToken
+ lock *sync.Mutex
+}
+
+var gftService = &gft{
+ options: nil,
+ gT: nil,
+ lock: &sync.Mutex{},
+}
+
+func SysGfToken() IGfToken {
+ if gftService.gT == nil {
+ gftService.lock.Lock()
+ defer gftService.lock.Unlock()
+ if gftService.gT == nil {
+ ctx := gctx.New()
+ err := g.Cfg().MustGet(ctx, "gfToken").Struct(&gftService.options)
+ liberr.ErrIsNil(ctx, err)
+ gftService.gT = GfToken(gftService.options)
+ }
+ }
+ return gftService.gT
+}
diff --git a/internal/service/upload.go b/internal/service/upload.go
new file mode 100644
index 0000000..1059477
--- /dev/null
+++ b/internal/service/upload.go
@@ -0,0 +1,306 @@
+package service
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "github.com/gogf/gf/v2/errors/gerror"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/net/ghttp"
+ "github.com/gogf/gf/v2/os/gfile"
+ "github.com/gogf/gf/v2/os/gtime"
+ "github.com/gogf/gf/v2/text/gregex"
+ "github.com/gogf/gf/v2/text/gstr"
+ "github.com/gogf/gf/v2/util/gconv"
+ "github.com/gogf/gf/v2/util/grand"
+ "github.com/tencentyun/cos-go-sdk-v5"
+ "github.com/tencentyun/cos-go-sdk-v5/debug"
+ "io"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+ "time"
+ "tyj_admin/api/v1/common"
+ "tyj_admin/internal/consts"
+ "tyj_admin/internal/model/entity"
+)
+
+type IUpload interface {
+ UploadFile(ctx context.Context, file *ghttp.UploadFile, checkFileType string, source int) (result common.UploadResponse, err error)
+ UploadFiles(ctx context.Context, files []*ghttp.UploadFile, checkFileType string, source int) (result common.UploadMultipleRes, err error)
+}
+
+type uploadTmpl struct{}
+
+func Upload() IUpload {
+ return &uploadTmpl{}
+}
+
+// 上传多文件
+func (s *uploadTmpl) UploadFiles(ctx context.Context, files []*ghttp.UploadFile, checkFileType string, source int) (result common.UploadMultipleRes, err error) {
+ for _, item := range files {
+ f, e := s.UploadFile(ctx, item, checkFileType, source)
+ if e != nil {
+ return
+ }
+ result = append(result, &f)
+ }
+ return
+}
+
+// 上传单文件
+func (s *uploadTmpl) UploadFile(ctx context.Context, file *ghttp.UploadFile, checkFileType string, source int) (result common.UploadResponse, err error) {
+
+ // 检查文件类型
+ err = s.CheckType(ctx, checkFileType, file)
+ if err != nil {
+ return
+ }
+
+ // 检查文件大小
+ err = s.CheckSize(ctx, checkFileType, file)
+ if err != nil {
+ return
+ }
+
+ // 非图片文件只能上传至本地
+ if checkFileType == consts.CheckFileTypeFile {
+ source = consts.SourceLocal
+ }
+
+ switch source {
+ // 上传至本地
+ case consts.SourceLocal:
+ result, err = s.UploadLocal(ctx, file)
+ // 上传至腾讯云
+ case consts.SourceTencent:
+ result, err = s.UploadTencent(ctx, file)
+ default:
+ err = errors.New("source参数错误!")
+ }
+
+ if err != nil {
+ return
+ }
+ return
+}
+
+// 上传至腾讯云
+func (s *uploadTmpl) UploadTencent(ctx context.Context, file *ghttp.UploadFile) (result common.UploadResponse, err error) {
+ v, err := g.Cfg().Get(ctx, "upload.tencentCOS")
+ if err != nil {
+ return
+ }
+ m := v.MapStrVar()
+ var (
+ upPath = m["upPath"].String()
+ rawUrl = m["rawUrl"].String()
+ secretID = m["secretID"].String()
+ secretKey = m["secretKey"].String()
+ )
+ name := gfile.Basename(file.Filename)
+ name = strings.ToLower(strconv.FormatInt(gtime.TimestampNano(), 36) + grand.S(6))
+ name = name + gfile.Ext(file.Filename)
+
+ path := upPath + name
+
+ url, _ := url.Parse(rawUrl)
+ b := &cos.BaseURL{BucketURL: url}
+ client := cos.NewClient(b, &http.Client{
+ Transport: &cos.AuthorizationTransport{
+ SecretID: secretID,
+ SecretKey: secretKey,
+ Transport: &debug.DebugRequestTransport{
+ RequestHeader: false,
+ RequestBody: false,
+ ResponseHeader: false,
+ ResponseBody: false,
+ },
+ },
+ })
+ opt := &cos.ObjectPutOptions{
+ ObjectPutHeaderOptions: &cos.ObjectPutHeaderOptions{
+ ContentLength: int64(file.Size),
+ },
+ }
+ var f io.ReadCloser
+ f, err = file.Open()
+ if err != nil {
+ return
+ }
+ defer f.Close()
+ _, err = client.Object.Put(context.Background(), path, f, opt)
+ result = common.UploadResponse{
+ Size: file.Size,
+ Path: rawUrl + path,
+ FullPath: rawUrl + path,
+ Name: file.Filename,
+ Type: file.Header.Get("Content-type"),
+ }
+ return
+}
+
+// 上传本地
+func (s *uploadTmpl) UploadLocal(ctx context.Context, file *ghttp.UploadFile) (result common.UploadResponse, err error) {
+ if file == nil {
+ err = errors.New("文件必须!")
+ return
+ }
+ r := g.RequestFromCtx(ctx)
+ urlPerfix := fmt.Sprintf("http://%s/", r.Host)
+ p := strings.Trim(consts.UploadPath, "/")
+ sp := s.getStaticPath(ctx)
+ if sp != "" {
+ sp = strings.Trim(sp, "/")
+ }
+ nowData := time.Now().Format("2006-01-02")
+ // 包含静态文件夹的路径
+ fullDirPath := sp + "/" + p + "/" + nowData
+ fileName, err := file.Save(fullDirPath, true)
+ if err != nil {
+ return
+ }
+ // 不含静态文件夹的路径
+ fullPath := p + "/" + nowData + "/" + fileName
+
+ result = common.UploadResponse{
+ Size: file.Size,
+ Path: fullPath,
+ FullPath: urlPerfix + fullPath,
+ Name: file.Filename,
+ Type: file.Header.Get("Content-type"),
+ }
+ return
+}
+
+// 检查上传文件大小
+func (s *uploadTmpl) CheckSize(ctx context.Context, checkFileType string, file *ghttp.UploadFile) (err error) {
+
+ var (
+ configSize *entity.SysConfig
+ )
+
+ if checkFileType == consts.CheckFileTypeFile {
+
+ //获取上传大小配置
+ configSize, err = s.getUpConfig(ctx, consts.FileSizeKey)
+ if err != nil {
+ return
+ }
+ } else if checkFileType == consts.CheckFileTypeImg {
+
+ //获取上传大小配置
+ configSize, err = s.getUpConfig(ctx, consts.ImgSizeKey)
+ if err != nil {
+ return
+ }
+ } else {
+ return errors.New(fmt.Sprintf("文件检查类型错误:%s|%s", consts.CheckFileTypeFile, consts.CheckFileTypeImg))
+ }
+
+ var rightSize bool
+ rightSize, err = s.checkSize(configSize.ConfigValue, file.Size)
+ if err != nil {
+ return
+ }
+ if !rightSize {
+ err = gerror.New("上传文件超过最大尺寸:" + configSize.ConfigValue)
+ return
+ }
+ return
+}
+
+// 检查上传文件类型
+func (s *uploadTmpl) CheckType(ctx context.Context, checkFileType string, file *ghttp.UploadFile) (err error) {
+
+ var (
+ configType *entity.SysConfig
+ )
+
+ if checkFileType == consts.CheckFileTypeFile {
+ //获取上传类型配置
+ configType, err = s.getUpConfig(ctx, consts.FileTypeKey)
+ if err != nil {
+ return
+ }
+
+ } else if checkFileType == consts.CheckFileTypeImg {
+ //获取上传类型配置
+ configType, err = s.getUpConfig(ctx, consts.ImgTypeKey)
+ if err != nil {
+ return
+ }
+ } else {
+ return errors.New(fmt.Sprintf("文件检查类型错误:%s|%s", consts.CheckFileTypeFile, consts.CheckFileTypeImg))
+ }
+
+ rightType := s.checkFileType(file.Filename, configType.ConfigValue)
+ if !rightType {
+ err = gerror.New("上传文件类型错误,只能包含后缀为:" + configType.ConfigValue + "的文件。")
+ return
+ }
+ return
+}
+
+// 获取上传配置
+func (s *uploadTmpl) getUpConfig(ctx context.Context, key string) (config *entity.SysConfig, err error) {
+ config, err = Config().GetConfigByKey(ctx, key)
+ if err != nil {
+ return
+ }
+ if config == nil {
+ err = gerror.New("上传文件类型未设置,请在后台配置")
+ return
+ }
+ return
+}
+
+// 判断上传文件类型是否合法
+func (s *uploadTmpl) checkFileType(fileName, typeString string) bool {
+ suffix := gstr.SubStrRune(fileName, gstr.PosRRune(fileName, ".")+1, gstr.LenRune(fileName)-1)
+ imageType := gstr.Split(typeString, ",")
+ rightType := false
+ for _, v := range imageType {
+ if gstr.Equal(suffix, v) {
+ rightType = true
+ break
+ }
+ }
+ return rightType
+}
+
+// 检查文件大小是否合法
+func (s *uploadTmpl) checkSize(configSize string, fileSize int64) (bool, error) {
+ match, err := gregex.MatchString(`^([0-9]+)(?i:([a-z]*))$`, configSize)
+ if err != nil {
+ return false, err
+ }
+ if len(match) == 0 {
+ err = gerror.New("上传文件大小未设置,请在后台配置,格式为(30M,30k,30MB)")
+ return false, err
+ }
+ var cfSize int64
+ switch gstr.ToUpper(match[2]) {
+ case "MB", "M":
+ cfSize = gconv.Int64(match[1]) * 1024 * 1024
+ case "KB", "K":
+ cfSize = gconv.Int64(match[1]) * 1024
+ case "":
+ cfSize = gconv.Int64(match[1])
+ }
+ if cfSize == 0 {
+ err = gerror.New("上传文件大小未设置,请在后台配置,格式为(30M,30k,30MB),最大单位为MB")
+ return false, err
+ }
+ return cfSize >= fileSize, nil
+}
+
+// 静态文件夹目录
+func (s *uploadTmpl) getStaticPath(ctx context.Context) string {
+ value, _ := g.Cfg().Get(ctx, "server.serverRoot")
+ if !value.IsEmpty() {
+ return value.String()
+ }
+ return ""
+}
diff --git a/library/libResponse/response.go b/library/libResponse/response.go
new file mode 100644
index 0000000..466e95b
--- /dev/null
+++ b/library/libResponse/response.go
@@ -0,0 +1,107 @@
+package libResponse
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/net/ghttp"
+ "github.com/gogf/gf/v2/os/gview"
+ "github.com/gogf/gf/v2/text/gstr"
+ "github.com/gogf/gf/v2/util/gconv"
+)
+
+const (
+ SuccessCode int = 0
+ ErrorCode int = -1
+)
+
+type Response struct {
+ // 代码
+ Code int `json:"code" example:"200"`
+ // 数据集
+ Data interface{} `json:"data"`
+ // 消息
+ Msg string `json:"message"`
+}
+
+var response = new(Response)
+
+func JsonExit(r *ghttp.Request, code int, msg string, data ...interface{}) {
+ response.JsonExit(r, code, msg, data...)
+}
+
+func RJson(r *ghttp.Request, code int, msg string, data ...interface{}) {
+ response.RJson(r, code, msg, data...)
+}
+
+func SusJson(isExit bool, r *ghttp.Request, msg string, data ...interface{}) {
+ response.SusJson(isExit, r, msg, data...)
+}
+
+func FailJson(isExit bool, r *ghttp.Request, msg string, data ...interface{}) {
+ response.FailJson(isExit, r, msg, data...)
+}
+
+func WriteTpl(r *ghttp.Request, tpl string, view *gview.View, params ...gview.Params) error {
+ return response.WriteTpl(r, tpl, view, params...)
+}
+
+// 返回JSON数据并退出当前HTTP执行函数。
+func (res *Response) JsonExit(r *ghttp.Request, code int, msg string, data ...interface{}) {
+ res.RJson(r, code, msg, data...)
+ r.ExitAll()
+}
+
+// 标准返回结果数据结构封装。
+// 返回固定数据结构的JSON:
+// code: 状态码(200:成功,302跳转,和http请求状态码一至);
+// msg: 请求结果信息;
+// data: 请求结果,根据不同接口返回结果的数据结构不同;
+func (res *Response) RJson(r *ghttp.Request, code int, msg string, data ...interface{}) {
+ responseData := interface{}(nil)
+ if len(data) > 0 {
+ responseData = data[0]
+ }
+ response = &Response{
+ Code: code,
+ Msg: msg,
+ Data: responseData,
+ }
+ r.Response.WriteJson(response)
+}
+
+//成功返回JSON
+func (res *Response) SusJson(isExit bool, r *ghttp.Request, msg string, data ...interface{}) {
+ if isExit {
+ res.JsonExit(r, SuccessCode, msg, data...)
+ }
+ res.RJson(r, SuccessCode, msg, data...)
+}
+
+//失败返回JSON
+func (res *Response) FailJson(isExit bool, r *ghttp.Request, msg string, data ...interface{}) {
+ if isExit {
+ res.JsonExit(r, ErrorCode, msg, data...)
+ }
+ res.RJson(r, ErrorCode, msg, data...)
+}
+
+// WriteTpl 模板输出
+func (res *Response) WriteTpl(r *ghttp.Request, tpl string, view *gview.View, params ...gview.Params) error {
+ //绑定模板中需要用到的方法
+ view.BindFuncMap(g.Map{
+ // 根据长度i来切割字符串
+ "subStr": func(str interface{}, i int) (s string) {
+ s1 := gconv.String(str)
+ if gstr.LenRune(s1) > i {
+ s = gstr.SubStrRune(s1, 0, i) + "..."
+ return s
+ }
+ return s1
+ },
+ })
+ r.Response.Write(view.Parse(r.GetCtx(), tpl, params...))
+ return nil
+}
+
+func (res *Response) Redirect(r *ghttp.Request, location string, code ...int) {
+ r.Response.RedirectTo(location, code...)
+}
diff --git a/library/libUtils/utils.go b/library/libUtils/utils.go
new file mode 100644
index 0000000..5cb3d8e
--- /dev/null
+++ b/library/libUtils/utils.go
@@ -0,0 +1,173 @@
+/*
+* @desc:工具
+*
+*
+* @Date: 2022/3/4 22:16
+ */
+
+package libUtils
+
+import (
+ "context"
+ "fmt"
+ "github.com/gogf/gf/v2/crypto/gmd5"
+ "github.com/gogf/gf/v2/encoding/gcharset"
+ "github.com/gogf/gf/v2/encoding/gjson"
+ "github.com/gogf/gf/v2/encoding/gurl"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/net/ghttp"
+ "net"
+ "net/http"
+ "os"
+ "path"
+ "strings"
+)
+
+// EncryptPassword 密码加密
+func EncryptPassword(password, salt string) string {
+ return gmd5.MustEncryptString(gmd5.MustEncryptString(password) + gmd5.MustEncryptString(salt))
+}
+
+// GetDomain 获取当前请求接口域名
+func GetDomain(ctx context.Context) string {
+ r := g.RequestFromCtx(ctx)
+ pathInfo, err := gurl.ParseURL(r.GetUrl(), -1)
+ if err != nil {
+ g.Log().Error(ctx, err)
+ return ""
+ }
+ return fmt.Sprintf("%s://%s:%s/", pathInfo["scheme"], pathInfo["host"], pathInfo["port"])
+}
+
+// GetClientIp 获取客户端IP
+func GetClientIp(ctx context.Context) string {
+ return g.RequestFromCtx(ctx).GetClientIp()
+}
+
+// GetUserAgent 获取user-agent
+func GetUserAgent(ctx context.Context) string {
+ return ghttp.RequestFromCtx(ctx).Header.Get("User-Agent")
+}
+
+// GetLocalIP 服务端ip
+func GetLocalIP() (ip string, err error) {
+ var addrs []net.Addr
+ addrs, err = net.InterfaceAddrs()
+ if err != nil {
+ return
+ }
+ for _, addr := range addrs {
+ ipAddr, ok := addr.(*net.IPNet)
+ if !ok {
+ continue
+ }
+ if ipAddr.IP.IsLoopback() {
+ continue
+ }
+ if !ipAddr.IP.IsGlobalUnicast() {
+ continue
+ }
+ return ipAddr.IP.String(), nil
+ }
+ return
+}
+
+// GetCityByIp 获取ip所属城市
+func GetCityByIp(ip string) string {
+ if ip == "" {
+ return ""
+ }
+ if ip == "[::1]" || ip == "127.0.0.1" {
+ return "内网IP"
+ }
+ url := "http://whois.pconline.com.cn/ipJson.jsp?json=true&ip=" + ip
+ bytes := g.Client().GetBytes(context.TODO(), url)
+ src := string(bytes)
+ srcCharset := "GBK"
+ tmp, _ := gcharset.ToUTF8(srcCharset, src)
+ json, err := gjson.DecodeToJson(tmp)
+ if err != nil {
+ return ""
+ }
+ if json.Get("code").Int() == 0 {
+ city := fmt.Sprintf("%s %s", json.Get("pro").String(), json.Get("city").String())
+ return city
+ } else {
+ return ""
+ }
+}
+
+// 写入文件
+func WriteToFile(fileName string, content string) error {
+ f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
+ if err != nil {
+ return err
+ }
+ n, _ := f.Seek(0, os.SEEK_END)
+ _, err = f.WriteAt([]byte(content), n)
+ defer f.Close()
+ return err
+}
+
+// 文件或文件夹是否存在
+func FileIsExisted(filename string) bool {
+ existed := true
+ if _, err := os.Stat(filename); os.IsNotExist(err) {
+ existed = false
+ }
+ return existed
+}
+
+// 解析路径获取文件名称及后缀
+func ParseFilePath(pathStr string) (fileName string, fileType string) {
+ fileNameWithSuffix := path.Base(pathStr)
+ fileType = path.Ext(fileNameWithSuffix)
+ fileName = strings.TrimSuffix(fileNameWithSuffix, fileType)
+ return
+}
+
+// IsNotExistMkDir 检查文件夹是否存在
+// 如果不存在则新建文件夹
+func IsNotExistMkDir(src string) error {
+ if exist := !FileIsExisted(src); exist == false {
+ if err := MkDir(src); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// MkDir 新建文件夹
+func MkDir(src string) error {
+ err := os.MkdirAll(src, os.ModePerm)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+//获取文件后缀
+func GetExt(fileName string) string {
+ return path.Ext(fileName)
+}
+
+// GetType 获取文件类型
+func GetType(p string) (result string, err error) {
+ file, err := os.Open(p)
+ if err != nil {
+ g.Log().Error(context.TODO(), err)
+ return
+ }
+ buff := make([]byte, 512)
+
+ _, err = file.Read(buff)
+
+ if err != nil {
+ g.Log().Error(context.TODO(), err)
+ return
+ }
+ filetype := http.DetectContentType(buff)
+ return filetype, nil
+}
diff --git a/library/liberr/err.go b/library/liberr/err.go
new file mode 100644
index 0000000..ac0e5c7
--- /dev/null
+++ b/library/liberr/err.go
@@ -0,0 +1,30 @@
+/*
+* @desc:错误处理
+*
+*
+* @Date: 2022/3/2 14:53
+ */
+
+package liberr
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+func ErrIsNil(ctx context.Context, err error, msg ...string) {
+ if !g.IsNil(err) {
+ if len(msg) > 0 {
+ g.Log().Error(ctx, err.Error())
+ panic(msg[0])
+ } else {
+ panic(err.Error())
+ }
+ }
+}
+
+func ValueIsNil(value interface{}, msg string) {
+ if g.IsNil(value) {
+ panic(msg)
+ }
+}
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..950061d
--- /dev/null
+++ b/main.go
@@ -0,0 +1,27 @@
+package main
+
+import (
+ _ "github.com/gogf/gf/contrib/drivers/mysql/v2"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gctx"
+ "github.com/gogf/gf/v2/os/glog"
+ "tyj_admin/internal/cmd"
+ _ "tyj_admin/internal/packed"
+ "tyj_admin/internal/service"
+)
+
+func init() {
+ ctx := gctx.New()
+ if service.SysInitConfig["autoInit"].Bool() && service.SysInit().IsCreateConfigFile() {
+ // 加载配置文件
+ err := service.SysInit().LoadConfigFile()
+ if err != nil {
+ g.Log().Panic(ctx, err)
+ }
+ }
+}
+
+func main() {
+ g.Log().SetFlags(glog.F_ASYNC | glog.F_TIME_DATE | glog.F_TIME_TIME | glog.F_FILE_LONG)
+ cmd.Main.Run(gctx.New())
+}
diff --git a/manifest/config/config.yaml.bak b/manifest/config/config.yaml.bak
new file mode 100644
index 0000000..fb126ee
--- /dev/null
+++ b/manifest/config/config.yaml.bak
@@ -0,0 +1,93 @@
+server:
+ address: ":8201"
+ serverRoot: "resource/public"
+ dumpRouterMap: true
+ routeOverWrite: true
+ openapiPath: "/api.json"
+ swaggerPath: "/swagger"
+ NameToUriType: 3
+ maxHeaderBytes: "20KB"
+ clientMaxBodySize: "50MB"
+ # Logging配置
+ logPath: "resource/log/server" # 日志文件存储目录路径,建议使用绝对路径。默认为空,表示关闭
+ logStdout: true # 日志是否输出到终端。默认为true
+ errorStack: true # 当Server捕获到异常时是否记录堆栈信息到日志中。默认为true
+ errorLogEnabled: true # 是否记录异常日志信息到日志中。默认为true
+ errorLogPattern: "error-{Ymd}.log" # 异常错误日志文件格式。默认为"error-{Ymd}.log"
+ accessLogEnabled: true # 是否记录访问日志。默认为false
+ accessLogPattern: "access-{Ymd}.log" # 访问日志文件格式。默认为"access-{Ymd}.log"
+
+logger:
+ path: "resource/log/run"
+ file: "{Y-m-d}.log"
+ level: "all"
+ stdout: true
+
+# Database.
+database:
+ logger:
+ level: "all"
+ stdout: true
+ Path: "resource/log/sql"
+
+ default:
+ link: "mysql:gfast3:gfast333@tcp(192.168.0.212:3306)/gfast-v3"
+ debug: true
+ charset: "utf8mb4" #数据库编码
+ dryRun: false #空跑
+ maxIdle: 10 #连接池最大闲置的连接数
+ maxOpen: 10 #连接池最大打开的连接数
+ maxLifetime: 30 #(单位秒)连接对象可重复使用的时间长度
+
+gfToken:
+ cacheKey: "gfToken_"
+ timeOut: 10800
+ maxRefresh: 5400
+ multiLogin: true
+ encryptKey: "49c54195e750b04e74a8429b17896586"
+ cacheModel: "redis"
+ excludePaths:
+ - "/api/v1/system/xxx"
+ - "/api/v1/system/xxx2"
+
+# Redis 配置示例
+redis:
+ # 单实例配置
+ default:
+ address: 127.0.0.1:6379
+ db: 1
+ idleTimeout: 600
+ maxActive: 100
+
+system:
+ notCheckAuthAdminIds: [1,2,31] #无需验证后台权限的用户id
+ dataDir: "./resource/data"
+ cache:
+ model: "redis" #缓存模式 memory OR redis
+ prefix: "gFastV3Cache_" #缓存前缀
+
+#casbin配置
+casbin:
+ modelFile: "./resource/casbin/rbac_model.conf"
+ policyFile: "./resource/casbin/rbac_policy.csv"
+
+
+# CLI.
+gfcli:
+ gen:
+ dao:
+ - link: "mysql:gfast3:gfast333@tcp(192.168.0.212:3306)/gfast-v3"
+ tables: "sys_user_post"
+ removePrefix: "gf_"
+ descriptionTag: true
+ noModelComment: true
+ path: "./internal/app/system"
+
+# 上传配置
+upload:
+ default: 0 # 默认上传至本地
+ tencentCOS:
+ upPath : "/gfast/"
+ rawUrl : "https://xxxx-xxxxxxxx.cos.ap-xxxxxxxx.myqcloud.com"
+ secretID : "xxxxxxxxxxxxxxxxxxxxxxxxx"
+ secretKey : "xxxxxxxxxxxxxxxxxxxxxxxxx"
diff --git a/manifest/config/initialize.yaml b/manifest/config/initialize.yaml
new file mode 100644
index 0000000..f91a4fe
--- /dev/null
+++ b/manifest/config/initialize.yaml
@@ -0,0 +1,4 @@
+initialize:
+ autoInit: false # 开启系统自动初始化
+ configPath: "./manifest/config/db.yaml" # 生成的配置文件所在路径
+ sqlFilePath: "./resource/data/gfast-v3.sql" # sql文件所在路径
\ No newline at end of file
diff --git a/manifest/deploy/kustomize/base/deployment.yaml b/manifest/deploy/kustomize/base/deployment.yaml
new file mode 100644
index 0000000..28f1d69
--- /dev/null
+++ b/manifest/deploy/kustomize/base/deployment.yaml
@@ -0,0 +1,21 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: template-single
+ labels:
+ app: template-single
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: template-single
+ template:
+ metadata:
+ labels:
+ app: template-single
+ spec:
+ containers:
+ - name : main
+ image: template-single
+ imagePullPolicy: Always
+
diff --git a/manifest/deploy/kustomize/base/kustomization.yaml b/manifest/deploy/kustomize/base/kustomization.yaml
new file mode 100644
index 0000000..302d92d
--- /dev/null
+++ b/manifest/deploy/kustomize/base/kustomization.yaml
@@ -0,0 +1,8 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+- deployment.yaml
+- service.yaml
+
+
+
diff --git a/manifest/deploy/kustomize/base/service.yaml b/manifest/deploy/kustomize/base/service.yaml
new file mode 100644
index 0000000..608771c
--- /dev/null
+++ b/manifest/deploy/kustomize/base/service.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: template-single
+spec:
+ ports:
+ - port: 80
+ protocol: TCP
+ targetPort: 8000
+ selector:
+ app: template-single
+
diff --git a/manifest/deploy/kustomize/overlays/develop/configmap.yaml b/manifest/deploy/kustomize/overlays/develop/configmap.yaml
new file mode 100644
index 0000000..3b1d0af
--- /dev/null
+++ b/manifest/deploy/kustomize/overlays/develop/configmap.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: template-single-configmap
+data:
+ config.yaml: |
+ server:
+ address: ":8000"
+ openapiPath: "/api.json"
+ swaggerPath: "/swagger"
+
+ logger:
+ level : "all"
+ stdout: true
diff --git a/manifest/deploy/kustomize/overlays/develop/deployment.yaml b/manifest/deploy/kustomize/overlays/develop/deployment.yaml
new file mode 100644
index 0000000..04e4851
--- /dev/null
+++ b/manifest/deploy/kustomize/overlays/develop/deployment.yaml
@@ -0,0 +1,10 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: template-single
+spec:
+ template:
+ spec:
+ containers:
+ - name : main
+ image: template-single:develop
\ No newline at end of file
diff --git a/manifest/deploy/kustomize/overlays/develop/kustomization.yaml b/manifest/deploy/kustomize/overlays/develop/kustomization.yaml
new file mode 100644
index 0000000..4731c47
--- /dev/null
+++ b/manifest/deploy/kustomize/overlays/develop/kustomization.yaml
@@ -0,0 +1,14 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+resources:
+- ../../base
+- configmap.yaml
+
+patchesStrategicMerge:
+- deployment.yaml
+
+namespace: default
+
+
+
diff --git a/manifest/docker/Dockerfile b/manifest/docker/Dockerfile
new file mode 100644
index 0000000..399619e
--- /dev/null
+++ b/manifest/docker/Dockerfile
@@ -0,0 +1,19 @@
+FROM loads/alpine:3.8
+
+###############################################################################
+# INSTALLATION
+###############################################################################
+
+ENV WORKDIR /app
+
+ADD resource $WORKDIR/
+
+ADD ./bin/linux_amd64/main $WORKDIR/main
+
+RUN chmod +x $WORKDIR/main
+
+###############################################################################
+# START
+###############################################################################
+WORKDIR $WORKDIR
+CMD ./main
diff --git a/manifest/docker/docker.sh b/manifest/docker/docker.sh
new file mode 100644
index 0000000..ff393f9
--- /dev/null
+++ b/manifest/docker/docker.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# This shell is executed before docker build.
+
+
+
+
+
diff --git a/resource/casbin/rbac_model.conf b/resource/casbin/rbac_model.conf
new file mode 100644
index 0000000..71159e3
--- /dev/null
+++ b/resource/casbin/rbac_model.conf
@@ -0,0 +1,14 @@
+[request_definition]
+r = sub, obj, act
+
+[policy_definition]
+p = sub, obj, act
+
+[role_definition]
+g = _, _
+
+[policy_effect]
+e = some(where (p.eft == allow))
+
+[matchers]
+m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
\ No newline at end of file
diff --git a/resource/casbin/rbac_policy.csv b/resource/casbin/rbac_policy.csv
new file mode 100644
index 0000000..f93d6df
--- /dev/null
+++ b/resource/casbin/rbac_policy.csv
@@ -0,0 +1,5 @@
+p, alice, data1, read
+p, bob, data2, write
+p, data2_admin, data2, read
+p, data2_admin, data2, write
+g, alice, data2_admin
\ No newline at end of file
diff --git a/resource/data/.gitkeep b/resource/data/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/resource/data/gfast-v3.sql b/resource/data/gfast-v3.sql
new file mode 100644
index 0000000..aab0e78
--- /dev/null
+++ b/resource/data/gfast-v3.sql
@@ -0,0 +1,1025 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server : localhost
+ Source Server Type : MySQL
+ Source Server Version : 50736
+ Source Host : localhost:3306
+ Source Schema : gfast-v3
+
+ Target Server Type : MySQL
+ Target Server Version : 50736
+ File Encoding : 65001
+
+ Date: 22/04/2022 18:17:11
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for casbin_rule
+-- ----------------------------
+DROP TABLE IF EXISTS `casbin_rule`;
+CREATE TABLE `casbin_rule` (
+ `ptype` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `v0` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `v1` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `v2` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `v3` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `v4` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+ `v5` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
+
+-- ----------------------------
+-- Records of casbin_rule
+-- ----------------------------
+INSERT INTO `casbin_rule` VALUES ('p', '2', '2', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('p', '3', '2', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('p', '4', '2', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('p', '3', '3', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('p', '2', '3', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('p', '5', '4', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('p', '2', '10', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('p', '8', '2', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('p', '8', '4', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('p', '1', '10', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('p', '1', '12', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('p', '1', '13', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('p', '1', '14', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('g', '42', '1', '', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('g', '42', '2', '', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('g', '1', '1', '', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('g', '1', '2', '', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('g', '2', '3', '', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('g', '2', '2', '', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('g', '4', '2', '', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('g', '5', '2', '', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('g', '7', '2', '', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('g', '8', '2', '', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('g', '10', '2', '', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('g', '14', '2', '', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('g', '15', '2', '', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('g', '16', '2', '', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('p', '4', '1', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('p', '2', '1', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('p', '8', '1', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('p', '1', '1', 'All', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('g', '6', '2', '', '', '', '');
+INSERT INTO `casbin_rule` VALUES ('g', '3', '2', '', '', '', '');
+
+-- ----------------------------
+-- Table structure for sys_auth_rule
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_auth_rule`;
+CREATE TABLE `sys_auth_rule` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `pid` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '父ID',
+ `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '规则名称',
+ `title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '规则名称',
+ `icon` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '图标',
+ `condition` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '条件',
+ `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注',
+ `menu_type` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '类型 0目录 1菜单 2按钮',
+ `weigh` int(10) NOT NULL DEFAULT 0 COMMENT '权重',
+ `is_hide` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 COMMENT '显示状态',
+ `path` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '路由地址',
+ `component` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '组件路径',
+ `is_link` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否外链 1是 0否',
+ `module_type` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '所属模块',
+ `model_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '模型ID',
+ `is_iframe` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否内嵌iframe',
+ `is_cached` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否缓存',
+ `redirect` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '路由重定向地址',
+ `is_affix` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否固定',
+ `link_url` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '链接地址',
+ `created_at` datetime(0) NULL DEFAULT NULL COMMENT '创建日期',
+ `updated_at` datetime(0) NULL DEFAULT NULL COMMENT '修改日期',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `name`(`name`) USING BTREE,
+ INDEX `pid`(`pid`) USING BTREE,
+ INDEX `weigh`(`weigh`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 34 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '菜单节点表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of sys_auth_rule
+-- ----------------------------
+INSERT INTO `sys_auth_rule` VALUES (1, 0, 'api/v1/system/auth', '权限管理', 'ele-Stamp', '', '', 0, 30, 0, '/system/auth', 'layout/routerView/parent', 0, '', 0, 0, 1, '0', 0, '', '2022-03-24 15:03:37', '2022-04-14 16:29:19');
+INSERT INTO `sys_auth_rule` VALUES (2, 1, 'api/v1/system/auth/menuList', '菜单管理', 'ele-Calendar', '', '', 1, 0, 0, '/system/auth/menuList', 'system/menu/index', 0, '', 0, 0, 1, '', 0, '', '2022-03-24 17:24:13', '2022-03-29 10:54:49');
+INSERT INTO `sys_auth_rule` VALUES (3, 2, 'api/v1/system/menu/add', '添加菜单', '', '', '', 2, 0, 0, '', '', 0, '', 0, 0, 1, '', 0, '', '2022-03-29 16:48:43', '2022-03-29 17:05:19');
+INSERT INTO `sys_auth_rule` VALUES (4, 2, 'api/v1/system/menu/update', '修改菜单', '', '', '', 2, 0, 0, '', '', 0, '', 0, 0, 1, '', 0, '', '2022-03-29 17:04:25', '2022-03-29 18:11:36');
+INSERT INTO `sys_auth_rule` VALUES (10, 1, 'api/v1/system/role/list', '角色管理', 'iconfont icon-juxingkaobei', '', '', 1, 0, 0, '/system/auth/roleList', 'system/role/index', 0, '', 0, 0, 1, '', 0, '', '2022-03-29 18:15:03', '2022-03-30 10:25:34');
+INSERT INTO `sys_auth_rule` VALUES (11, 2, 'api/v1/system/menu/delete', '删除菜单', '', '', '', 2, 0, 0, '', '', 0, '', 0, 0, 1, '', 0, '', '2022-04-06 14:49:10', '2022-04-06 14:49:17');
+INSERT INTO `sys_auth_rule` VALUES (12, 10, 'api/v1/system/role/add', '添加角色', '', '', '', 2, 0, 0, '', '', 0, '', 0, 0, 1, '', 0, '', '2022-04-06 14:49:46', '2022-04-06 14:49:46');
+INSERT INTO `sys_auth_rule` VALUES (13, 10, '/api/v1/system/role/edit', '修改角色', '', '', '', 2, 0, 0, '', '', 0, '', 0, 0, 1, '', 0, '', '2022-04-06 14:50:08', '2022-04-06 14:50:08');
+INSERT INTO `sys_auth_rule` VALUES (14, 10, '/api/v1/system/role/delete', '删除角色', '', '', '', 2, 0, 0, '', '', 0, '', 0, 0, 1, '', 0, '', '2022-04-06 14:50:22', '2022-04-06 14:50:22');
+INSERT INTO `sys_auth_rule` VALUES (15, 1, 'api/v1/system/dept/list', '部门管理', 'iconfont icon-siweidaotu', '', '', 1, 0, 0, '/system/auth/deptList', 'system/dept/index', 0, '', 0, 0, 1, '', 0, '', '2022-04-06 14:52:23', '2022-04-07 22:59:20');
+INSERT INTO `sys_auth_rule` VALUES (16, 17, 'aliyun', '阿里云-iframe', 'iconfont icon-diannao1', '', '', 1, 0, 0, '/demo/outLink/aliyun', 'layout/routerView/iframes', 1, '', 0, 1, 1, '', 0, 'https://www.aliyun.com/daily-act/ecs/activity_selection?spm=5176.8789780.J_3965641470.5.568845b58KHj51', '2022-04-06 17:26:29', '2022-04-07 15:27:17');
+INSERT INTO `sys_auth_rule` VALUES (17, 0, 'outLink', '外链测试', 'iconfont icon-zhongduancanshu', '', '', 0, 20, 0, '/demo/outLink', 'layout/routerView/parent', 0, '', 0, 0, 1, '', 0, '', '2022-04-07 15:20:51', '2022-04-14 16:29:07');
+INSERT INTO `sys_auth_rule` VALUES (18, 17, 'tenyun', '腾讯云-外链', 'iconfont icon-shouye_dongtaihui', '', '', 1, 0, 0, '/demo/outLink/tenyun', 'layout/routerView/link', 1, '', 0, 0, 1, '', 0, 'https://cloud.tencent.com/act/new?cps_key=20b1c3842f74986b2894e2c5fcde7ea2&fromSource=gwzcw.3775555.3775555.3775555&utm_id=gwzcw.3775555.3775555.3775555&utm_medium=cpc', '2022-04-07 15:23:52', '2022-04-07 15:27:25');
+INSERT INTO `sys_auth_rule` VALUES (19, 15, 'api/v1/system/dept/add', '添加部门', '', '', '', 2, 0, 0, '', '', 0, '', 0, 0, 1, '', 0, '', '2022-04-07 22:56:39', '2022-04-07 22:56:39');
+INSERT INTO `sys_auth_rule` VALUES (20, 15, 'api/v1/system/dept/edit', '修改部门', '', '', '', 2, 0, 0, '', '', 0, '', 0, 0, 1, '', 0, '', '2022-04-07 22:57:00', '2022-04-07 22:57:00');
+INSERT INTO `sys_auth_rule` VALUES (21, 15, 'api/v1/system/dept/delete', '删除部门', '', '', '', 2, 0, 0, '', '', 0, '', 0, 0, 1, '', 0, '', '2022-04-07 22:57:30', '2022-04-07 22:57:30');
+INSERT INTO `sys_auth_rule` VALUES (22, 1, 'api/v1/system/post/list', '岗位管理', 'iconfont icon-neiqianshujuchucun', '', '', 1, 0, 0, '/system/auth/postList', 'system/post/index', 0, '', 0, 0, 1, '', 0, '', '2022-04-07 22:58:46', '2022-04-09 14:26:15');
+INSERT INTO `sys_auth_rule` VALUES (23, 22, 'api/v1/system/post/add', '添加岗位', '', '', '', 2, 0, 0, '', '', 0, '', 0, 0, 1, '', 0, '', '2022-04-09 14:14:49', '2022-04-09 14:14:49');
+INSERT INTO `sys_auth_rule` VALUES (24, 22, 'api/v1/system/post/edit', '修改岗位', '', '', '', 2, 0, 0, '', '', 0, '', 0, 0, 1, '', 0, '', '2022-04-09 14:15:25', '2022-04-09 14:15:25');
+INSERT INTO `sys_auth_rule` VALUES (25, 22, 'api/v1/system/post/delete', '删除岗位', '', '', '', 2, 0, 0, '', '', 0, '', 0, 0, 1, '', 0, '', '2022-04-09 14:15:47', '2022-04-09 14:15:47');
+INSERT INTO `sys_auth_rule` VALUES (26, 1, 'api/v1/system/user/list', '用户管理', 'ele-User', '', '', 1, 0, 0, '/system/auth/user/list', 'system/user/index', 0, '', 0, 0, 1, '', 0, '', '2022-04-09 14:19:10', '2022-04-09 14:19:58');
+INSERT INTO `sys_auth_rule` VALUES (27, 0, 'api/v1/system/dict', '系统配置', 'iconfont icon-shuxingtu', '', '', 0, 40, 0, '/system/dict', 'layout/routerView/parent', 0, '', 0, 0, 1, '654', 0, '', '2022-04-14 16:28:51', '2022-04-18 14:40:56');
+INSERT INTO `sys_auth_rule` VALUES (28, 27, 'api/v1/system/dict/type/list', '字典管理', 'iconfont icon-crew_feature', '', '', 1, 0, 0, '/system/dict/type/list', 'system/dict/index', 0, '', 0, 0, 1, '', 0, '', '2022-04-14 16:32:10', '2022-04-16 17:02:50');
+INSERT INTO `sys_auth_rule` VALUES (29, 27, 'api/v1/system/dict/dataList', '字典数据管理', 'iconfont icon-putong', '', '', 1, 0, 1, '/system/dict/data/list/:dictType', 'system/dict/dataList', 0, '', 0, 0, 1, '', 0, '', '2022-04-18 12:04:17', '2022-04-18 14:58:43');
+INSERT INTO `sys_auth_rule` VALUES (30, 27, 'api/v1/system/config/list', '参数管理', 'ele-Cherry', '', '', 1, 0, 0, '/system/config/list', 'system/config/index', 0, '', 0, 0, 1, '', 0, '', '2022-04-18 21:05:20', '2022-04-18 21:13:19');
+INSERT INTO `sys_auth_rule` VALUES (31, 0, 'api/v1/system/monitor', '系统监控', 'iconfont icon-xuanzeqi', '', '', 0, 30, 0, '/system/monitor', 'layout/routerView/parent', 0, '', 0, 0, 1, '', 0, '', '2022-04-19 10:40:19', '2022-04-19 10:44:38');
+INSERT INTO `sys_auth_rule` VALUES (32, 31, 'api/v1/system/monitor/server', '服务监控', 'iconfont icon-shuju', '', '', 1, 0, 0, '/system/monitor/server', 'system/monitor/server/index', 0, '', 0, 0, 1, '', 0, '', '2022-04-19 10:43:32', '2022-04-19 10:44:47');
+INSERT INTO `sys_auth_rule` VALUES (33, 31, 'api/swagger', 'api文档', 'iconfont icon--chaifenlie', '', '', 1, 0, 0, '/system/swagger', 'layout/routerView/iframes', 1, '', 0, 1, 1, '', 0, 'http://localhost:8201/swagger', '2022-04-21 09:23:43', '2022-04-21 11:19:49');
+
+-- ----------------------------
+-- Table structure for sys_config
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_config`;
+CREATE TABLE `sys_config` (
+ `config_id` int(5) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '参数主键',
+ `config_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '参数名称',
+ `config_key` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '参数键名',
+ `config_value` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '参数键值',
+ `config_type` tinyint(1) NULL DEFAULT 0 COMMENT '系统内置(Y是 N否)',
+ `create_by` int(64) UNSIGNED NULL DEFAULT 0 COMMENT '创建者',
+ `update_by` int(64) UNSIGNED NULL DEFAULT 0 COMMENT '更新者',
+ `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `created_at` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+ `updated_at` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
+ PRIMARY KEY (`config_id`) USING BTREE,
+ UNIQUE INDEX `uni_config_key`(`config_key`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 15 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of sys_config
+-- ----------------------------
+INSERT INTO `sys_config` VALUES (1, '文件上传-文件大小', 'sys.uploadFile.fileSize', '50M', 1, 31, 31, '文件上传大小限制', NULL, '2021-07-06 14:57:35');
+INSERT INTO `sys_config` VALUES (2, '文件上传-文件类型', 'sys.uploadFile.fileType', 'doc,docx,zip,xls,xlsx,rar,jpg,jpeg,gif,npm,png', 1, 31, 31, '文件上传后缀类型限制', NULL, NULL);
+INSERT INTO `sys_config` VALUES (3, '图片上传-图片类型', 'sys.uploadFile.imageType', 'jpg,jpeg,gif,npm,png', 1, 31, 0, '图片上传后缀类型限制', NULL, NULL);
+INSERT INTO `sys_config` VALUES (4, '图片上传-图片大小', 'sys.uploadFile.imageSize', '50M', 1, 31, 31, '图片上传大小限制', NULL, NULL);
+INSERT INTO `sys_config` VALUES (11, '静态资源', 'static.resource', '/', 1, 2, 0, '', NULL, NULL);
+
+-- ----------------------------
+-- Table structure for sys_dept
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_dept`;
+CREATE TABLE `sys_dept` (
+ `dept_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '部门id',
+ `parent_id` bigint(20) NULL DEFAULT 0 COMMENT '父部门id',
+ `ancestors` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '祖级列表',
+ `dept_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '部门名称',
+ `order_num` int(4) NULL DEFAULT 0 COMMENT '显示顺序',
+ `leader` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '负责人',
+ `phone` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系电话',
+ `email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮箱',
+ `status` tinyint(3) UNSIGNED NULL DEFAULT 0 COMMENT '部门状态(0正常 1停用)',
+ `created_by` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '创建人',
+ `updated_by` bigint(20) NULL DEFAULT NULL COMMENT '修改人',
+ `created_at` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+ `updated_at` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
+ `deleted_at` datetime(0) NULL DEFAULT NULL COMMENT '删除时间',
+ PRIMARY KEY (`dept_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 204 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '部门表' ROW_FORMAT = Compact;
+
+-- ----------------------------
+-- Records of sys_dept
+-- ----------------------------
+INSERT INTO `sys_dept` VALUES (100, 0, '0', '奇讯科技', 0, '若依', '15888888888', 'ry@qq.com', 1, 0, 31, '2021-07-13 15:56:52', '2021-07-13 15:57:05', NULL);
+INSERT INTO `sys_dept` VALUES (101, 100, '0,100', '深圳总公司', 1, '若依', '15888888888', 'ry@qq.com', 1, 0, NULL, '2021-07-13 15:56:52', '2021-07-13 15:56:52', NULL);
+INSERT INTO `sys_dept` VALUES (102, 100, '0,100', '长沙分公司', 2, '若依', '15888888888', 'ry@qq.com', 1, 0, NULL, '2021-07-13 15:56:52', '2021-07-13 15:56:52', NULL);
+INSERT INTO `sys_dept` VALUES (103, 101, '0,100,101', '研发部门', 1, '若依', '15888888888', 'ry@qq.com', 1, 0, NULL, '2021-07-13 15:56:52', '2021-07-13 15:56:52', NULL);
+INSERT INTO `sys_dept` VALUES (104, 101, '0,100,101', '市场部门', 2, '若依', '15888888888', 'ry@qq.com', 1, 0, 31, '2021-07-13 15:56:52', '2021-11-04 09:16:38', NULL);
+INSERT INTO `sys_dept` VALUES (105, 101, '0,100,101', '测试部门', 3, '若依', '15888888888', 'ry@qq.com', 1, 0, NULL, '2021-07-13 15:56:52', '2021-07-13 15:56:52', NULL);
+INSERT INTO `sys_dept` VALUES (106, 101, '0,100,101', '财务部门', 4, '若依', '15888888888', 'ry@qq.com', 1, 0, NULL, '2021-07-13 15:56:52', '2021-07-13 15:56:52', NULL);
+INSERT INTO `sys_dept` VALUES (107, 101, '0,100,101', '运维部门', 5, '若依', '15888888888', 'ry@qq.com', 1, 0, NULL, '2021-07-13 15:56:52', '2021-07-13 15:56:52', NULL);
+INSERT INTO `sys_dept` VALUES (108, 102, '0,100,102', '市场部门', 1, '若依', '15888888888', 'ry@qq.com', 1, 0, NULL, '2021-07-13 15:56:52', '2021-07-13 15:56:52', NULL);
+INSERT INTO `sys_dept` VALUES (109, 102, '0,100,102', '财务部门', 2, '若依', '15888888888', 'ry@qq.com', 1, 0, NULL, '2021-07-13 15:56:52', '2021-07-13 15:56:52', NULL);
+INSERT INTO `sys_dept` VALUES (200, 100, '', '大数据', 1, '小刘', '18888888888', 'liou@qq.com', 1, 0, NULL, '2021-07-13 15:56:52', '2021-07-13 15:56:52', NULL);
+INSERT INTO `sys_dept` VALUES (201, 100, '', '开发', 1, '老李', '18888888888', 'li@qq.com', 0, 31, NULL, '2021-07-13 15:56:52', '2022-04-07 22:35:21', NULL);
+INSERT INTO `sys_dept` VALUES (202, 108, '', '外勤', 1, '小a', '18888888888', 'aa@qq.com', 1, 0, NULL, '2021-07-13 15:56:52', '2021-07-13 15:56:52', NULL);
+INSERT INTO `sys_dept` VALUES (203, 108, '', '行政', 0, 'aa', '18888888888', 'aa@qq.com', 0, 0, NULL, '2021-07-13 15:56:52', '2021-07-13 15:56:52', NULL);
+
+-- ----------------------------
+-- Table structure for sys_dict_data
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_dict_data`;
+CREATE TABLE `sys_dict_data` (
+ `dict_code` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '字典编码',
+ `dict_sort` int(4) NULL DEFAULT 0 COMMENT '字典排序',
+ `dict_label` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '字典标签',
+ `dict_value` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '字典键值',
+ `dict_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '字典类型',
+ `css_class` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '样式属性(其他样式扩展)',
+ `list_class` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '表格回显样式',
+ `is_default` tinyint(1) NULL DEFAULT 0 COMMENT '是否默认(1是 0否)',
+ `status` tinyint(1) NULL DEFAULT 0 COMMENT '状态(0正常 1停用)',
+ `create_by` bigint(64) UNSIGNED NULL DEFAULT 0 COMMENT '创建者',
+ `update_by` bigint(64) UNSIGNED NULL DEFAULT 0 COMMENT '更新者',
+ `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `created_at` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+ `updated_at` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
+ PRIMARY KEY (`dict_code`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 102 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '字典数据表' ROW_FORMAT = Compact;
+
+-- ----------------------------
+-- Records of sys_dict_data
+-- ----------------------------
+INSERT INTO `sys_dict_data` VALUES (1, 0, '男', '1', 'sys_user_sex', '', '', 0, 1, 31, 2, '备注信息', '2022-04-18 16:46:22', NULL);
+INSERT INTO `sys_dict_data` VALUES (2, 0, '女', '2', 'sys_user_sex', '', '', 0, 1, 31, 31, '备注信息', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (3, 0, '保密', '0', 'sys_user_sex', '', '', 1, 1, 31, 31, '备注信息', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (24, 0, '频道页', '1', 'cms_category_type', '', '', 0, 1, 31, 31, '作为频道页,不可作为栏目发布文章,可添加下级分类', NULL, '2021-07-21 10:54:22');
+INSERT INTO `sys_dict_data` VALUES (25, 0, '发布栏目', '2', 'cms_category_type', '', '', 0, 1, 31, 31, '作为发布栏目,可添加文章', NULL, '2021-07-21 10:54:22');
+INSERT INTO `sys_dict_data` VALUES (26, 0, '跳转栏目', '3', 'cms_category_type', '', '', 0, 1, 31, 31, '不直接发布内容,用于跳转页面', NULL, '2021-07-21 10:54:22');
+INSERT INTO `sys_dict_data` VALUES (27, 0, '单页栏目', '4', 'cms_category_type', '', '', 0, 1, 31, 31, '单页面模式,分类直接显示为文章', NULL, '2021-07-21 10:54:22');
+INSERT INTO `sys_dict_data` VALUES (28, 0, '正常', '0', 'sys_job_status', '', 'default', 1, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (29, 0, '暂停', '1', 'sys_job_status', '', 'default', 0, 1, 31, 31, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (30, 0, '默认', 'DEFAULT', 'sys_job_group', '', 'default', 1, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (31, 0, '系统', 'SYSTEM', 'sys_job_group', '', 'default', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (32, 0, '成功', '1', 'admin_login_status', '', 'default', 0, 1, 31, 31, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (33, 0, '失败', '0', 'admin_login_status', '', 'default', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (34, 0, '成功', '1', 'sys_oper_log_status', '', 'default', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (35, 0, '失败', '0', 'sys_oper_log_status', '', 'default', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (36, 0, '重复执行', '1', 'sys_job_policy', '', 'default', 1, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (37, 0, '执行一次', '2', 'sys_job_policy', '', 'default', 1, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (38, 0, '显示', '0', 'sys_show_hide', NULL, 'default', 1, 1, 31, 0, NULL, NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (39, 0, '隐藏', '1', 'sys_show_hide', NULL, 'default', 0, 1, 31, 0, NULL, NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (40, 0, '正常', '1', 'sys_normal_disable', '', 'default', 1, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (41, 0, '停用', '0', 'sys_normal_disable', '', 'default', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (49, 0, '是', '1', 'sys_yes_no', '', '', 1, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (50, 0, '否', '0', 'sys_yes_no', '', '', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (51, 0, '已发布', '1', 'cms_article_pub_type', '', '', 1, 1, 31, 31, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (54, 0, '未发布', '0', 'cms_article_pub_type', '', '', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (55, 0, '置顶', '1', 'cms_article_attr', '', '', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (56, 0, '推荐', '2', 'cms_article_attr', '', '', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (57, 0, '普通文章', '0', 'cms_article_type', '', '', 0, 1, 31, 31, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (58, 0, '跳转链接', '1', 'cms_article_type', '', '', 0, 1, 31, 31, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (59, 0, 'cms模型', '6', 'cms_cate_models', '', '', 0, 1, 1, 1, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (61, 0, '政府工作目标', '1', 'gov_cate_models', '', '', 0, 1, 2, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (62, 0, '系统后台', 'sys_admin', 'menu_module_type', '', '', 1, 1, 2, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (63, 0, '政务工作', 'gov_work', 'menu_module_type', '', '', 0, 1, 2, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (64, 0, '幻灯', '3', 'cms_article_attr', '', '', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (65, 0, '[work]测试业务表', 'wf_news', 'flow_type', '', '', 0, 1, 2, 2, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (66, 0, '回退修改', '-1', 'flow_status', '', '', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (67, 0, '保存中', '0', 'flow_status', '', '', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (68, 0, '流程中', '1', 'flow_status', '', '', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (69, 0, '审批通过', '2', 'flow_status', '', '', 0, 1, 31, 2, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (70, 2, '发布栏目', '2', 'sys_blog_sign', '', '', 0, 1, 31, 31, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (71, 3, '跳转栏目', '3', 'sys_blog_sign', '', '', 0, 1, 31, 31, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (72, 4, '单页栏目', '4', 'sys_blog_sign', '', '', 0, 1, 31, 31, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (73, 2, '置顶', '1', 'sys_log_sign', '', '', 0, 1, 31, 31, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (74, 3, '幻灯', '2', 'sys_log_sign', '', '', 0, 1, 31, 31, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (75, 4, '推荐', '3', 'sys_log_sign', '', '', 0, 1, 31, 31, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (76, 1, '一般', '0', 'sys_log_sign', '', '', 0, 1, 31, 31, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (77, 1, '频道页', '1', 'sys_blog_sign', '', '', 0, 1, 31, 31, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (78, 0, '普通', '0', 'flow_level', '', '', 0, 1, 31, 0, '', NULL, '2021-07-20 08:55:20');
+INSERT INTO `sys_dict_data` VALUES (79, 0, '加急', '1', 'flow_level', '', '', 0, 1, 31, 0, '', NULL, '2021-07-20 08:55:20');
+INSERT INTO `sys_dict_data` VALUES (80, 0, '紧急', '2', 'flow_level', '', '', 0, 1, 31, 0, '', NULL, '2021-07-20 08:55:20');
+INSERT INTO `sys_dict_data` VALUES (81, 0, '特急', '3', 'flow_level', '', '', 0, 1, 31, 31, '', NULL, '2021-07-20 08:55:25');
+INSERT INTO `sys_dict_data` VALUES (82, 0, '频道页', '1', 'sys_blog_type', '', '', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (83, 0, '发布栏目', '2', 'sys_blog_type', '', '', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (84, 0, '跳转栏目', '3', 'sys_blog_type', '', '', 0, 1, 31, 31, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (85, 0, '单页栏目', '4', 'sys_blog_type', '', '', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (87, 0, '[cms]文章表', 'cms_news', 'flow_type', '', '', 0, 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_data` VALUES (91, 0, '测试一下', '666', 'cms_article_type', '', '', 0, 1, 31, 0, '', '2021-08-03 17:04:12', '2021-08-03 17:04:12');
+INSERT INTO `sys_dict_data` VALUES (92, 0, '缓存测试222', '33333', 'cms_article_type', '', '', 0, 1, 31, 31, '', '2021-08-03 17:16:45', '2021-08-03 17:19:41');
+INSERT INTO `sys_dict_data` VALUES (93, 0, '缓存测试222', '11111', 'cms_article_type', '', '', 0, 1, 31, 31, '', '2021-08-03 17:26:14', '2021-08-03 17:26:26');
+INSERT INTO `sys_dict_data` VALUES (94, 0, '1折', '10', 'plugin_store_discount', '', '', 0, 1, 31, 0, '', '2021-08-14 11:59:38', '2021-08-14 11:59:38');
+INSERT INTO `sys_dict_data` VALUES (95, 0, '5折', '50', 'plugin_store_discount', '', '', 0, 1, 31, 0, '', '2021-08-14 11:59:49', '2021-08-14 11:59:49');
+INSERT INTO `sys_dict_data` VALUES (96, 0, '8折', '80', 'plugin_store_discount', '', '', 0, 1, 31, 0, '', '2021-08-14 12:00:00', '2021-08-14 12:00:00');
+INSERT INTO `sys_dict_data` VALUES (97, 0, '9折', '90', 'plugin_store_discount', '', '', 0, 1, 31, 0, '', '2021-08-14 12:00:07', '2021-08-14 12:00:07');
+INSERT INTO `sys_dict_data` VALUES (98, 0, '无折扣', '100', 'plugin_store_discount', '', '', 0, 1, 31, 0, '', '2021-08-14 12:00:16', '2021-08-14 12:00:16');
+INSERT INTO `sys_dict_data` VALUES (99, 0, '不显示', 'none', 'cms_nav_position', '', '', 1, 1, 22, 0, '', '2021-08-31 15:37:35', '2021-08-31 15:37:35');
+INSERT INTO `sys_dict_data` VALUES (100, 0, '顶部导航', 'top', 'cms_nav_position', '', '', 0, 1, 22, 0, '', '2021-08-31 15:37:57', '2021-08-31 15:37:57');
+INSERT INTO `sys_dict_data` VALUES (101, 0, '底部导航', 'bottom', 'cms_nav_position', '', '', 0, 1, 22, 0, '', '2021-08-31 15:38:08', '2021-08-31 15:38:08');
+
+-- ----------------------------
+-- Table structure for sys_dict_type
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_dict_type`;
+CREATE TABLE `sys_dict_type` (
+ `dict_id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '字典主键',
+ `dict_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '字典名称',
+ `dict_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '字典类型',
+ `status` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '状态(0正常 1停用)',
+ `create_by` int(64) UNSIGNED NULL DEFAULT 0 COMMENT '创建者',
+ `update_by` int(64) UNSIGNED NULL DEFAULT 0 COMMENT '更新者',
+ `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `created_at` datetime(0) NULL DEFAULT NULL COMMENT '创建日期',
+ `updated_at` datetime(0) NULL DEFAULT NULL COMMENT '修改日期',
+ PRIMARY KEY (`dict_id`) USING BTREE,
+ UNIQUE INDEX `dict_type`(`dict_type`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 50 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '字典类型表' ROW_FORMAT = Compact;
+
+-- ----------------------------
+-- Records of sys_dict_type
+-- ----------------------------
+INSERT INTO `sys_dict_type` VALUES (1, '用户性别', 'sys_user_sex', 1, 31, 1, '用于选择用户性别', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (2, '分类类型', 'cms_category_type', 1, 31, 3, '文章分类类型', NULL, '2021-07-21 10:54:22');
+INSERT INTO `sys_dict_type` VALUES (3, '任务状态', 'sys_job_status', 1, 31, 31, '任务状态列表', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (13, '任务分组', 'sys_job_group', 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (14, '管理员登录状态', 'admin_login_status', 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (15, '操作日志状态', 'sys_oper_log_status', 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (16, '任务策略', 'sys_job_policy', 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (17, '菜单状态', 'sys_show_hide', 1, 31, 0, '菜单状态', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (18, '系统开关', 'sys_normal_disable', 1, 31, 31, '系统开关', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (24, '系统内置', 'sys_yes_no', 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (25, '文章发布状态', 'cms_article_pub_type', 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (26, '文章附加状态', 'cms_article_attr', 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (27, '文章类型', 'cms_article_type', 1, 31, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (28, '文章栏目模型分类', 'cms_cate_models', 1, 1, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (29, '政务工作模型分类', 'gov_cate_models', 1, 2, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (30, '菜单模块类型', 'menu_module_type', 1, 2, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (31, '工作流程类型', 'flow_type', 1, 2, 0, '', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (32, '工作流程审批状态', 'flow_status', 1, 31, 0, '工作流程审批状态', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (33, '博客分类类型', 'sys_blog_type', 1, 31, 31, '博客分类中的标志', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (34, '博客日志标志', 'sys_log_sign', 1, 31, 0, '博客日志管理中的标志数据字典', NULL, NULL);
+INSERT INTO `sys_dict_type` VALUES (35, '工作流紧急状态', 'flow_level', 1, 31, 31, '', NULL, '2021-07-20 08:55:20');
+INSERT INTO `sys_dict_type` VALUES (48, '插件商城折扣', 'plugin_store_discount', 1, 31, 0, '', '2021-08-14 11:59:26', '2021-08-14 11:59:26');
+INSERT INTO `sys_dict_type` VALUES (49, 'CMS栏目导航位置', 'cms_nav_position', 1, 22, 0, '', '2021-08-31 15:37:04', '2021-08-31 15:37:04');
+
+-- ----------------------------
+-- Table structure for sys_login_log
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_login_log`;
+CREATE TABLE `sys_login_log` (
+ `info_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '访问ID',
+ `login_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '登录账号',
+ `ipaddr` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '登录IP地址',
+ `login_location` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '登录地点',
+ `browser` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '浏览器类型',
+ `os` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '操作系统',
+ `status` tinyint(4) NULL DEFAULT 0 COMMENT '登录状态(0成功 1失败)',
+ `msg` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '提示消息',
+ `login_time` datetime(0) NULL DEFAULT NULL COMMENT '登录时间',
+ `module` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '登录模块',
+ PRIMARY KEY (`info_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 886 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统访问记录' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of sys_login_log
+-- ----------------------------
+INSERT INTO `sys_login_log` VALUES (449, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 12:14:56', '系统后台');
+INSERT INTO `sys_login_log` VALUES (450, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 14:23:14', '系统后台');
+INSERT INTO `sys_login_log` VALUES (451, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 14:23:21', '系统后台');
+INSERT INTO `sys_login_log` VALUES (452, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 14:25:13', '系统后台');
+INSERT INTO `sys_login_log` VALUES (453, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 17:30:17', '系统后台');
+INSERT INTO `sys_login_log` VALUES (454, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 17:31:42', '系统后台');
+INSERT INTO `sys_login_log` VALUES (455, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 17:32:30', '系统后台');
+INSERT INTO `sys_login_log` VALUES (456, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 17:39:41', '系统后台');
+INSERT INTO `sys_login_log` VALUES (457, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 17:39:45', '系统后台');
+INSERT INTO `sys_login_log` VALUES (458, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 17:41:04', '系统后台');
+INSERT INTO `sys_login_log` VALUES (459, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 17:42:08', '系统后台');
+INSERT INTO `sys_login_log` VALUES (460, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 17:45:02', '系统后台');
+INSERT INTO `sys_login_log` VALUES (461, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 17:45:13', '系统后台');
+INSERT INTO `sys_login_log` VALUES (462, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 17:45:45', '系统后台');
+INSERT INTO `sys_login_log` VALUES (463, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 17:45:46', '系统后台');
+INSERT INTO `sys_login_log` VALUES (464, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 17:46:05', '系统后台');
+INSERT INTO `sys_login_log` VALUES (465, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 17:46:06', '系统后台');
+INSERT INTO `sys_login_log` VALUES (466, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 17:47:14', '系统后台');
+INSERT INTO `sys_login_log` VALUES (467, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 17:47:42', '系统后台');
+INSERT INTO `sys_login_log` VALUES (468, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 17:47:42', '系统后台');
+INSERT INTO `sys_login_log` VALUES (469, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 18:02:21', '系统后台');
+INSERT INTO `sys_login_log` VALUES (470, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 18:03:09', '系统后台');
+INSERT INTO `sys_login_log` VALUES (471, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 18:04:29', '系统后台');
+INSERT INTO `sys_login_log` VALUES (472, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 18:06:28', '系统后台');
+INSERT INTO `sys_login_log` VALUES (473, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 18:08:37', '系统后台');
+INSERT INTO `sys_login_log` VALUES (474, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 18:08:39', '系统后台');
+INSERT INTO `sys_login_log` VALUES (475, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 18:10:19', '系统后台');
+INSERT INTO `sys_login_log` VALUES (476, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 18:15:32', '系统后台');
+INSERT INTO `sys_login_log` VALUES (477, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 18:18:00', '系统后台');
+INSERT INTO `sys_login_log` VALUES (478, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 18:18:13', '系统后台');
+INSERT INTO `sys_login_log` VALUES (479, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-08 18:24:46', '系统后台');
+INSERT INTO `sys_login_log` VALUES (480, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-09 09:22:39', '系统后台');
+INSERT INTO `sys_login_log` VALUES (481, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-09 11:04:08', '系统后台');
+INSERT INTO `sys_login_log` VALUES (482, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-09 11:09:06', '系统后台');
+INSERT INTO `sys_login_log` VALUES (483, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-09 15:50:29', '系统后台');
+INSERT INTO `sys_login_log` VALUES (484, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-09 15:51:35', '系统后台');
+INSERT INTO `sys_login_log` VALUES (485, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-09 15:52:24', '系统后台');
+INSERT INTO `sys_login_log` VALUES (486, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-09 15:53:34', '系统后台');
+INSERT INTO `sys_login_log` VALUES (487, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-09 16:54:59', '系统后台');
+INSERT INTO `sys_login_log` VALUES (488, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-09 16:58:24', '系统后台');
+INSERT INTO `sys_login_log` VALUES (489, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-09 16:59:12', '系统后台');
+INSERT INTO `sys_login_log` VALUES (490, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-09 17:02:25', '系统后台');
+INSERT INTO `sys_login_log` VALUES (491, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-09 17:03:27', '系统后台');
+INSERT INTO `sys_login_log` VALUES (492, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-09 17:05:14', '系统后台');
+INSERT INTO `sys_login_log` VALUES (493, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 10:21:43', '系统后台');
+INSERT INTO `sys_login_log` VALUES (494, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 10:22:03', '系统后台');
+INSERT INTO `sys_login_log` VALUES (495, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 10:22:05', '系统后台');
+INSERT INTO `sys_login_log` VALUES (496, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 10:31:53', '系统后台');
+INSERT INTO `sys_login_log` VALUES (497, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 10:32:18', '系统后台');
+INSERT INTO `sys_login_log` VALUES (498, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 10:39:56', '系统后台');
+INSERT INTO `sys_login_log` VALUES (499, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 10:55:59', '系统后台');
+INSERT INTO `sys_login_log` VALUES (500, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 10:56:15', '系统后台');
+INSERT INTO `sys_login_log` VALUES (501, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 10:58:30', '系统后台');
+INSERT INTO `sys_login_log` VALUES (502, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 10:58:51', '系统后台');
+INSERT INTO `sys_login_log` VALUES (503, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 10:59:58', '系统后台');
+INSERT INTO `sys_login_log` VALUES (504, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 11:01:00', '系统后台');
+INSERT INTO `sys_login_log` VALUES (505, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 11:01:24', '系统后台');
+INSERT INTO `sys_login_log` VALUES (506, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 16:32:00', '系统后台');
+INSERT INTO `sys_login_log` VALUES (507, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 16:34:53', '系统后台');
+INSERT INTO `sys_login_log` VALUES (508, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 16:34:55', '系统后台');
+INSERT INTO `sys_login_log` VALUES (509, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 16:35:06', '系统后台');
+INSERT INTO `sys_login_log` VALUES (510, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 16:35:37', '系统后台');
+INSERT INTO `sys_login_log` VALUES (511, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 16:36:21', '系统后台');
+INSERT INTO `sys_login_log` VALUES (512, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 16:36:23', '系统后台');
+INSERT INTO `sys_login_log` VALUES (513, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-11 16:37:24', '系统后台');
+INSERT INTO `sys_login_log` VALUES (514, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 09:46:43', '系统后台');
+INSERT INTO `sys_login_log` VALUES (515, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 09:51:58', '系统后台');
+INSERT INTO `sys_login_log` VALUES (516, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 09:55:59', '系统后台');
+INSERT INTO `sys_login_log` VALUES (517, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 10:57:45', '系统后台');
+INSERT INTO `sys_login_log` VALUES (518, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 10:58:42', '系统后台');
+INSERT INTO `sys_login_log` VALUES (519, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 11:39:08', '系统后台');
+INSERT INTO `sys_login_log` VALUES (520, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 11:40:00', '系统后台');
+INSERT INTO `sys_login_log` VALUES (521, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 11:40:40', '系统后台');
+INSERT INTO `sys_login_log` VALUES (522, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:13:48', '系统后台');
+INSERT INTO `sys_login_log` VALUES (523, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:13:57', '系统后台');
+INSERT INTO `sys_login_log` VALUES (524, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:14:12', '系统后台');
+INSERT INTO `sys_login_log` VALUES (525, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:14:14', '系统后台');
+INSERT INTO `sys_login_log` VALUES (526, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:14:24', '系统后台');
+INSERT INTO `sys_login_log` VALUES (527, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:15:24', '系统后台');
+INSERT INTO `sys_login_log` VALUES (528, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:15:26', '系统后台');
+INSERT INTO `sys_login_log` VALUES (529, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:15:28', '系统后台');
+INSERT INTO `sys_login_log` VALUES (530, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:15:29', '系统后台');
+INSERT INTO `sys_login_log` VALUES (531, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:15:30', '系统后台');
+INSERT INTO `sys_login_log` VALUES (532, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:15:32', '系统后台');
+INSERT INTO `sys_login_log` VALUES (533, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:15:32', '系统后台');
+INSERT INTO `sys_login_log` VALUES (534, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:15:43', '系统后台');
+INSERT INTO `sys_login_log` VALUES (535, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:15:44', '系统后台');
+INSERT INTO `sys_login_log` VALUES (536, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:16:08', '系统后台');
+INSERT INTO `sys_login_log` VALUES (537, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:16:17', '系统后台');
+INSERT INTO `sys_login_log` VALUES (538, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:16:19', '系统后台');
+INSERT INTO `sys_login_log` VALUES (539, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:16:20', '系统后台');
+INSERT INTO `sys_login_log` VALUES (540, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-14 15:16:21', '系统后台');
+INSERT INTO `sys_login_log` VALUES (541, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-15 09:18:00', '系统后台');
+INSERT INTO `sys_login_log` VALUES (542, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-15 09:20:55', '系统后台');
+INSERT INTO `sys_login_log` VALUES (543, 'asda', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:17:33', '系统后台');
+INSERT INTO `sys_login_log` VALUES (544, 'asdasd', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:19:02', '系统后台');
+INSERT INTO `sys_login_log` VALUES (545, 'sadasd', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:21:28', '系统后台');
+INSERT INTO `sys_login_log` VALUES (546, 'sadasd', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:21:30', '系统后台');
+INSERT INTO `sys_login_log` VALUES (547, 'asd', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:23:09', '系统后台');
+INSERT INTO `sys_login_log` VALUES (548, 'asd', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:23:12', '系统后台');
+INSERT INTO `sys_login_log` VALUES (549, 'asd', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:23:23', '系统后台');
+INSERT INTO `sys_login_log` VALUES (550, 'asd', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:25:09', '系统后台');
+INSERT INTO `sys_login_log` VALUES (551, 'asd', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:25:25', '系统后台');
+INSERT INTO `sys_login_log` VALUES (552, 'sada', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:27:18', '系统后台');
+INSERT INTO `sys_login_log` VALUES (553, 'asd', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:28:18', '系统后台');
+INSERT INTO `sys_login_log` VALUES (554, 'sadas', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:41:06', '系统后台');
+INSERT INTO `sys_login_log` VALUES (555, 'sadas', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:41:08', '系统后台');
+INSERT INTO `sys_login_log` VALUES (556, 'asdasd', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:42:10', '系统后台');
+INSERT INTO `sys_login_log` VALUES (557, 'asdasd', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:42:13', '系统后台');
+INSERT INTO `sys_login_log` VALUES (558, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:42:32', '系统后台');
+INSERT INTO `sys_login_log` VALUES (559, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:42:42', '系统后台');
+INSERT INTO `sys_login_log` VALUES (560, 'sda', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:43:46', '系统后台');
+INSERT INTO `sys_login_log` VALUES (561, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:45:53', '系统后台');
+INSERT INTO `sys_login_log` VALUES (562, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:45:58', '系统后台');
+INSERT INTO `sys_login_log` VALUES (563, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:45:59', '系统后台');
+INSERT INTO `sys_login_log` VALUES (564, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:46:01', '系统后台');
+INSERT INTO `sys_login_log` VALUES (565, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:46:03', '系统后台');
+INSERT INTO `sys_login_log` VALUES (566, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:46:04', '系统后台');
+INSERT INTO `sys_login_log` VALUES (567, 'dema', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-15 14:46:05', '系统后台');
+INSERT INTO `sys_login_log` VALUES (568, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:46:14', '系统后台');
+INSERT INTO `sys_login_log` VALUES (569, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:46:16', '系统后台');
+INSERT INTO `sys_login_log` VALUES (570, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:46:20', '系统后台');
+INSERT INTO `sys_login_log` VALUES (571, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:46:46', '系统后台');
+INSERT INTO `sys_login_log` VALUES (572, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:48:44', '系统后台');
+INSERT INTO `sys_login_log` VALUES (573, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:49:26', '系统后台');
+INSERT INTO `sys_login_log` VALUES (574, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:49:27', '系统后台');
+INSERT INTO `sys_login_log` VALUES (575, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:49:27', '系统后台');
+INSERT INTO `sys_login_log` VALUES (576, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:49:27', '系统后台');
+INSERT INTO `sys_login_log` VALUES (577, 'admin', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:59:52', '系统后台');
+INSERT INTO `sys_login_log` VALUES (578, 'admin', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 14:59:55', '系统后台');
+INSERT INTO `sys_login_log` VALUES (579, 'admin', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:02:02', '系统后台');
+INSERT INTO `sys_login_log` VALUES (580, 'admin', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:03:01', '系统后台');
+INSERT INTO `sys_login_log` VALUES (581, 'admin', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:04:25', '系统后台');
+INSERT INTO `sys_login_log` VALUES (582, 'admin', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:04:30', '系统后台');
+INSERT INTO `sys_login_log` VALUES (583, 'admin', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:04:34', '系统后台');
+INSERT INTO `sys_login_log` VALUES (584, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:05:50', '系统后台');
+INSERT INTO `sys_login_log` VALUES (585, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:06:36', '系统后台');
+INSERT INTO `sys_login_log` VALUES (586, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:10:07', '系统后台');
+INSERT INTO `sys_login_log` VALUES (587, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:11:17', '系统后台');
+INSERT INTO `sys_login_log` VALUES (588, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:12:15', '系统后台');
+INSERT INTO `sys_login_log` VALUES (589, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:13:30', '系统后台');
+INSERT INTO `sys_login_log` VALUES (590, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:15:07', '系统后台');
+INSERT INTO `sys_login_log` VALUES (591, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:16:02', '系统后台');
+INSERT INTO `sys_login_log` VALUES (592, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:20:06', '系统后台');
+INSERT INTO `sys_login_log` VALUES (593, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:21:18', '系统后台');
+INSERT INTO `sys_login_log` VALUES (594, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:21:32', '系统后台');
+INSERT INTO `sys_login_log` VALUES (595, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:21:56', '系统后台');
+INSERT INTO `sys_login_log` VALUES (596, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:26:44', '系统后台');
+INSERT INTO `sys_login_log` VALUES (597, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:49:34', '系统后台');
+INSERT INTO `sys_login_log` VALUES (598, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:49:37', '系统后台');
+INSERT INTO `sys_login_log` VALUES (599, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:57:07', '系统后台');
+INSERT INTO `sys_login_log` VALUES (600, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 15:57:09', '系统后台');
+INSERT INTO `sys_login_log` VALUES (601, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 16:00:52', '系统后台');
+INSERT INTO `sys_login_log` VALUES (602, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 16:02:47', '系统后台');
+INSERT INTO `sys_login_log` VALUES (603, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 16:02:58', '系统后台');
+INSERT INTO `sys_login_log` VALUES (604, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-15 16:10:05', '系统后台');
+INSERT INTO `sys_login_log` VALUES (605, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-15 16:30:13', '系统后台');
+INSERT INTO `sys_login_log` VALUES (606, 'admin', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-15 16:31:16', '系统后台');
+INSERT INTO `sys_login_log` VALUES (607, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-15 16:31:46', '系统后台');
+INSERT INTO `sys_login_log` VALUES (608, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-15 16:33:18', '系统后台');
+INSERT INTO `sys_login_log` VALUES (609, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-15 16:34:24', '系统后台');
+INSERT INTO `sys_login_log` VALUES (610, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-15 17:55:46', '系统后台');
+INSERT INTO `sys_login_log` VALUES (611, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-15 17:56:40', '系统后台');
+INSERT INTO `sys_login_log` VALUES (612, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-15 17:57:46', '系统后台');
+INSERT INTO `sys_login_log` VALUES (613, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-15 18:00:21', '系统后台');
+INSERT INTO `sys_login_log` VALUES (614, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-15 18:01:42', '系统后台');
+INSERT INTO `sys_login_log` VALUES (615, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 18:05:44', '系统后台');
+INSERT INTO `sys_login_log` VALUES (616, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 18:21:44', '系统后台');
+INSERT INTO `sys_login_log` VALUES (617, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 18:21:52', '系统后台');
+INSERT INTO `sys_login_log` VALUES (618, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 18:22:23', '系统后台');
+INSERT INTO `sys_login_log` VALUES (619, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-15 18:23:20', '系统后台');
+INSERT INTO `sys_login_log` VALUES (620, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 09:30:54', '系统后台');
+INSERT INTO `sys_login_log` VALUES (621, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 09:57:49', '系统后台');
+INSERT INTO `sys_login_log` VALUES (622, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 09:58:17', '系统后台');
+INSERT INTO `sys_login_log` VALUES (623, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 10:14:18', '系统后台');
+INSERT INTO `sys_login_log` VALUES (624, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 10:20:26', '系统后台');
+INSERT INTO `sys_login_log` VALUES (625, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 10:22:18', '系统后台');
+INSERT INTO `sys_login_log` VALUES (626, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 10:22:23', '系统后台');
+INSERT INTO `sys_login_log` VALUES (627, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 10:22:24', '系统后台');
+INSERT INTO `sys_login_log` VALUES (628, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 10:22:28', '系统后台');
+INSERT INTO `sys_login_log` VALUES (629, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 10:32:10', '系统后台');
+INSERT INTO `sys_login_log` VALUES (630, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 10:32:49', '系统后台');
+INSERT INTO `sys_login_log` VALUES (631, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 11:30:03', '系统后台');
+INSERT INTO `sys_login_log` VALUES (632, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 12:03:09', '系统后台');
+INSERT INTO `sys_login_log` VALUES (633, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 12:06:17', '系统后台');
+INSERT INTO `sys_login_log` VALUES (634, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 14:14:50', '系统后台');
+INSERT INTO `sys_login_log` VALUES (635, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 15:57:09', '系统后台');
+INSERT INTO `sys_login_log` VALUES (636, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 16:43:46', '系统后台');
+INSERT INTO `sys_login_log` VALUES (637, 'demosada', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-16 17:17:12', '系统后台');
+INSERT INTO `sys_login_log` VALUES (638, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 17:17:30', '系统后台');
+INSERT INTO `sys_login_log` VALUES (639, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 17:17:43', '系统后台');
+INSERT INTO `sys_login_log` VALUES (640, 'demoasdasd', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-16 17:17:53', '系统后台');
+INSERT INTO `sys_login_log` VALUES (641, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 17:18:23', '系统后台');
+INSERT INTO `sys_login_log` VALUES (642, 'zsasda', '127.0.0.1', '内网IP', 'ApiPOST', '', 0, '账号密码错误', '2022-03-16 17:18:26', '系统后台');
+INSERT INTO `sys_login_log` VALUES (643, 'zsa', '127.0.0.1', '内网IP', 'ApiPOST', '', 0, '账号密码错误', '2022-03-16 17:18:41', '系统后台');
+INSERT INTO `sys_login_log` VALUES (644, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 0, '账号密码错误', '2022-03-16 17:18:48', '系统后台');
+INSERT INTO `sys_login_log` VALUES (645, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 0, '账号密码错误', '2022-03-16 17:19:45', '系统后台');
+INSERT INTO `sys_login_log` VALUES (646, 'demo55', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-16 17:21:06', '系统后台');
+INSERT INTO `sys_login_log` VALUES (647, 'demo4564646', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-16 17:21:21', '系统后台');
+INSERT INTO `sys_login_log` VALUES (648, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 17:21:56', '系统后台');
+INSERT INTO `sys_login_log` VALUES (649, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 17:22:52', '系统后台');
+INSERT INTO `sys_login_log` VALUES (650, 'demo2', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-16 17:24:11', '系统后台');
+INSERT INTO `sys_login_log` VALUES (651, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 17:24:37', '系统后台');
+INSERT INTO `sys_login_log` VALUES (652, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 17:25:12', '系统后台');
+INSERT INTO `sys_login_log` VALUES (653, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 17:25:22', '系统后台');
+INSERT INTO `sys_login_log` VALUES (654, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 17:25:27', '系统后台');
+INSERT INTO `sys_login_log` VALUES (655, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 0, '账号密码错误', '2022-03-16 17:25:56', '系统后台');
+INSERT INTO `sys_login_log` VALUES (656, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 17:26:03', '系统后台');
+INSERT INTO `sys_login_log` VALUES (657, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 17:26:08', '系统后台');
+INSERT INTO `sys_login_log` VALUES (658, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 17:27:17', '系统后台');
+INSERT INTO `sys_login_log` VALUES (659, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 17:27:52', '系统后台');
+INSERT INTO `sys_login_log` VALUES (660, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 17:28:07', '系统后台');
+INSERT INTO `sys_login_log` VALUES (661, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 17:28:10', '系统后台');
+INSERT INTO `sys_login_log` VALUES (662, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 17:28:31', '系统后台');
+INSERT INTO `sys_login_log` VALUES (663, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 17:29:00', '系统后台');
+INSERT INTO `sys_login_log` VALUES (664, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-16 17:30:28', '系统后台');
+INSERT INTO `sys_login_log` VALUES (665, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 17:30:46', '系统后台');
+INSERT INTO `sys_login_log` VALUES (666, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 17:31:12', '系统后台');
+INSERT INTO `sys_login_log` VALUES (667, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 17:31:13', '系统后台');
+INSERT INTO `sys_login_log` VALUES (668, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 17:32:00', '系统后台');
+INSERT INTO `sys_login_log` VALUES (669, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 17:37:39', '系统后台');
+INSERT INTO `sys_login_log` VALUES (670, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 17:42:16', '系统后台');
+INSERT INTO `sys_login_log` VALUES (671, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 17:44:00', '系统后台');
+INSERT INTO `sys_login_log` VALUES (672, 'zsss', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-16 17:45:23', '系统后台');
+INSERT INTO `sys_login_log` VALUES (673, 'zsss', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-16 17:45:29', '系统后台');
+INSERT INTO `sys_login_log` VALUES (674, 'zsss', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-16 17:45:34', '系统后台');
+INSERT INTO `sys_login_log` VALUES (675, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 17:50:57', '系统后台');
+INSERT INTO `sys_login_log` VALUES (676, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 18:05:59', '系统后台');
+INSERT INTO `sys_login_log` VALUES (677, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 18:18:27', '系统后台');
+INSERT INTO `sys_login_log` VALUES (678, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 18:22:40', '系统后台');
+INSERT INTO `sys_login_log` VALUES (679, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 18:24:14', '系统后台');
+INSERT INTO `sys_login_log` VALUES (680, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 18:24:43', '系统后台');
+INSERT INTO `sys_login_log` VALUES (681, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-16 18:24:51', '系统后台');
+INSERT INTO `sys_login_log` VALUES (682, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-17 10:00:59', '系统后台');
+INSERT INTO `sys_login_log` VALUES (683, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-17 10:04:08', '系统后台');
+INSERT INTO `sys_login_log` VALUES (684, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-17 10:05:28', '系统后台');
+INSERT INTO `sys_login_log` VALUES (685, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 10:29:12', '系统后台');
+INSERT INTO `sys_login_log` VALUES (686, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 10:35:19', '系统后台');
+INSERT INTO `sys_login_log` VALUES (687, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 10:43:37', '系统后台');
+INSERT INTO `sys_login_log` VALUES (688, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-17 10:45:05', '系统后台');
+INSERT INTO `sys_login_log` VALUES (689, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 10:45:18', '系统后台');
+INSERT INTO `sys_login_log` VALUES (690, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-17 10:45:37', '系统后台');
+INSERT INTO `sys_login_log` VALUES (691, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 0, '账号密码错误', '2022-03-17 10:46:50', '系统后台');
+INSERT INTO `sys_login_log` VALUES (692, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 10:47:21', '系统后台');
+INSERT INTO `sys_login_log` VALUES (693, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 10:48:23', '系统后台');
+INSERT INTO `sys_login_log` VALUES (694, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 10:51:19', '系统后台');
+INSERT INTO `sys_login_log` VALUES (695, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-17 10:52:20', '系统后台');
+INSERT INTO `sys_login_log` VALUES (696, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-17 10:55:42', '系统后台');
+INSERT INTO `sys_login_log` VALUES (697, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-17 10:55:43', '系统后台');
+INSERT INTO `sys_login_log` VALUES (698, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-17 10:55:44', '系统后台');
+INSERT INTO `sys_login_log` VALUES (699, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-17 10:55:45', '系统后台');
+INSERT INTO `sys_login_log` VALUES (700, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-17 10:57:36', '系统后台');
+INSERT INTO `sys_login_log` VALUES (701, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 11:06:06', '系统后台');
+INSERT INTO `sys_login_log` VALUES (702, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 11:09:07', '系统后台');
+INSERT INTO `sys_login_log` VALUES (703, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 11:11:10', '系统后台');
+INSERT INTO `sys_login_log` VALUES (704, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 11:26:31', '系统后台');
+INSERT INTO `sys_login_log` VALUES (705, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 11:30:27', '系统后台');
+INSERT INTO `sys_login_log` VALUES (706, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 11:36:21', '系统后台');
+INSERT INTO `sys_login_log` VALUES (707, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 11:42:24', '系统后台');
+INSERT INTO `sys_login_log` VALUES (708, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 11:45:25', '系统后台');
+INSERT INTO `sys_login_log` VALUES (709, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 11:54:51', '系统后台');
+INSERT INTO `sys_login_log` VALUES (710, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 14:41:42', '系统后台');
+INSERT INTO `sys_login_log` VALUES (711, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 14:45:39', '系统后台');
+INSERT INTO `sys_login_log` VALUES (712, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 14:55:57', '系统后台');
+INSERT INTO `sys_login_log` VALUES (713, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 15:15:12', '系统后台');
+INSERT INTO `sys_login_log` VALUES (714, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 15:20:43', '系统后台');
+INSERT INTO `sys_login_log` VALUES (715, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 15:21:49', '系统后台');
+INSERT INTO `sys_login_log` VALUES (716, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 15:24:28', '系统后台');
+INSERT INTO `sys_login_log` VALUES (717, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 15:46:38', '系统后台');
+INSERT INTO `sys_login_log` VALUES (718, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 15:48:02', '系统后台');
+INSERT INTO `sys_login_log` VALUES (719, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 15:49:52', '系统后台');
+INSERT INTO `sys_login_log` VALUES (720, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 15:50:36', '系统后台');
+INSERT INTO `sys_login_log` VALUES (721, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 15:51:48', '系统后台');
+INSERT INTO `sys_login_log` VALUES (722, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 15:54:50', '系统后台');
+INSERT INTO `sys_login_log` VALUES (723, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 15:56:04', '系统后台');
+INSERT INTO `sys_login_log` VALUES (724, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 15:57:18', '系统后台');
+INSERT INTO `sys_login_log` VALUES (725, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 15:58:24', '系统后台');
+INSERT INTO `sys_login_log` VALUES (726, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-17 16:04:05', '系统后台');
+INSERT INTO `sys_login_log` VALUES (727, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 16:04:39', '系统后台');
+INSERT INTO `sys_login_log` VALUES (728, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-17 16:10:20', '系统后台');
+INSERT INTO `sys_login_log` VALUES (729, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 16:13:49', '系统后台');
+INSERT INTO `sys_login_log` VALUES (730, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 16:16:06', '系统后台');
+INSERT INTO `sys_login_log` VALUES (731, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 16:32:57', '系统后台');
+INSERT INTO `sys_login_log` VALUES (732, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 16:39:26', '系统后台');
+INSERT INTO `sys_login_log` VALUES (733, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 16:42:27', '系统后台');
+INSERT INTO `sys_login_log` VALUES (734, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 16:44:38', '系统后台');
+INSERT INTO `sys_login_log` VALUES (735, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 16:46:11', '系统后台');
+INSERT INTO `sys_login_log` VALUES (736, 'zs', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 16:48:00', '系统后台');
+INSERT INTO `sys_login_log` VALUES (737, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 16:54:33', '系统后台');
+INSERT INTO `sys_login_log` VALUES (738, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-17 17:06:44', '系统后台');
+INSERT INTO `sys_login_log` VALUES (739, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 17:55:46', '系统后台');
+INSERT INTO `sys_login_log` VALUES (740, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-17 18:07:51', '系统后台');
+INSERT INTO `sys_login_log` VALUES (741, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-18 09:44:38', '系统后台');
+INSERT INTO `sys_login_log` VALUES (742, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-18 14:29:28', '系统后台');
+INSERT INTO `sys_login_log` VALUES (743, 'zs', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-18 15:22:13', '系统后台');
+INSERT INTO `sys_login_log` VALUES (744, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-18 15:22:29', '系统后台');
+INSERT INTO `sys_login_log` VALUES (745, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-21 09:21:30', '系统后台');
+INSERT INTO `sys_login_log` VALUES (746, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-21 14:14:54', '系统后台');
+INSERT INTO `sys_login_log` VALUES (747, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-21 14:14:59', '系统后台');
+INSERT INTO `sys_login_log` VALUES (748, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-21 14:15:44', '系统后台');
+INSERT INTO `sys_login_log` VALUES (749, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-21 14:16:28', '系统后台');
+INSERT INTO `sys_login_log` VALUES (750, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-21 14:38:30', '系统后台');
+INSERT INTO `sys_login_log` VALUES (751, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-21 15:17:20', '系统后台');
+INSERT INTO `sys_login_log` VALUES (752, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-21 15:29:55', '系统后台');
+INSERT INTO `sys_login_log` VALUES (753, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-21 15:58:22', '系统后台');
+INSERT INTO `sys_login_log` VALUES (754, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-21 18:06:31', '系统后台');
+INSERT INTO `sys_login_log` VALUES (755, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-22 09:01:15', '系统后台');
+INSERT INTO `sys_login_log` VALUES (756, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-22 09:11:55', '系统后台');
+INSERT INTO `sys_login_log` VALUES (757, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-24 09:00:52', '系统后台');
+INSERT INTO `sys_login_log` VALUES (758, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-24 09:59:09', '系统后台');
+INSERT INTO `sys_login_log` VALUES (759, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-24 14:45:09', '系统后台');
+INSERT INTO `sys_login_log` VALUES (760, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-24 14:47:54', '系统后台');
+INSERT INTO `sys_login_log` VALUES (761, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-24 14:48:20', '系统后台');
+INSERT INTO `sys_login_log` VALUES (762, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-24 14:52:37', '系统后台');
+INSERT INTO `sys_login_log` VALUES (763, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-24 15:02:19', '系统后台');
+INSERT INTO `sys_login_log` VALUES (764, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-24 15:02:36', '系统后台');
+INSERT INTO `sys_login_log` VALUES (765, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-24 15:05:42', '系统后台');
+INSERT INTO `sys_login_log` VALUES (766, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-24 17:06:28', '系统后台');
+INSERT INTO `sys_login_log` VALUES (767, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-24 17:09:39', '系统后台');
+INSERT INTO `sys_login_log` VALUES (768, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-25 15:08:31', '系统后台');
+INSERT INTO `sys_login_log` VALUES (769, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-25 15:11:56', '系统后台');
+INSERT INTO `sys_login_log` VALUES (770, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-25 15:12:13', '系统后台');
+INSERT INTO `sys_login_log` VALUES (771, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-25 16:06:30', '系统后台');
+INSERT INTO `sys_login_log` VALUES (772, 'demo2', '127.0.0.1', '内网IP', 'ApiPOST', '', 0, '账号密码错误', '2022-03-25 16:41:46', '系统后台');
+INSERT INTO `sys_login_log` VALUES (773, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-28 10:24:28', '系统后台');
+INSERT INTO `sys_login_log` VALUES (774, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-28 10:37:47', '系统后台');
+INSERT INTO `sys_login_log` VALUES (775, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-28 14:27:08', '系统后台');
+INSERT INTO `sys_login_log` VALUES (776, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-28 14:29:44', '系统后台');
+INSERT INTO `sys_login_log` VALUES (777, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-28 16:27:11', '系统后台');
+INSERT INTO `sys_login_log` VALUES (778, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-29 10:10:16', '系统后台');
+INSERT INTO `sys_login_log` VALUES (779, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-29 10:49:47', '系统后台');
+INSERT INTO `sys_login_log` VALUES (780, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-30 09:06:05', '系统后台');
+INSERT INTO `sys_login_log` VALUES (781, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-30 09:58:27', '系统后台');
+INSERT INTO `sys_login_log` VALUES (782, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-30 10:19:08', '系统后台');
+INSERT INTO `sys_login_log` VALUES (783, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-30 10:20:01', '系统后台');
+INSERT INTO `sys_login_log` VALUES (784, 'test', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-30 10:50:40', '系统后台');
+INSERT INTO `sys_login_log` VALUES (785, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-30 10:51:30', '系统后台');
+INSERT INTO `sys_login_log` VALUES (786, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-30 11:08:00', '系统后台');
+INSERT INTO `sys_login_log` VALUES (787, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-30 11:09:44', '系统后台');
+INSERT INTO `sys_login_log` VALUES (788, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-30 11:09:49', '系统后台');
+INSERT INTO `sys_login_log` VALUES (789, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-30 11:23:08', '系统后台');
+INSERT INTO `sys_login_log` VALUES (790, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-30 11:41:01', '系统后台');
+INSERT INTO `sys_login_log` VALUES (791, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-03-30 11:44:36', '系统后台');
+INSERT INTO `sys_login_log` VALUES (792, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-03-31 09:34:07', '系统后台');
+INSERT INTO `sys_login_log` VALUES (793, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-01 10:09:45', '系统后台');
+INSERT INTO `sys_login_log` VALUES (794, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-01 10:13:39', '系统后台');
+INSERT INTO `sys_login_log` VALUES (795, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-01 10:16:04', '系统后台');
+INSERT INTO `sys_login_log` VALUES (796, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-01 15:02:11', '系统后台');
+INSERT INTO `sys_login_log` VALUES (797, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-02 09:15:20', '系统后台');
+INSERT INTO `sys_login_log` VALUES (798, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-02 09:15:34', '系统后台');
+INSERT INTO `sys_login_log` VALUES (799, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-02 09:59:08', '系统后台');
+INSERT INTO `sys_login_log` VALUES (800, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-02 11:04:12', '系统后台');
+INSERT INTO `sys_login_log` VALUES (801, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-06 09:51:48', '系统后台');
+INSERT INTO `sys_login_log` VALUES (802, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-06 16:21:37', '系统后台');
+INSERT INTO `sys_login_log` VALUES (803, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-06 17:40:57', '系统后台');
+INSERT INTO `sys_login_log` VALUES (804, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-07 09:34:50', '系统后台');
+INSERT INTO `sys_login_log` VALUES (805, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-07 15:17:03', '系统后台');
+INSERT INTO `sys_login_log` VALUES (806, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-07 15:58:53', '系统后台');
+INSERT INTO `sys_login_log` VALUES (807, 'demo', '::1', '安徽省 合肥市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-07 22:13:22', '系统后台');
+INSERT INTO `sys_login_log` VALUES (808, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-08 09:26:14', '系统后台');
+INSERT INTO `sys_login_log` VALUES (809, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-08 12:03:47', '系统后台');
+INSERT INTO `sys_login_log` VALUES (810, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-08 14:17:47', '系统后台');
+INSERT INTO `sys_login_log` VALUES (811, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-08 14:24:23', '系统后台');
+INSERT INTO `sys_login_log` VALUES (812, 'demo', '::1', '安徽省 合肥市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-09 12:58:53', '系统后台');
+INSERT INTO `sys_login_log` VALUES (813, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-11 09:01:47', '系统后台');
+INSERT INTO `sys_login_log` VALUES (814, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-11 09:13:10', '系统后台');
+INSERT INTO `sys_login_log` VALUES (815, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-11 09:36:58', '系统后台');
+INSERT INTO `sys_login_log` VALUES (816, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-11 16:42:45', '系统后台');
+INSERT INTO `sys_login_log` VALUES (817, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-12 08:59:10', '系统后台');
+INSERT INTO `sys_login_log` VALUES (818, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-12 09:11:59', '系统后台');
+INSERT INTO `sys_login_log` VALUES (819, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-12 14:20:39', '系统后台');
+INSERT INTO `sys_login_log` VALUES (820, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-12 16:13:56', '系统后台');
+INSERT INTO `sys_login_log` VALUES (821, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-13 09:30:32', '系统后台');
+INSERT INTO `sys_login_log` VALUES (822, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-13 11:51:43', '系统后台');
+INSERT INTO `sys_login_log` VALUES (823, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-13 15:00:37', '系统后台');
+INSERT INTO `sys_login_log` VALUES (824, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-13 15:07:04', '系统后台');
+INSERT INTO `sys_login_log` VALUES (825, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-14 11:38:33', '系统后台');
+INSERT INTO `sys_login_log` VALUES (826, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-14 15:08:12', '系统后台');
+INSERT INTO `sys_login_log` VALUES (827, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-14 15:09:03', '系统后台');
+INSERT INTO `sys_login_log` VALUES (828, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-14 15:11:46', '系统后台');
+INSERT INTO `sys_login_log` VALUES (829, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-14 15:40:42', '系统后台');
+INSERT INTO `sys_login_log` VALUES (830, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-14 15:41:48', '系统后台');
+INSERT INTO `sys_login_log` VALUES (831, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-14 15:46:52', '系统后台');
+INSERT INTO `sys_login_log` VALUES (832, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-14 15:48:41', '系统后台');
+INSERT INTO `sys_login_log` VALUES (833, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-14 17:50:00', '系统后台');
+INSERT INTO `sys_login_log` VALUES (834, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-14 18:08:01', '系统后台');
+INSERT INTO `sys_login_log` VALUES (835, 'demo', '::1', '安徽省 合肥市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-14 21:10:21', '系统后台');
+INSERT INTO `sys_login_log` VALUES (836, 'demo', '::1', '安徽省 合肥市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-16 10:07:14', '系统后台');
+INSERT INTO `sys_login_log` VALUES (837, 'demo', '::1', '安徽省 合肥市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-16 10:48:15', '系统后台');
+INSERT INTO `sys_login_log` VALUES (838, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-16 11:15:08', '系统后台');
+INSERT INTO `sys_login_log` VALUES (839, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-16 11:15:16', '系统后台');
+INSERT INTO `sys_login_log` VALUES (840, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-16 11:15:18', '系统后台');
+INSERT INTO `sys_login_log` VALUES (841, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-16 11:15:20', '系统后台');
+INSERT INTO `sys_login_log` VALUES (842, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-16 15:59:10', '系统后台');
+INSERT INTO `sys_login_log` VALUES (843, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-16 15:59:12', '系统后台');
+INSERT INTO `sys_login_log` VALUES (844, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-16 15:59:14', '系统后台');
+INSERT INTO `sys_login_log` VALUES (845, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-16 15:59:15', '系统后台');
+INSERT INTO `sys_login_log` VALUES (846, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-16 15:59:16', '系统后台');
+INSERT INTO `sys_login_log` VALUES (847, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-16 15:59:17', '系统后台');
+INSERT INTO `sys_login_log` VALUES (848, 'demo', '::1', '安徽省 合肥市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-16 16:11:58', '系统后台');
+INSERT INTO `sys_login_log` VALUES (849, 'demo', '::1', '安徽省 合肥市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-16 17:01:43', '系统后台');
+INSERT INTO `sys_login_log` VALUES (850, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-18 10:33:28', '系统后台');
+INSERT INTO `sys_login_log` VALUES (851, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-18 10:45:05', '系统后台');
+INSERT INTO `sys_login_log` VALUES (852, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-18 16:27:06', '系统后台');
+INSERT INTO `sys_login_log` VALUES (853, 'demo', '::1', '安徽省 合肥市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-18 20:59:19', '系统后台');
+INSERT INTO `sys_login_log` VALUES (854, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-18 22:18:35', '系统后台');
+INSERT INTO `sys_login_log` VALUES (855, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-19 08:49:39', '系统后台');
+INSERT INTO `sys_login_log` VALUES (856, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-19 08:55:49', '系统后台');
+INSERT INTO `sys_login_log` VALUES (857, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-19 08:57:07', '系统后台');
+INSERT INTO `sys_login_log` VALUES (858, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-19 09:50:28', '系统后台');
+INSERT INTO `sys_login_log` VALUES (859, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-19 09:51:06', '系统后台');
+INSERT INTO `sys_login_log` VALUES (860, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-19 09:51:07', '系统后台');
+INSERT INTO `sys_login_log` VALUES (861, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-19 09:51:29', '系统后台');
+INSERT INTO `sys_login_log` VALUES (862, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-19 09:51:30', '系统后台');
+INSERT INTO `sys_login_log` VALUES (863, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-19 09:51:30', '系统后台');
+INSERT INTO `sys_login_log` VALUES (864, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-19 09:51:31', '系统后台');
+INSERT INTO `sys_login_log` VALUES (865, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-19 09:51:32', '系统后台');
+INSERT INTO `sys_login_log` VALUES (866, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-19 09:51:32', '系统后台');
+INSERT INTO `sys_login_log` VALUES (867, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-19 11:08:39', '系统后台');
+INSERT INTO `sys_login_log` VALUES (868, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-19 11:50:30', '系统后台');
+INSERT INTO `sys_login_log` VALUES (869, 'demo', '127.0.0.1', '内网IP', 'Firefox', 'Windows 10', 1, '登录成功', '2022-04-19 15:07:34', '系统后台');
+INSERT INTO `sys_login_log` VALUES (870, 'admin', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-19 16:38:37', '系统后台');
+INSERT INTO `sys_login_log` VALUES (871, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-19 17:29:59', '系统后台');
+INSERT INTO `sys_login_log` VALUES (872, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-20 08:42:41', '系统后台');
+INSERT INTO `sys_login_log` VALUES (873, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-20 09:51:36', '系统后台');
+INSERT INTO `sys_login_log` VALUES (874, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-20 10:41:01', '系统后台');
+INSERT INTO `sys_login_log` VALUES (875, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-20 10:50:15', '系统后台');
+INSERT INTO `sys_login_log` VALUES (876, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-20 10:50:19', '系统后台');
+INSERT INTO `sys_login_log` VALUES (877, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-20 10:50:59', '系统后台');
+INSERT INTO `sys_login_log` VALUES (878, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-20 14:38:28', '系统后台');
+INSERT INTO `sys_login_log` VALUES (879, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-20 16:26:04', '系统后台');
+INSERT INTO `sys_login_log` VALUES (880, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-20 16:27:13', '系统后台');
+INSERT INTO `sys_login_log` VALUES (881, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-21 08:31:03', '系统后台');
+INSERT INTO `sys_login_log` VALUES (882, 'demo', '::1', '云南省 曲靖市', 'Chrome', 'Windows 10', 1, '登录成功', '2022-04-21 09:22:27', '系统后台');
+INSERT INTO `sys_login_log` VALUES (883, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-21 17:17:35', '系统后台');
+INSERT INTO `sys_login_log` VALUES (884, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-21 17:27:48', '系统后台');
+INSERT INTO `sys_login_log` VALUES (885, 'demo', '127.0.0.1', '内网IP', 'ApiPOST', '', 1, '登录成功', '2022-04-21 17:28:09', '系统后台');
+
+-- ----------------------------
+-- Table structure for sys_oper_log
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_oper_log`;
+CREATE TABLE `sys_oper_log` (
+ `oper_id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '日志主键',
+ `title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '模块标题',
+ `business_type` int(2) NULL DEFAULT 0 COMMENT '业务类型(0其它 1新增 2修改 3删除)',
+ `method` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '方法名称',
+ `request_method` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '请求方式',
+ `operator_type` int(1) NULL DEFAULT 0 COMMENT '操作类别(0其它 1后台用户 2手机端用户)',
+ `oper_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '操作人员',
+ `dept_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '部门名称',
+ `oper_url` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '请求URL',
+ `oper_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '主机地址',
+ `oper_location` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '操作地点',
+ `oper_param` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '请求参数',
+ `json_result` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '返回参数',
+ `status` int(1) NULL DEFAULT 0 COMMENT '操作状态(0正常 1异常)',
+ `error_msg` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '错误消息',
+ `oper_time` datetime(0) NULL DEFAULT NULL COMMENT '操作时间',
+ PRIMARY KEY (`oper_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '操作日志记录' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for sys_post
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_post`;
+CREATE TABLE `sys_post` (
+ `post_id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '岗位ID',
+ `post_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '岗位编码',
+ `post_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '岗位名称',
+ `post_sort` int(4) NOT NULL COMMENT '显示顺序',
+ `status` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '状态(0正常 1停用)',
+ `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+ `created_by` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建人',
+ `updated_by` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT '修改人',
+ `created_at` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+ `updated_at` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
+ `deleted_at` datetime(0) NULL DEFAULT NULL COMMENT '删除时间',
+ PRIMARY KEY (`post_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '岗位信息表' ROW_FORMAT = Compact;
+
+-- ----------------------------
+-- Records of sys_post
+-- ----------------------------
+INSERT INTO `sys_post` VALUES (1, 'ceo', '董事长', 1, 1, '', 0, 0, '2021-07-11 11:32:58', NULL, NULL);
+INSERT INTO `sys_post` VALUES (2, 'se', '项目经理', 2, 1, '', 0, 0, '2021-07-12 11:01:26', NULL, NULL);
+INSERT INTO `sys_post` VALUES (3, 'hr', '人力资源', 3, 1, '', 0, 0, '2021-07-12 11:01:30', NULL, NULL);
+INSERT INTO `sys_post` VALUES (4, 'user', '普通员工', 4, 0, '普通员工', 0, 31, '2021-07-12 11:01:33', '2022-04-08 15:32:23', NULL);
+INSERT INTO `sys_post` VALUES (5, 'it', 'IT部', 5, 1, '信息部', 31, 31, '2021-07-12 11:09:42', '2022-04-09 12:59:12', NULL);
+INSERT INTO `sys_post` VALUES (6, '1111', '1111', 0, 1, '11111', 31, 0, '2022-04-08 15:32:44', '2022-04-08 15:32:44', '2022-04-08 15:51:24');
+INSERT INTO `sys_post` VALUES (7, '222', '2222', 0, 1, '22222', 31, 0, '2022-04-08 15:32:55', '2022-04-08 15:32:55', '2022-04-08 15:51:24');
+INSERT INTO `sys_post` VALUES (8, '33333', '3333', 0, 0, '33333', 31, 0, '2022-04-08 15:33:01', '2022-04-08 15:33:01', '2022-04-08 15:51:40');
+INSERT INTO `sys_post` VALUES (9, '222', '111', 0, 1, '2313213', 31, 0, '2022-04-08 15:52:53', '2022-04-08 15:52:53', '2022-04-08 15:52:56');
+
+-- ----------------------------
+-- Table structure for sys_role
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_role`;
+CREATE TABLE `sys_role` (
+ `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `status` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 COMMENT '状态;0:禁用;1:正常',
+ `list_order` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '排序',
+ `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '角色名称',
+ `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注',
+ `data_scope` tinyint(3) UNSIGNED NOT NULL DEFAULT 3 COMMENT '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)',
+ `created_at` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+ `updated_at` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `status`(`status`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '角色表' ROW_FORMAT = Compact;
+
+-- ----------------------------
+-- Records of sys_role
+-- ----------------------------
+INSERT INTO `sys_role` VALUES (1, 1, 0, '超级管理员', '备注', 3, '2022-04-01 11:38:39', '2022-04-09 12:59:28');
+INSERT INTO `sys_role` VALUES (2, 1, 0, '普通管理员', '备注', 3, '2022-04-01 11:38:39', '2022-04-01 11:38:39');
+INSERT INTO `sys_role` VALUES (3, 1, 0, '站点管理员', '站点管理人员', 3, '2022-04-01 11:38:39', '2022-04-01 11:38:39');
+INSERT INTO `sys_role` VALUES (4, 1, 0, '初级管理员', '初级管理员', 3, '2022-04-01 11:38:39', '2022-04-01 11:38:39');
+INSERT INTO `sys_role` VALUES (5, 1, 0, '高级管理员', '高级管理员', 2, '2022-04-01 11:38:39', '2022-04-01 11:38:39');
+INSERT INTO `sys_role` VALUES (8, 1, 0, '区级管理员', '', 2, '2022-04-01 11:38:39', '2022-04-06 09:53:40');
+
+-- ----------------------------
+-- Table structure for sys_role_dept
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_role_dept`;
+CREATE TABLE `sys_role_dept` (
+ `role_id` bigint(20) NOT NULL COMMENT '角色ID',
+ `dept_id` bigint(20) NOT NULL COMMENT '部门ID',
+ PRIMARY KEY (`role_id`, `dept_id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '角色和部门关联表' ROW_FORMAT = Compact;
+
+-- ----------------------------
+-- Records of sys_role_dept
+-- ----------------------------
+INSERT INTO `sys_role_dept` VALUES (5, 103);
+INSERT INTO `sys_role_dept` VALUES (5, 104);
+INSERT INTO `sys_role_dept` VALUES (5, 105);
+INSERT INTO `sys_role_dept` VALUES (8, 105);
+INSERT INTO `sys_role_dept` VALUES (8, 106);
+
+-- ----------------------------
+-- Table structure for sys_user
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_user`;
+CREATE TABLE `sys_user` (
+ `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `user_name` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '用户名',
+ `mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '中国手机不带国家代码,国际手机号格式为:国家代码-手机号',
+ `user_nickname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '用户昵称',
+ `birthday` int(11) NOT NULL DEFAULT 0 COMMENT '生日',
+ `user_password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '登录密码;cmf_password加密',
+ `user_salt` char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '加密盐',
+ `user_status` tinyint(3) UNSIGNED NOT NULL DEFAULT 1 COMMENT '用户状态;0:禁用,1:正常,2:未验证',
+ `user_email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户登录邮箱',
+ `sex` tinyint(2) NOT NULL DEFAULT 0 COMMENT '性别;0:保密,1:男,2:女',
+ `avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户头像',
+ `dept_id` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT '部门id',
+ `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '备注',
+ `is_admin` tinyint(4) NOT NULL DEFAULT 1 COMMENT '是否后台管理员 1 是 0 否',
+ `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '联系地址',
+ `describe` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT ' 描述信息',
+ `last_login_ip` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '最后登录ip',
+ `last_login_time` datetime(0) NULL DEFAULT NULL COMMENT '最后登录时间',
+ `created_at` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+ `updated_at` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
+ `deleted_at` datetime(0) NULL DEFAULT NULL COMMENT '删除时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `user_login`(`user_name`, `deleted_at`) USING BTREE,
+ UNIQUE INDEX `mobile`(`mobile`, `deleted_at`) USING BTREE,
+ INDEX `user_nickname`(`user_nickname`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 43 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = Compact;
+
+-- ----------------------------
+-- Records of sys_user
+-- ----------------------------
+INSERT INTO `sys_user` VALUES (1, 'admin', '13578342363', '超级管理员', 0, 'c567ae329f9929b518759d3bea13f492', 'f9aZTAa8yz', 1, 'yxh669@qq.com', 1, 'https://yxh-1301841944.cos.ap-chongqing.myqcloud.com/gfast/2021-07-19/ccwpeuqz1i2s769hua.jpeg', 101, '', 1, 'asdasfdsaf大发放打发士大夫发按时', '描述信息', '::1', '2022-04-19 16:38:37', '2021-06-22 17:58:00', '2022-04-19 16:38:37', NULL);
+INSERT INTO `sys_user` VALUES (2, 'yixiaohu', '13699885599', '奈斯', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, 'yxh@qq.com', 1, 'pub_upload/2020-11-02/c6sntzg7r96c7p9gqf.jpeg', 102, '备注', 1, '', '', '[::1]', '2022-02-14 18:10:40', '2021-06-22 17:58:00', '2022-04-13 11:20:03', NULL);
+INSERT INTO `sys_user` VALUES (3, 'zs', '16399669855', '张三', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, 'zs@qq.com', 0, 'https://yxh-1301841944.cos.ap-chongqing.myqcloud.com/gfast/2021-08-02/cd8nif79egjg9kbkgk.jpeg', 101, '', 1, '', '', '127.0.0.1', '2022-03-18 15:22:13', '2021-06-22 17:58:00', '2022-04-21 11:20:06', NULL);
+INSERT INTO `sys_user` VALUES (4, 'qlgl', '13758596696', '测试c', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, 'qlgl@qq.com', 0, '', 102, '', 1, '', '', '127.0.0.1', NULL, '2021-06-22 17:58:00', '2022-04-12 17:55:28', NULL);
+INSERT INTO `sys_user` VALUES (5, 'test', '13845696696', '测试2', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, '123@qq.com', 0, '', 101, '', 0, '', '', '::1', '2022-03-30 10:50:39', '2021-06-22 17:58:00', '2022-04-12 17:55:31', NULL);
+INSERT INTO `sys_user` VALUES (6, '18999998889', '13755866654', '刘大大', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, '1223@qq.com', 0, '', 103, '', 1, '', '', '[::1]', '2022-02-25 14:29:22', '2021-06-22 17:58:00', '2022-04-14 21:11:06', NULL);
+INSERT INTO `sys_user` VALUES (7, 'zmm', '13788566696', '张明明', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, '11123@qq.com', 0, '', 104, '', 1, '', '', '127.0.0.1', NULL, '2021-06-22 17:58:00', '2022-04-12 17:55:42', NULL);
+INSERT INTO `sys_user` VALUES (8, 'lxx', '13756566696', '李小小', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, '123333@qq.com', 0, '', 101, '', 1, '', '', '127.0.0.1', NULL, '2021-06-22 17:58:00', '2022-04-12 17:55:45', NULL);
+INSERT INTO `sys_user` VALUES (10, 'xmm', '13588999969', '小秘密', 0, '2de2a8df703bfc634cfda2cb2f6a59be', 'Frz7LJY7SE', 1, '696@qq.com', 0, '', 101, '', 1, '', '', '[::1]', '2021-07-22 17:08:53', '2021-06-22 17:58:00', '2022-04-12 17:55:50', NULL);
+INSERT INTO `sys_user` VALUES (14, 'cd_19', '13699888899', '看金利科技', 0, '1169d5fe4119fd4277a95f02d7036171', '7paigEoedh', 1, '', 0, '', 102, '', 1, '', '', '', NULL, '2021-06-22 17:58:00', '2022-04-12 18:13:22', NULL);
+INSERT INTO `sys_user` VALUES (15, 'lmm', '13587754545', '刘敏敏', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, 'a@coc.com', 0, '', 201, '', 1, '', '', '127.0.0.1', NULL, '2021-06-22 17:58:00', '2022-04-12 17:56:23', NULL);
+INSERT INTO `sys_user` VALUES (16, 'ldn', '13899658874', '李大牛', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, 'a@ll.con', 0, '', 102, '', 1, '', '', '127.0.0.1', NULL, '2021-06-22 17:58:00', '2022-04-12 17:56:27', NULL);
+INSERT INTO `sys_user` VALUES (20, 'dbc', '13877555566', '大百词', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, '', 0, '', 0, '', 1, '', '', '', NULL, '2021-06-22 17:58:00', '2021-06-22 17:58:00', NULL);
+INSERT INTO `sys_user` VALUES (22, 'yxfmlbb', '15969423326', '大数据部门测试', 0, '66f89b40ee4a10aabaf70c15756429ea', 'mvd2OtUe8f', 1, 'yxh6691@qq.com', 0, 'https://yxh-1301841944.cos.ap-chongqing.myqcloud.com/gfast/2021-09-29/cem20k3fdciosy7nwo.jpeg', 200, '', 1, '2222233', '1222', '[::1]', '2021-10-28 11:36:07', '2021-06-22 17:58:00', '2021-06-22 17:58:00', NULL);
+INSERT INTO `sys_user` VALUES (23, 'wangming', '13699888855', '王明', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, '', 0, '', 0, '', 1, '', '', '', NULL, '2021-06-22 17:58:00', '2021-06-22 17:58:00', NULL);
+INSERT INTO `sys_user` VALUES (24, 'zhk', '13699885591', '综合科', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, '', 0, '', 0, '', 1, '', '', '192.168.0.146', NULL, '2021-06-22 17:58:00', '2021-06-22 17:58:00', NULL);
+INSERT INTO `sys_user` VALUES (28, 'demo3', '18699888855', '测试账号1', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, '123132@qq.com', 0, '', 109, '', 1, '', '', '192.168.0.229', NULL, '2021-06-22 17:58:00', '2021-06-22 17:58:00', NULL);
+INSERT INTO `sys_user` VALUES (31, 'demo', '15334455789', '李四', 0, '39978de67915a11e94bfe9c879b2d9a1', 'gqwLs4n95E', 1, '223@qq.com', 2, 'https://yxh-1301841944.cos.ap-chongqing.myqcloud.com/gfast/2021-11-30/cg30rab8myj85vjzcf.jpeg', 109, '', 1, '云南省曲靖市22223', '12345', '127.0.0.1', '2022-04-21 17:28:09', '2021-06-22 17:58:00', '2022-04-21 17:28:09', NULL);
+INSERT INTO `sys_user` VALUES (32, 'demo100', '18699888859', '测试账号1', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, '', 0, '', 0, '', 1, '', '', '[::1]', '2021-11-24 18:01:21', '2021-06-22 17:58:00', '2021-06-22 17:58:00', NULL);
+INSERT INTO `sys_user` VALUES (33, 'demo110', '18699888853', '测试账号1', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, '', 0, '', 0, '', 1, '', '', '', NULL, '2021-06-22 17:58:00', '2021-06-22 17:58:00', NULL);
+INSERT INTO `sys_user` VALUES (34, 'yxfmlbb2', '15969423327', '研发部门测试', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, '1111@qqq.com', 1, '', 103, '', 0, '', '', '127.0.0.1', NULL, '2021-06-22 17:58:00', '2021-06-22 17:58:00', NULL);
+INSERT INTO `sys_user` VALUES (35, 'wk666', '18888888888', 'wk', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, '396861557@qq.com', 1, '', 100, '', 1, '', '', '[::1]', '2021-12-09 14:52:37', '2021-06-22 17:58:00', '2021-06-22 17:58:00', NULL);
+INSERT INTO `sys_user` VALUES (36, 'zxd', '13699885565', '张晓东', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, 'zxk@qq.com', 1, '', 201, '666', 1, '', '', '', NULL, '2021-06-22 17:58:00', '2021-06-22 17:58:00', NULL);
+INSERT INTO `sys_user` VALUES (37, 'yxfmlbb3', '13513513511', '张三', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, '111@qq.com', 0, '', 204, '', 1, '', '', '[::1]', '2021-07-26 14:49:25', '2021-06-22 17:58:00', '2021-07-26 14:49:18', NULL);
+INSERT INTO `sys_user` VALUES (38, 'test_user', '18888888880', 'test', 0, '542a6e44dbac171f260fc4a032cd5522', 'dlqVVBTADg', 1, '11@qq.com', 1, '', 200, '111', 0, '', '', '', NULL, '2021-06-22 17:58:00', '2021-07-12 22:05:29', NULL);
+INSERT INTO `sys_user` VALUES (39, 'asan', '18687460555', '阿三', 0, '2354837137115700e2adf870ac113dcf', 'drdDvbtYZW', 1, '456654@qq.com', 1, '', 201, '666666', 1, '', '', '', NULL, '2021-07-12 17:21:43', '2021-07-12 21:13:31', '2021-07-12 22:00:44');
+INSERT INTO `sys_user` VALUES (40, 'asi', '13655888888', '啊四', 0, 'fbb755b35d48759dad47bb1540249fd1', '9dfUstcxrz', 1, '5464@qq.com', 1, '', 201, 'adsaasd', 1, '', '', '', '0000-00-00 00:00:00', '2021-07-12 17:46:27', '2021-07-12 21:29:41', '2021-07-12 22:00:44');
+INSERT INTO `sys_user` VALUES (41, 'awu', '13578556546', '阿五', 0, '3b36a96afa0dfd66aa915e0816e0e9f6', '9gHRa9ho4U', 0, '132321@qq.com', 1, '', 201, 'asdasdasd', 1, '', '', '', NULL, '2021-07-12 17:54:31', '2021-07-12 21:46:34', '2021-07-12 21:59:56');
+INSERT INTO `sys_user` VALUES (42, 'demo01', '13699888556', '测试01222', 0, '048dc94116558fb40920f3553ecd5fe8', 'KiVrfzKJQx', 1, '456@qq.com', 2, '', 109, '测试用户', 1, '', '', '', NULL, '2022-04-12 16:15:23', '2022-04-12 17:54:49', NULL);
+
+-- ----------------------------
+-- Table structure for sys_user_online
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_user_online`;
+CREATE TABLE `sys_user_online` (
+ `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `uuid` char(32) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL DEFAULT '' COMMENT '用户标识',
+ `token` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL DEFAULT '' COMMENT '用户token',
+ `create_time` datetime(0) NULL DEFAULT NULL COMMENT '登录时间',
+ `user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名',
+ `ip` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '登录ip',
+ `explorer` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '浏览器',
+ `os` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '操作系统',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uni_token`(`token`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 17387 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户在线状态表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for sys_user_post
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_user_post`;
+CREATE TABLE `sys_user_post` (
+ `user_id` bigint(20) NOT NULL COMMENT '用户ID',
+ `post_id` bigint(20) NOT NULL COMMENT '岗位ID',
+ PRIMARY KEY (`user_id`, `post_id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户与岗位关联表' ROW_FORMAT = Compact;
+
+-- ----------------------------
+-- Records of sys_user_post
+-- ----------------------------
+INSERT INTO `sys_user_post` VALUES (1, 2);
+INSERT INTO `sys_user_post` VALUES (1, 3);
+INSERT INTO `sys_user_post` VALUES (2, 1);
+INSERT INTO `sys_user_post` VALUES (2, 2);
+INSERT INTO `sys_user_post` VALUES (3, 2);
+INSERT INTO `sys_user_post` VALUES (5, 2);
+INSERT INTO `sys_user_post` VALUES (10, 1);
+INSERT INTO `sys_user_post` VALUES (10, 2);
+INSERT INTO `sys_user_post` VALUES (10, 3);
+INSERT INTO `sys_user_post` VALUES (10, 4);
+INSERT INTO `sys_user_post` VALUES (10, 5);
+INSERT INTO `sys_user_post` VALUES (14, 1);
+INSERT INTO `sys_user_post` VALUES (15, 4);
+INSERT INTO `sys_user_post` VALUES (16, 2);
+INSERT INTO `sys_user_post` VALUES (22, 1);
+INSERT INTO `sys_user_post` VALUES (22, 2);
+INSERT INTO `sys_user_post` VALUES (31, 2);
+INSERT INTO `sys_user_post` VALUES (34, 1);
+INSERT INTO `sys_user_post` VALUES (35, 2);
+INSERT INTO `sys_user_post` VALUES (35, 3);
+INSERT INTO `sys_user_post` VALUES (36, 1);
+INSERT INTO `sys_user_post` VALUES (37, 3);
+INSERT INTO `sys_user_post` VALUES (38, 2);
+INSERT INTO `sys_user_post` VALUES (38, 3);
+INSERT INTO `sys_user_post` VALUES (42, 2);
+INSERT INTO `sys_user_post` VALUES (42, 3);
+
+SET FOREIGN_KEY_CHECKS = 1;
diff --git a/resource/i18n/.gitkeep b/resource/i18n/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/resource/public/html/.gitkeep b/resource/public/html/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/resource/public/plugin/.gitkeep b/resource/public/plugin/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/resource/public/resource/css/.gitkeep b/resource/public/resource/css/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/resource/public/resource/demo.html b/resource/public/resource/demo.html
new file mode 100644
index 0000000..f336480
--- /dev/null
+++ b/resource/public/resource/demo.html
@@ -0,0 +1,10 @@
+
+
+
+
+ demo
+
+
+hello word
+
+
\ No newline at end of file
diff --git a/resource/public/resource/image/.gitkeep b/resource/public/resource/image/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/resource/public/resource/js/.gitkeep b/resource/public/resource/js/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/resource/scripts/.gitkeep b/resource/scripts/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/resource/template/.gitkeep b/resource/template/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/utility/.gitkeep b/utility/.gitkeep
new file mode 100644
index 0000000..e69de29