├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── config.yml ├── PULL_REQUEST_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE │ └── pr_cn.md └── workflows │ ├── build.yml │ ├── codeql-analysis.yml │ ├── go.yml │ ├── issue-check-inactive.yml │ ├── issue-close-require.yml │ ├── issue-labeled.yml │ └── mirror.yaml ├── .gitignore ├── Dockerfile ├── Dockerfilebak ├── LICENSE.md ├── Makefile ├── README.Zh-cn.md ├── README.md ├── _config.yml ├── app ├── admin │ ├── apis │ │ ├── captcha.go │ │ ├── go_admin.go │ │ ├── sys_api.go │ │ ├── sys_config.go │ │ ├── sys_dept.go │ │ ├── sys_dict_data.go │ │ ├── sys_dict_type.go │ │ ├── sys_login_log.go │ │ ├── sys_menu.go │ │ ├── sys_opera_log.go │ │ ├── sys_post.go │ │ ├── sys_role.go │ │ └── sys_user.go │ ├── models │ │ ├── casbin_rule.go │ │ ├── datascope.go │ │ ├── initdb.go │ │ ├── sys_api.go │ │ ├── sys_config.go │ │ ├── sys_dept.go │ │ ├── sys_dict_data.go │ │ ├── sys_dict_type.go │ │ ├── sys_login_log.go │ │ ├── sys_menu.go │ │ ├── sys_opera_log.go │ │ ├── sys_post.go │ │ ├── sys_role.go │ │ └── sys_user.go │ ├── router │ │ ├── init_router.go │ │ ├── router.go │ │ ├── sys_api.go │ │ ├── sys_config.go │ │ ├── sys_dept.go │ │ ├── sys_dict.go │ │ ├── sys_login_log.go │ │ ├── sys_menu.go │ │ ├── sys_opera_log.go │ │ ├── sys_post.go │ │ ├── sys_role.go │ │ ├── sys_router.go │ │ └── sys_user.go │ └── service │ │ ├── dto │ │ ├── sys_api.go │ │ ├── sys_config.go │ │ ├── sys_dept.go │ │ ├── sys_dict_data.go │ │ ├── sys_dict_type.go │ │ ├── sys_login_log.go │ │ ├── sys_menu.go │ │ ├── sys_opera_log.go │ │ ├── sys_post.go │ │ ├── sys_role.go │ │ └── sys_user.go │ │ ├── sys_api.go │ │ ├── sys_config.go │ │ ├── sys_dept.go │ │ ├── sys_dict_data.go │ │ ├── sys_dict_type.go │ │ ├── sys_login_log.go │ │ ├── sys_menu.go │ │ ├── sys_opera_log.go │ │ ├── sys_post.go │ │ ├── sys_role.go │ │ ├── sys_role_menu.go │ │ └── sys_user.go ├── jobs │ ├── apis │ │ └── sys_job.go │ ├── examples.go │ ├── jobbase.go │ ├── models │ │ └── sys_job.go │ ├── router │ │ ├── int_router.go │ │ ├── router.go │ │ └── sys_job.go │ ├── service │ │ ├── dto │ │ │ └── sys_job.go │ │ └── sys_job.go │ └── type.go └── other │ ├── apis │ ├── file.go │ ├── sys_server_monitor.go │ └── tools │ │ ├── db_columns.go │ │ ├── db_tables.go │ │ ├── gen.go │ │ └── sys_tables.go │ ├── models │ └── tools │ │ ├── db_columns.go │ │ ├── db_tables.go │ │ ├── sys_columns.go │ │ └── sys_tables.go │ ├── router │ ├── file.go │ ├── gen_router.go │ ├── init_router.go │ ├── monitor.go │ ├── router.go │ └── sys_server_monitor.go │ └── service │ └── dto │ └── sys_tables.go ├── cmd ├── api │ ├── jobs.go │ ├── other.go │ └── server.go ├── app │ └── server.go ├── cobra.go ├── config │ └── server.go ├── migrate │ ├── migration │ │ ├── init.go │ │ ├── models │ │ │ ├── by.go │ │ │ ├── casbin_rule.go │ │ │ ├── initdb.go │ │ │ ├── model.go │ │ │ ├── role_dept.go │ │ │ ├── sys_api.go │ │ │ ├── sys_columns.go │ │ │ ├── sys_config.go │ │ │ ├── sys_dept.go │ │ │ ├── sys_dict_data.go │ │ │ ├── sys_dict_type.go │ │ │ ├── sys_job.go │ │ │ ├── sys_login_log.go │ │ │ ├── sys_menu.go │ │ │ ├── sys_opera_log.go │ │ │ ├── sys_post.go │ │ │ ├── sys_role.go │ │ │ ├── sys_tables.go │ │ │ ├── sys_user.go │ │ │ └── tb_demo.go │ │ ├── version-local │ │ │ └── doc.go │ │ └── version │ │ │ ├── 1599190683659_tables.go │ │ │ └── 1653638869132_migrate.go │ └── server.go └── version │ └── server.go ├── common ├── actions │ ├── create.go │ ├── delete.go │ ├── index.go │ ├── permission.go │ ├── type.go │ ├── update.go │ └── view.go ├── apis │ └── api.go ├── database │ ├── initialize.go │ ├── open.go │ └── open_sqlite3.go ├── dto │ ├── auto_form.go │ ├── generate.go │ ├── order.go │ ├── pagination.go │ ├── search.go │ └── type.go ├── file_store │ ├── initialize.go │ ├── interface.go │ ├── kodo.go │ ├── kodo_test.go │ ├── obs.go │ ├── obs_test.go │ ├── oss.go │ └── oss_test.go ├── global │ ├── adm.go │ ├── casbin.go │ ├── logo.go │ └── topic.go ├── ip.go ├── middleware │ ├── auth.go │ ├── customerror.go │ ├── db.go │ ├── demo.go │ ├── handler │ │ ├── auth.go │ │ ├── httpshandler.go │ │ ├── login.go │ │ ├── ping.go │ │ ├── role.go │ │ └── user.go │ ├── header.go │ ├── init.go │ ├── logger.go │ ├── permission.go │ ├── request_id.go │ ├── sentinel.go │ ├── settings.go │ └── trace.go ├── models │ ├── by.go │ ├── menu.go │ ├── migrate.go │ ├── response.go │ ├── type.go │ └── user.go ├── response │ └── binding.go ├── service │ └── service.go └── storage │ └── initialize.go ├── config ├── READMEN.md ├── db-begin-mysql.sql ├── db-end-mysql.sql ├── db-sqlserver.sql ├── db.sql ├── extend.go ├── pg.sql ├── settings.demo.yml ├── settings.full.yml ├── settings.sqlite.yml └── settings.yml ├── docker-compose.yml ├── docs └── admin │ ├── admin_docs.go │ ├── admin_swagger.json │ └── admin_swagger.yaml ├── go-admin-db.db ├── go.mod ├── main.go ├── package-lock.json ├── restart.sh ├── scripts ├── Dockerfile └── k8s │ ├── deploy.yml │ ├── prerun.sh │ └── storage.yml ├── ssh └── swag.sh ├── static ├── form-generator │ ├── css │ │ ├── index.1a124643.css │ │ └── parser-example.69e16e51.css │ ├── img │ │ └── logo.e1bc3747.png │ ├── index.html │ ├── js │ │ ├── chunk-vendors.971555db.js │ │ ├── index.8e6d9f8f.js │ │ ├── parser-example.ce55fa09.js │ │ ├── preview.8ce4e0db.js │ │ └── tinymce-example.641995ab.js │ └── preview.html └── uploadfile │ ├── 77cfc1dd-535c-4e60-b34a-5909e2cf5ed0.jpg │ └── log.txt ├── stop.sh ├── template ├── api_migrate.template ├── cmd_api.template ├── migrate.template ├── router.template └── v4 │ ├── actions │ ├── router_check_role.go.template │ └── router_no_check_role.go.template │ ├── dto.go.template │ ├── js.go.template │ ├── model.go.template │ ├── no_actions │ ├── apis.go.template │ ├── router_check_role.go.template │ ├── router_no_check_role.go.template │ └── service.go.template │ └── vue.go.template └── test ├── api.go.template ├── gen_test.go └── model.go.template /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: 🆕 Create new issue 4 | url: http://new-issue.go-admin.dev 5 | about: The issue which is not created via http://new-issue.go-admin.dev will be closed immediately. 6 | - name: 🆕 创建一个新 Issue 7 | url: http://new-issue.go-admin.dev 8 | about: 不是用 http://new-issue.go-admin.dev 创建的 issue 会被机器人自动关闭。 9 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | [[中文版模板 / Chinese template](https://github.com/go-admin-team/go-admin/blob/master/.github/PULL_REQUEST_TEMPLATE/pr_cn.md)] 15 | 16 | ### 🤔 This is a ... 17 | 18 | - [ ] New feature 19 | - [ ] Bug fix 20 | - [ ] Site / documentation update 21 | - [ ] Demo update 22 | - [ ] Component style update 23 | - [ ] TypeScript definition update 24 | - [ ] Bundle size optimization 25 | - [ ] Performance optimization 26 | - [ ] Enhancement feature 27 | - [ ] Internationalization 28 | - [ ] Refactoring 29 | - [ ] Code style optimization 30 | - [ ] Test Case 31 | - [ ] Branch merge 32 | - [ ] Other (about what?) 33 | 34 | ### 🔗 Related issue link 35 | 36 | 39 | 40 | ### 💡 Background and solution 41 | 42 | 47 | 48 | ### 📝 Changelog 49 | 50 | 53 | 54 | | Language | Changelog | 55 | | ---------- | --------- | 56 | | 🇺🇸 English | | 57 | | 🇨🇳 Chinese | | 58 | 59 | ### ☑️ Self-Check before Merge 60 | 61 | ⚠️ Please check all items below before review. ⚠️ 62 | 63 | - [ ] Doc is updated/provided or not needed 64 | - [ ] Demo is updated/provided or not needed 65 | - [ ] TypeScript's definition is updated/provided or not needed 66 | - [ ] Changelog is provided or not needed 67 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/pr_cn.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | [[English Template / 英文模板](https://github.com/go-admin-team/go-admin/blob/master/.github/PULL_REQUEST_TEMPLATE.md)] 10 | 11 | ### 🤔 这个变动的性质是? 12 | 13 | - [ ] 新特性提交 14 | - [ ] 日常 bug 修复 15 | - [ ] 站点、文档改进 16 | - [ ] 演示代码改进 17 | - [ ] 组件样式/交互改进 18 | - [ ] TypeScript 定义更新 19 | - [ ] 包体积优化 20 | - [ ] 性能优化 21 | - [ ] 功能增强 22 | - [ ] 国际化改进 23 | - [ ] 重构 24 | - [ ] 代码风格优化 25 | - [ ] 测试用例 26 | - [ ] 分支合并 27 | - [ ] 其他改动(是关于什么的改动?) 28 | 29 | ### 🔗 相关 Issue 30 | 31 | 34 | 35 | ### 💡 需求背景和解决方案 36 | 37 | 42 | 43 | ### 📝 更新日志 44 | 45 | 48 | 49 | | 语言 | 更新描述 | 50 | | ------- | -------- | 51 | | 🇺🇸 英文 | | 52 | | 🇨🇳 中文 | | 53 | 54 | ### ☑️ 请求合并前的自查清单 55 | 56 | ⚠️ 请自检并全部**勾选全部选项**。⚠️ 57 | 58 | - [ ] 文档已补充或无须补充 59 | - [ ] 代码演示已提供或无须提供 60 | - [ ] TypeScript 定义已补充或无须补充 61 | - [ ] Changelog 已提供或无须提供 62 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | IMAGE_NAME: registry.ap-northeast-1.aliyuncs.com/go-admin/go-admin-api # 镜像名称 11 | TAG: ${{ github.sha }} 12 | IMAGE_NAME_TAG: registry.ap-northeast-1.aliyuncs.com/go-admin/go-admin-api:${{ github.sha }} 13 | 14 | jobs: 15 | 16 | build: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v3 20 | 21 | - name: Set up Go 22 | uses: actions/setup-go@v3 23 | with: 24 | go-version: 1.24 25 | 26 | - name: Tidy 27 | run: go mod tidy 28 | 29 | - name: Build 30 | run: env CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -tags "sqlite3,json1" --ldflags "-extldflags -static" -o main . 31 | 32 | - name: Build the Docker image and push 33 | run: | 34 | docker login --username=${{ secrets.DOCKER_USERNAME }} registry.ap-northeast-1.aliyuncs.com --password=${{ secrets.DOCKER_PASSWORD }} 35 | echo "************ docker login end" 36 | docker build -t go-admin-api:latest . 37 | echo "************ docker build end" 38 | docker tag go-admin-api ${{ env.IMAGE_NAME_TAG }} 39 | echo "************ docker tag end" 40 | docker images 41 | echo "************ docker images end" 42 | docker push ${{ env.IMAGE_NAME_TAG }} # 推送 43 | echo "************ docker push end" 44 | 45 | - name: Restart server # 第五步,重启服务 46 | uses: appleboy/ssh-action@master 47 | env: 48 | GITHUB_SHA_X: ${GITHUB_SHA} 49 | with: 50 | host: ${{ secrets.SSH_HOST }} # 下面三个配置与上一步类似 51 | username: ${{ secrets.SSH_USERNAME }} 52 | key: ${{ secrets.DEPLOY_KEY }} 53 | # 重启的脚本,根据自身情况做相应改动,一般要做的是migrate数据库以及重启服务器 54 | script: | 55 | sudo docker rm -f go-admin-api 56 | sudo docker login --username=${{ secrets.DOCKER_USERNAME }} registry.ap-northeast-1.aliyuncs.com --password=${{ secrets.DOCKER_PASSWORD }} 57 | sudo docker run -d -p 8000:8000 --name go-admin-api ${{ env.IMAGE_NAME_TAG }} 58 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | # The branches below must be a subset of the branches above 8 | branches: [ master ] 9 | 10 | jobs: 11 | analyze: 12 | name: Analyze 13 | runs-on: ubuntu-latest 14 | 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | language: [ 'go' ] 19 | 20 | steps: 21 | - name: Checkout repository 22 | uses: actions/checkout@v2 23 | 24 | # Initializes the CodeQL tools for scanning. 25 | - name: Initialize CodeQL 26 | uses: github/codeql-action/init@v1 27 | with: 28 | languages: ${{ matrix.language }} 29 | # If you wish to specify custom queries, you can do so here or in a config file. 30 | # By default, queries listed here will override any specified in a config file. 31 | # Prefix the list here with "+" to use these queries and those in the config file. 32 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 33 | 34 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 35 | # If this step fails, then you should remove it and run the build manually (see below) 36 | - name: Autobuild 37 | uses: github/codeql-action/autobuild@v1 38 | 39 | # ℹ️ Command-line programs to run using the OS shell. 40 | # 📚 https://git.io/JvXDl 41 | 42 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 43 | # and modify them (or add more) to build your code if your project 44 | # uses a compiled language 45 | 46 | #- run: | 47 | # make bootstrap 48 | # make release 49 | 50 | - name: Perform CodeQL Analysis 51 | uses: github/codeql-action/analyze@v1 52 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: [ master, dev ] 6 | pull_request: 7 | branches: [ master ] 8 | env: 9 | REGISTRY: ghcr.io 10 | IMAGE_NAME: ${{ github.repository }} 11 | 12 | jobs: 13 | 14 | build: 15 | name: Build 16 | runs-on: ubuntu-latest 17 | steps: 18 | 19 | - name: Set up Go 1.18 20 | uses: actions/setup-go@v3 21 | with: 22 | go-version: 1.18 23 | id: go 24 | 25 | - name: Check out code into the Go module directory 26 | uses: actions/checkout@v3 27 | 28 | - name: Get dependencies 29 | run: go mod tidy 30 | - name: Build 31 | run: make build 32 | 33 | - name: Log in to the Container registry 34 | uses: docker/login-action@v2 35 | if: startsWith(${{github.ref}}, 'refs/tags/') 36 | with: 37 | registry: ${{ env.REGISTRY }} 38 | username: ${{ github.actor }} 39 | password: ${{ secrets.GITHUB_TOKEN }} 40 | 41 | - name: Extract metadata (tags, labels) for Docker 42 | id: meta 43 | if: startsWith(${{github.ref}}, 'refs/tags/') 44 | uses: docker/metadata-action@v4 45 | with: 46 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} 47 | flavor: | 48 | latest=auto 49 | tags: | 50 | type=schedule 51 | type=ref,event=tag 52 | type=sha,prefix=,format=long,enable=true,priority=100 53 | 54 | - name: Build and push Docker image 55 | uses: docker/build-push-action@v3 56 | if: startsWith(${{github.ref}}, 'refs/tags/') 57 | with: 58 | context: . 59 | file: scripts/Dockerfile 60 | push: true 61 | tags: ${{ steps.meta.outputs.tags }} 62 | labels: ${{ steps.meta.outputs.labels }} 63 | -------------------------------------------------------------------------------- /.github/workflows/issue-check-inactive.yml: -------------------------------------------------------------------------------- 1 | name: Issue Check Inactive 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 */15 * *" 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | issue-check-inactive: 12 | permissions: 13 | issues: write # for actions-cool/issues-helper to update issues 14 | pull-requests: write # for actions-cool/issues-helper to update PRs 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: check-inactive 18 | uses: actions-cool/issues-helper@v3 19 | with: 20 | actions: 'check-inactive' 21 | inactive-label: 'Inactive' 22 | inactive-day: 30 23 | -------------------------------------------------------------------------------- /.github/workflows/issue-close-require.yml: -------------------------------------------------------------------------------- 1 | name: Issue Close Require 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * *" 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | issue-close-require: 12 | permissions: 13 | issues: write # for actions-cool/issues-helper to update issues 14 | pull-requests: write # for actions-cool/issues-helper to update PRs 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: need reproduce 18 | uses: actions-cool/issues-helper@v3 19 | with: 20 | actions: 'close-issues' 21 | labels: '🤔 Need Reproduce' 22 | inactive-day: 3 23 | 24 | - name: needs more info 25 | uses: actions-cool/issues-helper@v3 26 | with: 27 | actions: 'close-issues' 28 | labels: 'needs-more-info' 29 | inactive-day: 3 30 | body: | 31 | Since the issue was labeled with `needs-more-info`, but no response in 3 days. This issue will be closed. If you have any questions, you can comment and reply. 32 | 由于该 issue 被标记为需要更多信息,却 3 天未收到回应。现关闭 issue,若有任何问题,可评论回复。 33 | -------------------------------------------------------------------------------- /.github/workflows/mirror.yaml: -------------------------------------------------------------------------------- 1 | name: 'GitHub Actions Mirror' 2 | 3 | on: [push, delete] 4 | 5 | jobs: 6 | mirror_to_gitee: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: 'Checkout' 10 | uses: actions/checkout@v1 11 | - name: 'Mirror to gitee' 12 | uses: pixta-dev/repository-mirroring-action@v1 13 | with: 14 | target_repo_url: 15 | git@gitee.com:go-admin-team/go-admin.git 16 | ssh_private_key: 17 | ${{ secrets.GITEE_KEY }} 18 | mirror_to_gitlab: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: 'Checkout' 22 | uses: actions/checkout@v1 23 | - name: 'Mirror to gitlab' 24 | uses: pixta-dev/repository-mirroring-action@v1 25 | with: 26 | target_repo_url: 27 | git@gitlab.com:go-admin-team/go-admin.git 28 | ssh_private_key: 29 | ${{ secrets.GITLAB_KEY }} 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .vscode 3 | */.DS_Store 4 | static/uploadfile 5 | main.exe 6 | *.exe 7 | go-admin 8 | go-admin.exe 9 | temp/ 10 | !temp 11 | vendor 12 | config/settings.dev.yml 13 | config/settings.dev.*.yml 14 | config/settings.dev.*.yml.log 15 | temp/logs 16 | config/settings.dev.yml.log 17 | config/settings.b.dev.yml 18 | cmd/migrate/migration/version-local/* 19 | !cmd/migrate/migration/version-local/doc.go 20 | 21 | # go sum 22 | go.sum 23 | config/settings.deva.yml 24 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine 2 | 3 | # ENV GOPROXY https://goproxy.cn/ 4 | 5 | RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories 6 | 7 | RUN apk update --no-cache 8 | RUN apk add --update gcc g++ libc6-compat 9 | RUN apk add --no-cache ca-certificates 10 | RUN apk add --no-cache tzdata 11 | ENV TZ Asia/Shanghai 12 | 13 | COPY ./main /main 14 | COPY ./config/settings.demo.yml /config/settings.yml 15 | COPY ./go-admin-db.db /go-admin-db.db 16 | EXPOSE 8000 17 | RUN chmod +x /main 18 | CMD ["/main","server","-c", "/config/settings.yml"] -------------------------------------------------------------------------------- /Dockerfilebak: -------------------------------------------------------------------------------- 1 | FROM golang:alpine as builder 2 | 3 | MAINTAINER lwnmengjing 4 | 5 | ENV GOPROXY https://goproxy.cn/ 6 | 7 | WORKDIR /go/release 8 | #RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories 9 | RUN apk update && apk add tzdata 10 | 11 | COPY go.mod ./go.mod 12 | RUN go mod tidy 13 | COPY . . 14 | RUN pwd && ls 15 | 16 | RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -installsuffix cgo -o go-admin . 17 | 18 | FROM alpine 19 | 20 | COPY --from=builder /go/release/go-admin / 21 | 22 | COPY --from=builder /go/release/config/settings.yml /config/settings.yml 23 | 24 | COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 25 | 26 | EXPOSE 8000 27 | 28 | CMD ["/go-admin","server","-c", "/config/settings.yml"] -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 go-admin-team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROJECT:=go-admin 2 | 3 | .PHONY: build 4 | build: 5 | CGO_ENABLED=0 go build -ldflags="-w -s" -a -installsuffix "" -o go-admin . 6 | 7 | # make build-linux 8 | build-linux: 9 | @docker build -t go-admin:latest . 10 | @echo "build successful" 11 | 12 | build-sqlite: 13 | go build -tags sqlite3 -ldflags="-w -s" -a -installsuffix -o go-admin . 14 | 15 | # make run 16 | run: 17 | # delete go-admin-api container 18 | @if [ $(shell docker ps -aq --filter name=go-admin --filter publish=8000) ]; then docker rm -f go-admin; fi 19 | 20 | # 启动方法一 run go-admin-api container docker-compose 启动方式 21 | # 进入到项目根目录 执行 make run 命令 22 | @docker-compose up -d 23 | 24 | # 启动方式二 docker run 这里注意-v挂载的宿主机的地址改为部署时的实际决对路径 25 | #@docker run --name=go-admin -p 8000:8000 -v /home/code/go/src/go-admin/go-admin/config:/go-admin-api/config -v /home/code/go/src/go-admin/go-admin-api/static:/go-admin/static -v /home/code/go/src/go-admin/go-admin/temp:/go-admin-api/temp -d --restart=always go-admin:latest 26 | 27 | @echo "go-admin service is running..." 28 | 29 | # delete Tag= 的镜像 30 | @docker image prune -f 31 | @docker ps -a | grep "go-admin" 32 | 33 | stop: 34 | # delete go-admin-api container 35 | @if [ $(shell docker ps -aq --filter name=go-admin --filter publish=8000) ]; then docker-compose down; fi 36 | #@if [ $(shell docker ps -aq --filter name=go-admin --filter publish=8000) ]; then docker rm -f go-admin; fi 37 | #@echo "go-admin stop success" 38 | 39 | 40 | #.PHONY: test 41 | #test: 42 | # go test -v ./... -cover 43 | 44 | #.PHONY: docker 45 | #docker: 46 | # docker build . -t go-admin:latest 47 | 48 | # make deploy 49 | deploy: 50 | 51 | #@git checkout master 52 | #@git pull origin master 53 | make build-linux 54 | make run 55 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /app/admin/apis/captcha.go: -------------------------------------------------------------------------------- 1 | package apis 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/go-admin-team/go-admin-core/sdk/api" 6 | "github.com/go-admin-team/go-admin-core/sdk/pkg/captcha" 7 | ) 8 | 9 | type System struct { 10 | api.Api 11 | } 12 | 13 | // GenerateCaptchaHandler 获取验证码 14 | // @Summary 获取验证码 15 | // @Description 获取验证码 16 | // @Tags 登陆 17 | // @Success 200 {object} response.Response{data=string,id=string,msg=string} "{"code": 200, "data": [...]}" 18 | // @Router /api/v1/captcha [get] 19 | func (e System) GenerateCaptchaHandler(c *gin.Context) { 20 | if err := e.MakeContext(c).Errors; err != nil { 21 | e.Error(500, err, "服务初始化失败!") 22 | return 23 | } 24 | id, b64s, answer, err := captcha.DriverDigitFunc() 25 | if err != nil { 26 | e.Logger.Errorf("DriverDigitFunc error, %s", err.Error()) 27 | e.Error(500, err, "验证码获取失败") 28 | return 29 | } 30 | e.Logger.Infof("DriverDigitFunc answer: %s", answer) 31 | e.Custom(gin.H{ 32 | "code": 200, 33 | "data": b64s, 34 | "id": id, 35 | "msg": "success", 36 | }) 37 | } 38 | -------------------------------------------------------------------------------- /app/admin/apis/go_admin.go: -------------------------------------------------------------------------------- 1 | package apis 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | const INDEX = ` 8 | 9 | 10 | 11 | 12 | GO-ADMIN欢迎您 13 | 20 | 21 | 29 | 30 | 31 | 32 | 33 | 34 | ` 35 | 36 | func GoAdmin(c *gin.Context) { 37 | c.Header("Content-Type", "text/html; charset=utf-8") 38 | c.String(200, INDEX) 39 | } 40 | -------------------------------------------------------------------------------- /app/admin/models/casbin_rule.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type CasbinRule struct { 4 | ID uint `gorm:"primaryKey;autoIncrement"` 5 | Ptype string `gorm:"size:512;uniqueIndex:unique_index"` 6 | V0 string `gorm:"size:512;uniqueIndex:unique_index"` 7 | V1 string `gorm:"size:512;uniqueIndex:unique_index"` 8 | V2 string `gorm:"size:512;uniqueIndex:unique_index"` 9 | V3 string `gorm:"size:512;uniqueIndex:unique_index"` 10 | V4 string `gorm:"size:512;uniqueIndex:unique_index"` 11 | V5 string `gorm:"size:512;uniqueIndex:unique_index"` 12 | } 13 | 14 | func (CasbinRule) TableName() string { 15 | return "sys_casbin_rule" 16 | } 17 | -------------------------------------------------------------------------------- /app/admin/models/initdb.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "fmt" 5 | "go-admin/common/global" 6 | "gorm.io/gorm" 7 | "io/ioutil" 8 | "log" 9 | "strings" 10 | ) 11 | 12 | func InitDb(db *gorm.DB) (err error) { 13 | filePath := "config/db.sql" 14 | err = ExecSql(db, filePath) 15 | if global.Driver == "postgres" { 16 | filePath = "config/pg.sql" 17 | err = ExecSql(db, filePath) 18 | } 19 | return err 20 | } 21 | 22 | func ExecSql(db *gorm.DB, filePath string) error { 23 | sql, err := Ioutil(filePath) 24 | if err != nil { 25 | fmt.Println("数据库基础数据初始化脚本读取失败!原因:", err.Error()) 26 | return err 27 | } 28 | sqlList := strings.Split(sql, ";") 29 | for i := 0; i < len(sqlList)-1; i++ { 30 | if strings.Contains(sqlList[i], "--") { 31 | fmt.Println(sqlList[i]) 32 | continue 33 | } 34 | sql := strings.Replace(sqlList[i]+";", "\n", "", -1) 35 | sql = strings.TrimSpace(sql) 36 | if err = db.Exec(sql).Error; err != nil { 37 | log.Printf("error sql: %s", sql) 38 | if !strings.Contains(err.Error(), "Query was empty") { 39 | return err 40 | } 41 | } 42 | } 43 | return nil 44 | } 45 | 46 | func Ioutil(filePath string) (string, error) { 47 | if contents, err := ioutil.ReadFile(filePath); err == nil { 48 | //因为contents是[]byte类型,直接转换成string类型后会多一行空格,需要使用strings.Replace替换换行符 49 | result := strings.Replace(string(contents), "\n", "", 1) 50 | fmt.Println("Use ioutil.ReadFile to read a file:", result) 51 | return result, nil 52 | } else { 53 | return "", err 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/admin/models/sys_api.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "io/ioutil" 8 | "regexp" 9 | "strings" 10 | 11 | "github.com/bitly/go-simplejson" 12 | "github.com/go-admin-team/go-admin-core/sdk" 13 | "github.com/go-admin-team/go-admin-core/sdk/runtime" 14 | "github.com/go-admin-team/go-admin-core/storage" 15 | 16 | "go-admin/common/models" 17 | ) 18 | 19 | type SysApi struct { 20 | Id int `json:"id" gorm:"primaryKey;autoIncrement;comment:主键编码"` 21 | Handle string `json:"handle" gorm:"size:128;comment:handle"` 22 | Title string `json:"title" gorm:"size:128;comment:标题"` 23 | Path string `json:"path" gorm:"size:128;comment:地址"` 24 | Action string `json:"action" gorm:"size:16;comment:请求类型"` 25 | Type string `json:"type" gorm:"size:16;comment:接口类型"` 26 | models.ModelTime 27 | models.ControlBy 28 | } 29 | 30 | func (*SysApi) TableName() string { 31 | return "sys_api" 32 | } 33 | 34 | func (e *SysApi) Generate() models.ActiveRecord { 35 | o := *e 36 | return &o 37 | } 38 | 39 | func (e *SysApi) GetId() interface{} { 40 | return e.Id 41 | } 42 | 43 | func SaveSysApi(message storage.Messager) (err error) { 44 | var rb []byte 45 | rb, err = json.Marshal(message.GetValues()) 46 | if err != nil { 47 | err = fmt.Errorf("json Marshal error, %v", err.Error()) 48 | return err 49 | } 50 | 51 | var l runtime.Routers 52 | err = json.Unmarshal(rb, &l) 53 | if err != nil { 54 | err = fmt.Errorf("json Unmarshal error, %s", err.Error()) 55 | return err 56 | } 57 | dbList := sdk.Runtime.GetDb() 58 | for _, d := range dbList { 59 | for _, v := range l.List { 60 | if v.HttpMethod != "HEAD" || 61 | strings.Contains(v.RelativePath, "/swagger/") || 62 | strings.Contains(v.RelativePath, "/static/") || 63 | strings.Contains(v.RelativePath, "/form-generator/") || 64 | strings.Contains(v.RelativePath, "/sys/tables") { 65 | 66 | // 根据接口方法注释里的@Summary填充接口名称,适用于代码生成器 67 | // 可在此处增加配置路径前缀的if判断,只对代码生成的自建应用进行定向的接口名称填充 68 | jsonFile, _ := ioutil.ReadFile("docs/swagger.json") 69 | jsonData, _ := simplejson.NewFromReader(bytes.NewReader(jsonFile)) 70 | urlPath := v.RelativePath 71 | idPatten := "(.*)/:(\\w+)" // 正则替换,把:id换成{id} 72 | reg, _ := regexp.Compile(idPatten) 73 | if reg.MatchString(urlPath) { 74 | urlPath = reg.ReplaceAllString(v.RelativePath, "${1}/{${2}}") // 把:id换成{id} 75 | } 76 | apiTitle, _ := jsonData.Get("paths").Get(urlPath).Get(strings.ToLower(v.HttpMethod)).Get("summary").String() 77 | 78 | err := d.Debug().Where(SysApi{Path: v.RelativePath, Action: v.HttpMethod}). 79 | Attrs(SysApi{Handle: v.Handler, Title: apiTitle}). 80 | FirstOrCreate(&SysApi{}). 81 | //Update("handle", v.Handler). 82 | Error 83 | if err != nil { 84 | err := fmt.Errorf("Models SaveSysApi error: %s \r\n ", err.Error()) 85 | return err 86 | } 87 | } 88 | } 89 | } 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /app/admin/models/sys_config.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "go-admin/common/models" 5 | ) 6 | 7 | type SysConfig struct { 8 | models.Model 9 | ConfigName string `json:"configName" gorm:"size:128;comment:ConfigName"` // 10 | ConfigKey string `json:"configKey" gorm:"size:128;comment:ConfigKey"` // 11 | ConfigValue string `json:"configValue" gorm:"size:255;comment:ConfigValue"` // 12 | ConfigType string `json:"configType" gorm:"size:64;comment:ConfigType"` 13 | IsFrontend string `json:"isFrontend" gorm:"size:64;comment:是否前台"` // 14 | Remark string `json:"remark" gorm:"size:128;comment:Remark"` // 15 | models.ControlBy 16 | models.ModelTime 17 | } 18 | 19 | func (*SysConfig) TableName() string { 20 | return "sys_config" 21 | } 22 | 23 | func (e *SysConfig) Generate() models.ActiveRecord { 24 | o := *e 25 | return &o 26 | } 27 | 28 | func (e *SysConfig) GetId() interface{} { 29 | return e.Id 30 | } 31 | -------------------------------------------------------------------------------- /app/admin/models/sys_dept.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "go-admin/common/models" 4 | 5 | type SysDept struct { 6 | DeptId int `json:"deptId" gorm:"primaryKey;autoIncrement;"` //部门编码 7 | ParentId int `json:"parentId" gorm:""` //上级部门 8 | DeptPath string `json:"deptPath" gorm:"size:255;"` // 9 | DeptName string `json:"deptName" gorm:"size:128;"` //部门名称 10 | Sort int `json:"sort" gorm:"size:4;"` //排序 11 | Leader string `json:"leader" gorm:"size:128;"` //负责人 12 | Phone string `json:"phone" gorm:"size:11;"` //手机 13 | Email string `json:"email" gorm:"size:64;"` //邮箱 14 | Status int `json:"status" gorm:"size:4;"` //状态 15 | models.ControlBy 16 | models.ModelTime 17 | DataScope string `json:"dataScope" gorm:"-"` 18 | Params string `json:"params" gorm:"-"` 19 | Children []SysDept `json:"children" gorm:"-"` 20 | } 21 | 22 | func (*SysDept) TableName() string { 23 | return "sys_dept" 24 | } 25 | 26 | func (e *SysDept) Generate() models.ActiveRecord { 27 | o := *e 28 | return &o 29 | } 30 | 31 | func (e *SysDept) GetId() interface{} { 32 | return e.DeptId 33 | } 34 | -------------------------------------------------------------------------------- /app/admin/models/sys_dict_data.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "go-admin/common/models" 5 | ) 6 | 7 | type SysDictData struct { 8 | DictCode int `json:"dictCode" gorm:"primaryKey;column:dict_code;autoIncrement;comment:主键编码"` 9 | DictSort int `json:"dictSort" gorm:"size:20;comment:DictSort"` 10 | DictLabel string `json:"dictLabel" gorm:"size:128;comment:DictLabel"` 11 | DictValue string `json:"dictValue" gorm:"size:255;comment:DictValue"` 12 | DictType string `json:"dictType" gorm:"size:64;comment:DictType"` 13 | CssClass string `json:"cssClass" gorm:"size:128;comment:CssClass"` 14 | ListClass string `json:"listClass" gorm:"size:128;comment:ListClass"` 15 | IsDefault string `json:"isDefault" gorm:"size:8;comment:IsDefault"` 16 | Status int `json:"status" gorm:"size:4;comment:Status"` 17 | Default string `json:"default" gorm:"size:8;comment:Default"` 18 | Remark string `json:"remark" gorm:"size:255;comment:Remark"` 19 | models.ControlBy 20 | models.ModelTime 21 | } 22 | 23 | func (*SysDictData) TableName() string { 24 | return "sys_dict_data" 25 | } 26 | 27 | func (e *SysDictData) Generate() models.ActiveRecord { 28 | o := *e 29 | return &o 30 | } 31 | 32 | func (e *SysDictData) GetId() interface{} { 33 | return e.DictCode 34 | } 35 | -------------------------------------------------------------------------------- /app/admin/models/sys_dict_type.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "go-admin/common/models" 5 | ) 6 | 7 | type SysDictType struct { 8 | ID int `json:"id" gorm:"primaryKey;column:dict_id;autoIncrement;comment:主键编码"` 9 | DictName string `json:"dictName" gorm:"size:128;comment:DictName"` 10 | DictType string `json:"dictType" gorm:"size:128;comment:DictType"` 11 | Status int `json:"status" gorm:"size:4;comment:Status"` 12 | Remark string `json:"remark" gorm:"size:255;comment:Remark"` 13 | models.ControlBy 14 | models.ModelTime 15 | } 16 | 17 | func (*SysDictType) TableName() string { 18 | return "sys_dict_type" 19 | } 20 | 21 | func (e *SysDictType) Generate() models.ActiveRecord { 22 | o := *e 23 | return &o 24 | } 25 | 26 | func (e *SysDictType) GetId() interface{} { 27 | return e.ID 28 | } 29 | -------------------------------------------------------------------------------- /app/admin/models/sys_login_log.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "time" 7 | 8 | log "github.com/go-admin-team/go-admin-core/logger" 9 | "github.com/go-admin-team/go-admin-core/sdk" 10 | "github.com/go-admin-team/go-admin-core/storage" 11 | 12 | "go-admin/common/models" 13 | ) 14 | 15 | type SysLoginLog struct { 16 | models.Model 17 | Username string `json:"username" gorm:"size:128;comment:用户名"` 18 | Status string `json:"status" gorm:"size:4;comment:状态"` 19 | Ipaddr string `json:"ipaddr" gorm:"size:255;comment:ip地址"` 20 | LoginLocation string `json:"loginLocation" gorm:"size:255;comment:归属地"` 21 | Browser string `json:"browser" gorm:"size:255;comment:浏览器"` 22 | Os string `json:"os" gorm:"size:255;comment:系统"` 23 | Platform string `json:"platform" gorm:"size:255;comment:固件"` 24 | LoginTime time.Time `json:"loginTime" gorm:"comment:登录时间"` 25 | Remark string `json:"remark" gorm:"size:255;comment:备注"` 26 | Msg string `json:"msg" gorm:"size:255;comment:信息"` 27 | CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"` 28 | UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"` 29 | models.ControlBy 30 | } 31 | 32 | func (*SysLoginLog) TableName() string { 33 | return "sys_login_log" 34 | } 35 | 36 | func (e *SysLoginLog) Generate() models.ActiveRecord { 37 | o := *e 38 | return &o 39 | } 40 | 41 | func (e *SysLoginLog) GetId() interface{} { 42 | return e.Id 43 | } 44 | 45 | // SaveLoginLog 从队列中获取登录日志 46 | func SaveLoginLog(message storage.Messager) (err error) { 47 | //准备db 48 | db := sdk.Runtime.GetDbByKey(message.GetPrefix()) 49 | if db == nil { 50 | err = errors.New("db not exist") 51 | log.Errorf("host[%s]'s %s", message.GetPrefix(), err.Error()) 52 | return err 53 | } 54 | var rb []byte 55 | rb, err = json.Marshal(message.GetValues()) 56 | if err != nil { 57 | log.Errorf("json Marshal error, %s", err.Error()) 58 | return err 59 | } 60 | var l SysLoginLog 61 | err = json.Unmarshal(rb, &l) 62 | if err != nil { 63 | log.Errorf("json Unmarshal error, %s", err.Error()) 64 | return err 65 | } 66 | err = db.Create(&l).Error 67 | if err != nil { 68 | log.Errorf("db create error, %s", err.Error()) 69 | return err 70 | } 71 | return nil 72 | } 73 | -------------------------------------------------------------------------------- /app/admin/models/sys_menu.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "go-admin/common/models" 4 | 5 | type SysMenu struct { 6 | MenuId int `json:"menuId" gorm:"primaryKey;autoIncrement"` 7 | MenuName string `json:"menuName" gorm:"size:128;"` 8 | Title string `json:"title" gorm:"size:128;"` 9 | Icon string `json:"icon" gorm:"size:128;"` 10 | Path string `json:"path" gorm:"size:128;"` 11 | Paths string `json:"paths" gorm:"size:128;"` 12 | MenuType string `json:"menuType" gorm:"size:1;"` 13 | Action string `json:"action" gorm:"size:16;"` 14 | Permission string `json:"permission" gorm:"size:255;"` 15 | ParentId int `json:"parentId" gorm:"size:11;"` 16 | NoCache bool `json:"noCache" gorm:"size:8;"` 17 | Breadcrumb string `json:"breadcrumb" gorm:"size:255;"` 18 | Component string `json:"component" gorm:"size:255;"` 19 | Sort int `json:"sort" gorm:"size:4;"` 20 | Visible string `json:"visible" gorm:"size:1;"` 21 | IsFrame string `json:"isFrame" gorm:"size:1;DEFAULT:0;"` 22 | SysApi []SysApi `json:"sysApi" gorm:"many2many:sys_menu_api_rule"` 23 | Apis []int `json:"apis" gorm:"-"` 24 | DataScope string `json:"dataScope" gorm:"-"` 25 | Params string `json:"params" gorm:"-"` 26 | RoleId int `gorm:"-"` 27 | Children []SysMenu `json:"children,omitempty" gorm:"-"` 28 | IsSelect bool `json:"is_select" gorm:"-"` 29 | models.ControlBy 30 | models.ModelTime 31 | } 32 | 33 | type SysMenuSlice []SysMenu 34 | 35 | func (x SysMenuSlice) Len() int { return len(x) } 36 | func (x SysMenuSlice) Less(i, j int) bool { return x[i].Sort < x[j].Sort } 37 | func (x SysMenuSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 38 | 39 | func (*SysMenu) TableName() string { 40 | return "sys_menu" 41 | } 42 | 43 | func (e *SysMenu) Generate() models.ActiveRecord { 44 | o := *e 45 | return &o 46 | } 47 | 48 | func (e *SysMenu) GetId() interface{} { 49 | return e.MenuId 50 | } 51 | -------------------------------------------------------------------------------- /app/admin/models/sys_post.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "go-admin/common/models" 4 | 5 | type SysPost struct { 6 | PostId int `gorm:"primaryKey;autoIncrement" json:"postId"` //岗位编号 7 | PostName string `gorm:"size:128;" json:"postName"` //岗位名称 8 | PostCode string `gorm:"size:128;" json:"postCode"` //岗位代码 9 | Sort int `gorm:"size:4;" json:"sort"` //岗位排序 10 | Status int `gorm:"size:4;" json:"status"` //状态 11 | Remark string `gorm:"size:255;" json:"remark"` //描述 12 | models.ControlBy 13 | models.ModelTime 14 | 15 | DataScope string `gorm:"-" json:"dataScope"` 16 | Params string `gorm:"-" json:"params"` 17 | } 18 | 19 | func (*SysPost) TableName() string { 20 | return "sys_post" 21 | } 22 | 23 | func (e *SysPost) Generate() models.ActiveRecord { 24 | o := *e 25 | return &o 26 | } 27 | 28 | func (e *SysPost) GetId() interface{} { 29 | return e.PostId 30 | } 31 | -------------------------------------------------------------------------------- /app/admin/models/sys_role.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "go-admin/common/models" 4 | 5 | type SysRole struct { 6 | RoleId int `json:"roleId" gorm:"primaryKey;autoIncrement"` // 角色编码 7 | RoleName string `json:"roleName" gorm:"size:128;"` // 角色名称 8 | Status string `json:"status" gorm:"size:4;"` // 状态 1禁用 2正常 9 | RoleKey string `json:"roleKey" gorm:"size:128;"` //角色代码 10 | RoleSort int `json:"roleSort" gorm:""` //角色排序 11 | Flag string `json:"flag" gorm:"size:128;"` // 12 | Remark string `json:"remark" gorm:"size:255;"` //备注 13 | Admin bool `json:"admin" gorm:"size:4;"` 14 | DataScope string `json:"dataScope" gorm:"size:128;"` 15 | Params string `json:"params" gorm:"-"` 16 | MenuIds []int `json:"menuIds" gorm:"-"` 17 | DeptIds []int `json:"deptIds" gorm:"-"` 18 | SysDept []SysDept `json:"sysDept" gorm:"many2many:sys_role_dept;foreignKey:RoleId;joinForeignKey:role_id;references:DeptId;joinReferences:dept_id;"` 19 | SysMenu *[]SysMenu `json:"sysMenu" gorm:"many2many:sys_role_menu;foreignKey:RoleId;joinForeignKey:role_id;references:MenuId;joinReferences:menu_id;"` 20 | models.ControlBy 21 | models.ModelTime 22 | } 23 | 24 | func (*SysRole) TableName() string { 25 | return "sys_role" 26 | } 27 | 28 | func (e *SysRole) Generate() models.ActiveRecord { 29 | o := *e 30 | return &o 31 | } 32 | 33 | func (e *SysRole) GetId() interface{} { 34 | return e.RoleId 35 | } 36 | -------------------------------------------------------------------------------- /app/admin/models/sys_user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "go-admin/common/models" 5 | "golang.org/x/crypto/bcrypt" 6 | "gorm.io/gorm" 7 | ) 8 | 9 | type SysUser struct { 10 | UserId int `gorm:"primaryKey;autoIncrement;comment:编码" json:"userId"` 11 | Username string `json:"username" gorm:"size:64;comment:用户名"` 12 | Password string `json:"-" gorm:"size:128;comment:密码"` 13 | NickName string `json:"nickName" gorm:"size:128;comment:昵称"` 14 | Phone string `json:"phone" gorm:"size:11;comment:手机号"` 15 | RoleId int `json:"roleId" gorm:"size:20;comment:角色ID"` 16 | Salt string `json:"-" gorm:"size:255;comment:加盐"` 17 | Avatar string `json:"avatar" gorm:"size:255;comment:头像"` 18 | Sex string `json:"sex" gorm:"size:255;comment:性别"` 19 | Email string `json:"email" gorm:"size:128;comment:邮箱"` 20 | DeptId int `json:"deptId" gorm:"size:20;comment:部门"` 21 | PostId int `json:"postId" gorm:"size:20;comment:岗位"` 22 | Remark string `json:"remark" gorm:"size:255;comment:备注"` 23 | Status string `json:"status" gorm:"size:4;comment:状态"` 24 | DeptIds []int `json:"deptIds" gorm:"-"` 25 | PostIds []int `json:"postIds" gorm:"-"` 26 | RoleIds []int `json:"roleIds" gorm:"-"` 27 | Dept *SysDept `json:"dept"` 28 | models.ControlBy 29 | models.ModelTime 30 | } 31 | 32 | func (*SysUser) TableName() string { 33 | return "sys_user" 34 | } 35 | 36 | func (e *SysUser) Generate() models.ActiveRecord { 37 | o := *e 38 | return &o 39 | } 40 | 41 | func (e *SysUser) GetId() interface{} { 42 | return e.UserId 43 | } 44 | 45 | // Encrypt 加密 46 | func (e *SysUser) Encrypt() (err error) { 47 | if e.Password == "" { 48 | return 49 | } 50 | 51 | var hash []byte 52 | if hash, err = bcrypt.GenerateFromPassword([]byte(e.Password), bcrypt.DefaultCost); err != nil { 53 | return 54 | } else { 55 | e.Password = string(hash) 56 | return 57 | } 58 | } 59 | 60 | func (e *SysUser) BeforeCreate(_ *gorm.DB) error { 61 | return e.Encrypt() 62 | } 63 | 64 | func (e *SysUser) BeforeUpdate(_ *gorm.DB) error { 65 | var err error 66 | if e.Password != "" { 67 | err = e.Encrypt() 68 | } 69 | return err 70 | } 71 | 72 | func (e *SysUser) AfterFind(_ *gorm.DB) error { 73 | e.DeptIds = []int{e.DeptId} 74 | e.PostIds = []int{e.PostId} 75 | e.RoleIds = []int{e.RoleId} 76 | return nil 77 | } 78 | -------------------------------------------------------------------------------- /app/admin/router/init_router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/gin-gonic/gin" 7 | log "github.com/go-admin-team/go-admin-core/logger" 8 | "github.com/go-admin-team/go-admin-core/sdk" 9 | common "go-admin/common/middleware" 10 | ) 11 | 12 | // InitRouter 路由初始化,不要怀疑,这里用到了 13 | func InitRouter() { 14 | var r *gin.Engine 15 | h := sdk.Runtime.GetEngine() 16 | if h == nil { 17 | log.Fatal("not found engine...") 18 | os.Exit(-1) 19 | } 20 | switch h.(type) { 21 | case *gin.Engine: 22 | r = h.(*gin.Engine) 23 | default: 24 | log.Fatal("not support other engine") 25 | os.Exit(-1) 26 | } 27 | 28 | // the jwt middleware 29 | authMiddleware, err := common.AuthInit() 30 | if err != nil { 31 | log.Fatalf("JWT Init Error, %s", err.Error()) 32 | } 33 | 34 | // 注册系统路由 35 | InitSysRouter(r, authMiddleware) 36 | 37 | // 注册业务路由 38 | // TODO: 这里可存放业务路由,里边并无实际路由只有演示代码 39 | InitExamplesRouter(r, authMiddleware) 40 | } 41 | -------------------------------------------------------------------------------- /app/admin/router/router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | _ "github.com/gin-gonic/gin" 6 | "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 7 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 8 | ) 9 | 10 | var ( 11 | routerNoCheckRole = make([]func(*gin.RouterGroup), 0) 12 | routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0) 13 | ) 14 | 15 | func InitExamplesRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine { 16 | 17 | // 无需认证的路由 18 | examplesNoCheckRoleRouter(r) 19 | // 需要认证的路由 20 | examplesCheckRoleRouter(r, authMiddleware) 21 | 22 | return r 23 | } 24 | 25 | // 无需认证的路由示例 26 | func examplesNoCheckRoleRouter(r *gin.Engine) { 27 | // 可根据业务需求来设置接口版本 28 | v1 := r.Group("/api/v1") 29 | for _, f := range routerNoCheckRole { 30 | f(v1) 31 | } 32 | } 33 | 34 | // 需要认证的路由示例 35 | func examplesCheckRoleRouter(r *gin.Engine, authMiddleware *jwtauth.GinJWTMiddleware) { 36 | // 可根据业务需求来设置接口版本 37 | v1 := r.Group("/api/v1") 38 | for _, f := range routerCheckRole { 39 | f(v1, authMiddleware) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/admin/router/sys_api.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | 7 | "go-admin/app/admin/apis" 8 | "go-admin/common/middleware" 9 | ) 10 | 11 | func init() { 12 | routerCheckRole = append(routerCheckRole, registerSysApiRouter) 13 | } 14 | 15 | // registerSysApiRouter 16 | func registerSysApiRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 17 | api := apis.SysApi{} 18 | r := v1.Group("/sys-api").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 19 | { 20 | r.GET("", api.GetPage) 21 | r.GET("/:id", api.Get) 22 | r.PUT("/:id", api.Update) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/admin/router/sys_config.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "go-admin/app/admin/apis" 5 | "go-admin/common/middleware" 6 | 7 | "github.com/gin-gonic/gin" 8 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 9 | ) 10 | 11 | func init() { 12 | routerCheckRole = append(routerCheckRole, registerSysConfigRouter) 13 | } 14 | 15 | // 需认证的路由代码 16 | func registerSysConfigRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 17 | api := apis.SysConfig{} 18 | r := v1.Group("/config").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 19 | { 20 | r.GET("", api.GetPage) 21 | r.GET("/:id", api.Get) 22 | r.POST("", api.Insert) 23 | r.PUT("/:id", api.Update) 24 | r.DELETE("", api.Delete) 25 | } 26 | 27 | r1 := v1.Group("/configKey").Use(authMiddleware.MiddlewareFunc()) 28 | { 29 | r1.GET("/:configKey", api.GetSysConfigByKEYForService) 30 | } 31 | 32 | r2 := v1.Group("/app-config") 33 | { 34 | r2.GET("", api.Get2SysApp) 35 | } 36 | 37 | r3 := v1.Group("/set-config").Use(authMiddleware.MiddlewareFunc()) 38 | { 39 | r3.PUT("", api.Update2Set) 40 | r3.GET("", api.Get2Set) 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /app/admin/router/sys_dept.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "go-admin/app/admin/apis" 7 | "go-admin/common/middleware" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, registerSysDeptRouter) 12 | } 13 | 14 | // 需认证的路由代码 15 | func registerSysDeptRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 16 | api := apis.SysDept{} 17 | 18 | r := v1.Group("/dept").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 19 | { 20 | r.GET("", api.GetPage) 21 | r.GET("/:id", api.Get) 22 | r.POST("", api.Insert) 23 | r.PUT("/:id", api.Update) 24 | r.DELETE("", api.Delete) 25 | } 26 | 27 | r1 := v1.Group("").Use(authMiddleware.MiddlewareFunc()) 28 | { 29 | r1.GET("/deptTree", api.Get2Tree) 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /app/admin/router/sys_dict.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "go-admin/app/admin/apis" 7 | "go-admin/common/middleware" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, registerDictRouter) 12 | } 13 | 14 | func registerDictRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 15 | dictApi := apis.SysDictType{} 16 | dataApi := apis.SysDictData{} 17 | dicts := v1.Group("/dict").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 18 | { 19 | 20 | dicts.GET("/data", dataApi.GetPage) 21 | dicts.GET("/data/:dictCode", dataApi.Get) 22 | dicts.POST("/data", dataApi.Insert) 23 | dicts.PUT("/data/:dictCode", dataApi.Update) 24 | dicts.DELETE("/data", dataApi.Delete) 25 | 26 | dicts.GET("/type-option-select", dictApi.GetAll) 27 | dicts.GET("/type", dictApi.GetPage) 28 | dicts.GET("/type/:id", dictApi.Get) 29 | dicts.POST("/type", dictApi.Insert) 30 | dicts.PUT("/type/:id", dictApi.Update) 31 | dicts.DELETE("/type", dictApi.Delete) 32 | } 33 | opSelect := v1.Group("/dict-data").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 34 | { 35 | opSelect.GET("/option-select", dataApi.GetAll) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/admin/router/sys_login_log.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "go-admin/app/admin/apis" 7 | "go-admin/common/middleware" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, registerSysLoginLogRouter) 12 | } 13 | 14 | // 需认证的路由代码 15 | func registerSysLoginLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 16 | api := apis.SysLoginLog{} 17 | 18 | r := v1.Group("/sys-login-log").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 19 | { 20 | r.GET("", api.GetPage) 21 | r.GET("/:id", api.Get) 22 | r.DELETE("", api.Delete) 23 | } 24 | } -------------------------------------------------------------------------------- /app/admin/router/sys_menu.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "go-admin/app/admin/apis" 7 | "go-admin/common/middleware" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, registerSysMenuRouter) 12 | } 13 | 14 | // 需认证的路由代码 15 | func registerSysMenuRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 16 | api := apis.SysMenu{} 17 | 18 | r := v1.Group("/menu").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 19 | { 20 | r.GET("", api.GetPage) 21 | r.GET("/:id", api.Get) 22 | r.POST("", api.Insert) 23 | r.PUT("/:id", api.Update) 24 | r.DELETE("", api.Delete) 25 | } 26 | 27 | r1 := v1.Group("").Use(authMiddleware.MiddlewareFunc()) 28 | { 29 | r1.GET("/menurole", api.GetMenuRole) 30 | //r1.GET("/menuids", api.GetMenuIDS) 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /app/admin/router/sys_opera_log.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "go-admin/app/admin/apis" 7 | "go-admin/common/middleware" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, registerSysOperaLogRouter) 12 | } 13 | 14 | // 需认证的路由代码 15 | func registerSysOperaLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 16 | api := apis.SysOperaLog{} 17 | r := v1.Group("/sys-opera-log").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 18 | { 19 | r.GET("", api.GetPage) 20 | r.GET("/:id", api.Get) 21 | r.DELETE("", api.Delete) 22 | } 23 | } -------------------------------------------------------------------------------- /app/admin/router/sys_post.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "go-admin/app/admin/apis" 7 | "go-admin/common/middleware" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, registerSyPostRouter) 12 | } 13 | 14 | // 需认证的路由代码 15 | func registerSyPostRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 16 | api := apis.SysPost{} 17 | r := v1.Group("/post").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 18 | { 19 | r.GET("", api.GetPage) 20 | r.GET("/:id", api.Get) 21 | r.POST("", api.Insert) 22 | r.PUT("/:id", api.Update) 23 | r.DELETE("", api.Delete) 24 | } 25 | } -------------------------------------------------------------------------------- /app/admin/router/sys_role.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | 7 | "go-admin/app/admin/apis" 8 | "go-admin/common/middleware" 9 | ) 10 | 11 | func init() { 12 | routerCheckRole = append(routerCheckRole, registerSysRoleRouter) 13 | } 14 | 15 | // 需认证的路由代码 16 | func registerSysRoleRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 17 | api := apis.SysRole{} 18 | r := v1.Group("/role").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 19 | { 20 | r.GET("", api.GetPage) 21 | r.GET("/:id", api.Get) 22 | r.POST("", api.Insert) 23 | r.PUT("/:id", api.Update) 24 | r.DELETE("", api.Delete) 25 | } 26 | r1 := v1.Group("").Use(authMiddleware.MiddlewareFunc()) 27 | { 28 | r1.PUT("/role-status", api.Update2Status) 29 | r1.PUT("/roledatascope", api.Update2DataScope) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/admin/router/sys_router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "go-admin/app/admin/apis" 5 | "mime" 6 | 7 | "github.com/go-admin-team/go-admin-core/sdk/config" 8 | 9 | "github.com/gin-gonic/gin" 10 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 11 | "github.com/go-admin-team/go-admin-core/sdk/pkg/ws" 12 | ginSwagger "github.com/swaggo/gin-swagger" 13 | 14 | swaggerfiles "github.com/swaggo/files" 15 | 16 | "go-admin/common/middleware" 17 | "go-admin/common/middleware/handler" 18 | _ "go-admin/docs/admin" 19 | ) 20 | 21 | func InitSysRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.RouterGroup { 22 | g := r.Group("") 23 | sysBaseRouter(g) 24 | // 静态文件 25 | sysStaticFileRouter(g) 26 | // swagger;注意:生产环境可以注释掉 27 | if config.ApplicationConfig.Mode != "prod" { 28 | sysSwaggerRouter(g) 29 | } 30 | // 需要认证 31 | sysCheckRoleRouterInit(g, authMiddleware) 32 | return g 33 | } 34 | 35 | func sysBaseRouter(r *gin.RouterGroup) { 36 | 37 | go ws.WebsocketManager.Start() 38 | go ws.WebsocketManager.SendService() 39 | go ws.WebsocketManager.SendAllService() 40 | 41 | if config.ApplicationConfig.Mode != "prod" { 42 | r.GET("/", apis.GoAdmin) 43 | } 44 | r.GET("/info", handler.Ping) 45 | } 46 | 47 | func sysStaticFileRouter(r *gin.RouterGroup) { 48 | err := mime.AddExtensionType(".js", "application/javascript") 49 | if err != nil { 50 | return 51 | } 52 | r.Static("/static", "./static") 53 | if config.ApplicationConfig.Mode != "prod" { 54 | r.Static("/form-generator", "./static/form-generator") 55 | } 56 | } 57 | 58 | func sysSwaggerRouter(r *gin.RouterGroup) { 59 | r.GET("/swagger/admin/*any", ginSwagger.WrapHandler(swaggerfiles.NewHandler(), ginSwagger.InstanceName("admin"))) 60 | } 61 | 62 | func sysCheckRoleRouterInit(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 63 | wss := r.Group("").Use(authMiddleware.MiddlewareFunc()) 64 | { 65 | wss.GET("/ws/:id/:channel", ws.WebsocketManager.WsClient) 66 | wss.GET("/wslogout/:id/:channel", ws.WebsocketManager.UnWsClient) 67 | } 68 | 69 | v1 := r.Group("/api/v1") 70 | { 71 | v1.POST("/login", authMiddleware.LoginHandler) 72 | // Refresh time can be longer than token timeout 73 | v1.GET("/refresh_token", authMiddleware.RefreshHandler) 74 | } 75 | registerBaseRouter(v1, authMiddleware) 76 | } 77 | 78 | func registerBaseRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 79 | api := apis.SysMenu{} 80 | api2 := apis.SysDept{} 81 | v1auth := v1.Group("").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 82 | { 83 | v1auth.GET("/roleMenuTreeselect/:roleId", api.GetMenuTreeSelect) 84 | //v1.GET("/menuTreeselect", api.GetMenuTreeSelect) 85 | v1auth.GET("/roleDeptTreeselect/:roleId", api2.GetDeptTreeRoleSelect) 86 | v1auth.POST("/logout", handler.LogOut) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /app/admin/router/sys_user.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "go-admin/app/admin/apis" 7 | "go-admin/common/actions" 8 | "go-admin/common/middleware" 9 | ) 10 | 11 | func init() { 12 | routerCheckRole = append(routerCheckRole, registerSysUserRouter) 13 | } 14 | 15 | // 需认证的路由代码 16 | func registerSysUserRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 17 | api := apis.SysUser{} 18 | r := v1.Group("/sys-user").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()).Use(actions.PermissionAction()) 19 | { 20 | r.GET("", api.GetPage) 21 | r.GET("/:id", api.Get) 22 | r.POST("", api.Insert) 23 | r.PUT("", api.Update) 24 | r.DELETE("", api.Delete) 25 | } 26 | 27 | user := v1.Group("/user").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()).Use(actions.PermissionAction()) 28 | { 29 | user.GET("/profile", api.GetProfile) 30 | user.POST("/avatar", api.InsetAvatar) 31 | user.PUT("/pwd/set", api.UpdatePwd) 32 | user.PUT("/pwd/reset", api.ResetPwd) 33 | user.PUT("/status", api.UpdateStatus) 34 | } 35 | v1auth := v1.Group("").Use(authMiddleware.MiddlewareFunc()) 36 | { 37 | v1auth.GET("/getinfo", api.GetInfo) 38 | } 39 | } -------------------------------------------------------------------------------- /app/admin/service/dto/sys_api.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "go-admin/app/admin/models" 5 | "go-admin/common/dto" 6 | common "go-admin/common/models" 7 | ) 8 | 9 | // SysApiGetPageReq 功能列表请求参数 10 | type SysApiGetPageReq struct { 11 | dto.Pagination `search:"-"` 12 | Title string `form:"title" search:"type:contains;column:title;table:sys_api" comment:"标题"` 13 | Path string `form:"path" search:"type:contains;column:path;table:sys_api" comment:"地址"` 14 | Action string `form:"action" search:"type:exact;column:action;table:sys_api" comment:"请求方式"` 15 | ParentId string `form:"parentId" search:"type:exact;column:parent_id;table:sys_api" comment:"按钮id"` 16 | Type string `form:"type" search:"-" comment:"类型"` 17 | SysApiOrder 18 | } 19 | 20 | type SysApiOrder struct { 21 | TitleOrder string `search:"type:order;column:title;table:sys_api" form:"titleOrder"` 22 | PathOrder string `search:"type:order;column:path;table:sys_api" form:"pathOrder"` 23 | CreatedAtOrder string `search:"type:order;column:created_at;table:sys_api" form:"createdAtOrder"` 24 | } 25 | 26 | func (m *SysApiGetPageReq) GetNeedSearch() interface{} { 27 | return *m 28 | } 29 | 30 | // SysApiInsertReq 功能创建请求参数 31 | type SysApiInsertReq struct { 32 | Id int `json:"-" comment:"编码"` // 编码 33 | Handle string `json:"handle" comment:"handle"` 34 | Title string `json:"title" comment:"标题"` 35 | Path string `json:"path" comment:"地址"` 36 | Type string `json:"type" comment:""` 37 | Action string `json:"action" comment:"类型"` 38 | common.ControlBy 39 | } 40 | 41 | func (s *SysApiInsertReq) Generate(model *models.SysApi) { 42 | model.Handle = s.Handle 43 | model.Title = s.Title 44 | model.Path = s.Path 45 | model.Type = s.Type 46 | model.Action = s.Action 47 | } 48 | 49 | func (s *SysApiInsertReq) GetId() interface{} { 50 | return s.Id 51 | } 52 | 53 | // SysApiUpdateReq 功能更新请求参数 54 | type SysApiUpdateReq struct { 55 | Id int `uri:"id" comment:"编码"` // 编码 56 | Handle string `json:"handle" comment:"handle"` 57 | Title string `json:"title" comment:"标题"` 58 | Path string `json:"path" comment:"地址"` 59 | Type string `json:"type" comment:""` 60 | Action string `json:"action" comment:"类型"` 61 | common.ControlBy 62 | } 63 | 64 | func (s *SysApiUpdateReq) Generate(model *models.SysApi) { 65 | if s.Id != 0 { 66 | model.Id = s.Id 67 | } 68 | model.Handle = s.Handle 69 | model.Title = s.Title 70 | model.Path = s.Path 71 | model.Type = s.Type 72 | model.Action = s.Action 73 | } 74 | 75 | func (s *SysApiUpdateReq) GetId() interface{} { 76 | return s.Id 77 | } 78 | 79 | // SysApiGetReq 功能获取请求参数 80 | type SysApiGetReq struct { 81 | Id int `uri:"id"` 82 | } 83 | 84 | func (s *SysApiGetReq) GetId() interface{} { 85 | return s.Id 86 | } 87 | 88 | // SysApiDeleteReq 功能删除请求参数 89 | type SysApiDeleteReq struct { 90 | Ids []int `json:"ids"` 91 | } 92 | 93 | func (s *SysApiDeleteReq) GetId() interface{} { 94 | return s.Ids 95 | } 96 | -------------------------------------------------------------------------------- /app/admin/service/dto/sys_dict_type.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "go-admin/app/admin/models" 5 | 6 | "go-admin/common/dto" 7 | common "go-admin/common/models" 8 | ) 9 | 10 | type SysDictTypeGetPageReq struct { 11 | dto.Pagination `search:"-"` 12 | DictId []int `form:"dictId" search:"type:in;column:dict_id;table:sys_dict_type"` 13 | DictName string `form:"dictName" search:"type:icontains;column:dict_name;table:sys_dict_type"` 14 | DictType string `form:"dictType" search:"type:icontains;column:dict_type;table:sys_dict_type"` 15 | Status int `form:"status" search:"type:exact;column:status;table:sys_dict_type"` 16 | } 17 | 18 | type SysDictTypeOrder struct { 19 | DictIdOrder string `search:"type:order;column:dict_id;table:sys_dict_type" form:"dictIdOrder"` 20 | } 21 | 22 | func (m *SysDictTypeGetPageReq) GetNeedSearch() interface{} { 23 | return *m 24 | } 25 | 26 | type SysDictTypeInsertReq struct { 27 | Id int `uri:"id"` 28 | DictName string `json:"dictName"` 29 | DictType string `json:"dictType"` 30 | Status int `json:"status"` 31 | Remark string `json:"remark"` 32 | common.ControlBy 33 | } 34 | 35 | func (s *SysDictTypeInsertReq) Generate(model *models.SysDictType) { 36 | if s.Id != 0 { 37 | model.ID = s.Id 38 | } 39 | model.DictName = s.DictName 40 | model.DictType = s.DictType 41 | model.Status = s.Status 42 | model.Remark = s.Remark 43 | 44 | } 45 | 46 | func (s *SysDictTypeInsertReq) GetId() interface{} { 47 | return s.Id 48 | } 49 | 50 | type SysDictTypeUpdateReq struct { 51 | Id int `uri:"id"` 52 | DictName string `json:"dictName"` 53 | DictType string `json:"dictType"` 54 | Status int `json:"status"` 55 | Remark string `json:"remark"` 56 | common.ControlBy 57 | } 58 | 59 | func (s *SysDictTypeUpdateReq) Generate(model *models.SysDictType) { 60 | if s.Id != 0 { 61 | model.ID = s.Id 62 | } 63 | model.DictName = s.DictName 64 | model.DictType = s.DictType 65 | model.Status = s.Status 66 | model.Remark = s.Remark 67 | 68 | } 69 | 70 | func (s *SysDictTypeUpdateReq) GetId() interface{} { 71 | return s.Id 72 | } 73 | 74 | type SysDictTypeGetReq struct { 75 | Id int `uri:"id"` 76 | } 77 | 78 | func (s *SysDictTypeGetReq) GetId() interface{} { 79 | return s.Id 80 | } 81 | 82 | type SysDictTypeDeleteReq struct { 83 | Ids []int `json:"ids"` 84 | common.ControlBy 85 | } 86 | 87 | func (s *SysDictTypeDeleteReq) GetId() interface{} { 88 | return s.Ids 89 | } 90 | -------------------------------------------------------------------------------- /app/admin/service/dto/sys_login_log.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "time" 5 | 6 | "go-admin/common/dto" 7 | ) 8 | 9 | type SysLoginLogGetPageReq struct { 10 | dto.Pagination `search:"-"` 11 | Username string `form:"username" search:"type:exact;column:username;table:sys_login_log" comment:"用户名"` 12 | Status string `form:"status" search:"type:exact;column:status;table:sys_login_log" comment:"状态"` 13 | Ipaddr string `form:"ipaddr" search:"type:exact;column:ipaddr;table:sys_login_log" comment:"ip地址"` 14 | LoginLocation string `form:"loginLocation" search:"type:exact;column:login_location;table:sys_login_log" comment:"归属地"` 15 | BeginTime string `form:"beginTime" search:"type:gte;column:ctime;table:sys_login_log" comment:"创建时间"` 16 | EndTime string `form:"endTime" search:"type:lte;column:ctime;table:sys_login_log" comment:"创建时间"` 17 | SysLoginLogOrder 18 | } 19 | 20 | type SysLoginLogOrder struct { 21 | CreatedAtOrder string `search:"type:order;column:created_at;table:sys_login_log" form:"createdAtOrder"` 22 | } 23 | 24 | func (m *SysLoginLogGetPageReq) GetNeedSearch() interface{} { 25 | return *m 26 | } 27 | 28 | type SysLoginLogControl struct { 29 | ID int `uri:"Id" comment:"主键"` // 主键 30 | Username string `json:"username" comment:"用户名"` 31 | Status string `json:"status" comment:"状态"` 32 | Ipaddr string `json:"ipaddr" comment:"ip地址"` 33 | LoginLocation string `json:"loginLocation" comment:"归属地"` 34 | Browser string `json:"browser" comment:"浏览器"` 35 | Os string `json:"os" comment:"系统"` 36 | Platform string `json:"platform" comment:"固件"` 37 | LoginTime time.Time `json:"loginTime" comment:"登录时间"` 38 | Remark string `json:"remark" comment:"备注"` 39 | Msg string `json:"msg" comment:"信息"` 40 | } 41 | 42 | type SysLoginLogGetReq struct { 43 | Id int `uri:"id"` 44 | } 45 | 46 | func (s *SysLoginLogGetReq) GetId() interface{} { 47 | return s.Id 48 | } 49 | 50 | // SysLoginLogDeleteReq 功能删除请求参数 51 | type SysLoginLogDeleteReq struct { 52 | Ids []int `json:"ids"` 53 | } 54 | 55 | func (s *SysLoginLogDeleteReq) GetId() interface{} { 56 | return s.Ids 57 | } -------------------------------------------------------------------------------- /app/admin/service/sys_login_log.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/go-admin-team/go-admin-core/sdk/service" 7 | "gorm.io/gorm" 8 | 9 | "go-admin/app/admin/models" 10 | "go-admin/app/admin/service/dto" 11 | cDto "go-admin/common/dto" 12 | ) 13 | 14 | type SysLoginLog struct { 15 | service.Service 16 | } 17 | 18 | // GetPage 获取SysLoginLog列表 19 | func (e *SysLoginLog) GetPage(c *dto.SysLoginLogGetPageReq, list *[]models.SysLoginLog, count *int64) error { 20 | var err error 21 | var data models.SysLoginLog 22 | 23 | err = e.Orm.Model(&data). 24 | Scopes( 25 | cDto.MakeCondition(c.GetNeedSearch()), 26 | cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), 27 | ). 28 | Find(list).Limit(-1).Offset(-1). 29 | Count(count).Error 30 | if err != nil { 31 | e.Log.Errorf("db error:%s", err) 32 | return err 33 | } 34 | return nil 35 | } 36 | 37 | // Get 获取SysLoginLog对象 38 | func (e *SysLoginLog) Get(d *dto.SysLoginLogGetReq, model *models.SysLoginLog) error { 39 | var err error 40 | db := e.Orm.First(model, d.GetId()) 41 | err = db.Error 42 | if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { 43 | err = errors.New("查看对象不存在或无权查看") 44 | e.Log.Errorf("db error:%s", err) 45 | return err 46 | } 47 | if err = db.Error; err != nil { 48 | e.Log.Errorf("db error:%s", err) 49 | return err 50 | } 51 | return nil 52 | } 53 | 54 | // Remove 删除SysLoginLog 55 | func (e *SysLoginLog) Remove(c *dto.SysLoginLogDeleteReq) error { 56 | var err error 57 | var data models.SysLoginLog 58 | 59 | db := e.Orm.Delete(&data, c.GetId()) 60 | if err = db.Error; err != nil { 61 | e.Log.Errorf("Delete error: %s", err) 62 | return err 63 | } 64 | if db.RowsAffected == 0 { 65 | err = errors.New("无权删除该数据") 66 | return err 67 | } 68 | return nil 69 | } 70 | -------------------------------------------------------------------------------- /app/admin/service/sys_opera_log.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "errors" 5 | 6 | "go-admin/app/admin/models" 7 | "go-admin/app/admin/service/dto" 8 | cDto "go-admin/common/dto" 9 | 10 | "github.com/go-admin-team/go-admin-core/sdk/service" 11 | "gorm.io/gorm" 12 | ) 13 | 14 | type SysOperaLog struct { 15 | service.Service 16 | } 17 | 18 | // GetPage 获取SysOperaLog列表 19 | func (e *SysOperaLog) GetPage(c *dto.SysOperaLogGetPageReq, list *[]models.SysOperaLog, count *int64) error { 20 | var err error 21 | var data models.SysOperaLog 22 | 23 | err = e.Orm.Model(&data). 24 | Scopes( 25 | cDto.MakeCondition(c.GetNeedSearch()), 26 | cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), 27 | ). 28 | Find(list).Limit(-1).Offset(-1). 29 | Count(count).Error 30 | if err != nil { 31 | e.Log.Errorf("Service GetSysOperaLogPage error:%s", err.Error()) 32 | return err 33 | } 34 | return nil 35 | } 36 | 37 | // Get 获取SysOperaLog对象 38 | func (e *SysOperaLog) Get(d *dto.SysOperaLogGetReq, model *models.SysOperaLog) error { 39 | var data models.SysOperaLog 40 | 41 | err := e.Orm.Model(&data). 42 | First(model, d.GetId()).Error 43 | if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { 44 | err = errors.New("查看对象不存在或无权查看") 45 | e.Log.Errorf("Service GetSysOperaLog error:%s", err.Error()) 46 | return err 47 | } 48 | if err != nil { 49 | e.Log.Errorf("Service GetSysOperaLog error:%s", err.Error()) 50 | return err 51 | } 52 | return nil 53 | } 54 | 55 | // Insert 创建SysOperaLog对象 56 | func (e *SysOperaLog) Insert(model *models.SysOperaLog) error { 57 | var err error 58 | var data models.SysOperaLog 59 | 60 | err = e.Orm.Model(&data). 61 | Create(model).Error 62 | if err != nil { 63 | e.Log.Errorf("Service InsertSysOperaLog error:%s", err.Error()) 64 | return err 65 | } 66 | return nil 67 | } 68 | 69 | // Remove 删除SysOperaLog 70 | func (e *SysOperaLog) Remove(d *dto.SysOperaLogDeleteReq) error { 71 | var err error 72 | var data models.SysOperaLog 73 | 74 | db := e.Orm.Model(&data).Delete(&data, d.GetId()) 75 | if err = db.Error; err != nil { 76 | e.Log.Errorf("Service RemoveSysOperaLog error:%s", err.Error()) 77 | return err 78 | } 79 | if db.RowsAffected == 0 { 80 | return errors.New("无权删除该数据") 81 | } 82 | return nil 83 | } 84 | -------------------------------------------------------------------------------- /app/admin/service/sys_post.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/go-admin-team/go-admin-core/sdk/service" 7 | "gorm.io/gorm" 8 | 9 | "go-admin/app/admin/models" 10 | "go-admin/app/admin/service/dto" 11 | cDto "go-admin/common/dto" 12 | ) 13 | 14 | type SysPost struct { 15 | service.Service 16 | } 17 | 18 | // GetPage 获取SysPost列表 19 | func (e *SysPost) GetPage(c *dto.SysPostPageReq, list *[]models.SysPost, count *int64) error { 20 | var err error 21 | var data models.SysPost 22 | 23 | err = e.Orm.Model(&data). 24 | Scopes( 25 | cDto.MakeCondition(c.GetNeedSearch()), 26 | cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), 27 | ). 28 | Find(list).Limit(-1).Offset(-1). 29 | Count(count).Error 30 | if err != nil { 31 | e.Log.Errorf("db error:%s \r", err) 32 | return err 33 | } 34 | return nil 35 | } 36 | 37 | // Get 获取SysPost对象 38 | func (e *SysPost) Get(d *dto.SysPostGetReq, model *models.SysPost) error { 39 | var err error 40 | var data models.SysPost 41 | 42 | db := e.Orm.Model(&data). 43 | First(model, d.GetId()) 44 | err = db.Error 45 | if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { 46 | err = errors.New("查看对象不存在或无权查看") 47 | e.Log.Errorf("db error:%s", err) 48 | return err 49 | } 50 | if err != nil { 51 | e.Log.Errorf("db error:%s", err) 52 | return err 53 | } 54 | return nil 55 | } 56 | 57 | // Insert 创建SysPost对象 58 | func (e *SysPost) Insert(c *dto.SysPostInsertReq) error { 59 | var err error 60 | var data models.SysPost 61 | c.Generate(&data) 62 | err = e.Orm.Create(&data).Error 63 | if err != nil { 64 | e.Log.Errorf("db error:%s", err) 65 | return err 66 | } 67 | return nil 68 | } 69 | 70 | // Update 修改SysPost对象 71 | func (e *SysPost) Update(c *dto.SysPostUpdateReq) error { 72 | var err error 73 | var model = models.SysPost{} 74 | e.Orm.First(&model, c.GetId()) 75 | c.Generate(&model) 76 | 77 | db := e.Orm.Save(&model) 78 | if err = db.Error; err != nil { 79 | e.Log.Errorf("db error:%s", err) 80 | return err 81 | } 82 | if db.RowsAffected == 0 { 83 | return errors.New("无权更新该数据") 84 | 85 | } 86 | return nil 87 | } 88 | 89 | // Remove 删除SysPost 90 | func (e *SysPost) Remove(d *dto.SysPostDeleteReq) error { 91 | var err error 92 | var data models.SysPost 93 | 94 | db := e.Orm.Model(&data).Delete(&data, d.GetId()) 95 | if err = db.Error; err != nil { 96 | e.Log.Errorf("Delete error: %s", err) 97 | return err 98 | } 99 | if db.RowsAffected == 0 { 100 | err = errors.New("无权删除该数据") 101 | return err 102 | } 103 | return nil 104 | } 105 | -------------------------------------------------------------------------------- /app/jobs/apis/sys_job.go: -------------------------------------------------------------------------------- 1 | package apis 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/go-admin-team/go-admin-core/sdk" 8 | "github.com/go-admin-team/go-admin-core/sdk/api" 9 | 10 | "go-admin/app/jobs/service" 11 | "go-admin/common/dto" 12 | ) 13 | 14 | type SysJob struct { 15 | api.Api 16 | } 17 | 18 | // RemoveJobForService 调用service实现 19 | func (e SysJob) RemoveJobForService(c *gin.Context) { 20 | v := dto.GeneralDelDto{} 21 | s := service.SysJob{} 22 | err := e.MakeContext(c). 23 | MakeOrm(). 24 | Bind(&v). 25 | MakeService(&s.Service). 26 | Errors 27 | if err != nil { 28 | e.Logger.Error(err) 29 | return 30 | } 31 | 32 | s.Cron = sdk.Runtime.GetCrontabKey(c.Request.Host) 33 | err = s.RemoveJob(&v) 34 | if err != nil { 35 | e.Logger.Errorf("RemoveJob error, %s", err.Error()) 36 | e.Error(500, err, "") 37 | return 38 | } 39 | e.OK(nil, s.Msg) 40 | } 41 | 42 | // StartJobForService 启动job service实现 43 | func (e SysJob) StartJobForService(c *gin.Context) { 44 | e.MakeContext(c) 45 | log := e.GetLogger() 46 | db, err := e.GetOrm() 47 | if err != nil { 48 | log.Error(err) 49 | return 50 | } 51 | var v dto.GeneralGetDto 52 | err = c.BindUri(&v) 53 | if err != nil { 54 | log.Warnf("参数验证错误, error: %s", err) 55 | e.Error(http.StatusUnprocessableEntity, err, "参数验证失败") 56 | return 57 | } 58 | s := service.SysJob{} 59 | s.Orm = db 60 | s.Log = log 61 | s.Cron = sdk.Runtime.GetCrontabKey(c.Request.Host) 62 | err = s.StartJob(&v) 63 | if err != nil { 64 | log.Errorf("GetCrontabKey error, %s", err.Error()) 65 | e.Error(500, err, err.Error()) 66 | return 67 | } 68 | e.OK(nil, s.Msg) 69 | } 70 | -------------------------------------------------------------------------------- /app/jobs/examples.go: -------------------------------------------------------------------------------- 1 | package jobs 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | // InitJob 9 | // 需要将定义的struct 添加到字典中; 10 | // 字典 key 可以配置到 自动任务 调用目标 中; 11 | func InitJob() { 12 | jobList = map[string]JobExec{ 13 | "ExamplesOne": ExamplesOne{}, 14 | // ... 15 | } 16 | } 17 | 18 | // ExamplesOne 19 | // 新添加的job 必须按照以下格式定义,并实现Exec函数 20 | type ExamplesOne struct { 21 | } 22 | 23 | func (t ExamplesOne) Exec(arg interface{}) error { 24 | str := time.Now().Format(timeFormat) + " [INFO] JobCore ExamplesOne exec success" 25 | // TODO: 这里需要注意 Examples 传入参数是 string 所以 arg.(string);请根据对应的类型进行转化; 26 | switch arg.(type) { 27 | 28 | case string: 29 | if arg.(string) != "" { 30 | fmt.Println("string", arg.(string)) 31 | fmt.Println(str, arg.(string)) 32 | } else { 33 | fmt.Println("arg is nil") 34 | fmt.Println(str, "arg is nil") 35 | } 36 | break 37 | } 38 | 39 | return nil 40 | } 41 | -------------------------------------------------------------------------------- /app/jobs/models/sys_job.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "go-admin/common/models" 5 | "gorm.io/gorm" 6 | ) 7 | 8 | type SysJob struct { 9 | JobId int `json:"jobId" gorm:"primaryKey;autoIncrement"` // 编码 10 | JobName string `json:"jobName" gorm:"size:255;"` // 名称 11 | JobGroup string `json:"jobGroup" gorm:"size:255;"` // 任务分组 12 | JobType int `json:"jobType" gorm:"size:1;"` // 任务类型 13 | CronExpression string `json:"cronExpression" gorm:"size:255;"` // cron表达式 14 | InvokeTarget string `json:"invokeTarget" gorm:"size:255;"` // 调用目标 15 | Args string `json:"args" gorm:"size:255;"` // 目标参数 16 | MisfirePolicy int `json:"misfirePolicy" gorm:"size:255;"` // 执行策略 17 | Concurrent int `json:"concurrent" gorm:"size:1;"` // 是否并发 18 | Status int `json:"status" gorm:"size:1;"` // 状态 19 | EntryId int `json:"entry_id" gorm:"size:11;"` // job启动时返回的id 20 | models.ControlBy 21 | models.ModelTime 22 | 23 | DataScope string `json:"dataScope" gorm:"-"` 24 | } 25 | 26 | func (*SysJob) TableName() string { 27 | return "sys_job" 28 | } 29 | 30 | func (e *SysJob) Generate() models.ActiveRecord { 31 | o := *e 32 | return &o 33 | } 34 | 35 | func (e *SysJob) GetId() interface{} { 36 | return e.JobId 37 | } 38 | 39 | func (e *SysJob) SetCreateBy(createBy int) { 40 | e.CreateBy = createBy 41 | } 42 | 43 | func (e *SysJob) SetUpdateBy(updateBy int) { 44 | e.UpdateBy = updateBy 45 | } 46 | 47 | func (e *SysJob) GetList(tx *gorm.DB, list interface{}) (err error) { 48 | return tx.Table(e.TableName()).Where("status = ?", 2).Find(list).Error 49 | } 50 | 51 | // Update 更新SysJob 52 | func (e *SysJob) Update(tx *gorm.DB, id interface{}) (err error) { 53 | return tx.Table(e.TableName()).Where(id).Updates(&e).Error 54 | } 55 | 56 | func (e *SysJob) RemoveAllEntryID(tx *gorm.DB) (update SysJob, err error) { 57 | if err = tx.Table(e.TableName()).Where("entry_id > ?", 0).Update("entry_id", 0).Error; err != nil { 58 | return 59 | } 60 | return 61 | } 62 | -------------------------------------------------------------------------------- /app/jobs/router/int_router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | //"github.com/go-admin-team/go-admin-core/sdk/pkg" 5 | "os" 6 | 7 | "github.com/gin-gonic/gin" 8 | log "github.com/go-admin-team/go-admin-core/logger" 9 | "github.com/go-admin-team/go-admin-core/sdk" 10 | common "go-admin/common/middleware" 11 | ) 12 | 13 | // InitRouter 路由初始化,不要怀疑,这里用到了 14 | func InitRouter() { 15 | var r *gin.Engine 16 | h := sdk.Runtime.GetEngine() 17 | if h == nil { 18 | log.Fatal("not found engine...") 19 | os.Exit(-1) 20 | } 21 | switch h.(type) { 22 | case *gin.Engine: 23 | r = h.(*gin.Engine) 24 | default: 25 | log.Fatal("not support other engine") 26 | os.Exit(-1) 27 | } 28 | 29 | authMiddleware, err := common.AuthInit() 30 | if err != nil { 31 | log.Fatalf("JWT Init Error, %s", err.Error()) 32 | } 33 | 34 | // 注册业务路由 35 | initRouter(r, authMiddleware) 36 | } 37 | -------------------------------------------------------------------------------- /app/jobs/router/router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | ) 7 | 8 | var ( 9 | routerNoCheckRole = make([]func(*gin.RouterGroup), 0) 10 | routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0) 11 | ) 12 | 13 | // initRouter 路由示例 14 | func initRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine { 15 | 16 | // 无需认证的路由 17 | noCheckRoleRouter(r) 18 | // 需要认证的路由 19 | checkRoleRouter(r, authMiddleware) 20 | 21 | return r 22 | } 23 | 24 | // noCheckRoleRouter 无需认证的路由示例 25 | func noCheckRoleRouter(r *gin.Engine) { 26 | // 可根据业务需求来设置接口版本 27 | v1 := r.Group("/api/v1") 28 | 29 | for _, f := range routerNoCheckRole { 30 | f(v1) 31 | } 32 | } 33 | 34 | // checkRoleRouter 需要认证的路由示例 35 | func checkRoleRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) { 36 | // 可根据业务需求来设置接口版本 37 | v1 := r.Group("/api/v1") 38 | 39 | for _, f := range routerCheckRole { 40 | f(v1, authMiddleware) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/jobs/router/sys_job.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "go-admin/app/jobs/apis" 7 | models2 "go-admin/app/jobs/models" 8 | dto2 "go-admin/app/jobs/service/dto" 9 | "go-admin/common/actions" 10 | "go-admin/common/middleware" 11 | ) 12 | 13 | func init() { 14 | routerCheckRole = append(routerCheckRole, registerSysJobRouter) 15 | } 16 | 17 | // 需认证的路由代码 18 | func registerSysJobRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 19 | 20 | r := v1.Group("/sysjob").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 21 | { 22 | sysJob := &models2.SysJob{} 23 | r.GET("", actions.PermissionAction(), actions.IndexAction(sysJob, new(dto2.SysJobSearch), func() interface{} { 24 | list := make([]models2.SysJob, 0) 25 | return &list 26 | })) 27 | r.GET("/:id", actions.PermissionAction(), actions.ViewAction(new(dto2.SysJobById), func() interface{} { 28 | return &dto2.SysJobItem{} 29 | })) 30 | r.POST("", actions.CreateAction(new(dto2.SysJobControl))) 31 | r.PUT("", actions.PermissionAction(), actions.UpdateAction(new(dto2.SysJobControl))) 32 | r.DELETE("", actions.PermissionAction(), actions.DeleteAction(new(dto2.SysJobById))) 33 | } 34 | sysJob := apis.SysJob{} 35 | 36 | v1.GET("/job/remove/:id", sysJob.RemoveJobForService) 37 | v1.GET("/job/start/:id", sysJob.StartJobForService) 38 | } 39 | -------------------------------------------------------------------------------- /app/jobs/service/sys_job.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "errors" 5 | "time" 6 | 7 | "github.com/go-admin-team/go-admin-core/sdk/service" 8 | "github.com/robfig/cron/v3" 9 | 10 | "go-admin/app/jobs" 11 | "go-admin/app/jobs/models" 12 | "go-admin/common/dto" 13 | ) 14 | 15 | type SysJob struct { 16 | service.Service 17 | Cron *cron.Cron 18 | } 19 | 20 | // RemoveJob 删除job 21 | func (e *SysJob) RemoveJob(c *dto.GeneralDelDto) error { 22 | var err error 23 | var data models.SysJob 24 | err = e.Orm.Table(data.TableName()).First(&data, c.Id).Error 25 | if err != nil { 26 | e.Log.Errorf("db error: %s", err) 27 | return err 28 | } 29 | cn := jobs.Remove(e.Cron, data.EntryId) 30 | 31 | select { 32 | case res := <-cn: 33 | if res { 34 | err = e.Orm.Table(data.TableName()).Where("entry_id = ?", data.EntryId).Update("entry_id", 0).Error 35 | if err != nil { 36 | e.Log.Errorf("db error: %s", err) 37 | } 38 | return err 39 | } 40 | case <-time.After(time.Second * 1): 41 | e.Msg = "操作超时!" 42 | return nil 43 | } 44 | return nil 45 | } 46 | 47 | // StartJob 启动任务 48 | func (e *SysJob) StartJob(c *dto.GeneralGetDto) error { 49 | var data models.SysJob 50 | var err error 51 | err = e.Orm.Table(data.TableName()).First(&data, c.Id).Error 52 | if err != nil { 53 | e.Log.Errorf("db error: %s", err) 54 | return err 55 | } 56 | 57 | if data.Status == 1 { 58 | err = errors.New("当前Job是关闭状态不能被启动,请先启用。") 59 | return err 60 | } 61 | 62 | if data.JobType == 1 { 63 | var j = &jobs.HttpJob{} 64 | j.InvokeTarget = data.InvokeTarget 65 | j.CronExpression = data.CronExpression 66 | j.JobId = data.JobId 67 | j.Name = data.JobName 68 | data.EntryId, err = jobs.AddJob(e.Cron, j) 69 | if err != nil { 70 | e.Log.Errorf("jobs AddJob[HttpJob] error: %s", err) 71 | } 72 | } else { 73 | var j = &jobs.ExecJob{} 74 | j.InvokeTarget = data.InvokeTarget 75 | j.CronExpression = data.CronExpression 76 | j.JobId = data.JobId 77 | j.Name = data.JobName 78 | j.Args = data.Args 79 | data.EntryId, err = jobs.AddJob(e.Cron, j) 80 | if err != nil { 81 | e.Log.Errorf("jobs AddJob[ExecJob] error: %s", err) 82 | } 83 | } 84 | if err != nil { 85 | return err 86 | } 87 | 88 | err = e.Orm.Table(data.TableName()).Where(c.Id).Updates(&data).Error 89 | if err != nil { 90 | e.Log.Errorf("db error: %s", err) 91 | } 92 | return err 93 | } 94 | -------------------------------------------------------------------------------- /app/jobs/type.go: -------------------------------------------------------------------------------- 1 | package jobs 2 | 3 | import "github.com/robfig/cron/v3" 4 | 5 | type Job interface { 6 | Run() 7 | addJob(*cron.Cron) (int, error) 8 | } 9 | 10 | type JobExec interface { 11 | Exec(arg interface{}) error 12 | } 13 | 14 | func CallExec(e JobExec, arg interface{}) error { 15 | return e.Exec(arg) 16 | } 17 | -------------------------------------------------------------------------------- /app/other/apis/tools/db_columns.go: -------------------------------------------------------------------------------- 1 | package tools 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 6 | _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 7 | 8 | "go-admin/app/other/models/tools" 9 | ) 10 | 11 | // GetDBColumnList 分页列表数据 12 | // @Summary 分页列表数据 / page list data 13 | // @Description 数据库表列分页列表 / database table column page list 14 | // @Tags 工具 / 生成工具 15 | // @Param tableName query string false "tableName / 数据表名称" 16 | // @Param pageSize query int false "pageSize / 页条数" 17 | // @Param pageIndex query int false "pageIndex / 页码" 18 | // @Success 200 {object} response.Response "{"code": 200, "data": [...]}" 19 | // @Router /api/v1/db/columns/page [get] 20 | func (e Gen) GetDBColumnList(c *gin.Context) { 21 | e.Context = c 22 | log := e.GetLogger() 23 | var data tools.DBColumns 24 | var err error 25 | var pageSize = 10 26 | var pageIndex = 1 27 | 28 | if size := c.Request.FormValue("pageSize"); size != "" { 29 | pageSize, err = pkg.StringToInt(size) 30 | } 31 | 32 | if index := c.Request.FormValue("pageIndex"); index != "" { 33 | pageIndex, err = pkg.StringToInt(index) 34 | } 35 | 36 | db, err := pkg.GetOrm(c) 37 | if err != nil { 38 | log.Errorf("get db connection error, %s", err.Error()) 39 | e.Error(500, err, "数据库连接获取失败") 40 | return 41 | } 42 | 43 | data.TableName = c.Request.FormValue("tableName") 44 | pkg.Assert(data.TableName == "", "table name cannot be empty!", 500) 45 | result, count, err := data.GetPage(db, pageSize, pageIndex) 46 | if err != nil { 47 | log.Errorf("GetPage error, %s", err.Error()) 48 | e.Error(500, err, "") 49 | return 50 | } 51 | e.PageOK(result, count, pageIndex, pageSize, "查询成功") 52 | } 53 | -------------------------------------------------------------------------------- /app/other/apis/tools/db_tables.go: -------------------------------------------------------------------------------- 1 | package tools 2 | 3 | import ( 4 | "errors" 5 | "github.com/gin-gonic/gin" 6 | "github.com/go-admin-team/go-admin-core/sdk/config" 7 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 8 | _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 9 | 10 | "go-admin/app/other/models/tools" 11 | ) 12 | 13 | // GetDBTableList 分页列表数据 14 | // @Summary 分页列表数据 / page list data 15 | // @Description 数据库表分页列表 / database table page list 16 | // @Tags 工具 / 生成工具 17 | // @Param tableName query string false "tableName / 数据表名称" 18 | // @Param pageSize query int false "pageSize / 页条数" 19 | // @Param pageIndex query int false "pageIndex / 页码" 20 | // @Success 200 {object} response.Response "{"code": 200, "data": [...]}" 21 | // @Router /api/v1/db/tables/page [get] 22 | func (e Gen) GetDBTableList(c *gin.Context) { 23 | //var res response.Response 24 | var data tools.DBTables 25 | var err error 26 | var pageSize = 10 27 | var pageIndex = 1 28 | e.Context = c 29 | log := e.GetLogger() 30 | if config.DatabaseConfig.Driver == "sqlite3" || config.DatabaseConfig.Driver == "postgres" { 31 | err = errors.New("对不起,sqlite3 或 postgres 不支持代码生成!") 32 | log.Warn(err) 33 | e.Error(403, err, "") 34 | return 35 | } 36 | 37 | if size := c.Request.FormValue("pageSize"); size != "" { 38 | pageSize, err = pkg.StringToInt(size) 39 | } 40 | 41 | if index := c.Request.FormValue("pageIndex"); index != "" { 42 | pageIndex, err = pkg.StringToInt(index) 43 | } 44 | 45 | db, err := pkg.GetOrm(c) 46 | if err != nil { 47 | log.Errorf("get db connection error, %s", err.Error()) 48 | e.Error(500, err, "数据库连接获取失败") 49 | return 50 | } 51 | 52 | data.TableName = c.Request.FormValue("tableName") 53 | result, count, err := data.GetPage(db, pageSize, pageIndex) 54 | if err != nil { 55 | log.Errorf("GetPage error, %s", err.Error()) 56 | e.Error(500, err, "") 57 | return 58 | } 59 | e.PageOK(result, count, pageIndex, pageSize, "查询成功") 60 | } 61 | -------------------------------------------------------------------------------- /app/other/models/tools/db_columns.go: -------------------------------------------------------------------------------- 1 | package tools 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/go-admin-team/go-admin-core/sdk/config" 7 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 8 | "gorm.io/gorm" 9 | ) 10 | 11 | type DBColumns struct { 12 | TableSchema string `gorm:"column:TABLE_SCHEMA" json:"tableSchema"` 13 | TableName string `gorm:"column:TABLE_NAME" json:"tableName"` 14 | ColumnName string `gorm:"column:COLUMN_NAME" json:"columnName"` 15 | ColumnDefault string `gorm:"column:COLUMN_DEFAULT" json:"columnDefault"` 16 | IsNullable string `gorm:"column:IS_NULLABLE" json:"isNullable"` 17 | DataType string `gorm:"column:DATA_TYPE" json:"dataType"` 18 | CharacterMaximumLength string `gorm:"column:CHARACTER_MAXIMUM_LENGTH" json:"characterMaximumLength"` 19 | CharacterSetName string `gorm:"column:CHARACTER_SET_NAME" json:"characterSetName"` 20 | ColumnType string `gorm:"column:COLUMN_TYPE" json:"columnType"` 21 | ColumnKey string `gorm:"column:COLUMN_KEY" json:"columnKey"` 22 | Extra string `gorm:"column:EXTRA" json:"extra"` 23 | ColumnComment string `gorm:"column:COLUMN_COMMENT" json:"columnComment"` 24 | } 25 | 26 | func (e *DBColumns) GetPage(tx *gorm.DB, pageSize int, pageIndex int) ([]DBColumns, int, error) { 27 | var doc []DBColumns 28 | var count int64 29 | table := new(gorm.DB) 30 | 31 | if config.DatabaseConfig.Driver == "mysql" { 32 | table = tx.Table("information_schema.`COLUMNS`") 33 | table = table.Where("table_schema= ? ", config.GenConfig.DBName) 34 | 35 | if e.TableName != "" { 36 | return nil, 0, errors.New("table name cannot be empty!") 37 | } 38 | 39 | table = table.Where("TABLE_NAME = ?", e.TableName) 40 | } 41 | 42 | if err := table.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Offset(-1).Limit(-1).Count(&count).Error; err != nil { 43 | return nil, 0, err 44 | } 45 | //table.Count(&count) 46 | return doc, int(count), nil 47 | 48 | } 49 | 50 | func (e *DBColumns) GetList(tx *gorm.DB) ([]DBColumns, error) { 51 | var doc []DBColumns 52 | table := new(gorm.DB) 53 | 54 | if e.TableName == "" { 55 | return nil, errors.New("table name cannot be empty!") 56 | } 57 | 58 | if config.DatabaseConfig.Driver == "mysql" { 59 | table = tx.Table("information_schema.columns") 60 | table = table.Where("table_schema= ? ", config.GenConfig.DBName) 61 | 62 | table = table.Where("TABLE_NAME = ?", e.TableName).Order("ORDINAL_POSITION asc") 63 | } else { 64 | pkg.Assert(true, "目前只支持mysql数据库", 500) 65 | } 66 | if err := table.Find(&doc).Error; err != nil { 67 | return doc, err 68 | } 69 | return doc, nil 70 | } -------------------------------------------------------------------------------- /app/other/models/tools/db_tables.go: -------------------------------------------------------------------------------- 1 | package tools 2 | 3 | import ( 4 | "errors" 5 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 6 | 7 | "gorm.io/gorm" 8 | 9 | config2 "github.com/go-admin-team/go-admin-core/sdk/config" 10 | ) 11 | 12 | type DBTables struct { 13 | TableName string `gorm:"column:TABLE_NAME" json:"tableName"` 14 | Engine string `gorm:"column:ENGINE" json:"engine"` 15 | TableRows string `gorm:"column:TABLE_ROWS" json:"tableRows"` 16 | TableCollation string `gorm:"column:TABLE_COLLATION" json:"tableCollation"` 17 | CreateTime string `gorm:"column:CREATE_TIME" json:"createTime"` 18 | UpdateTime string `gorm:"column:UPDATE_TIME" json:"updateTime"` 19 | TableComment string `gorm:"column:TABLE_COMMENT" json:"tableComment"` 20 | } 21 | 22 | func (e *DBTables) GetPage(tx *gorm.DB, pageSize int, pageIndex int) ([]DBTables, int, error) { 23 | var doc []DBTables 24 | table := new(gorm.DB) 25 | var count int64 26 | 27 | if config2.DatabaseConfig.Driver == "mysql" { 28 | table = tx.Table("information_schema.tables") 29 | table = table.Where("TABLE_NAME not in (select table_name from `" + config2.GenConfig.DBName + "`.sys_tables) ") 30 | table = table.Where("table_schema= ? ", config2.GenConfig.DBName) 31 | 32 | if e.TableName != "" { 33 | table = table.Where("TABLE_NAME = ?", e.TableName) 34 | } 35 | if err := table.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Offset(-1).Limit(-1).Count(&count).Error; err != nil { 36 | return nil, 0, err 37 | } 38 | } else { 39 | pkg.Assert(true, "目前只支持mysql数据库", 500) 40 | } 41 | 42 | //table.Count(&count) 43 | return doc, int(count), nil 44 | } 45 | 46 | func (e *DBTables) Get(tx *gorm.DB) (DBTables, error) { 47 | var doc DBTables 48 | if config2.DatabaseConfig.Driver == "mysql" { 49 | table := tx.Table("information_schema.tables") 50 | table = table.Where("table_schema= ? ", config2.GenConfig.DBName) 51 | if e.TableName == "" { 52 | return doc, errors.New("table name cannot be empty!") 53 | } 54 | table = table.Where("TABLE_NAME = ?", e.TableName) 55 | if err := table.First(&doc).Error; err != nil { 56 | return doc, err 57 | } 58 | } else { 59 | pkg.Assert(true, "目前只支持mysql数据库", 500) 60 | } 61 | return doc, nil 62 | } 63 | -------------------------------------------------------------------------------- /app/other/router/file.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "go-admin/app/other/apis" 7 | ) 8 | 9 | func init() { 10 | routerCheckRole = append(routerCheckRole, registerFileRouter) 11 | } 12 | 13 | // 需认证的路由代码 14 | func registerFileRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 15 | var api = apis.File{} 16 | r := v1.Group("").Use(authMiddleware.MiddlewareFunc()) 17 | { 18 | r.POST("/public/uploadFile", api.UploadFile) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/other/router/gen_router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "go-admin/app/admin/apis" 7 | "go-admin/app/other/apis/tools" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, sysNoCheckRoleRouter, registerDBRouter, registerSysTableRouter) 12 | } 13 | 14 | func sysNoCheckRoleRouter(v1 *gin.RouterGroup ,authMiddleware *jwt.GinJWTMiddleware) { 15 | r1 := v1.Group("") 16 | { 17 | sys := apis.System{} 18 | r1.GET("/captcha", sys.GenerateCaptchaHandler) 19 | } 20 | 21 | r := v1.Group("").Use(authMiddleware.MiddlewareFunc()) 22 | { 23 | gen := tools.Gen{} 24 | r.GET("/gen/preview/:tableId", gen.Preview) 25 | r.GET("/gen/toproject/:tableId", gen.GenCode) 26 | r.GET("/gen/apitofile/:tableId", gen.GenApiToFile) 27 | r.GET("/gen/todb/:tableId", gen.GenMenuAndApi) 28 | sysTable := tools.SysTable{} 29 | r.GET("/gen/tabletree", sysTable.GetSysTablesTree) 30 | } 31 | } 32 | 33 | func registerDBRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 34 | db := v1.Group("/db").Use(authMiddleware.MiddlewareFunc()) 35 | { 36 | gen := tools.Gen{} 37 | db.GET("/tables/page", gen.GetDBTableList) 38 | db.GET("/columns/page", gen.GetDBColumnList) 39 | } 40 | } 41 | 42 | func registerSysTableRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 43 | tables := v1.Group("/sys/tables") 44 | { 45 | sysTable := tools.SysTable{} 46 | tables.Group("").Use(authMiddleware.MiddlewareFunc()).GET("/page", sysTable.GetPage) 47 | tablesInfo := tables.Group("/info").Use(authMiddleware.MiddlewareFunc()) 48 | { 49 | tablesInfo.POST("", sysTable.Insert) 50 | tablesInfo.PUT("", sysTable.Update) 51 | tablesInfo.DELETE("/:tableId", sysTable.Delete) 52 | tablesInfo.GET("/:tableId", sysTable.Get) 53 | tablesInfo.GET("", sysTable.GetSysTablesInfo) 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /app/other/router/init_router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/gin-gonic/gin" 7 | log "github.com/go-admin-team/go-admin-core/logger" 8 | "github.com/go-admin-team/go-admin-core/sdk" 9 | common "go-admin/common/middleware" 10 | ) 11 | 12 | // InitRouter 路由初始化,不要怀疑,这里用到了 13 | func InitRouter() { 14 | var r *gin.Engine 15 | h := sdk.Runtime.GetEngine() 16 | if h == nil { 17 | log.Fatal("not found engine...") 18 | os.Exit(-1) 19 | } 20 | switch h.(type) { 21 | case *gin.Engine: 22 | r = h.(*gin.Engine) 23 | default: 24 | log.Fatal("not support other engine") 25 | os.Exit(-1) 26 | } 27 | // the jwt middleware 28 | authMiddleware, err := common.AuthInit() 29 | if err != nil { 30 | log.Fatalf("JWT Init Error, %s", err.Error()) 31 | } 32 | 33 | // 注册业务路由 34 | // TODO: 这里可存放业务路由,里边并无实际路由只有演示代码 35 | initRouter(r, authMiddleware) 36 | } 37 | -------------------------------------------------------------------------------- /app/other/router/monitor.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/go-admin-team/go-admin-core/tools/transfer" 8 | "github.com/prometheus/client_golang/prometheus/promhttp" 9 | ) 10 | 11 | func init() { 12 | routerNoCheckRole = append(routerNoCheckRole, registerMonitorRouter) 13 | } 14 | 15 | // 需认证的路由代码 16 | func registerMonitorRouter(v1 *gin.RouterGroup) { 17 | v1.GET("/metrics", transfer.Handler(promhttp.Handler())) 18 | //健康检查 19 | v1.GET("/health", func(c *gin.Context) { 20 | c.Status(http.StatusOK) 21 | }) 22 | 23 | } -------------------------------------------------------------------------------- /app/other/router/router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | ) 7 | 8 | var ( 9 | routerNoCheckRole = make([]func(*gin.RouterGroup), 0) 10 | routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0) 11 | ) 12 | 13 | // initRouter 路由示例 14 | func initRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine { 15 | 16 | // 无需认证的路由 17 | noCheckRoleRouter(r) 18 | // 需要认证的路由 19 | checkRoleRouter(r, authMiddleware) 20 | 21 | return r 22 | } 23 | 24 | // noCheckRoleRouter 无需认证的路由示例 25 | func noCheckRoleRouter(r *gin.Engine) { 26 | // 可根据业务需求来设置接口版本 27 | v1 := r.Group("/api/v1") 28 | 29 | for _, f := range routerNoCheckRole { 30 | f(v1) 31 | } 32 | } 33 | 34 | // checkRoleRouter 需要认证的路由示例 35 | func checkRoleRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) { 36 | // 可根据业务需求来设置接口版本 37 | v1 := r.Group("/api/v1") 38 | 39 | for _, f := range routerCheckRole { 40 | f(v1, authMiddleware) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/other/router/sys_server_monitor.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "go-admin/app/other/apis" 7 | "go-admin/common/middleware" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, registerSysServerMonitorRouter) 12 | } 13 | 14 | // 需认证的路由代码 15 | func registerSysServerMonitorRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 16 | api := apis.ServerMonitor{} 17 | r := v1.Group("/server-monitor").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 18 | { 19 | r.GET("", api.ServerInfo) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/other/service/dto/sys_tables.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type SysTableSearch struct { 4 | TBName string `form:"tableName" search:"type:exact;column:table_name;table:table_name"` 5 | TableComment string `form:"tableComment" search:"type:icontains;column:table_comment;table:table_comment"` 6 | } 7 | -------------------------------------------------------------------------------- /cmd/api/jobs.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "go-admin/app/jobs/router" 4 | 5 | func init() { 6 | //注册路由 fixme 其他应用的路由,在本目录新建文件放在init方法 7 | AppRouters = append(AppRouters, router.InitRouter) 8 | } 9 | -------------------------------------------------------------------------------- /cmd/api/other.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "go-admin/app/other/router" 4 | 5 | func init() { 6 | //注册路由 fixme 其他应用的路由,在本目录新建文件放在init方法 7 | AppRouters = append(AppRouters, router.InitRouter) 8 | } 9 | -------------------------------------------------------------------------------- /cmd/app/server.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "fmt" 7 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 8 | "github.com/go-admin-team/go-admin-core/sdk/pkg/utils" 9 | "github.com/spf13/cobra" 10 | "text/template" 11 | ) 12 | 13 | var ( 14 | appName string 15 | StartCmd = &cobra.Command{ 16 | Use: "app", 17 | Short: "Create a new app", 18 | Long: "Use when you need to create a new app", 19 | Example: "go-admin app -n admin", 20 | Run: func(cmd *cobra.Command, args []string) { 21 | run() 22 | }, 23 | } 24 | ) 25 | 26 | func init() { 27 | StartCmd.PersistentFlags().StringVarP(&appName, "name", "n", "", "Start server with provided configuration file") 28 | } 29 | 30 | func run() { 31 | 32 | fmt.Println(`start init`) 33 | //1. 读取配置 34 | 35 | fmt.Println(`generate migration file`) 36 | _ = genFile() 37 | 38 | } 39 | 40 | func genFile() error { 41 | if appName == "" { 42 | return errors.New("arg `name` invalid :name is empty") 43 | } 44 | path := "app/" 45 | appPath := path + appName 46 | err := utils.IsNotExistMkDir(appPath) 47 | if err != nil { 48 | return err 49 | } 50 | apiPath := appPath + "/apis/" 51 | err = utils.IsNotExistMkDir(apiPath) 52 | if err != nil { 53 | return err 54 | } 55 | modelsPath := appPath + "/models/" 56 | err = utils.IsNotExistMkDir(modelsPath) 57 | if err != nil { 58 | return err 59 | } 60 | routerPath := appPath + "/router/" 61 | err = utils.IsNotExistMkDir(routerPath) 62 | if err != nil { 63 | return err 64 | } 65 | servicePath := appPath + "/service/" 66 | err = utils.IsNotExistMkDir(servicePath) 67 | if err != nil { 68 | return err 69 | } 70 | dtoPath := appPath + "/service/dto/" 71 | err = utils.IsNotExistMkDir(dtoPath) 72 | if err != nil { 73 | return err 74 | } 75 | 76 | t1, err := template.ParseFiles("template/cmd_api.template") 77 | if err != nil { 78 | return err 79 | } 80 | m := map[string]string{} 81 | m["appName"] = appName 82 | var b1 bytes.Buffer 83 | err = t1.Execute(&b1, m) 84 | pkg.FileCreate(b1, "./cmd/api/"+appName+".go") 85 | t2, err := template.ParseFiles("template/router.template") 86 | var b2 bytes.Buffer 87 | err = t2.Execute(&b2, nil) 88 | pkg.FileCreate(b2, appPath+"/router/router.go") 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /cmd/cobra.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 7 | "go-admin/cmd/app" 8 | "go-admin/common/global" 9 | "os" 10 | 11 | "github.com/spf13/cobra" 12 | 13 | "go-admin/cmd/api" 14 | "go-admin/cmd/config" 15 | "go-admin/cmd/migrate" 16 | "go-admin/cmd/version" 17 | ) 18 | 19 | var rootCmd = &cobra.Command{ 20 | Use: "go-admin", 21 | Short: "go-admin", 22 | SilenceUsage: true, 23 | Long: `go-admin`, 24 | Args: func(cmd *cobra.Command, args []string) error { 25 | if len(args) < 1 { 26 | tip() 27 | return errors.New(pkg.Red("requires at least one arg")) 28 | } 29 | return nil 30 | }, 31 | PersistentPreRunE: func(*cobra.Command, []string) error { return nil }, 32 | Run: func(cmd *cobra.Command, args []string) { 33 | tip() 34 | }, 35 | } 36 | 37 | func tip() { 38 | usageStr := `欢迎使用 ` + pkg.Green(`go-admin `+global.Version) + ` 可以使用 ` + pkg.Red(`-h`) + ` 查看命令` 39 | usageStr1 := `也可以参考 https://doc.go-admin.dev/guide/ksks 的相关内容` 40 | fmt.Printf("%s\n", usageStr) 41 | fmt.Printf("%s\n", usageStr1) 42 | } 43 | 44 | func init() { 45 | rootCmd.AddCommand(api.StartCmd) 46 | rootCmd.AddCommand(migrate.StartCmd) 47 | rootCmd.AddCommand(version.StartCmd) 48 | rootCmd.AddCommand(config.StartCmd) 49 | rootCmd.AddCommand(app.StartCmd) 50 | } 51 | 52 | //Execute : apply commands 53 | func Execute() { 54 | if err := rootCmd.Execute(); err != nil { 55 | os.Exit(-1) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /cmd/config/server.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | 7 | "github.com/go-admin-team/go-admin-core/config/source/file" 8 | "github.com/spf13/cobra" 9 | 10 | "github.com/go-admin-team/go-admin-core/sdk/config" 11 | ) 12 | 13 | var ( 14 | configYml string 15 | StartCmd = &cobra.Command{ 16 | Use: "config", 17 | Short: "Get Application config info", 18 | Example: "go-admin config -c config/settings.yml", 19 | Run: func(cmd *cobra.Command, args []string) { 20 | run() 21 | }, 22 | } 23 | ) 24 | 25 | func init() { 26 | StartCmd.PersistentFlags().StringVarP(&configYml, "config", "c", "config/settings.yml", "Start server with provided configuration file") 27 | } 28 | 29 | func run() { 30 | config.Setup(file.NewSource(file.WithPath(configYml))) 31 | 32 | application, errs := json.MarshalIndent(config.ApplicationConfig, "", " ") //转换成JSON返回的是byte[] 33 | if errs != nil { 34 | fmt.Println(errs.Error()) 35 | } 36 | fmt.Println("application:", string(application)) 37 | 38 | jwt, errs := json.MarshalIndent(config.JwtConfig, "", " ") //转换成JSON返回的是byte[] 39 | if errs != nil { 40 | fmt.Println(errs.Error()) 41 | } 42 | fmt.Println("jwt:", string(jwt)) 43 | 44 | // todo 需要兼容 45 | database, errs := json.MarshalIndent(config.DatabasesConfig, "", " ") //转换成JSON返回的是byte[] 46 | if errs != nil { 47 | fmt.Println(errs.Error()) 48 | } 49 | fmt.Println("database:", string(database)) 50 | 51 | gen, errs := json.MarshalIndent(config.GenConfig, "", " ") //转换成JSON返回的是byte[] 52 | if errs != nil { 53 | fmt.Println(errs.Error()) 54 | } 55 | fmt.Println("gen:", string(gen)) 56 | 57 | loggerConfig, errs := json.MarshalIndent(config.LoggerConfig, "", " ") //转换成JSON返回的是byte[] 58 | if errs != nil { 59 | fmt.Println(errs.Error()) 60 | } 61 | fmt.Println("logger:", string(loggerConfig)) 62 | 63 | } 64 | -------------------------------------------------------------------------------- /cmd/migrate/migration/init.go: -------------------------------------------------------------------------------- 1 | package migration 2 | 3 | import ( 4 | "log" 5 | "path/filepath" 6 | "sort" 7 | "sync" 8 | 9 | "gorm.io/gorm" 10 | ) 11 | 12 | var Migrate = &Migration{ 13 | version: make(map[string]func(db *gorm.DB, version string) error), 14 | } 15 | 16 | type Migration struct { 17 | db *gorm.DB 18 | version map[string]func(db *gorm.DB, version string) error 19 | mutex sync.Mutex 20 | } 21 | 22 | func (e *Migration) GetDb() *gorm.DB { 23 | return e.db 24 | } 25 | 26 | func (e *Migration) SetDb(db *gorm.DB) { 27 | e.db = db 28 | } 29 | 30 | func (e *Migration) SetVersion(k string, f func(db *gorm.DB, version string) error) { 31 | e.mutex.Lock() 32 | defer e.mutex.Unlock() 33 | e.version[k] = f 34 | } 35 | 36 | func (e *Migration) Migrate() { 37 | versions := make([]string, 0) 38 | for k := range e.version { 39 | versions = append(versions, k) 40 | } 41 | if !sort.StringsAreSorted(versions) { 42 | sort.Strings(versions) 43 | } 44 | var err error 45 | var count int64 46 | for _, v := range versions { 47 | err = e.db.Table("sys_migration").Where("version = ?", v).Count(&count).Error 48 | if err != nil { 49 | log.Fatalln(err) 50 | } 51 | if count > 0 { 52 | log.Println(count) 53 | count = 0 54 | continue 55 | } 56 | err = (e.version[v])(e.db.Debug(), v) 57 | if err != nil { 58 | log.Fatalln(err) 59 | } 60 | } 61 | } 62 | 63 | func GetFilename(s string) string { 64 | s = filepath.Base(s) 65 | return s[:13] 66 | } 67 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/by.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "time" 5 | 6 | "gorm.io/gorm" 7 | ) 8 | 9 | type ControlBy struct { 10 | CreateBy int `json:"createBy" gorm:"index;comment:创建者"` 11 | UpdateBy int `json:"updateBy" gorm:"index;comment:更新者"` 12 | } 13 | 14 | type Model struct { 15 | Id int `json:"id" gorm:"primaryKey;autoIncrement;comment:主键编码"` 16 | } 17 | 18 | type ModelTime struct { 19 | CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"` 20 | UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"` 21 | DeletedAt gorm.DeletedAt `json:"-" gorm:"index;comment:删除时间"` 22 | } 23 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/casbin_rule.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | // CasbinRule sys_casbin_rule 4 | type CasbinRule struct { 5 | ID uint `gorm:"primaryKey;autoIncrement"` 6 | Ptype string `gorm:"size:512;uniqueIndex:unique_index"` 7 | V0 string `gorm:"size:512;uniqueIndex:unique_index"` 8 | V1 string `gorm:"size:512;uniqueIndex:unique_index"` 9 | V2 string `gorm:"size:512;uniqueIndex:unique_index"` 10 | V3 string `gorm:"size:512;uniqueIndex:unique_index"` 11 | V4 string `gorm:"size:512;uniqueIndex:unique_index"` 12 | V5 string `gorm:"size:512;uniqueIndex:unique_index"` 13 | } 14 | 15 | func (CasbinRule) TableName() string { 16 | return "sys_casbin_rule" 17 | } 18 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/initdb.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "fmt" 5 | "go-admin/common/global" 6 | "io/ioutil" 7 | "log" 8 | "strings" 9 | 10 | "gorm.io/gorm" 11 | ) 12 | 13 | func InitDb(db *gorm.DB) (err error) { 14 | filePath := "config/db.sql" 15 | if global.Driver == "postgres" { 16 | filePath := "config/db.sql" 17 | if err = ExecSql(db, filePath); err != nil { 18 | return err 19 | } 20 | filePath = "config/pg.sql" 21 | err = ExecSql(db, filePath) 22 | } else if global.Driver == "mysql" { 23 | filePath = "config/db-begin-mysql.sql" 24 | if err = ExecSql(db, filePath); err != nil { 25 | return err 26 | } 27 | filePath = "config/db.sql" 28 | if err = ExecSql(db, filePath); err != nil { 29 | return err 30 | } 31 | filePath = "config/db-end-mysql.sql" 32 | err = ExecSql(db, filePath) 33 | } else { 34 | err = ExecSql(db, filePath) 35 | } 36 | return err 37 | } 38 | 39 | func ExecSql(db *gorm.DB, filePath string) error { 40 | sql, err := Ioutil(filePath) 41 | if err != nil { 42 | fmt.Println("数据库基础数据初始化脚本读取失败!原因:", err.Error()) 43 | return err 44 | } 45 | sqlList := strings.Split(sql, ";") 46 | for i := 0; i < len(sqlList)-1; i++ { 47 | if strings.Contains(sqlList[i], "--") { 48 | fmt.Println(sqlList[i]) 49 | continue 50 | } 51 | sql := strings.Replace(sqlList[i]+";", "\n", "", -1) 52 | sql = strings.TrimSpace(sql) 53 | if err = db.Exec(sql).Error; err != nil { 54 | log.Printf("error sql: %s", sql) 55 | if !strings.Contains(err.Error(), "Query was empty") { 56 | return err 57 | } 58 | } 59 | } 60 | return nil 61 | } 62 | 63 | func Ioutil(filePath string) (string, error) { 64 | if contents, err := ioutil.ReadFile(filePath); err == nil { 65 | //因为contents是[]byte类型,直接转换成string类型后会多一行空格,需要使用strings.Replace替换换行符 66 | result := strings.Replace(string(contents), "\n", "", 1) 67 | fmt.Println("Use ioutil.ReadFile to read a file:", result) 68 | return result, nil 69 | } else { 70 | return "", err 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/model.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type BaseModel struct { 8 | CreatedAt time.Time `json:"createdAt"` 9 | UpdatedAt time.Time `json:"updatedAt"` 10 | DeletedAt *time.Time `json:"deletedAt"` 11 | } 12 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/role_dept.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysRoleDept struct { 4 | RoleId int `gorm:"size:11;primaryKey"` 5 | DeptId int `gorm:"size:11;primaryKey"` 6 | } 7 | 8 | func (SysRoleDept) TableName() string { 9 | return "sys_role_dept" 10 | } 11 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_api.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysApi struct { 4 | Id int `json:"id" gorm:"primaryKey;autoIncrement;comment:主键编码"` 5 | Handle string `json:"handle" gorm:"size:128;comment:handle"` 6 | Title string `json:"title" gorm:"size:128;comment:标题"` 7 | Path string `json:"path" gorm:"size:128;comment:地址"` 8 | Type string `json:"type" gorm:"size:16;comment:接口类型"` 9 | Action string `json:"action" gorm:"size:16;comment:请求类型"` 10 | ModelTime 11 | ControlBy 12 | } 13 | 14 | func (SysApi) TableName() string { 15 | return "sys_api" 16 | } -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_columns.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysColumns struct { 4 | ColumnId int `gorm:"primaryKey;autoIncrement" json:"columnId"` 5 | TableId int `gorm:"" json:"tableId"` 6 | ColumnName string `gorm:"size:128;" json:"columnName"` 7 | ColumnComment string `gorm:"column:column_comment;size:128;" json:"columnComment"` 8 | ColumnType string `gorm:"column:column_type;size:128;" json:"columnType"` 9 | GoType string `gorm:"column:go_type;size:128;" json:"goType"` 10 | GoField string `gorm:"column:go_field;size:128;" json:"goField"` 11 | JsonField string `gorm:"column:json_field;size:128;" json:"jsonField"` 12 | IsPk string `gorm:"column:is_pk;size:4;" json:"isPk"` 13 | IsIncrement string `gorm:"column:is_increment;size:4;" json:"isIncrement"` 14 | IsRequired string `gorm:"column:is_required;size:4;" json:"isRequired"` 15 | IsInsert string `gorm:"column:is_insert;size:4;" json:"isInsert"` 16 | IsEdit string `gorm:"column:is_edit;size:4;" json:"isEdit"` 17 | IsList string `gorm:"column:is_list;size:4;" json:"isList"` 18 | IsQuery string `gorm:"column:is_query;size:4;" json:"isQuery"` 19 | QueryType string `gorm:"column:query_type;size:128;" json:"queryType"` 20 | HtmlType string `gorm:"column:html_type;size:128;" json:"htmlType"` 21 | DictType string `gorm:"column:dict_type;size:128;" json:"dictType"` 22 | Sort int `gorm:"column:sort;" json:"sort"` 23 | List string `gorm:"column:list;size:1;" json:"list"` 24 | Pk bool `gorm:"column:pk;size:1;" json:"pk"` 25 | Required bool `gorm:"column:required;size:1;" json:"required"` 26 | SuperColumn bool `gorm:"column:super_column;size:1;" json:"superColumn"` 27 | UsableColumn bool `gorm:"column:usable_column;size:1;" json:"usableColumn"` 28 | Increment bool `gorm:"column:increment;size:1;" json:"increment"` 29 | Insert bool `gorm:"column:insert;size:1;" json:"insert"` 30 | Edit bool `gorm:"column:edit;size:1;" json:"edit"` 31 | Query bool `gorm:"column:query;size:1;" json:"query"` 32 | Remark string `gorm:"column:remark;size:255;" json:"remark"` 33 | FkTableName string `gorm:"" json:"fkTableName"` 34 | FkTableNameClass string `gorm:"" json:"fkTableNameClass"` 35 | FkTableNamePackage string `gorm:"" json:"fkTableNamePackage"` 36 | FkLabelId string `gorm:"" json:"fkLabelId"` 37 | FkLabelName string `gorm:"size:255;" json:"fkLabelName"` 38 | ModelTime 39 | ControlBy 40 | } 41 | 42 | func (SysColumns) TableName() string { 43 | return "sys_columns" 44 | } 45 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_config.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysConfig struct { 4 | Model 5 | ConfigName string `json:"configName" gorm:"type:varchar(128);comment:ConfigName"` 6 | ConfigKey string `json:"configKey" gorm:"type:varchar(128);comment:ConfigKey"` 7 | ConfigValue string `json:"configValue" gorm:"type:varchar(255);comment:ConfigValue"` 8 | ConfigType string `json:"configType" gorm:"type:varchar(64);comment:ConfigType"` 9 | IsFrontend int `json:"isFrontend" gorm:"type:varchar(64);comment:是否前台"` 10 | Remark string `json:"remark" gorm:"type:varchar(128);comment:Remark"` 11 | ControlBy 12 | ModelTime 13 | } 14 | 15 | func (SysConfig) TableName() string { 16 | return "sys_config" 17 | } 18 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_dept.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysDept struct { 4 | DeptId int `json:"deptId" gorm:"primaryKey;autoIncrement;"` //部门编码 5 | ParentId int `json:"parentId" gorm:""` //上级部门 6 | DeptPath string `json:"deptPath" gorm:"size:255;"` // 7 | DeptName string `json:"deptName" gorm:"size:128;"` //部门名称 8 | Sort int `json:"sort" gorm:"size:4;"` //排序 9 | Leader string `json:"leader" gorm:"size:128;"` //负责人 10 | Phone string `json:"phone" gorm:"size:11;"` //手机 11 | Email string `json:"email" gorm:"size:64;"` //邮箱 12 | Status int `json:"status" gorm:"size:4;"` //状态 13 | ControlBy 14 | ModelTime 15 | } 16 | 17 | func (SysDept) TableName() string { 18 | return "sys_dept" 19 | } 20 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_dict_data.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type DictData struct { 4 | DictCode int `gorm:"primaryKey;autoIncrement;" json:"dictCode" example:"1"` //字典编码 5 | DictSort int `gorm:"" json:"dictSort"` //显示顺序 6 | DictLabel string `gorm:"size:128;" json:"dictLabel"` //数据标签 7 | DictValue string `gorm:"size:255;" json:"dictValue"` //数据键值 8 | DictType string `gorm:"size:64;" json:"dictType"` //字典类型 9 | CssClass string `gorm:"size:128;" json:"cssClass"` // 10 | ListClass string `gorm:"size:128;" json:"listClass"` // 11 | IsDefault string `gorm:"size:8;" json:"isDefault"` // 12 | Status int `gorm:"size:4;" json:"status"` //状态 13 | Default string `gorm:"size:8;" json:"default"` // 14 | Remark string `gorm:"size:255;" json:"remark"` //备注 15 | ControlBy 16 | ModelTime 17 | } 18 | 19 | func (DictData) TableName() string { 20 | return "sys_dict_data" 21 | } 22 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_dict_type.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type DictType struct { 4 | DictId int `gorm:"primaryKey;autoIncrement;" json:"dictId"` 5 | DictName string `gorm:"size:128;" json:"dictName"` //字典名称 6 | DictType string `gorm:"size:128;" json:"dictType"` //字典类型 7 | Status int `gorm:"size:4;" json:"status"` //状态 8 | Remark string `gorm:"size:255;" json:"remark"` //备注 9 | ControlBy 10 | ModelTime 11 | } 12 | 13 | func (DictType) TableName() string { 14 | return "sys_dict_type" 15 | } 16 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_job.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysJob struct { 4 | JobId int `json:"jobId" gorm:"primaryKey;autoIncrement"` // 编码 5 | JobName string `json:"jobName" gorm:"size:255;"` // 名称 6 | JobGroup string `json:"jobGroup" gorm:"size:255;"` // 任务分组 7 | JobType int `json:"jobType" gorm:"size:1;"` // 任务类型 8 | CronExpression string `json:"cronExpression" gorm:"size:255;"` // cron表达式 9 | InvokeTarget string `json:"invokeTarget" gorm:"size:255;"` // 调用目标 10 | Args string `json:"args" gorm:"size:255;"` // 目标参数 11 | MisfirePolicy int `json:"misfirePolicy" gorm:"size:255;"` // 执行策略 12 | Concurrent int `json:"concurrent" gorm:"size:1;"` // 是否并发 13 | Status int `json:"status" gorm:"size:1;"` // 状态 14 | EntryId int `json:"entry_id" gorm:"size:11;"` // job启动时返回的id 15 | ModelTime 16 | ControlBy 17 | } 18 | 19 | func (SysJob) TableName() string { 20 | return "sys_job" 21 | } 22 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_login_log.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type SysLoginLog struct { 8 | Model 9 | Username string `json:"username" gorm:"type:varchar(128);comment:用户名"` 10 | Status string `json:"status" gorm:"type:varchar(4);comment:状态"` 11 | Ipaddr string `json:"ipaddr" gorm:"type:varchar(255);comment:ip地址"` 12 | LoginLocation string `json:"loginLocation" gorm:"type:varchar(255);comment:归属地"` 13 | Browser string `json:"browser" gorm:"type:varchar(255);comment:浏览器"` 14 | Os string `json:"os" gorm:"type:varchar(255);comment:系统"` 15 | Platform string `json:"platform" gorm:"type:varchar(255);comment:固件"` 16 | LoginTime time.Time `json:"loginTime" gorm:"type:timestamp;comment:登录时间"` 17 | Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"` 18 | Msg string `json:"msg" gorm:"type:varchar(255);comment:信息"` 19 | CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"` 20 | UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"` 21 | ControlBy 22 | } 23 | 24 | func (SysLoginLog) TableName() string { 25 | return "sys_login_log" 26 | } 27 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_menu.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysMenu struct { 4 | MenuId int `json:"menuId" gorm:"primaryKey;autoIncrement"` 5 | MenuName string `json:"menuName" gorm:"size:128;"` 6 | Title string `json:"title" gorm:"size:128;"` 7 | Icon string `json:"icon" gorm:"size:128;"` 8 | Path string `json:"path" gorm:"size:128;"` 9 | Paths string `json:"paths" gorm:"size:128;"` 10 | MenuType string `json:"menuType" gorm:"size:1;"` 11 | Action string `json:"action" gorm:"size:16;"` 12 | Permission string `json:"permission" gorm:"size:255;"` 13 | ParentId int `json:"parentId" gorm:"size:11;"` 14 | NoCache bool `json:"noCache" gorm:"size:8;"` 15 | Breadcrumb string `json:"breadcrumb" gorm:"size:255;"` 16 | Component string `json:"component" gorm:"size:255;"` 17 | Sort int `json:"sort" gorm:"size:4;"` 18 | Visible string `json:"visible" gorm:"size:1;"` 19 | IsFrame string `json:"isFrame" gorm:"size:1;DEFAULT:0;"` 20 | SysApi []SysApi `json:"sysApi" gorm:"many2many:sys_menu_api_rule"` 21 | ControlBy 22 | ModelTime 23 | } 24 | 25 | func (SysMenu) TableName() string { 26 | return "sys_menu" 27 | } -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_opera_log.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type SysOperaLog struct { 8 | Model 9 | Title string `json:"title" gorm:"type:varchar(255);comment:操作模块"` 10 | BusinessType string `json:"businessType" gorm:"type:varchar(128);comment:操作类型"` 11 | BusinessTypes string `json:"businessTypes" gorm:"type:varchar(128);comment:BusinessTypes"` 12 | Method string `json:"method" gorm:"type:varchar(128);comment:函数"` 13 | RequestMethod string `json:"requestMethod" gorm:"type:varchar(128);comment:请求方式: GET POST PUT DELETE"` 14 | OperatorType string `json:"operatorType" gorm:"type:varchar(128);comment:操作类型"` 15 | OperName string `json:"operName" gorm:"type:varchar(128);comment:操作者"` 16 | DeptName string `json:"deptName" gorm:"type:varchar(128);comment:部门名称"` 17 | OperUrl string `json:"operUrl" gorm:"type:varchar(255);comment:访问地址"` 18 | OperIp string `json:"operIp" gorm:"type:varchar(128);comment:客户端ip"` 19 | OperLocation string `json:"operLocation" gorm:"type:varchar(128);comment:访问位置"` 20 | OperParam string `json:"operParam" gorm:"type:text;comment:请求参数"` 21 | Status string `json:"status" gorm:"type:varchar(4);comment:操作状态 1:正常 2:关闭"` 22 | OperTime time.Time `json:"operTime" gorm:"type:timestamp;comment:操作时间"` 23 | JsonResult string `json:"jsonResult" gorm:"type:varchar(255);comment:返回数据"` 24 | Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"` 25 | LatencyTime string `json:"latencyTime" gorm:"type:varchar(128);comment:耗时"` 26 | UserAgent string `json:"userAgent" gorm:"type:varchar(255);comment:ua"` 27 | CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"` 28 | UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"` 29 | ControlBy 30 | } 31 | 32 | func (SysOperaLog) TableName() string { 33 | return "sys_opera_log" 34 | } 35 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_post.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysPost struct { 4 | PostId int `gorm:"primaryKey;autoIncrement" json:"postId"` //岗位编号 5 | PostName string `gorm:"size:128;" json:"postName"` //岗位名称 6 | PostCode string `gorm:"size:128;" json:"postCode"` //岗位代码 7 | Sort int `gorm:"size:4;" json:"sort"` //岗位排序 8 | Status int `gorm:"size:4;" json:"status"` //状态 9 | Remark string `gorm:"size:255;" json:"remark"` //描述 10 | ControlBy 11 | ModelTime 12 | } 13 | 14 | func (SysPost) TableName() string { 15 | return "sys_post" 16 | } -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_role.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysRole struct { 4 | RoleId int `json:"roleId" gorm:"primaryKey;autoIncrement"` // 角色编码 5 | RoleName string `json:"roleName" gorm:"size:128;"` // 角色名称 6 | Status string `json:"status" gorm:"size:4;"` // 7 | RoleKey string `json:"roleKey" gorm:"size:128;"` //角色代码 8 | RoleSort int `json:"roleSort" gorm:""` //角色排序 9 | Flag string `json:"flag" gorm:"size:128;"` // 10 | Remark string `json:"remark" gorm:"size:255;"` //备注 11 | Admin bool `json:"admin" gorm:"size:4;"` 12 | DataScope string `json:"dataScope" gorm:"size:128;"` 13 | SysMenu []SysMenu `json:"sysMenu" gorm:"many2many:sys_role_menu;foreignKey:RoleId;joinForeignKey:role_id;references:MenuId;joinReferences:menu_id;"` 14 | ControlBy 15 | ModelTime 16 | } 17 | 18 | func (SysRole) TableName() string { 19 | return "sys_role" 20 | } -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_tables.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysTables struct { 4 | TableId int `gorm:"primaryKey;autoIncrement" json:"tableId"` //表编码 5 | TBName string `gorm:"column:table_name;size:255;" json:"tableName"` //表名称 6 | TableComment string `gorm:"size:255;" json:"tableComment"` //表备注 7 | ClassName string `gorm:"size:255;" json:"className"` //类名 8 | TplCategory string `gorm:"size:255;" json:"tplCategory"` // 9 | PackageName string `gorm:"size:255;" json:"packageName"` //包名 10 | ModuleName string `gorm:"size:255;" json:"moduleName"` //go文件名 11 | ModuleFrontName string `gorm:"size:255;comment:前端文件名;" json:"moduleFrontName"` //前端文件名 12 | BusinessName string `gorm:"size:255;" json:"businessName"` // 13 | FunctionName string `gorm:"size:255;" json:"functionName"` //功能名称 14 | FunctionAuthor string `gorm:"size:255;" json:"functionAuthor"` //功能作者 15 | PkColumn string `gorm:"size:255;" json:"pkColumn"` 16 | PkGoField string `gorm:"size:255;" json:"pkGoField"` 17 | PkJsonField string `gorm:"size:255;" json:"pkJsonField"` 18 | Options string `gorm:"size:255;" json:"options"` 19 | TreeCode string `gorm:"size:255;" json:"treeCode"` 20 | TreeParentCode string `gorm:"size:255;" json:"treeParentCode"` 21 | TreeName string `gorm:"size:255;" json:"treeName"` 22 | Tree bool `gorm:"size:1;default:0;" json:"tree"` 23 | Crud bool `gorm:"size:1;default:1;" json:"crud"` 24 | Remark string `gorm:"size:255;" json:"remark"` 25 | IsDataScope int `gorm:"size:1;" json:"isDataScope"` 26 | IsActions int `gorm:"size:1;" json:"isActions"` 27 | IsAuth int `gorm:"size:1;" json:"isAuth"` 28 | IsLogicalDelete string `gorm:"size:1;" json:"isLogicalDelete"` 29 | LogicalDelete bool `gorm:"size:1;" json:"logicalDelete"` 30 | LogicalDeleteColumn string `gorm:"size:128;" json:"logicalDeleteColumn"` 31 | ModelTime 32 | ControlBy 33 | } 34 | 35 | func (SysTables) TableName() string { 36 | return "sys_tables" 37 | } 38 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "golang.org/x/crypto/bcrypt" 5 | "gorm.io/gorm" 6 | ) 7 | 8 | type SysUser struct { 9 | UserId int `gorm:"primaryKey;autoIncrement;comment:编码" json:"userId"` 10 | Username string `json:"username" gorm:"type:varchar(64);comment:用户名"` 11 | Password string `json:"-" gorm:"type:varchar(128);comment:密码"` 12 | NickName string `json:"nickName" gorm:"type:varchar(128);comment:昵称"` 13 | Phone string `json:"phone" gorm:"type:varchar(11);comment:手机号"` 14 | RoleId int `json:"roleId" gorm:"type:bigint;comment:角色ID"` 15 | Salt string `json:"-" gorm:"type:varchar(255);comment:加盐"` 16 | Avatar string `json:"avatar" gorm:"type:varchar(255);comment:头像"` 17 | Sex string `json:"sex" gorm:"type:varchar(255);comment:性别"` 18 | Email string `json:"email" gorm:"type:varchar(128);comment:邮箱"` 19 | DeptId int `json:"deptId" gorm:"type:bigint;comment:部门"` 20 | PostId int `json:"postId" gorm:"type:bigint;comment:岗位"` 21 | Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"` 22 | Status string `json:"status" gorm:"type:varchar(4);comment:状态"` 23 | ControlBy 24 | ModelTime 25 | } 26 | 27 | func (*SysUser) TableName() string { 28 | return "sys_user" 29 | } 30 | 31 | // Encrypt 加密 32 | func (e *SysUser) Encrypt() (err error) { 33 | if e.Password == "" { 34 | return 35 | } 36 | 37 | var hash []byte 38 | if hash, err = bcrypt.GenerateFromPassword([]byte(e.Password), bcrypt.DefaultCost); err != nil { 39 | return 40 | } else { 41 | e.Password = string(hash) 42 | return 43 | } 44 | } 45 | 46 | func (e *SysUser) BeforeCreate(_ *gorm.DB) error { 47 | return e.Encrypt() 48 | } 49 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/tb_demo.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type TbDemo struct { 4 | Model 5 | Name string `json:"name" gorm:"type:varchar(128);comment:名称"` 6 | ModelTime 7 | ControlBy 8 | } 9 | 10 | func (TbDemo) TableName() string { 11 | return "tb_demo" 12 | } 13 | -------------------------------------------------------------------------------- /cmd/migrate/migration/version-local/doc.go: -------------------------------------------------------------------------------- 1 | package version_local 2 | 3 | func init() { 4 | } 5 | 6 | /** 7 | 开发者项目的迁移脚本放在这个目录里,init写法参考version目录里的migrate或者自动生成 8 | */ 9 | -------------------------------------------------------------------------------- /cmd/migrate/migration/version/1599190683659_tables.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "github.com/go-admin-team/go-admin-core/sdk/config" 5 | "runtime" 6 | 7 | "go-admin/cmd/migrate/migration" 8 | "go-admin/cmd/migrate/migration/models" 9 | common "go-admin/common/models" 10 | 11 | "gorm.io/gorm" 12 | ) 13 | 14 | func init() { 15 | _, fileName, _, _ := runtime.Caller(0) 16 | migration.Migrate.SetVersion(migration.GetFilename(fileName), _1599190683659Tables) 17 | } 18 | 19 | func _1599190683659Tables(db *gorm.DB, version string) error { 20 | return db.Transaction(func(tx *gorm.DB) error { 21 | if config.DatabaseConfig.Driver == "mysql" { 22 | tx = tx.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4") 23 | } 24 | err := tx.Migrator().AutoMigrate( 25 | new(models.SysDept), 26 | new(models.SysConfig), 27 | new(models.SysTables), 28 | new(models.SysColumns), 29 | new(models.SysMenu), 30 | new(models.SysLoginLog), 31 | new(models.SysOperaLog), 32 | new(models.SysRoleDept), 33 | new(models.SysUser), 34 | new(models.SysRole), 35 | new(models.SysPost), 36 | new(models.DictData), 37 | new(models.DictType), 38 | new(models.SysJob), 39 | new(models.SysConfig), 40 | new(models.SysApi), 41 | new(models.TbDemo), 42 | ) 43 | if err != nil { 44 | return err 45 | } 46 | if err := models.InitDb(tx); err != nil { 47 | return err 48 | } 49 | return tx.Create(&common.Migration{ 50 | Version: version, 51 | }).Error 52 | }) 53 | } 54 | -------------------------------------------------------------------------------- /cmd/migrate/migration/version/1653638869132_migrate.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "go-admin/cmd/migrate/migration/models" 5 | common "go-admin/common/models" 6 | "gorm.io/gorm" 7 | "runtime" 8 | "strconv" 9 | 10 | "go-admin/cmd/migrate/migration" 11 | ) 12 | 13 | func init() { 14 | _, fileName, _, _ := runtime.Caller(0) 15 | migration.Migrate.SetVersion(migration.GetFilename(fileName), _1653638869132Test) 16 | } 17 | 18 | func _1653638869132Test(db *gorm.DB, version string) error { 19 | return db.Transaction(func(tx *gorm.DB) error { 20 | var list []models.SysMenu 21 | err := tx.Model(&models.SysMenu{}).Order("parent_id,menu_id").Find(&list).Error 22 | if err != nil { 23 | return err 24 | } 25 | for _, v := range list { 26 | if v.ParentId == 0 { 27 | v.Paths = "/0/" + strconv.Itoa(v.MenuId) 28 | } else { 29 | var e models.SysMenu 30 | err = tx.Model(&models.SysMenu{}).Where("menu_id=?", v.ParentId).First(&e).Error 31 | if err != nil { 32 | if err == gorm.ErrRecordNotFound { 33 | continue 34 | } 35 | return err 36 | } 37 | v.Paths = e.Paths + "/" + strconv.Itoa(v.MenuId) 38 | } 39 | err = tx.Model(&v).Update("paths", v.Paths).Error 40 | if err != nil { 41 | return err 42 | } 43 | } 44 | return tx.Create(&common.Migration{ 45 | Version: version, 46 | }).Error 47 | }) 48 | } 49 | -------------------------------------------------------------------------------- /cmd/version/server.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "fmt" 5 | "github.com/spf13/cobra" 6 | "go-admin/common/global" 7 | ) 8 | 9 | var ( 10 | StartCmd = &cobra.Command{ 11 | Use: "version", 12 | Short: "Get version info", 13 | Example: "go-admin version", 14 | PreRun: func(cmd *cobra.Command, args []string) { 15 | 16 | }, 17 | RunE: func(cmd *cobra.Command, args []string) error { 18 | return run() 19 | }, 20 | } 21 | ) 22 | 23 | func run() error { 24 | fmt.Println(global.Version) 25 | return nil 26 | } 27 | -------------------------------------------------------------------------------- /common/actions/create.go: -------------------------------------------------------------------------------- 1 | package actions 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/go-admin-team/go-admin-core/sdk/api" 8 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 9 | "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" 10 | "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 11 | 12 | "go-admin/common/dto" 13 | "go-admin/common/models" 14 | ) 15 | 16 | // CreateAction 通用新增动作 17 | func CreateAction(control dto.Control) gin.HandlerFunc { 18 | return func(c *gin.Context) { 19 | log := api.GetRequestLogger(c) 20 | db, err := pkg.GetOrm(c) 21 | if err != nil { 22 | log.Error(err) 23 | return 24 | } 25 | 26 | //新增操作 27 | req := control.Generate() 28 | err = req.Bind(c) 29 | if err != nil { 30 | response.Error(c, http.StatusUnprocessableEntity, err, err.Error()) 31 | return 32 | } 33 | var object models.ActiveRecord 34 | object, err = req.GenerateM() 35 | if err != nil { 36 | response.Error(c, 500, err, "模型生成失败") 37 | return 38 | } 39 | object.SetCreateBy(user.GetUserId(c)) 40 | err = db.WithContext(c).Create(object).Error 41 | if err != nil { 42 | log.Errorf("Create error: %s", err) 43 | response.Error(c, 500, err, "创建失败") 44 | return 45 | } 46 | response.OK(c, object.GetId(), "创建成功") 47 | c.Next() 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /common/actions/delete.go: -------------------------------------------------------------------------------- 1 | package actions 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | log "github.com/go-admin-team/go-admin-core/logger" 8 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 9 | "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" 10 | "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 11 | 12 | "go-admin/common/dto" 13 | "go-admin/common/models" 14 | ) 15 | 16 | // DeleteAction 通用删除动作 17 | func DeleteAction(control dto.Control) gin.HandlerFunc { 18 | return func(c *gin.Context) { 19 | db, err := pkg.GetOrm(c) 20 | if err != nil { 21 | log.Error(err) 22 | return 23 | } 24 | 25 | msgID := pkg.GenerateMsgIDFromContext(c) 26 | //删除操作 27 | req := control.Generate() 28 | err = req.Bind(c) 29 | if err != nil { 30 | log.Errorf("MsgID[%s] Bind error: %s", msgID, err) 31 | response.Error(c, http.StatusUnprocessableEntity, err, "参数验证失败") 32 | return 33 | } 34 | var object models.ActiveRecord 35 | object, err = req.GenerateM() 36 | if err != nil { 37 | response.Error(c, 500, err, "模型生成失败") 38 | return 39 | } 40 | 41 | object.SetUpdateBy(user.GetUserId(c)) 42 | 43 | //数据权限检查 44 | p := GetPermissionFromContext(c) 45 | 46 | db = db.WithContext(c).Scopes( 47 | Permission(object.TableName(), p), 48 | ).Where(req.GetId()).Delete(object) 49 | if err = db.Error; err != nil { 50 | log.Errorf("MsgID[%s] Delete error: %s", msgID, err) 51 | response.Error(c, 500, err, "删除失败") 52 | return 53 | } 54 | if db.RowsAffected == 0 { 55 | response.Error(c, http.StatusForbidden, nil, "无权删除该数据") 56 | return 57 | } 58 | response.OK(c, object.GetId(), "删除成功") 59 | c.Next() 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /common/actions/index.go: -------------------------------------------------------------------------------- 1 | package actions 2 | 3 | import ( 4 | "errors" 5 | "net/http" 6 | 7 | "github.com/gin-gonic/gin" 8 | log "github.com/go-admin-team/go-admin-core/logger" 9 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 10 | "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 11 | "gorm.io/gorm" 12 | 13 | "go-admin/common/dto" 14 | "go-admin/common/models" 15 | ) 16 | 17 | // IndexAction 通用查询动作 18 | func IndexAction(m models.ActiveRecord, d dto.Index, f func() interface{}) gin.HandlerFunc { 19 | return func(c *gin.Context) { 20 | db, err := pkg.GetOrm(c) 21 | if err != nil { 22 | log.Error(err) 23 | return 24 | } 25 | 26 | msgID := pkg.GenerateMsgIDFromContext(c) 27 | list := f() 28 | object := m.Generate() 29 | req := d.Generate() 30 | var count int64 31 | 32 | //查询列表 33 | err = req.Bind(c) 34 | if err != nil { 35 | response.Error(c, http.StatusUnprocessableEntity, err, "参数验证失败") 36 | return 37 | } 38 | 39 | //数据权限检查 40 | p := GetPermissionFromContext(c) 41 | 42 | err = db.WithContext(c).Model(object). 43 | Scopes( 44 | dto.MakeCondition(req.GetNeedSearch()), 45 | dto.Paginate(req.GetPageSize(), req.GetPageIndex()), 46 | Permission(object.TableName(), p), 47 | ). 48 | Find(list).Limit(-1).Offset(-1). 49 | Count(&count).Error 50 | if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { 51 | log.Errorf("MsgID[%s] Index error: %s", msgID, err) 52 | response.Error(c, 500, err, "查询失败") 53 | return 54 | } 55 | response.PageOK(c, list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") 56 | c.Next() 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /common/actions/type.go: -------------------------------------------------------------------------------- 1 | package actions 2 | 3 | const ( 4 | PermissionKey = "dataPermission" 5 | ) 6 | -------------------------------------------------------------------------------- /common/actions/update.go: -------------------------------------------------------------------------------- 1 | package actions 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | log "github.com/go-admin-team/go-admin-core/logger" 8 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 9 | "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" 10 | "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 11 | 12 | "go-admin/common/dto" 13 | "go-admin/common/models" 14 | ) 15 | 16 | // UpdateAction 通用更新动作 17 | func UpdateAction(control dto.Control) gin.HandlerFunc { 18 | return func(c *gin.Context) { 19 | db, err := pkg.GetOrm(c) 20 | if err != nil { 21 | log.Error(err) 22 | return 23 | } 24 | 25 | msgID := pkg.GenerateMsgIDFromContext(c) 26 | req := control.Generate() 27 | //更新操作 28 | err = req.Bind(c) 29 | if err != nil { 30 | response.Error(c, http.StatusUnprocessableEntity, err, "参数验证失败") 31 | return 32 | } 33 | var object models.ActiveRecord 34 | object, err = req.GenerateM() 35 | if err != nil { 36 | response.Error(c, 500, err, "模型生成失败") 37 | return 38 | } 39 | object.SetUpdateBy(user.GetUserId(c)) 40 | 41 | //数据权限检查 42 | p := GetPermissionFromContext(c) 43 | 44 | db = db.WithContext(c).Scopes( 45 | Permission(object.TableName(), p), 46 | ).Where(req.GetId()).Updates(object) 47 | if err = db.Error; err != nil { 48 | log.Errorf("MsgID[%s] Update error: %s", msgID, err) 49 | response.Error(c, 500, err, "更新失败") 50 | return 51 | } 52 | if db.RowsAffected == 0 { 53 | response.Error(c, http.StatusForbidden, nil, "无权更新该数据") 54 | return 55 | } 56 | response.OK(c, object.GetId(), "更新成功") 57 | c.Next() 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /common/actions/view.go: -------------------------------------------------------------------------------- 1 | package actions 2 | 3 | import ( 4 | "errors" 5 | "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 6 | "net/http" 7 | 8 | "github.com/gin-gonic/gin" 9 | log "github.com/go-admin-team/go-admin-core/logger" 10 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 11 | "gorm.io/gorm" 12 | 13 | "go-admin/common/dto" 14 | "go-admin/common/models" 15 | ) 16 | 17 | // ViewAction 通用详情动作 18 | func ViewAction(control dto.Control, f func() interface{}) gin.HandlerFunc { 19 | return func(c *gin.Context) { 20 | db, err := pkg.GetOrm(c) 21 | if err != nil { 22 | log.Error(err) 23 | return 24 | } 25 | 26 | msgID := pkg.GenerateMsgIDFromContext(c) 27 | //查看详情 28 | req := control.Generate() 29 | err = req.Bind(c) 30 | if err != nil { 31 | response.Error(c, http.StatusUnprocessableEntity, err, "参数验证失败") 32 | return 33 | } 34 | var object models.ActiveRecord 35 | object, err = req.GenerateM() 36 | if err != nil { 37 | response.Error(c, 500, err, "模型生成失败") 38 | return 39 | } 40 | 41 | var rsp interface{} 42 | if f != nil { 43 | rsp = f() 44 | } else { 45 | rsp, _ = req.GenerateM() 46 | } 47 | 48 | //数据权限检查 49 | p := GetPermissionFromContext(c) 50 | 51 | err = db.Model(object).WithContext(c).Scopes( 52 | Permission(object.TableName(), p), 53 | ).Where(req.GetId()).First(rsp).Error 54 | 55 | if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { 56 | response.Error(c, http.StatusNotFound, nil, "查看对象不存在或无权查看") 57 | return 58 | } 59 | if err != nil { 60 | log.Errorf("MsgID[%s] View error: %s", msgID, err) 61 | response.Error(c, 500, err, "查看失败") 62 | return 63 | } 64 | response.OK(c, rsp, "查询成功") 65 | c.Next() 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /common/database/initialize.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "time" 5 | 6 | log "github.com/go-admin-team/go-admin-core/logger" 7 | "github.com/go-admin-team/go-admin-core/sdk" 8 | toolsConfig "github.com/go-admin-team/go-admin-core/sdk/config" 9 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 10 | mycasbin "github.com/go-admin-team/go-admin-core/sdk/pkg/casbin" 11 | toolsDB "github.com/go-admin-team/go-admin-core/tools/database" 12 | . "github.com/go-admin-team/go-admin-core/tools/gorm/logger" 13 | "gorm.io/gorm" 14 | "gorm.io/gorm/logger" 15 | "gorm.io/gorm/schema" 16 | 17 | "go-admin/common/global" 18 | ) 19 | 20 | // Setup 配置数据库 21 | func Setup() { 22 | for k := range toolsConfig.DatabasesConfig { 23 | setupSimpleDatabase(k, toolsConfig.DatabasesConfig[k]) 24 | } 25 | } 26 | 27 | func setupSimpleDatabase(host string, c *toolsConfig.Database) { 28 | if global.Driver == "" { 29 | global.Driver = c.Driver 30 | } 31 | log.Infof("%s => %s", host, pkg.Green(c.Source)) 32 | registers := make([]toolsDB.ResolverConfigure, len(c.Registers)) 33 | for i := range c.Registers { 34 | registers[i] = toolsDB.NewResolverConfigure( 35 | c.Registers[i].Sources, 36 | c.Registers[i].Replicas, 37 | c.Registers[i].Policy, 38 | c.Registers[i].Tables) 39 | } 40 | resolverConfig := toolsDB.NewConfigure(c.Source, c.MaxIdleConns, c.MaxOpenConns, c.ConnMaxIdleTime, c.ConnMaxLifeTime, registers) 41 | db, err := resolverConfig.Init(&gorm.Config{ 42 | NamingStrategy: schema.NamingStrategy{ 43 | SingularTable: true, 44 | }, 45 | Logger: New( 46 | logger.Config{ 47 | SlowThreshold: time.Second, 48 | Colorful: true, 49 | LogLevel: logger.LogLevel( 50 | log.DefaultLogger.Options().Level.LevelForGorm()), 51 | }, 52 | ), 53 | }, opens[c.Driver]) 54 | 55 | if err != nil { 56 | log.Fatal(pkg.Red(c.Driver+" connect error :"), err) 57 | } else { 58 | log.Info(pkg.Green(c.Driver + " connect success !")) 59 | } 60 | 61 | e := mycasbin.Setup(db, "") 62 | 63 | sdk.Runtime.SetDb(host, db) 64 | sdk.Runtime.SetCasbin(host, e) 65 | } 66 | -------------------------------------------------------------------------------- /common/database/open.go: -------------------------------------------------------------------------------- 1 | //go:build !sqlite3 2 | 3 | package database 4 | 5 | import ( 6 | "gorm.io/driver/mysql" 7 | "gorm.io/driver/postgres" 8 | "gorm.io/driver/sqlserver" 9 | "gorm.io/gorm" 10 | ) 11 | 12 | var opens = map[string]func(string) gorm.Dialector{ 13 | "mysql": mysql.Open, 14 | "postgres": postgres.Open, 15 | "sqlserver": sqlserver.Open, 16 | } 17 | -------------------------------------------------------------------------------- /common/database/open_sqlite3.go: -------------------------------------------------------------------------------- 1 | //go:build sqlite3 2 | // +build sqlite3 3 | 4 | package database 5 | 6 | import ( 7 | "gorm.io/driver/mysql" 8 | "gorm.io/driver/postgres" 9 | "gorm.io/driver/sqlite" 10 | "gorm.io/driver/sqlserver" 11 | "gorm.io/gorm" 12 | ) 13 | 14 | var opens = map[string]func(string) gorm.Dialector{ 15 | "mysql": mysql.Open, 16 | "postgres": postgres.Open, 17 | "sqlite3": sqlite.Open, 18 | "sqlserver": sqlserver.Open, 19 | } 20 | -------------------------------------------------------------------------------- /common/dto/auto_form.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type AutoForm struct { 4 | Fields []Field `json:"fields"` 5 | FormRef string `json:"formRef"` 6 | FormModel string `json:"formModel"` 7 | Size string `json:"size"` 8 | LabelPosition string `json:"labelPosition"` 9 | LabelWidth int `json:"labelWidth"` 10 | FormRules string `json:"formRules"` 11 | Gutter int `json:"gutter"` 12 | Disabled bool `json:"disabled"` 13 | Span int `json:"span"` 14 | FormBtns bool `json:"formBtns"` 15 | } 16 | 17 | type Config struct { 18 | Label string `json:"label"` 19 | LabelWidth interface{} `json:"labelWidth"` 20 | ShowLabel bool `json:"showLabel"` 21 | ChangeTag bool `json:"changeTag"` 22 | Tag string `json:"tag"` 23 | TagIcon string `json:"tagIcon"` 24 | Required bool `json:"required"` 25 | Layout string `json:"layout"` 26 | Span int `json:"span"` 27 | Document string `json:"document"` 28 | RegList []interface{} `json:"regList"` 29 | FormId int `json:"formId"` 30 | RenderKey int64 `json:"renderKey"` 31 | DefaultValue interface{} `json:"defaultValue"` 32 | ShowTip bool `json:"showTip,omitempty"` 33 | ButtonText string `json:"buttonText,omitempty"` 34 | FileSize int `json:"fileSize,omitempty"` 35 | SizeUnit string `json:"sizeUnit,omitempty"` 36 | } 37 | 38 | type Option struct { 39 | Label string `json:"label"` 40 | Value string `json:"value"` 41 | } 42 | 43 | type Slot struct { 44 | Prepend string `json:"prepend,omitempty"` 45 | Append string `json:"append,omitempty"` 46 | ListType bool `json:"list-type,omitempty"` 47 | Options []Option `json:"options,omitempty"` 48 | } 49 | 50 | type Field struct { 51 | Config Config `json:"__config__"` 52 | Slot Slot `json:"__slot__"` 53 | Placeholder string `json:"placeholder,omitempty"` 54 | Style Style `json:"style,omitempty"` 55 | Clearable bool `json:"clearable,omitempty"` 56 | PrefixIcon string `json:"prefix-icon,omitempty"` 57 | SuffixIcon string `json:"suffix-icon,omitempty"` 58 | Maxlength interface{} `json:"maxlength"` 59 | ShowWordLimit bool `json:"show-word-limit,omitempty"` 60 | Readonly bool `json:"readonly,omitempty"` 61 | Disabled bool `json:"disabled"` 62 | VModel string `json:"__vModel__"` 63 | Action string `json:"action,omitempty"` 64 | Accept string `json:"accept,omitempty"` 65 | Name string `json:"name,omitempty"` 66 | AutoUpload bool `json:"auto-upload,omitempty"` 67 | ListType string `json:"list-type,omitempty"` 68 | Multiple bool `json:"multiple,omitempty"` 69 | Filterable bool `json:"filterable,omitempty"` 70 | } 71 | 72 | type Style struct { 73 | Width string `json:"width"` 74 | } 75 | -------------------------------------------------------------------------------- /common/dto/generate.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | vd "github.com/bytedance/go-tagexpr/v2/validator" 5 | "net/http" 6 | 7 | "github.com/gin-gonic/gin" 8 | "github.com/go-admin-team/go-admin-core/sdk/api" 9 | ) 10 | 11 | type ObjectById struct { 12 | Id int `uri:"id"` 13 | Ids []int `json:"ids"` 14 | } 15 | 16 | func (s *ObjectById) Bind(ctx *gin.Context) error { 17 | var err error 18 | log := api.GetRequestLogger(ctx) 19 | err = ctx.ShouldBindUri(s) 20 | if err != nil { 21 | log.Warnf("ShouldBindUri error: %s", err.Error()) 22 | return err 23 | } 24 | if ctx.Request.Method == http.MethodDelete { 25 | err = ctx.ShouldBind(&s) 26 | if err != nil { 27 | log.Warnf("ShouldBind error: %s", err.Error()) 28 | return err 29 | } 30 | if len(s.Ids) > 0 { 31 | return nil 32 | } 33 | if s.Ids == nil { 34 | s.Ids = make([]int, 0) 35 | } 36 | if s.Id != 0 { 37 | s.Ids = append(s.Ids, s.Id) 38 | } 39 | } 40 | if err = vd.Validate(s); err != nil { 41 | log.Errorf("Validate error: %s", err.Error()) 42 | return err 43 | } 44 | return err 45 | } 46 | 47 | func (s *ObjectById) GetId() interface{} { 48 | if len(s.Ids) > 0 { 49 | s.Ids = append(s.Ids, s.Id) 50 | return s.Ids 51 | } 52 | return s.Id 53 | } 54 | 55 | type ObjectGetReq struct { 56 | Id int `uri:"id"` 57 | } 58 | 59 | func (s *ObjectGetReq) Bind(ctx *gin.Context) error { 60 | var err error 61 | log := api.GetRequestLogger(ctx) 62 | err = ctx.ShouldBindUri(s) 63 | if err != nil { 64 | log.Warnf("ShouldBindUri error: %s", err.Error()) 65 | return err 66 | } 67 | if err = vd.Validate(s); err != nil { 68 | log.Errorf("Validate error: %s", err.Error()) 69 | return err 70 | } 71 | return err 72 | } 73 | 74 | func (s *ObjectGetReq) GetId() interface{} { 75 | return s.Id 76 | } 77 | 78 | type ObjectDeleteReq struct { 79 | Ids []int `json:"ids"` 80 | } 81 | 82 | func (s *ObjectDeleteReq) Bind(ctx *gin.Context) error { 83 | var err error 84 | log := api.GetRequestLogger(ctx) 85 | err = ctx.ShouldBind(&s) 86 | if err != nil { 87 | log.Warnf("ShouldBind error: %s", err.Error()) 88 | return err 89 | } 90 | if len(s.Ids) > 0 { 91 | return nil 92 | } 93 | if s.Ids == nil { 94 | s.Ids = make([]int, 0) 95 | } 96 | 97 | if err = vd.Validate(s); err != nil { 98 | log.Errorf("Validate error: %s", err.Error()) 99 | return err 100 | } 101 | return err 102 | } 103 | 104 | func (s *ObjectDeleteReq) GetId() interface{} { 105 | return s.Ids 106 | } 107 | -------------------------------------------------------------------------------- /common/dto/order.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "gorm.io/gorm" 5 | "gorm.io/gorm/clause" 6 | ) 7 | 8 | func OrderDest(sort string, bl bool) func(db *gorm.DB) *gorm.DB { 9 | return func(db *gorm.DB) *gorm.DB { 10 | return db.Order(clause.OrderByColumn{Column: clause.Column{Name: sort}, Desc: bl}) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /common/dto/pagination.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type Pagination struct { 4 | PageIndex int `form:"pageIndex"` 5 | PageSize int `form:"pageSize"` 6 | } 7 | 8 | func (m *Pagination) GetPageIndex() int { 9 | if m.PageIndex <= 0 { 10 | m.PageIndex = 1 11 | } 12 | return m.PageIndex 13 | } 14 | 15 | func (m *Pagination) GetPageSize() int { 16 | if m.PageSize <= 0 { 17 | m.PageSize = 10 18 | } 19 | return m.PageSize 20 | } 21 | -------------------------------------------------------------------------------- /common/dto/search.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "github.com/go-admin-team/go-admin-core/tools/search" 5 | "go-admin/common/global" 6 | "gorm.io/gorm" 7 | ) 8 | 9 | type GeneralDelDto struct { 10 | Id int `uri:"id" json:"id" validate:"required"` 11 | Ids []int `json:"ids"` 12 | } 13 | 14 | func (g GeneralDelDto) GetIds() []int { 15 | ids := make([]int, 0) 16 | if g.Id != 0 { 17 | ids = append(ids, g.Id) 18 | } 19 | if len(g.Ids) > 0 { 20 | for _, id := range g.Ids { 21 | if id > 0 { 22 | ids = append(ids, id) 23 | } 24 | } 25 | } else { 26 | if g.Id > 0 { 27 | ids = append(ids, g.Id) 28 | } 29 | } 30 | if len(ids) <= 0 { 31 | //方式全部删除 32 | ids = append(ids, 0) 33 | } 34 | return ids 35 | } 36 | 37 | type GeneralGetDto struct { 38 | Id int `uri:"id" json:"id" validate:"required"` 39 | } 40 | 41 | func MakeCondition(q interface{}) func(db *gorm.DB) *gorm.DB { 42 | return func(db *gorm.DB) *gorm.DB { 43 | condition := &search.GormCondition{ 44 | GormPublic: search.GormPublic{}, 45 | Join: make([]*search.GormJoin, 0), 46 | } 47 | search.ResolveSearchQuery(global.Driver, q, condition) 48 | for _, join := range condition.Join { 49 | if join == nil { 50 | continue 51 | } 52 | db = db.Joins(join.JoinOn) 53 | for k, v := range join.Where { 54 | db = db.Where(k, v...) 55 | } 56 | for k, v := range join.Or { 57 | db = db.Or(k, v...) 58 | } 59 | for _, o := range join.Order { 60 | db = db.Order(o) 61 | } 62 | } 63 | for k, v := range condition.Where { 64 | db = db.Where(k, v...) 65 | } 66 | for k, v := range condition.Or { 67 | db = db.Or(k, v...) 68 | } 69 | for _, o := range condition.Order { 70 | db = db.Order(o) 71 | } 72 | return db 73 | } 74 | } 75 | 76 | func Paginate(pageSize, pageIndex int) func(db *gorm.DB) *gorm.DB { 77 | return func(db *gorm.DB) *gorm.DB { 78 | offset := (pageIndex - 1) * pageSize 79 | if offset < 0 { 80 | offset = 0 81 | } 82 | return db.Offset(offset).Limit(pageSize) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /common/dto/type.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "go-admin/common/models" 6 | ) 7 | 8 | type Index interface { 9 | Generate() Index 10 | Bind(ctx *gin.Context) error 11 | GetPageIndex() int 12 | GetPageSize() int 13 | GetNeedSearch() interface{} 14 | } 15 | 16 | type Control interface { 17 | Generate() Control 18 | Bind(ctx *gin.Context) error 19 | GenerateM() (models.ActiveRecord, error) 20 | GetId() interface{} 21 | } 22 | -------------------------------------------------------------------------------- /common/file_store/initialize.go: -------------------------------------------------------------------------------- 1 | package file_store 2 | 3 | import "fmt" 4 | 5 | type OXS struct { 6 | // Endpoint 访问域名 7 | Endpoint string 8 | // AccessKeyID AK 9 | AccessKeyID string 10 | // AccessKeySecret AKS 11 | AccessKeySecret string 12 | // BucketName 桶名称 13 | BucketName string 14 | } 15 | 16 | // Setup 配置文件存储driver 17 | func (e *OXS) Setup(driver DriverType, options ...ClientOption) FileStoreType { 18 | fileStoreType := driver 19 | var fileStore FileStoreType 20 | switch fileStoreType { 21 | case AliYunOSS: 22 | fileStore = new(ALiYunOSS) 23 | err := fileStore.Setup(e.Endpoint, e.AccessKeyID, e.AccessKeySecret, e.BucketName) 24 | if err != nil { 25 | fmt.Println(err) 26 | } 27 | return fileStore 28 | case HuaweiOBS: 29 | fileStore = new(HuaWeiOBS) 30 | err := fileStore.Setup(e.Endpoint, e.AccessKeyID, e.AccessKeySecret, e.BucketName) 31 | if err != nil { 32 | fmt.Println(err) 33 | } 34 | return fileStore 35 | case QiNiuKodo: 36 | fileStore = new(QiNiuKODO) 37 | err := fileStore.Setup(e.Endpoint, e.AccessKeyID, e.AccessKeySecret, e.BucketName) 38 | if err != nil { 39 | fmt.Println(err) 40 | } 41 | return fileStore 42 | } 43 | 44 | return nil 45 | } 46 | -------------------------------------------------------------------------------- /common/file_store/interface.go: -------------------------------------------------------------------------------- 1 | package file_store 2 | 3 | // DriverType 驱动类型 4 | type DriverType string 5 | 6 | const ( 7 | // HuaweiOBS 华为云OBS 8 | HuaweiOBS DriverType = "HuaweiOBS" 9 | // AliYunOSS 阿里云OSS 10 | AliYunOSS DriverType = "AliYunOSS" 11 | // QiNiuKodo 七牛云kodo 12 | QiNiuKodo DriverType = "QiNiuKodo" 13 | ) 14 | 15 | type ClientOption map[string]interface{} 16 | 17 | // TODO: FileStoreType名称待定 18 | 19 | // FileStoreType OXS 20 | type FileStoreType interface { 21 | // Setup 装载 endpoint sss 22 | Setup(endpoint, accessKeyID, accessKeySecret, BucketName string, options ...ClientOption) error 23 | // UpLoad 上传 24 | UpLoad(yourObjectName string, localFile interface{}) error 25 | // GetTempToken 获取临时Token 26 | GetTempToken() (string, error) 27 | } 28 | -------------------------------------------------------------------------------- /common/file_store/kodo.go: -------------------------------------------------------------------------------- 1 | package file_store 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/qiniu/go-sdk/v7/auth/qbox" 7 | "github.com/qiniu/go-sdk/v7/storage" 8 | ) 9 | 10 | type Zone string 11 | 12 | const ( 13 | // HuaDong 华东 14 | HuaDong Zone = "HuaDong" 15 | // HuaBei 华北 16 | HuaBei Zone = "HuaBei" 17 | // HuaNan 华南 18 | HuaNan Zone = "HuaNan" 19 | // BeiMei 北美 20 | BeiMei Zone = "BeiMei" 21 | // XinJiaPo 新加坡 22 | XinJiaPo Zone = "XinJiaPo" 23 | ) 24 | 25 | type QiNiuKODO struct { 26 | Client interface{} 27 | BucketName string 28 | cfg storage.Config 29 | options []ClientOption 30 | } 31 | 32 | func (e *QiNiuKODO) getToken() string { 33 | putPolicy := storage.PutPolicy{ 34 | Scope: e.BucketName, 35 | } 36 | if len(e.options) > 0 && e.options[0]["Expires"] != nil { 37 | putPolicy.Expires = e.options[0]["Expires"].(uint64) 38 | } 39 | upToken := putPolicy.UploadToken(e.Client.(*qbox.Mac)) 40 | return upToken 41 | } 42 | 43 | //Setup 装载 44 | //endpoint sss 45 | func (e *QiNiuKODO) Setup(endpoint, accessKeyID, accessKeySecret, BucketName string, options ...ClientOption) error { 46 | 47 | mac := qbox.NewMac(accessKeyID, accessKeySecret) 48 | // 获取存储空间。 49 | cfg := storage.Config{} 50 | // 空间对应的机房 51 | e.setZoneORDefault(cfg, options...) 52 | // 是否使用https域名 53 | cfg.UseHTTPS = true 54 | // 上传是否使用CDN上传加速 55 | cfg.UseCdnDomains = false 56 | 57 | e.Client = mac 58 | e.BucketName = BucketName 59 | e.cfg = cfg 60 | e.options = options 61 | return nil 62 | } 63 | 64 | // setZoneORDefault 设置Zone或者默认华东 65 | func (e *QiNiuKODO) setZoneORDefault(cfg storage.Config, options ...ClientOption) { 66 | if len(options) > 0 && options[0]["Zone"] != nil { 67 | if _, ok := options[0]["Zone"].(Zone); !ok { 68 | cfg.Zone = &storage.ZoneHuadong 69 | } 70 | switch options[0]["Zone"].(Zone) { 71 | case HuaDong: 72 | cfg.Zone = &storage.ZoneHuadong 73 | case HuaBei: 74 | cfg.Zone = &storage.ZoneHuabei 75 | case HuaNan: 76 | cfg.Zone = &storage.ZoneHuanan 77 | case BeiMei: 78 | cfg.Zone = &storage.ZoneBeimei 79 | case XinJiaPo: 80 | cfg.Zone = &storage.ZoneXinjiapo 81 | default: 82 | cfg.Zone = &storage.ZoneHuadong 83 | } 84 | } 85 | } 86 | 87 | // UpLoad 文件上传 88 | func (e *QiNiuKODO) UpLoad(yourObjectName string, localFile interface{}) error { 89 | 90 | // 构建表单上传的对象 91 | formUploader := storage.NewFormUploader(&e.cfg) 92 | ret := storage.PutRet{} 93 | // 可选配置 94 | putExtra := storage.PutExtra{ 95 | Params: map[string]string{ 96 | "x:name": "github logo", 97 | }, 98 | } 99 | err := formUploader.PutFile(context.Background(), &ret, e.getToken(), yourObjectName, localFile.(string), &putExtra) 100 | if err != nil { 101 | fmt.Println(err) 102 | return err 103 | } 104 | fmt.Println(ret.Key, ret.Hash) 105 | return nil 106 | } 107 | 108 | func (e *QiNiuKODO) GetTempToken() (string, error) { 109 | token := e.getToken() 110 | return token, nil 111 | } 112 | -------------------------------------------------------------------------------- /common/file_store/kodo_test.go: -------------------------------------------------------------------------------- 1 | package file_store 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestKODOUpload(t *testing.T) { 8 | e := OXS{"", "", "", ""} 9 | var oxs = e.Setup(QiNiuKodo, map[string]interface{}{"Zone": "华东"}) 10 | err := oxs.UpLoad("test.png", "./test.png") 11 | if err != nil { 12 | t.Error(err) 13 | } 14 | t.Log("ok") 15 | } 16 | 17 | func TestKODOGetTempToken(t *testing.T) { 18 | e := OXS{"", "", "", ""} 19 | var oxs = e.Setup(QiNiuKodo, map[string]interface{}{"Zone": "华东"}) 20 | token, _ := oxs.GetTempToken() 21 | t.Log(token) 22 | t.Log("ok") 23 | } 24 | -------------------------------------------------------------------------------- /common/file_store/obs.go: -------------------------------------------------------------------------------- 1 | package file_store 2 | 3 | import ( 4 | "fmt" 5 | "github.com/huaweicloud/huaweicloud-sdk-go-obs/obs" 6 | "log" 7 | ) 8 | 9 | type HuaWeiOBS struct { 10 | Client interface{} 11 | BucketName string 12 | } 13 | 14 | func (e *HuaWeiOBS) Setup(endpoint, accessKeyID, accessKeySecret, BucketName string, options ...ClientOption) error { 15 | // 创建ObsClient结构体 16 | client, err := obs.New(accessKeyID, accessKeySecret, endpoint) 17 | if err != nil { 18 | log.Println("Error:", err) 19 | return err 20 | } 21 | e.Client = client 22 | e.BucketName = BucketName 23 | return nil 24 | } 25 | 26 | // UpLoad 文件上传 27 | // yourObjectName 文件路径名称,与objectKey是同一概念,表示断点续传上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg 28 | func (e *HuaWeiOBS) UpLoad(yourObjectName string, localFile interface{}) error { 29 | // 获取存储空间。 30 | input := &obs.PutFileInput{} 31 | input.Bucket = e.BucketName 32 | input.Key = yourObjectName 33 | input.SourceFile = localFile.(string) 34 | output, err := e.Client.(*obs.ObsClient).PutFile(input) 35 | 36 | if err == nil { 37 | fmt.Printf("RequestId:%s\n", output.RequestId) 38 | fmt.Printf("ETag:%s, StorageClass:%s\n", output.ETag, output.StorageClass) 39 | } else { 40 | if obsError, ok := err.(obs.ObsError); ok { 41 | fmt.Println(obsError.Code) 42 | fmt.Println(obsError.Message) 43 | } else { 44 | fmt.Println(err) 45 | } 46 | } 47 | return nil 48 | } 49 | 50 | func (e *HuaWeiOBS) GetTempToken() (string, error) { 51 | return "", nil 52 | } 53 | -------------------------------------------------------------------------------- /common/file_store/obs_test.go: -------------------------------------------------------------------------------- 1 | package file_store 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestOBSUpload(t *testing.T) { 8 | e := OXS{"", "", "", ""} 9 | var oxs = e.Setup(HuaweiOBS) 10 | err := oxs.UpLoad("test.png", "./test.png") 11 | if err != nil { 12 | t.Error(err) 13 | } 14 | t.Log("ok") 15 | } 16 | -------------------------------------------------------------------------------- /common/file_store/oss.go: -------------------------------------------------------------------------------- 1 | package file_store 2 | 3 | import ( 4 | "github.com/aliyun/aliyun-oss-go-sdk/oss" 5 | "log" 6 | ) 7 | 8 | type ALiYunOSS struct { 9 | Client interface{} 10 | BucketName string 11 | } 12 | 13 | //Setup 装载 14 | //endpoint sss 15 | func (e *ALiYunOSS) Setup(endpoint, accessKeyID, accessKeySecret, BucketName string, options ...ClientOption) error { 16 | client, err := oss.New(endpoint, accessKeyID, accessKeySecret) 17 | if err != nil { 18 | log.Println("Error:", err) 19 | return err 20 | } 21 | e.Client = client 22 | e.BucketName = BucketName 23 | 24 | return nil 25 | } 26 | 27 | // UpLoad 文件上传 28 | func (e *ALiYunOSS) UpLoad(yourObjectName string, localFile interface{}) error { 29 | // 获取存储空间。 30 | bucket, err := e.Client.(*oss.Client).Bucket(e.BucketName) 31 | if err != nil { 32 | log.Println("Error:", err) 33 | return err 34 | } 35 | // 设置分片大小为100 KB,指定分片上传并发数为3,并开启断点续传上传。 36 | // 其中与objectKey是同一概念,表示断点续传上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。 37 | // "LocalFile"为filePath,100*1024为partSize。 38 | err = bucket.UploadFile(yourObjectName, localFile.(string), 100*1024, oss.Routines(3), oss.Checkpoint(true, "")) 39 | if err != nil { 40 | log.Println("Error:", err) 41 | return err 42 | } 43 | return nil 44 | } 45 | 46 | func (e *ALiYunOSS) GetTempToken() (string, error) { 47 | return "", nil 48 | } 49 | -------------------------------------------------------------------------------- /common/file_store/oss_test.go: -------------------------------------------------------------------------------- 1 | package file_store 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestOSSUpload(t *testing.T) { 8 | // 打括号内填写自己的测试信息即可 9 | e := OXS{} 10 | var oxs = e.Setup(AliYunOSS) 11 | err := oxs.UpLoad("test.png", "./test.png") 12 | if err != nil { 13 | t.Error(err) 14 | } 15 | t.Log("ok") 16 | } 17 | -------------------------------------------------------------------------------- /common/global/adm.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | const ( 4 | // Version go-admin version info 5 | Version = "2.2.0" 6 | ) 7 | 8 | var ( 9 | // Driver 数据库驱动 10 | Driver string 11 | ) 12 | -------------------------------------------------------------------------------- /common/global/casbin.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | import ( 4 | "github.com/casbin/casbin/v2" 5 | "github.com/gin-gonic/gin" 6 | "github.com/go-admin-team/go-admin-core/sdk" 7 | "github.com/go-admin-team/go-admin-core/sdk/api" 8 | ) 9 | 10 | func LoadPolicy(c *gin.Context) (*casbin.SyncedEnforcer, error) { 11 | log := api.GetRequestLogger(c) 12 | if err := sdk.Runtime.GetCasbinKey(c.Request.Host).LoadPolicy(); err == nil { 13 | return sdk.Runtime.GetCasbinKey(c.Request.Host), err 14 | } else { 15 | log.Errorf("casbin rbac_model or policy init error, %s ", err.Error()) 16 | return nil, err 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /common/global/topic.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | const ( 4 | LoginLog = "login_log_queue" 5 | OperateLog = "operate_log_queue" 6 | ApiCheck = "api_check_queue" 7 | ) 8 | -------------------------------------------------------------------------------- /common/ip.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "strings" 6 | ) 7 | 8 | func GetClientIP(c *gin.Context) string { 9 | // 优先从 X-Forwarded-For 获取 IP 10 | ip := c.Request.Header.Get("X-Forwarded-For") 11 | if ip == "" || strings.Contains(ip, "127.0.0.1") { 12 | // 如果为空或为本地地址,则尝试从 X-Real-IP 获取 13 | ip = c.Request.Header.Get("X-real-ip") 14 | } 15 | if ip == "" { 16 | // 如果仍为空,则使用 RemoteIP 17 | ip = c.RemoteIP() 18 | } 19 | if ip == "" || ip == "127.0.0.1" { 20 | // 如果仍为空或为本地地址,则使用 ClientIP 21 | ip = c.ClientIP() 22 | } 23 | if ip == "" { 24 | // 最后兜底为本地地址 25 | ip = "127.0.0.1" 26 | } 27 | return ip 28 | } 29 | -------------------------------------------------------------------------------- /common/middleware/auth.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/go-admin-team/go-admin-core/sdk/config" 7 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 8 | "go-admin/common/middleware/handler" 9 | ) 10 | 11 | // AuthInit jwt验证new 12 | func AuthInit() (*jwt.GinJWTMiddleware, error) { 13 | timeout := time.Hour 14 | if config.ApplicationConfig.Mode == "dev" { 15 | timeout = time.Duration(876010) * time.Hour 16 | } else { 17 | if config.JwtConfig.Timeout != 0 { 18 | timeout = time.Duration(config.JwtConfig.Timeout) * time.Second 19 | } 20 | } 21 | return jwt.New(&jwt.GinJWTMiddleware{ 22 | Realm: "test zone", 23 | Key: []byte(config.JwtConfig.Secret), 24 | Timeout: timeout, 25 | MaxRefresh: time.Hour, 26 | PayloadFunc: handler.PayloadFunc, 27 | IdentityHandler: handler.IdentityHandler, 28 | Authenticator: handler.Authenticator, 29 | Authorizator: handler.Authorizator, 30 | Unauthorized: handler.Unauthorized, 31 | TokenLookup: "header: Authorization, query: token, cookie: jwt", 32 | TokenHeadName: "Bearer", 33 | TimeFunc: time.Now, 34 | }) 35 | 36 | } -------------------------------------------------------------------------------- /common/middleware/customerror.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "runtime" 7 | "strconv" 8 | "strings" 9 | "time" 10 | 11 | "github.com/gin-gonic/gin" 12 | ) 13 | 14 | func CustomError(c *gin.Context) { 15 | defer func() { 16 | if err := recover(); err != nil { 17 | 18 | if c.IsAborted() { 19 | c.Status(200) 20 | } 21 | switch errStr := err.(type) { 22 | case string: 23 | p := strings.Split(errStr, "#") 24 | if len(p) == 3 && p[0] == "CustomError" { 25 | statusCode, e := strconv.Atoi(p[1]) 26 | if e != nil { 27 | break 28 | } 29 | c.Status(statusCode) 30 | fmt.Println( 31 | time.Now().Format("2006-01-02 15:04:05"), 32 | "[ERROR]", 33 | c.Request.Method, 34 | c.Request.URL, 35 | statusCode, 36 | c.Request.RequestURI, 37 | c.ClientIP(), 38 | p[2], 39 | ) 40 | c.JSON(http.StatusOK, gin.H{ 41 | "code": statusCode, 42 | "msg": p[2], 43 | }) 44 | } else { 45 | c.JSON(http.StatusOK, gin.H{ 46 | "code": 500, 47 | "msg": errStr, 48 | }) 49 | } 50 | case runtime.Error: 51 | c.JSON(http.StatusOK, gin.H{ 52 | "code": 500, 53 | "msg": errStr.Error(), 54 | }) 55 | default: 56 | panic(err) 57 | } 58 | } 59 | }() 60 | c.Next() 61 | } 62 | -------------------------------------------------------------------------------- /common/middleware/db.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/go-admin-team/go-admin-core/sdk" 6 | ) 7 | 8 | func WithContextDb(c *gin.Context) { 9 | c.Set("db", sdk.Runtime.GetDbByKey(c.Request.Host).WithContext(c)) 10 | c.Next() 11 | } 12 | -------------------------------------------------------------------------------- /common/middleware/demo.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/go-admin-team/go-admin-core/sdk/config" 6 | "net/http" 7 | ) 8 | 9 | func DemoEvn() gin.HandlerFunc { 10 | return func(c *gin.Context) { 11 | method := c.Request.Method 12 | if config.ApplicationConfig.Mode == "demo" { 13 | if method == "GET" || 14 | method == "OPTIONS" || 15 | c.Request.RequestURI == "/api/v1/login" || 16 | c.Request.RequestURI == "/api/v1/logout" { 17 | c.Next() 18 | } else { 19 | c.JSON(http.StatusOK, gin.H{ 20 | "code": 500, 21 | "msg": "谢谢您的参与,但为了大家更好的体验,所以本次提交就算了吧!\U0001F600\U0001F600\U0001F600", 22 | }) 23 | c.Abort() 24 | return 25 | } 26 | } 27 | c.Next() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /common/middleware/handler/httpshandler.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/unrolled/secure" 6 | 7 | "github.com/go-admin-team/go-admin-core/sdk/config" 8 | ) 9 | 10 | func TlsHandler() gin.HandlerFunc { 11 | return func(c *gin.Context) { 12 | secureMiddleware := secure.New(secure.Options{ 13 | SSLRedirect: true, 14 | SSLHost: config.SslConfig.Domain, 15 | }) 16 | err := secureMiddleware.Process(c.Writer, c.Request) 17 | if err != nil { 18 | return 19 | } 20 | c.Next() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /common/middleware/handler/login.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | log "github.com/go-admin-team/go-admin-core/logger" 5 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 6 | "gorm.io/gorm" 7 | ) 8 | 9 | type Login struct { 10 | Username string `form:"UserName" json:"username" binding:"required"` 11 | Password string `form:"Password" json:"password" binding:"required"` 12 | Code string `form:"Code" json:"code" binding:"required"` 13 | UUID string `form:"UUID" json:"uuid" binding:"required"` 14 | } 15 | 16 | func (u *Login) GetUser(tx *gorm.DB) (user SysUser, role SysRole, err error) { 17 | err = tx.Table("sys_user").Where("username = ? and status = '2'", u.Username).First(&user).Error 18 | if err != nil { 19 | log.Errorf("get user error, %s", err.Error()) 20 | return 21 | } 22 | _, err = pkg.CompareHashAndPassword(user.Password, u.Password) 23 | if err != nil { 24 | log.Errorf("user login error, %s", err.Error()) 25 | return 26 | } 27 | err = tx.Table("sys_role").Where("role_id = ? ", user.RoleId).First(&role).Error 28 | if err != nil { 29 | log.Errorf("get role error, %s", err.Error()) 30 | return 31 | } 32 | return 33 | } 34 | -------------------------------------------------------------------------------- /common/middleware/handler/ping.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | func Ping(c *gin.Context) { 8 | c.JSON(200, gin.H{ 9 | "message": "ok", 10 | }) 11 | } 12 | -------------------------------------------------------------------------------- /common/middleware/handler/role.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import "go-admin/common/models" 4 | 5 | type SysRole struct { 6 | RoleId int `json:"roleId" gorm:"primaryKey;autoIncrement"` // 角色编码 7 | RoleName string `json:"roleName" gorm:"size:128;"` // 角色名称 8 | Status string `json:"status" gorm:"size:4;"` // 9 | RoleKey string `json:"roleKey" gorm:"size:128;"` //角色代码 10 | RoleSort int `json:"roleSort" gorm:""` //角色排序 11 | Flag string `json:"flag" gorm:"size:128;"` // 12 | Remark string `json:"remark" gorm:"size:255;"` //备注 13 | Admin bool `json:"admin" gorm:"size:4;"` 14 | DataScope string `json:"dataScope" gorm:"size:128;"` 15 | Params string `json:"params" gorm:"-"` 16 | MenuIds []int `json:"menuIds" gorm:"-"` 17 | DeptIds []int `json:"deptIds" gorm:"-"` 18 | models.ControlBy 19 | models.ModelTime 20 | } 21 | 22 | func (SysRole) TableName() string { 23 | return "sys_role" 24 | } 25 | -------------------------------------------------------------------------------- /common/middleware/handler/user.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "go-admin/common/models" 5 | "gorm.io/gorm" 6 | ) 7 | 8 | type SysUser struct { 9 | UserId int `gorm:"primaryKey;autoIncrement;comment:编码" json:"userId"` 10 | Username string `json:"username" gorm:"size:64;comment:用户名"` 11 | Password string `json:"-" gorm:"size:128;comment:密码"` 12 | NickName string `json:"nickName" gorm:"size:128;comment:昵称"` 13 | Phone string `json:"phone" gorm:"size:11;comment:手机号"` 14 | RoleId int `json:"roleId" gorm:"size:20;comment:角色ID"` 15 | Salt string `json:"-" gorm:"size:255;comment:加盐"` 16 | Avatar string `json:"avatar" gorm:"size:255;comment:头像"` 17 | Sex string `json:"sex" gorm:"size:255;comment:性别"` 18 | Email string `json:"email" gorm:"size:128;comment:邮箱"` 19 | DeptId int `json:"deptId" gorm:"size:20;comment:部门"` 20 | PostId int `json:"postId" gorm:"size:20;comment:岗位"` 21 | Remark string `json:"remark" gorm:"size:255;comment:备注"` 22 | Status string `json:"status" gorm:"size:4;comment:状态"` 23 | DeptIds []int `json:"deptIds" gorm:"-"` 24 | PostIds []int `json:"postIds" gorm:"-"` 25 | RoleIds []int `json:"roleIds" gorm:"-"` 26 | //Dept *SysDept `json:"dept"` 27 | models.ControlBy 28 | models.ModelTime 29 | } 30 | 31 | func (*SysUser) TableName() string { 32 | return "sys_user" 33 | } 34 | 35 | func (e *SysUser) AfterFind(_ *gorm.DB) error { 36 | e.DeptIds = []int{e.DeptId} 37 | e.PostIds = []int{e.PostId} 38 | e.RoleIds = []int{e.RoleId} 39 | return nil 40 | } 41 | -------------------------------------------------------------------------------- /common/middleware/header.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "net/http" 5 | "time" 6 | 7 | "github.com/gin-gonic/gin" 8 | ) 9 | 10 | // NoCache is a middleware function that appends headers 11 | // to prevent the client from caching the HTTP response. 12 | func NoCache(c *gin.Context) { 13 | c.Header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value") 14 | c.Header("Expires", "Thu, 01 Jan 1970 00:00:00 GMT") 15 | c.Header("Last-Modified", time.Now().UTC().Format(http.TimeFormat)) 16 | c.Next() 17 | } 18 | 19 | // Options is a middleware function that appends headers 20 | // for options requests and aborts then exits the middleware 21 | // chain and ends the request. 22 | func Options(c *gin.Context) { 23 | if c.Request.Method != "OPTIONS" { 24 | c.Next() 25 | } else { 26 | c.Header("Access-Control-Allow-Origin", "*") 27 | c.Header("Access-Control-Allow-Methods", "GET,POST,PUT,PATCH,DELETE,OPTIONS") 28 | c.Header("Access-Control-Allow-Headers", "authorization, origin, content-type, accept") 29 | c.Header("Allow", "HEAD,GET,POST,PUT,PATCH,DELETE,OPTIONS") 30 | c.Header("Content-Type", "application/json") 31 | c.AbortWithStatus(200) 32 | } 33 | } 34 | 35 | // Secure is a middleware function that appends security 36 | // and resource access headers. 37 | func Secure(c *gin.Context) { 38 | c.Header("Access-Control-Allow-Origin", "*") 39 | //c.Header("X-Frame-Options", "DENY") 40 | c.Header("X-Content-Type-Options", "nosniff") 41 | c.Header("X-XSS-Protection", "1; mode=block") 42 | if c.Request.TLS != nil { 43 | c.Header("Strict-Transport-Security", "max-age=31536000") 44 | } 45 | 46 | // Also consider adding Content-Security-Policy headers 47 | // c.Header("Content-Security-Policy", "script-src 'self' https://cdnjs.cloudflare.com") 48 | } 49 | -------------------------------------------------------------------------------- /common/middleware/init.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/go-admin-team/go-admin-core/sdk" 6 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 7 | "go-admin/common/actions" 8 | ) 9 | 10 | const ( 11 | JwtTokenCheck string = "JwtToken" 12 | RoleCheck string = "AuthCheckRole" 13 | PermissionCheck string = "PermissionAction" 14 | ) 15 | 16 | func InitMiddleware(r *gin.Engine) { 17 | r.Use(DemoEvn()) 18 | // 数据库链接 19 | r.Use(WithContextDb) 20 | // 日志处理 21 | r.Use(LoggerToFile()) 22 | // 自定义错误处理 23 | r.Use(CustomError) 24 | // NoCache is a middleware function that appends headers 25 | r.Use(NoCache) 26 | // 跨域处理 27 | r.Use(Options) 28 | // Secure is a middleware function that appends security 29 | r.Use(Secure) 30 | // 链路追踪 31 | //r.Use(middleware.Trace()) 32 | sdk.Runtime.SetMiddleware(JwtTokenCheck, (*jwt.GinJWTMiddleware).MiddlewareFunc) 33 | sdk.Runtime.SetMiddleware(RoleCheck, AuthCheckRole()) 34 | sdk.Runtime.SetMiddleware(PermissionCheck, actions.PermissionAction()) 35 | } 36 | -------------------------------------------------------------------------------- /common/middleware/permission.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/casbin/casbin/v2/util" 5 | "net/http" 6 | 7 | "github.com/gin-gonic/gin" 8 | "github.com/go-admin-team/go-admin-core/sdk" 9 | "github.com/go-admin-team/go-admin-core/sdk/api" 10 | "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 11 | "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 12 | ) 13 | 14 | // AuthCheckRole 权限检查中间件 15 | func AuthCheckRole() gin.HandlerFunc { 16 | return func(c *gin.Context) { 17 | log := api.GetRequestLogger(c) 18 | data, _ := c.Get(jwtauth.JwtPayloadKey) 19 | v := data.(jwtauth.MapClaims) 20 | e := sdk.Runtime.GetCasbinKey(c.Request.Host) 21 | var res, casbinExclude bool 22 | var err error 23 | //检查权限 24 | if v["rolekey"] == "admin" { 25 | res = true 26 | c.Next() 27 | return 28 | } 29 | for _, i := range CasbinExclude { 30 | if util.KeyMatch2(c.Request.URL.Path, i.Url) && c.Request.Method == i.Method { 31 | casbinExclude = true 32 | break 33 | } 34 | } 35 | if casbinExclude { 36 | log.Infof("Casbin exclusion, no validation method:%s path:%s", c.Request.Method, c.Request.URL.Path) 37 | c.Next() 38 | return 39 | } 40 | res, err = e.Enforce(v["rolekey"], c.Request.URL.Path, c.Request.Method) 41 | if err != nil { 42 | log.Errorf("AuthCheckRole error:%s method:%s path:%s", err, c.Request.Method, c.Request.URL.Path) 43 | response.Error(c, 500, err, "") 44 | return 45 | } 46 | 47 | if res { 48 | log.Infof("isTrue: %v role: %s method: %s path: %s", res, v["rolekey"], c.Request.Method, c.Request.URL.Path) 49 | c.Next() 50 | } else { 51 | log.Warnf("isTrue: %v role: %s method: %s path: %s message: %s", res, v["rolekey"], c.Request.Method, c.Request.URL.Path, "当前request无权限,请管理员确认!") 52 | c.JSON(http.StatusOK, gin.H{ 53 | "code": 403, 54 | "msg": "对不起,您没有该接口访问权限,请联系管理员", 55 | }) 56 | c.Abort() 57 | return 58 | } 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /common/middleware/request_id.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/go-admin-team/go-admin-core/logger" 5 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 6 | "net/http" 7 | "strings" 8 | 9 | "github.com/gin-gonic/gin" 10 | "github.com/google/uuid" 11 | ) 12 | 13 | // RequestId 自动增加requestId 14 | func RequestId(trafficKey string) gin.HandlerFunc { 15 | return func(c *gin.Context) { 16 | if c.Request.Method == http.MethodOptions { 17 | c.Next() 18 | return 19 | } 20 | requestId := c.GetHeader(trafficKey) 21 | if requestId == "" { 22 | requestId = c.GetHeader(strings.ToLower(trafficKey)) 23 | } 24 | if requestId == "" { 25 | requestId = uuid.New().String() 26 | } 27 | c.Request.Header.Set(trafficKey, requestId) 28 | c.Set(trafficKey, requestId) 29 | c.Set(pkg.LoggerKey, 30 | logger.NewHelper(logger.DefaultLogger). 31 | WithFields(map[string]interface{}{ 32 | trafficKey: requestId, 33 | })) 34 | c.Next() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /common/middleware/sentinel.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/alibaba/sentinel-golang/core/system" 5 | sentinel "github.com/alibaba/sentinel-golang/pkg/adapters/gin" 6 | "github.com/gin-gonic/gin" 7 | 8 | log "github.com/go-admin-team/go-admin-core/logger" 9 | ) 10 | 11 | // Sentinel 限流 12 | func Sentinel() gin.HandlerFunc { 13 | if _, err := system.LoadRules([]*system.Rule{ 14 | { 15 | MetricType: system.InboundQPS, 16 | TriggerCount: 200, 17 | Strategy: system.BBR, 18 | }, 19 | }); err != nil { 20 | log.Fatalf("Unexpected error: %+v", err) 21 | } 22 | return sentinel.SentinelMiddleware( 23 | sentinel.WithBlockFallback(func(ctx *gin.Context) { 24 | ctx.AbortWithStatusJSON(200, map[string]interface{}{ 25 | "msg": "too many request; the quota used up!", 26 | "code": 500, 27 | }) 28 | }), 29 | ) 30 | } 31 | -------------------------------------------------------------------------------- /common/middleware/settings.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | type UrlInfo struct { 4 | Url string 5 | Method string 6 | } 7 | 8 | // CasbinExclude casbin 排除的路由列表 9 | var CasbinExclude = []UrlInfo{ 10 | {Url: "/api/v1/dict/type-option-select", Method: "GET"}, 11 | {Url: "/api/v1/dict-data/option-select", Method: "GET"}, 12 | {Url: "/api/v1/deptTree", Method: "GET"}, 13 | {Url: "/api/v1/db/tables/page", Method: "GET"}, 14 | {Url: "/api/v1/db/columns/page", Method: "GET"}, 15 | {Url: "/api/v1/gen/toproject/:tableId", Method: "GET"}, 16 | {Url: "/api/v1/gen/todb/:tableId", Method: "GET"}, 17 | {Url: "/api/v1/gen/tabletree", Method: "GET"}, 18 | {Url: "/api/v1/gen/preview/:tableId", Method: "GET"}, 19 | {Url: "/api/v1/gen/apitofile/:tableId", Method: "GET"}, 20 | {Url: "/api/v1/getCaptcha", Method: "GET"}, 21 | {Url: "/api/v1/getinfo", Method: "GET"}, 22 | {Url: "/api/v1/menuTreeselect", Method: "GET"}, 23 | {Url: "/api/v1/menurole", Method: "GET"}, 24 | {Url: "/api/v1/menuids", Method: "GET"}, 25 | {Url: "/api/v1/roleMenuTreeselect/:roleId", Method: "GET"}, 26 | {Url: "/api/v1/roleDeptTreeselect/:roleId", Method: "GET"}, 27 | {Url: "/api/v1/refresh_token", Method: "GET"}, 28 | {Url: "/api/v1/configKey/:configKey", Method: "GET"}, 29 | {Url: "/api/v1/app-config", Method: "GET"}, 30 | {Url: "/api/v1/user/profile", Method: "GET"}, 31 | {Url: "/info", Method: "GET"}, 32 | {Url: "/api/v1/login", Method: "POST"}, 33 | {Url: "/api/v1/logout", Method: "POST"}, 34 | {Url: "/api/v1/user/avatar", Method: "POST"}, 35 | {Url: "/api/v1/user/pwd", Method: "PUT"}, 36 | {Url: "/api/v1/metrics", Method: "GET"}, 37 | {Url: "/api/v1/health", Method: "GET"}, 38 | {Url: "/", Method: "GET"}, 39 | {Url: "/api/v1/server-monitor", Method: "GET"}, 40 | {Url: "/api/v1/public/uploadFile", Method: "POST"}, 41 | {Url: "/api/v1/user/pwd/set", Method: "PUT"}, 42 | {Url: "/api/v1/sys-user", Method: "PUT"}, 43 | } 44 | -------------------------------------------------------------------------------- /common/middleware/trace.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/opentracing/opentracing-go" 6 | ) 7 | 8 | // Trace 链路追踪 9 | func Trace() gin.HandlerFunc { 10 | return func(ctx *gin.Context) { 11 | var sp opentracing.Span 12 | opName := ctx.Request.URL.Path 13 | // Attempt to join a trace by getting trace context from the headers. 14 | wireContext, err := opentracing.GlobalTracer().Extract( 15 | opentracing.TextMap, 16 | opentracing.HTTPHeadersCarrier(ctx.Request.Header)) 17 | if err != nil { 18 | // If for whatever reason we can't join, go ahead and start a new root span. 19 | sp = opentracing.StartSpan(opName) 20 | } else { 21 | sp = opentracing.StartSpan(opName, opentracing.ChildOf(wireContext)) 22 | } 23 | ctx.Set("traceSpan", sp) 24 | ctx.Next() 25 | sp.Finish() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /common/models/by.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "time" 5 | 6 | "gorm.io/gorm" 7 | ) 8 | 9 | type ControlBy struct { 10 | CreateBy int `json:"createBy" gorm:"index;comment:创建者"` 11 | UpdateBy int `json:"updateBy" gorm:"index;comment:更新者"` 12 | } 13 | 14 | // SetCreateBy 设置创建人id 15 | func (e *ControlBy) SetCreateBy(createBy int) { 16 | e.CreateBy = createBy 17 | } 18 | 19 | // SetUpdateBy 设置修改人id 20 | func (e *ControlBy) SetUpdateBy(updateBy int) { 21 | e.UpdateBy = updateBy 22 | } 23 | 24 | type Model struct { 25 | Id int `json:"id" gorm:"primaryKey;autoIncrement;comment:主键编码"` 26 | } 27 | 28 | type ModelTime struct { 29 | CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"` 30 | UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"` 31 | DeletedAt gorm.DeletedAt `json:"-" gorm:"index;comment:删除时间"` 32 | } -------------------------------------------------------------------------------- /common/models/menu.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | // Menu 菜单中的类型枚举值 4 | const ( 5 | // Directory 目录 6 | Directory string = "M" 7 | // Menu 菜单 8 | Menu string = "C" 9 | // Button 按钮 10 | Button string = "F" 11 | ) 12 | -------------------------------------------------------------------------------- /common/models/migrate.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Migration struct { 6 | Version string `gorm:"primaryKey"` 7 | ApplyTime time.Time `gorm:"autoCreateTime"` 8 | } 9 | 10 | func (Migration) TableName() string { 11 | return "sys_migration" 12 | } 13 | -------------------------------------------------------------------------------- /common/models/response.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type Response struct { 4 | // 代码 5 | Code int `json:"code" example:"200"` 6 | // 数据集 7 | Data interface{} `json:"data"` 8 | // 消息 9 | Msg string `json:"msg"` 10 | RequestId string `json:"requestId"` 11 | } 12 | 13 | type Page struct { 14 | List interface{} `json:"list"` 15 | Count int `json:"count"` 16 | PageIndex int `json:"pageIndex"` 17 | PageSize int `json:"pageSize"` 18 | } 19 | 20 | // ReturnOK 正常返回 21 | func (res *Response) ReturnOK() *Response { 22 | res.Code = 200 23 | return res 24 | } 25 | 26 | // ReturnError 错误返回 27 | func (res *Response) ReturnError(code int) *Response { 28 | res.Code = code 29 | return res 30 | } 31 | -------------------------------------------------------------------------------- /common/models/type.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "gorm.io/gorm/schema" 4 | 5 | type ActiveRecord interface { 6 | schema.Tabler 7 | SetCreateBy(createBy int) 8 | SetUpdateBy(updateBy int) 9 | Generate() ActiveRecord 10 | GetId() interface{} 11 | } 12 | -------------------------------------------------------------------------------- /common/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "gorm.io/gorm" 5 | 6 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 7 | ) 8 | 9 | // BaseUser 密码登录基础用户 10 | type BaseUser struct { 11 | Username string `json:"username" gorm:"type:varchar(100);comment:用户名"` 12 | Salt string `json:"-" gorm:"type:varchar(255);comment:加盐;<-"` 13 | PasswordHash string `json:"-" gorm:"type:varchar(128);comment:密码hash;<-"` 14 | Password string `json:"password" gorm:"-"` 15 | } 16 | 17 | // SetPassword 设置密码 18 | func (u *BaseUser) SetPassword(value string) { 19 | u.Password = value 20 | u.generateSalt() 21 | u.PasswordHash = u.GetPasswordHash() 22 | } 23 | 24 | // GetPasswordHash 获取密码hash 25 | func (u *BaseUser) GetPasswordHash() string { 26 | passwordHash, err := pkg.SetPassword(u.Password, u.Salt) 27 | if err != nil { 28 | return "" 29 | } 30 | return passwordHash 31 | } 32 | 33 | // generateSalt 生成加盐值 34 | func (u *BaseUser) generateSalt() { 35 | u.Salt = pkg.GenerateRandomKey16() 36 | } 37 | 38 | // Verify 验证密码 39 | func (u *BaseUser) Verify(db *gorm.DB, tableName string) bool { 40 | db.Table(tableName).Where("username = ?", u.Username).First(u) 41 | return u.GetPasswordHash() == u.PasswordHash 42 | } 43 | -------------------------------------------------------------------------------- /common/response/binding.go: -------------------------------------------------------------------------------- 1 | package response 2 | 3 | import ( 4 | "fmt" 5 | "github.com/gin-gonic/gin/binding" 6 | "reflect" 7 | "strings" 8 | "sync" 9 | ) 10 | 11 | const ( 12 | _ uint8 = iota 13 | json 14 | xml 15 | yaml 16 | form 17 | query 18 | ) 19 | 20 | //var constructor = &bindConstructor{} 21 | 22 | type bindConstructor struct { 23 | cache map[string][]uint8 24 | mux sync.Mutex 25 | } 26 | 27 | func (e *bindConstructor) GetBindingForGin(d interface{}) []binding.Binding { 28 | bs := e.getBinding(reflect.TypeOf(d).String()) 29 | if bs == nil { 30 | //重新构建 31 | bs = e.resolve(d) 32 | } 33 | gbs := make([]binding.Binding, len(bs)) 34 | for i, b := range bs { 35 | switch b { 36 | case json: 37 | gbs[i] = binding.JSON 38 | case xml: 39 | gbs[i] = binding.XML 40 | case yaml: 41 | gbs[i] = binding.YAML 42 | case form: 43 | gbs[i] = binding.Form 44 | case query: 45 | gbs[i] = binding.Query 46 | default: 47 | gbs[i] = nil 48 | } 49 | } 50 | return gbs 51 | } 52 | 53 | func (e *bindConstructor) resolve(d interface{}) []uint8 { 54 | bs := make([]uint8, 0) 55 | qType := reflect.TypeOf(d).Elem() 56 | var tag reflect.StructTag 57 | var ok bool 58 | fmt.Println(qType.Kind()) 59 | for i := 0; i < qType.NumField(); i++ { 60 | tag = qType.Field(i).Tag 61 | if _, ok = tag.Lookup("json"); ok { 62 | bs = append(bs, json) 63 | } 64 | if _, ok = tag.Lookup("xml"); ok { 65 | bs = append(bs, xml) 66 | } 67 | if _, ok = tag.Lookup("yaml"); ok { 68 | bs = append(bs, yaml) 69 | } 70 | if _, ok = tag.Lookup("form"); ok { 71 | bs = append(bs, form) 72 | } 73 | if _, ok = tag.Lookup("query"); ok { 74 | bs = append(bs, query) 75 | } 76 | if _, ok = tag.Lookup("uri"); ok { 77 | bs = append(bs, 0) 78 | } 79 | if t, ok := tag.Lookup("binding"); ok && strings.Index(t, "dive") > -1 { 80 | qValue := reflect.ValueOf(d) 81 | bs = append(bs, e.resolve(qValue.Field(i))...) 82 | continue 83 | } 84 | if t, ok := tag.Lookup("validate"); ok && strings.Index(t, "dive") > -1 { 85 | qValue := reflect.ValueOf(d) 86 | bs = append(bs, e.resolve(qValue.Field(i))...) 87 | } 88 | } 89 | return bs 90 | } 91 | 92 | func (e *bindConstructor) getBinding(name string) []uint8 { 93 | e.mux.Lock() 94 | defer e.mux.Unlock() 95 | return e.cache[name] 96 | } 97 | 98 | func (e *bindConstructor) setBinding(name string, bs []uint8) { 99 | e.mux.Lock() 100 | defer e.mux.Unlock() 101 | if e.cache == nil { 102 | e.cache = make(map[string][]uint8) 103 | } 104 | e.cache[name] = bs 105 | } 106 | -------------------------------------------------------------------------------- /common/service/service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-admin-team/go-admin-core/logger" 7 | "gorm.io/gorm" 8 | ) 9 | 10 | type Service struct { 11 | Orm *gorm.DB 12 | Msg string 13 | MsgID string 14 | Log *logger.Helper 15 | Error error 16 | } 17 | 18 | func (db *Service) AddError(err error) error { 19 | if db.Error == nil { 20 | db.Error = err 21 | } else if err != nil { 22 | db.Error = fmt.Errorf("%v; %w", db.Error, err) 23 | } 24 | return db.Error 25 | } 26 | -------------------------------------------------------------------------------- /common/storage/initialize.go: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: zhangwenjian 3 | * @Date: 2025/04/13 22:03 4 | * @Last Modified by: zhangwenjian 5 | * @Last Modified time: 2025/04/13 22:03 6 | */ 7 | 8 | package storage 9 | 10 | import ( 11 | "log" 12 | 13 | "github.com/go-admin-team/go-admin-core/sdk" 14 | "github.com/go-admin-team/go-admin-core/sdk/config" 15 | "github.com/go-admin-team/go-admin-core/sdk/pkg/captcha" 16 | ) 17 | 18 | // Setup 配置storage组件 19 | func Setup() { 20 | setupCache() 21 | setupCaptcha() 22 | setupQueue() 23 | } 24 | 25 | func setupCache() { 26 | cacheAdapter, err := config.CacheConfig.Setup() 27 | if err != nil { 28 | log.Fatalf("cache setup error, %s\n", err.Error()) 29 | } 30 | sdk.Runtime.SetCacheAdapter(cacheAdapter) 31 | } 32 | 33 | func setupCaptcha() { 34 | captcha.SetStore(captcha.NewCacheStore(sdk.Runtime.GetCacheAdapter(), 600)) 35 | } 36 | 37 | func setupQueue() { 38 | if config.QueueConfig.Empty() { 39 | return 40 | } 41 | if q := sdk.Runtime.GetQueueAdapter(); q != nil { 42 | q.Shutdown() 43 | } 44 | queueAdapter, err := config.QueueConfig.Setup() 45 | if err != nil { 46 | log.Fatalf("queue setup error, %s\n", err.Error()) 47 | } 48 | sdk.Runtime.SetQueueAdapter(queueAdapter) 49 | go queueAdapter.Run() 50 | } 51 | -------------------------------------------------------------------------------- /config/READMEN.md: -------------------------------------------------------------------------------- 1 | # ⚙ 配置详情 2 | 3 | 1. 配置文件说明 4 | ```yml 5 | settings: 6 | application: 7 | # 项目启动环境 8 | mode: dev # dev开发环境 prod线上环境; 9 | host: 0.0.0.0 # 主机ip 或者域名,默认0.0.0.0 10 | # 服务名称 11 | name: go-admin 12 | # 服务端口 13 | port: 8000 14 | readtimeout: 1 15 | writertimeout: 2 16 | log: 17 | # 日志文件存放路径 18 | dir: temp/logs 19 | jwt: 20 | # JWT加密字符串 21 | secret: go-admin 22 | # 过期时间单位:秒 23 | timeout: 3600 24 | database: 25 | # 数据库名称 26 | name: dbname 27 | # 数据库类型 28 | dbtype: mysql 29 | # 数据库地址 30 | host: 127.0.0.1 31 | # 数据库密码 32 | password: password 33 | # 数据库端口 34 | port: 3306 35 | # 数据库用户名 36 | username: root 37 | ``` -------------------------------------------------------------------------------- /config/db-begin-mysql.sql: -------------------------------------------------------------------------------- 1 | SET NAMES utf8mb4; 2 | SET FOREIGN_KEY_CHECKS = 0; -------------------------------------------------------------------------------- /config/db-end-mysql.sql: -------------------------------------------------------------------------------- 1 | SET FOREIGN_KEY_CHECKS = 1; -------------------------------------------------------------------------------- /config/extend.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | var ExtConfig Extend 4 | 5 | // Extend 扩展配置 6 | // extend: 7 | // demo: 8 | // name: demo-name 9 | // 使用方法: config.ExtConfig......即可!! 10 | type Extend struct { 11 | AMap AMap // 这里配置对应配置文件的结构即可 12 | } 13 | 14 | type AMap struct { 15 | Key string 16 | } 17 | -------------------------------------------------------------------------------- /config/pg.sql: -------------------------------------------------------------------------------- 1 | -- 开始初始化数据 ; 2 | create sequence if not exists sys_role_role_id_seq; 3 | create sequence if not exists sys_user_user_id_seq; 4 | create sequence if not exists sys_post_post_id_seq; 5 | create sequence if not exists sys_menu_menu_id_seq; 6 | create sequence if not exists sys_dict_type_dict_id_seq; 7 | create sequence if not exists sys_dict_data_dict_code_seq; 8 | create sequence if not exists sys_dept_dept_id_seq; 9 | create sequence if not exists sys_config_config_id_seq; 10 | create sequence if not exists sys_job_id_seq; 11 | 12 | select setval('sys_role_role_id_seq',4); 13 | select setval('sys_user_user_id_seq',5); 14 | select setval('sys_post_post_id_seq',4); 15 | select setval('sys_menu_menu_id_seq',543); 16 | select setval('sys_dict_type_dict_id_seq',12); 17 | select setval('sys_dict_data_dict_code_seq',34); 18 | select setval('sys_dept_dept_id_seq',11); 19 | select setval('sys_config_config_id_seq',6); 20 | select setval('sys_job_id_seq',3); 21 | -- 数据完成 ; 22 | -------------------------------------------------------------------------------- /config/settings.demo.yml: -------------------------------------------------------------------------------- 1 | settings: 2 | application: 3 | demomsg: "谢谢您的参与,但为了大家更好的体验,所以本次提交就算了吧!\U0001F600\U0001F600\U0001F600" 4 | enabledp: true 5 | host: 0.0.0.0 6 | mode: demo 7 | name: testApp 8 | port: 8000 9 | readtimeout: 10000 10 | writertimeout: 20000 11 | database: 12 | driver: sqlite3 13 | source: ./go-admin-db.db 14 | gen: 15 | dbname: testhhh 16 | frontpath: ../go-admin-ui/src 17 | jwt: 18 | secret: go-admin 19 | timeout: 3600 20 | logger: 21 | # 日志存放路径 22 | path: temp/logs 23 | # 日志输出,file:文件,default:命令行,其他:命令行 24 | stdout: '' #控制台日志,启用后,不输出到文件 25 | # 日志等级, trace, debug, info, warn, error, fatal 26 | level: trace 27 | # 数据库日志开关 28 | enableddb: true 29 | queue: 30 | memory: 31 | poolSize: 100 32 | extend: 33 | amap: 34 | key: de7a062c984bf828d5d1b3a631a517e4 -------------------------------------------------------------------------------- /config/settings.full.yml: -------------------------------------------------------------------------------- 1 | settings: 2 | application: 3 | # dev开发环境 test测试环境 prod线上环境 4 | mode: dev 5 | # 服务器ip,默认使用 0.0.0.0 6 | host: 0.0.0.0 7 | # 服务名称 8 | name: testApp 9 | # 端口号 10 | port: 8000 # 服务端口号 11 | readtimeout: 1 12 | writertimeout: 2 13 | # 数据权限功能开关 14 | enabledp: false 15 | ssl: 16 | # https对应的域名 17 | domain: localhost:8000 18 | # https开关 19 | enable: false 20 | # ssl 证书key 21 | key: keystring 22 | # ssl 证书路径 23 | pem: temp/pem.pem 24 | logger: 25 | # 日志存放路径 26 | path: temp/logs 27 | # 日志输出,file:文件,default:命令行,其他:命令行 28 | stdout: '' #控制台日志,启用后,不输出到文件 29 | # 日志等级, trace, debug, info, warn, error, fatal 30 | level: trace 31 | # 数据库日志开关 32 | enableddb: false 33 | jwt: 34 | # token 密钥,生产环境时及的修改 35 | secret: go-admin 36 | # token 过期时间 单位:秒 37 | timeout: 3600 38 | database: 39 | # 数据库类型 mysql,sqlite3, postgres 40 | driver: mysql 41 | # 数据库连接字符串 mysql 缺省信息 charset=utf8&parseTime=True&loc=Local&timeout=1000ms 42 | source: user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8&parseTime=True&loc=Local&timeout=1000ms 43 | # source: sqlite3.db 44 | # source: host=myhost port=myport user=gorm dbname=gorm password=mypassword 45 | registers: 46 | - sources: 47 | - user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8&parseTime=True&loc=Local&timeout=1000ms 48 | gen: 49 | # 代码生成读取的数据库名称 50 | dbname: dbname 51 | # 代码生成是使用前端代码存放位置,需要指定到src文件夹,相对路径 52 | frontpath: ../go-admin-ui/src 53 | queue: 54 | memory: 55 | poolSize: 100 56 | extend: # 扩展项使用说明 57 | demo: 58 | name: data 59 | -------------------------------------------------------------------------------- /config/settings.sqlite.yml: -------------------------------------------------------------------------------- 1 | settings: 2 | application: 3 | # dev开发环境 test测试环境 prod线上环境 4 | mode: dev 5 | # 服务器ip,默认使用 0.0.0.0 6 | host: 0.0.0.0 7 | # 服务名称 8 | name: testApp 9 | # 端口号 10 | port: 8000 # 服务端口号 11 | readtimeout: 3000 12 | writertimeout: 2000 13 | # 数据权限功能开关 14 | enabledp: false 15 | logger: 16 | # 日志存放路径 17 | path: temp/logs 18 | # 日志输出,file:文件,default:命令行,其他:命令行 19 | stdout: '' #控制台日志,启用后,不输出到文件 20 | # 日志等级, trace, debug, info, warn, error, fatal 21 | level: trace 22 | # 数据库日志开关 23 | enableddb: false 24 | jwt: 25 | # token 密钥,生产环境时及的修改 26 | secret: go-admin 27 | # token 过期时间 单位:秒 28 | timeout: 3600 29 | database: 30 | # 数据库类型 mysql,sqlite3, postgres 31 | driver: sqlite3 32 | # 数据库连接sqlite3数据文件的路径 33 | source: go-admin-db.db 34 | gen: 35 | # 代码生成读取的数据库名称 36 | dbname: dbname 37 | # 代码生成是使用前端代码存放位置,需要指定到src文件夹,相对路径 38 | frontpath: ../go-admin-ui/src 39 | -------------------------------------------------------------------------------- /config/settings.yml: -------------------------------------------------------------------------------- 1 | settings: 2 | application: 3 | # dev开发环境 test测试环境 prod线上环境 4 | mode: dev 5 | # 服务器ip,默认使用 0.0.0.0 6 | host: 0.0.0.0 7 | # 服务名称 8 | name: testApp 9 | # 端口号 10 | port: 8000 # 服务端口号 11 | readtimeout: 1 12 | writertimeout: 2 13 | # 数据权限功能开关 14 | enabledp: false 15 | logger: 16 | # 日志存放路径 17 | path: temp/logs 18 | # 日志输出,file:文件,default:命令行,其他:命令行 19 | stdout: '' #控制台日志,启用后,不输出到文件 20 | # 日志等级, trace, debug, info, warn, error, fatal 21 | level: trace 22 | # 数据库日志开关 23 | enableddb: false 24 | jwt: 25 | # token 密钥,生产环境时及的修改 26 | secret: go-admin 27 | # token 过期时间 单位:秒 28 | timeout: 3600 29 | database: 30 | # 数据库类型 mysql, sqlite3, postgres, sqlserver 31 | # sqlserver: sqlserver://用户名:密码@地址?database=数据库名 32 | driver: mysql 33 | # 数据库连接字符串 mysql 缺省信息 charset=utf8&parseTime=True&loc=Local&timeout=1000ms 34 | source: user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8&parseTime=True&loc=Local&timeout=1000ms 35 | # databases: 36 | # 'locaohost:8000': 37 | # driver: mysql 38 | # # 数据库连接字符串 mysql 缺省信息 charset=utf8&parseTime=True&loc=Local&timeout=1000ms 39 | # source: user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8&parseTime=True&loc=Local&timeout=1000ms 40 | # registers: 41 | # - sources: 42 | # - user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8&parseTime=True&loc=Local&timeout=1000ms 43 | gen: 44 | # 代码生成读取的数据库名称 45 | dbname: dbname 46 | # 代码生成是使用前端代码存放位置,需要指定到src文件夹,相对路径 47 | frontpath: ../go-admin-ui/src 48 | extend: # 扩展项使用说明 49 | demo: 50 | name: data 51 | cache: 52 | # redis: 53 | # addr: 127.0.0.1:6379 54 | # password: xxxxxx 55 | # db: 2 56 | # key存在即可 57 | memory: '' 58 | queue: 59 | memory: 60 | poolSize: 100 61 | # redis: 62 | # addr: 127.0.0.1:6379 63 | # password: xxxxxx 64 | # producer: 65 | # streamMaxLength: 100 66 | # approximateMaxLength: true 67 | # consumer: 68 | # visibilityTimeout: 60 69 | # bufferSize: 100 70 | # concurrency: 10 71 | # blockingTimeout: 5 72 | # reclaimInterval: 1 73 | locker: 74 | redis: -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | services: 3 | go-admin-api: 4 | container_name: go-admin 5 | image: go-admin:latest 6 | privileged: true 7 | restart: always 8 | ports: 9 | - 8000:8000 10 | volumes: 11 | - ./config/:/go-admin-api/config/ 12 | - ./static/:/go-admin-api/static/ 13 | - ./temp/:/go-admin-api/temp/ 14 | networks: 15 | - myweb 16 | networks: 17 | myweb: 18 | driver: bridge 19 | 20 | -------------------------------------------------------------------------------- /go-admin-db.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-admin-team/go-admin/3f995735e9864e306a29a1f42501ddf8239622e6/go-admin-db.db -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "go-admin/cmd" 5 | ) 6 | 7 | //go:generate swag init --parseDependency --parseDepth=6 --instanceName admin -o ./docs/admin 8 | 9 | // @title go-admin API 10 | // @version 2.0.0 11 | // @description 基于Gin + Vue + Element UI的前后端分离权限管理系统的接口文档 12 | // @description 添加qq群: 521386980 进入技术交流群 请先star,谢谢! 13 | // @license.name MIT 14 | // @license.url https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md 15 | 16 | // @securityDefinitions.apikey Bearer 17 | // @in header 18 | // @name Authorization 19 | func main() { 20 | cmd.Execute() 21 | } 22 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "lockfileVersion": 1 3 | } 4 | -------------------------------------------------------------------------------- /restart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "go build" 3 | go mod tidy 4 | go build -o go-admin main.go 5 | chmod +x ./go-admin 6 | echo "kill go-admin service" 7 | killall go-admin # kill go-admin service 8 | nohup ./go-admin server -c=config/settings.dev.yml >> access.log 2>&1 & #后台启动服务将日志写入access.log文件 9 | echo "run go-admin success" 10 | ps -aux | grep go-admin 11 | -------------------------------------------------------------------------------- /scripts/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine 2 | 3 | COPY ./go-admin / 4 | EXPOSE 8000 5 | 6 | CMD ["/go-admin","server","-c", "/config/settings.yml"] 7 | -------------------------------------------------------------------------------- /scripts/k8s/deploy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: go-admin 6 | labels: 7 | app: go-admin 8 | service: go-admin 9 | spec: 10 | ports: 11 | - port: 8000 12 | name: http 13 | protocol: TCP 14 | selector: 15 | app: go-admin 16 | --- 17 | apiVersion: apps/v1 18 | kind: Deployment 19 | metadata: 20 | name: go-admin-v1 21 | labels: 22 | app: go-admin 23 | version: v1 24 | spec: 25 | replicas: 1 26 | selector: 27 | matchLabels: 28 | app: go-admin 29 | version: v1 30 | template: 31 | metadata: 32 | labels: 33 | app: go-admin 34 | version: v1 35 | spec: 36 | containers: 37 | - name: go-admin 38 | image: registry.cn-shanghai.aliyuncs.com/go-admin-team/go-admin 39 | imagePullPolicy: IfNotPresent 40 | ports: 41 | - containerPort: 8000 42 | volumeMounts: 43 | - name: go-admin 44 | mountPath: /temp 45 | - name: go-admin 46 | mountPath: /static 47 | - name: go-admin-config 48 | mountPath: /config/ 49 | readOnly: true 50 | volumes: 51 | - name: go-admin 52 | persistentVolumeClaim: 53 | claimName: go-admin 54 | - name: go-admin-config 55 | configMap: 56 | name: settings-admin 57 | --- 58 | -------------------------------------------------------------------------------- /scripts/k8s/prerun.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | kubectl create ns go-admin 3 | kubectl create configmap settings-admin --from-file=../../config/settings.yml -n go-admin 4 | -------------------------------------------------------------------------------- /scripts/k8s/storage.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: go-admin 5 | namespace: go-admin 6 | spec: 7 | accessModes: 8 | - ReadWriteMany 9 | resources: 10 | requests: 11 | storage: "1Mi" 12 | volumeName: 13 | storageClassName: nfs-csi -------------------------------------------------------------------------------- /ssh/swag.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | swag i -g init_router.go -dir app/admin/router --instanceName admin --parseDependency -o docs/admin 4 | -------------------------------------------------------------------------------- /static/form-generator/css/parser-example.69e16e51.css: -------------------------------------------------------------------------------- 1 | .test-form[data-v-77b1aafa]{margin:15px auto;width:800px;padding:15px} -------------------------------------------------------------------------------- /static/form-generator/img/logo.e1bc3747.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-admin-team/go-admin/3f995735e9864e306a29a1f42501ddf8239622e6/static/form-generator/img/logo.e1bc3747.png -------------------------------------------------------------------------------- /static/form-generator/js/tinymce-example.641995ab.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["tinymce-example"],{a5aa:function(e,t,n){"use strict";n.r(t);var a=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",[n("Tinymce",{attrs:{height:300,placeholder:"在这里输入文字"},model:{value:e.defaultValue,callback:function(t){e.defaultValue=t},expression:"defaultValue"}})],1)},c=[],u=n("31c6"),l={components:{Tinymce:u["a"]},props:{},data:function(){return{defaultValue:"

配置文档参阅:http://tinymce.ax-z.cn

"}},computed:{},watch:{},created:function(){},mounted:function(){},methods:{}},o=l,i=n("2877"),p=Object(i["a"])(o,a,c,!1,null,null,null);t["default"]=p.exports}}]); -------------------------------------------------------------------------------- /static/form-generator/preview.html: -------------------------------------------------------------------------------- 1 | form-generator-preview
-------------------------------------------------------------------------------- /static/uploadfile/77cfc1dd-535c-4e60-b34a-5909e2cf5ed0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-admin-team/go-admin/3f995735e9864e306a29a1f42501ddf8239622e6/static/uploadfile/77cfc1dd-535c-4e60-b34a-5909e2cf5ed0.jpg -------------------------------------------------------------------------------- /static/uploadfile/log.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-admin-team/go-admin/3f995735e9864e306a29a1f42501ddf8239622e6/static/uploadfile/log.txt -------------------------------------------------------------------------------- /stop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | killall go-admin # kill go-admin service 3 | echo "stop go-admin success" 4 | ps -aux | grep go-admin -------------------------------------------------------------------------------- /template/cmd_api.template: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "go-admin/app/{{.appName}}/router" 4 | 5 | func init() { 6 | //注册路由 fixme 其他应用的路由,在本目录新建文件放在init方法 7 | AppRouters = append(AppRouters, router.InitRouter) 8 | } -------------------------------------------------------------------------------- /template/migrate.template: -------------------------------------------------------------------------------- 1 | package {{.Package}} 2 | 3 | import ( 4 | "gorm.io/gorm" 5 | "runtime" 6 | 7 | "go-admin/cmd/migrate/migration" 8 | common "go-admin/common/models" 9 | ) 10 | 11 | func init() { 12 | _, fileName, _, _ := runtime.Caller(0) 13 | migration.Migrate.SetVersion(migration.GetFilename(fileName), _{{.GenerateTime}}Test) 14 | } 15 | 16 | func _{{.GenerateTime}}Test(db *gorm.DB, version string) error { 17 | return db.Transaction(func(tx *gorm.DB) error { 18 | 19 | // TODO: 这里开始写入要变更的内容 20 | 21 | // TODO: 例如 修改表字段 使用过程中请删除此段代码 22 | //err := tx.Migrator().RenameColumn(&models.SysConfig{}, "config_id", "id") 23 | //if err != nil { 24 | // return err 25 | //} 26 | 27 | // TODO: 例如 新增表结构 使用过程中请删除此段代码 28 | //err = tx.Debug().Migrator().AutoMigrate( 29 | // new(models.CasbinRule), 30 | // ) 31 | //if err != nil { 32 | // return err 33 | //} 34 | 35 | 36 | return tx.Create(&common.Migration{ 37 | Version: version, 38 | }).Error 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /template/router.template: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | 4 | import ( 5 | "github.com/gin-gonic/gin" 6 | _ "github.com/gin-gonic/gin" 7 | log "github.com/go-admin-team/go-admin-core/logger" 8 | "github.com/go-admin-team/go-admin-core/sdk" 9 | // "github.com/go-admin-team/go-admin-core/sdk/pkg" 10 | "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 11 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 12 | common "go-admin/common/middleware" 13 | "os" 14 | ) 15 | 16 | var ( 17 | routerNoCheckRole = make([]func(*gin.RouterGroup), 0) 18 | routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0) 19 | ) 20 | 21 | // InitRouter 路由初始化 22 | func InitRouter() { 23 | var r *gin.Engine 24 | h := sdk.Runtime.GetEngine() 25 | if h == nil { 26 | h = gin.New() 27 | sdk.Runtime.SetEngine(h) 28 | } 29 | switch h.(type) { 30 | case *gin.Engine: 31 | r = h.(*gin.Engine) 32 | default: 33 | log.Fatal("not support other engine") 34 | os.Exit(-1) 35 | } 36 | 37 | // the jwt middleware 38 | authMiddleware, err := common.AuthInit() 39 | if err != nil { 40 | log.Fatalf("JWT Init Error, %s", err.Error()) 41 | } 42 | 43 | // 注册业务路由 44 | InitBusinessRouter(r, authMiddleware) 45 | } 46 | 47 | func InitBusinessRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine { 48 | 49 | // 无需认证的路由 50 | noCheckRoleRouter(r) 51 | // 需要认证的路由 52 | checkRoleRouter(r, authMiddleware) 53 | 54 | return r 55 | } 56 | 57 | // noCheckRoleRouter 无需认证的路由 58 | func noCheckRoleRouter(r *gin.Engine) { 59 | // 可根据业务需求来设置接口版本 60 | v := r.Group("/api/v1") 61 | 62 | for _, f := range routerNoCheckRole { 63 | f(v) 64 | } 65 | } 66 | 67 | // checkRoleRouter 需要认证的路由 68 | func checkRoleRouter(r *gin.Engine, authMiddleware *jwtauth.GinJWTMiddleware) { 69 | // 可根据业务需求来设置接口版本 70 | v := r.Group("/api/v1") 71 | 72 | for _, f := range routerCheckRole { 73 | f(v, authMiddleware) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /template/v4/actions/router_check_role.go.template: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | 7 | "go-admin/app/{{.PackageName}}/models" 8 | "go-admin/app/{{.PackageName}}/service/dto" 9 | "go-admin/common/actions" 10 | "go-admin/common/middleware" 11 | ) 12 | 13 | func init() { 14 | routerCheckRole = append(routerCheckRole, register{{.ClassName}}Router) 15 | } 16 | 17 | // 需认证的路由代码 18 | func register{{.ClassName}}Router(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 19 | r := v1.Group("/{{.ModuleName}}").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 20 | { 21 | model := &models.{{.ClassName}}{} 22 | r.GET("", actions.PermissionAction(), actions.IndexAction(model, new(dto.{{.ClassName}}Search), func() interface{} { 23 | list := make([]models.{{.ClassName}}, 0) 24 | return &list 25 | })) 26 | r.GET("/:id", actions.PermissionAction(), actions.ViewAction(new(dto.{{.ClassName}}ById), nil)) 27 | r.POST("", actions.CreateAction(new(dto.{{.ClassName}}Control))) 28 | r.PUT("/:id", actions.PermissionAction(), actions.UpdateAction(new(dto.{{.ClassName}}Control))) 29 | r.DELETE("", actions.PermissionAction(), actions.DeleteAction(new(dto.{{.ClassName}}ById))) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /template/v4/actions/router_no_check_role.go.template: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | 6 | "go-admin/app/{{.PackageName}}/middleware" 7 | "go-admin/app/{{.PackageName}}/models" 8 | "go-admin/app/{{.PackageName}}/service/dto" 9 | "go-admin/common/actions" 10 | ) 11 | 12 | func init() { 13 | routerNoCheckRole = append(routerNoCheckRole, register{{.ClassName}}Router) 14 | } 15 | 16 | // 无需认证的路由代码 17 | func register{{.ClassName}}Router(v1 *gin.RouterGroup) { 18 | r := v1.Group("/{{.ModuleName}}") 19 | { 20 | model := &models.{{.ClassName}}{} 21 | r.GET("", actions.IndexAction(model, new(dto.{{.ClassName}}Search), func() interface{} { 22 | list := make([]models.{{.ClassName}}, 0) 23 | return &list 24 | })) 25 | r.GET("/:id", actions.ViewAction(new(dto.{{.ClassName}}ById), nil)) 26 | r.POST("", actions.CreateAction(new(dto.{{.ClassName}}Control))) 27 | r.PUT("/:id", actions.UpdateAction(new(dto.{{.ClassName}}Control))) 28 | r.DELETE("", actions.DeleteAction(new(dto.{{.ClassName}}ById))) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /template/v4/js.go.template: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 查询{{.ClassName}}列表 4 | export function list{{.ClassName}}(query) { 5 | return request({ 6 | url: '/api/v1/{{.ModuleName}}', 7 | method: 'get', 8 | params: query 9 | }) 10 | } 11 | 12 | // 查询{{.ClassName}}详细 13 | export function get{{.ClassName}} ({{.PkJsonField}}) { 14 | return request({ 15 | url: '/api/v1/{{.ModuleName}}/' + {{.PkJsonField}}, 16 | method: 'get' 17 | }) 18 | } 19 | 20 | 21 | // 新增{{.ClassName}} 22 | export function add{{.ClassName}}(data) { 23 | return request({ 24 | url: '/api/v1/{{.ModuleName}}', 25 | method: 'post', 26 | data: data 27 | }) 28 | } 29 | 30 | // 修改{{.ClassName}} 31 | export function update{{.ClassName}}(data) { 32 | return request({ 33 | url: '/api/v1/{{.ModuleName}}/'+data.{{.PkJsonField}}, 34 | method: 'put', 35 | data: data 36 | }) 37 | } 38 | 39 | // 删除{{.ClassName}} 40 | export function del{{.ClassName}}(data) { 41 | return request({ 42 | url: '/api/v1/{{.ModuleName}}', 43 | method: 'delete', 44 | data: data 45 | }) 46 | } 47 | 48 | -------------------------------------------------------------------------------- /template/v4/model.go.template: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | {{- $bb := false -}} 5 | {{- range .Columns -}} 6 | {{- $z := .IsQuery -}} 7 | {{- if ($z) -}} 8 | {{- if eq .GoType "time.Time" -}}{{- $bb = true -}}{{- end -}} 9 | {{- end -}} 10 | {{- end -}} 11 | {{- range .Columns -}} 12 | {{- if eq .GoField "CreatedAt" -}} 13 | {{- else if eq .GoField "UpdatedAt" -}} 14 | {{- else if eq .GoField "DeletedAt" -}} 15 | {{- else -}} 16 | {{- if eq .GoType "time.Time" -}}{{- $bb = true -}}{{- end -}} 17 | {{- end -}} 18 | {{- end -}} 19 | {{- if eq $bb true }} 20 | "time" 21 | {{- end }} 22 | 23 | "go-admin/common/models" 24 | 25 | ) 26 | 27 | type {{.ClassName}} struct { 28 | models.Model 29 | {{ range .Columns -}} 30 | {{$x := .Pk}} 31 | {{- if ($x) }} 32 | {{- else if eq .GoField "CreatedAt" -}} 33 | {{- else if eq .GoField "UpdatedAt" -}} 34 | {{- else if eq .GoField "DeletedAt" -}} 35 | {{- else if eq .GoField "CreateBy" -}} 36 | {{- else if eq .GoField "UpdateBy" -}} 37 | {{- else }} 38 | {{.GoField}} {{.GoType}} `json:"{{.JsonField}}" gorm:"type:{{.ColumnType}};comment:{{- if eq .ColumnComment "" -}}{{.GoField}}{{- else -}}{{.ColumnComment}}{{end -}}"` {{end -}} 39 | {{- end }} 40 | models.ModelTime 41 | models.ControlBy 42 | } 43 | 44 | func ({{.ClassName}}) TableName() string { 45 | return "{{.TBName}}" 46 | } 47 | 48 | func (e *{{.ClassName}}) Generate() models.ActiveRecord { 49 | o := *e 50 | return &o 51 | } 52 | 53 | func (e *{{.ClassName}}) GetId() interface{} { 54 | return e.{{.PkGoField}} 55 | } -------------------------------------------------------------------------------- /template/v4/no_actions/router_check_role.go.template: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | 7 | "go-admin/app/{{.PackageName}}/apis" 8 | "go-admin/common/middleware" 9 | "go-admin/common/actions" 10 | ) 11 | 12 | func init() { 13 | routerCheckRole = append(routerCheckRole, register{{.ClassName}}Router) 14 | } 15 | 16 | // register{{.ClassName}}Router 17 | func register{{.ClassName}}Router(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 18 | api := apis.{{.ClassName}}{} 19 | r := v1.Group("/{{.ModuleName}}").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 20 | { 21 | r.GET("", actions.PermissionAction(), api.GetPage) 22 | r.GET("/:id", actions.PermissionAction(), api.Get) 23 | r.POST("", api.Insert) 24 | r.PUT("/:id", actions.PermissionAction(), api.Update) 25 | r.DELETE("", api.Delete) 26 | } 27 | } -------------------------------------------------------------------------------- /template/v4/no_actions/router_no_check_role.go.template: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | 7 | "go-admin/app/{{.PackageName}}/apis" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, register{{.ClassName}}Router) 12 | } 13 | 14 | // register{{.ClassName}}Router 15 | func register{{.ClassName}}Router(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 16 | api := apis.{{.ClassName}}{} 17 | r := v1.Group("/{{.ModuleName}}").Use(authMiddleware.MiddlewareFunc()) 18 | { 19 | r.GET("", api.GetPage) 20 | r.GET("/:id", api.Get) 21 | r.POST("", api.Insert) 22 | r.PUT("/:id", api.Update) 23 | r.DELETE("", api.Delete) 24 | } 25 | } -------------------------------------------------------------------------------- /test/gen_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | //"go-admin/models/tools" 5 | //"os" 6 | "testing" 7 | //"text/template" 8 | ) 9 | 10 | func TestGoModelTemplate(t *testing.T) { 11 | //t1, err := template.ParseFiles("model.go.template") 12 | //if err != nil { 13 | // t.Error(err) 14 | //} 15 | //table := tools.SysTables{} 16 | //table.TBName = "sys_tables" 17 | //tab, err := table.Get() 18 | //if err != nil { 19 | // t.Error(err) 20 | //} 21 | //file, err := os.Create("models/" + table.PackageName + ".go") 22 | //if err != nil { 23 | // t.Error(err) 24 | //} 25 | //defer file.Close() 26 | // 27 | //_ = t1.Execute(file, tab) 28 | t.Log("") 29 | } 30 | 31 | func TestGoApiTemplate(t *testing.T) { 32 | //t1, err := template.ParseFiles("api.go.template") 33 | //if err != nil { 34 | // t.Error(err) 35 | //} 36 | //table := tools.SysTables{} 37 | //table.TBName = "sys_tables" 38 | //tab, _ := table.Get() 39 | //file, err := os.Create("apis/" + table.PackageName + ".go") 40 | //if err != nil { 41 | // t.Error(err) 42 | //} 43 | //defer file.Close() 44 | // 45 | //_ = t1.Execute(file, tab) 46 | t.Log("") 47 | } 48 | -------------------------------------------------------------------------------- /test/model.go.template: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | orm "go-admin/global" 5 | "go-admin/utils" 6 | "time" 7 | ) 8 | 9 | type {{.ClassName}} struct { 10 | 11 | {{ range .Columns -}} 12 | {{$x := .Pk}} 13 | // {{.ColumnComment}} 14 | {{if ($x)}}{{.GoField}} {{.GoType}} `json:"{{.JsonField}}" gorm:"column:{{.ColumnName}};primary_key"`{{else}}{{.GoField}} {{.GoType}} `json:"{{.JsonField}}" gorm:"column:{{.ColumnName}};"`{{end}} 15 | {{ end -}} 16 | } 17 | 18 | // 创建{{.ClassName}} 19 | func (e *{{.ClassName}}) Create() ({{.ClassName}}, error) { 20 | var doc {{.ClassName}} 21 | doc.IsDel = "0" 22 | e.CreateTime = time.Now().String() 23 | result := orm.Eloquent.Table("{{.TableName}}").Create(&e) 24 | if result.Error != nil { 25 | err := result.Error 26 | return doc, err 27 | } 28 | doc = *e 29 | return doc, nil 30 | } 31 | 32 | // 获取{{.ClassName}} 33 | func (e *{{.ClassName}}) Get() ({{.ClassName}}, error) { 34 | var doc {{.ClassName}} 35 | 36 | table := orm.Eloquent.Table("{{.TableName}}") 37 | {{ range .Columns -}} 38 | {{$z := .IsQuery}} 39 | {{- if ($z) -}}if e.{{.GoField}} != "" { 40 | table = table.Where("{{.ColumnName}} = ?", e.{{.GoField}}) 41 | } 42 | {{ end }} 43 | {{- end -}} 44 | 45 | if err := table.First(&doc).Error; err != nil { 46 | return doc, err 47 | } 48 | return doc, nil 49 | } 50 | 51 | // 获取{{.ClassName}}带分页 52 | func (e *{{.ClassName}}) GetPage(pageSize int, pageIndex int) ([]{{.ClassName}}, int32, error) { 53 | var doc []{{.ClassName}} 54 | 55 | table := orm.Eloquent.Table("{{.TableName}}") 56 | {{ range .Columns -}} 57 | {{$z := .IsQuery}} 58 | {{- if ($z) -}}if e.{{.GoField}} != "" { 59 | table = table.Where("{{.ColumnName}} = ?", e.{{.GoField}}) 60 | } 61 | {{ end }} 62 | {{- end -}} 63 | 64 | // 数据权限控制 65 | dataPermission := new(DataPermission) 66 | dataPermission.UserId, _ = utils.StringToInt(e.DataScope) 67 | table,err := dataPermission.GetDataScope("{{.TableName}}", table) 68 | if err != nil { 69 | return nil, 0, err 70 | } 71 | var count int32 72 | table = table.Offset((pageIndex - 1) * pageSize).Limit(pageSize) 73 | if err := table.Find(&doc).Offset(-1).Limit(-1).Count(&count).Error; err != nil { 74 | return nil, 0, err 75 | } 76 | return doc, count, nil 77 | } 78 | 79 | // 更新{{.ClassName}} 80 | func (e *{{.ClassName}}) Update(id int) (update {{.ClassName}}, err error) { 81 | if err = orm.Eloquent.Table("{{.TableName}}").Where("{{.PkColumn}} = ?", id).First(&update).Error; err != nil { 82 | return 83 | } 84 | 85 | //参数1:是要修改的数据 86 | //参数2:是修改的数据 87 | if err = orm.Eloquent.Table("{{.TableName}}").Model(&update).Updates(&e).Error; err != nil { 88 | return 89 | } 90 | return 91 | } 92 | 93 | // 删除{{.ClassName}} 94 | func (e *{{.ClassName}}) Delete(id int) (success bool, err error) { 95 | 96 | if err = orm.Eloquent.Table("{{.TableName}}").Where("{{.PkColumn}} = ?", id).Delete(&{{.ClassName}}{}).Error; err != nil { 97 | success = false 98 | return 99 | } 100 | success = true 101 | return 102 | } 103 | 104 | --------------------------------------------------------------------------------