From 20a741ae113395822b00712f4f7be1380b4ef9df Mon Sep 17 00:00:00 2001 From: hucan <951870319@qq.com> Date: Mon, 12 May 2025 14:49:01 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E5=88=9D=E5=A7=8B=E5=8C=96=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 23 + Dockerfile | 18 + Dockerfilebak | 28 + LICENSE.md | 21 + Makefile | 54 + README.Zh-cn.md | 353 ++ README.md | 342 ++ _config.yml | 1 + app/admin/apis/captcha.go | 37 + app/admin/apis/go_admin.go | 39 + app/admin/apis/sys_api.go | 148 + app/admin/apis/sys_config.go | 313 ++ app/admin/apis/sys_dept.go | 238 + app/admin/apis/sys_dict_data.go | 220 + app/admin/apis/sys_dict_type.go | 210 + app/admin/apis/sys_login_log.go | 110 + app/admin/apis/sys_menu.go | 287 ++ app/admin/apis/sys_opera_log.go | 118 + app/admin/apis/sys_post.go | 184 + app/admin/apis/sys_role.go | 284 ++ app/admin/apis/sys_user.go | 459 ++ app/admin/models/casbin_rule.go | 16 + app/admin/models/datascope.go | 81 + app/admin/models/initdb.go | 55 + app/admin/models/model.go | 11 + app/admin/models/sys_api.go | 91 + app/admin/models/sys_config.go | 30 + app/admin/models/sys_dept.go | 33 + app/admin/models/sys_dict_data.go | 34 + app/admin/models/sys_dict_type.go | 28 + app/admin/models/sys_login_log.go | 72 + app/admin/models/sys_menu.go | 50 + app/admin/models/sys_opera_log.go | 88 + app/admin/models/sys_post.go | 30 + app/admin/models/sys_role.go | 35 + app/admin/models/sys_user.go | 77 + app/admin/router/init_router.go | 40 + app/admin/router/router.go | 41 + app/admin/router/sys_api.go | 24 + app/admin/router/sys_config.go | 43 + app/admin/router/sys_dept.go | 32 + app/admin/router/sys_dict.go | 37 + app/admin/router/sys_login_log.go | 24 + app/admin/router/sys_menu.go | 33 + app/admin/router/sys_opera_log.go | 23 + app/admin/router/sys_post.go | 25 + app/admin/router/sys_role.go | 31 + app/admin/router/sys_router.go | 88 + app/admin/router/sys_user.go | 39 + app/admin/service/dto/sys_api.go | 95 + app/admin/service/dto/sys_config.go | 112 + app/admin/service/dto/sys_dept.go | 110 + app/admin/service/dto/sys_dict_data.go | 108 + app/admin/service/dto/sys_dict_type.go | 89 + app/admin/service/dto/sys_login_log.go | 57 + app/admin/service/dto/sys_menu.go | 159 + app/admin/service/dto/sys_opera_log.go | 102 + app/admin/service/dto/sys_post.go | 111 + app/admin/service/dto/sys_role.go | 164 + app/admin/service/dto/sys_user.go | 189 + app/admin/service/sys_api.go | 123 + app/admin/service/sys_config.go | 182 + app/admin/service/sys_dept.go | 295 ++ app/admin/service/sys_dict_data.go | 121 + app/admin/service/sys_dict_type.go | 124 + app/admin/service/sys_login_log.go | 70 + app/admin/service/sys_menu.go | 423 ++ app/admin/service/sys_opera_log.go | 83 + app/admin/service/sys_post.go | 105 + app/admin/service/sys_role.go | 352 ++ app/admin/service/sys_role_menu.go | 110 + app/admin/service/sys_user.go | 266 + app/jobs/apis/sys_job.go | 69 + app/jobs/examples.go | 40 + app/jobs/jobbase.go | 203 + app/jobs/models/sys_job.go | 61 + app/jobs/router/int_router.go | 36 + app/jobs/router/router.go | 42 + app/jobs/router/sys_job.go | 38 + app/jobs/service/dto/sys_job.go | 108 + app/jobs/service/sys_job.go | 93 + app/jobs/type.go | 16 + app/other/apis/file.go | 204 + app/other/apis/sys_server_monitor.go | 186 + app/other/apis/tools/db_columns.go | 52 + app/other/apis/tools/db_tables.go | 60 + app/other/apis/tools/gen.go | 410 ++ app/other/apis/tools/sys_tables.go | 361 ++ app/other/models/tools/db_columns.go | 70 + app/other/models/tools/db_tables.go | 62 + app/other/models/tools/sys_columns.go | 100 + app/other/models/tools/sys_tables.go | 238 + app/other/router/file.go | 20 + app/other/router/gen_router.go | 56 + app/other/router/init_router.go | 36 + app/other/router/monitor.go | 23 + app/other/router/router.go | 42 + app/other/router/sys_server_monitor.go | 21 + app/other/service/dto/sys_tables.go | 6 + cmd/api/jobs.go | 8 + cmd/api/other.go | 8 + cmd/api/server.go | 186 + cmd/app/server.go | 90 + cmd/cobra.go | 57 + cmd/config/server.go | 63 + cmd/migrate/migration/init.go | 66 + cmd/migrate/migration/models/by.go | 22 + cmd/migrate/migration/models/casbin_rule.go | 17 + cmd/migrate/migration/models/initdb.go | 72 + cmd/migrate/migration/models/model.go | 11 + cmd/migrate/migration/models/role_dept.go | 10 + cmd/migrate/migration/models/sys_api.go | 16 + cmd/migrate/migration/models/sys_columns.go | 44 + cmd/migrate/migration/models/sys_config.go | 17 + cmd/migrate/migration/models/sys_dept.go | 19 + cmd/migrate/migration/models/sys_dict_data.go | 21 + cmd/migrate/migration/models/sys_dict_type.go | 15 + cmd/migrate/migration/models/sys_job.go | 21 + cmd/migrate/migration/models/sys_login_log.go | 26 + cmd/migrate/migration/models/sys_menu.go | 27 + cmd/migrate/migration/models/sys_opera_log.go | 34 + cmd/migrate/migration/models/sys_post.go | 16 + cmd/migrate/migration/models/sys_role.go | 20 + cmd/migrate/migration/models/sys_tables.go | 37 + cmd/migrate/migration/models/sys_user.go | 48 + cmd/migrate/migration/models/tb_demo.go | 12 + cmd/migrate/migration/version-local/doc.go | 8 + .../migration/version/1599190683659_tables.go | 53 + .../version/1653638869132_migrate.go | 48 + cmd/migrate/server.go | 106 + cmd/version/server.go | 26 + common/actions/create.go | 49 + common/actions/delete.go | 61 + common/actions/index.go | 58 + common/actions/permission.go | 96 + common/actions/type.go | 5 + common/actions/update.go | 59 + common/actions/view.go | 67 + common/apis/api.go | 135 + common/database/initialize.go | 65 + common/database/open.go | 16 + common/database/open_sqlite3.go | 19 + common/dto/auto_form.go | 74 + common/dto/generate.go | 106 + common/dto/order.go | 12 + common/dto/pagination.go | 20 + common/dto/search.go | 84 + common/dto/type.go | 21 + common/file_store/initialize.go | 45 + common/file_store/interface.go | 27 + common/file_store/kodo.go | 111 + common/file_store/kodo_test.go | 23 + common/file_store/obs.go | 52 + common/file_store/obs_test.go | 15 + common/file_store/oss.go | 48 + common/file_store/oss_test.go | 16 + common/global/adm.go | 11 + common/global/casbin.go | 18 + common/global/logo.go | 4 + common/global/topic.go | 7 + common/ip.go | 27 + common/middleware/auth.go | 36 + common/middleware/customerror.go | 61 + common/middleware/db.go | 11 + common/middleware/demo.go | 29 + common/middleware/handler/auth.go | 182 + common/middleware/handler/httpshandler.go | 22 + common/middleware/handler/login.go | 33 + common/middleware/handler/ping.go | 11 + common/middleware/handler/role.go | 24 + common/middleware/handler/user.go | 40 + common/middleware/header.go | 48 + common/middleware/init.go | 35 + common/middleware/logger.go | 136 + common/middleware/permission.go | 61 + common/middleware/request_id.go | 36 + common/middleware/sentinel.go | 30 + common/middleware/settings.go | 43 + common/middleware/trace.go | 27 + common/models/by.go | 32 + common/models/menu.go | 11 + common/models/migrate.go | 12 + common/models/response.go | 30 + common/models/type.go | 11 + common/models/user.go | 42 + common/response/binding.go | 105 + common/service/service.go | 25 + common/storage/initialize.go | 52 + config/READMEN.md | 37 + config/db-begin-mysql.sql | 2 + config/db-end-mysql.sql | 1 + config/db-sqlserver.sql | 342 ++ config/db.sql | 324 ++ config/extend.go | 16 + config/pg.sql | 21 + config/settings.demo.yml | 34 + config/settings.full.yml | 58 + config/settings.sqlite.yml | 38 + config/settings.yml | 74 + docker-compose.yml | 19 + docs/admin/admin_docs.go | 4373 +++++++++++++++++ docs/admin/admin_swagger.json | 4348 ++++++++++++++++ docs/admin/admin_swagger.yaml | 2771 +++++++++++ examples/run.go | 28 + go-admin-db.db | Bin 0 -> 348160 bytes go.mod | 146 + main.go | 21 + package-lock.json | 3 + restart.sh | 10 + scripts/Dockerfile | 6 + scripts/k8s/deploy.yml | 57 + scripts/k8s/prerun.sh | 3 + scripts/k8s/storage.yml | 13 + ssh/swag.sh | 3 + static/form-generator/css/index.1a124643.css | 1 + .../css/parser-example.69e16e51.css | 1 + static/form-generator/img/logo.e1bc3747.png | Bin 0 -> 10543 bytes static/form-generator/index.html | 1 + .../js/chunk-vendors.971555db.js | 19 + static/form-generator/js/index.8e6d9f8f.js | 1 + .../js/parser-example.ce55fa09.js | 1 + static/form-generator/js/preview.8ce4e0db.js | 1 + .../js/tinymce-example.641995ab.js | 1 + static/form-generator/preview.html | 1 + stop.sh | 4 + template/api_migrate.template | 326 ++ template/cmd_api.template | 8 + template/migrate.template | 40 + template/router.template | 75 + .../v4/actions/router_check_role.go.template | 31 + .../actions/router_no_check_role.go.template | 30 + template/v4/dto.go.template | 151 + template/v4/js.go.template | 47 + template/v4/model.go.template | 55 + template/v4/no_actions/apis.go.template | 198 + .../no_actions/router_check_role.go.template | 27 + .../router_no_check_role.go.template | 25 + template/v4/no_actions/service.go.template | 109 + template/v4/vue.go.template | 485 ++ test/api.go.template | 126 + test/gen_test.go | 47 + test/model.go.template | 103 + 242 files changed, 29323 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 Dockerfilebak create mode 100644 LICENSE.md create mode 100644 Makefile create mode 100644 README.Zh-cn.md create mode 100644 README.md create mode 100644 _config.yml create mode 100644 app/admin/apis/captcha.go create mode 100644 app/admin/apis/go_admin.go create mode 100644 app/admin/apis/sys_api.go create mode 100644 app/admin/apis/sys_config.go create mode 100644 app/admin/apis/sys_dept.go create mode 100644 app/admin/apis/sys_dict_data.go create mode 100644 app/admin/apis/sys_dict_type.go create mode 100644 app/admin/apis/sys_login_log.go create mode 100644 app/admin/apis/sys_menu.go create mode 100644 app/admin/apis/sys_opera_log.go create mode 100644 app/admin/apis/sys_post.go create mode 100644 app/admin/apis/sys_role.go create mode 100644 app/admin/apis/sys_user.go create mode 100644 app/admin/models/casbin_rule.go create mode 100644 app/admin/models/datascope.go create mode 100644 app/admin/models/initdb.go create mode 100644 app/admin/models/model.go create mode 100644 app/admin/models/sys_api.go create mode 100644 app/admin/models/sys_config.go create mode 100644 app/admin/models/sys_dept.go create mode 100644 app/admin/models/sys_dict_data.go create mode 100644 app/admin/models/sys_dict_type.go create mode 100644 app/admin/models/sys_login_log.go create mode 100644 app/admin/models/sys_menu.go create mode 100644 app/admin/models/sys_opera_log.go create mode 100644 app/admin/models/sys_post.go create mode 100644 app/admin/models/sys_role.go create mode 100644 app/admin/models/sys_user.go create mode 100644 app/admin/router/init_router.go create mode 100644 app/admin/router/router.go create mode 100644 app/admin/router/sys_api.go create mode 100644 app/admin/router/sys_config.go create mode 100644 app/admin/router/sys_dept.go create mode 100644 app/admin/router/sys_dict.go create mode 100644 app/admin/router/sys_login_log.go create mode 100644 app/admin/router/sys_menu.go create mode 100644 app/admin/router/sys_opera_log.go create mode 100644 app/admin/router/sys_post.go create mode 100644 app/admin/router/sys_role.go create mode 100644 app/admin/router/sys_router.go create mode 100644 app/admin/router/sys_user.go create mode 100644 app/admin/service/dto/sys_api.go create mode 100644 app/admin/service/dto/sys_config.go create mode 100644 app/admin/service/dto/sys_dept.go create mode 100644 app/admin/service/dto/sys_dict_data.go create mode 100644 app/admin/service/dto/sys_dict_type.go create mode 100644 app/admin/service/dto/sys_login_log.go create mode 100644 app/admin/service/dto/sys_menu.go create mode 100644 app/admin/service/dto/sys_opera_log.go create mode 100644 app/admin/service/dto/sys_post.go create mode 100644 app/admin/service/dto/sys_role.go create mode 100644 app/admin/service/dto/sys_user.go create mode 100644 app/admin/service/sys_api.go create mode 100644 app/admin/service/sys_config.go create mode 100644 app/admin/service/sys_dept.go create mode 100644 app/admin/service/sys_dict_data.go create mode 100644 app/admin/service/sys_dict_type.go create mode 100644 app/admin/service/sys_login_log.go create mode 100644 app/admin/service/sys_menu.go create mode 100644 app/admin/service/sys_opera_log.go create mode 100644 app/admin/service/sys_post.go create mode 100644 app/admin/service/sys_role.go create mode 100644 app/admin/service/sys_role_menu.go create mode 100644 app/admin/service/sys_user.go create mode 100644 app/jobs/apis/sys_job.go create mode 100644 app/jobs/examples.go create mode 100644 app/jobs/jobbase.go create mode 100644 app/jobs/models/sys_job.go create mode 100644 app/jobs/router/int_router.go create mode 100644 app/jobs/router/router.go create mode 100644 app/jobs/router/sys_job.go create mode 100644 app/jobs/service/dto/sys_job.go create mode 100644 app/jobs/service/sys_job.go create mode 100644 app/jobs/type.go create mode 100644 app/other/apis/file.go create mode 100644 app/other/apis/sys_server_monitor.go create mode 100644 app/other/apis/tools/db_columns.go create mode 100644 app/other/apis/tools/db_tables.go create mode 100644 app/other/apis/tools/gen.go create mode 100644 app/other/apis/tools/sys_tables.go create mode 100644 app/other/models/tools/db_columns.go create mode 100644 app/other/models/tools/db_tables.go create mode 100644 app/other/models/tools/sys_columns.go create mode 100644 app/other/models/tools/sys_tables.go create mode 100644 app/other/router/file.go create mode 100644 app/other/router/gen_router.go create mode 100644 app/other/router/init_router.go create mode 100644 app/other/router/monitor.go create mode 100644 app/other/router/router.go create mode 100644 app/other/router/sys_server_monitor.go create mode 100644 app/other/service/dto/sys_tables.go create mode 100644 cmd/api/jobs.go create mode 100644 cmd/api/other.go create mode 100644 cmd/api/server.go create mode 100644 cmd/app/server.go create mode 100644 cmd/cobra.go create mode 100644 cmd/config/server.go create mode 100644 cmd/migrate/migration/init.go create mode 100644 cmd/migrate/migration/models/by.go create mode 100644 cmd/migrate/migration/models/casbin_rule.go create mode 100644 cmd/migrate/migration/models/initdb.go create mode 100644 cmd/migrate/migration/models/model.go create mode 100644 cmd/migrate/migration/models/role_dept.go create mode 100644 cmd/migrate/migration/models/sys_api.go create mode 100644 cmd/migrate/migration/models/sys_columns.go create mode 100644 cmd/migrate/migration/models/sys_config.go create mode 100644 cmd/migrate/migration/models/sys_dept.go create mode 100644 cmd/migrate/migration/models/sys_dict_data.go create mode 100644 cmd/migrate/migration/models/sys_dict_type.go create mode 100644 cmd/migrate/migration/models/sys_job.go create mode 100644 cmd/migrate/migration/models/sys_login_log.go create mode 100644 cmd/migrate/migration/models/sys_menu.go create mode 100644 cmd/migrate/migration/models/sys_opera_log.go create mode 100644 cmd/migrate/migration/models/sys_post.go create mode 100644 cmd/migrate/migration/models/sys_role.go create mode 100644 cmd/migrate/migration/models/sys_tables.go create mode 100644 cmd/migrate/migration/models/sys_user.go create mode 100644 cmd/migrate/migration/models/tb_demo.go create mode 100644 cmd/migrate/migration/version-local/doc.go create mode 100644 cmd/migrate/migration/version/1599190683659_tables.go create mode 100644 cmd/migrate/migration/version/1653638869132_migrate.go create mode 100644 cmd/migrate/server.go create mode 100644 cmd/version/server.go create mode 100644 common/actions/create.go create mode 100644 common/actions/delete.go create mode 100644 common/actions/index.go create mode 100644 common/actions/permission.go create mode 100644 common/actions/type.go create mode 100644 common/actions/update.go create mode 100644 common/actions/view.go create mode 100644 common/apis/api.go create mode 100644 common/database/initialize.go create mode 100644 common/database/open.go create mode 100644 common/database/open_sqlite3.go create mode 100644 common/dto/auto_form.go create mode 100644 common/dto/generate.go create mode 100644 common/dto/order.go create mode 100644 common/dto/pagination.go create mode 100644 common/dto/search.go create mode 100644 common/dto/type.go create mode 100644 common/file_store/initialize.go create mode 100644 common/file_store/interface.go create mode 100644 common/file_store/kodo.go create mode 100644 common/file_store/kodo_test.go create mode 100644 common/file_store/obs.go create mode 100644 common/file_store/obs_test.go create mode 100644 common/file_store/oss.go create mode 100644 common/file_store/oss_test.go create mode 100644 common/global/adm.go create mode 100644 common/global/casbin.go create mode 100644 common/global/logo.go create mode 100644 common/global/topic.go create mode 100644 common/ip.go create mode 100644 common/middleware/auth.go create mode 100644 common/middleware/customerror.go create mode 100644 common/middleware/db.go create mode 100644 common/middleware/demo.go create mode 100644 common/middleware/handler/auth.go create mode 100644 common/middleware/handler/httpshandler.go create mode 100644 common/middleware/handler/login.go create mode 100644 common/middleware/handler/ping.go create mode 100644 common/middleware/handler/role.go create mode 100644 common/middleware/handler/user.go create mode 100644 common/middleware/header.go create mode 100644 common/middleware/init.go create mode 100644 common/middleware/logger.go create mode 100644 common/middleware/permission.go create mode 100644 common/middleware/request_id.go create mode 100644 common/middleware/sentinel.go create mode 100644 common/middleware/settings.go create mode 100644 common/middleware/trace.go create mode 100644 common/models/by.go create mode 100644 common/models/menu.go create mode 100644 common/models/migrate.go create mode 100644 common/models/response.go create mode 100644 common/models/type.go create mode 100644 common/models/user.go create mode 100644 common/response/binding.go create mode 100644 common/service/service.go create mode 100644 common/storage/initialize.go create mode 100644 config/READMEN.md create mode 100644 config/db-begin-mysql.sql create mode 100644 config/db-end-mysql.sql create mode 100644 config/db-sqlserver.sql create mode 100644 config/db.sql create mode 100644 config/extend.go create mode 100644 config/pg.sql create mode 100644 config/settings.demo.yml create mode 100644 config/settings.full.yml create mode 100644 config/settings.sqlite.yml create mode 100644 config/settings.yml create mode 100644 docker-compose.yml create mode 100644 docs/admin/admin_docs.go create mode 100644 docs/admin/admin_swagger.json create mode 100644 docs/admin/admin_swagger.yaml create mode 100644 examples/run.go create mode 100644 go-admin-db.db create mode 100644 go.mod create mode 100644 main.go create mode 100644 package-lock.json create mode 100644 restart.sh create mode 100644 scripts/Dockerfile create mode 100644 scripts/k8s/deploy.yml create mode 100644 scripts/k8s/prerun.sh create mode 100644 scripts/k8s/storage.yml create mode 100644 ssh/swag.sh create mode 100644 static/form-generator/css/index.1a124643.css create mode 100644 static/form-generator/css/parser-example.69e16e51.css create mode 100644 static/form-generator/img/logo.e1bc3747.png create mode 100644 static/form-generator/index.html create mode 100644 static/form-generator/js/chunk-vendors.971555db.js create mode 100644 static/form-generator/js/index.8e6d9f8f.js create mode 100644 static/form-generator/js/parser-example.ce55fa09.js create mode 100644 static/form-generator/js/preview.8ce4e0db.js create mode 100644 static/form-generator/js/tinymce-example.641995ab.js create mode 100644 static/form-generator/preview.html create mode 100644 stop.sh create mode 100644 template/api_migrate.template create mode 100644 template/cmd_api.template create mode 100644 template/migrate.template create mode 100644 template/router.template create mode 100644 template/v4/actions/router_check_role.go.template create mode 100644 template/v4/actions/router_no_check_role.go.template create mode 100644 template/v4/dto.go.template create mode 100644 template/v4/js.go.template create mode 100644 template/v4/model.go.template create mode 100644 template/v4/no_actions/apis.go.template create mode 100644 template/v4/no_actions/router_check_role.go.template create mode 100644 template/v4/no_actions/router_no_check_role.go.template create mode 100644 template/v4/no_actions/service.go.template create mode 100644 template/v4/vue.go.template create mode 100644 test/api.go.template create mode 100644 test/gen_test.go create mode 100644 test/model.go.template diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..24cb16d --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +.idea +.vscode +*/.DS_Store +static/uploadfile +main.exe +*.exe +go-admin +go-admin.exe +temp/ +!temp +vendor +config/settings.dev.yml +config/settings.dev.*.yml +config/settings.dev.*.yml.log +temp/logs +config/settings.dev.yml.log +config/settings.b.dev.yml +cmd/migrate/migration/version-local/* +!cmd/migrate/migration/version-local/doc.go + +# go sum +go.sum +config/settings.deva.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..fb3e023 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +FROM alpine + +# ENV GOPROXY https://goproxy.cn/ + +RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories + +RUN apk update --no-cache +RUN apk add --update gcc g++ libc6-compat +RUN apk add --no-cache ca-certificates +RUN apk add --no-cache tzdata +ENV TZ Asia/Shanghai + +COPY ./main /main +COPY ./config/settings.demo.yml /config/settings.yml +COPY ./go-admin-db.db /go-admin-db.db +EXPOSE 8000 +RUN chmod +x /main +CMD ["/main","server","-c", "/config/settings.yml"] \ No newline at end of file diff --git a/Dockerfilebak b/Dockerfilebak new file mode 100644 index 0000000..c5e33a5 --- /dev/null +++ b/Dockerfilebak @@ -0,0 +1,28 @@ +FROM golang:alpine as builder + +MAINTAINER lwnmengjing + +ENV GOPROXY https://goproxy.cn/ + +WORKDIR /go/release +#RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories +RUN apk update && apk add tzdata + +COPY go.mod ./go.mod +RUN go mod tidy +COPY . . +RUN pwd && ls + +RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -installsuffix cgo -o go-admin . + +FROM alpine + +COPY --from=builder /go/release/go-admin / + +COPY --from=builder /go/release/config/settings.yml /config/settings.yml + +COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /etc/localtime + +EXPOSE 8000 + +CMD ["/go-admin","server","-c", "/config/settings.yml"] \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..36b35f4 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 go-admin-team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..afdb1a1 --- /dev/null +++ b/Makefile @@ -0,0 +1,54 @@ +PROJECT:=go-admin + +.PHONY: build +build: + CGO_ENABLED=0 go build -ldflags="-w -s" -a -installsuffix "" -o go-admin . + +# make build-linux +build-linux: + @docker build -t go-admin:latest . + @echo "build successful" + +build-sqlite: + go build -tags sqlite3 -ldflags="-w -s" -a -installsuffix -o go-admin . + +# make run +run: + # delete go-admin-api container + @if [ $(shell docker ps -aq --filter name=go-admin --filter publish=8000) ]; then docker rm -f go-admin; fi + + # 启动方法一 run go-admin-api container docker-compose 启动方式 + # 进入到项目根目录 执行 make run 命令 + @docker-compose up -d + + # 启动方式二 docker run 这里注意-v挂载的宿主机的地址改为部署时的实际决对路径 + #@docker run --name=go-admin -p 8000:8000 -v /home/code/go/src/go-admin/go-admin/config:/go-admin-api/config -v /home/code/go/src/go-admin/go-admin-api/static:/go-admin/static -v /home/code/go/src/go-admin/go-admin/temp:/go-admin-api/temp -d --restart=always go-admin:latest + + @echo "go-admin service is running..." + + # delete Tag= 的镜像 + @docker image prune -f + @docker ps -a | grep "go-admin" + +stop: + # delete go-admin-api container + @if [ $(shell docker ps -aq --filter name=go-admin --filter publish=8000) ]; then docker-compose down; fi + #@if [ $(shell docker ps -aq --filter name=go-admin --filter publish=8000) ]; then docker rm -f go-admin; fi + #@echo "go-admin stop success" + + +#.PHONY: test +#test: +# go test -v ./... -cover + +#.PHONY: docker +#docker: +# docker build . -t go-admin:latest + +# make deploy +deploy: + + #@git checkout master + #@git pull origin master + make build-linux + make run diff --git a/README.Zh-cn.md b/README.Zh-cn.md new file mode 100644 index 0000000..50d207e --- /dev/null +++ b/README.Zh-cn.md @@ -0,0 +1,353 @@ +# go-admin + + + + +[![Build Status](https://github.com/wenjianzhang/go-admin/workflows/build/badge.svg)](https://github.com/go-admin-team/go-admin) +[![Release](https://img.shields.io/github/release/go-admin-team/go-admin.svg?style=flat-square)](https://github.com/go-admin-team/go-admin/releases) +[![License](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/go-admin-team/go-admin) + +[English](https://github.com/go-admin-team/go-admin/blob/master/README.md) | 简体中文 + +基于Gin + Vue + Element UI OR Arco Design OR Ant Design的前后端分离权限管理系统,系统初始化极度简单,只需要配置文件中,修改数据库连接,系统支持多指令操作,迁移指令可以让初始化数据库信息变得更简单,服务指令可以很简单的启动api服务 + +[在线文档](https://www.go-admin.pro) + +[前端项目](https://github.com/go-admin-team/go-admin-ui) + +[视频教程](https://space.bilibili.com/565616721/channel/detail?cid=125737) + +## 🎬 在线体验 + +Element UI vue体验:[https://vue2.go-admin.dev](https://vue2.go-admin.dev/#/login) +> ⚠️⚠️⚠️ 账号 / 密码: admin / 123456 + +Arco Design vue3 demo:[https://vue3.go-admin.dev](https://vue3.go-admin.dev/#/login) +> ⚠️⚠️⚠️ 账号 / 密码: admin / 123456 + +antd体验:[https://antd.go-admin.pro](https://antd.go-admin.pro/) +> ⚠️⚠️⚠️ 账号 / 密码: admin / 123456 + +## ✨ 特性 + +- 遵循 RESTful API 设计规范 + +- 基于 GIN WEB API 框架,提供了丰富的中间件支持(用户认证、跨域、访问日志、追踪ID等) + +- 基于Casbin的 RBAC 访问控制模型 + +- JWT 认证 + +- 支持 Swagger 文档(基于swaggo) + +- 基于 GORM 的数据库存储,可扩展多种类型数据库 + +- 配置文件简单的模型映射,快速能够得到想要的配置 + +- 代码生成工具 + +- 表单构建工具 + +- 多指令模式 + +- 多租户的支持 + +- TODO: 单元测试 + +## 🎁 内置 + +1. 多租户:系统默认支持多租户,按库分离,一个库一个租户。 +1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 +2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 +3. 岗位管理:配置系统用户所属担任职务。 +4. 菜单管理:配置系统菜单,操作权限,按钮权限标识,接口权限等。 +5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 +6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 +7. 参数管理:对系统动态配置常用参数。 +8. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 +9. 登录日志:系统登录日志记录查询包含登录异常。 +1. 接口文档:根据业务代码自动生成相关的api接口文档。 +1. 代码生成:根据数据表结构生成对应的增删改查相对应业务,全程可视化操作,让基本业务可以零代码实现。 +1. 表单构建:自定义页面样式,拖拉拽实现页面布局。 +1. 服务监控:查看一些服务器的基本信息。 +1. 内容管理:demo功能,下设分类管理、内容管理。可以参考使用方便快速入门。 +1. 定时任务:自动化任务,目前支持接口调用和函数调用。 + +## 准备工作 + +你需要在本地安装 [go] [gin] [node](http://nodejs.org/) 和 [git](https://git-scm.com/) + +同时配套了系列教程包含视频和文档,如何从下载完成到熟练使用,强烈建议大家先看完这些教程再来实践本项目!!! + +### 轻松实现go-admin写出第一个应用 - 文档教程 + +[步骤一 - 基础内容介绍](https://doc.zhangwj.com/guide/intro/tutorial01.html) + +[步骤二 - 实际应用 - 编写增删改查](https://doc.zhangwj.com/guide/intro/tutorial02.html) + +### 手把手教你从入门到放弃 - 视频教程 + +[如何启动go-admin](https://www.bilibili.com/video/BV1z5411x7JG) + +[使用生成工具轻松实现业务](https://www.bilibili.com/video/BV1Dg4y1i79D) + +[v1.1.0版本代码生成工具-释放双手](https://www.bilibili.com/video/BV1N54y1i71P) [进阶] + +[多命令启动方式讲解以及IDE配置](https://www.bilibili.com/video/BV1Fg4y1q7ph) + +[go-admin菜单的配置说明](https://www.bilibili.com/video/BV1Wp4y1D715) [必看] + +[如何配置菜单信息以及接口信息](https://www.bilibili.com/video/BV1zv411B7nG) [必看] + +[go-admin权限配置使用说明](https://www.bilibili.com/video/BV1rt4y197d3) [必看] + +[go-admin数据权限使用说明](https://www.bilibili.com/video/BV1LK4y1s71e) [必看] + +**如有问题请先看上述使用文档和文章,若不能满足,欢迎 issue 和 pr ,视频教程和文档持续更新中** + +## 📦 本地开发 + +### 环境要求 + +go 1.18 + +node版本: v14.16.0 + +npm版本: 6.14.11 + +### 开发目录创建 + +```bash + +# 创建开发目录 +mkdir goadmin +cd goadmin +``` + +### 获取代码 + +> 重点注意:两个项目必须放在同一文件夹下; + +```bash +# 获取后端代码 +git clone https://github.com/go-admin-team/go-admin.git + +# 获取前端代码 +git clone https://github.com/go-admin-team/go-admin-ui.git + +``` + +### 启动说明 + +#### 服务端启动说明 + +```bash +# 进入 go-admin 后端项目 +cd ./go-admin + +# 更新整理依赖 +go mod tidy + +# 编译项目 +go build + +# 修改配置 +# 文件路径 go-admin/config/settings.yml +vi ./config/settings.yml + +# 1. 配置文件中修改数据库信息 +# 注意: settings.database 下对应的配置数据 +# 2. 确认log路径 +``` + +:::tip ⚠️注意 在windows环境如果没有安装中CGO,会出现这个问题; + +```bash +E:\go-admin>go build +# github.com/mattn/go-sqlite3 +cgo: exec /missing-cc: exec: "/missing-cc": file does not exist +``` + +or + +```bash +D:\Code\go-admin>go build +# github.com/mattn/go-sqlite3 +cgo: exec gcc: exec: "gcc": executable file not found in %PATH% +``` + +[解决cgo问题进入](https://doc.go-admin.dev/zh-CN/guide/faq#cgo-%E7%9A%84%E9%97%AE%E9%A2%98) + +::: + +#### 初始化数据库,以及服务启动 + +``` bash +# 首次配置需要初始化数据库资源信息 +# macOS or linux 下使用 +$ ./go-admin migrate -c config/settings.dev.yml + +# ⚠️注意:windows 下使用 +$ go-admin.exe migrate -c config/settings.dev.yml + + +# 启动项目,也可以用IDE进行调试 +# macOS or linux 下使用 +$ ./go-admin server -c config/settings.yml + + +# ⚠️注意:windows 下使用 +$ go-admin.exe server -c config/settings.yml +``` + +#### sys_api 表的数据如何添加 + +在项目启动时,使用`-a true` 系统会自动添加缺少的接口数据 +```bash +./go-admin server -c config/settings.yml -a true +``` + +#### 使用docker 编译启动 + +```shell +# 编译镜像 +docker build -t go-admin . + +# 启动容器,第一个go-admin是容器名字,第二个go-admin是镜像名称 +# -v 映射配置文件 本地路径:容器路径 +docker run --name go-admin -p 8000:8000 -v /config/settings.yml:/config/settings.yml -d go-admin-server +``` + +#### 文档生成 + +```bash +go generate +``` + +#### 交叉编译 + +```bash +# windows +env GOOS=windows GOARCH=amd64 go build main.go + +# or +# linux +env GOOS=linux GOARCH=amd64 go build main.go +``` + +### UI交互端启动说明 + +```bash +# 安装依赖 +npm install + +# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题 +npm install --registry=https://registry.npmmirror.com + +# 启动服务 +npm run dev +``` + +## 📨 互动 + + + + + + + + + + + + + + +
wenjianzhang
微信公众号🔥🔥🔥go-admin技术交流乙号哔哩哔哩🔥🔥🔥
+ +## 💎 贡献者 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## JetBrains 开源证书支持 + +`go-admin` 项目一直以来都是在 JetBrains 公司旗下的 GoLand 集成开发环境中进行开发,基于 **free JetBrains Open Source license(s)** 正版免费授权,在此表达我的谢意。 + + + +## 🤝 特别感谢 + +1. [ant-design](https://github.com/ant-design/ant-design) +2. [ant-design-pro](https://github.com/ant-design/ant-design-pro) +2. [arco-design](https://github.com/arco-design/arco-design) +2. [arco-design-pro](https://github.com/arco-design/arco-design-pro) +4. [gin](https://github.com/gin-gonic/gin) +5. [casbin](https://github.com/casbin/casbin) +6. [spf13/viper](https://github.com/spf13/viper) +7. [gorm](https://github.com/jinzhu/gorm) +8. [gin-swagger](https://github.com/swaggo/gin-swagger) +9. [jwt-go](https://github.com/dgrijalva/jwt-go) +10. [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin) +11. [ruoyi-vue](https://gitee.com/y_project/RuoYi-Vue) +12. [form-generator](https://github.com/JakHuang/form-generator) + + +## 🤟 打赏 + +> 如果你觉得这个项目帮助到了你,你可以帮作者买一杯果汁表示鼓励 :tropical_drink: + + + +## 🤝 链接 + +[Go开发者成长线路图](http://www.golangroadmap.com/) + +## 🔑 License + +[MIT](https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md) + +Copyright (c) 2022 wenjianzhang diff --git a/README.md b/README.md new file mode 100644 index 0000000..aa0825a --- /dev/null +++ b/README.md @@ -0,0 +1,342 @@ + +# go-admin + + + + +[![Build Status](https://github.com/wenjianzhang/go-admin/workflows/build/badge.svg)](https://github.com/go-admin-team/go-admin) +[![Release](https://img.shields.io/github/release/go-admin-team/go-admin.svg?style=flat-square)](https://github.com/go-admin-team/go-admin/releases) +[![License](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/go-admin-team/go-admin) + +English | [简体中文](https://github.com/go-admin-team/go-admin/blob/master/README.Zh-cn.md) + +The front-end and back-end separation authority management system based on Gin + Vue + Element UI OR Arco Design is extremely simple to initialize the system. You only need to modify the database connection in the configuration file. The system supports multi-instruction operations. Migration instructions can make it easier to initialize database information. Service instructions It's easy to start the api service. + +[documentation](https://www.go-admin.dev) + +[Front-end project](https://github.com/go-admin-team/go-admin-ui) + +[Video tutorial](https://space.bilibili.com/565616721/channel/detail?cid=125737) + +## 🎬 Online Demo + +Element UI vue demo:[https://vue2.go-admin.dev](https://vue2.go-admin.dev/#/login) +> 账号 / 密码: admin / 123456 + +Arco Design vue3 demo:[https://vue3.go-admin.dev](https://vue3.go-admin.dev/#/login) +> 账号 / 密码: admin / 123456 + +antd demo:[https://antd.go-admin.pro](https://antd.go-admin.pro/) +> 账号 / 密码: admin / 123456 +> +## ✨ Feature + +- Follow RESTful API design specifications + +- Based on the GIN WEB API framework, it provides rich middleware support (user authentication, cross-domain, access log, tracking ID, etc.) + +- RBAC access control model based on Casbin + +- JWT authentication + +- Support Swagger documents (based on swaggo) + +- Database storage based on GORM, which can expand multiple types of databases + +- Simple model mapping of configuration files to quickly get the desired configuration + +- Code generation tool + +- Form builder + +- Multi-command mode + +- TODO: unit test + + +## 🎁 Internal + +1. User management: The user is the system operator, this function mainly completes the system user configuration. +2. Department management: configure the system organization (company, department, group), and display the tree structure to support data permissions. +3. Position management: configure the positions of system users. +4. Menu management: configure the system menu, operation authority, button authority identification, interface authority, etc. +5. Role management: Role menu permission assignment and role setting are divided into data scope permissions by organization. +6. Dictionary management: Maintain some relatively fixed data frequently used in the system. +7. Parameter management: dynamically configure common parameters for the system. +8. Operation log: system normal operation log record and query; system abnormal information log record and query. +9. Login log: The system login log record query contains login exceptions. +1. Interface documentation: Automatically generate related api interface documents according to the business code. +1. Code generation: According to the data table structure, generate the corresponding addition, deletion, modification, and check corresponding business, and the whole process of visual operation, so that the basic business can be implemented with zero code. +1. Form construction: Customize the page style, drag and drop to realize the page layout. +1. Service monitoring: View the basic information of some servers. +1. Content management: demo function, including classification management and content management. You can refer to the easy to use quick start. + +## Ready to work + +You need to install locally [go] [gin] [node](http://nodejs.org/) 和 [git](https://git-scm.com/) + +At the same time, a series of tutorials including videos and documents are provided. How to complete the downloading to the proficient use, it is strongly recommended that you read these tutorials before you practice this project! ! ! + +### Easily implement go-admin to write the first application-documentation tutorial + +[Step 1 - basic content introduction](https://doc.zhangwj.com/guide/intro/tutorial01.html) + +[Step 2 - Practical application - writing database operations](https://doc.zhangwj.com/guide/intro/tutorial02.html) + +### Teach you from getting started to giving up-video tutorial + +[How to start go-admin](https://www.bilibili.com/video/BV1z5411x7JG) + +[Easily implement business using build tools](https://www.bilibili.com/video/BV1Dg4y1i79D) + +[v1.1.0 version code generation tool-free your hands](https://www.bilibili.com/video/BV1N54y1i71P) [Advanced] + +[Explanation of multi-command startup mode and IDE configuration](https://www.bilibili.com/video/BV1Fg4y1q7ph) + +[Configuration instructions for go-admin menu](https://www.bilibili.com/video/BV1Wp4y1D715) [Must see] + +[How to configure menu information and interface information](https://www.bilibili.com/video/BV1zv411B7nG) [Must see] + +[go-admin permission configuration instructions](https://www.bilibili.com/video/BV1rt4y197d3) [Must see] + +[Instructions for use of go-admin data permissions](https://www.bilibili.com/video/BV1LK4y1s71e) [Must see] + +**If you have any questions, please read the above-mentioned usage documents and articles first. If you are not satisfied, welcome to issue and pr. Video tutorials and documents are being updated continuously.** + +## 📦 Local development + +### Environmental requirements + +go 1.18 + +nodejs: v14.16.0 + +npm: 6.14.11 + +### Development directory creation + +```bash + +# Create a development directory +mkdir goadmin +cd goadmin +``` + +### Get the code + +> Important note: the two projects must be placed in the same folder; + +```bash +# Get backend code +git clone https://github.com/go-admin-team/go-admin.git + +# Get the front-end code +git clone https://github.com/go-admin-team/go-admin-ui.git + +``` + +### Startup instructions + +#### Server startup instructions + +```bash +# Enter the go-admin backend project +cd ./go-admin + +# Update dependencies +go mod tidy + +# Compile the project +go build + +# Change setting +# File path go-admin/config/settings.yml +vi ./config/settings.yml + +# 1. Modify the database information in the configuration file +# Note: The corresponding configuration data under settings.database +# 2. Confirm the log path +``` + +:::tip ⚠️Note that this problem will occur if CGO is not installed in the windows10+ environment; + +```bash +E:\go-admin>go build +# github.com/mattn/go-sqlite3 +cgo: exec /missing-cc: exec: "/missing-cc": file does not exist +``` + +or + +```bash +D:\Code\go-admin>go build +# github.com/mattn/go-sqlite3 +cgo: exec gcc: exec: "gcc": executable file not found in %PATH% +``` + +[Solve the cgo problem and enter](https://doc.go-admin.dev/guide/faq#cgo-%E7%9A%84%E9%97%AE%E9%A2%98) + +::: + +#### Initialize the database, and start the service + +``` bash +# The first configuration needs to initialize the database resource information +# Use under macOS or linux +$ ./go-admin migrate -c config/settings.dev.yml + +# ⚠️Note: Use under windows +$ go-admin.exe migrate -c config/settings.dev.yml + +# Start the project, you can also use the IDE for debugging +# Use under macOS or linux +$ ./go-admin server -c config/settings.yml + +# ⚠️Note: Use under windows +$ go-admin.exe server -c config/settings.yml +``` + +#### Use docker to compile and start + +```shell +# Compile the image +docker build -t go-admin . + + +# Start the container, the first go-admin is the container name, and the second go-admin is the image name +# -v Mapping configuration file Local path: container path +docker run --name go-admin -p 8000:8000 -v /config/settings.yml:/config/settings.yml -d go-admin-server +``` + + + +#### Generation Document + +```bash +go generate +``` + +#### Cross compile +```bash +# windows +env GOOS=windows GOARCH=amd64 go build main.go + +# or +# linux +env GOOS=linux GOARCH=amd64 go build main.go +``` + +### UI interactive terminal startup instructions + +```bash +# Installation dependencies +npm install # or cnpm install + +# Start service +npm run dev +``` + +## 📨 Interactive + + + + + + + + + + + + + + +
wenjianzhang
WechatWechat公众号🔥🔥🔥go-admin技术交流乙号bilibili🔥🔥🔥
+ +## 💎 Contributors + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## JetBrains open source certificate support + +The `go-admin` project has always been developed in the GoLand integrated development environment under JetBrains, based on the **free JetBrains Open Source license(s)** genuine free license. I would like to express my gratitude. + + + + +## 🤝 Thanks + +1. [ant-design](https://github.com/ant-design/ant-design) +2. [ant-design-pro](https://github.com/ant-design/ant-design-pro) +2. [arco-design](https://github.com/arco-design/arco-design) +2. [arco-design-pro](https://github.com/arco-design/arco-design-pro) +2. [gin](https://github.com/gin-gonic/gin) +2. [casbin](https://github.com/casbin/casbin) +2. [spf13/viper](https://github.com/spf13/viper) +2. [gorm](https://github.com/jinzhu/gorm) +2. [gin-swagger](https://github.com/swaggo/gin-swagger) +2. [jwt-go](https://github.com/dgrijalva/jwt-go) +2. [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin) +2. [ruoyi-vue](https://gitee.com/y_project/RuoYi-Vue) +2. [form-generator](https://github.com/JakHuang/form-generator) + +## 🤟 Sponsor Us + +> If you think this project helped you, you can buy a glass of juice for the author to show encouragement :tropical_drink: + + + +## 🤝 Link +[Go developer growth roadmap](http://www.golangroadmap.com/) +[mss-boot-io](https://docs.mss-boot-io.top/) + +## 🔑 License + +[MIT](https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md) + +Copyright (c) 2022 wenjianzhang diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000..c419263 --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file diff --git a/app/admin/apis/captcha.go b/app/admin/apis/captcha.go new file mode 100644 index 0000000..f5bccac --- /dev/null +++ b/app/admin/apis/captcha.go @@ -0,0 +1,37 @@ +package apis + +import ( + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg/captcha" +) + +type System struct { + api.Api +} + +// GenerateCaptchaHandler 获取验证码 +// @Summary 获取验证码 +// @Description 获取验证码 +// @Tags 登陆 +// @Success 200 {object} response.Response{data=string,id=string,msg=string} "{"code": 200, "data": [...]}" +// @Router /api/v1/captcha [get] +func (e System) GenerateCaptchaHandler(c *gin.Context) { + err := e.MakeContext(c).Errors + if err != nil { + e.Error(500, err, "服务初始化失败!") + return + } + id, b64s, err := captcha.DriverDigitFunc() + if err != nil { + e.Logger.Errorf("DriverDigitFunc error, %s", err.Error()) + e.Error(500, err, "验证码获取失败") + return + } + e.Custom(gin.H{ + "code": 200, + "data": b64s, + "id": id, + "msg": "success", + }) +} diff --git a/app/admin/apis/go_admin.go b/app/admin/apis/go_admin.go new file mode 100644 index 0000000..14a06dc --- /dev/null +++ b/app/admin/apis/go_admin.go @@ -0,0 +1,39 @@ +package apis + +import ( + "github.com/gin-gonic/gin" +) + +const INDEX = ` + + + + +GO-ADMIN欢迎您 + + + + + + + + +` + +func GoAdmin(c *gin.Context) { + c.Header("Content-Type", "text/html; charset=utf-8") + c.String(200, INDEX) +} diff --git a/app/admin/apis/sys_api.go b/app/admin/apis/sys_api.go new file mode 100644 index 0000000..c2d3474 --- /dev/null +++ b/app/admin/apis/sys_api.go @@ -0,0 +1,148 @@ +package apis + +import ( + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + + "go-admin/app/admin/models" + "go-admin/app/admin/service" + "go-admin/app/admin/service/dto" + "go-admin/common/actions" +) + +type SysApi struct { + api.Api +} + +// GetPage 获取接口管理列表 +// @Summary 获取接口管理列表 +// @Description 获取接口管理列表 +// @Tags 接口管理 +// @Param name query string false "名称" +// @Param title query string false "标题" +// @Param path query string false "地址" +// @Param action query string false "类型" +// @Param pageSize query int false "页条数" +// @Param pageIndex query int false "页码" +// @Success 200 {object} response.Response{data=response.Page{list=[]models.SysApi}} "{"code": 200, "data": [...]}" +// @Router /api/v1/sys-api [get] +// @Security Bearer +func (e SysApi) GetPage(c *gin.Context) { + s := service.SysApi{} + req := dto.SysApiGetPageReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.Form). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + //数据权限检查 + p := actions.GetPermissionFromContext(c) + list := make([]models.SysApi, 0) + var count int64 + err = s.GetPage(&req, p, &list, &count) + if err != nil { + e.Error(500, err, "查询失败") + return + } + e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") +} + +// Get 获取接口管理 +// @Summary 获取接口管理 +// @Description 获取接口管理 +// @Tags 接口管理 +// @Param id path string false "id" +// @Success 200 {object} response.Response{data=models.SysApi} "{"code": 200, "data": [...]}" +// @Router /api/v1/sys-api/{id} [get] +// @Security Bearer +func (e SysApi) Get(c *gin.Context) { + req := dto.SysApiGetReq{} + s := service.SysApi{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + p := actions.GetPermissionFromContext(c) + var object models.SysApi + err = s.Get(&req, p, &object).Error + if err != nil { + e.Error(500, err, "查询失败") + return + } + e.OK(object, "查询成功") +} + +// Update 修改接口管理 +// @Summary 修改接口管理 +// @Description 修改接口管理 +// @Tags 接口管理 +// @Accept application/json +// @Product application/json +// @Param data body dto.SysApiUpdateReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}" +// @Router /api/v1/sys-api/{id} [put] +// @Security Bearer +func (e SysApi) Update(c *gin.Context) { + req := dto.SysApiUpdateReq{} + s := service.SysApi{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + return + } + req.SetUpdateBy(user.GetUserId(c)) + p := actions.GetPermissionFromContext(c) + err = s.Update(&req, p) + if err != nil { + e.Error(500, err, "更新失败") + return + } + e.OK(req.GetId(), "更新成功") +} + +// DeleteSysApi 删除接口管理 +// @Summary 删除接口管理 +// @Description 删除接口管理 +// @Tags 接口管理 +// @Param data body dto.SysApiDeleteReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}" +// @Router /api/v1/sys-api [delete] +// @Security Bearer +func (e SysApi) DeleteSysApi(c *gin.Context) { + req := dto.SysApiDeleteReq{} + s := service.SysApi{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + return + } + p := actions.GetPermissionFromContext(c) + err = s.Remove(&req, p) + if err != nil { + e.Error(500, err, "删除失败") + return + } + e.OK(req.GetId(), "删除成功") +} \ No newline at end of file diff --git a/app/admin/apis/sys_config.go b/app/admin/apis/sys_config.go new file mode 100644 index 0000000..0a95c8b --- /dev/null +++ b/app/admin/apis/sys_config.go @@ -0,0 +1,313 @@ +package apis + +import ( + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + + "go-admin/app/admin/models" + "go-admin/app/admin/service" + "go-admin/app/admin/service/dto" +) + +type SysConfig struct { + api.Api +} + +// GetPage 获取配置管理列表 +// @Summary 获取配置管理列表 +// @Description 获取配置管理列表 +// @Tags 配置管理 +// @Param configName query string false "名称" +// @Param configKey query string false "key" +// @Param configType query string false "类型" +// @Param isFrontend query int false "是否前端" +// @Param pageSize query int false "页条数" +// @Param pageIndex query int false "页码" +// @Success 200 {object} response.Response{data=response.Page{list=[]models.SysApi}} "{"code": 200, "data": [...]}" +// @Router /api/v1/sys-config [get] +// @Security Bearer +func (e SysConfig) GetPage(c *gin.Context) { + s := service.SysConfig{} + req := dto.SysConfigGetPageReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.Form). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + return + } + + list := make([]models.SysConfig, 0) + var count int64 + err = s.GetPage(&req, &list, &count) + if err != nil { + e.Error(500, err, "查询失败") + return + } + e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") +} + +// Get 获取配置管理 +// @Summary 获取配置管理 +// @Description 获取配置管理 +// @Tags 配置管理 +// @Param id path string false "id" +// @Success 200 {object} response.Response{data=models.SysConfig} "{"code": 200, "data": [...]}" +// @Router /api/v1/sys-config/{id} [get] +// @Security Bearer +func (e SysConfig) Get(c *gin.Context) { + req := dto.SysConfigGetReq{} + s := service.SysConfig{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + var object models.SysConfig + + err = s.Get(&req, &object) + if err != nil { + e.Error(500, err, err.Error()) + return + } + + e.OK(object, "查询成功") +} + +// Insert 创建配置管理 +// @Summary 创建配置管理 +// @Description 创建配置管理 +// @Tags 配置管理 +// @Accept application/json +// @Product application/json +// @Param data body dto.SysConfigControl true "body" +// @Success 200 {object} response.Response "{"code": 200, "message": "创建成功"}" +// @Router /api/v1/sys-config [post] +// @Security Bearer +func (e SysConfig) Insert(c *gin.Context) { + s := service.SysConfig{} + req := dto.SysConfigControl{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + req.SetCreateBy(user.GetUserId(c)) + + err = s.Insert(&req) + if err != nil { + e.Error(500, err, "创建失败") + return + } + e.OK(req.GetId(), "创建成功") +} + +// Update 修改配置管理 +// @Summary 修改配置管理 +// @Description 修改配置管理 +// @Tags 配置管理 +// @Accept application/json +// @Product application/json +// @Param data body dto.SysConfigControl true "body" +// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}" +// @Router /api/v1/sys-config/{id} [put] +// @Security Bearer +func (e SysConfig) Update(c *gin.Context) { + s := service.SysConfig{} + req := dto.SysConfigControl{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + req.SetUpdateBy(user.GetUserId(c)) + err = s.Update(&req) + if err != nil { + e.Error(500, err, "更新失败") + return + } + e.OK(req.GetId(), "更新成功") +} + +// Delete 删除配置管理 +// @Summary 删除配置管理 +// @Description 删除配置管理 +// @Tags 配置管理 +// @Param ids body []int false "ids" +// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}" +// @Router /api/v1/sys-config [delete] +// @Security Bearer +func (e SysConfig) Delete(c *gin.Context) { + s := service.SysConfig{} + req := dto.SysConfigDeleteReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + req.SetUpdateBy(user.GetUserId(c)) + + err = s.Remove(&req) + if err != nil { + e.Error(500, err, "删除失败") + return + } + e.OK(req.GetId(), "删除成功") +} + +// Get2SysApp 获取系统配置信息 +// @Summary 获取系统前台配置信息,主要注意这里不在验证权限 +// @Description 获取系统配置信息,主要注意这里不在验证权限 +// @Tags 配置管理 +// @Success 200 {object} response.Response{data=map[string]string} "{"code": 200, "data": [...]}" +// @Router /api/v1/app-config [get] +func (e SysConfig) Get2SysApp(c *gin.Context) { + req := dto.SysConfigGetToSysAppReq{} + s := service.SysConfig{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.Form). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + return + } + // 控制只读前台的数据 + req.IsFrontend = "1" + list := make([]models.SysConfig, 0) + err = s.GetWithKeyList(&req, &list) + if err != nil { + e.Error(500, err, "查询失败") + return + } + mp := make(map[string]string) + for i := 0; i < len(list); i++ { + key := list[i].ConfigKey + if key != "" { + mp[key] = list[i].ConfigValue + } + } + e.OK(mp, "查询成功") +} + +// Get2Set 获取配置 +// @Summary 获取配置 +// @Description 界面操作设置配置值的获取 +// @Tags 配置管理 +// @Accept application/json +// @Product application/json +// @Success 200 {object} response.Response{data=map[string]interface{}} "{"code": 200, "message": "修改成功"}" +// @Router /api/v1/set-config [get] +// @Security Bearer +func (e SysConfig) Get2Set(c *gin.Context) { + s := service.SysConfig{} + req := make([]dto.GetSetSysConfigReq, 0) + err := e.MakeContext(c). + MakeOrm(). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + err = s.GetForSet(&req) + if err != nil { + e.Error(500, err, "查询失败") + return + } + m := make(map[string]interface{}, 0) + for _, v := range req { + m[v.ConfigKey] = v.ConfigValue + } + e.OK(m, "查询成功") +} + +// Update2Set 设置配置 +// @Summary 设置配置 +// @Description 界面操作设置配置值 +// @Tags 配置管理 +// @Accept application/json +// @Product application/json +// @Param data body []dto.GetSetSysConfigReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}" +// @Router /api/v1/set-config [put] +// @Security Bearer +func (e SysConfig) Update2Set(c *gin.Context) { + s := service.SysConfig{} + req := make([]dto.GetSetSysConfigReq, 0) + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + err = s.UpdateForSet(&req) + if err != nil { + e.Error(500, err, err.Error()) + return + } + + e.OK("", "更新成功") +} + +// GetSysConfigByKEYForService 根据Key获取SysConfig的Service +// @Summary 根据Key获取SysConfig的Service +// @Description 根据Key获取SysConfig的Service +// @Tags 配置管理 +// @Param configKey path string false "configKey" +// @Success 200 {object} response.Response{data=dto.SysConfigByKeyReq} "{"code": 200, "data": [...]}" +// @Router /api/v1/sys-config/{id} [get] +// @Security Bearer +func (e SysConfig) GetSysConfigByKEYForService(c *gin.Context) { + var s = new(service.SysConfig) + var req = new(dto.SysConfigByKeyReq) + var resp = new(dto.GetSysConfigByKEYForServiceResp) + err := e.MakeContext(c). + MakeOrm(). + Bind(req, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + err = s.GetWithKey(req, resp) + if err != nil { + e.Error(500, err, err.Error()) + return + } + e.OK(resp, s.Msg) +} diff --git a/app/admin/apis/sys_dept.go b/app/admin/apis/sys_dept.go new file mode 100644 index 0000000..f37eae4 --- /dev/null +++ b/app/admin/apis/sys_dept.go @@ -0,0 +1,238 @@ +package apis + +import ( + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + "go-admin/app/admin/models" + + "go-admin/app/admin/service" + "go-admin/app/admin/service/dto" +) + +type SysDept struct { + api.Api +} + +// GetPage +// @Summary 分页部门列表数据 +// @Description 分页列表 +// @Tags 部门 +// @Param deptName query string false "deptName" +// @Param deptId query string false "deptId" +// @Param position query string false "position" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/dept [get] +// @Security Bearer +func (e SysDept) GetPage(c *gin.Context) { + s := service.SysDept{} + req := dto.SysDeptGetPageReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + list := make([]models.SysDept, 0) + list, err = s.SetDeptPage(&req) + if err != nil { + e.Error(500, err, "查询失败") + return + } + e.OK(list, "查询成功") +} + +// Get +// @Summary 获取部门数据 +// @Description 获取JSON +// @Tags 部门 +// @Param deptId path string false "deptId" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/dept/{deptId} [get] +// @Security Bearer +func (e SysDept) Get(c *gin.Context) { + s := service.SysDept{} + req := dto.SysDeptGetReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + var object models.SysDept + + err = s.Get(&req, &object) + if err != nil { + e.Error(500, err, "查询失败") + return + } + + e.OK(object, "查询成功") +} + +// Insert 添加部门 +// @Summary 添加部门 +// @Description 获取JSON +// @Tags 部门 +// @Accept application/json +// @Product application/json +// @Param data body dto.SysDeptInsertReq true "data" +// @Success 200 {string} string "{"code": 200, "message": "添加成功"}" +// @Success 200 {string} string "{"code": -1, "message": "添加失败"}" +// @Router /api/v1/dept [post] +// @Security Bearer +func (e SysDept) Insert(c *gin.Context) { + s := service.SysDept{} + req := dto.SysDeptInsertReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + // 设置创建人 + req.SetCreateBy(user.GetUserId(c)) + err = s.Insert(&req) + if err != nil { + e.Error(500, err, "创建失败") + return + } + e.OK(req.GetId(), "创建成功") +} + +// Update +// @Summary 修改部门 +// @Description 获取JSON +// @Tags 部门 +// @Accept application/json +// @Product application/json +// @Param id path int true "id" +// @Param data body dto.SysDeptUpdateReq true "body" +// @Success 200 {string} string "{"code": 200, "message": "添加成功"}" +// @Success 200 {string} string "{"code": -1, "message": "添加失败"}" +// @Router /api/v1/dept/{deptId} [put] +// @Security Bearer +func (e SysDept) Update(c *gin.Context) { + s := service.SysDept{} + req := dto.SysDeptUpdateReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + req.SetUpdateBy(user.GetUserId(c)) + err = s.Update(&req) + if err != nil { + e.Error(500, err, err.Error()) + return + } + e.OK(req.GetId(), "更新成功") +} + +// Delete +// @Summary 删除部门 +// @Description 删除数据 +// @Tags 部门 +// @Param data body dto.SysDeptDeleteReq true "body" +// @Success 200 {string} string "{"code": 200, "message": "删除成功"}" +// @Success 200 {string} string "{"code": -1, "message": "删除失败"}" +// @Router /api/v1/dept [delete] +// @Security Bearer +func (e SysDept) Delete(c *gin.Context) { + s := service.SysDept{} + req := dto.SysDeptDeleteReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + err = s.Remove(&req) + if err != nil { + e.Error(500, err, "删除失败") + return + } + e.OK(req.GetId(), "删除成功") +} + +// Get2Tree 用户管理 左侧部门树 +func (e SysDept) Get2Tree(c *gin.Context) { + s := service.SysDept{} + req := dto.SysDeptGetPageReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req,binding.Form). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + list := make([]dto.DeptLabel, 0) + list, err = s.SetDeptTree(&req) + if err != nil { + e.Error(500, err, "查询失败") + return + } + e.OK(list, "") +} + +// GetDeptTreeRoleSelect TODO: 此接口需要调整不应该将list和选中放在一起 +func (e SysDept) GetDeptTreeRoleSelect(c *gin.Context) { + s := service.SysDept{} + err := e.MakeContext(c). + MakeOrm(). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + id, err := pkg.StringToInt(c.Param("roleId")) + result, err := s.SetDeptLabel() + if err != nil { + e.Error(500, err, err.Error()) + return + } + menuIds := make([]int, 0) + if id != 0 { + menuIds, err = s.GetWithRoleId(id) + if err != nil { + e.Error(500, err, err.Error()) + return + } + } + e.OK(gin.H{ + "depts": result, + "checkedKeys": menuIds, + }, "") +} \ No newline at end of file diff --git a/app/admin/apis/sys_dict_data.go b/app/admin/apis/sys_dict_data.go new file mode 100644 index 0000000..049fe99 --- /dev/null +++ b/app/admin/apis/sys_dict_data.go @@ -0,0 +1,220 @@ +package apis + +import ( + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + "go-admin/app/admin/models" + + "go-admin/app/admin/service" + "go-admin/app/admin/service/dto" +) + +type SysDictData struct { + api.Api +} + +// GetPage +// @Summary 字典数据列表 +// @Description 获取JSON +// @Tags 字典数据 +// @Param status query string false "status" +// @Param dictCode query string false "dictCode" +// @Param dictType query string false "dictType" +// @Param pageSize query int false "页条数" +// @Param pageIndex query int false "页码" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/dict/data [get] +// @Security Bearer +func (e SysDictData) GetPage(c *gin.Context) { + s := service.SysDictData{} + req := dto.SysDictDataGetPageReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.Form). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + list := make([]models.SysDictData, 0) + var count int64 + err = s.GetPage(&req, &list, &count) + if err != nil { + e.Error(500, err, "查询失败") + return + } + + e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") +} + +// Get +// @Summary 通过编码获取字典数据 +// @Description 获取JSON +// @Tags 字典数据 +// @Param dictCode path int true "字典编码" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/dict/data/{dictCode} [get] +// @Security Bearer +func (e SysDictData) Get(c *gin.Context) { + s := service.SysDictData{} + req := dto.SysDictDataGetReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + var object models.SysDictData + + err = s.Get(&req, &object) + if err != nil { + e.Logger.Warnf("Get error: %s", err.Error()) + e.Error(500, err, "查询失败") + return + } + + e.OK(object, "查询成功") +} + +// Insert +// @Summary 添加字典数据 +// @Description 获取JSON +// @Tags 字典数据 +// @Accept application/json +// @Product application/json +// @Param data body dto.SysDictDataInsertReq true "data" +// @Success 200 {object} response.Response "{"code": 200, "message": "添加成功"}" +// @Router /api/v1/dict/data [post] +// @Security Bearer +func (e SysDictData) Insert(c *gin.Context) { + s := service.SysDictData{} + req := dto.SysDictDataInsertReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + req.SetCreateBy(user.GetUserId(c)) + err = s.Insert(&req) + if err != nil { + e.Error(500, err, "创建失败") + return + } + + e.OK(req.GetId(), "创建成功") +} + +// Update +// @Summary 修改字典数据 +// @Description 获取JSON +// @Tags 字典数据 +// @Accept application/json +// @Product application/json +// @Param data body dto.SysDictDataUpdateReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}" +// @Router /api/v1/dict/data/{dictCode} [put] +// @Security Bearer +func (e SysDictData) Update(c *gin.Context) { + s := service.SysDictData{} + req := dto.SysDictDataUpdateReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + req.SetUpdateBy(user.GetUserId(c)) + err = s.Update(&req) + if err != nil { + e.Error(500, err, "更新失败") + return + } + e.OK(req.GetId(), "更新成功") +} + +// Delete +// @Summary 删除字典数据 +// @Description 删除数据 +// @Tags 字典数据 +// @Param dictCode body dto.SysDictDataDeleteReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}" +// @Router /api/v1/dict/data [delete] +// @Security Bearer +func (e SysDictData) Delete(c *gin.Context) { + s := service.SysDictData{} + req := dto.SysDictDataDeleteReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + req.SetUpdateBy(user.GetUserId(c)) + err = s.Remove(&req) + if err != nil { + e.Error(500, err, "删除失败") + return + } + e.OK(req.GetId(), "删除成功") +} + +// GetAll 数据字典根据key获取 业务页面使用 +// @Summary 数据字典根据key获取 +// @Description 数据字典根据key获取 +// @Tags 字典数据 +// @Param dictType query int true "dictType" +// @Success 200 {object} response.Response{data=[]dto.SysDictDataGetAllResp} "{"code": 200, "data": [...]}" +// @Router /api/v1/dict-data/option-select [get] +// @Security Bearer +func (e SysDictData) GetAll(c *gin.Context) { + s := service.SysDictData{} + req := dto.SysDictDataGetPageReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + list := make([]models.SysDictData, 0) + err = s.GetAll(&req, &list) + if err != nil { + e.Error(500, err, "查询失败") + return + } + l := make([]dto.SysDictDataGetAllResp, 0) + for _, i := range list { + d := dto.SysDictDataGetAllResp{} + e.Translate(i, &d) + l = append(l, d) + } + + e.OK(l,"查询成功") +} diff --git a/app/admin/apis/sys_dict_type.go b/app/admin/apis/sys_dict_type.go new file mode 100644 index 0000000..b93035e --- /dev/null +++ b/app/admin/apis/sys_dict_type.go @@ -0,0 +1,210 @@ +package apis + +import ( + "fmt" + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + "go-admin/app/admin/models" + + "go-admin/app/admin/service" + "go-admin/app/admin/service/dto" +) + +type SysDictType struct { + api.Api +} + +// GetPage 字典类型列表数据 +// @Summary 字典类型列表数据 +// @Description 获取JSON +// @Tags 字典类型 +// @Param dictName query string false "dictName" +// @Param dictId query string false "dictId" +// @Param dictType query string false "dictType" +// @Param pageSize query int false "页条数" +// @Param pageIndex query int false "页码" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/dict/type [get] +// @Security Bearer +func (e SysDictType) GetPage(c *gin.Context) { + s := service.SysDictType{} + req :=dto.SysDictTypeGetPageReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.Form). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + list := make([]models.SysDictType, 0) + var count int64 + err = s.GetPage(&req, &list, &count) + if err != nil { + e.Error(500, err, "查询失败") + return + } + e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") +} + +// Get 字典类型通过字典id获取 +// @Summary 字典类型通过字典id获取 +// @Description 获取JSON +// @Tags 字典类型 +// @Param dictId path int true "字典类型编码" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/dict/type/{dictId} [get] +// @Security Bearer +func (e SysDictType) Get(c *gin.Context) { + s := service.SysDictType{} + req :=dto.SysDictTypeGetReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + var object models.SysDictType + err = s.Get(&req, &object) + if err != nil { + e.Error(500, err, "查询失败") + return + } + e.OK(object, "查询成功") +} + +//Insert 字典类型创建 +// @Summary 添加字典类型 +// @Description 获取JSON +// @Tags 字典类型 +// @Accept application/json +// @Product application/json +// @Param data body dto.SysDictTypeInsertReq true "data" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/dict/type [post] +// @Security Bearer +func (e SysDictType) Insert(c *gin.Context) { + s := service.SysDictType{} + req :=dto.SysDictTypeInsertReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + req.SetCreateBy(user.GetUserId(c)) + err = s.Insert(&req) + if err != nil { + e.Logger.Error(err) + e.Error(500, err,fmt.Sprintf(" 创建字典类型失败,详情:%s", err.Error())) + return + } + e.OK(req.GetId(), "创建成功") +} + +// Update +// @Summary 修改字典类型 +// @Description 获取JSON +// @Tags 字典类型 +// @Accept application/json +// @Product application/json +// @Param data body dto.SysDictTypeUpdateReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/dict/type/{dictId} [put] +// @Security Bearer +func (e SysDictType) Update(c *gin.Context) { + s := service.SysDictType{} + req :=dto.SysDictTypeUpdateReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Error(500, err, err.Error()) + e.Logger.Error(err) + return + } + req.SetUpdateBy(user.GetUserId(c)) + err = s.Update(&req) + if err != nil { + e.Logger.Error(err) + return + } + e.OK(req.GetId(), "更新成功") +} + +// Delete +// @Summary 删除字典类型 +// @Description 删除数据 +// @Tags 字典类型 +// @Param dictCode body dto.SysDictTypeDeleteReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/dict/type [delete] +// @Security Bearer +func (e SysDictType) Delete(c *gin.Context) { + s := service.SysDictType{} + req :=dto.SysDictTypeDeleteReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + req.SetUpdateBy(user.GetUserId(c)) + err = s.Remove(&req) + if err != nil { + e.Error(500, err, err.Error()) + return + } + e.OK(req.GetId(), "删除成功") +} + +// GetAll +// @Summary 字典类型全部数据 代码生成使用接口 +// @Description 获取JSON +// @Tags 字典类型 +// @Param dictName query string false "dictName" +// @Param dictId query string false "dictId" +// @Param dictType query string false "dictType" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/dict/type-option-select [get] +// @Security Bearer +func (e SysDictType) GetAll(c *gin.Context) { + s := service.SysDictType{} + req :=dto.SysDictTypeGetPageReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.Form). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + list := make([]models.SysDictType, 0) + err = s.GetAll(&req, &list) + if err != nil { + e.Error(500, err, err.Error()) + return + } + e.OK(list, "查询成功") +} \ No newline at end of file diff --git a/app/admin/apis/sys_login_log.go b/app/admin/apis/sys_login_log.go new file mode 100644 index 0000000..6b6b4af --- /dev/null +++ b/app/admin/apis/sys_login_log.go @@ -0,0 +1,110 @@ +package apis + +import ( + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" + "github.com/go-admin-team/go-admin-core/sdk/api" + "go-admin/app/admin/models" + + "go-admin/app/admin/service" + "go-admin/app/admin/service/dto" +) + +type SysLoginLog struct { + api.Api +} + +// GetPage 登录日志列表 +// @Summary 登录日志列表 +// @Description 获取JSON +// @Tags 登录日志 +// @Param username query string false "用户名" +// @Param ipaddr query string false "ip地址" +// @Param loginLocation query string false "归属地" +// @Param status query string false "状态" +// @Param beginTime query string false "开始时间" +// @Param endTime query string false "结束时间" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/sys-login-log [get] +// @Security Bearer +func (e SysLoginLog) GetPage(c *gin.Context) { + s := service.SysLoginLog{} + req :=dto.SysLoginLogGetPageReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.Form). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + list := make([]models.SysLoginLog, 0) + var count int64 + err = s.GetPage(&req, &list, &count) + if err != nil { + e.Error(500, err, "查询失败") + return + } + e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") +} + +// Get 登录日志通过id获取 +// @Summary 登录日志通过id获取 +// @Description 获取JSON +// @Tags 登录日志 +// @Param id path string false "id" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/sys-login-log/{id} [get] +// @Security Bearer +func (e SysLoginLog) Get(c *gin.Context) { + s := service.SysLoginLog{} + req :=dto.SysLoginLogGetReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + var object models.SysLoginLog + err = s.Get(&req, &object) + if err != nil { + e.Error(500, err, "查询失败") + return + } + e.OK(object, "查询成功") +} + +// Delete 登录日志删除 +// @Summary 登录日志删除 +// @Description 登录日志删除 +// @Tags 登录日志 +// @Param data body dto.SysLoginLogDeleteReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/sys-login-log [delete] +// @Security Bearer +func (e SysLoginLog) Delete(c *gin.Context) { + s := service.SysLoginLog{} + req :=dto.SysLoginLogDeleteReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + err = s.Remove(&req) + if err != nil { + e.Error(500, err, "删除失败") + return + } + e.OK(req.GetId(), "删除成功") +} \ No newline at end of file diff --git a/app/admin/apis/sys_menu.go b/app/admin/apis/sys_menu.go new file mode 100644 index 0000000..d6eab24 --- /dev/null +++ b/app/admin/apis/sys_menu.go @@ -0,0 +1,287 @@ +package apis + +import ( + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + "go-admin/app/admin/models" + + "go-admin/app/admin/service" + "go-admin/app/admin/service/dto" +) + +type SysMenu struct { + api.Api +} + +// GetPage Menu列表数据 +// @Summary Menu列表数据 +// @Description 获取JSON +// @Tags 菜单 +// @Param menuName query string false "menuName" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/menu [get] +// @Security Bearer +func (e SysMenu) GetPage(c *gin.Context) { + s := service.SysMenu{} + req := dto.SysMenuGetPageReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.Form). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + var list = make([]models.SysMenu, 0) + err = s.GetPage(&req, &list).Error + if err != nil { + e.Error(500, err, "查询失败") + return + } + e.OK(list, "查询成功") +} + +// Get 获取菜单详情 +// @Summary Menu详情数据 +// @Description 获取JSON +// @Tags 菜单 +// @Param id path string false "id" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/menu/{id} [get] +// @Security Bearer +func (e SysMenu) Get(c *gin.Context) { + req := dto.SysMenuGetReq{} + s := new(service.SysMenu) + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + var object = models.SysMenu{} + + err = s.Get(&req, &object).Error + if err != nil { + e.Error(500, err, "查询失败") + return + } + e.OK(object, "查询成功") +} + +// Insert 创建菜单 +// @Summary 创建菜单 +// @Description 获取JSON +// @Tags 菜单 +// @Accept application/json +// @Product application/json +// @Param data body dto.SysMenuInsertReq true "data" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/menu [post] +// @Security Bearer +func (e SysMenu) Insert(c *gin.Context) { + req := dto.SysMenuInsertReq{} + s := new(service.SysMenu) + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + // 设置创建人 + req.SetCreateBy(user.GetUserId(c)) + err = s.Insert(&req).Error + if err != nil { + e.Error(500, err, "创建失败") + return + } + e.OK(req.GetId(), "创建成功") +} + +// Update 修改菜单 +// @Summary 修改菜单 +// @Description 获取JSON +// @Tags 菜单 +// @Accept application/json +// @Product application/json +// @Param id path int true "id" +// @Param data body dto.SysMenuUpdateReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/menu/{id} [put] +// @Security Bearer +func (e SysMenu) Update(c *gin.Context) { + req := dto.SysMenuUpdateReq{} + s := new(service.SysMenu) + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + req.SetUpdateBy(user.GetUserId(c)) + err = s.Update(&req).Error + if err != nil { + e.Error(500, err, "更新失败") + return + } + e.OK(req.GetId(), "更新成功") +} + +// Delete 删除菜单 +// @Summary 删除菜单 +// @Description 删除数据 +// @Tags 菜单 +// @Param data body dto.SysMenuDeleteReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/menu [delete] +// @Security Bearer +func (e SysMenu) Delete(c *gin.Context) { + control := new(dto.SysMenuDeleteReq) + s := new(service.SysMenu) + err := e.MakeContext(c). + MakeOrm(). + Bind(control, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + err = s.Remove(control).Error + if err != nil { + e.Logger.Errorf("RemoveSysMenu error, %s", err) + e.Error(500, err, "删除失败") + return + } + e.OK(control.GetId(), "删除成功") +} + +// GetMenuRole 根据登录角色名称获取菜单列表数据(左菜单使用) +// @Summary 根据登录角色名称获取菜单列表数据(左菜单使用) +// @Description 获取JSON +// @Tags 菜单 +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/menurole [get] +// @Security Bearer +func (e SysMenu) GetMenuRole(c *gin.Context) { + s := new(service.SysMenu) + err := e.MakeContext(c). + MakeOrm(). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + result, err := s.SetMenuRole(user.GetRoleName(c)) + + if err != nil { + e.Error(500, err, "查询失败") + return + } + + e.OK(result, "") +} + +//// GetMenuIDS 获取角色对应的菜单id数组 +//// @Summary 获取角色对应的菜单id数组,设置角色权限使用 +//// @Description 获取JSON +//// @Tags 菜单 +//// @Param id path int true "id" +//// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +//// @Router /api/v1/menuids/{id} [get] +//// @Security Bearer +//func (e SysMenu) GetMenuIDS(c *gin.Context) { +// s := new(service.SysMenu) +// r := service.SysRole{} +// m := dto.SysRoleByName{} +// err := e.MakeContext(c). +// MakeOrm(). +// Bind(&m, binding.JSON). +// MakeService(&s.Service). +// MakeService(&r.Service). +// Errors +// if err != nil { +// e.Logger.Error(err) +// e.Error(500, err, err.Error()) +// return +// } +// var data models.SysRole +// err = r.GetWithName(&m, &data).Error +// +// //data.RoleName = c.GetString("role") +// //data.UpdateBy = user.GetUserId(c) +// //result, err := data.GetIDS(s.Orm) +// +// if err != nil { +// e.Logger.Errorf("GetIDS error, %s", err.Error()) +// e.Error(500, err, "获取失败") +// return +// } +// e.OK(result, "") +//} + +// GetMenuTreeSelect 根据角色ID查询菜单下拉树结构 +// @Summary 角色修改使用的菜单列表 +// @Description 获取JSON +// @Tags 菜单 +// @Accept application/json +// @Product application/json +// @Param roleId path int true "roleId" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/menuTreeselect/{roleId} [get] +// @Security Bearer +func (e SysMenu) GetMenuTreeSelect(c *gin.Context) { + m := service.SysMenu{} + r := service.SysRole{} + req :=dto.SelectRole{} + err := e.MakeContext(c). + MakeOrm(). + MakeService(&m.Service). + MakeService(&r.Service). + Bind(&req, nil). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + result, err := m.SetLabel() + if err != nil { + e.Error(500, err, "查询失败") + return + } + + menuIds := make([]int, 0) + if req.RoleId != 0 { + menuIds, err = r.GetRoleMenuId(req.RoleId) + if err != nil { + e.Error(500, err, "") + return + } + } + e.OK(gin.H{ + "menus": result, + "checkedKeys": menuIds, + }, "获取成功") +} \ No newline at end of file diff --git a/app/admin/apis/sys_opera_log.go b/app/admin/apis/sys_opera_log.go new file mode 100644 index 0000000..2803924 --- /dev/null +++ b/app/admin/apis/sys_opera_log.go @@ -0,0 +1,118 @@ +package apis + +import ( + "fmt" + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" + "github.com/go-admin-team/go-admin-core/sdk/api" + "go-admin/app/admin/models" + "go-admin/app/admin/service" + "go-admin/app/admin/service/dto" +) + +type SysOperaLog struct { + api.Api +} + +// GetPage 操作日志列表 +// @Summary 操作日志列表 +// @Description 获取JSON +// @Tags 操作日志 +// @Param title query string false "title" +// @Param method query string false "method" +// @Param requestMethod query string false "requestMethod" +// @Param operUrl query string false "operUrl" +// @Param operIp query string false "operIp" +// @Param status query string false "status" +// @Param beginTime query string false "beginTime" +// @Param endTime query string false "endTime" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/sys-opera-log [get] +// @Security Bearer +func (e SysOperaLog) GetPage(c *gin.Context) { + s := service.SysOperaLog{} + req := new(dto.SysOperaLogGetPageReq) + err := e.MakeContext(c). + MakeOrm(). + Bind(req, binding.Form). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + list := make([]models.SysOperaLog, 0) + var count int64 + + err = s.GetPage(req, &list, &count) + if err != nil { + e.Error(500, err, "查询失败") + return + } + + e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") +} + +// Get 操作日志通过id获取 +// @Summary 操作日志通过id获取 +// @Description 获取JSON +// @Tags 操作日志 +// @Param id path string false "id" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/sys-opera-log/{id} [get] +// @Security Bearer +func (e SysOperaLog) Get(c *gin.Context) { + s := new(service.SysOperaLog) + req :=dto.SysOperaLogGetReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + var object models.SysOperaLog + err = s.Get(&req, &object) + if err != nil { + e.Error(500, err, "查询失败") + return + } + e.OK(object, "查询成功") +} + +// Delete 操作日志删除 +// DeleteSysMenu 操作日志删除 +// @Summary 删除操作日志 +// @Description 删除数据 +// @Tags 操作日志 +// @Param data body dto.SysOperaLogDeleteReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/sys-opera-log [delete] +// @Security Bearer +func (e SysOperaLog) Delete(c *gin.Context) { + s := new(service.SysOperaLog) + req :=dto.SysOperaLogDeleteReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + err = s.Remove(&req) + if err != nil { + e.Logger.Error(err) + e.Error(500,err, fmt.Sprintf("删除失败!错误详情:%s", err.Error())) + return + } + e.OK(req.GetId(), "删除成功") +} diff --git a/app/admin/apis/sys_post.go b/app/admin/apis/sys_post.go new file mode 100644 index 0000000..a12d54a --- /dev/null +++ b/app/admin/apis/sys_post.go @@ -0,0 +1,184 @@ +package apis + +import ( + "fmt" + + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + + "go-admin/app/admin/models" + "go-admin/app/admin/service" + "go-admin/app/admin/service/dto" +) + +type SysPost struct { + api.Api +} + +// GetPage +// @Summary 岗位列表数据 +// @Description 获取JSON +// @Tags 岗位 +// @Param postName query string false "postName" +// @Param postCode query string false "postCode" +// @Param postId query string false "postId" +// @Param status query string false "status" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/post [get] +// @Security Bearer +func (e SysPost) GetPage(c *gin.Context) { + s := service.SysPost{} + req :=dto.SysPostPageReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.Form). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + list := make([]models.SysPost, 0) + var count int64 + + err = s.GetPage(&req, &list, &count) + if err != nil { + e.Error(500, err, "查询失败") + return + } + + e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") +} + +// Get +// @Summary 获取岗位信息 +// @Description 获取JSON +// @Tags 岗位 +// @Param id path int true "编码" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/post/{postId} [get] +// @Security Bearer +func (e SysPost) Get(c *gin.Context) { + s := service.SysPost{} + req :=dto.SysPostGetReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + var object models.SysPost + + err = s.Get(&req, &object) + if err != nil { + e.Error(500, err, fmt.Sprintf("岗位信息获取失败!错误详情:%s", err.Error())) + return + } + + e.OK(object, "查询成功") +} + +// Insert +// @Summary 添加岗位 +// @Description 获取JSON +// @Tags 岗位 +// @Accept application/json +// @Product application/json +// @Param data body dto.SysPostInsertReq true "data" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/post [post] +// @Security Bearer +func (e SysPost) Insert(c *gin.Context) { + s := service.SysPost{} + req :=dto.SysPostInsertReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + req.SetCreateBy(user.GetUserId(c)) + err = s.Insert(&req) + if err != nil { + e.Error(500, err, fmt.Sprintf("新建岗位失败!错误详情:%s", err.Error())) + return + } + e.OK(req.GetId(), "创建成功") +} + +// Update +// @Summary 修改岗位 +// @Description 获取JSON +// @Tags 岗位 +// @Accept application/json +// @Product application/json +// @Param data body dto.SysPostUpdateReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/post/{id} [put] +// @Security Bearer +func (e SysPost) Update(c *gin.Context) { + s := service.SysPost{} + req :=dto.SysPostUpdateReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + req.SetUpdateBy(user.GetUserId(c)) + + err = s.Update(&req) + if err != nil { + e.Error(500, err, fmt.Sprintf("岗位更新失败!错误详情:%s", err.Error())) + return + } + e.OK(req.GetId(), "更新成功") +} + +// Delete +// @Summary 删除岗位 +// @Description 删除数据 +// @Tags 岗位 +// @Param id body dto.SysPostDeleteReq true "请求参数" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/post [delete] +// @Security Bearer +func (e SysPost) Delete(c *gin.Context) { + s := service.SysPost{} + req :=dto.SysPostDeleteReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + req.SetUpdateBy(user.GetUserId(c)) + err = s.Remove(&req) + if err != nil { + e.Error(500, err, fmt.Sprintf("岗位删除失败!错误详情:%s", err.Error())) + return + } + e.OK(req.GetId(), "删除成功") +} \ No newline at end of file diff --git a/app/admin/apis/sys_role.go b/app/admin/apis/sys_role.go new file mode 100644 index 0000000..d7ee1e7 --- /dev/null +++ b/app/admin/apis/sys_role.go @@ -0,0 +1,284 @@ +package apis + +import ( + "fmt" + "go-admin/common/global" + "net/http" + + "github.com/gin-gonic/gin/binding" + "github.com/go-admin-team/go-admin-core/sdk" + "go-admin/app/admin/models" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + + "go-admin/app/admin/service" + "go-admin/app/admin/service/dto" +) + +type SysRole struct { + api.Api +} + +// GetPage +// @Summary 角色列表数据 +// @Description Get JSON +// @Tags 角色/Role +// @Param roleName query string false "roleName" +// @Param status query string false "status" +// @Param roleKey query string false "roleKey" +// @Param pageSize query int false "页条数" +// @Param pageIndex query int false "页码" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/role [get] +// @Security Bearer +func (e SysRole) GetPage(c *gin.Context) { + s := service.SysRole{} + req := dto.SysRoleGetPageReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.Form). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + list := make([]models.SysRole, 0) + var count int64 + + err = s.GetPage(&req, &list, &count) + if err != nil { + e.Error(500, err, "查询失败") + return + } + + e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") +} + +// Get +// @Summary 获取Role数据 +// @Description 获取JSON +// @Tags 角色/Role +// @Param roleId path string false "roleId" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/role/{id} [get] +// @Security Bearer +func (e SysRole) Get(c *gin.Context) { + s := service.SysRole{} + req := dto.SysRoleGetReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, fmt.Sprintf(" %s ", err.Error())) + return + } + + var object models.SysRole + + err = s.Get(&req, &object) + if err != nil { + e.Error(http.StatusUnprocessableEntity, err, "查询失败") + return + } + + e.OK(object, "查询成功") +} + +// Insert +// @Summary 创建角色 +// @Description 获取JSON +// @Tags 角色/Role +// @Accept application/json +// @Product application/json +// @Param data body dto.SysRoleInsertReq true "data" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/role [post] +// @Security Bearer +func (e SysRole) Insert(c *gin.Context) { + s := service.SysRole{} + req := dto.SysRoleInsertReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + // 设置创建人 + req.CreateBy = user.GetUserId(c) + if req.Status == "" { + req.Status = "2" + } + cb := sdk.Runtime.GetCasbinKey(c.Request.Host) + err = s.Insert(&req, cb) + if err != nil { + e.Logger.Error(err) + e.Error(500, err, "创建失败,"+err.Error()) + return + } + _, err = global.LoadPolicy(c) + if err != nil { + e.Logger.Error(err) + e.Error(500, err, "创建失败,"+err.Error()) + return + } + e.OK(req.GetId(), "创建成功") +} + +// Update 修改用户角色 +// @Summary 修改用户角色 +// @Description 获取JSON +// @Tags 角色/Role +// @Accept application/json +// @Product application/json +// @Param data body dto.SysRoleUpdateReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/role/{id} [put] +// @Security Bearer +func (e SysRole) Update(c *gin.Context) { + s := service.SysRole{} + req := dto.SysRoleUpdateReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, nil, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + cb := sdk.Runtime.GetCasbinKey(c.Request.Host) + + req.SetUpdateBy(user.GetUserId(c)) + + err = s.Update(&req, cb) + if err != nil { + e.Logger.Error(err) + return + } + + _, err = global.LoadPolicy(c) + if err != nil { + e.Logger.Error(err) + e.Error(500, err, "更新失败,"+err.Error()) + return + } + + e.OK(req.GetId(), "更新成功") +} + +// Delete +// @Summary 删除用户角色 +// @Description 删除数据 +// @Tags 角色/Role +// @Param data body dto.SysRoleDeleteReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/role [delete] +// @Security Bearer +func (e SysRole) Delete(c *gin.Context) { + s := new(service.SysRole) + req := dto.SysRoleDeleteReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, fmt.Sprintf("删除角色 %v 失败,\r\n失败信息 %s", req.Ids, err.Error())) + return + } + + cb := sdk.Runtime.GetCasbinKey(c.Request.Host) + err = s.Remove(&req, cb) + if err != nil { + e.Logger.Error(err) + e.Error(500, err, "") + return + } + + e.OK(req.GetId(), fmt.Sprintf("删除角色角色 %v 状态成功!", req.GetId())) +} + +// Update2Status 修改用户角色状态 +// @Summary 修改用户角色 +// @Description 获取JSON +// @Tags 角色/Role +// @Accept application/json +// @Product application/json +// @Param data body dto.UpdateStatusReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/role-status/{id} [put] +// @Security Bearer +func (e SysRole) Update2Status(c *gin.Context) { + s := service.SysRole{} + req := dto.UpdateStatusReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, fmt.Sprintf("更新角色状态失败,失败原因:%s ", err.Error())) + return + } + req.SetUpdateBy(user.GetUserId(c)) + err = s.UpdateStatus(&req) + if err != nil { + e.Error(500, err, fmt.Sprintf("更新角色状态失败,失败原因:%s ", err.Error())) + return + } + e.OK(req.GetId(), fmt.Sprintf("更新角色 %v 状态成功!", req.GetId())) +} + +// Update2DataScope 更新角色数据权限 +// @Summary 更新角色数据权限 +// @Description 获取JSON +// @Tags 角色/Role +// @Accept application/json +// @Product application/json +// @Param data body dto.RoleDataScopeReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/role-status/{id} [put] +// @Security Bearer +func (e SysRole) Update2DataScope(c *gin.Context) { + s := service.SysRole{} + req := dto.RoleDataScopeReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + data := &models.SysRole{ + RoleId: req.RoleId, + DataScope: req.DataScope, + DeptIds: req.DeptIds, + } + data.UpdateBy = user.GetUserId(c) + err = s.UpdateDataScope(&req).Error + if err != nil { + e.Error(500, err, fmt.Sprintf("更新角色数据权限失败!错误详情:%s", err.Error())) + return + } + e.OK(nil, "操作成功") +} diff --git a/app/admin/apis/sys_user.go b/app/admin/apis/sys_user.go new file mode 100644 index 0000000..64eb501 --- /dev/null +++ b/app/admin/apis/sys_user.go @@ -0,0 +1,459 @@ +package apis + +import ( + "github.com/gin-gonic/gin/binding" + "go-admin/app/admin/models" + "golang.org/x/crypto/bcrypt" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + "github.com/google/uuid" + + "go-admin/app/admin/service" + "go-admin/app/admin/service/dto" + "go-admin/common/actions" +) + +type SysUser struct { + api.Api +} + +// GetPage +// @Summary 列表用户信息数据 +// @Description 获取JSON +// @Tags 用户 +// @Param username query string false "username" +// @Success 200 {string} {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/sys-user [get] +// @Security Bearer +func (e SysUser) GetPage(c *gin.Context) { + s := service.SysUser{} + req := dto.SysUserGetPageReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + //数据权限检查 + p := actions.GetPermissionFromContext(c) + + list := make([]models.SysUser, 0) + var count int64 + + err = s.GetPage(&req, p, &list, &count) + if err != nil { + e.Error(500, err, "查询失败") + return + } + + e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") +} + +// Get +// @Summary 获取用户 +// @Description 获取JSON +// @Tags 用户 +// @Param userId path int true "用户编码" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/sys-user/{userId} [get] +// @Security Bearer +func (e SysUser) Get(c *gin.Context) { + s := service.SysUser{} + req := dto.SysUserById{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + var object models.SysUser + //数据权限检查 + p := actions.GetPermissionFromContext(c) + err = s.Get(&req, p, &object) + if err != nil { + e.Error(http.StatusUnprocessableEntity, err, "查询失败") + return + } + e.OK(object, "查询成功") +} + +// Insert +// @Summary 创建用户 +// @Description 获取JSON +// @Tags 用户 +// @Accept application/json +// @Product application/json +// @Param data body dto.SysUserInsertReq true "用户数据" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/sys-user [post] +// @Security Bearer +func (e SysUser) Insert(c *gin.Context) { + s := service.SysUser{} + req := dto.SysUserInsertReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + // 设置创建人 + req.SetCreateBy(user.GetUserId(c)) + err = s.Insert(&req) + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + e.OK(req.GetId(), "创建成功") +} + +// Update +// @Summary 修改用户数据 +// @Description 获取JSON +// @Tags 用户 +// @Accept application/json +// @Product application/json +// @Param data body dto.SysUserUpdateReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/sys-user/{userId} [put] +// @Security Bearer +func (e SysUser) Update(c *gin.Context) { + s := service.SysUser{} + req := dto.SysUserUpdateReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + req.SetUpdateBy(user.GetUserId(c)) + + //数据权限检查 + p := actions.GetPermissionFromContext(c) + + err = s.Update(&req, p) + if err != nil { + e.Logger.Error(err) + return + } + e.OK(req.GetId(), "更新成功") +} + +// Delete +// @Summary 删除用户数据 +// @Description 删除数据 +// @Tags 用户 +// @Param userId path int true "userId" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/sys-user/{userId} [delete] +// @Security Bearer +func (e SysUser) Delete(c *gin.Context) { + s := service.SysUser{} + req := dto.SysUserById{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + // 设置编辑人 + req.SetUpdateBy(user.GetUserId(c)) + + // 数据权限检查 + p := actions.GetPermissionFromContext(c) + + err = s.Remove(&req, p) + if err != nil { + e.Logger.Error(err) + return + } + e.OK(req.GetId(), "删除成功") +} + +// InsetAvatar +// @Summary 修改头像 +// @Description 获取JSON +// @Tags 个人中心 +// @Accept multipart/form-data +// @Param file formData file true "file" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/user/avatar [post] +// @Security Bearer +func (e SysUser) InsetAvatar(c *gin.Context) { + s := service.SysUser{} + req := dto.UpdateSysUserAvatarReq{} + err := e.MakeContext(c). + MakeOrm(). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + // 数据权限检查 + p := actions.GetPermissionFromContext(c) + form, _ := c.MultipartForm() + files := form.File["upload[]"] + guid := uuid.New().String() + filPath := "static/uploadfile/" + guid + ".jpg" + for _, file := range files { + e.Logger.Debugf("upload avatar file: %s", file.Filename) + // 上传文件至指定目录 + err = c.SaveUploadedFile(file, filPath) + if err != nil { + e.Logger.Errorf("save file error, %s", err.Error()) + e.Error(500, err, "") + return + } + } + req.UserId = p.UserId + req.Avatar = "/" + filPath + + err = s.UpdateAvatar(&req, p) + if err != nil { + e.Logger.Error(err) + return + } + e.OK(filPath, "修改成功") +} + +// UpdateStatus 修改用户状态 +// @Summary 修改用户状态 +// @Description 获取JSON +// @Tags 用户 +// @Accept application/json +// @Product application/json +// @Param data body dto.UpdateSysUserStatusReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/user/status [put] +// @Security Bearer +func (e SysUser) UpdateStatus(c *gin.Context) { + s := service.SysUser{} + req := dto.UpdateSysUserStatusReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON, nil). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + req.SetUpdateBy(user.GetUserId(c)) + + //数据权限检查 + p := actions.GetPermissionFromContext(c) + + err = s.UpdateStatus(&req, p) + if err != nil { + e.Logger.Error(err) + return + } + e.OK(req.GetId(), "更新成功") +} + +// ResetPwd 重置用户密码 +// @Summary 重置用户密码 +// @Description 获取JSON +// @Tags 用户 +// @Accept application/json +// @Product application/json +// @Param data body dto.ResetSysUserPwdReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/user/pwd/reset [put] +// @Security Bearer +func (e SysUser) ResetPwd(c *gin.Context) { + s := service.SysUser{} + req := dto.ResetSysUserPwdReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + req.SetUpdateBy(user.GetUserId(c)) + + //数据权限检查 + p := actions.GetPermissionFromContext(c) + + err = s.ResetPwd(&req, p) + if err != nil { + e.Logger.Error(err) + return + } + e.OK(req.GetId(), "更新成功") +} + +// UpdatePwd +// @Summary 修改密码 +// @Description 获取JSON +// @Tags 用户 +// @Accept application/json +// @Product application/json +// @Param data body dto.PassWord true "body" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/user/pwd/set [put] +// @Security Bearer +func (e SysUser) UpdatePwd(c *gin.Context) { + s := service.SysUser{} + req := dto.PassWord{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + // 数据权限检查 + p := actions.GetPermissionFromContext(c) + var hash []byte + if hash, err = bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost); err != nil { + req.NewPassword = string(hash) + } + + err = s.UpdatePwd(user.GetUserId(c), req.OldPassword, req.NewPassword, p) + if err != nil { + e.Logger.Error(err) + e.Error(http.StatusForbidden, err, "密码修改失败") + return + } + + e.OK(nil, "密码修改成功") +} + +// GetProfile +// @Summary 获取个人中心用户 +// @Description 获取JSON +// @Tags 个人中心 +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/user/profile [get] +// @Security Bearer +func (e SysUser) GetProfile(c *gin.Context) { + s := service.SysUser{} + req := dto.SysUserById{} + err := e.MakeContext(c). + MakeOrm(). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + req.Id = user.GetUserId(c) + + sysUser := models.SysUser{} + roles := make([]models.SysRole, 0) + posts := make([]models.SysPost, 0) + err = s.GetProfile(&req, &sysUser, &roles, &posts) + if err != nil { + e.Logger.Errorf("get user profile error, %s", err.Error()) + e.Error(500, err, "获取用户信息失败") + return + } + e.OK(gin.H{ + "user": sysUser, + "roles": roles, + "posts": posts, + }, "查询成功") +} + +// GetInfo +// @Summary 获取个人信息 +// @Description 获取JSON +// @Tags 个人中心 +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/getinfo [get] +// @Security Bearer +func (e SysUser) GetInfo(c *gin.Context) { + req := dto.SysUserById{} + s := service.SysUser{} + r := service.SysRole{} + err := e.MakeContext(c). + MakeOrm(). + MakeService(&r.Service). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + p := actions.GetPermissionFromContext(c) + var roles = make([]string, 1) + roles[0] = user.GetRoleName(c) + var permissions = make([]string, 1) + permissions[0] = "*:*:*" + var buttons = make([]string, 1) + buttons[0] = "*:*:*" + + var mp = make(map[string]interface{}) + mp["roles"] = roles + if user.GetRoleName(c) == "admin" || user.GetRoleName(c) == "系统管理员" { + mp["permissions"] = permissions + mp["buttons"] = buttons + } else { + list, _ := r.GetById(user.GetRoleId(c)) + mp["permissions"] = list + mp["buttons"] = list + } + sysUser := models.SysUser{} + req.Id = user.GetUserId(c) + err = s.Get(&req, p, &sysUser) + if err != nil { + e.Error(http.StatusUnauthorized, err, "登录失败") + return + } + mp["introduction"] = " am a super administrator" + mp["avatar"] = "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif" + if sysUser.Avatar != "" { + mp["avatar"] = sysUser.Avatar + } + mp["userName"] = sysUser.NickName + mp["userId"] = sysUser.UserId + mp["deptId"] = sysUser.DeptId + mp["name"] = sysUser.NickName + mp["code"] = 200 + e.OK(mp, "") +} diff --git a/app/admin/models/casbin_rule.go b/app/admin/models/casbin_rule.go new file mode 100644 index 0000000..d9013ee --- /dev/null +++ b/app/admin/models/casbin_rule.go @@ -0,0 +1,16 @@ +package models + +type CasbinRule struct { + ID uint `gorm:"primaryKey;autoIncrement"` + Ptype string `gorm:"size:512;uniqueIndex:unique_index"` + V0 string `gorm:"size:512;uniqueIndex:unique_index"` + V1 string `gorm:"size:512;uniqueIndex:unique_index"` + V2 string `gorm:"size:512;uniqueIndex:unique_index"` + V3 string `gorm:"size:512;uniqueIndex:unique_index"` + V4 string `gorm:"size:512;uniqueIndex:unique_index"` + V5 string `gorm:"size:512;uniqueIndex:unique_index"` +} + +func (CasbinRule) TableName() string { + return "sys_casbin_rule" +} diff --git a/app/admin/models/datascope.go b/app/admin/models/datascope.go new file mode 100644 index 0000000..8ccd047 --- /dev/null +++ b/app/admin/models/datascope.go @@ -0,0 +1,81 @@ +package models + +import ( + "errors" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "gorm.io/gorm" + + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk/config" +) + +type DataPermission struct { + DataScope string + UserId int + DeptId int + RoleId int +} + +func (e *DataPermission) GetDataScope(tableName string, db *gorm.DB) (*gorm.DB, error) { + + if !config.ApplicationConfig.EnableDP { + usageStr := `数据权限已经为您` + pkg.Green(`关闭`) + `,如需开启请参考配置文件字段说明` + log.Debug("%s\n", usageStr) + return db, nil + } + user := new(SysUser) + role := new(SysRole) + err := db.Find(user, e.UserId).Error + if err != nil { + return nil, errors.New("获取用户数据出错 msg:" + err.Error()) + } + err = db.Find(role, user.RoleId).Error + if err != nil { + return nil, errors.New("获取用户数据出错 msg:" + err.Error()) + } + if role.DataScope == "2" { + db = db.Where(tableName+".create_by in (select sys_user.user_id from sys_role_dept left join sys_user on sys_user.dept_id=sys_role_dept.dept_id where sys_role_dept.role_id = ?)", user.RoleId) + } + if role.DataScope == "3" { + db = db.Where(tableName+".create_by in (SELECT user_id from sys_user where dept_id = ? )", user.DeptId) + } + if role.DataScope == "4" { + db = db.Where(tableName+".create_by in (SELECT user_id from sys_user where sys_user.dept_id in(select dept_id from sys_dept where dept_path like ? ))", "%"+pkg.IntToString(user.DeptId)+"%") + } + if role.DataScope == "5" || role.DataScope == "" { + db = db.Where(tableName+".create_by = ?", e.UserId) + } + + return db, nil +} + +//func DataScopes(tableName string, userId int) func(db *gorm.DB) *gorm.DB { +// return func(db *gorm.DB) *gorm.DB { +// user := new(SysUser) +// role := new(SysRole) +// user.UserId = userId +// err := db.Find(user, userId).Error +// if err != nil { +// db.Error = errors.New("获取用户数据出错 msg:" + err.Error()) +// return db +// } +// err = db.Find(role, user.RoleId).Error +// if err != nil { +// db.Error = errors.New("获取用户数据出错 msg:" + err.Error()) +// return db +// } +// if role.DataScope == "2" { +// return db.Where(tableName+".create_by in (select sys_user.user_id from sys_role_dept left join sys_user on sys_user.dept_id=sys_role_dept.dept_id where sys_role_dept.role_id = ?)", user.RoleId) +// } +// if role.DataScope == "3" { +// return db.Where(tableName+".create_by in (SELECT user_id from sys_user where dept_id = ? )", user.DeptId) +// } +// if role.DataScope == "4" { +// return db.Where(tableName+".create_by in (SELECT user_id from sys_user where sys_user.dept_id in(select dept_id from sys_dept where dept_path like ? ))", "%"+pkg.IntToString(user.DeptId)+"%") +// } +// if role.DataScope == "5" || role.DataScope == "" { +// return db.Where(tableName+".create_by = ?", userId) +// } +// return db +// } +//} diff --git a/app/admin/models/initdb.go b/app/admin/models/initdb.go new file mode 100644 index 0000000..cdec260 --- /dev/null +++ b/app/admin/models/initdb.go @@ -0,0 +1,55 @@ +package models + +import ( + "fmt" + "go-admin/common/global" + "gorm.io/gorm" + "io/ioutil" + "log" + "strings" +) + +func InitDb(db *gorm.DB) (err error) { + filePath := "config/db.sql" + err = ExecSql(db, filePath) + if global.Driver == "postgres" { + filePath = "config/pg.sql" + err = ExecSql(db, filePath) + } + return err +} + +func ExecSql(db *gorm.DB, filePath string) error { + sql, err := Ioutil(filePath) + if err != nil { + fmt.Println("数据库基础数据初始化脚本读取失败!原因:", err.Error()) + return err + } + sqlList := strings.Split(sql, ";") + for i := 0; i < len(sqlList)-1; i++ { + if strings.Contains(sqlList[i], "--") { + fmt.Println(sqlList[i]) + continue + } + sql := strings.Replace(sqlList[i]+";", "\n", "", -1) + sql = strings.TrimSpace(sql) + if err = db.Exec(sql).Error; err != nil { + log.Printf("error sql: %s", sql) + if !strings.Contains(err.Error(), "Query was empty") { + return err + } + } + } + return nil +} + +func Ioutil(filePath string) (string, error) { + if contents, err := ioutil.ReadFile(filePath); err == nil { + //因为contents是[]byte类型,直接转换成string类型后会多一行空格,需要使用strings.Replace替换换行符 + result := strings.Replace(string(contents), "\n", "", 1) + fmt.Println("Use ioutil.ReadFile to read a file:", result) + return result, nil + } else { + return "", err + } +} diff --git a/app/admin/models/model.go b/app/admin/models/model.go new file mode 100644 index 0000000..4a1c439 --- /dev/null +++ b/app/admin/models/model.go @@ -0,0 +1,11 @@ +package models + +import ( + "time" +) + +type BaseModel struct { + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` +} diff --git a/app/admin/models/sys_api.go b/app/admin/models/sys_api.go new file mode 100644 index 0000000..0b78e49 --- /dev/null +++ b/app/admin/models/sys_api.go @@ -0,0 +1,91 @@ +package models + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "regexp" + "strings" + + "github.com/bitly/go-simplejson" + "github.com/go-admin-team/go-admin-core/sdk" + "github.com/go-admin-team/go-admin-core/sdk/runtime" + "github.com/go-admin-team/go-admin-core/storage" + + "go-admin/common/models" +) + +type SysApi struct { + Id int `json:"id" gorm:"primaryKey;autoIncrement;comment:主键编码"` + Handle string `json:"handle" gorm:"size:128;comment:handle"` + Title string `json:"title" gorm:"size:128;comment:标题"` + Path string `json:"path" gorm:"size:128;comment:地址"` + Action string `json:"action" gorm:"size:16;comment:请求类型"` + Type string `json:"type" gorm:"size:16;comment:接口类型"` + models.ModelTime + models.ControlBy +} + +func (*SysApi) TableName() string { + return "sys_api" +} + +func (e *SysApi) Generate() models.ActiveRecord { + o := *e + return &o +} + +func (e *SysApi) GetId() interface{} { + return e.Id +} + +func SaveSysApi(message storage.Messager) (err error) { + var rb []byte + rb, err = json.Marshal(message.GetValues()) + if err != nil { + err = fmt.Errorf("json Marshal error, %v", err.Error()) + return err + } + + var l runtime.Routers + err = json.Unmarshal(rb, &l) + if err != nil { + err = fmt.Errorf("json Unmarshal error, %s", err.Error()) + return err + } + dbList := sdk.Runtime.GetDb() + for _, d := range dbList { + for _, v := range l.List { + if v.HttpMethod != "HEAD" || + strings.Contains(v.RelativePath, "/swagger/") || + strings.Contains(v.RelativePath, "/static/") || + strings.Contains(v.RelativePath, "/form-generator/") || + strings.Contains(v.RelativePath, "/sys/tables") { + + // 根据接口方法注释里的@Summary填充接口名称,适用于代码生成器 + // 可在此处增加配置路径前缀的if判断,只对代码生成的自建应用进行定向的接口名称填充 + jsonFile, _ := ioutil.ReadFile("docs/swagger.json") + jsonData, _ := simplejson.NewFromReader(bytes.NewReader(jsonFile)) + urlPath := v.RelativePath + idPatten := "(.*)/:(\\w+)" // 正则替换,把:id换成{id} + reg, _ := regexp.Compile(idPatten) + if reg.MatchString(urlPath) { + urlPath = reg.ReplaceAllString(v.RelativePath, "${1}/{${2}}") // 把:id换成{id} + } + apiTitle, _ := jsonData.Get("paths").Get(urlPath).Get(strings.ToLower(v.HttpMethod)).Get("summary").String() + + err := d.Debug().Where(SysApi{Path: v.RelativePath, Action: v.HttpMethod}). + Attrs(SysApi{Handle: v.Handler, Title: apiTitle}). + FirstOrCreate(&SysApi{}). + //Update("handle", v.Handler). + Error + if err != nil { + err := fmt.Errorf("Models SaveSysApi error: %s \r\n ", err.Error()) + return err + } + } + } + } + return nil +} diff --git a/app/admin/models/sys_config.go b/app/admin/models/sys_config.go new file mode 100644 index 0000000..2024bbb --- /dev/null +++ b/app/admin/models/sys_config.go @@ -0,0 +1,30 @@ +package models + +import ( + "go-admin/common/models" +) + +type SysConfig struct { + models.Model + ConfigName string `json:"configName" gorm:"size:128;comment:ConfigName"` // + ConfigKey string `json:"configKey" gorm:"size:128;comment:ConfigKey"` // + ConfigValue string `json:"configValue" gorm:"size:255;comment:ConfigValue"` // + ConfigType string `json:"configType" gorm:"size:64;comment:ConfigType"` + IsFrontend string `json:"isFrontend" gorm:"size:64;comment:是否前台"` // + Remark string `json:"remark" gorm:"size:128;comment:Remark"` // + models.ControlBy + models.ModelTime +} + +func (*SysConfig) TableName() string { + return "sys_config" +} + +func (e *SysConfig) Generate() models.ActiveRecord { + o := *e + return &o +} + +func (e *SysConfig) GetId() interface{} { + return e.Id +} diff --git a/app/admin/models/sys_dept.go b/app/admin/models/sys_dept.go new file mode 100644 index 0000000..e4400de --- /dev/null +++ b/app/admin/models/sys_dept.go @@ -0,0 +1,33 @@ +package models + +import "go-admin/common/models" + +type SysDept struct { + DeptId int `json:"deptId" gorm:"primaryKey;autoIncrement;"` //部门编码 + ParentId int `json:"parentId" gorm:""` //上级部门 + DeptPath string `json:"deptPath" gorm:"size:255;"` // + DeptName string `json:"deptName" gorm:"size:128;"` //部门名称 + Sort int `json:"sort" gorm:"size:4;"` //排序 + Leader string `json:"leader" gorm:"size:128;"` //负责人 + Phone string `json:"phone" gorm:"size:11;"` //手机 + Email string `json:"email" gorm:"size:64;"` //邮箱 + Status int `json:"status" gorm:"size:4;"` //状态 + models.ControlBy + models.ModelTime + DataScope string `json:"dataScope" gorm:"-"` + Params string `json:"params" gorm:"-"` + Children []SysDept `json:"children" gorm:"-"` +} + +func (*SysDept) TableName() string { + return "sys_dept" +} + +func (e *SysDept) Generate() models.ActiveRecord { + o := *e + return &o +} + +func (e *SysDept) GetId() interface{} { + return e.DeptId +} diff --git a/app/admin/models/sys_dict_data.go b/app/admin/models/sys_dict_data.go new file mode 100644 index 0000000..15abf89 --- /dev/null +++ b/app/admin/models/sys_dict_data.go @@ -0,0 +1,34 @@ +package models + +import ( + "go-admin/common/models" +) + +type SysDictData struct { + DictCode int `json:"dictCode" gorm:"primaryKey;column:dict_code;autoIncrement;comment:主键编码"` + DictSort int `json:"dictSort" gorm:"size:20;comment:DictSort"` + DictLabel string `json:"dictLabel" gorm:"size:128;comment:DictLabel"` + DictValue string `json:"dictValue" gorm:"size:255;comment:DictValue"` + DictType string `json:"dictType" gorm:"size:64;comment:DictType"` + CssClass string `json:"cssClass" gorm:"size:128;comment:CssClass"` + ListClass string `json:"listClass" gorm:"size:128;comment:ListClass"` + IsDefault string `json:"isDefault" gorm:"size:8;comment:IsDefault"` + Status int `json:"status" gorm:"size:4;comment:Status"` + Default string `json:"default" gorm:"size:8;comment:Default"` + Remark string `json:"remark" gorm:"size:255;comment:Remark"` + models.ControlBy + models.ModelTime +} + +func (*SysDictData) TableName() string { + return "sys_dict_data" +} + +func (e *SysDictData) Generate() models.ActiveRecord { + o := *e + return &o +} + +func (e *SysDictData) GetId() interface{} { + return e.DictCode +} diff --git a/app/admin/models/sys_dict_type.go b/app/admin/models/sys_dict_type.go new file mode 100644 index 0000000..49f7ebe --- /dev/null +++ b/app/admin/models/sys_dict_type.go @@ -0,0 +1,28 @@ +package models + +import ( + "go-admin/common/models" +) + +type SysDictType struct { + ID int `json:"id" gorm:"primaryKey;column:dict_id;autoIncrement;comment:主键编码"` + DictName string `json:"dictName" gorm:"size:128;comment:DictName"` + DictType string `json:"dictType" gorm:"size:128;comment:DictType"` + Status int `json:"status" gorm:"size:4;comment:Status"` + Remark string `json:"remark" gorm:"size:255;comment:Remark"` + models.ControlBy + models.ModelTime +} + +func (*SysDictType) TableName() string { + return "sys_dict_type" +} + +func (e *SysDictType) Generate() models.ActiveRecord { + o := *e + return &o +} + +func (e *SysDictType) GetId() interface{} { + return e.ID +} diff --git a/app/admin/models/sys_login_log.go b/app/admin/models/sys_login_log.go new file mode 100644 index 0000000..98873e8 --- /dev/null +++ b/app/admin/models/sys_login_log.go @@ -0,0 +1,72 @@ +package models + +import ( + "encoding/json" + "errors" + "time" + + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk" + "github.com/go-admin-team/go-admin-core/storage" + + "go-admin/common/models" +) + +type SysLoginLog struct { + models.Model + Username string `json:"username" gorm:"size:128;comment:用户名"` + Status string `json:"status" gorm:"size:4;comment:状态"` + Ipaddr string `json:"ipaddr" gorm:"size:255;comment:ip地址"` + LoginLocation string `json:"loginLocation" gorm:"size:255;comment:归属地"` + Browser string `json:"browser" gorm:"size:255;comment:浏览器"` + Os string `json:"os" gorm:"size:255;comment:系统"` + Platform string `json:"platform" gorm:"size:255;comment:固件"` + LoginTime time.Time `json:"loginTime" gorm:"comment:登录时间"` + Remark string `json:"remark" gorm:"size:255;comment:备注"` + Msg string `json:"msg" gorm:"size:255;comment:信息"` + CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"` + UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"` + models.ControlBy +} + +func (*SysLoginLog) TableName() string { + return "sys_login_log" +} + +func (e *SysLoginLog) Generate() models.ActiveRecord { + o := *e + return &o +} + +func (e *SysLoginLog) GetId() interface{} { + return e.Id +} + +// SaveLoginLog 从队列中获取登录日志 +func SaveLoginLog(message storage.Messager) (err error) { + //准备db + db := sdk.Runtime.GetDbByKey(message.GetPrefix()) + if db == nil { + err = errors.New("db not exist") + log.Errorf("host[%s]'s %s", message.GetPrefix(), err.Error()) + return err + } + var rb []byte + rb, err = json.Marshal(message.GetValues()) + if err != nil { + log.Errorf("json Marshal error, %s", err.Error()) + return err + } + var l SysLoginLog + err = json.Unmarshal(rb, &l) + if err != nil { + log.Errorf("json Unmarshal error, %s", err.Error()) + return err + } + err = db.Create(&l).Error + if err != nil { + log.Errorf("db create error, %s", err.Error()) + return err + } + return nil +} diff --git a/app/admin/models/sys_menu.go b/app/admin/models/sys_menu.go new file mode 100644 index 0000000..ea7e669 --- /dev/null +++ b/app/admin/models/sys_menu.go @@ -0,0 +1,50 @@ +package models + +import "go-admin/common/models" + +type SysMenu struct { + MenuId int `json:"menuId" gorm:"primaryKey;autoIncrement"` + MenuName string `json:"menuName" gorm:"size:128;"` + Title string `json:"title" gorm:"size:128;"` + Icon string `json:"icon" gorm:"size:128;"` + Path string `json:"path" gorm:"size:128;"` + Paths string `json:"paths" gorm:"size:128;"` + MenuType string `json:"menuType" gorm:"size:1;"` + Action string `json:"action" gorm:"size:16;"` + Permission string `json:"permission" gorm:"size:255;"` + ParentId int `json:"parentId" gorm:"size:11;"` + NoCache bool `json:"noCache" gorm:"size:8;"` + Breadcrumb string `json:"breadcrumb" gorm:"size:255;"` + Component string `json:"component" gorm:"size:255;"` + Sort int `json:"sort" gorm:"size:4;"` + Visible string `json:"visible" gorm:"size:1;"` + IsFrame string `json:"isFrame" gorm:"size:1;DEFAULT:0;"` + SysApi []SysApi `json:"sysApi" gorm:"many2many:sys_menu_api_rule"` + Apis []int `json:"apis" gorm:"-"` + DataScope string `json:"dataScope" gorm:"-"` + Params string `json:"params" gorm:"-"` + RoleId int `gorm:"-"` + Children []SysMenu `json:"children,omitempty" gorm:"-"` + IsSelect bool `json:"is_select" gorm:"-"` + models.ControlBy + models.ModelTime +} + +type SysMenuSlice []SysMenu + +func (x SysMenuSlice) Len() int { return len(x) } +func (x SysMenuSlice) Less(i, j int) bool { return x[i].Sort < x[j].Sort } +func (x SysMenuSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] } + +func (*SysMenu) TableName() string { + return "sys_menu" +} + +func (e *SysMenu) Generate() models.ActiveRecord { + o := *e + return &o +} + +func (e *SysMenu) GetId() interface{} { + return e.MenuId +} diff --git a/app/admin/models/sys_opera_log.go b/app/admin/models/sys_opera_log.go new file mode 100644 index 0000000..e29a54d --- /dev/null +++ b/app/admin/models/sys_opera_log.go @@ -0,0 +1,88 @@ +package models + +import ( + "encoding/json" + "errors" + "time" + + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk" + "github.com/go-admin-team/go-admin-core/storage" + + "go-admin/common/models" +) + +type SysOperaLog struct { + models.Model + Title string `json:"title" gorm:"size:255;comment:操作模块"` + BusinessType string `json:"businessType" gorm:"size:128;comment:操作类型"` + BusinessTypes string `json:"businessTypes" gorm:"size:128;comment:BusinessTypes"` + Method string `json:"method" gorm:"size:128;comment:函数"` + RequestMethod string `json:"requestMethod" gorm:"size:128;comment:请求方式 GET POST PUT DELETE"` + OperatorType string `json:"operatorType" gorm:"size:128;comment:操作类型"` + OperName string `json:"operName" gorm:"size:128;comment:操作者"` + DeptName string `json:"deptName" gorm:"size:128;comment:部门名称"` + OperUrl string `json:"operUrl" gorm:"size:255;comment:访问地址"` + OperIp string `json:"operIp" gorm:"size:128;comment:客户端ip"` + OperLocation string `json:"operLocation" gorm:"size:128;comment:访问位置"` + OperParam string `json:"operParam" gorm:"text;comment:请求参数"` + Status string `json:"status" gorm:"size:4;comment:操作状态 1:正常 2:关闭"` + OperTime time.Time `json:"operTime" gorm:"comment:操作时间"` + JsonResult string `json:"jsonResult" gorm:"size:255;comment:返回数据"` + Remark string `json:"remark" gorm:"size:255;comment:备注"` + LatencyTime string `json:"latencyTime" gorm:"size:128;comment:耗时"` + UserAgent string `json:"userAgent" gorm:"size:255;comment:ua"` + CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"` + UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"` + models.ControlBy +} + +func (*SysOperaLog) TableName() string { + return "sys_opera_log" +} + +func (e *SysOperaLog) Generate() models.ActiveRecord { + o := *e + return &o +} + +func (e *SysOperaLog) GetId() interface{} { + return e.Id +} + +// SaveOperaLog 从队列中获取操作日志 +func SaveOperaLog(message storage.Messager) (err error) { + //准备db + db := sdk.Runtime.GetDbByKey(message.GetPrefix()) + if db == nil { + err = errors.New("db not exist") + log.Errorf("host[%s]'s %s", message.GetPrefix(), err.Error()) + // Log writing to the database ignores error + return nil + } + var rb []byte + rb, err = json.Marshal(message.GetValues()) + if err != nil { + log.Errorf("json Marshal error, %s", err.Error()) + // Log writing to the database ignores error + return nil + } + var l SysOperaLog + err = json.Unmarshal(rb, &l) + if err != nil { + log.Errorf("json Unmarshal error, %s", err.Error()) + // Log writing to the database ignores error + return nil + } + // 超出100个字符返回值截断 + if len(l.JsonResult) > 100 { + l.JsonResult = l.JsonResult[:100] + } + err = db.Create(&l).Error + if err != nil { + log.Errorf("db create error, %s", err.Error()) + // Log writing to the database ignores error + return nil + } + return nil +} diff --git a/app/admin/models/sys_post.go b/app/admin/models/sys_post.go new file mode 100644 index 0000000..705318a --- /dev/null +++ b/app/admin/models/sys_post.go @@ -0,0 +1,30 @@ +package models + +import "go-admin/common/models" + +type SysPost struct { + PostId int `gorm:"primaryKey;autoIncrement" json:"postId"` //岗位编号 + PostName string `gorm:"size:128;" json:"postName"` //岗位名称 + PostCode string `gorm:"size:128;" json:"postCode"` //岗位代码 + Sort int `gorm:"size:4;" json:"sort"` //岗位排序 + Status int `gorm:"size:4;" json:"status"` //状态 + Remark string `gorm:"size:255;" json:"remark"` //描述 + models.ControlBy + models.ModelTime + + DataScope string `gorm:"-" json:"dataScope"` + Params string `gorm:"-" json:"params"` +} + +func (*SysPost) TableName() string { + return "sys_post" +} + +func (e *SysPost) Generate() models.ActiveRecord { + o := *e + return &o +} + +func (e *SysPost) GetId() interface{} { + return e.PostId +} diff --git a/app/admin/models/sys_role.go b/app/admin/models/sys_role.go new file mode 100644 index 0000000..d23fb17 --- /dev/null +++ b/app/admin/models/sys_role.go @@ -0,0 +1,35 @@ +package models + +import "go-admin/common/models" + +type SysRole struct { + RoleId int `json:"roleId" gorm:"primaryKey;autoIncrement"` // 角色编码 + RoleName string `json:"roleName" gorm:"size:128;"` // 角色名称 + Status string `json:"status" gorm:"size:4;"` // 状态 1禁用 2正常 + RoleKey string `json:"roleKey" gorm:"size:128;"` //角色代码 + RoleSort int `json:"roleSort" gorm:""` //角色排序 + Flag string `json:"flag" gorm:"size:128;"` // + Remark string `json:"remark" gorm:"size:255;"` //备注 + Admin bool `json:"admin" gorm:"size:4;"` + DataScope string `json:"dataScope" gorm:"size:128;"` + Params string `json:"params" gorm:"-"` + MenuIds []int `json:"menuIds" gorm:"-"` + DeptIds []int `json:"deptIds" gorm:"-"` + SysDept []SysDept `json:"sysDept" gorm:"many2many:sys_role_dept;foreignKey:RoleId;joinForeignKey:role_id;references:DeptId;joinReferences:dept_id;"` + SysMenu *[]SysMenu `json:"sysMenu" gorm:"many2many:sys_role_menu;foreignKey:RoleId;joinForeignKey:role_id;references:MenuId;joinReferences:menu_id;"` + models.ControlBy + models.ModelTime +} + +func (*SysRole) TableName() string { + return "sys_role" +} + +func (e *SysRole) Generate() models.ActiveRecord { + o := *e + return &o +} + +func (e *SysRole) GetId() interface{} { + return e.RoleId +} diff --git a/app/admin/models/sys_user.go b/app/admin/models/sys_user.go new file mode 100644 index 0000000..eab2cad --- /dev/null +++ b/app/admin/models/sys_user.go @@ -0,0 +1,77 @@ +package models + +import ( + "go-admin/common/models" + "golang.org/x/crypto/bcrypt" + "gorm.io/gorm" +) + +type SysUser struct { + UserId int `gorm:"primaryKey;autoIncrement;comment:编码" json:"userId"` + Username string `json:"username" gorm:"size:64;comment:用户名"` + Password string `json:"-" gorm:"size:128;comment:密码"` + NickName string `json:"nickName" gorm:"size:128;comment:昵称"` + Phone string `json:"phone" gorm:"size:11;comment:手机号"` + RoleId int `json:"roleId" gorm:"size:20;comment:角色ID"` + Salt string `json:"-" gorm:"size:255;comment:加盐"` + Avatar string `json:"avatar" gorm:"size:255;comment:头像"` + Sex string `json:"sex" gorm:"size:255;comment:性别"` + Email string `json:"email" gorm:"size:128;comment:邮箱"` + DeptId int `json:"deptId" gorm:"size:20;comment:部门"` + PostId int `json:"postId" gorm:"size:20;comment:岗位"` + Remark string `json:"remark" gorm:"size:255;comment:备注"` + Status string `json:"status" gorm:"size:4;comment:状态"` + DeptIds []int `json:"deptIds" gorm:"-"` + PostIds []int `json:"postIds" gorm:"-"` + RoleIds []int `json:"roleIds" gorm:"-"` + Dept *SysDept `json:"dept"` + models.ControlBy + models.ModelTime +} + +func (*SysUser) TableName() string { + return "sys_user" +} + +func (e *SysUser) Generate() models.ActiveRecord { + o := *e + return &o +} + +func (e *SysUser) GetId() interface{} { + return e.UserId +} + +// Encrypt 加密 +func (e *SysUser) Encrypt() (err error) { + if e.Password == "" { + return + } + + var hash []byte + if hash, err = bcrypt.GenerateFromPassword([]byte(e.Password), bcrypt.DefaultCost); err != nil { + return + } else { + e.Password = string(hash) + return + } +} + +func (e *SysUser) BeforeCreate(_ *gorm.DB) error { + return e.Encrypt() +} + +func (e *SysUser) BeforeUpdate(_ *gorm.DB) error { + var err error + if e.Password != "" { + err = e.Encrypt() + } + return err +} + +func (e *SysUser) AfterFind(_ *gorm.DB) error { + e.DeptIds = []int{e.DeptId} + e.PostIds = []int{e.PostId} + e.RoleIds = []int{e.RoleId} + return nil +} diff --git a/app/admin/router/init_router.go b/app/admin/router/init_router.go new file mode 100644 index 0000000..61fb978 --- /dev/null +++ b/app/admin/router/init_router.go @@ -0,0 +1,40 @@ +package router + +import ( + "os" + + "github.com/gin-gonic/gin" + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk" + common "go-admin/common/middleware" +) + +// InitRouter 路由初始化,不要怀疑,这里用到了 +func InitRouter() { + var r *gin.Engine + h := sdk.Runtime.GetEngine() + if h == nil { + log.Fatal("not found engine...") + os.Exit(-1) + } + switch h.(type) { + case *gin.Engine: + r = h.(*gin.Engine) + default: + log.Fatal("not support other engine") + os.Exit(-1) + } + + // the jwt middleware + authMiddleware, err := common.AuthInit() + if err != nil { + log.Fatalf("JWT Init Error, %s", err.Error()) + } + + // 注册系统路由 + InitSysRouter(r, authMiddleware) + + // 注册业务路由 + // TODO: 这里可存放业务路由,里边并无实际路由只有演示代码 + InitExamplesRouter(r, authMiddleware) +} diff --git a/app/admin/router/router.go b/app/admin/router/router.go new file mode 100644 index 0000000..d2c4581 --- /dev/null +++ b/app/admin/router/router.go @@ -0,0 +1,41 @@ +package router + +import ( + "github.com/gin-gonic/gin" + _ "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" +) + +var ( + routerNoCheckRole = make([]func(*gin.RouterGroup), 0) + routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0) +) + +func InitExamplesRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine { + + // 无需认证的路由 + examplesNoCheckRoleRouter(r) + // 需要认证的路由 + examplesCheckRoleRouter(r, authMiddleware) + + return r +} + +// 无需认证的路由示例 +func examplesNoCheckRoleRouter(r *gin.Engine) { + // 可根据业务需求来设置接口版本 + v1 := r.Group("/api/v1") + for _, f := range routerNoCheckRole { + f(v1) + } +} + +// 需要认证的路由示例 +func examplesCheckRoleRouter(r *gin.Engine, authMiddleware *jwtauth.GinJWTMiddleware) { + // 可根据业务需求来设置接口版本 + v1 := r.Group("/api/v1") + for _, f := range routerCheckRole { + f(v1, authMiddleware) + } +} diff --git a/app/admin/router/sys_api.go b/app/admin/router/sys_api.go new file mode 100644 index 0000000..8272df3 --- /dev/null +++ b/app/admin/router/sys_api.go @@ -0,0 +1,24 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + + "go-admin/app/admin/apis" + "go-admin/common/middleware" +) + +func init() { + routerCheckRole = append(routerCheckRole, registerSysApiRouter) +} + +// registerSysApiRouter +func registerSysApiRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.SysApi{} + r := v1.Group("/sys-api").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + r.GET("", api.GetPage) + r.GET("/:id", api.Get) + r.PUT("/:id", api.Update) + } +} diff --git a/app/admin/router/sys_config.go b/app/admin/router/sys_config.go new file mode 100644 index 0000000..2dabd08 --- /dev/null +++ b/app/admin/router/sys_config.go @@ -0,0 +1,43 @@ +package router + +import ( + "go-admin/app/admin/apis" + "go-admin/common/middleware" + + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" +) + +func init() { + routerCheckRole = append(routerCheckRole, registerSysConfigRouter) +} + +// 需认证的路由代码 +func registerSysConfigRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.SysConfig{} + r := v1.Group("/config").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + r.GET("", api.GetPage) + r.GET("/:id", api.Get) + r.POST("", api.Insert) + r.PUT("/:id", api.Update) + r.DELETE("", api.Delete) + } + + r1 := v1.Group("/configKey").Use(authMiddleware.MiddlewareFunc()) + { + r1.GET("/:configKey", api.GetSysConfigByKEYForService) + } + + r2 := v1.Group("/app-config") + { + r2.GET("", api.Get2SysApp) + } + + r3 := v1.Group("/set-config").Use(authMiddleware.MiddlewareFunc()) + { + r3.PUT("", api.Update2Set) + r3.GET("", api.Get2Set) + } + +} diff --git a/app/admin/router/sys_dept.go b/app/admin/router/sys_dept.go new file mode 100644 index 0000000..f939374 --- /dev/null +++ b/app/admin/router/sys_dept.go @@ -0,0 +1,32 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + "go-admin/app/admin/apis" + "go-admin/common/middleware" +) + +func init() { + routerCheckRole = append(routerCheckRole, registerSysDeptRouter) +} + +// 需认证的路由代码 +func registerSysDeptRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.SysDept{} + + r := v1.Group("/dept").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + r.GET("", api.GetPage) + r.GET("/:id", api.Get) + r.POST("", api.Insert) + r.PUT("/:id", api.Update) + r.DELETE("", api.Delete) + } + + r1 := v1.Group("").Use(authMiddleware.MiddlewareFunc()) + { + r1.GET("/deptTree", api.Get2Tree) + } + +} \ No newline at end of file diff --git a/app/admin/router/sys_dict.go b/app/admin/router/sys_dict.go new file mode 100644 index 0000000..ae9e0c4 --- /dev/null +++ b/app/admin/router/sys_dict.go @@ -0,0 +1,37 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + "go-admin/app/admin/apis" + "go-admin/common/middleware" +) + +func init() { + routerCheckRole = append(routerCheckRole, registerDictRouter) +} + +func registerDictRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + dictApi := apis.SysDictType{} + dataApi := apis.SysDictData{} + dicts := v1.Group("/dict").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + + dicts.GET("/data", dataApi.GetPage) + dicts.GET("/data/:dictCode", dataApi.Get) + dicts.POST("/data", dataApi.Insert) + dicts.PUT("/data/:dictCode", dataApi.Update) + dicts.DELETE("/data", dataApi.Delete) + + dicts.GET("/type-option-select", dictApi.GetAll) + dicts.GET("/type", dictApi.GetPage) + dicts.GET("/type/:id", dictApi.Get) + dicts.POST("/type", dictApi.Insert) + dicts.PUT("/type/:id", dictApi.Update) + dicts.DELETE("/type", dictApi.Delete) + } + opSelect := v1.Group("/dict-data").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + opSelect.GET("/option-select", dataApi.GetAll) + } +} diff --git a/app/admin/router/sys_login_log.go b/app/admin/router/sys_login_log.go new file mode 100644 index 0000000..61b4e83 --- /dev/null +++ b/app/admin/router/sys_login_log.go @@ -0,0 +1,24 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + "go-admin/app/admin/apis" + "go-admin/common/middleware" +) + +func init() { + routerCheckRole = append(routerCheckRole, registerSysLoginLogRouter) +} + +// 需认证的路由代码 +func registerSysLoginLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.SysLoginLog{} + + r := v1.Group("/sys-login-log").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + r.GET("", api.GetPage) + r.GET("/:id", api.Get) + r.DELETE("", api.Delete) + } +} \ No newline at end of file diff --git a/app/admin/router/sys_menu.go b/app/admin/router/sys_menu.go new file mode 100644 index 0000000..b5cad5a --- /dev/null +++ b/app/admin/router/sys_menu.go @@ -0,0 +1,33 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + "go-admin/app/admin/apis" + "go-admin/common/middleware" +) + +func init() { + routerCheckRole = append(routerCheckRole, registerSysMenuRouter) +} + +// 需认证的路由代码 +func registerSysMenuRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.SysMenu{} + + r := v1.Group("/menu").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + r.GET("", api.GetPage) + r.GET("/:id", api.Get) + r.POST("", api.Insert) + r.PUT("/:id", api.Update) + r.DELETE("", api.Delete) + } + + r1 := v1.Group("").Use(authMiddleware.MiddlewareFunc()) + { + r1.GET("/menurole", api.GetMenuRole) + //r1.GET("/menuids", api.GetMenuIDS) + } + +} \ No newline at end of file diff --git a/app/admin/router/sys_opera_log.go b/app/admin/router/sys_opera_log.go new file mode 100644 index 0000000..d24d54f --- /dev/null +++ b/app/admin/router/sys_opera_log.go @@ -0,0 +1,23 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + "go-admin/app/admin/apis" + "go-admin/common/middleware" +) + +func init() { + routerCheckRole = append(routerCheckRole, registerSysOperaLogRouter) +} + +// 需认证的路由代码 +func registerSysOperaLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.SysOperaLog{} + r := v1.Group("/sys-opera-log").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + r.GET("", api.GetPage) + r.GET("/:id", api.Get) + r.DELETE("", api.Delete) + } +} \ No newline at end of file diff --git a/app/admin/router/sys_post.go b/app/admin/router/sys_post.go new file mode 100644 index 0000000..e299a5d --- /dev/null +++ b/app/admin/router/sys_post.go @@ -0,0 +1,25 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + "go-admin/app/admin/apis" + "go-admin/common/middleware" +) + +func init() { + routerCheckRole = append(routerCheckRole, registerSyPostRouter) +} + +// 需认证的路由代码 +func registerSyPostRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.SysPost{} + r := v1.Group("/post").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + r.GET("", api.GetPage) + r.GET("/:id", api.Get) + r.POST("", api.Insert) + r.PUT("/:id", api.Update) + r.DELETE("", api.Delete) + } +} \ No newline at end of file diff --git a/app/admin/router/sys_role.go b/app/admin/router/sys_role.go new file mode 100644 index 0000000..5bfdd2a --- /dev/null +++ b/app/admin/router/sys_role.go @@ -0,0 +1,31 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + + "go-admin/app/admin/apis" + "go-admin/common/middleware" +) + +func init() { + routerCheckRole = append(routerCheckRole, registerSysRoleRouter) +} + +// 需认证的路由代码 +func registerSysRoleRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.SysRole{} + r := v1.Group("/role").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + r.GET("", api.GetPage) + r.GET("/:id", api.Get) + r.POST("", api.Insert) + r.PUT("/:id", api.Update) + r.DELETE("", api.Delete) + } + r1 := v1.Group("").Use(authMiddleware.MiddlewareFunc()) + { + r1.PUT("/role-status", api.Update2Status) + r1.PUT("/roledatascope", api.Update2DataScope) + } +} diff --git a/app/admin/router/sys_router.go b/app/admin/router/sys_router.go new file mode 100644 index 0000000..b713e4b --- /dev/null +++ b/app/admin/router/sys_router.go @@ -0,0 +1,88 @@ +package router + +import ( + "go-admin/app/admin/apis" + "mime" + + "github.com/go-admin-team/go-admin-core/sdk/config" + + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + "github.com/go-admin-team/go-admin-core/sdk/pkg/ws" + ginSwagger "github.com/swaggo/gin-swagger" + + swaggerfiles "github.com/swaggo/files" + + "go-admin/common/middleware" + "go-admin/common/middleware/handler" + _ "go-admin/docs/admin" +) + +func InitSysRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.RouterGroup { + g := r.Group("") + sysBaseRouter(g) + // 静态文件 + sysStaticFileRouter(g) + // swagger;注意:生产环境可以注释掉 + if config.ApplicationConfig.Mode != "prod" { + sysSwaggerRouter(g) + } + // 需要认证 + sysCheckRoleRouterInit(g, authMiddleware) + return g +} + +func sysBaseRouter(r *gin.RouterGroup) { + + go ws.WebsocketManager.Start() + go ws.WebsocketManager.SendService() + go ws.WebsocketManager.SendAllService() + + if config.ApplicationConfig.Mode != "prod" { + r.GET("/", apis.GoAdmin) + } + r.GET("/info", handler.Ping) +} + +func sysStaticFileRouter(r *gin.RouterGroup) { + err := mime.AddExtensionType(".js", "application/javascript") + if err != nil { + return + } + r.Static("/static", "./static") + if config.ApplicationConfig.Mode != "prod" { + r.Static("/form-generator", "./static/form-generator") + } +} + +func sysSwaggerRouter(r *gin.RouterGroup) { + r.GET("/swagger/admin/*any", ginSwagger.WrapHandler(swaggerfiles.NewHandler(), ginSwagger.InstanceName("admin"))) +} + +func sysCheckRoleRouterInit(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + wss := r.Group("").Use(authMiddleware.MiddlewareFunc()) + { + wss.GET("/ws/:id/:channel", ws.WebsocketManager.WsClient) + wss.GET("/wslogout/:id/:channel", ws.WebsocketManager.UnWsClient) + } + + v1 := r.Group("/api/v1") + { + v1.POST("/login", authMiddleware.LoginHandler) + // Refresh time can be longer than token timeout + v1.GET("/refresh_token", authMiddleware.RefreshHandler) + } + registerBaseRouter(v1, authMiddleware) +} + +func registerBaseRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.SysMenu{} + api2 := apis.SysDept{} + v1auth := v1.Group("").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + v1auth.GET("/roleMenuTreeselect/:roleId", api.GetMenuTreeSelect) + //v1.GET("/menuTreeselect", api.GetMenuTreeSelect) + v1auth.GET("/roleDeptTreeselect/:roleId", api2.GetDeptTreeRoleSelect) + v1auth.POST("/logout", handler.LogOut) + } +} diff --git a/app/admin/router/sys_user.go b/app/admin/router/sys_user.go new file mode 100644 index 0000000..4a545a6 --- /dev/null +++ b/app/admin/router/sys_user.go @@ -0,0 +1,39 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + "go-admin/app/admin/apis" + "go-admin/common/actions" + "go-admin/common/middleware" +) + +func init() { + routerCheckRole = append(routerCheckRole, registerSysUserRouter) +} + +// 需认证的路由代码 +func registerSysUserRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.SysUser{} + r := v1.Group("/sys-user").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()).Use(actions.PermissionAction()) + { + r.GET("", api.GetPage) + r.GET("/:id", api.Get) + r.POST("", api.Insert) + r.PUT("", api.Update) + r.DELETE("", api.Delete) + } + + user := v1.Group("/user").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()).Use(actions.PermissionAction()) + { + user.GET("/profile", api.GetProfile) + user.POST("/avatar", api.InsetAvatar) + user.PUT("/pwd/set", api.UpdatePwd) + user.PUT("/pwd/reset", api.ResetPwd) + user.PUT("/status", api.UpdateStatus) + } + v1auth := v1.Group("").Use(authMiddleware.MiddlewareFunc()) + { + v1auth.GET("/getinfo", api.GetInfo) + } +} \ No newline at end of file diff --git a/app/admin/service/dto/sys_api.go b/app/admin/service/dto/sys_api.go new file mode 100644 index 0000000..d26034e --- /dev/null +++ b/app/admin/service/dto/sys_api.go @@ -0,0 +1,95 @@ +package dto + +import ( + "go-admin/app/admin/models" + "go-admin/common/dto" + common "go-admin/common/models" +) + +// SysApiGetPageReq 功能列表请求参数 +type SysApiGetPageReq struct { + dto.Pagination `search:"-"` + Title string `form:"title" search:"type:contains;column:title;table:sys_api" comment:"标题"` + Path string `form:"path" search:"type:contains;column:path;table:sys_api" comment:"地址"` + Action string `form:"action" search:"type:exact;column:action;table:sys_api" comment:"请求方式"` + ParentId string `form:"parentId" search:"type:exact;column:parent_id;table:sys_api" comment:"按钮id"` + Type string `form:"type" search:"-" comment:"类型"` + SysApiOrder +} + +type SysApiOrder struct { + TitleOrder string `search:"type:order;column:title;table:sys_api" form:"titleOrder"` + PathOrder string `search:"type:order;column:path;table:sys_api" form:"pathOrder"` + CreatedAtOrder string `search:"type:order;column:created_at;table:sys_api" form:"createdAtOrder"` +} + +func (m *SysApiGetPageReq) GetNeedSearch() interface{} { + return *m +} + +// SysApiInsertReq 功能创建请求参数 +type SysApiInsertReq struct { + Id int `json:"-" comment:"编码"` // 编码 + Handle string `json:"handle" comment:"handle"` + Title string `json:"title" comment:"标题"` + Path string `json:"path" comment:"地址"` + Type string `json:"type" comment:""` + Action string `json:"action" comment:"类型"` + common.ControlBy +} + +func (s *SysApiInsertReq) Generate(model *models.SysApi) { + model.Handle = s.Handle + model.Title = s.Title + model.Path = s.Path + model.Type = s.Type + model.Action = s.Action +} + +func (s *SysApiInsertReq) GetId() interface{} { + return s.Id +} + +// SysApiUpdateReq 功能更新请求参数 +type SysApiUpdateReq struct { + Id int `uri:"id" comment:"编码"` // 编码 + Handle string `json:"handle" comment:"handle"` + Title string `json:"title" comment:"标题"` + Path string `json:"path" comment:"地址"` + Type string `json:"type" comment:""` + Action string `json:"action" comment:"类型"` + common.ControlBy +} + +func (s *SysApiUpdateReq) Generate(model *models.SysApi) { + if s.Id != 0 { + model.Id = s.Id + } + model.Handle = s.Handle + model.Title = s.Title + model.Path = s.Path + model.Type = s.Type + model.Action = s.Action +} + +func (s *SysApiUpdateReq) GetId() interface{} { + return s.Id +} + +// SysApiGetReq 功能获取请求参数 +type SysApiGetReq struct { + Id int `uri:"id"` +} + +func (s *SysApiGetReq) GetId() interface{} { + return s.Id +} + +// SysApiDeleteReq 功能删除请求参数 +type SysApiDeleteReq struct { + Ids []int `json:"ids"` +} + +func (s *SysApiDeleteReq) GetId() interface{} { + return s.Ids +} diff --git a/app/admin/service/dto/sys_config.go b/app/admin/service/dto/sys_config.go new file mode 100644 index 0000000..06f7467 --- /dev/null +++ b/app/admin/service/dto/sys_config.go @@ -0,0 +1,112 @@ +package dto + +import ( + "go-admin/app/admin/models" + "go-admin/common/dto" + common "go-admin/common/models" +) + +// SysConfigGetPageReq 列表或者搜索使用结构体 +type SysConfigGetPageReq struct { + dto.Pagination `search:"-"` + ConfigName string `form:"configName" search:"type:contains;column:config_name;table:sys_config"` + ConfigKey string `form:"configKey" search:"type:contains;column:config_key;table:sys_config"` + ConfigType string `form:"configType" search:"type:exact;column:config_type;table:sys_config"` + IsFrontend string `form:"isFrontend" search:"type:exact;column:is_frontend;table:sys_config"` + SysConfigOrder +} + +type SysConfigOrder struct { + IdOrder string `search:"type:order;column:id;table:sys_config" form:"idOrder"` + ConfigNameOrder string `search:"type:order;column:config_name;table:sys_config" form:"configNameOrder"` + ConfigKeyOrder string `search:"type:order;column:config_key;table:sys_config" form:"configKeyOrder"` + ConfigTypeOrder string `search:"type:order;column:config_type;table:sys_config" form:"configTypeOrder"` + CreatedAtOrder string `search:"type:order;column:created_at;table:sys_config" form:"createdAtOrder"` +} + +func (m *SysConfigGetPageReq) GetNeedSearch() interface{} { + return *m +} + +type SysConfigGetToSysAppReq struct { + IsFrontend string `form:"isFrontend" search:"type:exact;column:is_frontend;table:sys_config"` +} + +func (m *SysConfigGetToSysAppReq) GetNeedSearch() interface{} { + return *m +} + +// SysConfigControl 增、改使用的结构体 +type SysConfigControl struct { + Id int `uri:"Id" comment:"编码"` // 编码 + ConfigName string `json:"configName" comment:""` + ConfigKey string `uri:"configKey" json:"configKey" comment:""` + ConfigValue string `json:"configValue" comment:""` + ConfigType string `json:"configType" comment:""` + IsFrontend string `json:"isFrontend"` + Remark string `json:"remark" comment:""` + common.ControlBy +} + +// Generate 结构体数据转化 从 SysConfigControl 至 system.SysConfig 对应的模型 +func (s *SysConfigControl) Generate(model *models.SysConfig) { + if s.Id == 0 { + model.Model = common.Model{Id: s.Id} + } + model.ConfigName = s.ConfigName + model.ConfigKey = s.ConfigKey + model.ConfigValue = s.ConfigValue + model.ConfigType = s.ConfigType + model.IsFrontend = s.IsFrontend + model.Remark = s.Remark + +} + +// GetId 获取数据对应的ID +func (s *SysConfigControl) GetId() interface{} { + return s.Id +} + +// GetSetSysConfigReq 增、改使用的结构体 +type GetSetSysConfigReq struct { + ConfigKey string `json:"configKey" comment:""` + ConfigValue string `json:"configValue" comment:""` +} + +// Generate 结构体数据转化 从 SysConfigControl 至 system.SysConfig 对应的模型 +func (s *GetSetSysConfigReq) Generate(model *models.SysConfig) { + model.ConfigValue = s.ConfigValue +} + +type UpdateSetSysConfigReq map[string]string + +// SysConfigByKeyReq 根据Key获取配置 +type SysConfigByKeyReq struct { + ConfigKey string `uri:"configKey" search:"type:contains;column:config_key;table:sys_config"` +} + +func (m *SysConfigByKeyReq) GetNeedSearch() interface{} { + return *m +} + +type GetSysConfigByKEYForServiceResp struct { + ConfigKey string `json:"configKey" comment:""` + ConfigValue string `json:"configValue" comment:""` +} + +type SysConfigGetReq struct { + Id int `uri:"id"` +} + +func (s *SysConfigGetReq) GetId() interface{} { + return s.Id +} + +type SysConfigDeleteReq struct { + Ids []int `json:"ids"` + common.ControlBy +} + +func (s *SysConfigDeleteReq) GetId() interface{} { + return s.Ids +} diff --git a/app/admin/service/dto/sys_dept.go b/app/admin/service/dto/sys_dept.go new file mode 100644 index 0000000..345a550 --- /dev/null +++ b/app/admin/service/dto/sys_dept.go @@ -0,0 +1,110 @@ +package dto + +import ( + "go-admin/app/admin/models" + common "go-admin/common/models" +) + +// SysDeptGetPageReq 列表或者搜索使用结构体 +type SysDeptGetPageReq struct { + DeptId int `form:"deptId" search:"type:exact;column:dept_id;table:sys_dept" comment:"id"` //id + ParentId int `form:"parentId" search:"type:exact;column:parent_id;table:sys_dept" comment:"上级部门"` //上级部门 + DeptPath string `form:"deptPath" search:"type:exact;column:dept_path;table:sys_dept" comment:""` //路径 + DeptName string `form:"deptName" search:"type:exact;column:dept_name;table:sys_dept" comment:"部门名称"` //部门名称 + Sort int `form:"sort" search:"type:exact;column:sort;table:sys_dept" comment:"排序"` //排序 + Leader string `form:"leader" search:"type:exact;column:leader;table:sys_dept" comment:"负责人"` //负责人 + Phone string `form:"phone" search:"type:exact;column:phone;table:sys_dept" comment:"手机"` //手机 + Email string `form:"email" search:"type:exact;column:email;table:sys_dept" comment:"邮箱"` //邮箱 + Status string `form:"status" search:"type:exact;column:status;table:sys_dept" comment:"状态"` //状态 +} + +func (m *SysDeptGetPageReq) GetNeedSearch() interface{} { + return *m +} + +type SysDeptInsertReq struct { + DeptId int `uri:"id" comment:"编码"` // 编码 + ParentId int `json:"parentId" comment:"上级部门" vd:"?"` //上级部门 + DeptPath string `json:"deptPath" comment:""` //路径 + DeptName string `json:"deptName" comment:"部门名称" vd:"len($)>0"` //部门名称 + Sort int `json:"sort" comment:"排序" vd:"?"` //排序 + Leader string `json:"leader" comment:"负责人" vd:"@:len($)>0; msg:'leader不能为空'"` //负责人 + Phone string `json:"phone" comment:"手机" vd:"?"` //手机 + Email string `json:"email" comment:"邮箱" vd:"?"` //邮箱 + Status int `json:"status" comment:"状态" vd:"$>0"` //状态 + common.ControlBy +} + +func (s *SysDeptInsertReq) Generate(model *models.SysDept) { + if s.DeptId != 0 { + model.DeptId = s.DeptId + } + model.DeptName = s.DeptName + model.ParentId = s.ParentId + model.DeptPath = s.DeptPath + model.Sort = s.Sort + model.Leader = s.Leader + model.Phone = s.Phone + model.Email = s.Email + model.Status = s.Status +} + +// GetId 获取数据对应的ID +func (s *SysDeptInsertReq) GetId() interface{} { + return s.DeptId +} + +type SysDeptUpdateReq struct { + DeptId int `uri:"id" comment:"编码"` // 编码 + ParentId int `json:"parentId" comment:"上级部门" vd:"?"` //上级部门 + DeptPath string `json:"deptPath" comment:""` //路径 + DeptName string `json:"deptName" comment:"部门名称" vd:"len($)>0"` //部门名称 + Sort int `json:"sort" comment:"排序" vd:"?"` //排序 + Leader string `json:"leader" comment:"负责人" vd:"@:len($)>0; msg:'leader不能为空'"` //负责人 + Phone string `json:"phone" comment:"手机" vd:"?"` //手机 + Email string `json:"email" comment:"邮箱" vd:"?"` //邮箱 + Status int `json:"status" comment:"状态" vd:"$>0"` //状态 + common.ControlBy +} + +// Generate 结构体数据转化 从 SysDeptControl 至 SysDept 对应的模型 +func (s *SysDeptUpdateReq) Generate(model *models.SysDept) { + if s.DeptId != 0 { + model.DeptId = s.DeptId + } + model.DeptName = s.DeptName + model.ParentId = s.ParentId + model.DeptPath = s.DeptPath + model.Sort = s.Sort + model.Leader = s.Leader + model.Phone = s.Phone + model.Email = s.Email + model.Status = s.Status +} + +// GetId 获取数据对应的ID +func (s *SysDeptUpdateReq) GetId() interface{} { + return s.DeptId +} + +type SysDeptGetReq struct { + Id int `uri:"id"` +} + +func (s *SysDeptGetReq) GetId() interface{} { + return s.Id +} + +type SysDeptDeleteReq struct { + Ids []int `json:"ids"` +} + +func (s *SysDeptDeleteReq) GetId() interface{} { + return s.Ids +} + +type DeptLabel struct { + Id int `gorm:"-" json:"id"` + Label string `gorm:"-" json:"label"` + Children []DeptLabel `gorm:"-" json:"children"` +} diff --git a/app/admin/service/dto/sys_dict_data.go b/app/admin/service/dto/sys_dict_data.go new file mode 100644 index 0000000..842f418 --- /dev/null +++ b/app/admin/service/dto/sys_dict_data.go @@ -0,0 +1,108 @@ +package dto + +import ( + "go-admin/app/admin/models" + "go-admin/common/dto" + common "go-admin/common/models" +) + +type SysDictDataGetPageReq struct { + dto.Pagination `search:"-"` + Id int `form:"id" search:"type:exact;column:dict_code;table:sys_dict_data" comment:""` + DictLabel string `form:"dictLabel" search:"type:contains;column:dict_label;table:sys_dict_data" comment:""` + DictValue string `form:"dictValue" search:"type:contains;column:dict_value;table:sys_dict_data" comment:""` + DictType string `form:"dictType" search:"type:contains;column:dict_type;table:sys_dict_data" comment:""` + Status string `form:"status" search:"type:exact;column:status;table:sys_dict_data" comment:""` +} + +func (m *SysDictDataGetPageReq) GetNeedSearch() interface{} { + return *m +} + +type SysDictDataGetAllResp struct { + DictLabel string `json:"label"` + DictValue string `json:"value"` +} + +type SysDictDataInsertReq struct { + Id int `json:"-" comment:""` + DictSort int `json:"dictSort" comment:""` + DictLabel string `json:"dictLabel" comment:""` + DictValue string `json:"dictValue" comment:""` + DictType string `json:"dictType" comment:""` + CssClass string `json:"cssClass" comment:""` + ListClass string `json:"listClass" comment:""` + IsDefault string `json:"isDefault" comment:""` + Status int `json:"status" comment:""` + Default string `json:"default" comment:""` + Remark string `json:"remark" comment:""` + common.ControlBy +} + +func (s *SysDictDataInsertReq) Generate(model *models.SysDictData) { + model.DictCode = s.Id + model.DictSort = s.DictSort + model.DictLabel = s.DictLabel + model.DictValue = s.DictValue + model.DictType = s.DictType + model.CssClass = s.CssClass + model.ListClass = s.ListClass + model.IsDefault = s.IsDefault + model.Status = s.Status + model.Default = s.Default + model.Remark = s.Remark +} + +func (s *SysDictDataInsertReq) GetId() interface{} { + return s.Id +} + +type SysDictDataUpdateReq struct { + Id int `uri:"dictCode" comment:""` + DictSort int `json:"dictSort" comment:""` + DictLabel string `json:"dictLabel" comment:""` + DictValue string `json:"dictValue" comment:""` + DictType string `json:"dictType" comment:""` + CssClass string `json:"cssClass" comment:""` + ListClass string `json:"listClass" comment:""` + IsDefault string `json:"isDefault" comment:""` + Status int `json:"status" comment:""` + Default string `json:"default" comment:""` + Remark string `json:"remark" comment:""` + common.ControlBy +} + +func (s *SysDictDataUpdateReq) Generate(model *models.SysDictData) { + model.DictCode = s.Id + model.DictSort = s.DictSort + model.DictLabel = s.DictLabel + model.DictValue = s.DictValue + model.DictType = s.DictType + model.CssClass = s.CssClass + model.ListClass = s.ListClass + model.IsDefault = s.IsDefault + model.Status = s.Status + model.Default = s.Default + model.Remark = s.Remark +} + +func (s *SysDictDataUpdateReq) GetId() interface{} { + return s.Id +} + +type SysDictDataGetReq struct { + Id int `uri:"dictCode"` +} + +func (s *SysDictDataGetReq) GetId() interface{} { + return s.Id +} + +type SysDictDataDeleteReq struct { + Ids []int `json:"ids"` + common.ControlBy `json:"-"` +} + +func (s *SysDictDataDeleteReq) GetId() interface{} { + return s.Ids +} diff --git a/app/admin/service/dto/sys_dict_type.go b/app/admin/service/dto/sys_dict_type.go new file mode 100644 index 0000000..db66432 --- /dev/null +++ b/app/admin/service/dto/sys_dict_type.go @@ -0,0 +1,89 @@ +package dto + +import ( + "go-admin/app/admin/models" + + "go-admin/common/dto" + common "go-admin/common/models" +) + +type SysDictTypeGetPageReq struct { + dto.Pagination `search:"-"` + DictId []int `form:"dictId" search:"type:in;column:dict_id;table:sys_dict_type"` + DictName string `form:"dictName" search:"type:icontains;column:dict_name;table:sys_dict_type"` + DictType string `form:"dictType" search:"type:icontains;column:dict_type;table:sys_dict_type"` + Status int `form:"status" search:"type:exact;column:status;table:sys_dict_type"` +} + +type SysDictTypeOrder struct { + DictIdOrder string `search:"type:order;column:dict_id;table:sys_dict_type" form:"dictIdOrder"` +} + +func (m *SysDictTypeGetPageReq) GetNeedSearch() interface{} { + return *m +} + +type SysDictTypeInsertReq struct { + Id int `uri:"id"` + DictName string `json:"dictName"` + DictType string `json:"dictType"` + Status int `json:"status"` + Remark string `json:"remark"` + common.ControlBy +} + +func (s *SysDictTypeInsertReq) Generate(model *models.SysDictType) { + if s.Id != 0 { + model.ID = s.Id + } + model.DictName = s.DictName + model.DictType = s.DictType + model.Status = s.Status + model.Remark = s.Remark + +} + +func (s *SysDictTypeInsertReq) GetId() interface{} { + return s.Id +} + +type SysDictTypeUpdateReq struct { + Id int `uri:"id"` + DictName string `json:"dictName"` + DictType string `json:"dictType"` + Status int `json:"status"` + Remark string `json:"remark"` + common.ControlBy +} + +func (s *SysDictTypeUpdateReq) Generate(model *models.SysDictType) { + if s.Id != 0 { + model.ID = s.Id + } + model.DictName = s.DictName + model.DictType = s.DictType + model.Status = s.Status + model.Remark = s.Remark + +} + +func (s *SysDictTypeUpdateReq) GetId() interface{} { + return s.Id +} + +type SysDictTypeGetReq struct { + Id int `uri:"id"` +} + +func (s *SysDictTypeGetReq) GetId() interface{} { + return s.Id +} + +type SysDictTypeDeleteReq struct { + Ids []int `json:"ids"` + common.ControlBy +} + +func (s *SysDictTypeDeleteReq) GetId() interface{} { + return s.Ids +} diff --git a/app/admin/service/dto/sys_login_log.go b/app/admin/service/dto/sys_login_log.go new file mode 100644 index 0000000..42a6e45 --- /dev/null +++ b/app/admin/service/dto/sys_login_log.go @@ -0,0 +1,57 @@ +package dto + +import ( + "time" + + "go-admin/common/dto" +) + +type SysLoginLogGetPageReq struct { + dto.Pagination `search:"-"` + Username string `form:"username" search:"type:exact;column:username;table:sys_login_log" comment:"用户名"` + Status string `form:"status" search:"type:exact;column:status;table:sys_login_log" comment:"状态"` + Ipaddr string `form:"ipaddr" search:"type:exact;column:ipaddr;table:sys_login_log" comment:"ip地址"` + LoginLocation string `form:"loginLocation" search:"type:exact;column:login_location;table:sys_login_log" comment:"归属地"` + BeginTime string `form:"beginTime" search:"type:gte;column:ctime;table:sys_login_log" comment:"创建时间"` + EndTime string `form:"endTime" search:"type:lte;column:ctime;table:sys_login_log" comment:"创建时间"` + SysLoginLogOrder +} + +type SysLoginLogOrder struct { + CreatedAtOrder string `search:"type:order;column:created_at;table:sys_login_log" form:"createdAtOrder"` +} + +func (m *SysLoginLogGetPageReq) GetNeedSearch() interface{} { + return *m +} + +type SysLoginLogControl struct { + ID int `uri:"Id" comment:"主键"` // 主键 + Username string `json:"username" comment:"用户名"` + Status string `json:"status" comment:"状态"` + Ipaddr string `json:"ipaddr" comment:"ip地址"` + LoginLocation string `json:"loginLocation" comment:"归属地"` + Browser string `json:"browser" comment:"浏览器"` + Os string `json:"os" comment:"系统"` + Platform string `json:"platform" comment:"固件"` + LoginTime time.Time `json:"loginTime" comment:"登录时间"` + Remark string `json:"remark" comment:"备注"` + Msg string `json:"msg" comment:"信息"` +} + +type SysLoginLogGetReq struct { + Id int `uri:"id"` +} + +func (s *SysLoginLogGetReq) GetId() interface{} { + return s.Id +} + +// SysLoginLogDeleteReq 功能删除请求参数 +type SysLoginLogDeleteReq struct { + Ids []int `json:"ids"` +} + +func (s *SysLoginLogDeleteReq) GetId() interface{} { + return s.Ids +} \ No newline at end of file diff --git a/app/admin/service/dto/sys_menu.go b/app/admin/service/dto/sys_menu.go new file mode 100644 index 0000000..67f4674 --- /dev/null +++ b/app/admin/service/dto/sys_menu.go @@ -0,0 +1,159 @@ +package dto + +import ( + "go-admin/app/admin/models" + common "go-admin/common/models" + + "go-admin/common/dto" +) + +// SysMenuGetPageReq 列表或者搜索使用结构体 +type SysMenuGetPageReq struct { + dto.Pagination `search:"-"` + Title string `form:"title" search:"type:contains;column:title;table:sys_menu" comment:"菜单名称"` // 菜单名称 + Visible int `form:"visible" search:"type:exact;column:visible;table:sys_menu" comment:"显示状态"` // 显示状态 +} + +func (m *SysMenuGetPageReq) GetNeedSearch() interface{} { + return *m +} + +type SysMenuInsertReq struct { + MenuId int `uri:"id" comment:"编码"` // 编码 + MenuName string `form:"menuName" comment:"菜单name"` //菜单name + Title string `form:"title" comment:"显示名称"` //显示名称 + Icon string `form:"icon" comment:"图标"` //图标 + Path string `form:"path" comment:"路径"` //路径 + Paths string `form:"paths" comment:"id路径"` //id路径 + MenuType string `form:"menuType" comment:"菜单类型"` //菜单类型 + SysApi []models.SysApi `form:"sysApi"` + Apis []int `form:"apis"` + Action string `form:"action" comment:"请求方式"` //请求方式 + Permission string `form:"permission" comment:"权限编码"` //权限编码 + ParentId int `form:"parentId" comment:"上级菜单"` //上级菜单 + NoCache bool `form:"noCache" comment:"是否缓存"` //是否缓存 + Breadcrumb string `form:"breadcrumb" comment:"是否面包屑"` //是否面包屑 + Component string `form:"component" comment:"组件"` //组件 + Sort int `form:"sort" comment:"排序"` //排序 + Visible string `form:"visible" comment:"是否显示"` //是否显示 + IsFrame string `form:"isFrame" comment:"是否frame"` //是否frame + common.ControlBy +} + +func (s *SysMenuInsertReq) Generate(model *models.SysMenu) { + if s.MenuId != 0 { + model.MenuId = s.MenuId + } + model.MenuName = s.MenuName + model.Title = s.Title + model.Icon = s.Icon + model.Path = s.Path + model.Paths = s.Paths + model.MenuType = s.MenuType + model.Action = s.Action + model.SysApi = s.SysApi + model.Permission = s.Permission + model.ParentId = s.ParentId + model.NoCache = s.NoCache + model.Breadcrumb = s.Breadcrumb + model.Component = s.Component + model.Sort = s.Sort + model.Visible = s.Visible + model.IsFrame = s.IsFrame + if s.CreateBy != 0 { + model.CreateBy = s.CreateBy + } + if s.UpdateBy != 0 { + model.UpdateBy = s.UpdateBy + } +} + +func (s *SysMenuInsertReq) GetId() interface{} { + return s.MenuId +} + +type SysMenuUpdateReq struct { + MenuId int `uri:"id" comment:"编码"` // 编码 + MenuName string `form:"menuName" comment:"菜单name"` //菜单name + Title string `form:"title" comment:"显示名称"` //显示名称 + Icon string `form:"icon" comment:"图标"` //图标 + Path string `form:"path" comment:"路径"` //路径 + Paths string `form:"paths" comment:"id路径"` //id路径 + MenuType string `form:"menuType" comment:"菜单类型"` //菜单类型 + SysApi []models.SysApi `form:"sysApi"` + Apis []int `form:"apis"` + Action string `form:"action" comment:"请求方式"` //请求方式 + Permission string `form:"permission" comment:"权限编码"` //权限编码 + ParentId int `form:"parentId" comment:"上级菜单"` //上级菜单 + NoCache bool `form:"noCache" comment:"是否缓存"` //是否缓存 + Breadcrumb string `form:"breadcrumb" comment:"是否面包屑"` //是否面包屑 + Component string `form:"component" comment:"组件"` //组件 + Sort int `form:"sort" comment:"排序"` //排序 + Visible string `form:"visible" comment:"是否显示"` //是否显示 + IsFrame string `form:"isFrame" comment:"是否frame"` //是否frame + common.ControlBy +} + +func (s *SysMenuUpdateReq) Generate(model *models.SysMenu) { + if s.MenuId != 0 { + model.MenuId = s.MenuId + } + model.MenuName = s.MenuName + model.Title = s.Title + model.Icon = s.Icon + model.Path = s.Path + model.Paths = s.Paths + model.MenuType = s.MenuType + model.Action = s.Action + model.SysApi = s.SysApi + model.Permission = s.Permission + model.ParentId = s.ParentId + model.NoCache = s.NoCache + model.Breadcrumb = s.Breadcrumb + model.Component = s.Component + model.Sort = s.Sort + model.Visible = s.Visible + model.IsFrame = s.IsFrame + if s.CreateBy != 0 { + model.CreateBy = s.CreateBy + } + if s.UpdateBy != 0 { + model.UpdateBy = s.UpdateBy + } +} + +func (s *SysMenuUpdateReq) GetId() interface{} { + return s.MenuId +} + +type SysMenuGetReq struct { + Id int `uri:"id"` +} + +func (s *SysMenuGetReq) GetId() interface{} { + return s.Id +} + +type SysMenuDeleteReq struct { + Ids []int `json:"ids"` + common.ControlBy +} + +func (s *SysMenuDeleteReq) GetId() interface{} { + return s.Ids +} + +type MenuLabel struct { + Id int `json:"id,omitempty" gorm:"-"` + Label string `json:"label,omitempty" gorm:"-"` + Children []MenuLabel `json:"children,omitempty" gorm:"-"` +} + +type MenuRole struct { + models.SysMenu + IsSelect bool `json:"is_select" gorm:"-"` +} + +type SelectRole struct { + RoleId int `uri:"roleId"` +} diff --git a/app/admin/service/dto/sys_opera_log.go b/app/admin/service/dto/sys_opera_log.go new file mode 100644 index 0000000..5df36eb --- /dev/null +++ b/app/admin/service/dto/sys_opera_log.go @@ -0,0 +1,102 @@ +package dto + +import ( + "time" + + "go-admin/app/admin/models" + "go-admin/common/dto" + common "go-admin/common/models" +) + +const ( + OperaStatusEnabel = "1" // 状态-正常 + OperaStatusDisable = "2" // 状态-关闭 +) + +type SysOperaLogGetPageReq struct { + dto.Pagination `search:"-"` + Title string `form:"title" search:"type:contains;column:title;table:sys_opera_log" comment:"操作模块"` + Method string `form:"method" search:"type:contains;column:method;table:sys_opera_log" comment:"函数"` + RequestMethod string `form:"requestMethod" search:"type:contains;column:request_method;table:sys_opera_log" comment:"请求方式: GET POST PUT DELETE"` + OperUrl string `form:"operUrl" search:"type:contains;column:oper_url;table:sys_opera_log" comment:"访问地址"` + OperIp string `form:"operIp" search:"type:exact;column:oper_ip;table:sys_opera_log" comment:"客户端ip"` + Status int `form:"status" search:"type:exact;column:status;table:sys_opera_log" comment:"状态 1:正常 2:关闭"` + BeginTime string `form:"beginTime" search:"type:gte;column:created_at;table:sys_opera_log" comment:"创建时间"` + EndTime string `form:"endTime" search:"type:lte;column:created_at;table:sys_opera_log" comment:"更新时间"` + SysOperaLogOrder +} + +type SysOperaLogOrder struct { + CreatedAtOrder string `search:"type:order;column:created_at;table:sys_opera_log" form:"createdAtOrder"` +} + +func (m *SysOperaLogGetPageReq) GetNeedSearch() interface{} { + return *m +} + +type SysOperaLogControl struct { + ID int `uri:"Id" comment:"编码"` // 编码 + Title string `json:"title" comment:"操作模块"` + BusinessType string `json:"businessType" comment:"操作类型"` + BusinessTypes string `json:"businessTypes" comment:""` + Method string `json:"method" comment:"函数"` + RequestMethod string `json:"requestMethod" comment:"请求方式"` + OperatorType string `json:"operatorType" comment:"操作类型"` + OperName string `json:"operName" comment:"操作者"` + DeptName string `json:"deptName" comment:"部门名称"` + OperUrl string `json:"operUrl" comment:"访问地址"` + OperIp string `json:"operIp" comment:"客户端ip"` + OperLocation string `json:"operLocation" comment:"访问位置"` + OperParam string `json:"operParam" comment:"请求参数"` + Status string `json:"status" comment:"操作状态"` + OperTime time.Time `json:"operTime" comment:"操作时间"` + JsonResult string `json:"jsonResult" comment:"返回数据"` + Remark string `json:"remark" comment:"备注"` + LatencyTime string `json:"latencyTime" comment:"耗时"` + UserAgent string `json:"userAgent" comment:"ua"` +} + +func (s *SysOperaLogControl) Generate() (*models.SysOperaLog, error) { + return &models.SysOperaLog{ + Model: common.Model{Id: s.ID}, + Title: s.Title, + BusinessType: s.BusinessType, + BusinessTypes: s.BusinessTypes, + Method: s.Method, + RequestMethod: s.RequestMethod, + OperatorType: s.OperatorType, + OperName: s.OperName, + DeptName: s.DeptName, + OperUrl: s.OperUrl, + OperIp: s.OperIp, + OperLocation: s.OperLocation, + OperParam: s.OperParam, + Status: s.Status, + OperTime: s.OperTime, + JsonResult: s.JsonResult, + Remark: s.Remark, + LatencyTime: s.LatencyTime, + UserAgent: s.UserAgent, + }, nil +} + +func (s *SysOperaLogControl) GetId() interface{} { + return s.ID +} + +type SysOperaLogGetReq struct { + Id int `uri:"id"` +} + +func (s *SysOperaLogGetReq) GetId() interface{} { + return s.Id +} + +// SysOperaLogDeleteReq 功能删除请求参数 +type SysOperaLogDeleteReq struct { + Ids []int `json:"ids"` +} + +func (s *SysOperaLogDeleteReq) GetId() interface{} { + return s.Ids +} diff --git a/app/admin/service/dto/sys_post.go b/app/admin/service/dto/sys_post.go new file mode 100644 index 0000000..2b432a7 --- /dev/null +++ b/app/admin/service/dto/sys_post.go @@ -0,0 +1,111 @@ +package dto + +import ( + "go-admin/app/admin/models" + common "go-admin/common/models" + + "go-admin/common/dto" +) + +// SysPostPageReq 列表或者搜索使用结构体 +type SysPostPageReq struct { + dto.Pagination `search:"-"` + PostId int `form:"postId" search:"type:exact;column:post_id;table:sys_post" comment:"id"` // id + PostName string `form:"postName" search:"type:contains;column:post_name;table:sys_post" comment:"名称"` // 名称 + PostCode string `form:"postCode" search:"type:contains;column:post_code;table:sys_post" comment:"编码"` // 编码 + Sort int `form:"sort" search:"type:exact;column:sort;table:sys_post" comment:"排序"` // 排序 + Status int `form:"status" search:"type:exact;column:status;table:sys_post" comment:"状态"` // 状态 + Remark string `form:"remark" search:"type:exact;column:remark;table:sys_post" comment:"备注"` // 备注 +} + +func (m *SysPostPageReq) GetNeedSearch() interface{} { + return *m +} + +// SysPostInsertReq 增使用的结构体 +type SysPostInsertReq struct { + PostId int `uri:"id" comment:"id"` + PostName string `form:"postName" comment:"名称"` + PostCode string `form:"postCode" comment:"编码"` + Sort int `form:"sort" comment:"排序"` + Status int `form:"status" comment:"状态"` + Remark string `form:"remark" comment:"备注"` + common.ControlBy +} + +func (s *SysPostInsertReq) Generate(model *models.SysPost) { + model.PostName = s.PostName + model.PostCode = s.PostCode + model.Sort = s.Sort + model.Status = s.Status + model.Remark = s.Remark + if s.ControlBy.UpdateBy != 0 { + model.UpdateBy = s.UpdateBy + } + if s.ControlBy.CreateBy != 0 { + model.CreateBy = s.CreateBy + } +} + +// GetId 获取数据对应的ID +func (s *SysPostInsertReq) GetId() interface{} { + return s.PostId +} + +// SysPostUpdateReq 改使用的结构体 +type SysPostUpdateReq struct { + PostId int `uri:"id" comment:"id"` + PostName string `form:"postName" comment:"名称"` + PostCode string `form:"postCode" comment:"编码"` + Sort int `form:"sort" comment:"排序"` + Status int `form:"status" comment:"状态"` + Remark string `form:"remark" comment:"备注"` + common.ControlBy +} + +func (s *SysPostUpdateReq) Generate(model *models.SysPost) { + model.PostId = s.PostId + model.PostName = s.PostName + model.PostCode = s.PostCode + model.Sort = s.Sort + model.Status = s.Status + model.Remark = s.Remark + if s.ControlBy.UpdateBy != 0 { + model.UpdateBy = s.UpdateBy + } + if s.ControlBy.CreateBy != 0 { + model.CreateBy = s.CreateBy + } +} + +func (s *SysPostUpdateReq) GetId() interface{} { + return s.PostId +} + +// SysPostGetReq 获取单个的结构体 +type SysPostGetReq struct { + Id int `uri:"id"` +} + +func (s *SysPostGetReq) GetId() interface{} { + return s.Id +} + +// SysPostDeleteReq 删除的结构体 +type SysPostDeleteReq struct { + Ids []int `json:"ids"` + common.ControlBy +} + +func (s *SysPostDeleteReq) Generate(model *models.SysPost) { + if s.ControlBy.UpdateBy != 0 { + model.UpdateBy = s.UpdateBy + } + if s.ControlBy.CreateBy != 0 { + model.CreateBy = s.CreateBy + } +} + +func (s *SysPostDeleteReq) GetId() interface{} { + return s.Ids +} diff --git a/app/admin/service/dto/sys_role.go b/app/admin/service/dto/sys_role.go new file mode 100644 index 0000000..789b85e --- /dev/null +++ b/app/admin/service/dto/sys_role.go @@ -0,0 +1,164 @@ +package dto + +import ( + "go-admin/app/admin/models" + common "go-admin/common/models" + + "go-admin/common/dto" +) + +type SysRoleGetPageReq struct { + dto.Pagination `search:"-"` + + RoleId int `form:"roleId" search:"type:exact;column:role_id;table:sys_role" comment:"角色编码"` // 角色编码 + RoleName string `form:"roleName" search:"type:exact;column:role_name;table:sys_role" comment:"角色名称"` // 角色名称 + Status string `form:"status" search:"type:exact;column:status;table:sys_role" comment:"状态"` // 状态 + RoleKey string `form:"roleKey" search:"type:exact;column:role_key;table:sys_role" comment:"角色代码"` // 角色代码 + RoleSort int `form:"roleSort" search:"type:exact;column:role_sort;table:sys_role" comment:"角色排序"` // 角色排序 + Flag string `form:"flag" search:"type:exact;column:flag;table:sys_role" comment:"标记"` // 标记 + Remark string `form:"remark" search:"type:exact;column:remark;table:sys_role" comment:"备注"` // 备注 + Admin bool `form:"admin" search:"type:exact;column:admin;table:sys_role" comment:"是否管理员"` + DataScope string `form:"dataScope" search:"type:exact;column:data_scope;table:sys_role" comment:"是否管理员"` +} + +type SysRoleOrder struct { + RoleIdOrder string `search:"type:order;column:role_id;table:sys_role" form:"roleIdOrder"` + RoleNameOrder string `search:"type:order;column:role_name;table:sys_role" form:"roleNameOrder"` + RoleSortOrder string `search:"type:order;column:role_sort;table:sys_role" form:"usernameOrder"` + StatusOrder string `search:"type:order;column:status;table:sys_role" form:"statusOrder"` + CreatedAtOrder string `search:"type:order;column:created_at;table:sys_role" form:"createdAtOrder"` +} + +func (m *SysRoleGetPageReq) GetNeedSearch() interface{} { + return *m +} + +type SysRoleInsertReq struct { + RoleId int `uri:"id" comment:"角色编码"` // 角色编码 + RoleName string `form:"roleName" comment:"角色名称"` // 角色名称 + Status string `form:"status" comment:"状态"` // 状态 1禁用 2正常 + RoleKey string `form:"roleKey" comment:"角色代码"` // 角色代码 + RoleSort int `form:"roleSort" comment:"角色排序"` // 角色排序 + Flag string `form:"flag" comment:"标记"` // 标记 + Remark string `form:"remark" comment:"备注"` // 备注 + Admin bool `form:"admin" comment:"是否管理员"` + DataScope string `form:"dataScope"` + SysMenu []models.SysMenu `form:"sysMenu"` + MenuIds []int `form:"menuIds"` + SysDept []models.SysDept `form:"sysDept"` + DeptIds []int `form:"deptIds"` + common.ControlBy +} + +func (s *SysRoleInsertReq) Generate(model *models.SysRole) { + if s.RoleId != 0 { + model.RoleId = s.RoleId + } + model.RoleName = s.RoleName + model.Status = s.Status + model.RoleKey = s.RoleKey + model.RoleSort = s.RoleSort + model.Flag = s.Flag + model.Remark = s.Remark + model.Admin = s.Admin + model.DataScope = s.DataScope + model.SysMenu = &s.SysMenu + model.SysDept = s.SysDept +} + +func (s *SysRoleInsertReq) GetId() interface{} { + return s.RoleId +} + +type SysRoleUpdateReq struct { + RoleId int `uri:"id" comment:"角色编码"` // 角色编码 + RoleName string `form:"roleName" comment:"角色名称"` // 角色名称 + Status string `form:"status" comment:"状态"` // 状态 + RoleKey string `form:"roleKey" comment:"角色代码"` // 角色代码 + RoleSort int `form:"roleSort" comment:"角色排序"` // 角色排序 + Flag string `form:"flag" comment:"标记"` // 标记 + Remark string `form:"remark" comment:"备注"` // 备注 + Admin bool `form:"admin" comment:"是否管理员"` + DataScope string `form:"dataScope"` + SysMenu []models.SysMenu `form:"sysMenu"` + MenuIds []int `form:"menuIds"` + SysDept []models.SysDept `form:"sysDept"` + DeptIds []int `form:"deptIds"` + common.ControlBy +} + +func (s *SysRoleUpdateReq) Generate(model *models.SysRole) { + if s.RoleId != 0 { + model.RoleId = s.RoleId + } + model.RoleName = s.RoleName + model.Status = s.Status + model.RoleKey = s.RoleKey + model.RoleSort = s.RoleSort + model.Flag = s.Flag + model.Remark = s.Remark + model.Admin = s.Admin + model.DataScope = s.DataScope + model.SysMenu = &s.SysMenu + model.SysDept = s.SysDept +} + +func (s *SysRoleUpdateReq) GetId() interface{} { + return s.RoleId +} + +type UpdateStatusReq struct { + RoleId int `form:"roleId" comment:"角色编码"` // 角色编码 + Status string `form:"status" comment:"状态"` // 状态 + common.ControlBy +} + +func (s *UpdateStatusReq) Generate(model *models.SysRole) { + if s.RoleId != 0 { + model.RoleId = s.RoleId + } + model.Status = s.Status +} + +func (s *UpdateStatusReq) GetId() interface{} { + return s.RoleId +} + +type SysRoleByName struct { + RoleName string `form:"role"` // 角色编码 +} + +type SysRoleGetReq struct { + Id int `uri:"id"` +} + +func (s *SysRoleGetReq) GetId() interface{} { + return s.Id +} + +type SysRoleDeleteReq struct { + Ids []int `json:"ids"` +} + +func (s *SysRoleDeleteReq) GetId() interface{} { + return s.Ids +} + +// RoleDataScopeReq 角色数据权限修改 +type RoleDataScopeReq struct { + RoleId int `json:"roleId" binding:"required"` + DataScope string `json:"dataScope" binding:"required"` + DeptIds []int `json:"deptIds"` +} + +func (s *RoleDataScopeReq) Generate(model *models.SysRole) { + if s.RoleId != 0 { + model.RoleId = s.RoleId + } + model.DataScope = s.DataScope + model.DeptIds = s.DeptIds +} + +type DeptIdList struct { + DeptId int `json:"DeptId"` +} diff --git a/app/admin/service/dto/sys_user.go b/app/admin/service/dto/sys_user.go new file mode 100644 index 0000000..b1de094 --- /dev/null +++ b/app/admin/service/dto/sys_user.go @@ -0,0 +1,189 @@ +package dto + +import ( + "go-admin/app/admin/models" + + "go-admin/common/dto" + common "go-admin/common/models" +) + +type SysUserGetPageReq struct { + dto.Pagination `search:"-"` + UserId int `form:"userId" search:"type:exact;column:user_id;table:sys_user" comment:"用户ID"` + Username string `form:"username" search:"type:contains;column:username;table:sys_user" comment:"用户名"` + NickName string `form:"nickName" search:"type:contains;column:nick_name;table:sys_user" comment:"昵称"` + Phone string `form:"phone" search:"type:contains;column:phone;table:sys_user" comment:"手机号"` + RoleId string `form:"roleId" search:"type:exact;column:role_id;table:sys_user" comment:"角色ID"` + Sex string `form:"sex" search:"type:exact;column:sex;table:sys_user" comment:"性别"` + Email string `form:"email" search:"type:contains;column:email;table:sys_user" comment:"邮箱"` + PostId string `form:"postId" search:"type:exact;column:post_id;table:sys_user" comment:"岗位"` + Status string `form:"status" search:"type:exact;column:status;table:sys_user" comment:"状态"` + DeptJoin `search:"type:left;on:dept_id:dept_id;table:sys_user;join:sys_dept"` + SysUserOrder +} + +type SysUserOrder struct { + UserIdOrder string `search:"type:order;column:user_id;table:sys_user" form:"userIdOrder"` + UsernameOrder string `search:"type:order;column:username;table:sys_user" form:"usernameOrder"` + StatusOrder string `search:"type:order;column:status;table:sys_user" form:"statusOrder"` + CreatedAtOrder string `search:"type:order;column:created_at;table:sys_user" form:"createdAtOrder"` +} + +type DeptJoin struct { + DeptId string `search:"type:contains;column:dept_path;table:sys_dept" form:"deptId"` +} + +func (m *SysUserGetPageReq) GetNeedSearch() interface{} { + return *m +} + +type ResetSysUserPwdReq struct { + UserId int `json:"userId" comment:"用户ID" vd:"$>0"` // 用户ID + Password string `json:"password" comment:"密码" vd:"len($)>0"` + common.ControlBy +} + +func (s *ResetSysUserPwdReq) GetId() interface{} { + return s.UserId +} + +func (s *ResetSysUserPwdReq) Generate(model *models.SysUser) { + if s.UserId != 0 { + model.UserId = s.UserId + } + model.Password = s.Password +} + +type UpdateSysUserAvatarReq struct { + UserId int `json:"userId" comment:"用户ID" vd:"len($)>0"` // 用户ID + Avatar string `json:"avatar" comment:"头像" vd:"len($)>0"` + common.ControlBy +} + +func (s *UpdateSysUserAvatarReq) GetId() interface{} { + return s.UserId +} + +func (s *UpdateSysUserAvatarReq) Generate(model *models.SysUser) { + if s.UserId != 0 { + model.UserId = s.UserId + } + model.Avatar = s.Avatar +} + +type UpdateSysUserStatusReq struct { + UserId int `json:"userId" comment:"用户ID" vd:"$>0"` // 用户ID + Status string `json:"status" comment:"状态" vd:"len($)>0"` + common.ControlBy +} + +func (s *UpdateSysUserStatusReq) GetId() interface{} { + return s.UserId +} + +func (s *UpdateSysUserStatusReq) Generate(model *models.SysUser) { + if s.UserId != 0 { + model.UserId = s.UserId + } + model.Status = s.Status +} + +type SysUserInsertReq struct { + UserId int `json:"userId" comment:"用户ID"` // 用户ID + Username string `json:"username" comment:"用户名" vd:"len($)>0"` + Password string `json:"password" comment:"密码"` + NickName string `json:"nickName" comment:"昵称" vd:"len($)>0"` + Phone string `json:"phone" comment:"手机号" vd:"len($)>0"` + RoleId int `json:"roleId" comment:"角色ID"` + Avatar string `json:"avatar" comment:"头像"` + Sex string `json:"sex" comment:"性别"` + Email string `json:"email" comment:"邮箱" vd:"len($)>0,email"` + DeptId int `json:"deptId" comment:"部门" vd:"$>0"` + PostId int `json:"postId" comment:"岗位"` + Remark string `json:"remark" comment:"备注"` + Status string `json:"status" comment:"状态" vd:"len($)>0" default:"1"` + common.ControlBy +} + +func (s *SysUserInsertReq) Generate(model *models.SysUser) { + if s.UserId != 0 { + model.UserId = s.UserId + } + model.Username = s.Username + model.Password = s.Password + model.NickName = s.NickName + model.Phone = s.Phone + model.RoleId = s.RoleId + model.Avatar = s.Avatar + model.Sex = s.Sex + model.Email = s.Email + model.DeptId = s.DeptId + model.PostId = s.PostId + model.Remark = s.Remark + model.Status = s.Status + model.CreateBy = s.CreateBy +} + +func (s *SysUserInsertReq) GetId() interface{} { + return s.UserId +} + +type SysUserUpdateReq struct { + UserId int `json:"userId" comment:"用户ID"` // 用户ID + Username string `json:"username" comment:"用户名" vd:"len($)>0"` + NickName string `json:"nickName" comment:"昵称" vd:"len($)>0"` + Phone string `json:"phone" comment:"手机号" vd:"len($)>0"` + RoleId int `json:"roleId" comment:"角色ID"` + Avatar string `json:"avatar" comment:"头像"` + Sex string `json:"sex" comment:"性别"` + Email string `json:"email" comment:"邮箱" vd:"len($)>0,email"` + DeptId int `json:"deptId" comment:"部门" vd:"$>0"` + PostId int `json:"postId" comment:"岗位"` + Remark string `json:"remark" comment:"备注"` + Status string `json:"status" comment:"状态" default:"1"` + common.ControlBy +} + +func (s *SysUserUpdateReq) Generate(model *models.SysUser) { + if s.UserId != 0 { + model.UserId = s.UserId + } + model.Username = s.Username + model.NickName = s.NickName + model.Phone = s.Phone + model.RoleId = s.RoleId + model.Avatar = s.Avatar + model.Sex = s.Sex + model.Email = s.Email + model.DeptId = s.DeptId + model.PostId = s.PostId + model.Remark = s.Remark + model.Status = s.Status +} + +func (s *SysUserUpdateReq) GetId() interface{} { + return s.UserId +} + +type SysUserById struct { + dto.ObjectById + common.ControlBy +} + +func (s *SysUserById) GetId() interface{} { + if len(s.Ids) > 0 { + s.Ids = append(s.Ids, s.Id) + return s.Ids + } + return s.Id +} + +func (s *SysUserById) GenerateM() (common.ActiveRecord, error) { + return &models.SysUser{}, nil +} + +// PassWord 密码 +type PassWord struct { + NewPassword string `json:"newPassword" vd:"len($)>0"` + OldPassword string `json:"oldPassword" vd:"len($)>0"` +} diff --git a/app/admin/service/sys_api.go b/app/admin/service/sys_api.go new file mode 100644 index 0000000..cb4d895 --- /dev/null +++ b/app/admin/service/sys_api.go @@ -0,0 +1,123 @@ +package service + +import ( + "errors" + "fmt" + + "github.com/go-admin-team/go-admin-core/sdk/runtime" + "github.com/go-admin-team/go-admin-core/sdk/service" + "gorm.io/gorm" + + "go-admin/app/admin/models" + "go-admin/app/admin/service/dto" + "go-admin/common/actions" + cDto "go-admin/common/dto" + "go-admin/common/global" +) + +type SysApi struct { + service.Service +} + +// GetPage 获取SysApi列表 +func (e *SysApi) GetPage(c *dto.SysApiGetPageReq, p *actions.DataPermission, list *[]models.SysApi, count *int64) error { + var err error + var data models.SysApi + + orm := e.Orm.Debug().Model(&data). + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), + actions.Permission(data.TableName(), p), + ) + if c.Type != "" { + qType := c.Type + if qType == "暂无" { + qType = "" + } + if global.Driver == "postgres" { + orm = orm.Where("type = ?", qType) + } else { + orm = orm.Where("`type` = ?", qType) + } + + } + err = orm.Find(list).Limit(-1).Offset(-1). + Count(count).Error + if err != nil { + e.Log.Errorf("Service GetSysApiPage error:%s", err) + return err + } + return nil +} + +// Get 获取SysApi对象with id +func (e *SysApi) Get(d *dto.SysApiGetReq, p *actions.DataPermission, model *models.SysApi) *SysApi { + var data models.SysApi + err := e.Orm.Model(&data). + Scopes( + actions.Permission(data.TableName(), p), + ). + First(model, d.GetId()).Error + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = errors.New("查看对象不存在或无权查看") + e.Log.Errorf("Service GetSysApi error:%s", err) + _ = e.AddError(err) + return e + } + if err != nil { + e.Log.Errorf("db error:%s", err) + _ = e.AddError(err) + return e + } + return e +} + +// Update 修改SysApi对象 +func (e *SysApi) Update(c *dto.SysApiUpdateReq, p *actions.DataPermission) error { + var model = models.SysApi{} + db := e.Orm.Debug().First(&model, c.GetId()) + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + } + c.Generate(&model) + db = e.Orm.Save(&model) + if err := db.Error; err != nil { + e.Log.Errorf("Service UpdateSysApi error:%s", err) + return err + } + + return nil +} + +// Remove 删除SysApi +func (e *SysApi) Remove(d *dto.SysApiDeleteReq, p *actions.DataPermission) error { + var data models.SysApi + + db := e.Orm.Model(&data). + Scopes( + actions.Permission(data.TableName(), p), + ).Delete(&data, d.GetId()) + if err := db.Error; err != nil { + e.Log.Errorf("Service RemoveSysApi error:%s", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权删除该数据") + } + return nil +} + +// CheckStorageSysApi 创建SysApi对象 +func (e *SysApi) CheckStorageSysApi(c *[]runtime.Router) error { + for _, v := range *c { + err := e.Orm.Debug().Where(models.SysApi{Path: v.RelativePath, Action: v.HttpMethod}). + Attrs(models.SysApi{Handle: v.Handler}). + FirstOrCreate(&models.SysApi{}).Error + if err != nil { + err := fmt.Errorf("Service CheckStorageSysApi error: %s \r\n ", err.Error()) + return err + } + } + return nil +} diff --git a/app/admin/service/sys_config.go b/app/admin/service/sys_config.go new file mode 100644 index 0000000..c21fe44 --- /dev/null +++ b/app/admin/service/sys_config.go @@ -0,0 +1,182 @@ +package service + +import ( + "errors" + + "go-admin/app/admin/models" + "go-admin/app/admin/service/dto" + cDto "go-admin/common/dto" + + "github.com/go-admin-team/go-admin-core/sdk/service" + "gorm.io/gorm" +) + +type SysConfig struct { + service.Service +} + +// GetPage 获取SysConfig列表 +func (e *SysConfig) GetPage(c *dto.SysConfigGetPageReq, list *[]models.SysConfig, count *int64) error { + err := e.Orm. + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), + ). + Find(list).Limit(-1).Offset(-1). + Count(count).Error + if err != nil { + e.Log.Errorf("Service GetSysConfigPage error:%s", err) + return err + } + return nil +} + +// Get 获取SysConfig对象 +func (e *SysConfig) Get(d *dto.SysConfigGetReq, model *models.SysConfig) error { + err := e.Orm.First(model, d.GetId()).Error + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = errors.New("查看对象不存在或无权查看") + e.Log.Errorf("Service GetSysConfigPage error:%s", err) + return err + } + if err != nil { + e.Log.Errorf("Service GetSysConfig error:%s", err) + return err + } + return nil +} + +// Insert 创建SysConfig对象 +func (e *SysConfig) Insert(c *dto.SysConfigControl) error { + var err error + var data models.SysConfig + c.Generate(&data) + err = e.Orm.Create(&data).Error + if err != nil { + e.Log.Errorf("Service InsertSysConfig error:%s", err) + return err + } + return nil +} + +// Update 修改SysConfig对象 +func (e *SysConfig) Update(c *dto.SysConfigControl) error { + var err error + var model = models.SysConfig{} + e.Orm.First(&model, c.GetId()) + c.Generate(&model) + db := e.Orm.Save(&model) + err = db.Error + if err != nil { + e.Log.Errorf("Service UpdateSysConfig error:%s", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + + } + return nil +} + +// SetSysConfig 修改SysConfig对象 +func (e *SysConfig) SetSysConfig(c *[]dto.GetSetSysConfigReq) error { + var err error + for _, req := range *c { + var model = models.SysConfig{} + e.Orm.Where("config_key = ?", req.ConfigKey).First(&model) + if model.Id != 0 { + req.Generate(&model) + db := e.Orm.Save(&model) + err = db.Error + if err != nil { + e.Log.Errorf("Service SetSysConfig error:%s", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + } + } + } + return nil +} + +func (e *SysConfig) GetForSet(c *[]dto.GetSetSysConfigReq) error { + var err error + var data models.SysConfig + + err = e.Orm.Model(&data). + Find(c).Error + if err != nil { + e.Log.Errorf("Service GetSysConfigPage error:%s", err) + return err + } + return nil +} + +func (e *SysConfig) UpdateForSet(c *[]dto.GetSetSysConfigReq) error { + m := *c + for _, req := range m { + var data models.SysConfig + if err := e.Orm.Where("config_key = ?", req.ConfigKey). + First(&data).Error; err != nil { + e.Log.Errorf("Service GetSysConfigPage error:%s", err) + return err + } + if data.ConfigValue != req.ConfigValue { + data.ConfigValue = req.ConfigValue + + if err := e.Orm.Save(&data).Error; err != nil { + e.Log.Errorf("Service GetSysConfigPage error:%s", err) + return err + } + } + + } + + return nil +} + +// Remove 删除SysConfig +func (e *SysConfig) Remove(d *dto.SysConfigDeleteReq) error { + var err error + var data models.SysConfig + + db := e.Orm.Delete(&data, d.Ids) + if err = db.Error; err != nil { + err = db.Error + e.Log.Errorf("Service RemoveSysConfig error:%s", err) + return err + } + if db.RowsAffected == 0 { + err = errors.New("无权删除该数据") + return err + } + return nil +} + +// GetWithKey 根据Key获取SysConfig +func (e *SysConfig) GetWithKey(c *dto.SysConfigByKeyReq, resp *dto.GetSysConfigByKEYForServiceResp) error { + var err error + var data models.SysConfig + err = e.Orm.Table(data.TableName()).Where("config_key = ?", c.ConfigKey).First(resp).Error + if err != nil { + e.Log.Errorf("At Service GetSysConfigByKEY Error:%s", err) + return err + } + + return nil +} + +func (e *SysConfig) GetWithKeyList(c *dto.SysConfigGetToSysAppReq, list *[]models.SysConfig) error { + var err error + err = e.Orm. + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + ). + Find(list).Error + if err != nil { + e.Log.Errorf("Service GetSysConfigByKey error:%s", err) + return err + } + return nil +} diff --git a/app/admin/service/sys_dept.go b/app/admin/service/sys_dept.go new file mode 100644 index 0000000..fd43d5c --- /dev/null +++ b/app/admin/service/sys_dept.go @@ -0,0 +1,295 @@ +package service + +import ( + "errors" + "go-admin/app/admin/models" + + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + + "gorm.io/gorm" + + "go-admin/app/admin/service/dto" + cDto "go-admin/common/dto" + + "github.com/go-admin-team/go-admin-core/sdk/service" +) + +type SysDept struct { + service.Service +} + +// GetPage 获取SysDept列表 +//func (e *SysDept) GetPage(c *dto.SysDeptGetPageReq, list *[]models.SysDept) error { +// var err error +// var data models.SysDept +// +// err = e.Orm.Model(&data). +// Scopes( +// cDto.MakeCondition(c.GetNeedSearch()), +// ). +// Find(list).Error +// if err != nil { +// e.Log.Errorf("db error:%s", err) +// return err +// } +// return nil +//} + +// Get 获取SysDept对象 +func (e *SysDept) Get(d *dto.SysDeptGetReq, model *models.SysDept) error { + var err error + var data models.SysDept + + db := e.Orm.Model(&data). + First(model, d.GetId()) + err = db.Error + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = errors.New("查看对象不存在或无权查看") + e.Log.Errorf("db error:%s", err) + return err + } + if err = db.Error; err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + return nil +} + +// Insert 创建SysDept对象 +func (e *SysDept) Insert(c *dto.SysDeptInsertReq) error { + var err error + var data models.SysDept + c.Generate(&data) + tx := e.Orm.Debug().Begin() + defer func() { + if err != nil { + tx.Rollback() + } else { + tx.Commit() + } + }() + err = tx.Create(&data).Error + if err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + deptPath := pkg.IntToString(data.DeptId) + "/" + if data.ParentId != 0 { + var deptP models.SysDept + tx.First(&deptP, data.ParentId) + deptPath = deptP.DeptPath + deptPath + } else { + deptPath = "/0/" + deptPath + } + var mp = map[string]string{} + mp["dept_path"] = deptPath + if err := tx.Model(&data).Update("dept_path", deptPath).Error; err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + return nil +} + +// Update 修改SysDept对象 +func (e *SysDept) Update(c *dto.SysDeptUpdateReq) error { + var err error + var model = models.SysDept{} + tx := e.Orm.Debug().Begin() + defer func() { + if err != nil { + tx.Rollback() + } else { + tx.Commit() + } + }() + tx.First(&model, c.GetId()) + c.Generate(&model) + + deptPath := pkg.IntToString(model.DeptId) + "/" + if model.ParentId != 0 { + var deptP models.SysDept + tx.First(&deptP, model.ParentId) + deptPath = deptP.DeptPath + deptPath + } else { + deptPath = "/0/" + deptPath + } + model.DeptPath = deptPath + db := tx.Save(&model) + if err = db.Error; err != nil { + e.Log.Errorf("UpdateSysDept error:%s", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + } + return nil +} + +// Remove 删除SysDept +func (e *SysDept) Remove(d *dto.SysDeptDeleteReq) error { + var err error + var data models.SysDept + + db := e.Orm.Model(&data).Delete(&data, d.GetId()) + if err = db.Error; err != nil { + err = db.Error + e.Log.Errorf("Delete error: %s", err) + return err + } + if db.RowsAffected == 0 { + err = errors.New("无权删除该数据") + return err + } + return nil +} + +// GetSysDeptList 获取组织数据 +func (e *SysDept) getList(c *dto.SysDeptGetPageReq, list *[]models.SysDept) error { + var err error + var data models.SysDept + + err = e.Orm.Model(&data). + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + ). + Find(list).Error + if err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + return nil +} + +// SetDeptTree 设置组织数据 +func (e *SysDept) SetDeptTree(c *dto.SysDeptGetPageReq) (m []dto.DeptLabel, err error) { + var list []models.SysDept + err = e.getList(c, &list) + + m = make([]dto.DeptLabel, 0) + for i := 0; i < len(list); i++ { + if list[i].ParentId != 0 { + continue + } + e := dto.DeptLabel{} + e.Id = list[i].DeptId + e.Label = list[i].DeptName + deptsInfo := deptTreeCall(&list, e) + + m = append(m, deptsInfo) + } + return +} + +// Call 递归构造组织数据 +func deptTreeCall(deptList *[]models.SysDept, dept dto.DeptLabel) dto.DeptLabel { + list := *deptList + min := make([]dto.DeptLabel, 0) + for j := 0; j < len(list); j++ { + if dept.Id != list[j].ParentId { + continue + } + mi := dto.DeptLabel{Id: list[j].DeptId, Label: list[j].DeptName, Children: []dto.DeptLabel{}} + ms := deptTreeCall(deptList, mi) + min = append(min, ms) + } + dept.Children = min + return dept +} + +// SetDeptPage 设置dept页面数据 +func (e *SysDept) SetDeptPage(c *dto.SysDeptGetPageReq) (m []models.SysDept, err error) { + var list []models.SysDept + err = e.getList(c, &list) + for i := 0; i < len(list); i++ { + if list[i].ParentId != 0 { + continue + } + info := e.deptPageCall(&list, list[i]) + m = append(m, info) + } + return +} + +func (e *SysDept) deptPageCall(deptlist *[]models.SysDept, menu models.SysDept) models.SysDept { + list := *deptlist + min := make([]models.SysDept, 0) + for j := 0; j < len(list); j++ { + if menu.DeptId != list[j].ParentId { + continue + } + mi := models.SysDept{} + mi.DeptId = list[j].DeptId + mi.ParentId = list[j].ParentId + mi.DeptPath = list[j].DeptPath + mi.DeptName = list[j].DeptName + mi.Sort = list[j].Sort + mi.Leader = list[j].Leader + mi.Phone = list[j].Phone + mi.Email = list[j].Email + mi.Status = list[j].Status + mi.CreatedAt = list[j].CreatedAt + mi.Children = []models.SysDept{} + ms := e.deptPageCall(deptlist, mi) + min = append(min, ms) + } + menu.Children = min + return menu +} + +// GetWithRoleId 获取角色的部门ID集合 +func (e *SysDept) GetWithRoleId(roleId int) ([]int, error) { + deptIds := make([]int, 0) + deptList := make([]dto.DeptIdList, 0) + if err := e.Orm.Table("sys_role_dept"). + Select("sys_role_dept.dept_id"). + Joins("LEFT JOIN sys_dept on sys_dept.dept_id=sys_role_dept.dept_id"). + Where("role_id = ? ", roleId). + Where(" sys_role_dept.dept_id not in(select sys_dept.parent_id from sys_role_dept LEFT JOIN sys_dept on sys_dept.dept_id=sys_role_dept.dept_id where role_id =? )", roleId). + Find(&deptList).Error; err != nil { + return nil, err + } + for i := 0; i < len(deptList); i++ { + deptIds = append(deptIds, deptList[i].DeptId) + } + return deptIds, nil +} + +func (e *SysDept) SetDeptLabel() (m []dto.DeptLabel, err error) { + list := make([]models.SysDept, 0) + err = e.Orm.Find(&list).Error + if err != nil { + log.Error("find dept list error, %s", err.Error()) + return + } + m = make([]dto.DeptLabel, 0) + var item dto.DeptLabel + for i := range list { + if list[i].ParentId != 0 { + continue + } + item = dto.DeptLabel{} + item.Id = list[i].DeptId + item.Label = list[i].DeptName + deptInfo := deptLabelCall(&list, item) + m = append(m, deptInfo) + } + return +} + +// deptLabelCall +func deptLabelCall(deptList *[]models.SysDept, dept dto.DeptLabel) dto.DeptLabel { + list := *deptList + var mi dto.DeptLabel + min := make([]dto.DeptLabel, 0) + for j := 0; j < len(list); j++ { + if dept.Id != list[j].ParentId { + continue + } + mi = dto.DeptLabel{Id: list[j].DeptId, Label: list[j].DeptName, Children: []dto.DeptLabel{}} + ms := deptLabelCall(deptList, mi) + min = append(min, ms) + } + dept.Children = min + return dept +} diff --git a/app/admin/service/sys_dict_data.go b/app/admin/service/sys_dict_data.go new file mode 100644 index 0000000..553ad4c --- /dev/null +++ b/app/admin/service/sys_dict_data.go @@ -0,0 +1,121 @@ +package service + +import ( + "errors" + + "github.com/go-admin-team/go-admin-core/sdk/service" + "gorm.io/gorm" + + "go-admin/app/admin/models" + "go-admin/app/admin/service/dto" + cDto "go-admin/common/dto" +) + +type SysDictData struct { + service.Service +} + +// GetPage 获取列表 +func (e *SysDictData) GetPage(c *dto.SysDictDataGetPageReq, list *[]models.SysDictData, count *int64) error { + var err error + var data models.SysDictData + + err = e.Orm.Model(&data). + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), + ). + Find(list).Limit(-1).Offset(-1). + Count(count).Error + if err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + return nil +} + +// Get 获取对象 +func (e *SysDictData) Get(d *dto.SysDictDataGetReq, model *models.SysDictData) error { + var err error + var data models.SysDictData + + db := e.Orm.Model(&data). + First(model, d.GetId()) + err = db.Error + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = errors.New("查看对象不存在或无权查看") + e.Log.Errorf("db error: %s", err) + return err + } + if err = db.Error; err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + return nil +} + +// Insert 创建对象 +func (e *SysDictData) Insert(c *dto.SysDictDataInsertReq) error { + var err error + var data = new(models.SysDictData) + c.Generate(data) + err = e.Orm.Create(data).Error + if err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + return nil +} + +// Update 修改对象 +func (e *SysDictData) Update(c *dto.SysDictDataUpdateReq) error { + var err error + var model = models.SysDictData{} + e.Orm.First(&model, c.GetId()) + c.Generate(&model) + db := e.Orm.Save(model) + if err = db.Error; err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + + } + return nil +} + +// Remove 删除 +func (e *SysDictData) Remove(c *dto.SysDictDataDeleteReq) error { + var err error + var data models.SysDictData + + db := e.Orm.Delete(&data, c.GetId()) + if err = db.Error; err != nil { + err = db.Error + e.Log.Errorf("Delete error: %s", err) + return err + } + if db.RowsAffected == 0 { + err = errors.New("无权删除该数据") + return err + } + return nil +} + +// GetAll 获取所有 +func (e *SysDictData) GetAll(c *dto.SysDictDataGetPageReq, list *[]models.SysDictData) error { + var err error + var data models.SysDictData + + err = e.Orm.Model(&data). + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + ). + Find(list).Error + if err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + return nil +} diff --git a/app/admin/service/sys_dict_type.go b/app/admin/service/sys_dict_type.go new file mode 100644 index 0000000..5d6ff2b --- /dev/null +++ b/app/admin/service/sys_dict_type.go @@ -0,0 +1,124 @@ +package service + +import ( + "errors" + "fmt" + "github.com/go-admin-team/go-admin-core/sdk/service" + "gorm.io/gorm" + + "go-admin/app/admin/models" + "go-admin/app/admin/service/dto" + cDto "go-admin/common/dto" +) + +type SysDictType struct { + service.Service +} + +// GetPage 获取列表 +func (e *SysDictType) GetPage(c *dto.SysDictTypeGetPageReq, list *[]models.SysDictType, count *int64) error { + var err error + var data models.SysDictType + + err = e.Orm.Model(&data). + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), + ). + Find(list).Limit(-1).Offset(-1). + Count(count).Error + if err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + return nil +} + +// Get 获取对象 +func (e *SysDictType) Get(d *dto.SysDictTypeGetReq, model *models.SysDictType) error { + var err error + + db := e.Orm.First(model, d.GetId()) + err = db.Error + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = errors.New("查看对象不存在或无权查看") + e.Log.Errorf("db error: %s", err) + return err + } + if err = db.Error; err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + return nil +} + +// Insert 创建对象 +func (e *SysDictType) Insert(c *dto.SysDictTypeInsertReq) error { + var err error + var data models.SysDictType + c.Generate(&data) + var count int64 + e.Orm.Model(&data).Where("dict_type = ?", data.DictType).Count(&count) + if count > 0 { + return errors.New(fmt.Sprintf("当前字典类型[%s]已经存在!", data.DictType)) + } + err = e.Orm.Create(&data).Error + if err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + return nil +} + +// Update 修改对象 +func (e *SysDictType) Update(c *dto.SysDictTypeUpdateReq) error { + var err error + var model = models.SysDictType{} + e.Orm.First(&model, c.GetId()) + c.Generate(&model) + db := e.Orm.Save(&model) + if err = db.Error; err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + + } + return nil +} + +// Remove 删除 +func (e *SysDictType) Remove(d *dto.SysDictTypeDeleteReq) error { + var err error + var data models.SysDictType + + db := e.Orm.Delete(&data, d.GetId()) + if err = db.Error; err != nil { + err = db.Error + e.Log.Errorf("Delete error: %s", err) + return err + } + if db.RowsAffected == 0 { + err = errors.New("无权删除该数据") + return err + } + return nil +} + +// GetAll 获取所有 +func (e *SysDictType) GetAll(c *dto.SysDictTypeGetPageReq, list *[]models.SysDictType) error { + var err error + var data models.SysDictType + + err = e.Orm.Model(&data). + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + ). + Find(list).Error + if err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + return nil +} diff --git a/app/admin/service/sys_login_log.go b/app/admin/service/sys_login_log.go new file mode 100644 index 0000000..985feb3 --- /dev/null +++ b/app/admin/service/sys_login_log.go @@ -0,0 +1,70 @@ +package service + +import ( + "errors" + + "github.com/go-admin-team/go-admin-core/sdk/service" + "gorm.io/gorm" + + "go-admin/app/admin/models" + "go-admin/app/admin/service/dto" + cDto "go-admin/common/dto" +) + +type SysLoginLog struct { + service.Service +} + +// GetPage 获取SysLoginLog列表 +func (e *SysLoginLog) GetPage(c *dto.SysLoginLogGetPageReq, list *[]models.SysLoginLog, count *int64) error { + var err error + var data models.SysLoginLog + + err = e.Orm.Model(&data). + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), + ). + Find(list).Limit(-1).Offset(-1). + Count(count).Error + if err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + return nil +} + +// Get 获取SysLoginLog对象 +func (e *SysLoginLog) Get(d *dto.SysLoginLogGetReq, model *models.SysLoginLog) error { + var err error + db := e.Orm.First(model, d.GetId()) + err = db.Error + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = errors.New("查看对象不存在或无权查看") + e.Log.Errorf("db error:%s", err) + return err + } + if err = db.Error; err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + return nil +} + +// Remove 删除SysLoginLog +func (e *SysLoginLog) Remove(c *dto.SysLoginLogDeleteReq) error { + var err error + var data models.SysLoginLog + + db := e.Orm.Delete(&data, c.GetId()) + if err = db.Error; err != nil { + err = db.Error + e.Log.Errorf("Delete error: %s", err) + return err + } + if db.RowsAffected == 0 { + err = errors.New("无权删除该数据") + return err + } + return nil +} diff --git a/app/admin/service/sys_menu.go b/app/admin/service/sys_menu.go new file mode 100644 index 0000000..3d6aab7 --- /dev/null +++ b/app/admin/service/sys_menu.go @@ -0,0 +1,423 @@ +package service + +import ( + "fmt" + "sort" + "strings" + + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "github.com/pkg/errors" + "gorm.io/gorm" + + "go-admin/app/admin/models" + "go-admin/app/admin/service/dto" + cDto "go-admin/common/dto" + cModels "go-admin/common/models" + + "github.com/go-admin-team/go-admin-core/sdk/service" +) + +type SysMenu struct { + service.Service +} + +// GetPage 获取SysMenu列表 +func (e *SysMenu) GetPage(c *dto.SysMenuGetPageReq, menus *[]models.SysMenu) *SysMenu { + var menu = make([]models.SysMenu, 0) + err := e.getPage(c, &menu).Error + if err != nil { + _ = e.AddError(err) + return e + } + for i := 0; i < len(menu); i++ { + if menu[i].ParentId != 0 { + continue + } + menusInfo := menuCall(&menu, menu[i]) + *menus = append(*menus, menusInfo) + } + return e +} + +// getPage 菜单分页列表 +func (e *SysMenu) getPage(c *dto.SysMenuGetPageReq, list *[]models.SysMenu) *SysMenu { + var err error + var data models.SysMenu + + err = e.Orm.Model(&data). + Scopes( + cDto.OrderDest("sort", false), + cDto.MakeCondition(c.GetNeedSearch()), + ).Preload("SysApi"). + Find(list).Error + if err != nil { + e.Log.Errorf("getSysMenuPage error:%s", err) + _ = e.AddError(err) + return e + } + return e +} + +// Get 获取SysMenu对象 +func (e *SysMenu) Get(d *dto.SysMenuGetReq, model *models.SysMenu) *SysMenu { + var err error + var data models.SysMenu + + db := e.Orm.Model(&data).Preload("SysApi"). + First(model, d.GetId()) + err = db.Error + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = errors.New("查看对象不存在或无权查看") + e.Log.Errorf("GetSysMenu error:%s", err) + _ = e.AddError(err) + return e + } + if err != nil { + e.Log.Errorf("db error:%s", err) + _ = e.AddError(err) + return e + } + apis := make([]int, 0) + for _, v := range model.SysApi { + apis = append(apis, v.Id) + } + model.Apis = apis + return e +} + +// Insert 创建SysMenu对象 +func (e *SysMenu) Insert(c *dto.SysMenuInsertReq) *SysMenu { + var err error + var data models.SysMenu + c.Generate(&data) + tx := e.Orm.Debug().Begin() + defer func() { + if err != nil { + tx.Rollback() + } else { + tx.Commit() + } + }() + err = tx.Where("id in ?", c.Apis).Find(&data.SysApi).Error + if err != nil { + tx.Rollback() + e.Log.Errorf("db error:%s", err) + _ = e.AddError(err) + } + err = tx.Create(&data).Error + if err != nil { + tx.Rollback() + e.Log.Errorf("db error:%s", err) + _ = e.AddError(err) + } + c.MenuId = data.MenuId + err = e.initPaths(tx, &data) + if err != nil { + tx.Rollback() + e.Log.Errorf("db error:%s", err) + _ = e.AddError(err) + } + tx.Commit() + return e +} + +func (e *SysMenu) initPaths(tx *gorm.DB, menu *models.SysMenu) error { + var err error + var data models.SysMenu + parentMenu := new(models.SysMenu) + if menu.ParentId != 0 { + err = tx.Model(&data).First(parentMenu, menu.ParentId).Error + if err != nil { + return err + } + if parentMenu.Paths == "" { + err = errors.New("父级paths异常,请尝试对当前节点父级菜单进行更新操作!") + return err + } + menu.Paths = parentMenu.Paths + "/" + pkg.IntToString(menu.MenuId) + } else { + menu.Paths = "/0/" + pkg.IntToString(menu.MenuId) + } + err = tx.Model(&data).Where("menu_id = ?", menu.MenuId).Update("paths", menu.Paths).Error + return err +} + +// Update 修改SysMenu对象 +func (e *SysMenu) Update(c *dto.SysMenuUpdateReq) *SysMenu { + var err error + tx := e.Orm.Debug().Begin() + defer func() { + if err != nil { + tx.Rollback() + } else { + tx.Commit() + } + }() + var alist = make([]models.SysApi, 0) + var model = models.SysMenu{} + tx.Preload("SysApi").First(&model, c.GetId()) + oldPath := model.Paths + tx.Where("id in ?", c.Apis).Find(&alist) + err = tx.Model(&model).Association("SysApi").Delete(model.SysApi) + if err != nil { + e.Log.Errorf("delete policy error:%s", err) + _ = e.AddError(err) + return e + } + c.Generate(&model) + model.SysApi = alist + db := tx.Model(&model).Session(&gorm.Session{FullSaveAssociations: true}).Debug().Save(&model) + if err = db.Error; err != nil { + e.Log.Errorf("db error:%s", err) + _ = e.AddError(err) + return e + } + if db.RowsAffected == 0 { + _ = e.AddError(errors.New("无权更新该数据")) + return e + } + var menuList []models.SysMenu + tx.Where("paths like ?", oldPath+"%").Find(&menuList) + for _, v := range menuList { + v.Paths = strings.Replace(v.Paths, oldPath, model.Paths, 1) + tx.Model(&v).Update("paths", v.Paths) + } + return e +} + +// Remove 删除SysMenu +func (e *SysMenu) Remove(d *dto.SysMenuDeleteReq) *SysMenu { + var err error + var data models.SysMenu + + db := e.Orm.Model(&data).Delete(&data, d.Ids) + if err = db.Error; err != nil { + err = db.Error + e.Log.Errorf("Delete error: %s", err) + _ = e.AddError(err) + } + if db.RowsAffected == 0 { + err = errors.New("无权删除该数据") + _ = e.AddError(err) + } + return e +} + +// GetList 获取菜单数据 +func (e *SysMenu) GetList(c *dto.SysMenuGetPageReq, list *[]models.SysMenu) error { + var err error + var data models.SysMenu + + err = e.Orm.Model(&data). + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + ). + Find(list).Error + if err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + return nil +} + +// SetLabel 修改角色中 设置菜单基础数据 +func (e *SysMenu) SetLabel() (m []dto.MenuLabel, err error) { + var list []models.SysMenu + err = e.GetList(&dto.SysMenuGetPageReq{}, &list) + + m = make([]dto.MenuLabel, 0) + for i := 0; i < len(list); i++ { + if list[i].ParentId != 0 { + continue + } + e := dto.MenuLabel{} + e.Id = list[i].MenuId + e.Label = list[i].Title + deptsInfo := menuLabelCall(&list, e) + + m = append(m, deptsInfo) + } + return +} + +// GetSysMenuByRoleName 左侧菜单 +func (e *SysMenu) GetSysMenuByRoleName(roleName ...string) ([]models.SysMenu, error) { + var MenuList []models.SysMenu + var role models.SysRole + var err error + admin := false + for _, s := range roleName { + if s == "admin" { + admin = true + } + } + + if len(roleName) > 0 && admin { + var data []models.SysMenu + err = e.Orm.Where(" menu_type in ('M','C')"). + Order("sort"). + Find(&data). + Error + MenuList = data + } else { + err = e.Orm.Model(&role).Preload("SysMenu", func(db *gorm.DB) *gorm.DB { + return db.Where(" menu_type in ('M','C')").Order("sort") + }).Where("role_name in ?", roleName).Find(&role). + Error + MenuList = *role.SysMenu + } + + if err != nil { + e.Log.Errorf("db error:%s", err) + } + return MenuList, err +} + +// menuLabelCall 递归构造组织数据 +func menuLabelCall(eList *[]models.SysMenu, dept dto.MenuLabel) dto.MenuLabel { + list := *eList + + min := make([]dto.MenuLabel, 0) + for j := 0; j < len(list); j++ { + + if dept.Id != list[j].ParentId { + continue + } + mi := dto.MenuLabel{} + mi.Id = list[j].MenuId + mi.Label = list[j].Title + mi.Children = []dto.MenuLabel{} + if list[j].MenuType != "F" { + ms := menuLabelCall(eList, mi) + min = append(min, ms) + } else { + min = append(min, mi) + } + } + if len(min) > 0 { + dept.Children = min + } else { + dept.Children = nil + } + return dept +} + +// menuCall 构建菜单树 +func menuCall(menuList *[]models.SysMenu, menu models.SysMenu) models.SysMenu { + list := *menuList + + min := make([]models.SysMenu, 0) + for j := 0; j < len(list); j++ { + + if menu.MenuId != list[j].ParentId { + continue + } + mi := models.SysMenu{} + mi.MenuId = list[j].MenuId + mi.MenuName = list[j].MenuName + mi.Title = list[j].Title + mi.Icon = list[j].Icon + mi.Path = list[j].Path + mi.MenuType = list[j].MenuType + mi.Action = list[j].Action + mi.Permission = list[j].Permission + mi.ParentId = list[j].ParentId + mi.NoCache = list[j].NoCache + mi.Breadcrumb = list[j].Breadcrumb + mi.Component = list[j].Component + mi.Sort = list[j].Sort + mi.Visible = list[j].Visible + mi.CreatedAt = list[j].CreatedAt + mi.SysApi = list[j].SysApi + mi.Children = []models.SysMenu{} + + if mi.MenuType != cModels.Button { + ms := menuCall(menuList, mi) + min = append(min, ms) + } else { + min = append(min, mi) + } + } + menu.Children = min + return menu +} + +func menuDistinct(menuList []models.SysMenu) (result []models.SysMenu) { + distinctMap := make(map[int]struct{}, len(menuList)) + for _, menu := range menuList { + if _, ok := distinctMap[menu.MenuId]; !ok { + distinctMap[menu.MenuId] = struct{}{} + result = append(result, menu) + } + } + return result +} + +func recursiveSetMenu(orm *gorm.DB, mIds []int, menus *[]models.SysMenu) error { + if len(mIds) == 0 || menus == nil { + return nil + } + var subMenus []models.SysMenu + err := orm.Where(fmt.Sprintf(" menu_type in ('%s', '%s', '%s') and menu_id in ?", + cModels.Directory, cModels.Menu, cModels.Button), mIds).Order("sort").Find(&subMenus).Error + if err != nil { + return err + } + + subIds := make([]int, 0) + for _, menu := range subMenus { + if menu.ParentId != 0 { + subIds = append(subIds, menu.ParentId) + } + if menu.MenuType != cModels.Button { + *menus = append(*menus, menu) + } + } + return recursiveSetMenu(orm, subIds, menus) +} + +// SetMenuRole 获取左侧菜单树使用 +func (e *SysMenu) SetMenuRole(roleName string) (m []models.SysMenu, err error) { + menus, err := e.getByRoleName(roleName) + m = make([]models.SysMenu, 0) + for i := 0; i < len(menus); i++ { + if menus[i].ParentId != 0 { + continue + } + menusInfo := menuCall(&menus, menus[i]) + m = append(m, menusInfo) + } + return +} + +func (e *SysMenu) getByRoleName(roleName string) ([]models.SysMenu, error) { + var role models.SysRole + var err error + data := make([]models.SysMenu, 0) + + if roleName == "admin" { + err = e.Orm.Where(" menu_type in ('M','C') and deleted_at is null"). + Order("sort"). + Find(&data). + Error + err = errors.WithStack(err) + } else { + role.RoleKey = roleName + err = e.Orm.Model(&role).Where("role_key = ? ", roleName).Preload("SysMenu").First(&role).Error + + if role.SysMenu != nil { + mIds := make([]int, 0) + for _, menu := range *role.SysMenu { + mIds = append(mIds, menu.MenuId) + } + if err := recursiveSetMenu(e.Orm, mIds, &data); err != nil { + return nil, err + } + + data = menuDistinct(data) + } + } + + sort.Sort(models.SysMenuSlice(data)) + return data, err +} diff --git a/app/admin/service/sys_opera_log.go b/app/admin/service/sys_opera_log.go new file mode 100644 index 0000000..c94b82c --- /dev/null +++ b/app/admin/service/sys_opera_log.go @@ -0,0 +1,83 @@ +package service + +import ( + "errors" + + "go-admin/app/admin/models" + "go-admin/app/admin/service/dto" + cDto "go-admin/common/dto" + + "github.com/go-admin-team/go-admin-core/sdk/service" + "gorm.io/gorm" +) + +type SysOperaLog struct { + service.Service +} + +// GetPage 获取SysOperaLog列表 +func (e *SysOperaLog) GetPage(c *dto.SysOperaLogGetPageReq, list *[]models.SysOperaLog, count *int64) error { + var err error + var data models.SysOperaLog + + err = e.Orm.Model(&data). + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), + ). + Find(list).Limit(-1).Offset(-1). + Count(count).Error + if err != nil { + e.Log.Errorf("Service GetSysOperaLogPage error:%s", err.Error()) + return err + } + return nil +} + +// Get 获取SysOperaLog对象 +func (e *SysOperaLog) Get(d *dto.SysOperaLogGetReq, model *models.SysOperaLog) error { + var data models.SysOperaLog + + err := e.Orm.Model(&data). + First(model, d.GetId()).Error + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = errors.New("查看对象不存在或无权查看") + e.Log.Errorf("Service GetSysOperaLog error:%s", err.Error()) + return err + } + if err != nil { + e.Log.Errorf("Service GetSysOperaLog error:%s", err.Error()) + return err + } + return nil +} + +// Insert 创建SysOperaLog对象 +func (e *SysOperaLog) Insert(model *models.SysOperaLog) error { + var err error + var data models.SysOperaLog + + err = e.Orm.Model(&data). + Create(model).Error + if err != nil { + e.Log.Errorf("Service InsertSysOperaLog error:%s", err.Error()) + return err + } + return nil +} + +// Remove 删除SysOperaLog +func (e *SysOperaLog) Remove(d *dto.SysOperaLogDeleteReq) error { + var err error + var data models.SysOperaLog + + db := e.Orm.Model(&data).Delete(&data, d.GetId()) + if err = db.Error; err != nil { + e.Log.Errorf("Service RemoveSysOperaLog error:%s", err.Error()) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权删除该数据") + } + return nil +} diff --git a/app/admin/service/sys_post.go b/app/admin/service/sys_post.go new file mode 100644 index 0000000..51956f4 --- /dev/null +++ b/app/admin/service/sys_post.go @@ -0,0 +1,105 @@ +package service + +import ( + "errors" + + "github.com/go-admin-team/go-admin-core/sdk/service" + "gorm.io/gorm" + + "go-admin/app/admin/models" + "go-admin/app/admin/service/dto" + cDto "go-admin/common/dto" +) + +type SysPost struct { + service.Service +} + +// GetPage 获取SysPost列表 +func (e *SysPost) GetPage(c *dto.SysPostPageReq, list *[]models.SysPost, count *int64) error { + var err error + var data models.SysPost + + err = e.Orm.Model(&data). + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), + ). + Find(list).Limit(-1).Offset(-1). + Count(count).Error + if err != nil { + e.Log.Errorf("db error:%s \r", err) + return err + } + return nil +} + +// Get 获取SysPost对象 +func (e *SysPost) Get(d *dto.SysPostGetReq, model *models.SysPost) error { + var err error + var data models.SysPost + + db := e.Orm.Model(&data). + First(model, d.GetId()) + err = db.Error + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = errors.New("查看对象不存在或无权查看") + e.Log.Errorf("db error:%s", err) + return err + } + if err = db.Error; err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + return nil +} + +// Insert 创建SysPost对象 +func (e *SysPost) Insert(c *dto.SysPostInsertReq) error { + var err error + var data models.SysPost + c.Generate(&data) + err = e.Orm.Create(&data).Error + if err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + return nil +} + +// Update 修改SysPost对象 +func (e *SysPost) Update(c *dto.SysPostUpdateReq) error { + var err error + var model = models.SysPost{} + e.Orm.First(&model, c.GetId()) + c.Generate(&model) + + db := e.Orm.Save(&model) + if err = db.Error; err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + + } + return nil +} + +// Remove 删除SysPost +func (e *SysPost) Remove(d *dto.SysPostDeleteReq) error { + var err error + var data models.SysPost + + db := e.Orm.Model(&data).Delete(&data, d.GetId()) + if err = db.Error; err != nil { + err = db.Error + e.Log.Errorf("Delete error: %s", err) + return err + } + if db.RowsAffected == 0 { + err = errors.New("无权删除该数据") + return err + } + return nil +} \ No newline at end of file diff --git a/app/admin/service/sys_role.go b/app/admin/service/sys_role.go new file mode 100644 index 0000000..f1fee74 --- /dev/null +++ b/app/admin/service/sys_role.go @@ -0,0 +1,352 @@ +package service + +import ( + "errors" + + "github.com/go-admin-team/go-admin-core/sdk/config" + "gorm.io/gorm/clause" + + "github.com/casbin/casbin/v2" + + "github.com/go-admin-team/go-admin-core/sdk/service" + "gorm.io/gorm" + + "go-admin/app/admin/models" + "go-admin/app/admin/service/dto" + cDto "go-admin/common/dto" +) + +type SysRole struct { + service.Service +} + +// GetPage 获取SysRole列表 +func (e *SysRole) GetPage(c *dto.SysRoleGetPageReq, list *[]models.SysRole, count *int64) error { + var err error + var data models.SysRole + + err = e.Orm.Model(&data).Preload("SysMenu"). + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), + ). + Find(list).Limit(-1).Offset(-1). + Count(count).Error + if err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + return nil +} + +// Get 获取SysRole对象 +func (e *SysRole) Get(d *dto.SysRoleGetReq, model *models.SysRole) error { + var err error + db := e.Orm.First(model, d.GetId()) + err = db.Error + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = errors.New("查看对象不存在或无权查看") + e.Log.Errorf("db error:%s", err) + return err + } + if err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + model.MenuIds, err = e.GetRoleMenuId(model.RoleId) + if err != nil { + e.Log.Errorf("get menuIds error, %s", err.Error()) + return err + } + return nil +} + +// Insert 创建SysRole对象 +func (e *SysRole) Insert(c *dto.SysRoleInsertReq, cb *casbin.SyncedEnforcer) error { + var err error + var data models.SysRole + var dataMenu []models.SysMenu + err = e.Orm.Preload("SysApi").Where("menu_id in ?", c.MenuIds).Find(&dataMenu).Error + if err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + c.SysMenu = dataMenu + c.Generate(&data) + tx := e.Orm + if config.DatabaseConfig.Driver != "sqlite3" { + tx := e.Orm.Begin() + defer func() { + if err != nil { + tx.Rollback() + } else { + tx.Commit() + } + }() + } + var count int64 + err = tx.Model(&data).Where("role_key = ?", c.RoleKey).Count(&count).Error + if err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + + if count > 0 { + err = errors.New("roleKey已存在,需更换在提交!") + e.Log.Errorf("db error:%s", err) + return err + } + + err = tx.Create(&data).Error + if err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + + mp := make(map[string]interface{}, 0) + polices := make([][]string, 0) + for _, menu := range dataMenu { + for _, api := range menu.SysApi { + if mp[data.RoleKey+"-"+api.Path+"-"+api.Action] != "" { + mp[data.RoleKey+"-"+api.Path+"-"+api.Action] = "" + polices = append(polices, []string{data.RoleKey, api.Path, api.Action}) + } + } + } + + if len(polices) <= 0 { + return nil + } + + // 写入 sys_casbin_rule 权限表里 当前角色数据的记录 + _, err = cb.AddNamedPolicies("p", polices) + if err != nil { + return err + } + + return nil +} + +// Update 修改SysRole对象 +func (e *SysRole) Update(c *dto.SysRoleUpdateReq, cb *casbin.SyncedEnforcer) error { + var err error + tx := e.Orm + if config.DatabaseConfig.Driver != "sqlite3" { + tx := e.Orm.Begin() + defer func() { + if err != nil { + tx.Rollback() + } else { + tx.Commit() + } + }() + } + var model = models.SysRole{} + var mlist = make([]models.SysMenu, 0) + tx.Preload("SysMenu").First(&model, c.GetId()) + tx.Preload("SysApi").Where("menu_id in ?", c.MenuIds).Find(&mlist) + err = tx.Model(&model).Association("SysMenu").Delete(model.SysMenu) + if err != nil { + e.Log.Errorf("delete policy error:%s", err) + return err + } + c.Generate(&model) + model.SysMenu = &mlist + // 更新关联的数据,使用 FullSaveAssociations 模式 + db := tx.Session(&gorm.Session{FullSaveAssociations: true}).Debug().Save(&model) + + if err = db.Error; err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + } + + // 清除 sys_casbin_rule 权限表里 当前角色的所有记录 + _, err = cb.RemoveFilteredPolicy(0, model.RoleKey) + if err != nil { + e.Log.Errorf("delete policy error:%s", err) + return err + } + mp := make(map[string]interface{}, 0) + polices := make([][]string, 0) + for _, menu := range mlist { + for _, api := range menu.SysApi { + if mp[model.RoleKey+"-"+api.Path+"-"+api.Action] != "" { + mp[model.RoleKey+"-"+api.Path+"-"+api.Action] = "" + //_, err = cb.AddNamedPolicy("p", model.RoleKey, api.Path, api.Action) + polices = append(polices, []string{model.RoleKey, api.Path, api.Action}) + } + } + } + if len(polices) <= 0 { + return nil + } + + // 写入 sys_casbin_rule 权限表里 当前角色数据的记录 + _, err = cb.AddNamedPolicies("p", polices) + if err != nil { + return err + } + return nil +} + +// Remove 删除SysRole +func (e *SysRole) Remove(c *dto.SysRoleDeleteReq, cb *casbin.SyncedEnforcer) error { + var err error + tx := e.Orm + if config.DatabaseConfig.Driver != "sqlite3" { + tx := e.Orm.Begin() + defer func() { + if err != nil { + tx.Rollback() + } else { + tx.Commit() + } + }() + } + var model = models.SysRole{} + tx.Preload("SysMenu").Preload("SysDept").First(&model, c.GetId()) + //删除 SysRole 时,同时删除角色所有 关联其它表 记录 (SysMenu 和 SysMenu) + db := tx.Select(clause.Associations).Delete(&model) + + if err = db.Error; err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + } + + // 清除 sys_casbin_rule 权限表里 当前角色的所有记录 + _, _ = cb.RemoveFilteredPolicy(0, model.RoleKey) + + return nil +} + +// GetRoleMenuId 获取角色对应的菜单ids +func (e *SysRole) GetRoleMenuId(roleId int) ([]int, error) { + menuIds := make([]int, 0) + model := models.SysRole{} + model.RoleId = roleId + if err := e.Orm.Model(&model).Preload("SysMenu").First(&model).Error; err != nil { + return nil, err + } + l := *model.SysMenu + for i := 0; i < len(l); i++ { + menuIds = append(menuIds, l[i].MenuId) + } + return menuIds, nil +} + +func (e *SysRole) UpdateDataScope(c *dto.RoleDataScopeReq) *SysRole { + var err error + tx := e.Orm + if config.DatabaseConfig.Driver != "sqlite3" { + tx := e.Orm.Begin() + defer func() { + if err != nil { + tx.Rollback() + } else { + tx.Commit() + } + }() + } + var dlist = make([]models.SysDept, 0) + var model = models.SysRole{} + tx.Preload("SysDept").First(&model, c.RoleId) + tx.Where("dept_id in ?", c.DeptIds).Find(&dlist) + // 删除SysRole 和 SysDept 的关联关系 + err = tx.Model(&model).Association("SysDept").Delete(model.SysDept) + if err != nil { + e.Log.Errorf("delete SysDept error:%s", err) + _ = e.AddError(err) + return e + } + c.Generate(&model) + model.SysDept = dlist + // 更新关联的数据,使用 FullSaveAssociations 模式 + db := tx.Model(&model).Session(&gorm.Session{FullSaveAssociations: true}).Debug().Save(&model) + if err = db.Error; err != nil { + e.Log.Errorf("db error:%s", err) + _ = e.AddError(err) + return e + } + if db.RowsAffected == 0 { + _ = e.AddError(errors.New("无权更新该数据")) + return e + } + return e +} + +// UpdateStatus 修改SysRole对象status +func (e *SysRole) UpdateStatus(c *dto.UpdateStatusReq) error { + var err error + tx := e.Orm + if config.DatabaseConfig.Driver != "sqlite3" { + tx := e.Orm.Begin() + defer func() { + if err != nil { + tx.Rollback() + } else { + tx.Commit() + } + }() + } + var model = models.SysRole{} + tx.First(&model, c.GetId()) + c.Generate(&model) + // 更新关联的数据,使用 FullSaveAssociations 模式 + db := tx.Session(&gorm.Session{FullSaveAssociations: true}).Debug().Save(&model) + if err = db.Error; err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + } + return nil +} + +// GetWithName 获取SysRole对象 +func (e *SysRole) GetWithName(d *dto.SysRoleByName, model *models.SysRole) *SysRole { + var err error + db := e.Orm.Where("role_name = ?", d.RoleName).First(model) + err = db.Error + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = errors.New("查看对象不存在或无权查看") + e.Log.Errorf("db error:%s", err) + _ = e.AddError(err) + return e + } + if err != nil { + e.Log.Errorf("db error:%s", err) + _ = e.AddError(err) + return e + } + model.MenuIds, err = e.GetRoleMenuId(model.RoleId) + if err != nil { + e.Log.Errorf("get menuIds error, %s", err.Error()) + _ = e.AddError(err) + return e + } + return e +} + +// GetById 获取SysRole对象 +func (e *SysRole) GetById(roleId int) ([]string, error) { + permissions := make([]string, 0) + model := models.SysRole{} + model.RoleId = roleId + if err := e.Orm.Model(&model).Preload("SysMenu").First(&model).Error; err != nil { + return nil, err + } + l := *model.SysMenu + for i := 0; i < len(l); i++ { + if l[i].Permission != "" { + permissions = append(permissions, l[i].Permission) + } + } + return permissions, nil +} diff --git a/app/admin/service/sys_role_menu.go b/app/admin/service/sys_role_menu.go new file mode 100644 index 0000000..9d5d38b --- /dev/null +++ b/app/admin/service/sys_role_menu.go @@ -0,0 +1,110 @@ +package service + +import ( + "github.com/go-admin-team/go-admin-core/sdk/service" +) + +// SysRoleMenu 即将弃用结构体 +type SysRoleMenu struct { + service.Service +} + +//func (e *SysRoleMenu) ReloadRule(tx *gorm.DB, roleId int, menuId []int) (err error) { +// var role models.SysRole +// +// msgID := e.MsgID +// +// menu := make([]models.Menu, 0) +// roleMenu := make([]models.RoleMenu, len(menuId)) +// casbinRule := make([]models.CasbinRule, 0) +// //先删除所有的 +// err = e.DeleteRoleMenu(tx, roleId) +// if err != nil { +// return +// } +// +// // 在事务中做一些数据库操作(从这一点使用'tx',而不是'db') +// err = tx.Where("role_id = ?", roleId).First(&role).Error +// if err != nil { +// log.Errorf("msgID[%s] get role error, %s", msgID, err.Error()) +// return +// } +// err = tx.Where("menu_id in (?)", menuId). +// //Select("path, action, menu_id, menu_type"). +// Find(&menu).Error +// if err != nil { +// log.Errorf("msgID[%s] get menu error, %s", msgID, err.Error()) +// return +// } +// for i := range menu { +// roleMenu[i] = models.RoleMenu{ +// RoleId: role.RoleId, +// MenuId: menu[i].MenuId, +// RoleName: role.RoleKey, +// } +// if menu[i].MenuType == "A" { +// casbinRule = append(casbinRule, models.CasbinRule{ +// PType: "p", +// V0: role.RoleKey, +// V1: menu[i].Path, +// V2: menu[i].Action, +// }) +// } +// } +// err = tx.Create(&roleMenu).Error +// if err != nil { +// log.Errorf("msgID[%s] batch create role's menu error, %s", msgID, err.Error()) +// return +// } +// if len(casbinRule) > 0 { +// err = tx.Create(&casbinRule).Error +// if err != nil { +// log.Errorf("msgID[%s] batch create casbin rule error, %s", msgID, err.Error()) +// return +// } +// } +// +// return +//} + +//func (e *SysRoleMenu) DeleteRoleMenu(tx *gorm.DB, roleId int) (err error) { +// msgID := e.MsgID +// err = tx.Where("role_id = ?", roleId). +// Delete(&models.SysRoleDept{}).Error +// if err != nil { +// log.Errorf("msgID[%s] delete role's dept error, %s", msgID, err.Error()) +// return +// } +// err = tx.Where("role_id = ?", roleId). +// Delete(&models.RoleMenu{}).Error +// if err != nil { +// log.Errorf("msgID[%s] delete role's menu error, %s", msgID, err.Error()) +// return +// } +// var role models.SysRole +// err = tx.Where("role_id = ?", roleId). +// First(&role).Error +// if err != nil { +// log.Errorf("msgID[%s] get role error, %s", msgID, err.Error()) +// return +// } +// err = tx.Where("v0 = ?", role.RoleKey). +// Delete(&models.CasbinRule{}).Error +// if err != nil { +// log.Errorf("msgID[%s] delete casbin rule error, %s", msgID, err.Error()) +// return +// } +// return +//} +// +//func (e *SysRoleMenu) GetIDS(tx *gorm.DB, roleName string) ([]models.MenuPath, error) { +// var r []models.MenuPath +// table := tx.Select("sys_menu.path").Table("sys_role_menu") +// table = table.Joins("left join sys_role on sys_role.role_id=sys_role_menu.role_id") +// table = table.Joins("left join sys_menu on sys_menu.id=sys_role_menu.menu_id") +// table = table.Where("sys_role.role_name = ? and sys_menu.type=1", roleName) +// if err := table.Find(&r).Error; err != nil { +// return nil, err +// } +// return r, nil +//} \ No newline at end of file diff --git a/app/admin/service/sys_user.go b/app/admin/service/sys_user.go new file mode 100644 index 0000000..2a03c03 --- /dev/null +++ b/app/admin/service/sys_user.go @@ -0,0 +1,266 @@ +package service + +import ( + "errors" + "go-admin/app/admin/models" + "go-admin/app/admin/service/dto" + + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "github.com/go-admin-team/go-admin-core/sdk/service" + "gorm.io/gorm" + + "go-admin/common/actions" + cDto "go-admin/common/dto" +) + +type SysUser struct { + service.Service +} + +// GetPage 获取SysUser列表 +func (e *SysUser) GetPage(c *dto.SysUserGetPageReq, p *actions.DataPermission, list *[]models.SysUser, count *int64) error { + var err error + var data models.SysUser + + err = e.Orm.Debug().Preload("Dept"). + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), + actions.Permission(data.TableName(), p), + ). + Find(list).Limit(-1).Offset(-1). + Count(count).Error + if err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + return nil +} + +// Get 获取SysUser对象 +func (e *SysUser) Get(d *dto.SysUserById, p *actions.DataPermission, model *models.SysUser) error { + var data models.SysUser + + err := e.Orm.Model(&data).Debug(). + Scopes( + actions.Permission(data.TableName(), p), + ). + First(model, d.GetId()).Error + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = errors.New("查看对象不存在或无权查看") + e.Log.Errorf("db error: %s", err) + return err + } + if err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + return nil +} + +// Insert 创建SysUser对象 +func (e *SysUser) Insert(c *dto.SysUserInsertReq) error { + var err error + var data models.SysUser + var i int64 + err = e.Orm.Model(&data).Where("username = ?", c.Username).Count(&i).Error + if err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + if i > 0 { + err := errors.New("用户名已存在!") + e.Log.Errorf("db error: %s", err) + return err + } + c.Generate(&data) + err = e.Orm.Create(&data).Error + if err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + return nil +} + +// Update 修改SysUser对象 +func (e *SysUser) Update(c *dto.SysUserUpdateReq, p *actions.DataPermission) error { + var err error + var model models.SysUser + db := e.Orm.Scopes( + actions.Permission(model.TableName(), p), + ).First(&model, c.GetId()) + if err = db.Error; err != nil { + e.Log.Errorf("Service UpdateSysUser error: %s", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + + } + c.Generate(&model) + update := e.Orm.Model(&model).Where("user_id = ?", &model.UserId).Omit("password", "salt").Updates(&model) + if err = update.Error; err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + if update.RowsAffected == 0 { + err = errors.New("update userinfo error") + log.Warnf("db update error") + return err + } + return nil +} + +// UpdateAvatar 更新用户头像 +func (e *SysUser) UpdateAvatar(c *dto.UpdateSysUserAvatarReq, p *actions.DataPermission) error { + var err error + var model models.SysUser + db := e.Orm.Scopes( + actions.Permission(model.TableName(), p), + ).First(&model, c.GetId()) + if err = db.Error; err != nil { + e.Log.Errorf("Service UpdateSysUser error: %s", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + + } + err = e.Orm.Table(model.TableName()).Where("user_id =? ", c.UserId).Updates(c).Error + if err != nil { + e.Log.Errorf("Service UpdateSysUser error: %s", err) + return err + } + return nil +} + +// UpdateStatus 更新用户状态 +func (e *SysUser) UpdateStatus(c *dto.UpdateSysUserStatusReq, p *actions.DataPermission) error { + var err error + var model models.SysUser + db := e.Orm.Scopes( + actions.Permission(model.TableName(), p), + ).First(&model, c.GetId()) + if err = db.Error; err != nil { + e.Log.Errorf("Service UpdateSysUser error: %s", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + + } + err = e.Orm.Table(model.TableName()).Where("user_id =? ", c.UserId).Updates(c).Error + if err != nil { + e.Log.Errorf("Service UpdateSysUser error: %s", err) + return err + } + return nil +} + +// ResetPwd 重置用户密码 +func (e *SysUser) ResetPwd(c *dto.ResetSysUserPwdReq, p *actions.DataPermission) error { + var err error + var model models.SysUser + db := e.Orm.Scopes( + actions.Permission(model.TableName(), p), + ).First(&model, c.GetId()) + if err = db.Error; err != nil { + e.Log.Errorf("At Service ResetSysUserPwd error: %s", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + } + c.Generate(&model) + err = e.Orm.Omit("username", "nick_name", "phone", "role_id", "avatar", "sex").Save(&model).Error + if err != nil { + e.Log.Errorf("At Service ResetSysUserPwd error: %s", err) + return err + } + return nil +} + +// Remove 删除SysUser +func (e *SysUser) Remove(c *dto.SysUserById, p *actions.DataPermission) error { + var err error + var data models.SysUser + + db := e.Orm.Model(&data). + Scopes( + actions.Permission(data.TableName(), p), + ).Delete(&data, c.GetId()) + if err = db.Error; err != nil { + e.Log.Errorf("Error found in RemoveSysUser : %s", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权删除该数据") + } + return nil +} + +// UpdatePwd 修改SysUser对象密码 +func (e *SysUser) UpdatePwd(id int, oldPassword, newPassword string, p *actions.DataPermission) error { + var err error + + if newPassword == "" { + return nil + } + c := &models.SysUser{} + + err = e.Orm.Model(c). + Scopes( + actions.Permission(c.TableName(), p), + ).Select("UserId", "Password", "Salt"). + First(c, id).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return errors.New("无权更新该数据") + } + e.Log.Errorf("db error: %s", err) + return err + } + var ok bool + ok, err = pkg.CompareHashAndPassword(c.Password, oldPassword) + if err != nil { + e.Log.Errorf("CompareHashAndPassword error, %s", err.Error()) + return err + } + if !ok { + err = errors.New("incorrect Password") + e.Log.Warnf("user[%d] %s", id, err.Error()) + return err + } + c.Password = newPassword + db := e.Orm.Model(c).Where("user_id = ?", id). + Select("Password", "Salt"). + Updates(c) + if err = db.Error; err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + if db.RowsAffected == 0 { + err = errors.New("set password error") + log.Warnf("db update error") + return err + } + return nil +} + +func (e *SysUser) GetProfile(c *dto.SysUserById, user *models.SysUser, roles *[]models.SysRole, posts *[]models.SysPost) error { + err := e.Orm.Preload("Dept").First(user, c.GetId()).Error + if err != nil { + return err + } + err = e.Orm.Find(roles, user.RoleId).Error + if err != nil { + return err + } + err = e.Orm.Find(posts, user.PostIds).Error + if err != nil { + return err + } + + return nil +} diff --git a/app/jobs/apis/sys_job.go b/app/jobs/apis/sys_job.go new file mode 100644 index 0000000..296138d --- /dev/null +++ b/app/jobs/apis/sys_job.go @@ -0,0 +1,69 @@ +package apis + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk" + "github.com/go-admin-team/go-admin-core/sdk/api" + + "go-admin/app/jobs/service" + "go-admin/common/dto" +) + +type SysJob struct { + api.Api +} + +// RemoveJobForService 调用service实现 +func (e SysJob) RemoveJobForService(c *gin.Context) { + v := dto.GeneralDelDto{} + s := service.SysJob{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&v). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + return + } + + s.Cron = sdk.Runtime.GetCrontabKey(c.Request.Host) + err = s.RemoveJob(&v) + if err != nil { + e.Logger.Errorf("RemoveJob error, %s", err.Error()) + e.Error(500, err, "") + return + } + e.OK(nil, s.Msg) +} + +// StartJobForService 启动job service实现 +func (e SysJob) StartJobForService(c *gin.Context) { + e.MakeContext(c) + log := e.GetLogger() + db, err := e.GetOrm() + if err != nil { + log.Error(err) + return + } + var v dto.GeneralGetDto + err = c.BindUri(&v) + if err != nil { + log.Warnf("参数验证错误, error: %s", err) + e.Error(http.StatusUnprocessableEntity, err, "参数验证失败") + return + } + s := service.SysJob{} + s.Orm = db + s.Log = log + s.Cron = sdk.Runtime.GetCrontabKey(c.Request.Host) + err = s.StartJob(&v) + if err != nil { + log.Errorf("GetCrontabKey error, %s", err.Error()) + e.Error(500, err, err.Error()) + return + } + e.OK(nil, s.Msg) +} diff --git a/app/jobs/examples.go b/app/jobs/examples.go new file mode 100644 index 0000000..ed233cc --- /dev/null +++ b/app/jobs/examples.go @@ -0,0 +1,40 @@ +package jobs + +import ( + "fmt" + "time" +) + +// InitJob +// 需要将定义的struct 添加到字典中; +// 字典 key 可以配置到 自动任务 调用目标 中; +func InitJob() { + jobList = map[string]JobExec{ + "ExamplesOne": ExamplesOne{}, + // ... + } +} + +// ExamplesOne +// 新添加的job 必须按照以下格式定义,并实现Exec函数 +type ExamplesOne struct { +} + +func (t ExamplesOne) Exec(arg interface{}) error { + str := time.Now().Format(timeFormat) + " [INFO] JobCore ExamplesOne exec success" + // TODO: 这里需要注意 Examples 传入参数是 string 所以 arg.(string);请根据对应的类型进行转化; + switch arg.(type) { + + case string: + if arg.(string) != "" { + fmt.Println("string", arg.(string)) + fmt.Println(str, arg.(string)) + } else { + fmt.Println("arg is nil") + fmt.Println(str, "arg is nil") + } + break + } + + return nil +} diff --git a/app/jobs/jobbase.go b/app/jobs/jobbase.go new file mode 100644 index 0000000..5993b3c --- /dev/null +++ b/app/jobs/jobbase.go @@ -0,0 +1,203 @@ +package jobs + +import ( + "fmt" + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk" + models2 "go-admin/app/jobs/models" + "gorm.io/gorm" + "time" + + "github.com/robfig/cron/v3" + + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "github.com/go-admin-team/go-admin-core/sdk/pkg/cronjob" +) + +var timeFormat = "2006-01-02 15:04:05" +var retryCount = 3 + +var jobList map[string]JobExec + +//var lock sync.Mutex + +type JobCore struct { + InvokeTarget string + Name string + JobId int + EntryId int + CronExpression string + Args string +} + +// HttpJob 任务类型 http +type HttpJob struct { + JobCore +} + +type ExecJob struct { + JobCore +} + +func (e *ExecJob) Run() { + startTime := time.Now() + var obj = jobList[e.InvokeTarget] + if obj == nil { + log.Warn("[Job] ExecJob Run job nil") + return + } + err := CallExec(obj.(JobExec), e.Args) + if err != nil { + // 如果失败暂停一段时间重试 + fmt.Println(time.Now().Format(timeFormat), " [ERROR] mission failed! ", err) + } + // 结束时间 + endTime := time.Now() + + // 执行时间 + latencyTime := endTime.Sub(startTime) + //TODO: 待完善部分 + //str := time.Now().Format(timeFormat) + " [INFO] JobCore " + string(e.EntryId) + "exec success , spend :" + latencyTime.String() + //ws.SendAll(str) + log.Info("[Job] JobCore %s exec success , spend :%v", e.Name, latencyTime) + return +} + +// Run http 任务接口 +func (h *HttpJob) Run() { + + startTime := time.Now() + var count = 0 + var err error + var str string + /* 循环 */ +LOOP: + if count < retryCount { + /* 跳过迭代 */ + str, err = pkg.Get(h.InvokeTarget) + if err != nil { + // 如果失败暂停一段时间重试 + fmt.Println(time.Now().Format(timeFormat), " [ERROR] mission failed! ", err) + fmt.Printf(time.Now().Format(timeFormat)+" [INFO] Retry after the task fails %d seconds! %s \n", (count+1)*5, str) + time.Sleep(time.Duration(count+1) * 5 * time.Second) + count = count + 1 + goto LOOP + } + } + // 结束时间 + endTime := time.Now() + + // 执行时间 + latencyTime := endTime.Sub(startTime) + //TODO: 待完善部分 + + log.Infof("[Job] JobCore %s exec success , spend :%v", h.Name, latencyTime) + return +} + +// Setup 初始化 +func Setup(dbs map[string]*gorm.DB) { + + fmt.Println(time.Now().Format(timeFormat), " [INFO] JobCore Starting...") + + for k, db := range dbs { + sdk.Runtime.SetCrontab(k, cronjob.NewWithSeconds()) + setup(k, db) + } +} + +func setup(key string, db *gorm.DB) { + crontab := sdk.Runtime.GetCrontabKey(key) + sysJob := models2.SysJob{} + jobList := make([]models2.SysJob, 0) + err := sysJob.GetList(db, &jobList) + if err != nil { + fmt.Println(time.Now().Format(timeFormat), " [ERROR] JobCore init error", err) + } + if len(jobList) == 0 { + fmt.Println(time.Now().Format(timeFormat), " [INFO] JobCore total:0") + } + + _, err = sysJob.RemoveAllEntryID(db) + if err != nil { + fmt.Println(time.Now().Format(timeFormat), " [ERROR] JobCore remove entry_id error", err) + } + + for i := 0; i < len(jobList); i++ { + if jobList[i].JobType == 1 { + j := &HttpJob{} + j.InvokeTarget = jobList[i].InvokeTarget + j.CronExpression = jobList[i].CronExpression + j.JobId = jobList[i].JobId + j.Name = jobList[i].JobName + + sysJob.EntryId, err = AddJob(crontab, j) + } else if jobList[i].JobType == 2 { + j := &ExecJob{} + j.InvokeTarget = jobList[i].InvokeTarget + j.CronExpression = jobList[i].CronExpression + j.JobId = jobList[i].JobId + j.Name = jobList[i].JobName + j.Args = jobList[i].Args + sysJob.EntryId, err = AddJob(crontab, j) + } + err = sysJob.Update(db, jobList[i].JobId) + } + + // 其中任务 + crontab.Start() + fmt.Println(time.Now().Format(timeFormat), " [INFO] JobCore start success.") + // 关闭任务 + defer crontab.Stop() + select {} +} + +// AddJob 添加任务 AddJob(invokeTarget string, jobId int, jobName string, cronExpression string) +func AddJob(c *cron.Cron, job Job) (int, error) { + if job == nil { + fmt.Println("unknown") + return 0, nil + } + return job.addJob(c) +} + +func (h *HttpJob) addJob(c *cron.Cron) (int, error) { + id, err := c.AddJob(h.CronExpression, h) + if err != nil { + fmt.Println(time.Now().Format(timeFormat), " [ERROR] JobCore AddJob error", err) + return 0, err + } + EntryId := int(id) + return EntryId, nil +} + +func (e *ExecJob) addJob(c *cron.Cron) (int, error) { + id, err := c.AddJob(e.CronExpression, e) + if err != nil { + fmt.Println(time.Now().Format(timeFormat), " [ERROR] JobCore AddJob error", err) + return 0, err + } + EntryId := int(id) + return EntryId, nil +} + +// Remove 移除任务 +func Remove(c *cron.Cron, entryID int) chan bool { + ch := make(chan bool) + go func() { + c.Remove(cron.EntryID(entryID)) + fmt.Println(time.Now().Format(timeFormat), " [INFO] JobCore Remove success ,info entryID :", entryID) + ch <- true + }() + return ch +} + +// 任务停止 +//func Stop() chan bool { +// ch := make(chan bool) +// go func() { +// global.GADMCron.Stop() +// ch <- true +// }() +// return ch +//} diff --git a/app/jobs/models/sys_job.go b/app/jobs/models/sys_job.go new file mode 100644 index 0000000..a8cc6bf --- /dev/null +++ b/app/jobs/models/sys_job.go @@ -0,0 +1,61 @@ +package models + +import ( + "go-admin/common/models" + "gorm.io/gorm" +) + +type SysJob struct { + JobId int `json:"jobId" gorm:"primaryKey;autoIncrement"` // 编码 + JobName string `json:"jobName" gorm:"size:255;"` // 名称 + JobGroup string `json:"jobGroup" gorm:"size:255;"` // 任务分组 + JobType int `json:"jobType" gorm:"size:1;"` // 任务类型 + CronExpression string `json:"cronExpression" gorm:"size:255;"` // cron表达式 + InvokeTarget string `json:"invokeTarget" gorm:"size:255;"` // 调用目标 + Args string `json:"args" gorm:"size:255;"` // 目标参数 + MisfirePolicy int `json:"misfirePolicy" gorm:"size:255;"` // 执行策略 + Concurrent int `json:"concurrent" gorm:"size:1;"` // 是否并发 + Status int `json:"status" gorm:"size:1;"` // 状态 + EntryId int `json:"entry_id" gorm:"size:11;"` // job启动时返回的id + models.ControlBy + models.ModelTime + + DataScope string `json:"dataScope" gorm:"-"` +} + +func (*SysJob) TableName() string { + return "sys_job" +} + +func (e *SysJob) Generate() models.ActiveRecord { + o := *e + return &o +} + +func (e *SysJob) GetId() interface{} { + return e.JobId +} + +func (e *SysJob) SetCreateBy(createBy int) { + e.CreateBy = createBy +} + +func (e *SysJob) SetUpdateBy(updateBy int) { + e.UpdateBy = updateBy +} + +func (e *SysJob) GetList(tx *gorm.DB, list interface{}) (err error) { + return tx.Table(e.TableName()).Where("status = ?", 2).Find(list).Error +} + +// Update 更新SysJob +func (e *SysJob) Update(tx *gorm.DB, id interface{}) (err error) { + return tx.Table(e.TableName()).Where(id).Updates(&e).Error +} + +func (e *SysJob) RemoveAllEntryID(tx *gorm.DB) (update SysJob, err error) { + if err = tx.Table(e.TableName()).Where("entry_id > ?", 0).Update("entry_id", 0).Error; err != nil { + return + } + return +} diff --git a/app/jobs/router/int_router.go b/app/jobs/router/int_router.go new file mode 100644 index 0000000..ab65faa --- /dev/null +++ b/app/jobs/router/int_router.go @@ -0,0 +1,36 @@ +package router + +import ( + //"github.com/go-admin-team/go-admin-core/sdk/pkg" + "os" + + "github.com/gin-gonic/gin" + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk" + common "go-admin/common/middleware" +) + +// InitRouter 路由初始化,不要怀疑,这里用到了 +func InitRouter() { + var r *gin.Engine + h := sdk.Runtime.GetEngine() + if h == nil { + log.Fatal("not found engine...") + os.Exit(-1) + } + switch h.(type) { + case *gin.Engine: + r = h.(*gin.Engine) + default: + log.Fatal("not support other engine") + os.Exit(-1) + } + + authMiddleware, err := common.AuthInit() + if err != nil { + log.Fatalf("JWT Init Error, %s", err.Error()) + } + + // 注册业务路由 + initRouter(r, authMiddleware) +} diff --git a/app/jobs/router/router.go b/app/jobs/router/router.go new file mode 100644 index 0000000..8c893a2 --- /dev/null +++ b/app/jobs/router/router.go @@ -0,0 +1,42 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" +) + +var ( + routerNoCheckRole = make([]func(*gin.RouterGroup), 0) + routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0) +) + +// initRouter 路由示例 +func initRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine { + + // 无需认证的路由 + noCheckRoleRouter(r) + // 需要认证的路由 + checkRoleRouter(r, authMiddleware) + + return r +} + +// noCheckRoleRouter 无需认证的路由示例 +func noCheckRoleRouter(r *gin.Engine) { + // 可根据业务需求来设置接口版本 + v1 := r.Group("/api/v1") + + for _, f := range routerNoCheckRole { + f(v1) + } +} + +// checkRoleRouter 需要认证的路由示例 +func checkRoleRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) { + // 可根据业务需求来设置接口版本 + v1 := r.Group("/api/v1") + + for _, f := range routerCheckRole { + f(v1, authMiddleware) + } +} diff --git a/app/jobs/router/sys_job.go b/app/jobs/router/sys_job.go new file mode 100644 index 0000000..89723d4 --- /dev/null +++ b/app/jobs/router/sys_job.go @@ -0,0 +1,38 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + "go-admin/app/jobs/apis" + models2 "go-admin/app/jobs/models" + dto2 "go-admin/app/jobs/service/dto" + "go-admin/common/actions" + "go-admin/common/middleware" +) + +func init() { + routerCheckRole = append(routerCheckRole, registerSysJobRouter) +} + +// 需认证的路由代码 +func registerSysJobRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + + r := v1.Group("/sysjob").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + sysJob := &models2.SysJob{} + r.GET("", actions.PermissionAction(), actions.IndexAction(sysJob, new(dto2.SysJobSearch), func() interface{} { + list := make([]models2.SysJob, 0) + return &list + })) + r.GET("/:id", actions.PermissionAction(), actions.ViewAction(new(dto2.SysJobById), func() interface{} { + return &dto2.SysJobItem{} + })) + r.POST("", actions.CreateAction(new(dto2.SysJobControl))) + r.PUT("", actions.PermissionAction(), actions.UpdateAction(new(dto2.SysJobControl))) + r.DELETE("", actions.PermissionAction(), actions.DeleteAction(new(dto2.SysJobById))) + } + sysJob := apis.SysJob{} + + v1.GET("/job/remove/:id", sysJob.RemoveJobForService) + v1.GET("/job/start/:id", sysJob.StartJobForService) +} diff --git a/app/jobs/service/dto/sys_job.go b/app/jobs/service/dto/sys_job.go new file mode 100644 index 0000000..c66bcbd --- /dev/null +++ b/app/jobs/service/dto/sys_job.go @@ -0,0 +1,108 @@ +package dto + +import ( + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk/api" + "go-admin/app/jobs/models" + + "go-admin/common/dto" + common "go-admin/common/models" +) + +type SysJobSearch struct { + dto.Pagination `search:"-"` + JobId int `form:"jobId" search:"type:exact;column:job_id;table:sys_job"` + JobName string `form:"jobName" search:"type:icontains;column:job_name;table:sys_job"` + JobGroup string `form:"jobGroup" search:"type:exact;column:job_group;table:sys_job"` + CronExpression string `form:"cronExpression" search:"type:exact;column:cron_expression;table:sys_job"` + InvokeTarget string `form:"invokeTarget" search:"type:exact;column:invoke_target;table:sys_job"` + Status int `form:"status" search:"type:exact;column:status;table:sys_job"` +} + +func (m *SysJobSearch) GetNeedSearch() interface{} { + return *m +} + +func (m *SysJobSearch) Bind(ctx *gin.Context) error { + log := api.GetRequestLogger(ctx) + err := ctx.ShouldBind(m) + if err != nil { + log.Errorf("Bind error: %s", err) + } + return err +} + +func (m *SysJobSearch) Generate() dto.Index { + o := *m + return &o +} + +type SysJobControl struct { + JobId int `json:"jobId"` + JobName string `json:"jobName" validate:"required"` // 名称 + JobGroup string `json:"jobGroup"` // 任务分组 + JobType int `json:"jobType"` // 任务类型 + CronExpression string `json:"cronExpression"` // cron表达式 + InvokeTarget string `json:"invokeTarget"` // 调用目标 + Args string `json:"args"` // 目标参数 + MisfirePolicy int `json:"misfirePolicy"` // 执行策略 + Concurrent int `json:"concurrent"` // 是否并发 + Status int `json:"status"` // 状态 + EntryId int `json:"entryId"` // job启动时返回的id +} + +func (s *SysJobControl) Bind(ctx *gin.Context) error { + return ctx.ShouldBind(s) +} + +func (s *SysJobControl) Generate() dto.Control { + cp := *s + return &cp +} + +func (s *SysJobControl) GenerateM() (common.ActiveRecord, error) { + return &models.SysJob{ + JobId: s.JobId, + JobName: s.JobName, + JobGroup: s.JobGroup, + JobType: s.JobType, + CronExpression: s.CronExpression, + InvokeTarget: s.InvokeTarget, + Args: s.Args, + MisfirePolicy: s.MisfirePolicy, + Concurrent: s.Concurrent, + Status: s.Status, + EntryId: s.EntryId, + }, nil +} + +func (s *SysJobControl) GetId() interface{} { + return s.JobId +} + +type SysJobById struct { + dto.ObjectById +} + +func (s *SysJobById) Generate() dto.Control { + cp := *s + return &cp +} + +func (s *SysJobById) GenerateM() (common.ActiveRecord, error) { + return &models.SysJob{}, nil +} + +type SysJobItem struct { + JobId int `json:"jobId"` + JobName string `json:"jobName" validate:"required"` // 名称 + JobGroup string `json:"jobGroup"` // 任务分组 + JobType int `json:"jobType"` // 任务类型 + CronExpression string `json:"cronExpression"` // cron表达式 + InvokeTarget string `json:"invokeTarget"` // 调用目标 + Args string `json:"args"` // 目标参数 + MisfirePolicy int `json:"misfirePolicy"` // 执行策略 + Concurrent int `json:"concurrent"` // 是否并发 + Status int `json:"status"` // 状态 + EntryId int `json:"entryId"` // job启动时返回的id +} diff --git a/app/jobs/service/sys_job.go b/app/jobs/service/sys_job.go new file mode 100644 index 0000000..a1ab810 --- /dev/null +++ b/app/jobs/service/sys_job.go @@ -0,0 +1,93 @@ +package service + +import ( + "errors" + "time" + + "github.com/go-admin-team/go-admin-core/sdk/service" + "github.com/robfig/cron/v3" + + "go-admin/app/jobs" + "go-admin/app/jobs/models" + "go-admin/common/dto" +) + +type SysJob struct { + service.Service + Cron *cron.Cron +} + +// RemoveJob 删除job +func (e *SysJob) RemoveJob(c *dto.GeneralDelDto) error { + var err error + var data models.SysJob + err = e.Orm.Table(data.TableName()).First(&data, c.Id).Error + if err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + cn := jobs.Remove(e.Cron, data.EntryId) + + select { + case res := <-cn: + if res { + err = e.Orm.Table(data.TableName()).Where("entry_id = ?", data.EntryId).Update("entry_id", 0).Error + if err != nil { + e.Log.Errorf("db error: %s", err) + } + return err + } + case <-time.After(time.Second * 1): + e.Msg = "操作超时!" + return nil + } + return nil +} + +// StartJob 启动任务 +func (e *SysJob) StartJob(c *dto.GeneralGetDto) error { + var data models.SysJob + var err error + err = e.Orm.Table(data.TableName()).First(&data, c.Id).Error + if err != nil { + e.Log.Errorf("db error: %s", err) + return err + } + + if data.Status == 1 { + err = errors.New("当前Job是关闭状态不能被启动,请先启用。") + return err + } + + if data.JobType == 1 { + var j = &jobs.HttpJob{} + j.InvokeTarget = data.InvokeTarget + j.CronExpression = data.CronExpression + j.JobId = data.JobId + j.Name = data.JobName + data.EntryId, err = jobs.AddJob(e.Cron, j) + if err != nil { + e.Log.Errorf("jobs AddJob[HttpJob] error: %s", err) + } + } else { + var j = &jobs.ExecJob{} + j.InvokeTarget = data.InvokeTarget + j.CronExpression = data.CronExpression + j.JobId = data.JobId + j.Name = data.JobName + j.Args = data.Args + data.EntryId, err = jobs.AddJob(e.Cron, j) + if err != nil { + e.Log.Errorf("jobs AddJob[ExecJob] error: %s", err) + } + } + if err != nil { + return err + } + + err = e.Orm.Table(data.TableName()).Where(c.Id).Updates(&data).Error + if err != nil { + e.Log.Errorf("db error: %s", err) + } + return err +} diff --git a/app/jobs/type.go b/app/jobs/type.go new file mode 100644 index 0000000..1b5c30b --- /dev/null +++ b/app/jobs/type.go @@ -0,0 +1,16 @@ +package jobs + +import "github.com/robfig/cron/v3" + +type Job interface { + Run() + addJob(*cron.Cron) (int, error) +} + +type JobExec interface { + Exec(arg interface{}) error +} + +func CallExec(e JobExec, arg interface{}) error { + return e.Exec(arg) +} diff --git a/app/other/apis/file.go b/app/other/apis/file.go new file mode 100644 index 0000000..e0d77f4 --- /dev/null +++ b/app/other/apis/file.go @@ -0,0 +1,204 @@ +package apis + +import ( + "encoding/base64" + "errors" + "fmt" + "io/ioutil" + "strings" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "github.com/go-admin-team/go-admin-core/sdk/pkg/utils" + "github.com/google/uuid" + + "go-admin/common/file_store" +) + +type FileResponse struct { + Size int64 `json:"size"` + Path string `json:"path"` + FullPath string `json:"full_path"` + Name string `json:"name"` + Type string `json:"type"` +} + +const path = "static/uploadfile/" + +type File struct { + api.Api +} + +// UploadFile 上传图片 +// @Summary 上传图片 +// @Description 获取JSON +// @Tags 公共接口 +// @Accept multipart/form-data +// @Param type query string true "type" (1:单图,2:多图, 3:base64图片) +// @Param file formData file true "file" +// @Success 200 {string} string "{"code": 200, "message": "添加成功"}" +// @Success 200 {string} string "{"code": -1, "message": "添加失败"}" +// @Router /api/v1/public/uploadFile [post] +// @Security Bearer +func (e File) UploadFile(c *gin.Context) { + e.MakeContext(c) + tag, _ := c.GetPostForm("type") + urlPrefix := fmt.Sprintf("%s://%s/", "http", c.Request.Host) + var fileResponse FileResponse + + switch tag { + case "1": // 单图 + var done bool + fileResponse, done = e.singleFile(c, fileResponse, urlPrefix) + if done { + return + } + e.OK(fileResponse, "上传成功") + return + case "2": // 多图 + multipartFile := e.multipleFile(c, urlPrefix) + e.OK(multipartFile, "上传成功") + return + case "3": // base64 + fileResponse = e.baseImg(c, fileResponse, urlPrefix) + e.OK(fileResponse, "上传成功") + default: + var done bool + fileResponse, done = e.singleFile(c, fileResponse, urlPrefix) + if done { + return + } + e.OK(fileResponse, "上传成功") + return + } + +} + +func (e File) baseImg(c *gin.Context, fileResponse FileResponse, urlPerfix string) FileResponse { + files, _ := c.GetPostForm("file") + file2list := strings.Split(files, ",") + ddd, _ := base64.StdEncoding.DecodeString(file2list[1]) + guid := uuid.New().String() + fileName := guid + ".jpg" + err := utils.IsNotExistMkDir(path) + if err != nil { + e.Error(500, errors.New(""), "初始化文件路径失败") + } + base64File := path + fileName + _ = ioutil.WriteFile(base64File, ddd, 0666) + typeStr := strings.Replace(strings.Replace(file2list[0], "data:", "", -1), ";base64", "", -1) + fileResponse = FileResponse{ + Size: pkg.GetFileSize(base64File), + Path: base64File, + FullPath: urlPerfix + base64File, + Name: "", + Type: typeStr, + } + source, _ := c.GetPostForm("source") + err = thirdUpload(source, fileName, base64File) + if err != nil { + e.Error(200, errors.New(""), "上传第三方失败") + return fileResponse + } + if source != "1" { + fileResponse.Path = "/static/uploadfile/" + fileName + fileResponse.FullPath = "/static/uploadfile/" + fileName + } + return fileResponse +} + +func (e File) multipleFile(c *gin.Context, urlPerfix string) []FileResponse { + files := c.Request.MultipartForm.File["file"] + source, _ := c.GetPostForm("source") + var multipartFile []FileResponse + for _, f := range files { + guid := uuid.New().String() + fileName := guid + utils.GetExt(f.Filename) + + err := utils.IsNotExistMkDir(path) + if err != nil { + e.Error(500, errors.New(""), "初始化文件路径失败") + } + multipartFileName := path + fileName + err1 := c.SaveUploadedFile(f, multipartFileName) + fileType, _ := utils.GetType(multipartFileName) + if err1 == nil { + err := thirdUpload(source, fileName, multipartFileName) + if err != nil { + e.Error(500, errors.New(""), "上传第三方失败") + } else { + fileResponse := FileResponse{ + Size: pkg.GetFileSize(multipartFileName), + Path: multipartFileName, + FullPath: urlPerfix + multipartFileName, + Name: f.Filename, + Type: fileType, + } + if source != "1" { + fileResponse.Path = "/static/uploadfile/" + fileName + fileResponse.FullPath = "/static/uploadfile/" + fileName + } + multipartFile = append(multipartFile, fileResponse) + } + } + } + return multipartFile +} + +func (e File) singleFile(c *gin.Context, fileResponse FileResponse, urlPerfix string) (FileResponse, bool) { + files, err := c.FormFile("file") + + if err != nil { + e.Error(200, errors.New(""), "图片不能为空") + return FileResponse{}, true + } + // 上传文件至指定目录 + guid := uuid.New().String() + + fileName := guid + utils.GetExt(files.Filename) + + err = utils.IsNotExistMkDir(path) + if err != nil { + e.Error(500, errors.New(""), "初始化文件路径失败") + } + singleFile := path + fileName + _ = c.SaveUploadedFile(files, singleFile) + fileType, _ := utils.GetType(singleFile) + fileResponse = FileResponse{ + Size: pkg.GetFileSize(singleFile), + Path: singleFile, + FullPath: urlPerfix + singleFile, + Name: files.Filename, + Type: fileType, + } + //source, _ := c.GetPostForm("source") + //err = thirdUpload(source, fileName, singleFile) + //if err != nil { + // e.Error(200, errors.New(""), "上传第三方失败") + // return FileResponse{}, true + //} + fileResponse.Path = "/static/uploadfile/" + fileName + fileResponse.FullPath = "/static/uploadfile/" + fileName + return fileResponse, false +} + +func thirdUpload(source string, name string, path string) error { + switch source { + case "2": + return ossUpload("img/"+name, path) + case "3": + return qiniuUpload("img/"+name, path) + } + return nil +} + +func ossUpload(name string, path string) error { + oss := file_store.ALiYunOSS{} + return oss.UpLoad(name, path) +} + +func qiniuUpload(name string, path string) error { + oss := file_store.ALiYunOSS{} + return oss.UpLoad(name, path) +} diff --git a/app/other/apis/sys_server_monitor.go b/app/other/apis/sys_server_monitor.go new file mode 100644 index 0000000..c9aee1d --- /dev/null +++ b/app/other/apis/sys_server_monitor.go @@ -0,0 +1,186 @@ +package apis + +import ( + "fmt" + "github.com/shirou/gopsutil/v3/net" + "runtime" + "strconv" + "strings" + "time" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + "github.com/shirou/gopsutil/v3/cpu" + "github.com/shirou/gopsutil/v3/disk" + "github.com/shirou/gopsutil/v3/host" + "github.com/shirou/gopsutil/v3/mem" +) + +const ( + B = 1 + KB = 1024 * B + MB = 1024 * KB + GB = 1024 * MB +) + +var ( + //Version string + //expectDiskFsTypes = []string{ + // "apfs", "ext4", "ext3", "ext2", "f2fs", "reiserfs", "jfs", "btrfs", + // "fuseblk", "zfs", "simfs", "ntfs", "fat32", "exfat", "xfs", "fuse.rclone", + //} + excludeNetInterfaces = []string{ + "lo", "tun", "docker", "veth", "br-", "vmbr", "vnet", "kube", + } + //getMacDiskNo = regexp.MustCompile(`\/dev\/disk(\d)s.*`) +) + +var ( + netInSpeed, netOutSpeed, netInTransfer, netOutTransfer, lastUpdateNetStats uint64 + cachedBootTime time.Time +) + +type ServerMonitor struct { + api.Api +} + +// GetHourDiffer 获取相差时间 +func GetHourDiffer(startTime, endTime string) int64 { + var hour int64 + t1, err := time.ParseInLocation("2006-01-02 15:04:05", startTime, time.Local) + t2, err := time.ParseInLocation("2006-01-02 15:04:05", endTime, time.Local) + if err == nil && t1.Before(t2) { + diff := t2.Unix() - t1.Unix() // + hour = diff / 3600 + return hour + } else { + return hour + } +} + +// ServerInfo 获取系统信息 +// @Summary 系统信息 +// @Description 获取JSON +// @Tags 系统信息 +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/server-monitor [get] +// @Security Bearer +func (e ServerMonitor) ServerInfo(c *gin.Context) { + e.Context = c + + sysInfo, err := host.Info() + osDic := make(map[string]interface{}, 0) + osDic["goOs"] = runtime.GOOS + osDic["arch"] = runtime.GOARCH + osDic["mem"] = runtime.MemProfileRate + osDic["compiler"] = runtime.Compiler + osDic["version"] = runtime.Version() + osDic["numGoroutine"] = runtime.NumGoroutine() + osDic["ip"] = pkg.GetLocaHonst() + osDic["projectDir"] = pkg.GetCurrentPath() + osDic["hostName"] = sysInfo.Hostname + osDic["time"] = time.Now().Format("2006-01-02 15:04:05") + + memory, _ := mem.VirtualMemory() + memDic := make(map[string]interface{}, 0) + memDic["used"] = memory.Used / MB + memDic["total"] = memory.Total / MB + + fmt.Println("mem", int(memory.Total/memory.Used*100)) + memDic["percent"] = pkg.Round(memory.UsedPercent, 2) + + swapDic := make(map[string]interface{}, 0) + swapDic["used"] = memory.SwapTotal - memory.SwapFree + swapDic["total"] = memory.SwapTotal + + cpuDic := make(map[string]interface{}, 0) + cpuDic["cpuInfo"], _ = cpu.Info() + percent, _ := cpu.Percent(0, false) + cpuDic["percent"] = pkg.Round(percent[0], 2) + cpuDic["cpuNum"], _ = cpu.Counts(false) + + //服务器磁盘信息 + disklist := make([]disk.UsageStat, 0) + //所有分区 + var diskTotal, diskUsed, diskUsedPercent float64 + diskInfo, err := disk.Partitions(true) + if err == nil { + for _, p := range diskInfo { + diskDetail, err := disk.Usage(p.Mountpoint) + if err == nil { + diskDetail.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", diskDetail.UsedPercent), 64) + diskDetail.Total = diskDetail.Total / 1024 / 1024 + diskDetail.Used = diskDetail.Used / 1024 / 1024 + diskDetail.Free = diskDetail.Free / 1024 / 1024 + disklist = append(disklist, *diskDetail) + + } + } + } + + d, _ := disk.Usage("/") + + diskTotal = float64(d.Total / GB) + diskUsed = float64(d.Used / GB) + diskUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", d.UsedPercent), 64) + + diskDic := make(map[string]interface{}, 0) + diskDic["total"] = diskTotal + diskDic["used"] = diskUsed + diskDic["percent"] = diskUsedPercent + + bootTime, _ := host.BootTime() + cachedBootTime = time.Unix(int64(bootTime), 0) + + TrackNetworkSpeed() + netDic := make(map[string]interface{}, 0) + netDic["in"] = pkg.Round(float64(netInSpeed/KB), 2) + netDic["out"] = pkg.Round(float64(netOutSpeed/KB), 2) + e.Custom(gin.H{ + "code": 200, + "os": osDic, + "mem": memDic, + "cpu": cpuDic, + "disk": diskDic, + "net": netDic, + "swap": swapDic, + "location": "Aliyun", + "bootTime": GetHourDiffer(cachedBootTime.Format("2006-01-02 15:04:05"), time.Now().Format("2006-01-02 15:04:05")), + }) +} + +func TrackNetworkSpeed() { + var innerNetInTransfer, innerNetOutTransfer uint64 + nc, err := net.IOCounters(true) + if err == nil { + for _, v := range nc { + if isListContainsStr(excludeNetInterfaces, v.Name) { + continue + } + innerNetInTransfer += v.BytesRecv + innerNetOutTransfer += v.BytesSent + } + now := uint64(time.Now().Unix()) + diff := now - lastUpdateNetStats + if diff > 0 { + netInSpeed = (innerNetInTransfer - netInTransfer) / diff + fmt.Println("netInSpeed", netInSpeed) + netOutSpeed = (innerNetOutTransfer - netOutTransfer) / diff + fmt.Println("netOutSpeed", netOutSpeed) + } + netInTransfer = innerNetInTransfer + netOutTransfer = innerNetOutTransfer + lastUpdateNetStats = now + } +} + +func isListContainsStr(list []string, str string) bool { + for i := 0; i < len(list); i++ { + if strings.Contains(str, list[i]) { + return true + } + } + return false +} diff --git a/app/other/apis/tools/db_columns.go b/app/other/apis/tools/db_columns.go new file mode 100644 index 0000000..e0b8390 --- /dev/null +++ b/app/other/apis/tools/db_columns.go @@ -0,0 +1,52 @@ +package tools + +import ( + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + + "go-admin/app/other/models/tools" +) + +// GetDBColumnList 分页列表数据 +// @Summary 分页列表数据 / page list data +// @Description 数据库表列分页列表 / database table column page list +// @Tags 工具 / 生成工具 +// @Param tableName query string false "tableName / 数据表名称" +// @Param pageSize query int false "pageSize / 页条数" +// @Param pageIndex query int false "pageIndex / 页码" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/db/columns/page [get] +func (e Gen) GetDBColumnList(c *gin.Context) { + e.Context = c + log := e.GetLogger() + var data tools.DBColumns + var err error + var pageSize = 10 + var pageIndex = 1 + + if size := c.Request.FormValue("pageSize"); size != "" { + pageSize, err = pkg.StringToInt(size) + } + + if index := c.Request.FormValue("pageIndex"); index != "" { + pageIndex, err = pkg.StringToInt(index) + } + + db, err := pkg.GetOrm(c) + if err != nil { + log.Errorf("get db connection error, %s", err.Error()) + e.Error(500, err, "数据库连接获取失败") + return + } + + data.TableName = c.Request.FormValue("tableName") + pkg.Assert(data.TableName == "", "table name cannot be empty!", 500) + result, count, err := data.GetPage(db, pageSize, pageIndex) + if err != nil { + log.Errorf("GetPage error, %s", err.Error()) + e.Error(500, err, "") + return + } + e.PageOK(result, count, pageIndex, pageSize, "查询成功") +} diff --git a/app/other/apis/tools/db_tables.go b/app/other/apis/tools/db_tables.go new file mode 100644 index 0000000..d1ec3c4 --- /dev/null +++ b/app/other/apis/tools/db_tables.go @@ -0,0 +1,60 @@ +package tools + +import ( + "errors" + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk/config" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + + "go-admin/app/other/models/tools" +) + +// GetDBTableList 分页列表数据 +// @Summary 分页列表数据 / page list data +// @Description 数据库表分页列表 / database table page list +// @Tags 工具 / 生成工具 +// @Param tableName query string false "tableName / 数据表名称" +// @Param pageSize query int false "pageSize / 页条数" +// @Param pageIndex query int false "pageIndex / 页码" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/db/tables/page [get] +func (e Gen) GetDBTableList(c *gin.Context) { + //var res response.Response + var data tools.DBTables + var err error + var pageSize = 10 + var pageIndex = 1 + e.Context = c + log := e.GetLogger() + if config.DatabaseConfig.Driver == "sqlite3" || config.DatabaseConfig.Driver == "postgres" { + err = errors.New("对不起,sqlite3 或 postgres 不支持代码生成!") + log.Warn(err) + e.Error(403, err, "") + return + } + + if size := c.Request.FormValue("pageSize"); size != "" { + pageSize, err = pkg.StringToInt(size) + } + + if index := c.Request.FormValue("pageIndex"); index != "" { + pageIndex, err = pkg.StringToInt(index) + } + + db, err := pkg.GetOrm(c) + if err != nil { + log.Errorf("get db connection error, %s", err.Error()) + e.Error(500, err, "数据库连接获取失败") + return + } + + data.TableName = c.Request.FormValue("tableName") + result, count, err := data.GetPage(db, pageSize, pageIndex) + if err != nil { + log.Errorf("GetPage error, %s", err.Error()) + e.Error(500, err, "") + return + } + e.PageOK(result, count, pageIndex, pageSize, "查询成功") +} diff --git a/app/other/apis/tools/gen.go b/app/other/apis/tools/gen.go new file mode 100644 index 0000000..e9baafc --- /dev/null +++ b/app/other/apis/tools/gen.go @@ -0,0 +1,410 @@ +package tools + +import ( + "bytes" + "fmt" + "go-admin/app/admin/service" + "go-admin/app/admin/service/dto" + "strconv" + "strings" + "text/template" + "time" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/config" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + + "go-admin/app/other/models/tools" +) + +type Gen struct { + api.Api +} + +func (e Gen) Preview(c *gin.Context) { + e.Context = c + log := e.GetLogger() + table := tools.SysTables{} + id, err := pkg.StringToInt(c.Param("tableId")) + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("tableId接收失败!错误详情:%s", err.Error())) + return + } + table.TableId = id + t1, err := template.ParseFiles("template/v4/model.go.template") + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("model模版读取失败!错误详情:%s", err.Error())) + return + } + t2, err := template.ParseFiles("template/v4/no_actions/apis.go.template") + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("api模版读取失败!错误详情:%s", err.Error())) + return + } + t3, err := template.ParseFiles("template/v4/js.go.template") + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("js模版读取失败!错误详情:%s", err.Error())) + return + } + t4, err := template.ParseFiles("template/v4/vue.go.template") + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("vue模版读取失败!错误详情:%s", err.Error())) + return + } + t5, err := template.ParseFiles("template/v4/no_actions/router_check_role.go.template") + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("路由模版读取失败!错误详情:%s", err.Error())) + return + } + t6, err := template.ParseFiles("template/v4/dto.go.template") + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("dto模版读取失败!错误详情:%s", err.Error())) + return + } + t7, err := template.ParseFiles("template/v4/no_actions/service.go.template") + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("service模版读取失败!错误详情:%s", err.Error())) + return + } + + db, err := pkg.GetOrm(c) + if err != nil { + log.Errorf("get db connection error, %s", err.Error()) + e.Error(500, err, fmt.Sprintf("数据库链接获取失败!错误详情:%s", err.Error())) + return + } + + tab, _ := table.Get(db,false) + var b1 bytes.Buffer + err = t1.Execute(&b1, tab) + var b2 bytes.Buffer + err = t2.Execute(&b2, tab) + var b3 bytes.Buffer + err = t3.Execute(&b3, tab) + var b4 bytes.Buffer + err = t4.Execute(&b4, tab) + var b5 bytes.Buffer + err = t5.Execute(&b5, tab) + var b6 bytes.Buffer + err = t6.Execute(&b6, tab) + var b7 bytes.Buffer + err = t7.Execute(&b7, tab) + + mp := make(map[string]interface{}) + mp["template/model.go.template"] = b1.String() + mp["template/api.go.template"] = b2.String() + mp["template/js.go.template"] = b3.String() + mp["template/vue.go.template"] = b4.String() + mp["template/router.go.template"] = b5.String() + mp["template/dto.go.template"] = b6.String() + mp["template/service.go.template"] = b7.String() + e.OK(mp, "") +} + +func (e Gen) GenCode(c *gin.Context) { + e.Context = c + log := e.GetLogger() + table := tools.SysTables{} + id, err := pkg.StringToInt(c.Param("tableId")) + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("tableId参数接收失败!错误详情:%s", err.Error())) + return + } + + db, err := pkg.GetOrm(c) + if err != nil { + log.Errorf("get db connection error, %s", err.Error()) + e.Error(500, err, fmt.Sprintf("数据库链接获取失败!错误详情:%s", err.Error())) + return + } + + table.TableId = id + tab, _ := table.Get(db,false) + + e.NOActionsGen(c, tab) + + e.OK("", "Code generated successfully!") +} + +func (e Gen) GenApiToFile(c *gin.Context) { + e.Context = c + log := e.GetLogger() + table := tools.SysTables{} + id, err := pkg.StringToInt(c.Param("tableId")) + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("tableId参数获取失败!错误详情:%s", err.Error())) + return + } + + db, err := pkg.GetOrm(c) + if err != nil { + log.Errorf("get db connection error, %s", err.Error()) + e.Error(500, err, fmt.Sprintf("数据库链接获取失败!错误详情:%s", err.Error())) + return + } + + table.TableId = id + tab, _ := table.Get(db,false) + e.genApiToFile(c, tab) + + e.OK("", "Code generated successfully!") +} + +func (e Gen) NOActionsGen(c *gin.Context, tab tools.SysTables) { + e.Context = c + log := e.GetLogger() + tab.MLTBName = strings.Replace(tab.TBName, "_", "-", -1) + + basePath := "template/v4/" + routerFile := basePath + "no_actions/router_check_role.go.template" + + if tab.IsAuth == 2 { + routerFile = basePath + "no_actions/router_no_check_role.go.template" + } + + t1, err := template.ParseFiles(basePath + "model.go.template") + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("model模版读取失败!错误详情:%s", err.Error())) + return + } + t2, err := template.ParseFiles(basePath + "no_actions/apis.go.template") + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("api模版读取失败!错误详情:%s", err.Error())) + return + } + t3, err := template.ParseFiles(routerFile) + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("路由模版失败!错误详情:%s", err.Error())) + return + } + t4, err := template.ParseFiles(basePath + "js.go.template") + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("js模版解析失败!错误详情:%s", err.Error())) + return + } + t5, err := template.ParseFiles(basePath + "vue.go.template") + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("vue模版解析失败!错误详情:%s", err.Error())) + return + } + t6, err := template.ParseFiles(basePath + "dto.go.template") + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("dto模版解析失败失败!错误详情:%s", err.Error())) + return + } + t7, err := template.ParseFiles(basePath + "no_actions/service.go.template") + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("service模版失败!错误详情:%s", err.Error())) + return + } + + _ = pkg.PathCreate("./app/" + tab.PackageName + "/apis/") + _ = pkg.PathCreate("./app/" + tab.PackageName + "/models/") + _ = pkg.PathCreate("./app/" + tab.PackageName + "/router/") + _ = pkg.PathCreate("./app/" + tab.PackageName + "/service/dto/") + _ = pkg.PathCreate(config.GenConfig.FrontPath + "/api/" + tab.PackageName + "/") + err = pkg.PathCreate(config.GenConfig.FrontPath + "/views/" + tab.PackageName + "/" + tab.MLTBName + "/") + if err != nil { + log.Error(err) + e.Error(500, err, fmt.Sprintf("views目录创建失败!错误详情:%s", err.Error())) + return + } + + var b1 bytes.Buffer + err = t1.Execute(&b1, tab) + var b2 bytes.Buffer + err = t2.Execute(&b2, tab) + var b3 bytes.Buffer + err = t3.Execute(&b3, tab) + var b4 bytes.Buffer + err = t4.Execute(&b4, tab) + var b5 bytes.Buffer + err = t5.Execute(&b5, tab) + var b6 bytes.Buffer + err = t6.Execute(&b6, tab) + var b7 bytes.Buffer + err = t7.Execute(&b7, tab) + pkg.FileCreate(b1, "./app/"+tab.PackageName+"/models/"+tab.TBName+".go") + pkg.FileCreate(b2, "./app/"+tab.PackageName+"/apis/"+tab.TBName+".go") + pkg.FileCreate(b3, "./app/"+tab.PackageName+"/router/"+tab.TBName+".go") + pkg.FileCreate(b4, config.GenConfig.FrontPath+"/api/"+tab.PackageName+"/"+tab.MLTBName+".js") + pkg.FileCreate(b5, config.GenConfig.FrontPath+"/views/"+tab.PackageName+"/"+tab.MLTBName+"/index.vue") + pkg.FileCreate(b6, "./app/"+tab.PackageName+"/service/dto/"+tab.TBName+".go") + pkg.FileCreate(b7, "./app/"+tab.PackageName+"/service/"+tab.TBName+".go") + +} + +func (e Gen) genApiToFile(c *gin.Context, tab tools.SysTables) { + err := e.MakeContext(c). + MakeOrm(). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + basePath := "template/" + + t1, err := template.ParseFiles(basePath + "api_migrate.template") + if err != nil { + e.Logger.Error(err) + e.Error(500, err, fmt.Sprintf("数据迁移模版解析失败!错误详情:%s", err.Error())) + return + } + i := strconv.FormatInt(time.Now().UnixNano()/1e6, 10) + var b1 bytes.Buffer + err = t1.Execute(&b1, struct { + tools.SysTables + GenerateTime string + }{tab, i}) + + pkg.FileCreate(b1, "./cmd/migrate/migration/version-local/"+i+"_migrate.go") + +} + +func (e Gen) GenMenuAndApi(c *gin.Context) { + s := service.SysMenu{} + err := e.MakeContext(c). + MakeOrm(). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + table := tools.SysTables{} + id, err := pkg.StringToInt(c.Param("tableId")) + if err != nil { + e.Logger.Error(err) + e.Error(500, err, fmt.Sprintf("tableId参数解析失败!错误详情:%s", err.Error())) + return + } + + table.TableId = id + tab, _ := table.Get(e.Orm,true) + tab.MLTBName = strings.Replace(tab.TBName, "_", "-", -1) + + Mmenu := dto.SysMenuInsertReq{} + Mmenu.Title = tab.TableComment + Mmenu.Icon = "pass" + Mmenu.Path = "/" + tab.MLTBName + Mmenu.MenuType = "M" + Mmenu.Action = "无" + Mmenu.ParentId = 0 + Mmenu.NoCache = false + Mmenu.Component = "Layout" + Mmenu.Sort = 0 + Mmenu.Visible = "0" + Mmenu.IsFrame = "0" + Mmenu.CreateBy = 1 + s.Insert(&Mmenu) + + Cmenu := dto.SysMenuInsertReq{} + Cmenu.MenuName = tab.ClassName + "Manage" + Cmenu.Title = tab.TableComment + Cmenu.Icon = "pass" + Cmenu.Path = "/" + tab.PackageName + "/" + tab.MLTBName + Cmenu.MenuType = "C" + Cmenu.Action = "无" + Cmenu.Permission = tab.PackageName + ":" + tab.BusinessName + ":list" + Cmenu.ParentId = Mmenu.MenuId + Cmenu.NoCache = false + Cmenu.Component = "/" + tab.PackageName + "/" + tab.MLTBName + "/index" + Cmenu.Sort = 0 + Cmenu.Visible = "0" + Cmenu.IsFrame = "0" + Cmenu.CreateBy = 1 + Cmenu.UpdateBy = 1 + s.Insert(&Cmenu) + + MList := dto.SysMenuInsertReq{} + MList.MenuName = "" + MList.Title = "分页获取" + tab.TableComment + MList.Icon = "" + MList.Path = tab.TBName + MList.MenuType = "F" + MList.Action = "无" + MList.Permission = tab.PackageName + ":" + tab.BusinessName + ":query" + MList.ParentId = Cmenu.MenuId + MList.NoCache = false + MList.Sort = 0 + MList.Visible = "0" + MList.IsFrame = "0" + MList.CreateBy = 1 + MList.UpdateBy = 1 + s.Insert(&MList) + + MCreate := dto.SysMenuInsertReq{} + MCreate.MenuName = "" + MCreate.Title = "创建" + tab.TableComment + MCreate.Icon = "" + MCreate.Path = tab.TBName + MCreate.MenuType = "F" + MCreate.Action = "无" + MCreate.Permission = tab.PackageName + ":" + tab.BusinessName + ":add" + MCreate.ParentId = Cmenu.MenuId + MCreate.NoCache = false + MCreate.Sort = 0 + MCreate.Visible = "0" + MCreate.IsFrame = "0" + MCreate.CreateBy = 1 + MCreate.UpdateBy = 1 + s.Insert(&MCreate) + + MUpdate := dto.SysMenuInsertReq{} + MUpdate.MenuName = "" + MUpdate.Title = "修改" + tab.TableComment + MUpdate.Icon = "" + MUpdate.Path = tab.TBName + MUpdate.MenuType = "F" + MUpdate.Action = "无" + MUpdate.Permission = tab.PackageName + ":" + tab.BusinessName + ":edit" + MUpdate.ParentId = Cmenu.MenuId + MUpdate.NoCache = false + MUpdate.Sort = 0 + MUpdate.Visible = "0" + MUpdate.IsFrame = "0" + MUpdate.CreateBy = 1 + MUpdate.UpdateBy = 1 + s.Insert(&MUpdate) + + MDelete := dto.SysMenuInsertReq{} + MDelete.MenuName = "" + MDelete.Title = "删除" + tab.TableComment + MDelete.Icon = "" + MDelete.Path = tab.TBName + MDelete.MenuType = "F" + MDelete.Action = "无" + MDelete.Permission = tab.PackageName + ":" + tab.BusinessName + ":remove" + MDelete.ParentId = Cmenu.MenuId + MDelete.NoCache = false + MDelete.Sort = 0 + MDelete.Visible = "0" + MDelete.IsFrame = "0" + MDelete.CreateBy = 1 + MDelete.UpdateBy = 1 + s.Insert(&MDelete) + + e.OK("", "数据生成成功!") +} diff --git a/app/other/apis/tools/sys_tables.go b/app/other/apis/tools/sys_tables.go new file mode 100644 index 0000000..ea7dee7 --- /dev/null +++ b/app/other/apis/tools/sys_tables.go @@ -0,0 +1,361 @@ +package tools + +import ( + "strings" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + "gorm.io/gorm" + + "go-admin/app/other/models/tools" +) + +type SysTable struct { + api.Api +} + +// GetPage 分页列表数据 +// @Summary 分页列表数据 +// @Description 生成表分页列表 +// @Tags 工具 / 生成工具 +// @Param tableName query string false "tableName / 数据表名称" +// @Param pageSize query int false "pageSize / 页条数" +// @Param pageIndex query int false "pageIndex / 页码" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/sys/tables/page [get] +func (e SysTable) GetPage(c *gin.Context) { + e.Context = c + log := e.GetLogger() + var data tools.SysTables + var err error + var pageSize = 10 + var pageIndex = 1 + + if size := c.Request.FormValue("pageSize"); size != "" { + pageSize, err = pkg.StringToInt(size) + } + + if index := c.Request.FormValue("pageIndex"); index != "" { + pageIndex, err = pkg.StringToInt(index) + } + + db, err := e.GetOrm() + if err != nil { + log.Errorf("get db connection error, %s", err.Error()) + e.Error(500, err, "数据库连接获取失败") + return + } + + data.TBName = c.Request.FormValue("tableName") + data.TableComment = c.Request.FormValue("tableComment") + result, count, err := data.GetPage(db, pageSize, pageIndex) + if err != nil { + log.Errorf("GetPage error, %s", err.Error()) + e.Error(500, err, "") + return + } + e.PageOK(result, count, pageIndex, pageSize, "查询成功") +} + +// Get +// @Summary 获取配置 +// @Description 获取JSON +// @Tags 工具 / 生成工具 +// @Param configKey path int true "configKey" +// @Success 200 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/sys/tables/info/{tableId} [get] +// @Security Bearer +func (e SysTable) Get(c *gin.Context) { + e.Context = c + log := e.GetLogger() + db, err := e.GetOrm() + if err != nil { + log.Errorf("get db connection error, %s", err.Error()) + e.Error(500, err, "数据库连接获取失败") + return + } + + var data tools.SysTables + data.TableId, _ = pkg.StringToInt(c.Param("tableId")) + result, err := data.Get(db,true) + if err != nil { + log.Errorf("Get error, %s", err.Error()) + e.Error(500, err, "") + return + } + + mp := make(map[string]interface{}) + mp["list"] = result.Columns + mp["info"] = result + e.OK(mp, "") +} + +func (e SysTable) GetSysTablesInfo(c *gin.Context) { + e.Context = c + log := e.GetLogger() + db, err := e.GetOrm() + if err != nil { + log.Errorf("get db connection error, %s", err.Error()) + e.Error(500, err, "数据库连接获取失败") + return + } + + var data tools.SysTables + if c.Request.FormValue("tableName") != "" { + data.TBName = c.Request.FormValue("tableName") + } + result, err := data.Get(db,true) + if err != nil { + log.Errorf("Get error, %s", err.Error()) + e.Error(500, err, "抱歉未找到相关信息") + return + } + + mp := make(map[string]interface{}) + mp["list"] = result.Columns + mp["info"] = result + e.OK(mp, "") + //res.Data = mp + //c.JSON(http.StatusOK, res.ReturnOK()) +} + +func (e SysTable) GetSysTablesTree(c *gin.Context) { + e.Context = c + log := e.GetLogger() + db, err := e.GetOrm() + if err != nil { + log.Errorf("get db connection error, %s", err.Error()) + e.Error(500, err, "数据库连接获取失败") + return + } + + var data tools.SysTables + result, err := data.GetTree(db) + if err != nil { + log.Errorf("GetTree error, %s", err.Error()) + e.Error(500, err, "抱歉未找到相关信息") + return + } + + e.OK(result, "") +} + +// Insert +// @Summary 添加表结构 +// @Description 添加表结构 +// @Tags 工具 / 生成工具 +// @Accept application/json +// @Product application/json +// @Param tables query string false "tableName / 数据表名称" +// @Success 200 {string} string "{"code": 200, "message": "添加成功"}" +// @Success 200 {string} string "{"code": -1, "message": "添加失败"}" +// @Router /api/v1/sys/tables/info [post] +// @Security Bearer +func (e SysTable) Insert(c *gin.Context) { + e.Context = c + log := e.GetLogger() + db, err := e.GetOrm() + if err != nil { + log.Errorf("get db connection error, %s", err.Error()) + e.Error(500, err, "数据库连接获取失败") + return + } + + tablesList := strings.Split(c.Request.FormValue("tables"), ",") + for i := 0; i < len(tablesList); i++ { + + data, err := genTableInit(db, tablesList, i, c) + if err != nil { + log.Errorf("genTableInit error, %s", err.Error()) + e.Error(500, err, "") + return + } + + _, err = data.Create(db) + if err != nil { + log.Errorf("Create error, %s", err.Error()) + e.Error(500, err, "") + return + } + } + e.OK(nil, "添加成功") + +} + +func genTableInit(tx *gorm.DB, tablesList []string, i int, c *gin.Context) (tools.SysTables, error) { + var data tools.SysTables + var dbTable tools.DBTables + var dbColumn tools.DBColumns + data.TBName = tablesList[i] + data.CreateBy = 0 + + dbTable.TableName = data.TBName + dbtable, err := dbTable.Get(tx) + if err != nil { + return data, err + } + + dbColumn.TableName = data.TBName + tablenamelist := strings.Split(dbColumn.TableName, "_") + for i := 0; i < len(tablenamelist); i++ { + strStart := string([]byte(tablenamelist[i])[:1]) + strend := string([]byte(tablenamelist[i])[1:]) + // 大驼峰表名 结构体使用 + data.ClassName += strings.ToUpper(strStart) + strend + // 小驼峰表名 js函数名和权限标识使用 + if i == 0 { + data.BusinessName += strings.ToLower(strStart) + strend + } else { + data.BusinessName += strings.ToUpper(strStart) + strend + } + //data.PackageName += strings.ToLower(strStart) + strings.ToLower(strend) + //data.ModuleName += strings.ToLower(strStart) + strings.ToLower(strend) + } + //data.ModuleFrontName = strings.ReplaceAll(data.ModuleName, "_", "-") + data.PackageName = "admin" + data.TplCategory = "crud" + data.Crud = true + // 中横线表名称,接口路径、前端文件夹名称和js名称使用 + data.ModuleName = strings.Replace(data.TBName, "_", "-", -1) + dbcolumn, err := dbColumn.GetList(tx) + data.CreateBy = 0 + data.TableComment = dbtable.TableComment + if dbtable.TableComment == "" { + data.TableComment = data.ClassName + } + + data.FunctionName = data.TableComment + //data.BusinessName = data.ModuleName + data.IsLogicalDelete = "1" + data.LogicalDelete = true + data.LogicalDeleteColumn = "is_del" + data.IsActions = 2 + data.IsDataScope = 1 + data.IsAuth = 1 + + data.FunctionAuthor = "wenjianzhang" + for i := 0; i < len(dbcolumn); i++ { + var column tools.SysColumns + column.ColumnComment = dbcolumn[i].ColumnComment + column.ColumnName = dbcolumn[i].ColumnName + column.ColumnType = dbcolumn[i].ColumnType + column.Sort = i + 1 + column.Insert = true + column.IsInsert = "1" + column.QueryType = "EQ" + column.IsPk = "0" + + namelist := strings.Split(dbcolumn[i].ColumnName, "_") + for i := 0; i < len(namelist); i++ { + strStart := string([]byte(namelist[i])[:1]) + strend := string([]byte(namelist[i])[1:]) + column.GoField += strings.ToUpper(strStart) + strend + if i == 0 { + column.JsonField = strings.ToLower(strStart) + strend + } else { + column.JsonField += strings.ToUpper(strStart) + strend + } + } + if strings.Contains(dbcolumn[i].ColumnKey, "PR") { + column.IsPk = "1" + column.Pk = true + data.PkColumn = dbcolumn[i].ColumnName + //column.GoField = strings.ToUpper(column.GoField) + //column.JsonField = strings.ToUpper(column.JsonField) + data.PkGoField = column.GoField + data.PkJsonField = column.JsonField + } + column.IsRequired = "0" + if strings.Contains(dbcolumn[i].IsNullable, "NO") { + column.IsRequired = "1" + column.Required = true + } + + if strings.Contains(dbcolumn[i].ColumnType, "int") { + if strings.Contains(dbcolumn[i].ColumnKey, "PR") { + column.GoType = "int" + } else { + column.GoType = "string" + } + column.HtmlType = "input" + } else if strings.Contains(dbcolumn[i].ColumnType, "timestamp") { + column.GoType = "time.Time" + column.HtmlType = "datetime" + } else if strings.Contains(dbcolumn[i].ColumnType, "datetime") { + column.GoType = "time.Time" + column.HtmlType = "datetime" + } else { + column.GoType = "string" + column.HtmlType = "input" + } + + data.Columns = append(data.Columns, column) + } + return data, err +} + +// Update +// @Summary 修改表结构 +// @Description 修改表结构 +// @Tags 工具 / 生成工具 +// @Accept application/json +// @Product application/json +// @Param data body tools.SysTables true "body" +// @Success 200 {string} string "{"code": 200, "message": "添加成功"}" +// @Success 200 {string} string "{"code": -1, "message": "添加失败"}" +// @Router /api/v1/sys/tables/info [put] +// @Security Bearer +func (e SysTable) Update(c *gin.Context) { + var data tools.SysTables + err := c.Bind(&data) + pkg.HasError(err, "数据解析失败", 500) + + e.Context = c + log := e.GetLogger() + db, err := e.GetOrm() + if err != nil { + log.Errorf("get db connection error, %s", err.Error()) + e.Error(500, err, "数据库连接获取失败") + return + } + + data.UpdateBy = 0 + result, err := data.Update(db) + if err != nil { + log.Errorf("Update error, %s", err.Error()) + e.Error(500, err, "") + return + } + e.OK(result, "修改成功") +} + +// Delete +// @Summary 删除表结构 +// @Description 删除表结构 +// @Tags 工具 / 生成工具 +// @Param tableId path int true "tableId" +// @Success 200 {string} string "{"code": 200, "message": "删除成功"}" +// @Success 200 {string} string "{"code": -1, "message": "删除失败"}" +// @Router /api/v1/sys/tables/info/{tableId} [delete] +func (e SysTable) Delete(c *gin.Context) { + e.Context = c + log := e.GetLogger() + db, err := e.GetOrm() + if err != nil { + log.Errorf("get db connection error, %s", err.Error()) + e.Error(500, err, "数据库连接获取失败") + return + } + + var data tools.SysTables + IDS := pkg.IdsStrToIdsIntGroup("tableId", c) + _, err = data.BatchDelete(db, IDS) + if err != nil { + log.Errorf("BatchDelete error, %s", err.Error()) + e.Error(500, err, "删除失败") + return + } + e.OK(nil, "删除成功") +} diff --git a/app/other/models/tools/db_columns.go b/app/other/models/tools/db_columns.go new file mode 100644 index 0000000..46d9bc6 --- /dev/null +++ b/app/other/models/tools/db_columns.go @@ -0,0 +1,70 @@ +package tools + +import ( + "errors" + + "github.com/go-admin-team/go-admin-core/sdk/config" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "gorm.io/gorm" +) + +type DBColumns struct { + TableSchema string `gorm:"column:TABLE_SCHEMA" json:"tableSchema"` + TableName string `gorm:"column:TABLE_NAME" json:"tableName"` + ColumnName string `gorm:"column:COLUMN_NAME" json:"columnName"` + ColumnDefault string `gorm:"column:COLUMN_DEFAULT" json:"columnDefault"` + IsNullable string `gorm:"column:IS_NULLABLE" json:"isNullable"` + DataType string `gorm:"column:DATA_TYPE" json:"dataType"` + CharacterMaximumLength string `gorm:"column:CHARACTER_MAXIMUM_LENGTH" json:"characterMaximumLength"` + CharacterSetName string `gorm:"column:CHARACTER_SET_NAME" json:"characterSetName"` + ColumnType string `gorm:"column:COLUMN_TYPE" json:"columnType"` + ColumnKey string `gorm:"column:COLUMN_KEY" json:"columnKey"` + Extra string `gorm:"column:EXTRA" json:"extra"` + ColumnComment string `gorm:"column:COLUMN_COMMENT" json:"columnComment"` +} + +func (e *DBColumns) GetPage(tx *gorm.DB, pageSize int, pageIndex int) ([]DBColumns, int, error) { + var doc []DBColumns + var count int64 + table := new(gorm.DB) + + if config.DatabaseConfig.Driver == "mysql" { + table = tx.Table("information_schema.`COLUMNS`") + table = table.Where("table_schema= ? ", config.GenConfig.DBName) + + if e.TableName != "" { + return nil, 0, errors.New("table name cannot be empty!") + } + + table = table.Where("TABLE_NAME = ?", e.TableName) + } + + if err := table.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Offset(-1).Limit(-1).Count(&count).Error; err != nil { + return nil, 0, err + } + //table.Count(&count) + return doc, int(count), nil + +} + +func (e *DBColumns) GetList(tx *gorm.DB) ([]DBColumns, error) { + var doc []DBColumns + table := new(gorm.DB) + + if e.TableName == "" { + return nil, errors.New("table name cannot be empty!") + } + + if config.DatabaseConfig.Driver == "mysql" { + table = tx.Table("information_schema.columns") + table = table.Where("table_schema= ? ", config.GenConfig.DBName) + + table = table.Where("TABLE_NAME = ?", e.TableName).Order("ORDINAL_POSITION asc") + } else { + pkg.Assert(true, "目前只支持mysql数据库", 500) + } + if err := table.Find(&doc).Error; err != nil { + return doc, err + } + return doc, nil +} \ No newline at end of file diff --git a/app/other/models/tools/db_tables.go b/app/other/models/tools/db_tables.go new file mode 100644 index 0000000..77c4927 --- /dev/null +++ b/app/other/models/tools/db_tables.go @@ -0,0 +1,62 @@ +package tools + +import ( + "errors" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + + "gorm.io/gorm" + + config2 "github.com/go-admin-team/go-admin-core/sdk/config" +) + +type DBTables struct { + TableName string `gorm:"column:TABLE_NAME" json:"tableName"` + Engine string `gorm:"column:ENGINE" json:"engine"` + TableRows string `gorm:"column:TABLE_ROWS" json:"tableRows"` + TableCollation string `gorm:"column:TABLE_COLLATION" json:"tableCollation"` + CreateTime string `gorm:"column:CREATE_TIME" json:"createTime"` + UpdateTime string `gorm:"column:UPDATE_TIME" json:"updateTime"` + TableComment string `gorm:"column:TABLE_COMMENT" json:"tableComment"` +} + +func (e *DBTables) GetPage(tx *gorm.DB, pageSize int, pageIndex int) ([]DBTables, int, error) { + var doc []DBTables + table := new(gorm.DB) + var count int64 + + if config2.DatabaseConfig.Driver == "mysql" { + table = tx.Table("information_schema.tables") + table = table.Where("TABLE_NAME not in (select table_name from `" + config2.GenConfig.DBName + "`.sys_tables) ") + table = table.Where("table_schema= ? ", config2.GenConfig.DBName) + + if e.TableName != "" { + table = table.Where("TABLE_NAME = ?", e.TableName) + } + if err := table.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Offset(-1).Limit(-1).Count(&count).Error; err != nil { + return nil, 0, err + } + } else { + pkg.Assert(true, "目前只支持mysql数据库", 500) + } + + //table.Count(&count) + return doc, int(count), nil +} + +func (e *DBTables) Get(tx *gorm.DB) (DBTables, error) { + var doc DBTables + if config2.DatabaseConfig.Driver == "mysql" { + table := tx.Table("information_schema.tables") + table = table.Where("table_schema= ? ", config2.GenConfig.DBName) + if e.TableName == "" { + return doc, errors.New("table name cannot be empty!") + } + table = table.Where("TABLE_NAME = ?", e.TableName) + if err := table.First(&doc).Error; err != nil { + return doc, err + } + } else { + pkg.Assert(true, "目前只支持mysql数据库", 500) + } + return doc, nil +} diff --git a/app/other/models/tools/sys_columns.go b/app/other/models/tools/sys_columns.go new file mode 100644 index 0000000..f3adeb3 --- /dev/null +++ b/app/other/models/tools/sys_columns.go @@ -0,0 +1,100 @@ +package tools + +import ( + "go-admin/app/admin/models" + "gorm.io/gorm" +) + +type SysColumns struct { + ColumnId int `gorm:"primaryKey;autoIncrement" json:"columnId"` + TableId int `gorm:"" json:"tableId"` + ColumnName string `gorm:"size:128;" json:"columnName"` + ColumnComment string `gorm:"column:column_comment;size:128;" json:"columnComment"` + ColumnType string `gorm:"column:column_type;size:128;" json:"columnType"` + GoType string `gorm:"column:go_type;size:128;" json:"goType"` + GoField string `gorm:"column:go_field;size:128;" json:"goField"` + JsonField string `gorm:"column:json_field;size:128;" json:"jsonField"` + IsPk string `gorm:"column:is_pk;size:4;" json:"isPk"` + IsIncrement string `gorm:"column:is_increment;size:4;" json:"isIncrement"` + IsRequired string `gorm:"column:is_required;size:4;" json:"isRequired"` + IsInsert string `gorm:"column:is_insert;size:4;" json:"isInsert"` + IsEdit string `gorm:"column:is_edit;size:4;" json:"isEdit"` + IsList string `gorm:"column:is_list;size:4;" json:"isList"` + IsQuery string `gorm:"column:is_query;size:4;" json:"isQuery"` + QueryType string `gorm:"column:query_type;size:128;" json:"queryType"` + HtmlType string `gorm:"column:html_type;size:128;" json:"htmlType"` + DictType string `gorm:"column:dict_type;size:128;" json:"dictType"` + Sort int `gorm:"column:sort;" json:"sort"` + List string `gorm:"column:list;size:1;" json:"list"` + Pk bool `gorm:"column:pk;size:1;" json:"pk"` + Required bool `gorm:"column:required;size:1;" json:"required"` + SuperColumn bool `gorm:"column:super_column;size:1;" json:"superColumn"` + UsableColumn bool `gorm:"column:usable_column;size:1;" json:"usableColumn"` + Increment bool `gorm:"column:increment;size:1;" json:"increment"` + Insert bool `gorm:"column:insert;size:1;" json:"insert"` + Edit bool `gorm:"column:edit;size:1;" json:"edit"` + Query bool `gorm:"column:query;size:1;" json:"query"` + Remark string `gorm:"column:remark;size:255;" json:"remark"` + FkTableName string `gorm:"" json:"fkTableName"` + FkTableNameClass string `gorm:"" json:"fkTableNameClass"` + FkTableNamePackage string `gorm:"" json:"fkTableNamePackage"` + FkCol []SysColumns `gorm:"-" json:"fkCol"` + FkLabelId string `gorm:"" json:"fkLabelId"` + FkLabelName string `gorm:"size:255;" json:"fkLabelName"` + CreateBy int `gorm:"column:create_by;size:20;" json:"createBy"` + UpdateBy int `gorm:"column:update_By;size:20;" json:"updateBy"` + + models.BaseModel +} + +func (*SysColumns) TableName() string { + return "sys_columns" +} + +func (e *SysColumns) GetList(tx *gorm.DB, exclude bool) ([]SysColumns, error) { + var doc []SysColumns + table := tx.Table("sys_columns") + table = table.Where("table_id = ? ", e.TableId) + if exclude { + notIn := make([]string, 0, 6) + notIn = append(notIn, "id") + notIn = append(notIn, "create_by") + notIn = append(notIn, "update_by") + notIn = append(notIn, "created_at") + notIn = append(notIn, "updated_at") + notIn = append(notIn, "deleted_at") + table = table.Where(" column_name not in(?)", notIn) + } + + if err := table.Find(&doc).Error; err != nil { + return nil, err + } + return doc, nil +} + +func (e *SysColumns) Create(tx *gorm.DB) (SysColumns, error) { + var doc SysColumns + e.CreateBy = 0 + result := tx.Table("sys_columns").Create(&e) + if result.Error != nil { + err := result.Error + return doc, err + } + doc = *e + return doc, nil +} + +func (e *SysColumns) Update(tx *gorm.DB) (update SysColumns, err error) { + if err = tx.Table("sys_columns").First(&update, e.ColumnId).Error; err != nil { + return + } + + //参数1:是要修改的数据 + //参数2:是修改的数据 + e.UpdateBy = 0 + if err = tx.Table("sys_columns").Model(&update).Updates(&e).Error; err != nil { + return + } + + return +} diff --git a/app/other/models/tools/sys_tables.go b/app/other/models/tools/sys_tables.go new file mode 100644 index 0000000..91ded97 --- /dev/null +++ b/app/other/models/tools/sys_tables.go @@ -0,0 +1,238 @@ +package tools + +import ( + common "go-admin/common/models" + "strings" + + "gorm.io/gorm" + + "go-admin/app/admin/models" +) + +type SysTables struct { + TableId int `gorm:"primaryKey;autoIncrement" json:"tableId"` //表编码 + TBName string `gorm:"column:table_name;size:255;" json:"tableName"` //表名称 + MLTBName string `gorm:"-" json:"-"` //表名称 + TableComment string `gorm:"size:255;" json:"tableComment"` //表备注 + ClassName string `gorm:"size:255;" json:"className"` //类名 + TplCategory string `gorm:"size:255;" json:"tplCategory"` // + PackageName string `gorm:"size:255;" json:"packageName"` //包名 + ModuleName string `gorm:"size:255;" json:"moduleName"` //go文件名 + ModuleFrontName string `gorm:"size:255;comment:前端文件名;" json:"moduleFrontName"` //前端文件名 + BusinessName string `gorm:"size:255;" json:"businessName"` // + FunctionName string `gorm:"size:255;" json:"functionName"` //功能名称 + FunctionAuthor string `gorm:"size:255;" json:"functionAuthor"` //功能作者 + PkColumn string `gorm:"size:255;" json:"pkColumn"` + PkGoField string `gorm:"size:255;" json:"pkGoField"` + PkJsonField string `gorm:"size:255;" json:"pkJsonField"` + Options string `gorm:"size:255;" json:"options"` + TreeCode string `gorm:"size:255;" json:"treeCode"` + TreeParentCode string `gorm:"size:255;" json:"treeParentCode"` + TreeName string `gorm:"size:255;" json:"treeName"` + Tree bool `gorm:"size:1;default:0;" json:"tree"` + Crud bool `gorm:"size:1;default:1;" json:"crud"` + Remark string `gorm:"size:255;" json:"remark"` + IsDataScope int `gorm:"size:1;" json:"isDataScope"` + IsActions int `gorm:"size:1;" json:"isActions"` + IsAuth int `gorm:"size:1;" json:"isAuth"` + IsLogicalDelete string `gorm:"size:1;" json:"isLogicalDelete"` + LogicalDelete bool `gorm:"size:1;" json:"logicalDelete"` + LogicalDeleteColumn string `gorm:"size:128;" json:"logicalDeleteColumn"` + common.ModelTime + common.ControlBy + DataScope string `gorm:"-" json:"dataScope"` + Params Params `gorm:"-" json:"params"` + Columns []SysColumns `gorm:"-" json:"columns"` + + models.BaseModel +} + +func (*SysTables) TableName() string { + return "sys_tables" +} + +type Params struct { + TreeCode string `gorm:"-" json:"treeCode"` + TreeParentCode string `gorm:"-" json:"treeParentCode"` + TreeName string `gorm:"-" json:"treeName"` +} + +func (e *SysTables) GetPage(tx *gorm.DB, pageSize int, pageIndex int) ([]SysTables, int, error) { + var doc []SysTables + + table := tx.Table("sys_tables") + + if e.TBName != "" { + table = table.Where("table_name = ?", e.TBName) + } + if e.TableComment != "" { + table = table.Where("table_comment = ?", e.TableComment) + } + + var count int64 + + if err := table.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Offset(-1).Limit(-1).Count(&count).Error; err != nil { + return nil, 0, err + } + //table.Where("`deleted_at` IS NULL").Count(&count) + return doc, int(count), nil +} + +func (e *SysTables) Get(tx *gorm.DB, exclude bool) (SysTables, error) { + var doc SysTables + var err error + table := tx.Table("sys_tables") + + if e.TBName != "" { + table = table.Where("table_name = ?", e.TBName) + } + if e.TableId != 0 { + table = table.Where("table_id = ?", e.TableId) + } + if e.TableComment != "" { + table = table.Where("table_comment = ?", e.TableComment) + } + + if err := table.First(&doc).Error; err != nil { + return doc, err + } + var col SysColumns + col.TableId = doc.TableId + if doc.Columns, err = col.GetList(tx, exclude); err != nil { + return doc, err + } + + return doc, nil +} + +func (e *SysTables) GetTree(tx *gorm.DB) ([]SysTables, error) { + var doc []SysTables + var err error + table := tx.Table("sys_tables") + + if e.TBName != "" { + table = table.Where("table_name = ?", e.TBName) + } + if e.TableId != 0 { + table = table.Where("table_id = ?", e.TableId) + } + if e.TableComment != "" { + table = table.Where("table_comment = ?", e.TableComment) + } + + if err := table.Find(&doc).Error; err != nil { + return doc, err + } + for i := 0; i < len(doc); i++ { + var col SysColumns + //col.FkCol = append(col.FkCol, SysColumns{ColumnId: 0, ColumnName: "请选择"}) + col.TableId = doc[i].TableId + if doc[i].Columns, err = col.GetList(tx, false); err != nil { + return doc, err + } + + } + + return doc, nil +} + +func (e *SysTables) Create(tx *gorm.DB) (SysTables, error) { + var doc SysTables + e.CreateBy = 0 + result := tx.Table("sys_tables").Create(&e) + if result.Error != nil { + err := result.Error + return doc, err + } + doc = *e + for i := 0; i < len(e.Columns); i++ { + e.Columns[i].TableId = doc.TableId + + _, _ = e.Columns[i].Create(tx) + } + + return doc, nil +} + +func (e *SysTables) Update(tx *gorm.DB) (update SysTables, err error) { + //if err = orm.Eloquent.Table("sys_tables").First(&update, e.TableId).Error; err != nil { + // return + //} + + //参数1:是要修改的数据 + //参数2:是修改的数据 + e.UpdateBy = 0 + if err = tx.Table("sys_tables").Where("table_id = ?", e.TableId).Updates(&e).Error; err != nil { + return + } + + tableNames := make([]string, 0) + for i := range e.Columns { + if e.Columns[i].FkTableName != "" { + tableNames = append(tableNames, e.Columns[i].FkTableName) + } + } + + tables := make([]SysTables, 0) + tableMap := make(map[string]*SysTables) + if len(tableNames) > 0 { + if err = tx.Table("sys_tables").Where("table_name in (?)", tableNames).Find(&tables).Error; err != nil { + return + } + for i := range tables { + tableMap[tables[i].TBName] = &tables[i] + } + } + + for i := 0; i < len(e.Columns); i++ { + if e.Columns[i].FkTableName != "" { + t, ok := tableMap[e.Columns[i].FkTableName] + if ok { + e.Columns[i].FkTableNameClass = t.ClassName + t.MLTBName = strings.Replace(t.TBName, "_", "-", -1) + e.Columns[i].FkTableNamePackage = t.MLTBName + } else { + tableNameList := strings.Split(e.Columns[i].FkTableName, "_") + e.Columns[i].FkTableNameClass = "" + //e.Columns[i].FkTableNamePackage = "" + for a := 0; a < len(tableNameList); a++ { + strStart := string([]byte(tableNameList[a])[:1]) + strEnd := string([]byte(tableNameList[a])[1:]) + e.Columns[i].FkTableNameClass += strings.ToUpper(strStart) + strEnd + //e.Columns[i].FkTableNamePackage += strings.ToLower(strStart) + strings.ToLower(strEnd) + } + } + } + _, _ = e.Columns[i].Update(tx) + } + return +} + +func (e *SysTables) Delete(db *gorm.DB) (success bool, err error) { + tx := db.Begin() + defer func() { + if err != nil { + tx.Rollback() + } else { + tx.Commit() + } + }() + if err = tx.Table("sys_tables").Delete(SysTables{}, "table_id = ?", e.TableId).Error; err != nil { + success = false + return + } + if err = tx.Table("sys_columns").Delete(SysColumns{}, "table_id = ?", e.TableId).Error; err != nil { + success = false + return + } + success = true + return +} + +func (e *SysTables) BatchDelete(tx *gorm.DB, id []int) (Result bool, err error) { + if err = tx.Unscoped().Table(e.TableName()).Where(" table_id in (?)", id).Delete(&SysColumns{}).Error; err != nil { + return + } + Result = true + return +} diff --git a/app/other/router/file.go b/app/other/router/file.go new file mode 100644 index 0000000..c3bd3ac --- /dev/null +++ b/app/other/router/file.go @@ -0,0 +1,20 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + "go-admin/app/other/apis" +) + +func init() { + routerCheckRole = append(routerCheckRole, registerFileRouter) +} + +// 需认证的路由代码 +func registerFileRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + var api = apis.File{} + r := v1.Group("").Use(authMiddleware.MiddlewareFunc()) + { + r.POST("/public/uploadFile", api.UploadFile) + } +} diff --git a/app/other/router/gen_router.go b/app/other/router/gen_router.go new file mode 100644 index 0000000..c3c356b --- /dev/null +++ b/app/other/router/gen_router.go @@ -0,0 +1,56 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + "go-admin/app/admin/apis" + "go-admin/app/other/apis/tools" +) + +func init() { + routerCheckRole = append(routerCheckRole, sysNoCheckRoleRouter, registerDBRouter, registerSysTableRouter) +} + +func sysNoCheckRoleRouter(v1 *gin.RouterGroup ,authMiddleware *jwt.GinJWTMiddleware) { + r1 := v1.Group("") + { + sys := apis.System{} + r1.GET("/captcha", sys.GenerateCaptchaHandler) + } + + r := v1.Group("").Use(authMiddleware.MiddlewareFunc()) + { + gen := tools.Gen{} + r.GET("/gen/preview/:tableId", gen.Preview) + r.GET("/gen/toproject/:tableId", gen.GenCode) + r.GET("/gen/apitofile/:tableId", gen.GenApiToFile) + r.GET("/gen/todb/:tableId", gen.GenMenuAndApi) + sysTable := tools.SysTable{} + r.GET("/gen/tabletree", sysTable.GetSysTablesTree) + } +} + +func registerDBRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + db := v1.Group("/db").Use(authMiddleware.MiddlewareFunc()) + { + gen := tools.Gen{} + db.GET("/tables/page", gen.GetDBTableList) + db.GET("/columns/page", gen.GetDBColumnList) + } +} + +func registerSysTableRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + tables := v1.Group("/sys/tables") + { + sysTable := tools.SysTable{} + tables.Group("").Use(authMiddleware.MiddlewareFunc()).GET("/page", sysTable.GetPage) + tablesInfo := tables.Group("/info").Use(authMiddleware.MiddlewareFunc()) + { + tablesInfo.POST("", sysTable.Insert) + tablesInfo.PUT("", sysTable.Update) + tablesInfo.DELETE("/:tableId", sysTable.Delete) + tablesInfo.GET("/:tableId", sysTable.Get) + tablesInfo.GET("", sysTable.GetSysTablesInfo) + } + } +} \ No newline at end of file diff --git a/app/other/router/init_router.go b/app/other/router/init_router.go new file mode 100644 index 0000000..708f93e --- /dev/null +++ b/app/other/router/init_router.go @@ -0,0 +1,36 @@ +package router + +import ( + "os" + + "github.com/gin-gonic/gin" + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk" + common "go-admin/common/middleware" +) + +// InitRouter 路由初始化,不要怀疑,这里用到了 +func InitRouter() { + var r *gin.Engine + h := sdk.Runtime.GetEngine() + if h == nil { + log.Fatal("not found engine...") + os.Exit(-1) + } + switch h.(type) { + case *gin.Engine: + r = h.(*gin.Engine) + default: + log.Fatal("not support other engine") + os.Exit(-1) + } + // the jwt middleware + authMiddleware, err := common.AuthInit() + if err != nil { + log.Fatalf("JWT Init Error, %s", err.Error()) + } + + // 注册业务路由 + // TODO: 这里可存放业务路由,里边并无实际路由只有演示代码 + initRouter(r, authMiddleware) +} diff --git a/app/other/router/monitor.go b/app/other/router/monitor.go new file mode 100644 index 0000000..cdbe7ad --- /dev/null +++ b/app/other/router/monitor.go @@ -0,0 +1,23 @@ +package router + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/tools/transfer" + "github.com/prometheus/client_golang/prometheus/promhttp" +) + +func init() { + routerNoCheckRole = append(routerNoCheckRole, registerMonitorRouter) +} + +// 需认证的路由代码 +func registerMonitorRouter(v1 *gin.RouterGroup) { + v1.GET("/metrics", transfer.Handler(promhttp.Handler())) + //健康检查 + v1.GET("/health", func(c *gin.Context) { + c.Status(http.StatusOK) + }) + +} \ No newline at end of file diff --git a/app/other/router/router.go b/app/other/router/router.go new file mode 100644 index 0000000..8c893a2 --- /dev/null +++ b/app/other/router/router.go @@ -0,0 +1,42 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" +) + +var ( + routerNoCheckRole = make([]func(*gin.RouterGroup), 0) + routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0) +) + +// initRouter 路由示例 +func initRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine { + + // 无需认证的路由 + noCheckRoleRouter(r) + // 需要认证的路由 + checkRoleRouter(r, authMiddleware) + + return r +} + +// noCheckRoleRouter 无需认证的路由示例 +func noCheckRoleRouter(r *gin.Engine) { + // 可根据业务需求来设置接口版本 + v1 := r.Group("/api/v1") + + for _, f := range routerNoCheckRole { + f(v1) + } +} + +// checkRoleRouter 需要认证的路由示例 +func checkRoleRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) { + // 可根据业务需求来设置接口版本 + v1 := r.Group("/api/v1") + + for _, f := range routerCheckRole { + f(v1, authMiddleware) + } +} diff --git a/app/other/router/sys_server_monitor.go b/app/other/router/sys_server_monitor.go new file mode 100644 index 0000000..ffa91a1 --- /dev/null +++ b/app/other/router/sys_server_monitor.go @@ -0,0 +1,21 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + "go-admin/app/other/apis" + "go-admin/common/middleware" +) + +func init() { + routerCheckRole = append(routerCheckRole, registerSysServerMonitorRouter) +} + +// 需认证的路由代码 +func registerSysServerMonitorRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.ServerMonitor{} + r := v1.Group("/server-monitor").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + r.GET("", api.ServerInfo) + } +} diff --git a/app/other/service/dto/sys_tables.go b/app/other/service/dto/sys_tables.go new file mode 100644 index 0000000..2e8b923 --- /dev/null +++ b/app/other/service/dto/sys_tables.go @@ -0,0 +1,6 @@ +package dto + +type SysTableSearch struct { + TBName string `form:"tableName" search:"type:exact;column:table_name;table:table_name"` + TableComment string `form:"tableComment" search:"type:icontains;column:table_comment;table:table_comment"` +} diff --git a/cmd/api/jobs.go b/cmd/api/jobs.go new file mode 100644 index 0000000..e95caf8 --- /dev/null +++ b/cmd/api/jobs.go @@ -0,0 +1,8 @@ +package api + +import "go-admin/app/jobs/router" + +func init() { + //注册路由 fixme 其他应用的路由,在本目录新建文件放在init方法 + AppRouters = append(AppRouters, router.InitRouter) +} diff --git a/cmd/api/other.go b/cmd/api/other.go new file mode 100644 index 0000000..4c291be --- /dev/null +++ b/cmd/api/other.go @@ -0,0 +1,8 @@ +package api + +import "go-admin/app/other/router" + +func init() { + //注册路由 fixme 其他应用的路由,在本目录新建文件放在init方法 + AppRouters = append(AppRouters, router.InitRouter) +} diff --git a/cmd/api/server.go b/cmd/api/server.go new file mode 100644 index 0000000..5c8f01a --- /dev/null +++ b/cmd/api/server.go @@ -0,0 +1,186 @@ +package api + +import ( + "context" + "fmt" + "github.com/go-admin-team/go-admin-core/sdk/runtime" + "log" + "net/http" + "os" + "os/signal" + "time" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/config/source/file" + "github.com/go-admin-team/go-admin-core/sdk" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/config" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "github.com/spf13/cobra" + + "go-admin/app/admin/models" + "go-admin/app/admin/router" + "go-admin/app/jobs" + "go-admin/common/database" + "go-admin/common/global" + common "go-admin/common/middleware" + "go-admin/common/middleware/handler" + "go-admin/common/storage" + ext "go-admin/config" +) + +var ( + configYml string + apiCheck bool + StartCmd = &cobra.Command{ + Use: "server", + Short: "Start API server", + Example: "go-admin server -c config/settings.yml", + SilenceUsage: true, + PreRun: func(cmd *cobra.Command, args []string) { + setup() + }, + RunE: func(cmd *cobra.Command, args []string) error { + return run() + }, + } +) + +var AppRouters = make([]func(), 0) + +func init() { + StartCmd.PersistentFlags().StringVarP(&configYml, "config", "c", "config/settings.yml", "Start server with provided configuration file") + StartCmd.PersistentFlags().BoolVarP(&apiCheck, "api", "a", false, "Start server with check api data") + + //注册路由 fixme 其他应用的路由,在本目录新建文件放在init方法 + AppRouters = append(AppRouters, router.InitRouter) +} + +func setup() { + // 注入配置扩展项 + config.ExtendConfig = &ext.ExtConfig + //1. 读取配置 + config.Setup( + file.NewSource(file.WithPath(configYml)), + database.Setup, + storage.Setup, + ) + //注册监听函数 + queue := sdk.Runtime.GetMemoryQueue("") + queue.Register(global.LoginLog, models.SaveLoginLog) + queue.Register(global.OperateLog, models.SaveOperaLog) + queue.Register(global.ApiCheck, models.SaveSysApi) + go queue.Run() + + usageStr := `starting api server...` + log.Println(usageStr) +} + +func run() error { + if config.ApplicationConfig.Mode == pkg.ModeProd.String() { + gin.SetMode(gin.ReleaseMode) + } + initRouter() + + for _, f := range AppRouters { + f() + } + + srv := &http.Server{ + Addr: fmt.Sprintf("%s:%d", config.ApplicationConfig.Host, config.ApplicationConfig.Port), + Handler: sdk.Runtime.GetEngine(), + } + + go func() { + jobs.InitJob() + jobs.Setup(sdk.Runtime.GetDb()) + + }() + + if apiCheck { + var routers = sdk.Runtime.GetRouter() + q := sdk.Runtime.GetMemoryQueue("") + mp := make(map[string]interface{}, 0) + mp["List"] = routers + message, err := sdk.Runtime.GetStreamMessage("", global.ApiCheck, mp) + if err != nil { + log.Printf("GetStreamMessage error, %s \n", err.Error()) + //日志报错错误,不中断请求 + } else { + err = q.Append(message) + if err != nil { + log.Printf("Append message error, %s \n", err.Error()) + } + } + } + + go func() { + // 服务连接 + if config.SslConfig.Enable { + if err := srv.ListenAndServeTLS(config.SslConfig.Pem, config.SslConfig.KeyStr); err != nil && err != http.ErrServerClosed { + log.Fatal("listen: ", err) + } + } else { + if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { + log.Fatal("listen: ", err) + } + } + }() + fmt.Println(pkg.Red(string(global.LogoContent))) + tip() + fmt.Println(pkg.Green("Server run at:")) + fmt.Printf("- Local: %s://localhost:%d/ \r\n", "http", config.ApplicationConfig.Port) + fmt.Printf("- Network: %s://%s:%d/ \r\n", pkg.GetLocaHonst(), "http", config.ApplicationConfig.Port) + fmt.Println(pkg.Green("Swagger run at:")) + fmt.Printf("- Local: http://localhost:%d/swagger/admin/index.html \r\n", config.ApplicationConfig.Port) + fmt.Printf("- Network: %s://%s:%d/swagger/admin/index.html \r\n", "http", pkg.GetLocaHonst(), config.ApplicationConfig.Port) + fmt.Printf("%s Enter Control + C Shutdown Server \r\n", pkg.GetCurrentTimeStr()) + // 等待中断信号以优雅地关闭服务器(设置 5 秒的超时时间) + quit := make(chan os.Signal, 1) + signal.Notify(quit, os.Interrupt) + <-quit + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + fmt.Printf("%s Shutdown Server ... \r\n", pkg.GetCurrentTimeStr()) + + if err := srv.Shutdown(ctx); err != nil { + log.Fatal("Server Shutdown:", err) + } + log.Println("Server exiting") + + return nil +} + +var Router runtime.Router + +func tip() { + usageStr := `欢迎使用 ` + pkg.Green(`go-admin `+global.Version) + ` 可以使用 ` + pkg.Red(`-h`) + ` 查看命令` + fmt.Printf("%s \n\n", usageStr) +} + +func initRouter() { + var r *gin.Engine + h := sdk.Runtime.GetEngine() + if h == nil { + h = gin.New() + sdk.Runtime.SetEngine(h) + } + switch h.(type) { + case *gin.Engine: + r = h.(*gin.Engine) + default: + log.Fatal("not support other engine") + //os.Exit(-1) + } + if config.SslConfig.Enable { + r.Use(handler.TlsHandler()) + } + //r.Use(middleware.Metrics()) + r.Use(common.Sentinel()). + Use(common.RequestId(pkg.TrafficKey)). + Use(api.SetRequestLogger) + + common.InitMiddleware(r) + +} diff --git a/cmd/app/server.go b/cmd/app/server.go new file mode 100644 index 0000000..013ac38 --- /dev/null +++ b/cmd/app/server.go @@ -0,0 +1,90 @@ +package app + +import ( + "bytes" + "errors" + "fmt" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "github.com/go-admin-team/go-admin-core/sdk/pkg/utils" + "github.com/spf13/cobra" + "text/template" +) + +var ( + appName string + StartCmd = &cobra.Command{ + Use: "app", + Short: "Create a new app", + Long: "Use when you need to create a new app", + Example: "go-admin app -n admin", + Run: func(cmd *cobra.Command, args []string) { + run() + }, + } +) + +func init() { + StartCmd.PersistentFlags().StringVarP(&appName, "name", "n", "", "Start server with provided configuration file") +} + +func run() { + + fmt.Println(`start init`) + //1. 读取配置 + + fmt.Println(`generate migration file`) + _ = genFile() + +} + +func genFile() error { + if appName == "" { + return errors.New("arg `name` invalid :name is empty") + } + path := "app/" + appPath := path + appName + err := utils.IsNotExistMkDir(appPath) + if err != nil { + return err + } + apiPath := appPath + "/apis/" + err = utils.IsNotExistMkDir(apiPath) + if err != nil { + return err + } + modelsPath := appPath + "/models/" + err = utils.IsNotExistMkDir(modelsPath) + if err != nil { + return err + } + routerPath := appPath + "/router/" + err = utils.IsNotExistMkDir(routerPath) + if err != nil { + return err + } + servicePath := appPath + "/service/" + err = utils.IsNotExistMkDir(servicePath) + if err != nil { + return err + } + dtoPath := appPath + "/service/dto/" + err = utils.IsNotExistMkDir(dtoPath) + if err != nil { + return err + } + + t1, err := template.ParseFiles("template/cmd_api.template") + if err != nil { + return err + } + m := map[string]string{} + m["appName"] = appName + var b1 bytes.Buffer + err = t1.Execute(&b1, m) + pkg.FileCreate(b1, "./cmd/api/"+appName+".go") + t2, err := template.ParseFiles("template/router.template") + var b2 bytes.Buffer + err = t2.Execute(&b2, nil) + pkg.FileCreate(b2, appPath+"/router/router.go") + return nil +} diff --git a/cmd/cobra.go b/cmd/cobra.go new file mode 100644 index 0000000..d6030a9 --- /dev/null +++ b/cmd/cobra.go @@ -0,0 +1,57 @@ +package cmd + +import ( + "errors" + "fmt" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "go-admin/cmd/app" + "go-admin/common/global" + "os" + + "github.com/spf13/cobra" + + "go-admin/cmd/api" + "go-admin/cmd/config" + "go-admin/cmd/migrate" + "go-admin/cmd/version" +) + +var rootCmd = &cobra.Command{ + Use: "go-admin", + Short: "go-admin", + SilenceUsage: true, + Long: `go-admin`, + Args: func(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + tip() + return errors.New(pkg.Red("requires at least one arg")) + } + return nil + }, + PersistentPreRunE: func(*cobra.Command, []string) error { return nil }, + Run: func(cmd *cobra.Command, args []string) { + tip() + }, +} + +func tip() { + usageStr := `欢迎使用 ` + pkg.Green(`go-admin `+global.Version) + ` 可以使用 ` + pkg.Red(`-h`) + ` 查看命令` + usageStr1 := `也可以参考 https://doc.go-admin.dev/guide/ksks 的相关内容` + fmt.Printf("%s\n", usageStr) + fmt.Printf("%s\n", usageStr1) +} + +func init() { + rootCmd.AddCommand(api.StartCmd) + rootCmd.AddCommand(migrate.StartCmd) + rootCmd.AddCommand(version.StartCmd) + rootCmd.AddCommand(config.StartCmd) + rootCmd.AddCommand(app.StartCmd) +} + +//Execute : apply commands +func Execute() { + if err := rootCmd.Execute(); err != nil { + os.Exit(-1) + } +} diff --git a/cmd/config/server.go b/cmd/config/server.go new file mode 100644 index 0000000..52ce85b --- /dev/null +++ b/cmd/config/server.go @@ -0,0 +1,63 @@ +package config + +import ( + "encoding/json" + "fmt" + + "github.com/go-admin-team/go-admin-core/config/source/file" + "github.com/spf13/cobra" + + "github.com/go-admin-team/go-admin-core/sdk/config" +) + +var ( + configYml string + StartCmd = &cobra.Command{ + Use: "config", + Short: "Get Application config info", + Example: "go-admin config -c config/settings.yml", + Run: func(cmd *cobra.Command, args []string) { + run() + }, + } +) + +func init() { + StartCmd.PersistentFlags().StringVarP(&configYml, "config", "c", "config/settings.yml", "Start server with provided configuration file") +} + +func run() { + config.Setup(file.NewSource(file.WithPath(configYml))) + + application, errs := json.MarshalIndent(config.ApplicationConfig, "", " ") //转换成JSON返回的是byte[] + if errs != nil { + fmt.Println(errs.Error()) + } + fmt.Println("application:", string(application)) + + jwt, errs := json.MarshalIndent(config.JwtConfig, "", " ") //转换成JSON返回的是byte[] + if errs != nil { + fmt.Println(errs.Error()) + } + fmt.Println("jwt:", string(jwt)) + + // todo 需要兼容 + database, errs := json.MarshalIndent(config.DatabasesConfig, "", " ") //转换成JSON返回的是byte[] + if errs != nil { + fmt.Println(errs.Error()) + } + fmt.Println("database:", string(database)) + + gen, errs := json.MarshalIndent(config.GenConfig, "", " ") //转换成JSON返回的是byte[] + if errs != nil { + fmt.Println(errs.Error()) + } + fmt.Println("gen:", string(gen)) + + loggerConfig, errs := json.MarshalIndent(config.LoggerConfig, "", " ") //转换成JSON返回的是byte[] + if errs != nil { + fmt.Println(errs.Error()) + } + fmt.Println("logger:", string(loggerConfig)) + +} diff --git a/cmd/migrate/migration/init.go b/cmd/migrate/migration/init.go new file mode 100644 index 0000000..739e6b4 --- /dev/null +++ b/cmd/migrate/migration/init.go @@ -0,0 +1,66 @@ +package migration + +import ( + "log" + "path/filepath" + "sort" + "sync" + + "gorm.io/gorm" +) + +var Migrate = &Migration{ + version: make(map[string]func(db *gorm.DB, version string) error), +} + +type Migration struct { + db *gorm.DB + version map[string]func(db *gorm.DB, version string) error + mutex sync.Mutex +} + +func (e *Migration) GetDb() *gorm.DB { + return e.db +} + +func (e *Migration) SetDb(db *gorm.DB) { + e.db = db +} + +func (e *Migration) SetVersion(k string, f func(db *gorm.DB, version string) error) { + e.mutex.Lock() + defer e.mutex.Unlock() + e.version[k] = f +} + +func (e *Migration) Migrate() { + versions := make([]string, 0) + for k := range e.version { + versions = append(versions, k) + } + if !sort.StringsAreSorted(versions) { + sort.Strings(versions) + } + var err error + var count int64 + for _, v := range versions { + err = e.db.Table("sys_migration").Where("version = ?", v).Count(&count).Error + if err != nil { + log.Fatalln(err) + } + if count > 0 { + log.Println(count) + count = 0 + continue + } + err = (e.version[v])(e.db.Debug(), v) + if err != nil { + log.Fatalln(err) + } + } +} + +func GetFilename(s string) string { + s = filepath.Base(s) + return s[:13] +} diff --git a/cmd/migrate/migration/models/by.go b/cmd/migrate/migration/models/by.go new file mode 100644 index 0000000..c9dd906 --- /dev/null +++ b/cmd/migrate/migration/models/by.go @@ -0,0 +1,22 @@ +package models + +import ( + "time" + + "gorm.io/gorm" +) + +type ControlBy struct { + CreateBy int `json:"createBy" gorm:"index;comment:创建者"` + UpdateBy int `json:"updateBy" gorm:"index;comment:更新者"` +} + +type Model struct { + Id int `json:"id" gorm:"primaryKey;autoIncrement;comment:主键编码"` +} + +type ModelTime struct { + CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"` + UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"` + DeletedAt gorm.DeletedAt `json:"-" gorm:"index;comment:删除时间"` +} diff --git a/cmd/migrate/migration/models/casbin_rule.go b/cmd/migrate/migration/models/casbin_rule.go new file mode 100644 index 0000000..bab7203 --- /dev/null +++ b/cmd/migrate/migration/models/casbin_rule.go @@ -0,0 +1,17 @@ +package models + +// CasbinRule sys_casbin_rule +type CasbinRule struct { + ID uint `gorm:"primaryKey;autoIncrement"` + Ptype string `gorm:"size:512;uniqueIndex:unique_index"` + V0 string `gorm:"size:512;uniqueIndex:unique_index"` + V1 string `gorm:"size:512;uniqueIndex:unique_index"` + V2 string `gorm:"size:512;uniqueIndex:unique_index"` + V3 string `gorm:"size:512;uniqueIndex:unique_index"` + V4 string `gorm:"size:512;uniqueIndex:unique_index"` + V5 string `gorm:"size:512;uniqueIndex:unique_index"` +} + +func (CasbinRule) TableName() string { + return "sys_casbin_rule" +} diff --git a/cmd/migrate/migration/models/initdb.go b/cmd/migrate/migration/models/initdb.go new file mode 100644 index 0000000..ba7f4ca --- /dev/null +++ b/cmd/migrate/migration/models/initdb.go @@ -0,0 +1,72 @@ +package models + +import ( + "fmt" + "go-admin/common/global" + "io/ioutil" + "log" + "strings" + + "gorm.io/gorm" +) + +func InitDb(db *gorm.DB) (err error) { + filePath := "config/db.sql" + if global.Driver == "postgres" { + filePath := "config/db.sql" + if err = ExecSql(db, filePath); err != nil { + return err + } + filePath = "config/pg.sql" + err = ExecSql(db, filePath) + } else if global.Driver == "mysql" { + filePath = "config/db-begin-mysql.sql" + if err = ExecSql(db, filePath); err != nil { + return err + } + filePath = "config/db.sql" + if err = ExecSql(db, filePath); err != nil { + return err + } + filePath = "config/db-end-mysql.sql" + err = ExecSql(db, filePath) + } else { + err = ExecSql(db, filePath) + } + return err +} + +func ExecSql(db *gorm.DB, filePath string) error { + sql, err := Ioutil(filePath) + if err != nil { + fmt.Println("数据库基础数据初始化脚本读取失败!原因:", err.Error()) + return err + } + sqlList := strings.Split(sql, ";") + for i := 0; i < len(sqlList)-1; i++ { + if strings.Contains(sqlList[i], "--") { + fmt.Println(sqlList[i]) + continue + } + sql := strings.Replace(sqlList[i]+";", "\n", "", -1) + sql = strings.TrimSpace(sql) + if err = db.Exec(sql).Error; err != nil { + log.Printf("error sql: %s", sql) + if !strings.Contains(err.Error(), "Query was empty") { + return err + } + } + } + return nil +} + +func Ioutil(filePath string) (string, error) { + if contents, err := ioutil.ReadFile(filePath); err == nil { + //因为contents是[]byte类型,直接转换成string类型后会多一行空格,需要使用strings.Replace替换换行符 + result := strings.Replace(string(contents), "\n", "", 1) + fmt.Println("Use ioutil.ReadFile to read a file:", result) + return result, nil + } else { + return "", err + } +} diff --git a/cmd/migrate/migration/models/model.go b/cmd/migrate/migration/models/model.go new file mode 100644 index 0000000..4a1c439 --- /dev/null +++ b/cmd/migrate/migration/models/model.go @@ -0,0 +1,11 @@ +package models + +import ( + "time" +) + +type BaseModel struct { + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` +} diff --git a/cmd/migrate/migration/models/role_dept.go b/cmd/migrate/migration/models/role_dept.go new file mode 100644 index 0000000..0aae705 --- /dev/null +++ b/cmd/migrate/migration/models/role_dept.go @@ -0,0 +1,10 @@ +package models + +type SysRoleDept struct { + RoleId int `gorm:"size:11;primaryKey"` + DeptId int `gorm:"size:11;primaryKey"` +} + +func (SysRoleDept) TableName() string { + return "sys_role_dept" +} diff --git a/cmd/migrate/migration/models/sys_api.go b/cmd/migrate/migration/models/sys_api.go new file mode 100644 index 0000000..8d75170 --- /dev/null +++ b/cmd/migrate/migration/models/sys_api.go @@ -0,0 +1,16 @@ +package models + +type SysApi struct { + Id int `json:"id" gorm:"primaryKey;autoIncrement;comment:主键编码"` + Handle string `json:"handle" gorm:"size:128;comment:handle"` + Title string `json:"title" gorm:"size:128;comment:标题"` + Path string `json:"path" gorm:"size:128;comment:地址"` + Type string `json:"type" gorm:"size:16;comment:接口类型"` + Action string `json:"action" gorm:"size:16;comment:请求类型"` + ModelTime + ControlBy +} + +func (SysApi) TableName() string { + return "sys_api" +} \ No newline at end of file diff --git a/cmd/migrate/migration/models/sys_columns.go b/cmd/migrate/migration/models/sys_columns.go new file mode 100644 index 0000000..2c8377e --- /dev/null +++ b/cmd/migrate/migration/models/sys_columns.go @@ -0,0 +1,44 @@ +package models + +type SysColumns struct { + ColumnId int `gorm:"primaryKey;autoIncrement" json:"columnId"` + TableId int `gorm:"" json:"tableId"` + ColumnName string `gorm:"size:128;" json:"columnName"` + ColumnComment string `gorm:"column:column_comment;size:128;" json:"columnComment"` + ColumnType string `gorm:"column:column_type;size:128;" json:"columnType"` + GoType string `gorm:"column:go_type;size:128;" json:"goType"` + GoField string `gorm:"column:go_field;size:128;" json:"goField"` + JsonField string `gorm:"column:json_field;size:128;" json:"jsonField"` + IsPk string `gorm:"column:is_pk;size:4;" json:"isPk"` + IsIncrement string `gorm:"column:is_increment;size:4;" json:"isIncrement"` + IsRequired string `gorm:"column:is_required;size:4;" json:"isRequired"` + IsInsert string `gorm:"column:is_insert;size:4;" json:"isInsert"` + IsEdit string `gorm:"column:is_edit;size:4;" json:"isEdit"` + IsList string `gorm:"column:is_list;size:4;" json:"isList"` + IsQuery string `gorm:"column:is_query;size:4;" json:"isQuery"` + QueryType string `gorm:"column:query_type;size:128;" json:"queryType"` + HtmlType string `gorm:"column:html_type;size:128;" json:"htmlType"` + DictType string `gorm:"column:dict_type;size:128;" json:"dictType"` + Sort int `gorm:"column:sort;" json:"sort"` + List string `gorm:"column:list;size:1;" json:"list"` + Pk bool `gorm:"column:pk;size:1;" json:"pk"` + Required bool `gorm:"column:required;size:1;" json:"required"` + SuperColumn bool `gorm:"column:super_column;size:1;" json:"superColumn"` + UsableColumn bool `gorm:"column:usable_column;size:1;" json:"usableColumn"` + Increment bool `gorm:"column:increment;size:1;" json:"increment"` + Insert bool `gorm:"column:insert;size:1;" json:"insert"` + Edit bool `gorm:"column:edit;size:1;" json:"edit"` + Query bool `gorm:"column:query;size:1;" json:"query"` + Remark string `gorm:"column:remark;size:255;" json:"remark"` + FkTableName string `gorm:"" json:"fkTableName"` + FkTableNameClass string `gorm:"" json:"fkTableNameClass"` + FkTableNamePackage string `gorm:"" json:"fkTableNamePackage"` + FkLabelId string `gorm:"" json:"fkLabelId"` + FkLabelName string `gorm:"size:255;" json:"fkLabelName"` + ModelTime + ControlBy +} + +func (SysColumns) TableName() string { + return "sys_columns" +} diff --git a/cmd/migrate/migration/models/sys_config.go b/cmd/migrate/migration/models/sys_config.go new file mode 100644 index 0000000..bd79da3 --- /dev/null +++ b/cmd/migrate/migration/models/sys_config.go @@ -0,0 +1,17 @@ +package models + +type SysConfig struct { + Model + ConfigName string `json:"configName" gorm:"type:varchar(128);comment:ConfigName"` + ConfigKey string `json:"configKey" gorm:"type:varchar(128);comment:ConfigKey"` + ConfigValue string `json:"configValue" gorm:"type:varchar(255);comment:ConfigValue"` + ConfigType string `json:"configType" gorm:"type:varchar(64);comment:ConfigType"` + IsFrontend int `json:"isFrontend" gorm:"type:varchar(64);comment:是否前台"` + Remark string `json:"remark" gorm:"type:varchar(128);comment:Remark"` + ControlBy + ModelTime +} + +func (SysConfig) TableName() string { + return "sys_config" +} diff --git a/cmd/migrate/migration/models/sys_dept.go b/cmd/migrate/migration/models/sys_dept.go new file mode 100644 index 0000000..5f74c62 --- /dev/null +++ b/cmd/migrate/migration/models/sys_dept.go @@ -0,0 +1,19 @@ +package models + +type SysDept struct { + DeptId int `json:"deptId" gorm:"primaryKey;autoIncrement;"` //部门编码 + ParentId int `json:"parentId" gorm:""` //上级部门 + DeptPath string `json:"deptPath" gorm:"size:255;"` // + DeptName string `json:"deptName" gorm:"size:128;"` //部门名称 + Sort int `json:"sort" gorm:"size:4;"` //排序 + Leader string `json:"leader" gorm:"size:128;"` //负责人 + Phone string `json:"phone" gorm:"size:11;"` //手机 + Email string `json:"email" gorm:"size:64;"` //邮箱 + Status int `json:"status" gorm:"size:4;"` //状态 + ControlBy + ModelTime +} + +func (SysDept) TableName() string { + return "sys_dept" +} diff --git a/cmd/migrate/migration/models/sys_dict_data.go b/cmd/migrate/migration/models/sys_dict_data.go new file mode 100644 index 0000000..c2936c8 --- /dev/null +++ b/cmd/migrate/migration/models/sys_dict_data.go @@ -0,0 +1,21 @@ +package models + +type DictData struct { + DictCode int `gorm:"primaryKey;autoIncrement;" json:"dictCode" example:"1"` //字典编码 + DictSort int `gorm:"" json:"dictSort"` //显示顺序 + DictLabel string `gorm:"size:128;" json:"dictLabel"` //数据标签 + DictValue string `gorm:"size:255;" json:"dictValue"` //数据键值 + DictType string `gorm:"size:64;" json:"dictType"` //字典类型 + CssClass string `gorm:"size:128;" json:"cssClass"` // + ListClass string `gorm:"size:128;" json:"listClass"` // + IsDefault string `gorm:"size:8;" json:"isDefault"` // + Status int `gorm:"size:4;" json:"status"` //状态 + Default string `gorm:"size:8;" json:"default"` // + Remark string `gorm:"size:255;" json:"remark"` //备注 + ControlBy + ModelTime +} + +func (DictData) TableName() string { + return "sys_dict_data" +} diff --git a/cmd/migrate/migration/models/sys_dict_type.go b/cmd/migrate/migration/models/sys_dict_type.go new file mode 100644 index 0000000..4c79e37 --- /dev/null +++ b/cmd/migrate/migration/models/sys_dict_type.go @@ -0,0 +1,15 @@ +package models + +type DictType struct { + DictId int `gorm:"primaryKey;autoIncrement;" json:"dictId"` + DictName string `gorm:"size:128;" json:"dictName"` //字典名称 + DictType string `gorm:"size:128;" json:"dictType"` //字典类型 + Status int `gorm:"size:4;" json:"status"` //状态 + Remark string `gorm:"size:255;" json:"remark"` //备注 + ControlBy + ModelTime +} + +func (DictType) TableName() string { + return "sys_dict_type" +} diff --git a/cmd/migrate/migration/models/sys_job.go b/cmd/migrate/migration/models/sys_job.go new file mode 100644 index 0000000..e826d10 --- /dev/null +++ b/cmd/migrate/migration/models/sys_job.go @@ -0,0 +1,21 @@ +package models + +type SysJob struct { + JobId int `json:"jobId" gorm:"primaryKey;autoIncrement"` // 编码 + JobName string `json:"jobName" gorm:"size:255;"` // 名称 + JobGroup string `json:"jobGroup" gorm:"size:255;"` // 任务分组 + JobType int `json:"jobType" gorm:"size:1;"` // 任务类型 + CronExpression string `json:"cronExpression" gorm:"size:255;"` // cron表达式 + InvokeTarget string `json:"invokeTarget" gorm:"size:255;"` // 调用目标 + Args string `json:"args" gorm:"size:255;"` // 目标参数 + MisfirePolicy int `json:"misfirePolicy" gorm:"size:255;"` // 执行策略 + Concurrent int `json:"concurrent" gorm:"size:1;"` // 是否并发 + Status int `json:"status" gorm:"size:1;"` // 状态 + EntryId int `json:"entry_id" gorm:"size:11;"` // job启动时返回的id + ModelTime + ControlBy +} + +func (SysJob) TableName() string { + return "sys_job" +} diff --git a/cmd/migrate/migration/models/sys_login_log.go b/cmd/migrate/migration/models/sys_login_log.go new file mode 100644 index 0000000..f4a878b --- /dev/null +++ b/cmd/migrate/migration/models/sys_login_log.go @@ -0,0 +1,26 @@ +package models + +import ( + "time" +) + +type SysLoginLog struct { + Model + Username string `json:"username" gorm:"type:varchar(128);comment:用户名"` + Status string `json:"status" gorm:"type:varchar(4);comment:状态"` + Ipaddr string `json:"ipaddr" gorm:"type:varchar(255);comment:ip地址"` + LoginLocation string `json:"loginLocation" gorm:"type:varchar(255);comment:归属地"` + Browser string `json:"browser" gorm:"type:varchar(255);comment:浏览器"` + Os string `json:"os" gorm:"type:varchar(255);comment:系统"` + Platform string `json:"platform" gorm:"type:varchar(255);comment:固件"` + LoginTime time.Time `json:"loginTime" gorm:"type:timestamp;comment:登录时间"` + Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"` + Msg string `json:"msg" gorm:"type:varchar(255);comment:信息"` + CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"` + UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"` + ControlBy +} + +func (SysLoginLog) TableName() string { + return "sys_login_log" +} diff --git a/cmd/migrate/migration/models/sys_menu.go b/cmd/migrate/migration/models/sys_menu.go new file mode 100644 index 0000000..c69252f --- /dev/null +++ b/cmd/migrate/migration/models/sys_menu.go @@ -0,0 +1,27 @@ +package models + +type SysMenu struct { + MenuId int `json:"menuId" gorm:"primaryKey;autoIncrement"` + MenuName string `json:"menuName" gorm:"size:128;"` + Title string `json:"title" gorm:"size:128;"` + Icon string `json:"icon" gorm:"size:128;"` + Path string `json:"path" gorm:"size:128;"` + Paths string `json:"paths" gorm:"size:128;"` + MenuType string `json:"menuType" gorm:"size:1;"` + Action string `json:"action" gorm:"size:16;"` + Permission string `json:"permission" gorm:"size:255;"` + ParentId int `json:"parentId" gorm:"size:11;"` + NoCache bool `json:"noCache" gorm:"size:8;"` + Breadcrumb string `json:"breadcrumb" gorm:"size:255;"` + Component string `json:"component" gorm:"size:255;"` + Sort int `json:"sort" gorm:"size:4;"` + Visible string `json:"visible" gorm:"size:1;"` + IsFrame string `json:"isFrame" gorm:"size:1;DEFAULT:0;"` + SysApi []SysApi `json:"sysApi" gorm:"many2many:sys_menu_api_rule"` + ControlBy + ModelTime +} + +func (SysMenu) TableName() string { + return "sys_menu" +} \ No newline at end of file diff --git a/cmd/migrate/migration/models/sys_opera_log.go b/cmd/migrate/migration/models/sys_opera_log.go new file mode 100644 index 0000000..5055b96 --- /dev/null +++ b/cmd/migrate/migration/models/sys_opera_log.go @@ -0,0 +1,34 @@ +package models + +import ( + "time" +) + +type SysOperaLog struct { + Model + Title string `json:"title" gorm:"type:varchar(255);comment:操作模块"` + BusinessType string `json:"businessType" gorm:"type:varchar(128);comment:操作类型"` + BusinessTypes string `json:"businessTypes" gorm:"type:varchar(128);comment:BusinessTypes"` + Method string `json:"method" gorm:"type:varchar(128);comment:函数"` + RequestMethod string `json:"requestMethod" gorm:"type:varchar(128);comment:请求方式: GET POST PUT DELETE"` + OperatorType string `json:"operatorType" gorm:"type:varchar(128);comment:操作类型"` + OperName string `json:"operName" gorm:"type:varchar(128);comment:操作者"` + DeptName string `json:"deptName" gorm:"type:varchar(128);comment:部门名称"` + OperUrl string `json:"operUrl" gorm:"type:varchar(255);comment:访问地址"` + OperIp string `json:"operIp" gorm:"type:varchar(128);comment:客户端ip"` + OperLocation string `json:"operLocation" gorm:"type:varchar(128);comment:访问位置"` + OperParam string `json:"operParam" gorm:"type:text;comment:请求参数"` + Status string `json:"status" gorm:"type:varchar(4);comment:操作状态 1:正常 2:关闭"` + OperTime time.Time `json:"operTime" gorm:"type:timestamp;comment:操作时间"` + JsonResult string `json:"jsonResult" gorm:"type:varchar(255);comment:返回数据"` + Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"` + LatencyTime string `json:"latencyTime" gorm:"type:varchar(128);comment:耗时"` + UserAgent string `json:"userAgent" gorm:"type:varchar(255);comment:ua"` + CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"` + UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"` + ControlBy +} + +func (SysOperaLog) TableName() string { + return "sys_opera_log" +} diff --git a/cmd/migrate/migration/models/sys_post.go b/cmd/migrate/migration/models/sys_post.go new file mode 100644 index 0000000..195208a --- /dev/null +++ b/cmd/migrate/migration/models/sys_post.go @@ -0,0 +1,16 @@ +package models + +type SysPost struct { + PostId int `gorm:"primaryKey;autoIncrement" json:"postId"` //岗位编号 + PostName string `gorm:"size:128;" json:"postName"` //岗位名称 + PostCode string `gorm:"size:128;" json:"postCode"` //岗位代码 + Sort int `gorm:"size:4;" json:"sort"` //岗位排序 + Status int `gorm:"size:4;" json:"status"` //状态 + Remark string `gorm:"size:255;" json:"remark"` //描述 + ControlBy + ModelTime +} + +func (SysPost) TableName() string { + return "sys_post" +} \ No newline at end of file diff --git a/cmd/migrate/migration/models/sys_role.go b/cmd/migrate/migration/models/sys_role.go new file mode 100644 index 0000000..0bd5ee3 --- /dev/null +++ b/cmd/migrate/migration/models/sys_role.go @@ -0,0 +1,20 @@ +package models + +type SysRole struct { + RoleId int `json:"roleId" gorm:"primaryKey;autoIncrement"` // 角色编码 + RoleName string `json:"roleName" gorm:"size:128;"` // 角色名称 + Status string `json:"status" gorm:"size:4;"` // + RoleKey string `json:"roleKey" gorm:"size:128;"` //角色代码 + RoleSort int `json:"roleSort" gorm:""` //角色排序 + Flag string `json:"flag" gorm:"size:128;"` // + Remark string `json:"remark" gorm:"size:255;"` //备注 + Admin bool `json:"admin" gorm:"size:4;"` + DataScope string `json:"dataScope" gorm:"size:128;"` + SysMenu []SysMenu `json:"sysMenu" gorm:"many2many:sys_role_menu;foreignKey:RoleId;joinForeignKey:role_id;references:MenuId;joinReferences:menu_id;"` + ControlBy + ModelTime +} + +func (SysRole) TableName() string { + return "sys_role" +} \ No newline at end of file diff --git a/cmd/migrate/migration/models/sys_tables.go b/cmd/migrate/migration/models/sys_tables.go new file mode 100644 index 0000000..0e53032 --- /dev/null +++ b/cmd/migrate/migration/models/sys_tables.go @@ -0,0 +1,37 @@ +package models + +type SysTables struct { + TableId int `gorm:"primaryKey;autoIncrement" json:"tableId"` //表编码 + TBName string `gorm:"column:table_name;size:255;" json:"tableName"` //表名称 + TableComment string `gorm:"size:255;" json:"tableComment"` //表备注 + ClassName string `gorm:"size:255;" json:"className"` //类名 + TplCategory string `gorm:"size:255;" json:"tplCategory"` // + PackageName string `gorm:"size:255;" json:"packageName"` //包名 + ModuleName string `gorm:"size:255;" json:"moduleName"` //go文件名 + ModuleFrontName string `gorm:"size:255;comment:前端文件名;" json:"moduleFrontName"` //前端文件名 + BusinessName string `gorm:"size:255;" json:"businessName"` // + FunctionName string `gorm:"size:255;" json:"functionName"` //功能名称 + FunctionAuthor string `gorm:"size:255;" json:"functionAuthor"` //功能作者 + PkColumn string `gorm:"size:255;" json:"pkColumn"` + PkGoField string `gorm:"size:255;" json:"pkGoField"` + PkJsonField string `gorm:"size:255;" json:"pkJsonField"` + Options string `gorm:"size:255;" json:"options"` + TreeCode string `gorm:"size:255;" json:"treeCode"` + TreeParentCode string `gorm:"size:255;" json:"treeParentCode"` + TreeName string `gorm:"size:255;" json:"treeName"` + Tree bool `gorm:"size:1;default:0;" json:"tree"` + Crud bool `gorm:"size:1;default:1;" json:"crud"` + Remark string `gorm:"size:255;" json:"remark"` + IsDataScope int `gorm:"size:1;" json:"isDataScope"` + IsActions int `gorm:"size:1;" json:"isActions"` + IsAuth int `gorm:"size:1;" json:"isAuth"` + IsLogicalDelete string `gorm:"size:1;" json:"isLogicalDelete"` + LogicalDelete bool `gorm:"size:1;" json:"logicalDelete"` + LogicalDeleteColumn string `gorm:"size:128;" json:"logicalDeleteColumn"` + ModelTime + ControlBy +} + +func (SysTables) TableName() string { + return "sys_tables" +} diff --git a/cmd/migrate/migration/models/sys_user.go b/cmd/migrate/migration/models/sys_user.go new file mode 100644 index 0000000..31e3637 --- /dev/null +++ b/cmd/migrate/migration/models/sys_user.go @@ -0,0 +1,48 @@ +package models + +import ( + "golang.org/x/crypto/bcrypt" + "gorm.io/gorm" +) + +type SysUser struct { + UserId int `gorm:"primaryKey;autoIncrement;comment:编码" json:"userId"` + Username string `json:"username" gorm:"type:varchar(64);comment:用户名"` + Password string `json:"-" gorm:"type:varchar(128);comment:密码"` + NickName string `json:"nickName" gorm:"type:varchar(128);comment:昵称"` + Phone string `json:"phone" gorm:"type:varchar(11);comment:手机号"` + RoleId int `json:"roleId" gorm:"type:bigint;comment:角色ID"` + Salt string `json:"-" gorm:"type:varchar(255);comment:加盐"` + Avatar string `json:"avatar" gorm:"type:varchar(255);comment:头像"` + Sex string `json:"sex" gorm:"type:varchar(255);comment:性别"` + Email string `json:"email" gorm:"type:varchar(128);comment:邮箱"` + DeptId int `json:"deptId" gorm:"type:bigint;comment:部门"` + PostId int `json:"postId" gorm:"type:bigint;comment:岗位"` + Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"` + Status string `json:"status" gorm:"type:varchar(4);comment:状态"` + ControlBy + ModelTime +} + +func (*SysUser) TableName() string { + return "sys_user" +} + +// Encrypt 加密 +func (e *SysUser) Encrypt() (err error) { + if e.Password == "" { + return + } + + var hash []byte + if hash, err = bcrypt.GenerateFromPassword([]byte(e.Password), bcrypt.DefaultCost); err != nil { + return + } else { + e.Password = string(hash) + return + } +} + +func (e *SysUser) BeforeCreate(_ *gorm.DB) error { + return e.Encrypt() +} diff --git a/cmd/migrate/migration/models/tb_demo.go b/cmd/migrate/migration/models/tb_demo.go new file mode 100644 index 0000000..7d30541 --- /dev/null +++ b/cmd/migrate/migration/models/tb_demo.go @@ -0,0 +1,12 @@ +package models + +type TbDemo struct { + Model + Name string `json:"name" gorm:"type:varchar(128);comment:名称"` + ModelTime + ControlBy +} + +func (TbDemo) TableName() string { + return "tb_demo" +} diff --git a/cmd/migrate/migration/version-local/doc.go b/cmd/migrate/migration/version-local/doc.go new file mode 100644 index 0000000..2cec8bc --- /dev/null +++ b/cmd/migrate/migration/version-local/doc.go @@ -0,0 +1,8 @@ +package version_local + +func init() { +} + +/** +开发者项目的迁移脚本放在这个目录里,init写法参考version目录里的migrate或者自动生成 +*/ diff --git a/cmd/migrate/migration/version/1599190683659_tables.go b/cmd/migrate/migration/version/1599190683659_tables.go new file mode 100644 index 0000000..df2dafa --- /dev/null +++ b/cmd/migrate/migration/version/1599190683659_tables.go @@ -0,0 +1,53 @@ +package version + +import ( + "github.com/go-admin-team/go-admin-core/sdk/config" + "runtime" + + "go-admin/cmd/migrate/migration" + "go-admin/cmd/migrate/migration/models" + common "go-admin/common/models" + + "gorm.io/gorm" +) + +func init() { + _, fileName, _, _ := runtime.Caller(0) + migration.Migrate.SetVersion(migration.GetFilename(fileName), _1599190683659Tables) +} + +func _1599190683659Tables(db *gorm.DB, version string) error { + return db.Transaction(func(tx *gorm.DB) error { + if config.DatabaseConfig.Driver == "mysql" { + tx = tx.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4") + } + err := tx.Migrator().AutoMigrate( + new(models.SysDept), + new(models.SysConfig), + new(models.SysTables), + new(models.SysColumns), + new(models.SysMenu), + new(models.SysLoginLog), + new(models.SysOperaLog), + new(models.SysRoleDept), + new(models.SysUser), + new(models.SysRole), + new(models.SysPost), + new(models.DictData), + new(models.DictType), + new(models.SysJob), + new(models.SysConfig), + new(models.SysApi), + new(models.TbDemo), + ) + if err != nil { + return err + } + if err := models.InitDb(tx); err != nil { + return err + } + return tx.Create(&common.Migration{ + Version: version, + }).Error + }) +} diff --git a/cmd/migrate/migration/version/1653638869132_migrate.go b/cmd/migrate/migration/version/1653638869132_migrate.go new file mode 100644 index 0000000..59a8fa0 --- /dev/null +++ b/cmd/migrate/migration/version/1653638869132_migrate.go @@ -0,0 +1,48 @@ +package version + +import ( + "go-admin/cmd/migrate/migration/models" + common "go-admin/common/models" + "gorm.io/gorm" + "runtime" + "strconv" + + "go-admin/cmd/migrate/migration" +) + +func init() { + _, fileName, _, _ := runtime.Caller(0) + migration.Migrate.SetVersion(migration.GetFilename(fileName), _1653638869132Test) +} + +func _1653638869132Test(db *gorm.DB, version string) error { + return db.Transaction(func(tx *gorm.DB) error { + var list []models.SysMenu + err := tx.Model(&models.SysMenu{}).Order("parent_id,menu_id").Find(&list).Error + if err != nil { + return err + } + for _, v := range list { + if v.ParentId == 0 { + v.Paths = "/0/" + strconv.Itoa(v.MenuId) + } else { + var e models.SysMenu + err = tx.Model(&models.SysMenu{}).Where("menu_id=?", v.ParentId).First(&e).Error + if err != nil { + if err == gorm.ErrRecordNotFound { + continue + } + return err + } + v.Paths = e.Paths + "/" + strconv.Itoa(v.MenuId) + } + err = tx.Model(&v).Update("paths", v.Paths).Error + if err != nil { + return err + } + } + return tx.Create(&common.Migration{ + Version: version, + }).Error + }) +} diff --git a/cmd/migrate/server.go b/cmd/migrate/server.go new file mode 100644 index 0000000..fa25741 --- /dev/null +++ b/cmd/migrate/server.go @@ -0,0 +1,106 @@ +package migrate + +import ( + "bytes" + "fmt" + "github.com/go-admin-team/go-admin-core/sdk" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "strconv" + "text/template" + "time" + + "github.com/go-admin-team/go-admin-core/config/source/file" + "github.com/spf13/cobra" + + "github.com/go-admin-team/go-admin-core/sdk/config" + "go-admin/cmd/migrate/migration" + _ "go-admin/cmd/migrate/migration/version" + _ "go-admin/cmd/migrate/migration/version-local" + "go-admin/common/database" + "go-admin/common/models" +) + +var ( + configYml string + generate bool + goAdmin bool + host string + StartCmd = &cobra.Command{ + Use: "migrate", + Short: "Initialize the database", + Example: "go-admin migrate -c config/settings.yml", + Run: func(cmd *cobra.Command, args []string) { + run() + }, + } +) + +// fixme 在您看不见代码的时候运行迁移,我觉得是不安全的,所以编译后最好不要去执行迁移 +func init() { + StartCmd.PersistentFlags().StringVarP(&configYml, "config", "c", "config/settings.yml", "Start server with provided configuration file") + StartCmd.PersistentFlags().BoolVarP(&generate, "generate", "g", false, "generate migration file") + StartCmd.PersistentFlags().BoolVarP(&goAdmin, "goAdmin", "a", false, "generate go-admin migration file") + StartCmd.PersistentFlags().StringVarP(&host, "domain", "d", "*", "select tenant host") +} + +func run() { + + if !generate { + fmt.Println(`start init`) + //1. 读取配置 + config.Setup( + file.NewSource(file.WithPath(configYml)), + initDB, + ) + } else { + fmt.Println(`generate migration file`) + _ = genFile() + } +} + +func migrateModel() error { + if host == "" { + host = "*" + } + db := sdk.Runtime.GetDbByKey(host) + if config.DatabasesConfig[host].Driver == "mysql" { + //初始化数据库时候用 + db.Set("gorm:table_options", "ENGINE=InnoDB CHARSET=utf8mb4") + } + err := db.Debug().AutoMigrate(&models.Migration{}) + if err != nil { + return err + } + migration.Migrate.SetDb(db.Debug()) + migration.Migrate.Migrate() + return err +} +func initDB() { + //3. 初始化数据库链接 + database.Setup() + //4. 数据库迁移 + fmt.Println("数据库迁移开始") + _ = migrateModel() + fmt.Println(`数据库基础数据初始化成功`) +} + +func genFile() error { + t1, err := template.ParseFiles("template/migrate.template") + if err != nil { + return err + } + m := map[string]string{} + m["GenerateTime"] = strconv.FormatInt(time.Now().UnixNano()/1e6, 10) + m["Package"] = "version_local" + if goAdmin { + m["Package"] = "version" + } + var b1 bytes.Buffer + err = t1.Execute(&b1, m) + if goAdmin { + pkg.FileCreate(b1, "./cmd/migrate/migration/version/"+m["GenerateTime"]+"_migrate.go") + } else { + pkg.FileCreate(b1, "./cmd/migrate/migration/version-local/"+m["GenerateTime"]+"_migrate.go") + } + return nil +} diff --git a/cmd/version/server.go b/cmd/version/server.go new file mode 100644 index 0000000..329e1ea --- /dev/null +++ b/cmd/version/server.go @@ -0,0 +1,26 @@ +package version + +import ( + "fmt" + "github.com/spf13/cobra" + "go-admin/common/global" +) + +var ( + StartCmd = &cobra.Command{ + Use: "version", + Short: "Get version info", + Example: "go-admin version", + PreRun: func(cmd *cobra.Command, args []string) { + + }, + RunE: func(cmd *cobra.Command, args []string) error { + return run() + }, + } +) + +func run() error { + fmt.Println(global.Version) + return nil +} diff --git a/common/actions/create.go b/common/actions/create.go new file mode 100644 index 0000000..81989e5 --- /dev/null +++ b/common/actions/create.go @@ -0,0 +1,49 @@ +package actions + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + + "go-admin/common/dto" + "go-admin/common/models" +) + +// CreateAction 通用新增动作 +func CreateAction(control dto.Control) gin.HandlerFunc { + return func(c *gin.Context) { + log := api.GetRequestLogger(c) + db, err := pkg.GetOrm(c) + if err != nil { + log.Error(err) + return + } + + //新增操作 + req := control.Generate() + err = req.Bind(c) + if err != nil { + response.Error(c, http.StatusUnprocessableEntity, err, err.Error()) + return + } + var object models.ActiveRecord + object, err = req.GenerateM() + if err != nil { + response.Error(c, 500, err, "模型生成失败") + return + } + object.SetCreateBy(user.GetUserId(c)) + err = db.WithContext(c).Create(object).Error + if err != nil { + log.Errorf("Create error: %s", err) + response.Error(c, 500, err, "创建失败") + return + } + response.OK(c, object.GetId(), "创建成功") + c.Next() + } +} diff --git a/common/actions/delete.go b/common/actions/delete.go new file mode 100644 index 0000000..811b9bf --- /dev/null +++ b/common/actions/delete.go @@ -0,0 +1,61 @@ +package actions + +import ( + "net/http" + + "github.com/gin-gonic/gin" + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + + "go-admin/common/dto" + "go-admin/common/models" +) + +// DeleteAction 通用删除动作 +func DeleteAction(control dto.Control) gin.HandlerFunc { + return func(c *gin.Context) { + db, err := pkg.GetOrm(c) + if err != nil { + log.Error(err) + return + } + + msgID := pkg.GenerateMsgIDFromContext(c) + //删除操作 + req := control.Generate() + err = req.Bind(c) + if err != nil { + log.Errorf("MsgID[%s] Bind error: %s", msgID, err) + response.Error(c, http.StatusUnprocessableEntity, err, "参数验证失败") + return + } + var object models.ActiveRecord + object, err = req.GenerateM() + if err != nil { + response.Error(c, 500, err, "模型生成失败") + return + } + + object.SetUpdateBy(user.GetUserId(c)) + + //数据权限检查 + p := GetPermissionFromContext(c) + + db = db.WithContext(c).Scopes( + Permission(object.TableName(), p), + ).Where(req.GetId()).Delete(object) + if err = db.Error; err != nil { + log.Errorf("MsgID[%s] Delete error: %s", msgID, err) + response.Error(c, 500, err, "删除失败") + return + } + if db.RowsAffected == 0 { + response.Error(c, http.StatusForbidden, nil, "无权删除该数据") + return + } + response.OK(c, object.GetId(), "删除成功") + c.Next() + } +} diff --git a/common/actions/index.go b/common/actions/index.go new file mode 100644 index 0000000..4453094 --- /dev/null +++ b/common/actions/index.go @@ -0,0 +1,58 @@ +package actions + +import ( + "errors" + "net/http" + + "github.com/gin-gonic/gin" + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + "gorm.io/gorm" + + "go-admin/common/dto" + "go-admin/common/models" +) + +// IndexAction 通用查询动作 +func IndexAction(m models.ActiveRecord, d dto.Index, f func() interface{}) gin.HandlerFunc { + return func(c *gin.Context) { + db, err := pkg.GetOrm(c) + if err != nil { + log.Error(err) + return + } + + msgID := pkg.GenerateMsgIDFromContext(c) + list := f() + object := m.Generate() + req := d.Generate() + var count int64 + + //查询列表 + err = req.Bind(c) + if err != nil { + response.Error(c, http.StatusUnprocessableEntity, err, "参数验证失败") + return + } + + //数据权限检查 + p := GetPermissionFromContext(c) + + err = db.WithContext(c).Model(object). + Scopes( + dto.MakeCondition(req.GetNeedSearch()), + dto.Paginate(req.GetPageSize(), req.GetPageIndex()), + Permission(object.TableName(), p), + ). + Find(list).Limit(-1).Offset(-1). + Count(&count).Error + if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { + log.Errorf("MsgID[%s] Index error: %s", msgID, err) + response.Error(c, 500, err, "查询失败") + return + } + response.PageOK(c, list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") + c.Next() + } +} diff --git a/common/actions/permission.go b/common/actions/permission.go new file mode 100644 index 0000000..82532c4 --- /dev/null +++ b/common/actions/permission.go @@ -0,0 +1,96 @@ +package actions + +import ( + "errors" + + "github.com/gin-gonic/gin" + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk/config" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + "gorm.io/gorm" +) + +type DataPermission struct { + DataScope string + UserId int + DeptId int + RoleId int +} + +func PermissionAction() gin.HandlerFunc { + return func(c *gin.Context) { + db, err := pkg.GetOrm(c) + if err != nil { + log.Error(err) + return + } + + msgID := pkg.GenerateMsgIDFromContext(c) + var p = new(DataPermission) + if userId := user.GetUserIdStr(c); userId != "" { + p, err = newDataPermission(db, userId) + if err != nil { + log.Errorf("MsgID[%s] PermissionAction error: %s", msgID, err) + response.Error(c, 500, err, "权限范围鉴定错误") + c.Abort() + return + } + } + c.Set(PermissionKey, p) + c.Next() + } +} + +func newDataPermission(tx *gorm.DB, userId interface{}) (*DataPermission, error) { + var err error + p := &DataPermission{} + + err = tx.Table("sys_user"). + Select("sys_user.user_id", "sys_role.role_id", "sys_user.dept_id", "sys_role.data_scope"). + Joins("left join sys_role on sys_role.role_id = sys_user.role_id"). + Where("sys_user.user_id = ?", userId). + Scan(p).Error + if err != nil { + err = errors.New("获取用户数据出错 msg:" + err.Error()) + return nil, err + } + return p, nil +} + +func Permission(tableName string, p *DataPermission) func(db *gorm.DB) *gorm.DB { + return func(db *gorm.DB) *gorm.DB { + if !config.ApplicationConfig.EnableDP { + return db + } + switch p.DataScope { + case "2": + return db.Where(tableName+".create_by in (select sys_user.user_id from sys_role_dept left join sys_user on sys_user.dept_id=sys_role_dept.dept_id where sys_role_dept.role_id = ?)", p.RoleId) + case "3": + return db.Where(tableName+".create_by in (SELECT user_id from sys_user where dept_id = ? )", p.DeptId) + case "4": + return db.Where(tableName+".create_by in (SELECT user_id from sys_user where sys_user.dept_id in(select dept_id from sys_dept where dept_path like ? ))", "%/"+pkg.IntToString(p.DeptId)+"/%") + case "5": + return db.Where(tableName+".create_by = ?", p.UserId) + default: + return db + } + } +} + +func getPermissionFromContext(c *gin.Context) *DataPermission { + p := new(DataPermission) + if pm, ok := c.Get(PermissionKey); ok { + switch pm.(type) { + case *DataPermission: + p = pm.(*DataPermission) + } + } + return p +} + +// GetPermissionFromContext 提供非action写法数据范围约束 +func GetPermissionFromContext(c *gin.Context) *DataPermission { + return getPermissionFromContext(c) +} diff --git a/common/actions/type.go b/common/actions/type.go new file mode 100644 index 0000000..69beb8c --- /dev/null +++ b/common/actions/type.go @@ -0,0 +1,5 @@ +package actions + +const ( + PermissionKey = "dataPermission" +) diff --git a/common/actions/update.go b/common/actions/update.go new file mode 100644 index 0000000..7052334 --- /dev/null +++ b/common/actions/update.go @@ -0,0 +1,59 @@ +package actions + +import ( + "net/http" + + "github.com/gin-gonic/gin" + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + + "go-admin/common/dto" + "go-admin/common/models" +) + +// UpdateAction 通用更新动作 +func UpdateAction(control dto.Control) gin.HandlerFunc { + return func(c *gin.Context) { + db, err := pkg.GetOrm(c) + if err != nil { + log.Error(err) + return + } + + msgID := pkg.GenerateMsgIDFromContext(c) + req := control.Generate() + //更新操作 + err = req.Bind(c) + if err != nil { + response.Error(c, http.StatusUnprocessableEntity, err, "参数验证失败") + return + } + var object models.ActiveRecord + object, err = req.GenerateM() + if err != nil { + response.Error(c, 500, err, "模型生成失败") + return + } + object.SetUpdateBy(user.GetUserId(c)) + + //数据权限检查 + p := GetPermissionFromContext(c) + + db = db.WithContext(c).Scopes( + Permission(object.TableName(), p), + ).Where(req.GetId()).Updates(object) + if err = db.Error; err != nil { + log.Errorf("MsgID[%s] Update error: %s", msgID, err) + response.Error(c, 500, err, "更新失败") + return + } + if db.RowsAffected == 0 { + response.Error(c, http.StatusForbidden, nil, "无权更新该数据") + return + } + response.OK(c, object.GetId(), "更新成功") + c.Next() + } +} diff --git a/common/actions/view.go b/common/actions/view.go new file mode 100644 index 0000000..b134f53 --- /dev/null +++ b/common/actions/view.go @@ -0,0 +1,67 @@ +package actions + +import ( + "errors" + "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + "net/http" + + "github.com/gin-gonic/gin" + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "gorm.io/gorm" + + "go-admin/common/dto" + "go-admin/common/models" +) + +// ViewAction 通用详情动作 +func ViewAction(control dto.Control, f func() interface{}) gin.HandlerFunc { + return func(c *gin.Context) { + db, err := pkg.GetOrm(c) + if err != nil { + log.Error(err) + return + } + + msgID := pkg.GenerateMsgIDFromContext(c) + //查看详情 + req := control.Generate() + err = req.Bind(c) + if err != nil { + response.Error(c, http.StatusUnprocessableEntity, err, "参数验证失败") + return + } + var object models.ActiveRecord + object, err = req.GenerateM() + if err != nil { + response.Error(c, 500, err, "模型生成失败") + return + } + + var rsp interface{} + if f != nil { + rsp = f() + } else { + rsp, _ = req.GenerateM() + } + + //数据权限检查 + p := GetPermissionFromContext(c) + + err = db.Model(object).WithContext(c).Scopes( + Permission(object.TableName(), p), + ).Where(req.GetId()).First(rsp).Error + + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + response.Error(c, http.StatusNotFound, nil, "查看对象不存在或无权查看") + return + } + if err != nil { + log.Errorf("MsgID[%s] View error: %s", msgID, err) + response.Error(c, 500, err, "查看失败") + return + } + response.OK(c, rsp, "查询成功") + c.Next() + } +} diff --git a/common/apis/api.go b/common/apis/api.go new file mode 100644 index 0000000..4b2c58b --- /dev/null +++ b/common/apis/api.go @@ -0,0 +1,135 @@ +package apis + +import ( + "errors" + "fmt" + + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" + "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + "gorm.io/gorm" + + "go-admin/common/service" +) + +type Api struct { + Context *gin.Context + Logger *logger.Helper + Orm *gorm.DB + Errors error +} + +func (e *Api) AddError(err error) { + if e.Errors == nil { + e.Errors = err + } else if err != nil { + e.Logger.Error(err) + e.Errors = fmt.Errorf("%v; %w", e.Errors, err) + } +} + +// MakeContext 设置http上下文 +func (e *Api) MakeContext(c *gin.Context) *Api { + e.Context = c + e.Logger = api.GetRequestLogger(c) + return e +} + +// GetLogger 获取上下文提供的日志 +func (e *Api) GetLogger() *logger.Helper { + return api.GetRequestLogger(e.Context) +} + +func (e *Api) Bind(d interface{}, bindings ...binding.Binding) *Api { + var err error + if len(bindings) == 0 { + bindings = append(bindings, binding.JSON, nil) + } + for i := range bindings { + switch bindings[i] { + case binding.JSON: + err = e.Context.ShouldBindWith(d, binding.JSON) + case binding.XML: + err = e.Context.ShouldBindWith(d, binding.XML) + case binding.Form: + err = e.Context.ShouldBindWith(d, binding.Form) + case binding.Query: + err = e.Context.ShouldBindWith(d, binding.Query) + case binding.FormPost: + err = e.Context.ShouldBindWith(d, binding.FormPost) + case binding.FormMultipart: + err = e.Context.ShouldBindWith(d, binding.FormMultipart) + case binding.ProtoBuf: + err = e.Context.ShouldBindWith(d, binding.ProtoBuf) + case binding.MsgPack: + err = e.Context.ShouldBindWith(d, binding.MsgPack) + case binding.YAML: + err = e.Context.ShouldBindWith(d, binding.YAML) + case binding.Header: + err = e.Context.ShouldBindWith(d, binding.Header) + default: + err = e.Context.ShouldBindUri(d) + } + if err != nil { + e.AddError(err) + } + } + return e +} + +// GetOrm 获取Orm DB +func (e *Api) GetOrm() (*gorm.DB, error) { + db, err := pkg.GetOrm(e.Context) + if err != nil { + e.Error(500, err, "数据库连接获取失败") + return nil, err + } + return db, nil +} + +// MakeOrm 设置Orm DB +func (e *Api) MakeOrm() *Api { + var err error + if e.Logger == nil { + err = errors.New("at MakeOrm logger is nil") + //e.Logger.Error(500, err, "at MakeOrm logger is nil") + e.AddError(err) + return e + } + db, err := pkg.GetOrm(e.Context) + if err != nil { + e.Logger.Error(500, err, "数据库连接获取失败") + e.AddError(err) + } + e.Orm = db + return e +} + +func (e *Api) MakeService(c *service.Service) *Api { + c.Log = e.Logger + c.Orm = e.Orm + return e +} + +// Error 通常错误数据处理 +func (e *Api) Error(code int, err error, msg string) { + response.Error(e.Context, code, err, msg) +} + +// OK 通常成功数据处理 +func (e *Api) OK(data interface{}, msg string) { + response.OK(e.Context, data, msg) +} + +// PageOK 分页数据处理 +func (e *Api) PageOK(result interface{}, count int, pageIndex int, pageSize int, msg string) { + response.PageOK(e.Context, result, count, pageIndex, pageSize, msg) +} + +// Custom 兼容函数 +func (e *Api) Custom(data gin.H) { + response.Custum(e.Context, data) +} diff --git a/common/database/initialize.go b/common/database/initialize.go new file mode 100644 index 0000000..22e6d61 --- /dev/null +++ b/common/database/initialize.go @@ -0,0 +1,65 @@ +package database + +import ( + "time" + + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk" + toolsConfig "github.com/go-admin-team/go-admin-core/sdk/config" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + mycasbin "github.com/go-admin-team/go-admin-core/sdk/pkg/casbin" + toolsDB "github.com/go-admin-team/go-admin-core/tools/database" + . "github.com/go-admin-team/go-admin-core/tools/gorm/logger" + "gorm.io/gorm" + "gorm.io/gorm/logger" + "gorm.io/gorm/schema" + + "go-admin/common/global" +) + +// Setup 配置数据库 +func Setup() { + for k := range toolsConfig.DatabasesConfig { + setupSimpleDatabase(k, toolsConfig.DatabasesConfig[k]) + } +} + +func setupSimpleDatabase(host string, c *toolsConfig.Database) { + if global.Driver == "" { + global.Driver = c.Driver + } + log.Infof("%s => %s", host, pkg.Green(c.Source)) + registers := make([]toolsDB.ResolverConfigure, len(c.Registers)) + for i := range c.Registers { + registers[i] = toolsDB.NewResolverConfigure( + c.Registers[i].Sources, + c.Registers[i].Replicas, + c.Registers[i].Policy, + c.Registers[i].Tables) + } + resolverConfig := toolsDB.NewConfigure(c.Source, c.MaxIdleConns, c.MaxOpenConns, c.ConnMaxIdleTime, c.ConnMaxLifeTime, registers) + db, err := resolverConfig.Init(&gorm.Config{ + NamingStrategy: schema.NamingStrategy{ + SingularTable: true, + }, + Logger: New( + logger.Config{ + SlowThreshold: time.Second, + Colorful: true, + LogLevel: logger.LogLevel( + log.DefaultLogger.Options().Level.LevelForGorm()), + }, + ), + }, opens[c.Driver]) + + if err != nil { + log.Fatal(pkg.Red(c.Driver+" connect error :"), err) + } else { + log.Info(pkg.Green(c.Driver + " connect success !")) + } + + e := mycasbin.Setup(db, "") + + sdk.Runtime.SetDb(host, db) + sdk.Runtime.SetCasbin(host, e) +} diff --git a/common/database/open.go b/common/database/open.go new file mode 100644 index 0000000..de02868 --- /dev/null +++ b/common/database/open.go @@ -0,0 +1,16 @@ +//go:build !sqlite3 + +package database + +import ( + "gorm.io/driver/mysql" + "gorm.io/driver/postgres" + "gorm.io/driver/sqlserver" + "gorm.io/gorm" +) + +var opens = map[string]func(string) gorm.Dialector{ + "mysql": mysql.Open, + "postgres": postgres.Open, + "sqlserver": sqlserver.Open, +} diff --git a/common/database/open_sqlite3.go b/common/database/open_sqlite3.go new file mode 100644 index 0000000..aaebe94 --- /dev/null +++ b/common/database/open_sqlite3.go @@ -0,0 +1,19 @@ +//go:build sqlite3 +// +build sqlite3 + +package database + +import ( + "gorm.io/driver/mysql" + "gorm.io/driver/postgres" + "gorm.io/driver/sqlite" + "gorm.io/driver/sqlserver" + "gorm.io/gorm" +) + +var opens = map[string]func(string) gorm.Dialector{ + "mysql": mysql.Open, + "postgres": postgres.Open, + "sqlite3": sqlite.Open, + "sqlserver": sqlserver.Open, +} diff --git a/common/dto/auto_form.go b/common/dto/auto_form.go new file mode 100644 index 0000000..c99976a --- /dev/null +++ b/common/dto/auto_form.go @@ -0,0 +1,74 @@ +package dto + +type AutoForm struct { + Fields []Field `json:"fields"` + FormRef string `json:"formRef"` + FormModel string `json:"formModel"` + Size string `json:"size"` + LabelPosition string `json:"labelPosition"` + LabelWidth int `json:"labelWidth"` + FormRules string `json:"formRules"` + Gutter int `json:"gutter"` + Disabled bool `json:"disabled"` + Span int `json:"span"` + FormBtns bool `json:"formBtns"` +} + +type Config struct { + Label string `json:"label"` + LabelWidth interface{} `json:"labelWidth"` + ShowLabel bool `json:"showLabel"` + ChangeTag bool `json:"changeTag"` + Tag string `json:"tag"` + TagIcon string `json:"tagIcon"` + Required bool `json:"required"` + Layout string `json:"layout"` + Span int `json:"span"` + Document string `json:"document"` + RegList []interface{} `json:"regList"` + FormId int `json:"formId"` + RenderKey int64 `json:"renderKey"` + DefaultValue interface{} `json:"defaultValue"` + ShowTip bool `json:"showTip,omitempty"` + ButtonText string `json:"buttonText,omitempty"` + FileSize int `json:"fileSize,omitempty"` + SizeUnit string `json:"sizeUnit,omitempty"` +} + +type Option struct { + Label string `json:"label"` + Value string `json:"value"` +} + +type Slot struct { + Prepend string `json:"prepend,omitempty"` + Append string `json:"append,omitempty"` + ListType bool `json:"list-type,omitempty"` + Options []Option `json:"options,omitempty"` +} + +type Field struct { + Config Config `json:"__config__"` + Slot Slot `json:"__slot__"` + Placeholder string `json:"placeholder,omitempty"` + Style Style `json:"style,omitempty"` + Clearable bool `json:"clearable,omitempty"` + PrefixIcon string `json:"prefix-icon,omitempty"` + SuffixIcon string `json:"suffix-icon,omitempty"` + Maxlength interface{} `json:"maxlength"` + ShowWordLimit bool `json:"show-word-limit,omitempty"` + Readonly bool `json:"readonly,omitempty"` + Disabled bool `json:"disabled"` + VModel string `json:"__vModel__"` + Action string `json:"action,omitempty"` + Accept string `json:"accept,omitempty"` + Name string `json:"name,omitempty"` + AutoUpload bool `json:"auto-upload,omitempty"` + ListType string `json:"list-type,omitempty"` + Multiple bool `json:"multiple,omitempty"` + Filterable bool `json:"filterable,omitempty"` +} + +type Style struct { + Width string `json:"width"` +} diff --git a/common/dto/generate.go b/common/dto/generate.go new file mode 100644 index 0000000..313ae6a --- /dev/null +++ b/common/dto/generate.go @@ -0,0 +1,106 @@ +package dto + +import ( + vd "github.com/bytedance/go-tagexpr/v2/validator" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk/api" +) + +type ObjectById struct { + Id int `uri:"id"` + Ids []int `json:"ids"` +} + +func (s *ObjectById) Bind(ctx *gin.Context) error { + var err error + log := api.GetRequestLogger(ctx) + err = ctx.ShouldBindUri(s) + if err != nil { + log.Warnf("ShouldBindUri error: %s", err.Error()) + return err + } + if ctx.Request.Method == http.MethodDelete { + err = ctx.ShouldBind(&s) + if err != nil { + log.Warnf("ShouldBind error: %s", err.Error()) + return err + } + if len(s.Ids) > 0 { + return nil + } + if s.Ids == nil { + s.Ids = make([]int, 0) + } + if s.Id != 0 { + s.Ids = append(s.Ids, s.Id) + } + } + if err = vd.Validate(s); err != nil { + log.Errorf("Validate error: %s", err.Error()) + return err + } + return err +} + +func (s *ObjectById) GetId() interface{} { + if len(s.Ids) > 0 { + s.Ids = append(s.Ids, s.Id) + return s.Ids + } + return s.Id +} + +type ObjectGetReq struct { + Id int `uri:"id"` +} + +func (s *ObjectGetReq) Bind(ctx *gin.Context) error { + var err error + log := api.GetRequestLogger(ctx) + err = ctx.ShouldBindUri(s) + if err != nil { + log.Warnf("ShouldBindUri error: %s", err.Error()) + return err + } + if err = vd.Validate(s); err != nil { + log.Errorf("Validate error: %s", err.Error()) + return err + } + return err +} + +func (s *ObjectGetReq) GetId() interface{} { + return s.Id +} + +type ObjectDeleteReq struct { + Ids []int `json:"ids"` +} + +func (s *ObjectDeleteReq) Bind(ctx *gin.Context) error { + var err error + log := api.GetRequestLogger(ctx) + err = ctx.ShouldBind(&s) + if err != nil { + log.Warnf("ShouldBind error: %s", err.Error()) + return err + } + if len(s.Ids) > 0 { + return nil + } + if s.Ids == nil { + s.Ids = make([]int, 0) + } + + if err = vd.Validate(s); err != nil { + log.Errorf("Validate error: %s", err.Error()) + return err + } + return err +} + +func (s *ObjectDeleteReq) GetId() interface{} { + return s.Ids +} diff --git a/common/dto/order.go b/common/dto/order.go new file mode 100644 index 0000000..25455fb --- /dev/null +++ b/common/dto/order.go @@ -0,0 +1,12 @@ +package dto + +import ( + "gorm.io/gorm" + "gorm.io/gorm/clause" +) + +func OrderDest(sort string, bl bool) func(db *gorm.DB) *gorm.DB { + return func(db *gorm.DB) *gorm.DB { + return db.Order(clause.OrderByColumn{Column: clause.Column{Name: sort}, Desc: bl}) + } +} diff --git a/common/dto/pagination.go b/common/dto/pagination.go new file mode 100644 index 0000000..ee438e5 --- /dev/null +++ b/common/dto/pagination.go @@ -0,0 +1,20 @@ +package dto + +type Pagination struct { + PageIndex int `form:"pageIndex"` + PageSize int `form:"pageSize"` +} + +func (m *Pagination) GetPageIndex() int { + if m.PageIndex <= 0 { + m.PageIndex = 1 + } + return m.PageIndex +} + +func (m *Pagination) GetPageSize() int { + if m.PageSize <= 0 { + m.PageSize = 10 + } + return m.PageSize +} diff --git a/common/dto/search.go b/common/dto/search.go new file mode 100644 index 0000000..72cc60e --- /dev/null +++ b/common/dto/search.go @@ -0,0 +1,84 @@ +package dto + +import ( + "github.com/go-admin-team/go-admin-core/tools/search" + "go-admin/common/global" + "gorm.io/gorm" +) + +type GeneralDelDto struct { + Id int `uri:"id" json:"id" validate:"required"` + Ids []int `json:"ids"` +} + +func (g GeneralDelDto) GetIds() []int { + ids := make([]int, 0) + if g.Id != 0 { + ids = append(ids, g.Id) + } + if len(g.Ids) > 0 { + for _, id := range g.Ids { + if id > 0 { + ids = append(ids, id) + } + } + } else { + if g.Id > 0 { + ids = append(ids, g.Id) + } + } + if len(ids) <= 0 { + //方式全部删除 + ids = append(ids, 0) + } + return ids +} + +type GeneralGetDto struct { + Id int `uri:"id" json:"id" validate:"required"` +} + +func MakeCondition(q interface{}) func(db *gorm.DB) *gorm.DB { + return func(db *gorm.DB) *gorm.DB { + condition := &search.GormCondition{ + GormPublic: search.GormPublic{}, + Join: make([]*search.GormJoin, 0), + } + search.ResolveSearchQuery(global.Driver, q, condition) + for _, join := range condition.Join { + if join == nil { + continue + } + db = db.Joins(join.JoinOn) + for k, v := range join.Where { + db = db.Where(k, v...) + } + for k, v := range join.Or { + db = db.Or(k, v...) + } + for _, o := range join.Order { + db = db.Order(o) + } + } + for k, v := range condition.Where { + db = db.Where(k, v...) + } + for k, v := range condition.Or { + db = db.Or(k, v...) + } + for _, o := range condition.Order { + db = db.Order(o) + } + return db + } +} + +func Paginate(pageSize, pageIndex int) func(db *gorm.DB) *gorm.DB { + return func(db *gorm.DB) *gorm.DB { + offset := (pageIndex - 1) * pageSize + if offset < 0 { + offset = 0 + } + return db.Offset(offset).Limit(pageSize) + } +} diff --git a/common/dto/type.go b/common/dto/type.go new file mode 100644 index 0000000..e029943 --- /dev/null +++ b/common/dto/type.go @@ -0,0 +1,21 @@ +package dto + +import ( + "github.com/gin-gonic/gin" + "go-admin/common/models" +) + +type Index interface { + Generate() Index + Bind(ctx *gin.Context) error + GetPageIndex() int + GetPageSize() int + GetNeedSearch() interface{} +} + +type Control interface { + Generate() Control + Bind(ctx *gin.Context) error + GenerateM() (models.ActiveRecord, error) + GetId() interface{} +} diff --git a/common/file_store/initialize.go b/common/file_store/initialize.go new file mode 100644 index 0000000..fabce9f --- /dev/null +++ b/common/file_store/initialize.go @@ -0,0 +1,45 @@ +package file_store + +import "fmt" + +type OXS struct { + // Endpoint 访问域名 + Endpoint string + // AccessKeyID AK + AccessKeyID string + // AccessKeySecret AKS + AccessKeySecret string + // BucketName 桶名称 + BucketName string +} + +// Setup 配置文件存储driver +func (e *OXS) Setup(driver DriverType, options ...ClientOption) FileStoreType { + fileStoreType := driver + var fileStore FileStoreType + switch fileStoreType { + case AliYunOSS: + fileStore = new(ALiYunOSS) + err := fileStore.Setup(e.Endpoint, e.AccessKeyID, e.AccessKeySecret, e.BucketName) + if err != nil { + fmt.Println(err) + } + return fileStore + case HuaweiOBS: + fileStore = new(HuaWeiOBS) + err := fileStore.Setup(e.Endpoint, e.AccessKeyID, e.AccessKeySecret, e.BucketName) + if err != nil { + fmt.Println(err) + } + return fileStore + case QiNiuKodo: + fileStore = new(QiNiuKODO) + err := fileStore.Setup(e.Endpoint, e.AccessKeyID, e.AccessKeySecret, e.BucketName) + if err != nil { + fmt.Println(err) + } + return fileStore + } + + return nil +} diff --git a/common/file_store/interface.go b/common/file_store/interface.go new file mode 100644 index 0000000..acecbe9 --- /dev/null +++ b/common/file_store/interface.go @@ -0,0 +1,27 @@ +package file_store + +// DriverType 驱动类型 +type DriverType string + +const ( + // HuaweiOBS 华为云OBS + HuaweiOBS DriverType = "HuaweiOBS" + // AliYunOSS 阿里云OSS + AliYunOSS DriverType = "AliYunOSS" + // QiNiuKodo 七牛云kodo + QiNiuKodo DriverType = "QiNiuKodo" +) + +type ClientOption map[string]interface{} + +// TODO: FileStoreType名称待定 + +// FileStoreType OXS +type FileStoreType interface { + // Setup 装载 endpoint sss + Setup(endpoint, accessKeyID, accessKeySecret, BucketName string, options ...ClientOption) error + // UpLoad 上传 + UpLoad(yourObjectName string, localFile interface{}) error + // GetTempToken 获取临时Token + GetTempToken() (string, error) +} diff --git a/common/file_store/kodo.go b/common/file_store/kodo.go new file mode 100644 index 0000000..db896e2 --- /dev/null +++ b/common/file_store/kodo.go @@ -0,0 +1,111 @@ +package file_store + +import ( + "context" + "fmt" + "github.com/qiniu/go-sdk/v7/auth/qbox" + "github.com/qiniu/go-sdk/v7/storage" +) + +type Zone string + +const ( + // HuaDong 华东 + HuaDong Zone = "HuaDong" + // HuaBei 华北 + HuaBei Zone = "HuaBei" + // HuaNan 华南 + HuaNan Zone = "HuaNan" + // BeiMei 北美 + BeiMei Zone = "BeiMei" + // XinJiaPo 新加坡 + XinJiaPo Zone = "XinJiaPo" +) + +type QiNiuKODO struct { + Client interface{} + BucketName string + cfg storage.Config + options []ClientOption +} + +func (e *QiNiuKODO) getToken() string { + putPolicy := storage.PutPolicy{ + Scope: e.BucketName, + } + if len(e.options) > 0 && e.options[0]["Expires"] != nil { + putPolicy.Expires = e.options[0]["Expires"].(uint64) + } + upToken := putPolicy.UploadToken(e.Client.(*qbox.Mac)) + return upToken +} + +//Setup 装载 +//endpoint sss +func (e *QiNiuKODO) Setup(endpoint, accessKeyID, accessKeySecret, BucketName string, options ...ClientOption) error { + + mac := qbox.NewMac(accessKeyID, accessKeySecret) + // 获取存储空间。 + cfg := storage.Config{} + // 空间对应的机房 + e.setZoneORDefault(cfg, options...) + // 是否使用https域名 + cfg.UseHTTPS = true + // 上传是否使用CDN上传加速 + cfg.UseCdnDomains = false + + e.Client = mac + e.BucketName = BucketName + e.cfg = cfg + e.options = options + return nil +} + +// setZoneORDefault 设置Zone或者默认华东 +func (e *QiNiuKODO) setZoneORDefault(cfg storage.Config, options ...ClientOption) { + if len(options) > 0 && options[0]["Zone"] != nil { + if _, ok := options[0]["Zone"].(Zone); !ok { + cfg.Zone = &storage.ZoneHuadong + } + switch options[0]["Zone"].(Zone) { + case HuaDong: + cfg.Zone = &storage.ZoneHuadong + case HuaBei: + cfg.Zone = &storage.ZoneHuabei + case HuaNan: + cfg.Zone = &storage.ZoneHuanan + case BeiMei: + cfg.Zone = &storage.ZoneBeimei + case XinJiaPo: + cfg.Zone = &storage.ZoneXinjiapo + default: + cfg.Zone = &storage.ZoneHuadong + } + } +} + +// UpLoad 文件上传 +func (e *QiNiuKODO) UpLoad(yourObjectName string, localFile interface{}) error { + + // 构建表单上传的对象 + formUploader := storage.NewFormUploader(&e.cfg) + ret := storage.PutRet{} + // 可选配置 + putExtra := storage.PutExtra{ + Params: map[string]string{ + "x:name": "github logo", + }, + } + err := formUploader.PutFile(context.Background(), &ret, e.getToken(), yourObjectName, localFile.(string), &putExtra) + if err != nil { + fmt.Println(err) + return err + } + fmt.Println(ret.Key, ret.Hash) + return nil +} + +func (e *QiNiuKODO) GetTempToken() (string, error) { + token := e.getToken() + return token, nil +} diff --git a/common/file_store/kodo_test.go b/common/file_store/kodo_test.go new file mode 100644 index 0000000..a8767ae --- /dev/null +++ b/common/file_store/kodo_test.go @@ -0,0 +1,23 @@ +package file_store + +import ( + "testing" +) + +func TestKODOUpload(t *testing.T) { + e := OXS{"", "", "", ""} + var oxs = e.Setup(QiNiuKodo, map[string]interface{}{"Zone": "华东"}) + err := oxs.UpLoad("test.png", "./test.png") + if err != nil { + t.Error(err) + } + t.Log("ok") +} + +func TestKODOGetTempToken(t *testing.T) { + e := OXS{"", "", "", ""} + var oxs = e.Setup(QiNiuKodo, map[string]interface{}{"Zone": "华东"}) + token, _ := oxs.GetTempToken() + t.Log(token) + t.Log("ok") +} diff --git a/common/file_store/obs.go b/common/file_store/obs.go new file mode 100644 index 0000000..e937729 --- /dev/null +++ b/common/file_store/obs.go @@ -0,0 +1,52 @@ +package file_store + +import ( + "fmt" + "github.com/huaweicloud/huaweicloud-sdk-go-obs/obs" + "log" +) + +type HuaWeiOBS struct { + Client interface{} + BucketName string +} + +func (e *HuaWeiOBS) Setup(endpoint, accessKeyID, accessKeySecret, BucketName string, options ...ClientOption) error { + // 创建ObsClient结构体 + client, err := obs.New(accessKeyID, accessKeySecret, endpoint) + if err != nil { + log.Println("Error:", err) + return err + } + e.Client = client + e.BucketName = BucketName + return nil +} + +// UpLoad 文件上传 +// yourObjectName 文件路径名称,与objectKey是同一概念,表示断点续传上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg +func (e *HuaWeiOBS) UpLoad(yourObjectName string, localFile interface{}) error { + // 获取存储空间。 + input := &obs.PutFileInput{} + input.Bucket = e.BucketName + input.Key = yourObjectName + input.SourceFile = localFile.(string) + output, err := e.Client.(*obs.ObsClient).PutFile(input) + + if err == nil { + fmt.Printf("RequestId:%s\n", output.RequestId) + fmt.Printf("ETag:%s, StorageClass:%s\n", output.ETag, output.StorageClass) + } else { + if obsError, ok := err.(obs.ObsError); ok { + fmt.Println(obsError.Code) + fmt.Println(obsError.Message) + } else { + fmt.Println(err) + } + } + return nil +} + +func (e *HuaWeiOBS) GetTempToken() (string, error) { + return "", nil +} diff --git a/common/file_store/obs_test.go b/common/file_store/obs_test.go new file mode 100644 index 0000000..0960750 --- /dev/null +++ b/common/file_store/obs_test.go @@ -0,0 +1,15 @@ +package file_store + +import ( + "testing" +) + +func TestOBSUpload(t *testing.T) { + e := OXS{"", "", "", ""} + var oxs = e.Setup(HuaweiOBS) + err := oxs.UpLoad("test.png", "./test.png") + if err != nil { + t.Error(err) + } + t.Log("ok") +} diff --git a/common/file_store/oss.go b/common/file_store/oss.go new file mode 100644 index 0000000..c35627b --- /dev/null +++ b/common/file_store/oss.go @@ -0,0 +1,48 @@ +package file_store + +import ( + "github.com/aliyun/aliyun-oss-go-sdk/oss" + "log" +) + +type ALiYunOSS struct { + Client interface{} + BucketName string +} + +//Setup 装载 +//endpoint sss +func (e *ALiYunOSS) Setup(endpoint, accessKeyID, accessKeySecret, BucketName string, options ...ClientOption) error { + client, err := oss.New(endpoint, accessKeyID, accessKeySecret) + if err != nil { + log.Println("Error:", err) + return err + } + e.Client = client + e.BucketName = BucketName + + return nil +} + +// UpLoad 文件上传 +func (e *ALiYunOSS) UpLoad(yourObjectName string, localFile interface{}) error { + // 获取存储空间。 + bucket, err := e.Client.(*oss.Client).Bucket(e.BucketName) + if err != nil { + log.Println("Error:", err) + return err + } + // 设置分片大小为100 KB,指定分片上传并发数为3,并开启断点续传上传。 + // 其中与objectKey是同一概念,表示断点续传上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。 + // "LocalFile"为filePath,100*1024为partSize。 + err = bucket.UploadFile(yourObjectName, localFile.(string), 100*1024, oss.Routines(3), oss.Checkpoint(true, "")) + if err != nil { + log.Println("Error:", err) + return err + } + return nil +} + +func (e *ALiYunOSS) GetTempToken() (string, error) { + return "", nil +} diff --git a/common/file_store/oss_test.go b/common/file_store/oss_test.go new file mode 100644 index 0000000..f04dd22 --- /dev/null +++ b/common/file_store/oss_test.go @@ -0,0 +1,16 @@ +package file_store + +import ( + "testing" +) + +func TestOSSUpload(t *testing.T) { + // 打括号内填写自己的测试信息即可 + e := OXS{} + var oxs = e.Setup(AliYunOSS) + err := oxs.UpLoad("test.png", "./test.png") + if err != nil { + t.Error(err) + } + t.Log("ok") +} diff --git a/common/global/adm.go b/common/global/adm.go new file mode 100644 index 0000000..1344cac --- /dev/null +++ b/common/global/adm.go @@ -0,0 +1,11 @@ +package global + +const ( + // Version go-admin version info + Version = "2.1.2" +) + +var ( + // Driver 数据库驱动 + Driver string +) diff --git a/common/global/casbin.go b/common/global/casbin.go new file mode 100644 index 0000000..72b7e6c --- /dev/null +++ b/common/global/casbin.go @@ -0,0 +1,18 @@ +package global + +import ( + "github.com/casbin/casbin/v2" + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk" + "github.com/go-admin-team/go-admin-core/sdk/api" +) + +func LoadPolicy(c *gin.Context) (*casbin.SyncedEnforcer, error) { + log := api.GetRequestLogger(c) + if err := sdk.Runtime.GetCasbinKey(c.Request.Host).LoadPolicy(); err == nil { + return sdk.Runtime.GetCasbinKey(c.Request.Host), err + } else { + log.Errorf("casbin rbac_model or policy init error, %s ", err.Error()) + return nil, err + } +} diff --git a/common/global/logo.go b/common/global/logo.go new file mode 100644 index 0000000..e4ed471 --- /dev/null +++ b/common/global/logo.go @@ -0,0 +1,4 @@ +package global + +// LogoContent go-admin ascii显示,减少静态文件依赖 +var LogoContent = []byte{10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 95, 95, 95, 95, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 44, 45, 45, 45, 44, 32, 32, 32, 32, 32, 32, 32, 32, 44, 39, 32, 32, 44, 32, 96, 46, 32, 32, 44, 45, 45, 44, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 44, 45, 45, 45, 46, 32, 32, 32, 32, 32, 32, 44, 45, 45, 45, 44, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 44, 45, 45, 45, 46, 39, 124, 32, 32, 32, 32, 32, 44, 45, 43, 45, 44, 46, 39, 32, 95, 32, 124, 44, 45, 45, 46, 39, 124, 32, 32, 32, 32, 32, 32, 32, 32, 32, 44, 45, 45, 45, 44, 10, 32, 32, 44, 45, 45, 45, 45, 46, 95, 44, 46, 32, 32, 39, 32, 32, 32, 44, 39, 92, 32, 32, 32, 44, 39, 32, 32, 46, 39, 32, 124, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 124, 32, 32, 32, 124, 32, 58, 32, 32, 44, 45, 43, 45, 46, 32, 59, 32, 32, 32, 44, 32, 124, 124, 124, 32, 32, 124, 44, 32, 32, 32, 32, 32, 32, 44, 45, 43, 45, 46, 32, 47, 32, 32, 124, 10, 32, 47, 32, 32, 32, 47, 32, 32, 39, 32, 47, 32, 47, 32, 32, 32, 47, 32, 32, 32, 124, 44, 45, 45, 45, 46, 39, 32, 32, 32, 44, 32, 44, 45, 45, 46, 45, 45, 46, 32, 32, 32, 32, 32, 32, 124, 32, 32, 32, 124, 32, 124, 32, 44, 45, 45, 46, 39, 124, 39, 32, 32, 32, 124, 32, 32, 124, 124, 96, 45, 45, 39, 95, 32, 32, 32, 32, 32, 44, 45, 45, 46, 39, 124, 39, 32, 32, 32, 124, 10, 124, 32, 32, 32, 58, 32, 32, 32, 32, 32, 124, 46, 32, 32, 32, 59, 32, 44, 46, 32, 58, 124, 32, 32, 32, 124, 32, 32, 32, 32, 124, 47, 32, 32, 32, 32, 32, 32, 32, 92, 32, 32, 32, 44, 45, 45, 46, 95, 95, 124, 32, 124, 124, 32, 32, 32, 124, 32, 32, 44, 39, 44, 32, 124, 32, 32, 124, 44, 44, 39, 32, 44, 39, 124, 32, 32, 32, 124, 32, 32, 32, 124, 32, 32, 44, 34, 39, 32, 124, 10, 124, 32, 32, 32, 124, 32, 46, 92, 32, 32, 46, 39, 32, 32, 32, 124, 32, 124, 58, 32, 58, 58, 32, 32, 32, 58, 32, 32, 46, 39, 46, 45, 45, 46, 32, 32, 46, 45, 46, 32, 124, 32, 47, 32, 32, 32, 44, 39, 32, 32, 32, 124, 124, 32, 32, 32, 124, 32, 47, 32, 32, 124, 32, 124, 45, 45, 39, 32, 39, 32, 32, 124, 32, 124, 32, 32, 32, 124, 32, 32, 32, 124, 32, 47, 32, 32, 124, 32, 124, 10, 46, 32, 32, 32, 59, 32, 39, 59, 32, 32, 124, 39, 32, 32, 32, 124, 32, 46, 59, 32, 58, 58, 32, 32, 32, 124, 46, 39, 32, 32, 32, 92, 95, 95, 92, 47, 58, 32, 46, 32, 46, 46, 32, 32, 32, 39, 32, 32, 47, 32, 32, 124, 124, 32, 32, 32, 58, 32, 124, 32, 32, 124, 32, 44, 32, 32, 32, 32, 124, 32, 32, 124, 32, 58, 32, 32, 32, 124, 32, 32, 32, 124, 32, 124, 32, 32, 124, 32, 124, 10, 39, 32, 32, 32, 46, 32, 32, 32, 46, 32, 124, 124, 32, 32, 32, 58, 32, 32, 32, 32, 124, 96, 45, 45, 45, 39, 32, 32, 32, 32, 32, 44, 34, 32, 46, 45, 45, 46, 59, 32, 124, 39, 32, 32, 32, 59, 32, 124, 58, 32, 32, 124, 124, 32, 32, 32, 58, 32, 124, 32, 32, 124, 47, 32, 32, 32, 32, 32, 39, 32, 32, 58, 32, 124, 95, 95, 32, 124, 32, 32, 32, 124, 32, 124, 32, 32, 124, 47, 10, 32, 96, 45, 45, 45, 96, 45, 39, 124, 32, 124, 32, 92, 32, 32, 32, 92, 32, 32, 47, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 47, 32, 32, 47, 32, 32, 44, 46, 32, 32, 124, 124, 32, 32, 32, 124, 32, 39, 47, 32, 32, 39, 124, 32, 32, 32, 124, 32, 124, 96, 45, 39, 32, 32, 32, 32, 32, 32, 124, 32, 32, 124, 32, 39, 46, 39, 124, 124, 32, 32, 32, 124, 32, 124, 45, 45, 39, 10, 32, 46, 39, 95, 95, 47, 92, 95, 58, 32, 124, 32, 32, 96, 45, 45, 45, 45, 39, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 59, 32, 32, 58, 32, 32, 32, 46, 39, 32, 32, 32, 92, 32, 32, 32, 58, 32, 32, 32, 32, 58, 124, 124, 32, 32, 32, 59, 47, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 59, 32, 32, 58, 32, 32, 32, 32, 59, 124, 32, 32, 32, 124, 47, 10, 32, 124, 32, 32, 32, 58, 32, 32, 32, 32, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 124, 32, 32, 44, 32, 32, 32, 32, 32, 46, 45, 46, 47, 92, 32, 32, 32, 92, 32, 32, 47, 32, 32, 39, 45, 45, 45, 39, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 124, 32, 32, 44, 32, 32, 32, 47, 32, 39, 45, 45, 45, 39, 10, 32, 32, 92, 32, 32, 32, 92, 32, 32, 47, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 96, 45, 45, 96, 45, 45, 45, 39, 32, 32, 32, 32, 32, 96, 45, 45, 45, 45, 39, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 96, 45, 39, 10, 32, 32, 32, 96, 45, 45, 96, 45, 39, 10} diff --git a/common/global/topic.go b/common/global/topic.go new file mode 100644 index 0000000..60e1d34 --- /dev/null +++ b/common/global/topic.go @@ -0,0 +1,7 @@ +package global + +const ( + LoginLog = "login_log_queue" + OperateLog = "operate_log_queue" + ApiCheck = "api_check_queue" +) diff --git a/common/ip.go b/common/ip.go new file mode 100644 index 0000000..bc4d9ef --- /dev/null +++ b/common/ip.go @@ -0,0 +1,27 @@ +package common + +import ( + "github.com/gin-gonic/gin" + "strings" +) + +func GetClientIP(c *gin.Context) string { + ClientIP := c.ClientIP() + //fmt.Println("ClientIP:", ClientIP) + RemoteIP := c.RemoteIP() + //fmt.Println("RemoteIP:", RemoteIP) + ip := c.Request.Header.Get("X-Forwarded-For") + if strings.Contains(ip, "127.0.0.1") || ip == "" { + ip = c.Request.Header.Get("X-real-ip") + } + if ip == "" { + ip = "127.0.0.1" + } + if RemoteIP != "127.0.0.1" { + ip = RemoteIP + } + if ClientIP != "127.0.0.1" { + ip = ClientIP + } + return ip +} diff --git a/common/middleware/auth.go b/common/middleware/auth.go new file mode 100644 index 0000000..6562cff --- /dev/null +++ b/common/middleware/auth.go @@ -0,0 +1,36 @@ +package middleware + +import ( + "time" + + "github.com/go-admin-team/go-admin-core/sdk/config" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + "go-admin/common/middleware/handler" +) + +// AuthInit jwt验证new +func AuthInit() (*jwt.GinJWTMiddleware, error) { + timeout := time.Hour + if config.ApplicationConfig.Mode == "dev" { + timeout = time.Duration(876010) * time.Hour + } else { + if config.JwtConfig.Timeout != 0 { + timeout = time.Duration(config.JwtConfig.Timeout) * time.Second + } + } + return jwt.New(&jwt.GinJWTMiddleware{ + Realm: "test zone", + Key: []byte(config.JwtConfig.Secret), + Timeout: timeout, + MaxRefresh: time.Hour, + PayloadFunc: handler.PayloadFunc, + IdentityHandler: handler.IdentityHandler, + Authenticator: handler.Authenticator, + Authorizator: handler.Authorizator, + Unauthorized: handler.Unauthorized, + TokenLookup: "header: Authorization, query: token, cookie: jwt", + TokenHeadName: "Bearer", + TimeFunc: time.Now, + }) + +} \ No newline at end of file diff --git a/common/middleware/customerror.go b/common/middleware/customerror.go new file mode 100644 index 0000000..1f92628 --- /dev/null +++ b/common/middleware/customerror.go @@ -0,0 +1,61 @@ +package middleware + +import ( + "fmt" + "net/http" + "runtime" + "strconv" + "strings" + "time" + + "github.com/gin-gonic/gin" +) + +func CustomError(c *gin.Context) { + defer func() { + if err := recover(); err != nil { + + if c.IsAborted() { + c.Status(200) + } + switch errStr := err.(type) { + case string: + p := strings.Split(errStr, "#") + if len(p) == 3 && p[0] == "CustomError" { + statusCode, e := strconv.Atoi(p[1]) + if e != nil { + break + } + c.Status(statusCode) + fmt.Println( + time.Now().Format("2006-01-02 15:04:05"), + "[ERROR]", + c.Request.Method, + c.Request.URL, + statusCode, + c.Request.RequestURI, + c.ClientIP(), + p[2], + ) + c.JSON(http.StatusOK, gin.H{ + "code": statusCode, + "msg": p[2], + }) + } else { + c.JSON(http.StatusOK, gin.H{ + "code": 500, + "msg": errStr, + }) + } + case runtime.Error: + c.JSON(http.StatusOK, gin.H{ + "code": 500, + "msg": errStr.Error(), + }) + default: + panic(err) + } + } + }() + c.Next() +} diff --git a/common/middleware/db.go b/common/middleware/db.go new file mode 100644 index 0000000..0e73a2d --- /dev/null +++ b/common/middleware/db.go @@ -0,0 +1,11 @@ +package middleware + +import ( + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk" +) + +func WithContextDb(c *gin.Context) { + c.Set("db", sdk.Runtime.GetDbByKey(c.Request.Host).WithContext(c)) + c.Next() +} diff --git a/common/middleware/demo.go b/common/middleware/demo.go new file mode 100644 index 0000000..f13f28f --- /dev/null +++ b/common/middleware/demo.go @@ -0,0 +1,29 @@ +package middleware + +import ( + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk/config" + "net/http" +) + +func DemoEvn() gin.HandlerFunc { + return func(c *gin.Context) { + method := c.Request.Method + if config.ApplicationConfig.Mode == "demo" { + if method == "GET" || + method == "OPTIONS" || + c.Request.RequestURI == "/api/v1/login" || + c.Request.RequestURI == "/api/v1/logout" { + c.Next() + } else { + c.JSON(http.StatusOK, gin.H{ + "code": 500, + "msg": "谢谢您的参与,但为了大家更好的体验,所以本次提交就算了吧!\U0001F600\U0001F600\U0001F600", + }) + c.Abort() + return + } + } + c.Next() + } +} diff --git a/common/middleware/handler/auth.go b/common/middleware/handler/auth.go new file mode 100644 index 0000000..ddb6791 --- /dev/null +++ b/common/middleware/handler/auth.go @@ -0,0 +1,182 @@ +package handler + +import ( + "go-admin/app/admin/models" + "go-admin/common" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/config" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "github.com/go-admin-team/go-admin-core/sdk/pkg/captcha" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + "github.com/mssola/user_agent" + "go-admin/common/global" +) + +func PayloadFunc(data interface{}) jwt.MapClaims { + if v, ok := data.(map[string]interface{}); ok { + u, _ := v["user"].(SysUser) + r, _ := v["role"].(SysRole) + return jwt.MapClaims{ + jwt.IdentityKey: u.UserId, + jwt.RoleIdKey: r.RoleId, + jwt.RoleKey: r.RoleKey, + jwt.NiceKey: u.Username, + jwt.DataScopeKey: r.DataScope, + jwt.RoleNameKey: r.RoleName, + } + } + return jwt.MapClaims{} +} + +func IdentityHandler(c *gin.Context) interface{} { + claims := jwt.ExtractClaims(c) + return map[string]interface{}{ + "IdentityKey": claims["identity"], + "UserName": claims["nice"], + "RoleKey": claims["rolekey"], + "UserId": claims["identity"], + "RoleIds": claims["roleid"], + "DataScope": claims["datascope"], + } +} + +// Authenticator 获取token +// @Summary 登陆 +// @Description 获取token +// @Description LoginHandler can be used by clients to get a jwt token. +// @Description Payload needs to be json in the form of {"username": "USERNAME", "password": "PASSWORD"}. +// @Description Reply will be of the form {"token": "TOKEN"}. +// @Description dev mode:It should be noted that all fields cannot be empty, and a value of 0 can be passed in addition to the account password +// @Description 注意:开发模式:需要注意全部字段不能为空,账号密码外可以传入0值 +// @Tags 登陆 +// @Accept application/json +// @Product application/json +// @Param account body Login true "account" +// @Success 200 {string} string "{"code": 200, "expire": "2019-08-07T12:45:48+08:00", "token": ".eyJleHAiOjE1NjUxNTMxNDgsImlkIjoiYWRtaW4iLCJvcmlnX2lhdCI6MTU2NTE0OTU0OH0.-zvzHvbg0A" }" +// @Router /api/v1/login [post] +func Authenticator(c *gin.Context) (interface{}, error) { + log := api.GetRequestLogger(c) + db, err := pkg.GetOrm(c) + if err != nil { + log.Errorf("get db error, %s", err.Error()) + response.Error(c, 500, err, "数据库连接获取失败") + return nil, jwt.ErrFailedAuthentication + } + + var loginVals Login + var status = "2" + var msg = "登录成功" + var username = "" + defer func() { + LoginLogToDB(c, status, msg, username) + }() + + if err = c.ShouldBind(&loginVals); err != nil { + username = loginVals.Username + msg = "数据解析失败" + status = "1" + + return nil, jwt.ErrMissingLoginValues + } + if config.ApplicationConfig.Mode != "dev" { + if !captcha.Verify(loginVals.UUID, loginVals.Code, true) { + username = loginVals.Username + msg = "验证码错误" + status = "1" + + return nil, jwt.ErrInvalidVerificationode + } + } + sysUser, role, e := loginVals.GetUser(db) + if e == nil { + username = loginVals.Username + + return map[string]interface{}{"user": sysUser, "role": role}, nil + } else { + msg = "登录失败" + status = "1" + log.Warnf("%s login failed!", loginVals.Username) + } + return nil, jwt.ErrFailedAuthentication +} + +// LoginLogToDB Write log to database +func LoginLogToDB(c *gin.Context, status string, msg string, username string) { + if !config.LoggerConfig.EnabledDB { + return + } + log := api.GetRequestLogger(c) + l := make(map[string]interface{}) + + ua := user_agent.New(c.Request.UserAgent()) + l["ipaddr"] = common.GetClientIP(c) + l["loginLocation"] = "" // pkg.GetLocation(common.GetClientIP(c),gaConfig.ExtConfig.AMap.Key) + l["loginTime"] = pkg.GetCurrentTime() + l["status"] = status + l["remark"] = c.Request.UserAgent() + browserName, browserVersion := ua.Browser() + l["browser"] = browserName + " " + browserVersion + l["os"] = ua.OS() + l["platform"] = ua.Platform() + l["username"] = username + l["msg"] = msg + + q := sdk.Runtime.GetMemoryQueue(c.Request.Host) + message, err := sdk.Runtime.GetStreamMessage("", global.LoginLog, l) + if err != nil { + log.Errorf("GetStreamMessage error, %s", err.Error()) + //日志报错错误,不中断请求 + } else { + err = q.Append(message) + if err != nil { + log.Errorf("Append message error, %s", err.Error()) + } + } +} + +// LogOut +// @Summary 退出登录 +// @Description 获取token +// LoginHandler can be used by clients to get a jwt token. +// Reply will be of the form {"token": "TOKEN"}. +// @Accept application/json +// @Product application/json +// @Success 200 {string} string "{"code": 200, "msg": "成功退出系统" }" +// @Router /logout [post] +// @Security Bearer +func LogOut(c *gin.Context) { + LoginLogToDB(c, "2", "退出成功", user.GetUserName(c)) + c.JSON(http.StatusOK, gin.H{ + "code": 200, + "msg": "退出成功", + }) + +} + +func Authorizator(data interface{}, c *gin.Context) bool { + + if v, ok := data.(map[string]interface{}); ok { + u, _ := v["user"].(models.SysUser) + r, _ := v["role"].(models.SysRole) + c.Set("role", r.RoleName) + c.Set("roleIds", r.RoleId) + c.Set("userId", u.UserId) + c.Set("userName", u.Username) + c.Set("dataScope", r.DataScope) + return true + } + return false +} + +func Unauthorized(c *gin.Context, code int, message string) { + c.JSON(http.StatusOK, gin.H{ + "code": code, + "msg": message, + }) +} diff --git a/common/middleware/handler/httpshandler.go b/common/middleware/handler/httpshandler.go new file mode 100644 index 0000000..e127439 --- /dev/null +++ b/common/middleware/handler/httpshandler.go @@ -0,0 +1,22 @@ +package handler + +import ( + "github.com/gin-gonic/gin" + "github.com/unrolled/secure" + + "github.com/go-admin-team/go-admin-core/sdk/config" +) + +func TlsHandler() gin.HandlerFunc { + return func(c *gin.Context) { + secureMiddleware := secure.New(secure.Options{ + SSLRedirect: true, + SSLHost: config.SslConfig.Domain, + }) + err := secureMiddleware.Process(c.Writer, c.Request) + if err != nil { + return + } + c.Next() + } +} diff --git a/common/middleware/handler/login.go b/common/middleware/handler/login.go new file mode 100644 index 0000000..d17626c --- /dev/null +++ b/common/middleware/handler/login.go @@ -0,0 +1,33 @@ +package handler + +import ( + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "gorm.io/gorm" +) + +type Login struct { + Username string `form:"UserName" json:"username" binding:"required"` + Password string `form:"Password" json:"password" binding:"required"` + Code string `form:"Code" json:"code" binding:"required"` + UUID string `form:"UUID" json:"uuid" binding:"required"` +} + +func (u *Login) GetUser(tx *gorm.DB) (user SysUser, role SysRole, err error) { + err = tx.Table("sys_user").Where("username = ? and status = '2'", u.Username).First(&user).Error + if err != nil { + log.Errorf("get user error, %s", err.Error()) + return + } + _, err = pkg.CompareHashAndPassword(user.Password, u.Password) + if err != nil { + log.Errorf("user login error, %s", err.Error()) + return + } + err = tx.Table("sys_role").Where("role_id = ? ", user.RoleId).First(&role).Error + if err != nil { + log.Errorf("get role error, %s", err.Error()) + return + } + return +} diff --git a/common/middleware/handler/ping.go b/common/middleware/handler/ping.go new file mode 100644 index 0000000..ab4d645 --- /dev/null +++ b/common/middleware/handler/ping.go @@ -0,0 +1,11 @@ +package handler + +import ( + "github.com/gin-gonic/gin" +) + +func Ping(c *gin.Context) { + c.JSON(200, gin.H{ + "message": "ok", + }) +} diff --git a/common/middleware/handler/role.go b/common/middleware/handler/role.go new file mode 100644 index 0000000..0895ebc --- /dev/null +++ b/common/middleware/handler/role.go @@ -0,0 +1,24 @@ +package handler + +import "go-admin/common/models" + +type SysRole struct { + RoleId int `json:"roleId" gorm:"primaryKey;autoIncrement"` // 角色编码 + RoleName string `json:"roleName" gorm:"size:128;"` // 角色名称 + Status string `json:"status" gorm:"size:4;"` // + RoleKey string `json:"roleKey" gorm:"size:128;"` //角色代码 + RoleSort int `json:"roleSort" gorm:""` //角色排序 + Flag string `json:"flag" gorm:"size:128;"` // + Remark string `json:"remark" gorm:"size:255;"` //备注 + Admin bool `json:"admin" gorm:"size:4;"` + DataScope string `json:"dataScope" gorm:"size:128;"` + Params string `json:"params" gorm:"-"` + MenuIds []int `json:"menuIds" gorm:"-"` + DeptIds []int `json:"deptIds" gorm:"-"` + models.ControlBy + models.ModelTime +} + +func (SysRole) TableName() string { + return "sys_role" +} diff --git a/common/middleware/handler/user.go b/common/middleware/handler/user.go new file mode 100644 index 0000000..b34d4db --- /dev/null +++ b/common/middleware/handler/user.go @@ -0,0 +1,40 @@ +package handler + +import ( + "go-admin/common/models" + "gorm.io/gorm" +) + +type SysUser struct { + UserId int `gorm:"primaryKey;autoIncrement;comment:编码" json:"userId"` + Username string `json:"username" gorm:"size:64;comment:用户名"` + Password string `json:"-" gorm:"size:128;comment:密码"` + NickName string `json:"nickName" gorm:"size:128;comment:昵称"` + Phone string `json:"phone" gorm:"size:11;comment:手机号"` + RoleId int `json:"roleId" gorm:"size:20;comment:角色ID"` + Salt string `json:"-" gorm:"size:255;comment:加盐"` + Avatar string `json:"avatar" gorm:"size:255;comment:头像"` + Sex string `json:"sex" gorm:"size:255;comment:性别"` + Email string `json:"email" gorm:"size:128;comment:邮箱"` + DeptId int `json:"deptId" gorm:"size:20;comment:部门"` + PostId int `json:"postId" gorm:"size:20;comment:岗位"` + Remark string `json:"remark" gorm:"size:255;comment:备注"` + Status string `json:"status" gorm:"size:4;comment:状态"` + DeptIds []int `json:"deptIds" gorm:"-"` + PostIds []int `json:"postIds" gorm:"-"` + RoleIds []int `json:"roleIds" gorm:"-"` + //Dept *SysDept `json:"dept"` + models.ControlBy + models.ModelTime +} + +func (*SysUser) TableName() string { + return "sys_user" +} + +func (e *SysUser) AfterFind(_ *gorm.DB) error { + e.DeptIds = []int{e.DeptId} + e.PostIds = []int{e.PostId} + e.RoleIds = []int{e.RoleId} + return nil +} diff --git a/common/middleware/header.go b/common/middleware/header.go new file mode 100644 index 0000000..b1411e5 --- /dev/null +++ b/common/middleware/header.go @@ -0,0 +1,48 @@ +package middleware + +import ( + "net/http" + "time" + + "github.com/gin-gonic/gin" +) + +// NoCache is a middleware function that appends headers +// to prevent the client from caching the HTTP response. +func NoCache(c *gin.Context) { + c.Header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value") + c.Header("Expires", "Thu, 01 Jan 1970 00:00:00 GMT") + c.Header("Last-Modified", time.Now().UTC().Format(http.TimeFormat)) + c.Next() +} + +// Options is a middleware function that appends headers +// for options requests and aborts then exits the middleware +// chain and ends the request. +func Options(c *gin.Context) { + if c.Request.Method != "OPTIONS" { + c.Next() + } else { + c.Header("Access-Control-Allow-Origin", "*") + c.Header("Access-Control-Allow-Methods", "GET,POST,PUT,PATCH,DELETE,OPTIONS") + c.Header("Access-Control-Allow-Headers", "authorization, origin, content-type, accept") + c.Header("Allow", "HEAD,GET,POST,PUT,PATCH,DELETE,OPTIONS") + c.Header("Content-Type", "application/json") + c.AbortWithStatus(200) + } +} + +// Secure is a middleware function that appends security +// and resource access headers. +func Secure(c *gin.Context) { + c.Header("Access-Control-Allow-Origin", "*") + //c.Header("X-Frame-Options", "DENY") + c.Header("X-Content-Type-Options", "nosniff") + c.Header("X-XSS-Protection", "1; mode=block") + if c.Request.TLS != nil { + c.Header("Strict-Transport-Security", "max-age=31536000") + } + + // Also consider adding Content-Security-Policy headers + // c.Header("Content-Security-Policy", "script-src 'self' https://cdnjs.cloudflare.com") +} diff --git a/common/middleware/init.go b/common/middleware/init.go new file mode 100644 index 0000000..9902698 --- /dev/null +++ b/common/middleware/init.go @@ -0,0 +1,35 @@ +package middleware + +import ( + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + "go-admin/common/actions" +) + +const ( + JwtTokenCheck string = "JwtToken" + RoleCheck string = "AuthCheckRole" + PermissionCheck string = "PermissionAction" +) + +func InitMiddleware(r *gin.Engine) { + r.Use(DemoEvn()) + // 数据库链接 + r.Use(WithContextDb) + // 日志处理 + r.Use(LoggerToFile()) + // 自定义错误处理 + r.Use(CustomError) + // NoCache is a middleware function that appends headers + r.Use(NoCache) + // 跨域处理 + r.Use(Options) + // Secure is a middleware function that appends security + r.Use(Secure) + // 链路追踪 + //r.Use(middleware.Trace()) + sdk.Runtime.SetMiddleware(JwtTokenCheck, (*jwt.GinJWTMiddleware).MiddlewareFunc) + sdk.Runtime.SetMiddleware(RoleCheck, AuthCheckRole()) + sdk.Runtime.SetMiddleware(PermissionCheck, actions.PermissionAction()) +} diff --git a/common/middleware/logger.go b/common/middleware/logger.go new file mode 100644 index 0000000..89c2c07 --- /dev/null +++ b/common/middleware/logger.go @@ -0,0 +1,136 @@ +package middleware + +import ( + "bufio" + "bytes" + "encoding/json" + "go-admin/app/admin/service/dto" + "go-admin/common" + "io" + "io/ioutil" + "net/http" + "strings" + "time" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/config" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + + "go-admin/common/global" +) + +// LoggerToFile 日志记录到文件 +func LoggerToFile() gin.HandlerFunc { + return func(c *gin.Context) { + log := api.GetRequestLogger(c) + // 开始时间 + startTime := time.Now() + // 处理请求 + var body string + switch c.Request.Method { + case http.MethodPost, http.MethodPut, http.MethodGet, http.MethodDelete: + bf := bytes.NewBuffer(nil) + wt := bufio.NewWriter(bf) + _, err := io.Copy(wt, c.Request.Body) + if err != nil { + log.Warnf("copy body error, %s", err.Error()) + err = nil + } + rb, _ := ioutil.ReadAll(bf) + c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(rb)) + body = string(rb) + } + + c.Next() + url := c.Request.RequestURI + if strings.Index(url, "logout") > -1 || + strings.Index(url, "login") > -1 { + return + } + // 结束时间 + endTime := time.Now() + if c.Request.Method == http.MethodOptions { + return + } + + rt, bl := c.Get("result") + var result = "" + if bl { + rb, err := json.Marshal(rt) + if err != nil { + log.Warnf("json Marshal result error, %s", err.Error()) + } else { + result = string(rb) + } + } + + st, bl := c.Get("status") + var statusBus = 0 + if bl { + statusBus = st.(int) + } + + // 请求方式 + reqMethod := c.Request.Method + // 请求路由 + reqUri := c.Request.RequestURI + // 状态码 + statusCode := c.Writer.Status() + // 请求IP + clientIP := common.GetClientIP(c) + // 执行时间 + latencyTime := endTime.Sub(startTime) + // 日志格式 + logData := map[string]interface{}{ + "statusCode": statusCode, + "latencyTime": latencyTime, + "clientIP": clientIP, + "method": reqMethod, + "uri": reqUri, + } + log.WithFields(logData).Info() + + if c.Request.Method != "OPTIONS" && config.LoggerConfig.EnabledDB && statusCode != 404 { + SetDBOperLog(c, clientIP, statusCode, reqUri, reqMethod, latencyTime, body, result, statusBus) + } + } +} + +// SetDBOperLog 写入操作日志表 fixme 该方法后续即将弃用 +func SetDBOperLog(c *gin.Context, clientIP string, statusCode int, reqUri string, reqMethod string, latencyTime time.Duration, body string, result string, status int) { + + log := api.GetRequestLogger(c) + l := make(map[string]interface{}) + l["_fullPath"] = c.FullPath() + l["operUrl"] = reqUri + l["operIp"] = clientIP + l["operLocation"] = "" // pkg.GetLocation(clientIP, gaConfig.ExtConfig.AMap.Key) + l["operName"] = user.GetUserName(c) + l["requestMethod"] = reqMethod + l["operParam"] = body + l["operTime"] = time.Now() + l["jsonResult"] = result + l["latencyTime"] = latencyTime.String() + l["statusCode"] = statusCode + l["userAgent"] = c.Request.UserAgent() + l["createBy"] = user.GetUserId(c) + l["updateBy"] = user.GetUserId(c) + if status == http.StatusOK { + l["status"] = dto.OperaStatusEnabel + } else { + l["status"] = dto.OperaStatusDisable + } + q := sdk.Runtime.GetMemoryQueue(c.Request.Host) + message, err := sdk.Runtime.GetStreamMessage("", global.OperateLog, l) + if err != nil { + log.Errorf("GetStreamMessage error, %s", err.Error()) + //日志报错错误,不中断请求 + } else { + err = q.Append(message) + if err != nil { + log.Errorf("Append message error, %s", err.Error()) + } + } +} diff --git a/common/middleware/permission.go b/common/middleware/permission.go new file mode 100644 index 0000000..00d1b1f --- /dev/null +++ b/common/middleware/permission.go @@ -0,0 +1,61 @@ +package middleware + +import ( + "github.com/casbin/casbin/v2/util" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + "github.com/go-admin-team/go-admin-core/sdk/pkg/response" +) + +// AuthCheckRole 权限检查中间件 +func AuthCheckRole() gin.HandlerFunc { + return func(c *gin.Context) { + log := api.GetRequestLogger(c) + data, _ := c.Get(jwtauth.JwtPayloadKey) + v := data.(jwtauth.MapClaims) + e := sdk.Runtime.GetCasbinKey(c.Request.Host) + var res, casbinExclude bool + var err error + //检查权限 + if v["rolekey"] == "admin" { + res = true + c.Next() + return + } + for _, i := range CasbinExclude { + if util.KeyMatch2(c.Request.URL.Path, i.Url) && c.Request.Method == i.Method { + casbinExclude = true + break + } + } + if casbinExclude { + log.Infof("Casbin exclusion, no validation method:%s path:%s", c.Request.Method, c.Request.URL.Path) + c.Next() + return + } + res, err = e.Enforce(v["rolekey"], c.Request.URL.Path, c.Request.Method) + if err != nil { + log.Errorf("AuthCheckRole error:%s method:%s path:%s", err, c.Request.Method, c.Request.URL.Path) + response.Error(c, 500, err, "") + return + } + + if res { + log.Infof("isTrue: %v role: %s method: %s path: %s", res, v["rolekey"], c.Request.Method, c.Request.URL.Path) + c.Next() + } else { + log.Warnf("isTrue: %v role: %s method: %s path: %s message: %s", res, v["rolekey"], c.Request.Method, c.Request.URL.Path, "当前request无权限,请管理员确认!") + c.JSON(http.StatusOK, gin.H{ + "code": 403, + "msg": "对不起,您没有该接口访问权限,请联系管理员", + }) + c.Abort() + return + } + + } +} diff --git a/common/middleware/request_id.go b/common/middleware/request_id.go new file mode 100644 index 0000000..8dedd83 --- /dev/null +++ b/common/middleware/request_id.go @@ -0,0 +1,36 @@ +package middleware + +import ( + "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk/pkg" + "net/http" + "strings" + + "github.com/gin-gonic/gin" + "github.com/google/uuid" +) + +// RequestId 自动增加requestId +func RequestId(trafficKey string) gin.HandlerFunc { + return func(c *gin.Context) { + if c.Request.Method == http.MethodOptions { + c.Next() + return + } + requestId := c.GetHeader(trafficKey) + if requestId == "" { + requestId = c.GetHeader(strings.ToLower(trafficKey)) + } + if requestId == "" { + requestId = uuid.New().String() + } + c.Request.Header.Set(trafficKey, requestId) + c.Set(trafficKey, requestId) + c.Set(pkg.LoggerKey, + logger.NewHelper(logger.DefaultLogger). + WithFields(map[string]interface{}{ + trafficKey: requestId, + })) + c.Next() + } +} diff --git a/common/middleware/sentinel.go b/common/middleware/sentinel.go new file mode 100644 index 0000000..603559a --- /dev/null +++ b/common/middleware/sentinel.go @@ -0,0 +1,30 @@ +package middleware + +import ( + "github.com/alibaba/sentinel-golang/core/system" + sentinel "github.com/alibaba/sentinel-golang/pkg/adapters/gin" + "github.com/gin-gonic/gin" + + log "github.com/go-admin-team/go-admin-core/logger" +) + +// Sentinel 限流 +func Sentinel() gin.HandlerFunc { + if _, err := system.LoadRules([]*system.Rule{ + { + MetricType: system.InboundQPS, + TriggerCount: 200, + Strategy: system.BBR, + }, + }); err != nil { + log.Fatalf("Unexpected error: %+v", err) + } + return sentinel.SentinelMiddleware( + sentinel.WithBlockFallback(func(ctx *gin.Context) { + ctx.AbortWithStatusJSON(200, map[string]interface{}{ + "msg": "too many request; the quota used up!", + "code": 500, + }) + }), + ) +} diff --git a/common/middleware/settings.go b/common/middleware/settings.go new file mode 100644 index 0000000..daf8d30 --- /dev/null +++ b/common/middleware/settings.go @@ -0,0 +1,43 @@ +package middleware + +type UrlInfo struct { + Url string + Method string +} + +// CasbinExclude casbin 排除的路由列表 +var CasbinExclude = []UrlInfo{ + {Url: "/api/v1/dict/type-option-select", Method: "GET"}, + {Url: "/api/v1/dict-data/option-select", Method: "GET"}, + {Url: "/api/v1/deptTree", Method: "GET"}, + {Url: "/api/v1/db/tables/page", Method: "GET"}, + {Url: "/api/v1/db/columns/page", Method: "GET"}, + {Url: "/api/v1/gen/toproject/:tableId", Method: "GET"}, + {Url: "/api/v1/gen/todb/:tableId", Method: "GET"}, + {Url: "/api/v1/gen/tabletree", Method: "GET"}, + {Url: "/api/v1/gen/preview/:tableId", Method: "GET"}, + {Url: "/api/v1/gen/apitofile/:tableId", Method: "GET"}, + {Url: "/api/v1/getCaptcha", Method: "GET"}, + {Url: "/api/v1/getinfo", Method: "GET"}, + {Url: "/api/v1/menuTreeselect", Method: "GET"}, + {Url: "/api/v1/menurole", Method: "GET"}, + {Url: "/api/v1/menuids", Method: "GET"}, + {Url: "/api/v1/roleMenuTreeselect/:roleId", Method: "GET"}, + {Url: "/api/v1/roleDeptTreeselect/:roleId", Method: "GET"}, + {Url: "/api/v1/refresh_token", Method: "GET"}, + {Url: "/api/v1/configKey/:configKey", Method: "GET"}, + {Url: "/api/v1/app-config", Method: "GET"}, + {Url: "/api/v1/user/profile", Method: "GET"}, + {Url: "/info", Method: "GET"}, + {Url: "/api/v1/login", Method: "POST"}, + {Url: "/api/v1/logout", Method: "POST"}, + {Url: "/api/v1/user/avatar", Method: "POST"}, + {Url: "/api/v1/user/pwd", Method: "PUT"}, + {Url: "/api/v1/metrics", Method: "GET"}, + {Url: "/api/v1/health", Method: "GET"}, + {Url: "/", Method: "GET"}, + {Url: "/api/v1/server-monitor", Method: "GET"}, + {Url: "/api/v1/public/uploadFile", Method: "POST"}, + {Url: "/api/v1/user/pwd/set", Method: "PUT"}, + {Url: "/api/v1/sys-user", Method: "PUT"}, +} diff --git a/common/middleware/trace.go b/common/middleware/trace.go new file mode 100644 index 0000000..6cce4a3 --- /dev/null +++ b/common/middleware/trace.go @@ -0,0 +1,27 @@ +package middleware + +import ( + "github.com/gin-gonic/gin" + "github.com/opentracing/opentracing-go" +) + +// Trace 链路追踪 +func Trace() gin.HandlerFunc { + return func(ctx *gin.Context) { + var sp opentracing.Span + opName := ctx.Request.URL.Path + // Attempt to join a trace by getting trace context from the headers. + wireContext, err := opentracing.GlobalTracer().Extract( + opentracing.TextMap, + opentracing.HTTPHeadersCarrier(ctx.Request.Header)) + if err != nil { + // If for whatever reason we can't join, go ahead and start a new root span. + sp = opentracing.StartSpan(opName) + } else { + sp = opentracing.StartSpan(opName, opentracing.ChildOf(wireContext)) + } + ctx.Set("traceSpan", sp) + ctx.Next() + sp.Finish() + } +} diff --git a/common/models/by.go b/common/models/by.go new file mode 100644 index 0000000..181c7ed --- /dev/null +++ b/common/models/by.go @@ -0,0 +1,32 @@ +package models + +import ( + "time" + + "gorm.io/gorm" +) + +type ControlBy struct { + CreateBy int `json:"createBy" gorm:"index;comment:创建者"` + UpdateBy int `json:"updateBy" gorm:"index;comment:更新者"` +} + +// SetCreateBy 设置创建人id +func (e *ControlBy) SetCreateBy(createBy int) { + e.CreateBy = createBy +} + +// SetUpdateBy 设置修改人id +func (e *ControlBy) SetUpdateBy(updateBy int) { + e.UpdateBy = updateBy +} + +type Model struct { + Id int `json:"id" gorm:"primaryKey;autoIncrement;comment:主键编码"` +} + +type ModelTime struct { + CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"` + UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"` + DeletedAt gorm.DeletedAt `json:"-" gorm:"index;comment:删除时间"` +} \ No newline at end of file diff --git a/common/models/menu.go b/common/models/menu.go new file mode 100644 index 0000000..e3b0c92 --- /dev/null +++ b/common/models/menu.go @@ -0,0 +1,11 @@ +package models + +// Menu 菜单中的类型枚举值 +const ( + // Directory 目录 + Directory string = "M" + // Menu 菜单 + Menu string = "C" + // Button 按钮 + Button string = "F" +) diff --git a/common/models/migrate.go b/common/models/migrate.go new file mode 100644 index 0000000..5573cb2 --- /dev/null +++ b/common/models/migrate.go @@ -0,0 +1,12 @@ +package models + +import "time" + +type Migration struct { + Version string `gorm:"primaryKey"` + ApplyTime time.Time `gorm:"autoCreateTime"` +} + +func (Migration) TableName() string { + return "sys_migration" +} diff --git a/common/models/response.go b/common/models/response.go new file mode 100644 index 0000000..8ee0625 --- /dev/null +++ b/common/models/response.go @@ -0,0 +1,30 @@ +package models + +type Response struct { + // 代码 + Code int `json:"code" example:"200"` + // 数据集 + Data interface{} `json:"data"` + // 消息 + Msg string `json:"msg"` + RequestId string `json:"requestId"` +} + +type Page struct { + List interface{} `json:"list"` + Count int `json:"count"` + PageIndex int `json:"pageIndex"` + PageSize int `json:"pageSize"` +} + +// ReturnOK 正常返回 +func (res *Response) ReturnOK() *Response { + res.Code = 200 + return res +} + +// ReturnError 错误返回 +func (res *Response) ReturnError(code int) *Response { + res.Code = code + return res +} diff --git a/common/models/type.go b/common/models/type.go new file mode 100644 index 0000000..2087d55 --- /dev/null +++ b/common/models/type.go @@ -0,0 +1,11 @@ +package models + +import "gorm.io/gorm/schema" + +type ActiveRecord interface { + schema.Tabler + SetCreateBy(createBy int) + SetUpdateBy(updateBy int) + Generate() ActiveRecord + GetId() interface{} +} diff --git a/common/models/user.go b/common/models/user.go new file mode 100644 index 0000000..6053bb3 --- /dev/null +++ b/common/models/user.go @@ -0,0 +1,42 @@ +package models + +import ( + "gorm.io/gorm" + + "github.com/go-admin-team/go-admin-core/sdk/pkg" +) + +// BaseUser 密码登录基础用户 +type BaseUser struct { + Username string `json:"username" gorm:"type:varchar(100);comment:用户名"` + Salt string `json:"-" gorm:"type:varchar(255);comment:加盐;<-"` + PasswordHash string `json:"-" gorm:"type:varchar(128);comment:密码hash;<-"` + Password string `json:"password" gorm:"-"` +} + +// SetPassword 设置密码 +func (u *BaseUser) SetPassword(value string) { + u.Password = value + u.generateSalt() + u.PasswordHash = u.GetPasswordHash() +} + +// GetPasswordHash 获取密码hash +func (u *BaseUser) GetPasswordHash() string { + passwordHash, err := pkg.SetPassword(u.Password, u.Salt) + if err != nil { + return "" + } + return passwordHash +} + +// generateSalt 生成加盐值 +func (u *BaseUser) generateSalt() { + u.Salt = pkg.GenerateRandomKey16() +} + +// Verify 验证密码 +func (u *BaseUser) Verify(db *gorm.DB, tableName string) bool { + db.Table(tableName).Where("username = ?", u.Username).First(u) + return u.GetPasswordHash() == u.PasswordHash +} diff --git a/common/response/binding.go b/common/response/binding.go new file mode 100644 index 0000000..6cf279a --- /dev/null +++ b/common/response/binding.go @@ -0,0 +1,105 @@ +package response + +import ( + "fmt" + "github.com/gin-gonic/gin/binding" + "reflect" + "strings" + "sync" +) + +const ( + _ uint8 = iota + json + xml + yaml + form + query +) + +//var constructor = &bindConstructor{} + +type bindConstructor struct { + cache map[string][]uint8 + mux sync.Mutex +} + +func (e *bindConstructor) GetBindingForGin(d interface{}) []binding.Binding { + bs := e.getBinding(reflect.TypeOf(d).String()) + if bs == nil { + //重新构建 + bs = e.resolve(d) + } + gbs := make([]binding.Binding, len(bs)) + for i, b := range bs { + switch b { + case json: + gbs[i] = binding.JSON + case xml: + gbs[i] = binding.XML + case yaml: + gbs[i] = binding.YAML + case form: + gbs[i] = binding.Form + case query: + gbs[i] = binding.Query + default: + gbs[i] = nil + } + } + return gbs +} + +func (e *bindConstructor) resolve(d interface{}) []uint8 { + bs := make([]uint8, 0) + qType := reflect.TypeOf(d).Elem() + var tag reflect.StructTag + var ok bool + fmt.Println(qType.Kind()) + for i := 0; i < qType.NumField(); i++ { + tag = qType.Field(i).Tag + if _, ok = tag.Lookup("json"); ok { + bs = append(bs, json) + } + if _, ok = tag.Lookup("xml"); ok { + bs = append(bs, xml) + } + if _, ok = tag.Lookup("yaml"); ok { + bs = append(bs, yaml) + } + if _, ok = tag.Lookup("form"); ok { + bs = append(bs, form) + } + if _, ok = tag.Lookup("query"); ok { + bs = append(bs, query) + } + if _, ok = tag.Lookup("uri"); ok { + bs = append(bs, 0) + } + if t, ok := tag.Lookup("binding"); ok && strings.Index(t, "dive") > -1 { + qValue := reflect.ValueOf(d) + bs = append(bs, e.resolve(qValue.Field(i))...) + continue + } + if t, ok := tag.Lookup("validate"); ok && strings.Index(t, "dive") > -1 { + qValue := reflect.ValueOf(d) + bs = append(bs, e.resolve(qValue.Field(i))...) + } + } + return bs +} + +func (e *bindConstructor) getBinding(name string) []uint8 { + e.mux.Lock() + defer e.mux.Unlock() + return e.cache[name] +} + +func (e *bindConstructor) setBinding(name string, bs []uint8) { + e.mux.Lock() + defer e.mux.Unlock() + if e.cache == nil { + e.cache = make(map[string][]uint8) + } + e.cache[name] = bs +} diff --git a/common/service/service.go b/common/service/service.go new file mode 100644 index 0000000..0deb4a9 --- /dev/null +++ b/common/service/service.go @@ -0,0 +1,25 @@ +package service + +import ( + "fmt" + + "github.com/go-admin-team/go-admin-core/logger" + "gorm.io/gorm" +) + +type Service struct { + Orm *gorm.DB + Msg string + MsgID string + Log *logger.Helper + Error error +} + +func (db *Service) AddError(err error) error { + if db.Error == nil { + db.Error = err + } else if err != nil { + db.Error = fmt.Errorf("%v; %w", db.Error, err) + } + return db.Error +} diff --git a/common/storage/initialize.go b/common/storage/initialize.go new file mode 100644 index 0000000..6fa323d --- /dev/null +++ b/common/storage/initialize.go @@ -0,0 +1,52 @@ +/* + * @Author: lwnmengjing + * @Date: 2021/6/10 3:39 下午 + * @Last Modified by: lwnmengjing + * @Last Modified time: 2021/6/10 3:39 下午 + */ + +package storage + +import ( + "log" + + "github.com/go-admin-team/go-admin-core/sdk" + "github.com/go-admin-team/go-admin-core/sdk/config" + "github.com/go-admin-team/go-admin-core/sdk/pkg/captcha" +) + +// Setup 配置storage组件 +func Setup() { + //4. 设置缓存 + cacheAdapter, err := config.CacheConfig.Setup() + if err != nil { + log.Fatalf("cache setup error, %s\n", err.Error()) + } + sdk.Runtime.SetCacheAdapter(cacheAdapter) + //5. 设置验证码store + captcha.SetStore(captcha.NewCacheStore(cacheAdapter, 600)) + + //6. 设置队列 + if !config.QueueConfig.Empty() { + if q := sdk.Runtime.GetQueueAdapter(); q != nil { + q.Shutdown() + } + queueAdapter, err := config.QueueConfig.Setup() + if err != nil { + log.Fatalf("queue setup error, %s\n", err.Error()) + } + sdk.Runtime.SetQueueAdapter(queueAdapter) + defer func() { + go queueAdapter.Run() + }() + } + + //7. 设置分布式锁 + if !config.LockerConfig.Empty() { + lockerAdapter, err := config.LockerConfig.Setup() + if err != nil { + log.Fatalf("locker setup error, %s\n", err.Error()) + } + sdk.Runtime.SetLockerAdapter(lockerAdapter) + } +} diff --git a/config/READMEN.md b/config/READMEN.md new file mode 100644 index 0000000..8ff880d --- /dev/null +++ b/config/READMEN.md @@ -0,0 +1,37 @@ +# ⚙ 配置详情 + +1. 配置文件说明 +```yml +settings: + application: + # 项目启动环境 + mode: dev # dev开发环境 test测试环境 prod线上环境; + host: 0.0.0.0 # 主机ip 或者域名,默认0.0.0.0 + # 服务名称 + name: go-admin + # 服务端口 + port: 8000 + readtimeout: 1 + writertimeout: 2 + log: + # 日志文件存放路径 + dir: temp/logs + jwt: + # JWT加密字符串 + secret: go-admin + # 过期时间单位:秒 + timeout: 3600 + database: + # 数据库名称 + name: dbname + # 数据库类型 + dbtype: mysql + # 数据库地址 + host: 127.0.0.1 + # 数据库密码 + password: password + # 数据库端口 + port: 3306 + # 数据库用户名 + username: root +``` \ No newline at end of file diff --git a/config/db-begin-mysql.sql b/config/db-begin-mysql.sql new file mode 100644 index 0000000..04da2f1 --- /dev/null +++ b/config/db-begin-mysql.sql @@ -0,0 +1,2 @@ +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; \ No newline at end of file diff --git a/config/db-end-mysql.sql b/config/db-end-mysql.sql new file mode 100644 index 0000000..4bd9d01 --- /dev/null +++ b/config/db-end-mysql.sql @@ -0,0 +1 @@ +SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file diff --git a/config/db-sqlserver.sql b/config/db-sqlserver.sql new file mode 100644 index 0000000..0ba4168 --- /dev/null +++ b/config/db-sqlserver.sql @@ -0,0 +1,342 @@ +-- 开始初始化数据 ; +SET IDENTITY_INSERT sys_api ON; +INSERT INTO sys_api (id, handle, title, path, type, "action", created_at, updated_at, deleted_at, create_by, update_by)VALUES +(5, 'go-admin/app/admin/apis.SysLoginLog.Get-fm', '登录日志通过id获取', '/api/v1/sys-login-log/:id', 'BUS', 'GET', '2021-05-13 19:59:00.728', '2021-06-17 11:37:12.331', NULL, 0, 0), +(6, 'go-admin/app/admin/apis.SysOperaLog.GetPage-fm', '操作日志列表', '/api/v1/sys-opera-log', 'BUS', 'GET', '2021-05-13 19:59:00.778', '2021-06-17 11:48:40.732', NULL, 0, 0), +(7, 'go-admin/app/admin/apis.SysOperaLog.Get-fm', '操作日志通过id获取', '/api/v1/sys-opera-log/:id', 'BUS', 'GET', '2021-05-13 19:59:00.821', '2021-06-16 21:49:48.598', NULL, 0, 0), +(8, 'go-admin/common/actions.IndexAction.func1', '分类列表', '/api/v1/syscategory', 'BUS', 'GET', '2021-05-13 19:59:00.870', '2021-06-13 20:53:47.883', NULL, 0, 0), +(9, 'go-admin/common/actions.ViewAction.func1', '分类通过id获取', '/api/v1/syscategory/:id', 'BUS', 'GET', '2021-05-13 19:59:00.945', '2021-06-13 20:53:47.926', NULL, 0, 0), +(10, 'go-admin/common/actions.IndexAction.func1', '内容列表', '/api/v1/syscontent', 'BUS', 'GET', '2021-05-13 19:59:01.005', '2021-06-13 20:53:47.966', NULL, 0, 0), +(11, 'go-admin/common/actions.ViewAction.func1', '内容通过id获取', '/api/v1/syscontent/:id', 'BUS', 'GET', '2021-05-13 19:59:01.056', '2021-06-13 20:53:48.005', NULL, 0, 0), +(15, 'go-admin/common/actions.IndexAction.func1', 'job列表', '/api/v1/sysjob', 'BUS', 'GET', '2021-05-13 19:59:01.248', '2021-06-13 20:53:48.169', NULL, 0, 0), +(16, 'go-admin/common/actions.ViewAction.func1', 'job通过id获取', '/api/v1/sysjob/:id', 'BUS', 'GET', '2021-05-13 19:59:01.298', '2021-06-13 20:53:48.214', NULL, 0, 0), +(21, 'go-admin/app/admin/apis.SysDictType.GetPage-fm', '字典类型列表', '/api/v1/dict/type', 'BUS', 'GET', '2021-05-13 19:59:01.525', '2021-06-17 11:48:40.732', NULL, 0, 0), +(22, 'go-admin/app/admin/apis.SysDictType.GetAll-fm', '字典类型查询【代码生成】', '/api/v1/dict/type-option-select', 'SYS', 'GET', '2021-05-13 19:59:01.582', '2021-06-13 20:53:48.388', NULL, 0, 0), +(23, 'go-admin/app/admin/apis.SysDictType.Get-fm', '字典类型通过id获取', '/api/v1/dict/type/:id', 'BUS', 'GET', '2021-05-13 19:59:01.632', '2021-06-17 11:48:40.732', NULL, 0, 0), +(24, 'go-admin/app/admin/apis.SysDictData.GetPage-fm', '字典数据列表', '/api/v1/dict/data', 'BUS', 'GET', '2021-05-13 19:59:01.684', '2021-06-17 11:48:40.732', NULL, 0, 0), +(25, 'go-admin/app/admin/apis.SysDictData.Get-fm', '字典数据通过code获取', '/api/v1/dict/data/:dictCode', 'BUS', 'GET', '2021-05-13 19:59:01.732', '2021-06-17 11:48:40.732', NULL, 0, 0), +(26, 'go-admin/app/admin/apis.SysDictData.GetSysDictDataAll-fm', '数据字典根据key获取', '/api/v1/dict-data/option-select', 'SYS', 'GET', '2021-05-13 19:59:01.832', '2021-06-17 11:48:40.732', NULL, 0, 0), +(27, 'go-admin/app/admin/apis.SysDept.GetPage-fm', '部门列表', '/api/v1/dept', 'BUS', 'GET', '2021-05-13 19:59:01.940', '2021-06-17 11:48:40.732', NULL, 0, 0), +(28, 'go-admin/app/admin/apis.SysDept.Get-fm', '部门通过id获取', '/api/v1/dept/:id', 'BUS', 'GET', '2021-05-13 19:59:02.009', '2021-06-17 11:48:40.732', NULL, 0, 0), +(29, 'go-admin/app/admin/apis.SysDept.Get2Tree-fm', '查询部门下拉树【角色权限-自定权限】', '/api/v1/deptTree', 'SYS', 'GET', '2021-05-13 19:59:02.050', '2021-06-17 11:48:40.732', NULL, 0, 0), +(30, 'go-admin/app/admin/apis/tools.(*Gen).GetDBTableList-fm', '数据库表列表', '/api/v1/db/tables/page', 'SYS', 'GET', '2021-05-13 19:59:02.098', '2021-06-13 20:53:48.730', NULL, 0, 0), +(31, 'go-admin/app/admin/apis/tools.(*Gen).GetDBColumnList-fm', '数据表列列表', '/api/v1/db/columns/page', 'SYS', 'GET', '2021-05-13 19:59:02.140', '2021-06-13 20:53:48.771', NULL, 0, 0), +(32, 'go-admin/app/admin/apis/tools.Gen.GenCode-fm', '数据库表生成到项目', '/api/v1/gen/toproject/:tableId', 'SYS', 'GET', '2021-05-13 19:59:02.183', '2021-06-13 20:53:48.812', NULL, 0, 0), +(33, 'go-admin/app/admin/apis/tools.Gen.GenMenuAndApi-fm', '数据库表生成到DB', '/api/v1/gen/todb/:tableId', 'SYS', 'GET', '2021-05-13 19:59:02.227', '2021-06-13 20:53:48.853', NULL, 0, 0), +(34, 'go-admin/app/admin/apis/tools.(*SysTable).GetSysTablesTree-fm', '关系表数据【代码生成】', '/api/v1/gen/tabletree', 'SYS', 'GET', '2021-05-13 19:59:02.271', '2021-06-13 20:53:48.893', NULL, 0, 0), +(35, 'go-admin/app/admin/apis/tools.Gen.Preview-fm', '生成预览通过id获取', '/api/v1/gen/preview/:tableId', 'SYS', 'GET', '2021-05-13 19:59:02.315', '2021-06-13 20:53:48.935', NULL, 0, 0), +(36, 'go-admin/app/admin/apis/tools.Gen.GenApiToFile-fm', '生成api带文件', '/api/v1/gen/apitofile/:tableId', 'SYS', 'GET', '2021-05-13 19:59:02.357', '2021-06-13 20:53:48.977', NULL, 0, 0), +(37, 'go-admin/app/admin/apis.System.GenerateCaptchaHandler-fm', '验证码获取', '/api/v1/getCaptcha', 'SYS', 'GET', '2021-05-13 19:59:02.405', '2021-06-13 20:53:49.020', NULL, 0, 0), +(38, 'go-admin/app/admin/apis.SysUser.GetInfo-fm', '用户信息获取', '/api/v1/getinfo', 'SYS', 'GET', '2021-05-13 19:59:02.447', '2021-06-13 20:53:49.065', NULL, 0, 0), +(39, 'go-admin/app/admin/apis.SysMenu.GetPage-fm', '菜单列表', '/api/v1/menu', 'BUS', 'GET', '2021-05-13 19:59:02.497', '2021-06-17 11:48:40.732', NULL, 0, 0), +(40, 'go-admin/app/admin/apis.SysMenu.GetMenuTreeSelect-fm', '查询菜单下拉树结构【废弃】', '/api/v1/menuTreeselect', 'SYS', 'GET', '2021-05-13 19:59:02.542', '2021-06-03 22:37:21.857', NULL, 0, 0), +(41, 'go-admin/app/admin/apis.SysMenu.Get-fm', '菜单通过id获取', '/api/v1/menu/:id', 'BUS', 'GET', '2021-05-13 19:59:02.584', '2021-06-17 11:48:40.732', NULL, 0, 0), +(42, 'go-admin/app/admin/apis.SysMenu.GetMenuRole-fm', '角色菜单【顶部左侧菜单】', '/api/v1/menurole', 'SYS', 'GET', '2021-05-13 19:59:02.630', '2021-06-13 20:53:49.574', NULL, 0, 0), +(43, 'go-admin/app/admin/apis.SysMenu.GetMenuIDS-fm', '获取角色对应的菜单id数组【废弃】', '/api/v1/menuids', 'SYS', 'GET', '2021-05-13 19:59:02.675', '2021-06-03 22:39:52.500', NULL, 0, 0), +(44, 'go-admin/app/admin/apis.SysRole.GetPage-fm', '角色列表', '/api/v1/role', 'BUS', 'GET', '2021-05-13 19:59:02.720', '2021-06-17 11:48:40.732', NULL, 0, 0), +(45, 'go-admin/app/admin/apis.SysMenu.GetMenuTreeSelect-fm', '菜单权限列表【角色配菜单使用】', '/api/v1/roleMenuTreeselect/:roleId', 'SYS', 'GET', '2021-05-13 19:59:02.762', '2021-06-17 11:48:40.732', NULL, 0, 0), +(46, 'go-admin/app/admin/apis.SysDept.GetDeptTreeRoleSelect-fm', '角色部门结构树【自定义数据权限】', '/api/v1/roleDeptTreeselect/:roleId', 'SYS', 'GET', '2021-05-13 19:59:02.809', '2021-06-17 11:48:40.732', NULL, 0, 0), +(47, 'go-admin/app/admin/apis.SysRole.Get-fm', '角色通过id获取', '/api/v1/role/:id', 'BUS', 'GET', '2021-05-13 19:59:02.850', '2021-06-17 11:48:40.732', NULL, 0, 0), +(48, 'github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth.(*GinJWTMiddleware).RefreshHandler-fm', '刷新token', '/api/v1/refresh_token', 'SYS', 'GET', '2021-05-13 19:59:02.892', '2021-06-13 20:53:49.278', NULL, 0, 0), +(53, 'go-admin/app/admin/apis.SysConfig.GetPage-fm', '参数列表', '/api/v1/config', 'BUS', 'GET', '2021-05-13 19:59:03.116', '2021-06-17 11:48:40.732', NULL, 0, 0), +(54, 'go-admin/app/admin/apis.SysConfig.Get-fm', '参数通过id获取', '/api/v1/config/:id', 'BUS', 'GET', '2021-05-13 19:59:03.157', '2021-06-17 11:48:40.732', NULL, 0, 0), +(55, 'go-admin/app/admin/apis.SysConfig.GetSysConfigByKEYForService-fm', '参数通过键名搜索【基础默认配置】', '/api/v1/configKey/:configKey', 'SYS', 'GET', '2021-05-13 19:59:03.198', '2021-06-13 20:53:49.745', NULL, 0, 0), +(57, 'go-admin/app/jobs/apis.SysJob.RemoveJobForService-fm', 'job移除', '/api/v1/job/remove/:id', 'BUS', 'GET', '2021-05-13 19:59:03.295', '2021-06-13 20:53:49.786', NULL, 0, 0), +(58, 'go-admin/app/jobs/apis.SysJob.StartJobForService-fm', 'job启动', '/api/v1/job/start/:id', 'BUS', 'GET', '2021-05-13 19:59:03.339', '2021-06-13 20:53:49.829', NULL, 0, 0), +(59, 'go-admin/app/admin/apis.SysPost.GetPage-fm', '岗位列表', '/api/v1/post', 'BUS', 'GET', '2021-05-13 19:59:03.381', '2021-06-17 11:48:40.732', NULL, 0, 0), +(60, 'go-admin/app/admin/apis.SysPost.Get-fm', '岗位通过id获取', '/api/v1/post/:id', 'BUS', 'GET', '2021-05-13 19:59:03.433', '2021-06-17 11:48:40.732', NULL, 0, 0), +(62, 'go-admin/app/admin/apis.SysConfig.GetSysConfigBySysApp-fm', '系统前端参数', '/api/v1/app-config', 'SYS', 'GET', '2021-05-13 19:59:03.526', '2021-06-13 20:53:49.994', NULL, 0, 0), +(63, 'go-admin/app/admin/apis.SysUser.GetProfile-fm', '*用户信息获取', '/api/v1/user/profile', 'SYS', 'GET', '2021-05-13 19:59:03.567', '2021-06-13 20:53:50.038', NULL, 0, 0), +(66, 'github.com/go-admin-team/go-admin-core/sdk/pkg/ws.(*Manager).WsClient-fm', '链接ws【定时任务log】', '/ws/:id/:channel', 'BUS', 'GET', '2021-05-13 19:59:03.705', '2021-06-13 20:53:50.167', NULL, 0, 0), +(67, 'github.com/go-admin-team/go-admin-core/sdk/pkg/ws.(*Manager).UnWsClient-fm', '退出ws【定时任务log】', '/wslogout/:id/:channel', 'BUS', 'GET', '2021-05-13 19:59:03.756', '2021-06-13 20:53:50.209', NULL, 0, 0), +(68, 'go-admin/common/middleware/handler.Ping', '*用户基本信息', '/info', 'SYS', 'GET', '2021-05-13 19:59:03.800', '2021-06-13 20:53:50.251', NULL, 0, 0), +(72, 'go-admin/common/actions.CreateAction.func1', '分类创建', '/api/v1/syscategory', 'BUS', 'POST', '2021-05-13 19:59:03.982', '2021-06-13 20:53:50.336', NULL, 0, 0), +(73, 'go-admin/common/actions.CreateAction.func1', '内容创建', '/api/v1/syscontent', 'BUS', 'POST', '2021-05-13 19:59:04.027', '2021-06-13 20:53:50.375', NULL, 0, 0), +(76, 'go-admin/common/actions.CreateAction.func1', 'job创建', '/api/v1/sysjob', 'BUS', 'POST', '2021-05-13 19:59:04.164', '2021-06-13 20:53:50.500', NULL, 0, 0), +(80, 'go-admin/app/admin/apis.SysDictData.Insert-fm', '字典数据创建', '/api/v1/dict/data', 'BUS', 'POST', '2021-05-13 19:59:04.347', '2021-06-17 11:48:40.732', NULL, 0, 0), +(81, 'go-admin/app/admin/apis.SysDictType.Insert-fm', '字典类型创建', '/api/v1/dict/type', 'BUS', 'POST', '2021-05-13 19:59:04.391', '2021-06-17 11:48:40.732', NULL, 0, 0), +(82, 'go-admin/app/admin/apis.SysDept.Insert-fm', '部门创建', '/api/v1/dept', 'BUS', 'POST', '2021-05-13 19:59:04.435', '2021-06-17 11:48:40.732', NULL, 0, 0), +(85, 'github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth.(*GinJWTMiddleware).LoginHandler-fm', '*登录', '/api/v1/login', 'SYS', 'POST', '2021-05-13 19:59:04.597', '2021-06-13 20:53:50.784', NULL, 0, 0), +(86, 'go-admin/common/middleware/handler.LogOut', '*退出', '/api/v1/logout', 'SYS', 'POST', '2021-05-13 19:59:04.642', '2021-06-13 20:53:50.824', NULL, 0, 0), +(87, 'go-admin/app/admin/apis.SysConfig.Insert-fm', '参数创建', '/api/v1/config', 'BUS', 'POST', '2021-05-13 19:59:04.685', '2021-06-17 11:48:40.732', NULL, 0, 0), +(88, 'go-admin/app/admin/apis.SysMenu.Insert-fm', '菜单创建', '/api/v1/menu', 'BUS', 'POST', '2021-05-13 19:59:04.777', '2021-06-17 11:48:40.732', NULL, 0, 0), +(89, 'go-admin/app/admin/apis.SysPost.Insert-fm', '岗位创建', '/api/v1/post', 'BUS', 'POST', '2021-05-13 19:59:04.886', '2021-06-17 11:48:40.732', NULL, 0, 0), +(90, 'go-admin/app/admin/apis.SysRole.Insert-fm', '角色创建', '/api/v1/role', 'BUS', 'POST', '2021-05-13 19:59:04.975', '2021-06-17 11:48:40.732', NULL, 0, 0), +(91, 'go-admin/app/admin/apis.SysUser.InsetAvatar-fm', '*用户头像编辑', '/api/v1/user/avatar', 'SYS', 'POST', '2021-05-13 19:59:05.058', '2021-06-13 20:53:51.079', NULL, 0, 0), +(92, 'go-admin/app/admin/apis.SysApi.Update-fm', '接口编辑', '/api/v1/sys-api/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.122', '2021-06-17 11:48:40.732', NULL, 0, 0), +(95, 'go-admin/common/actions.UpdateAction.func1', '分类编辑', '/api/v1/syscategory/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.255', '2021-06-13 20:53:51.247', NULL, 0, 0), +(96, 'go-admin/common/actions.UpdateAction.func1', '内容编辑', '/api/v1/syscontent/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.299', '2021-06-13 20:53:51.289', NULL, 0, 0), +(97, 'go-admin/common/actions.UpdateAction.func1', 'job编辑', '/api/v1/sysjob', 'BUS', 'PUT', '2021-05-13 19:59:05.343', '2021-06-13 20:53:51.331', NULL, 0, 0), +(101, 'go-admin/app/admin/apis.SysDictData.Update-fm', '字典数据编辑', '/api/v1/dict/data/:dictCode', 'BUS', 'PUT', '2021-05-13 19:59:05.519', '2021-06-17 11:48:40.732', NULL, 0, 0), +(102, 'go-admin/app/admin/apis.SysDictType.Update-fm', '字典类型编辑', '/api/v1/dict/type/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.569', '2021-06-17 11:48:40.732', NULL, 0, 0), +(103, 'go-admin/app/admin/apis.SysDept.Update-fm', '部门编辑', '/api/v1/dept/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.613', '2021-06-17 11:48:40.732', NULL, 0, 0), +(104, 'go-admin/app/other/apis.SysFileDir.Update-fm', '文件夹编辑', '/api/v1/file-dir/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.662', '2021-06-13 20:53:51.847', NULL, 0, 0), +(105, 'go-admin/app/other/apis.SysFileInfo.Update-fm', '文件编辑', '/api/v1/file-info/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.709', '2021-06-13 20:53:51.892', NULL, 0, 0), +(106, 'go-admin/app/admin/apis.SysRole.Update-fm', '角色编辑', '/api/v1/role/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.752', '2021-06-17 11:48:40.732', NULL, 0, 0), +(107, 'go-admin/app/admin/apis.SysRole.Update2DataScope-fm', '角色数据权限修改', '/api/v1/roledatascope', 'BUS', 'PUT', '2021-05-13 19:59:05.803', '2021-06-17 11:48:40.732', NULL, 0, 0), +(108, 'go-admin/app/admin/apis.SysConfig.Update-fm', '参数编辑', '/api/v1/config/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.848', '2021-06-17 11:48:40.732', NULL, 0, 0), +(109, 'go-admin/app/admin/apis.SysMenu.Update-fm', '编辑菜单', '/api/v1/menu/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.891', '2021-06-17 11:48:40.732', NULL, 0, 0), +(110, 'go-admin/app/admin/apis.SysPost.Update-fm', '岗位编辑', '/api/v1/post/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.934', '2021-06-17 11:48:40.732', NULL, 0, 0), +(111, 'go-admin/app/admin/apis.SysUser.UpdatePwd-fm', '*用户修改密码', '/api/v1/user/pwd', 'SYS', 'PUT', '2021-05-13 19:59:05.987', '2021-06-13 20:53:51.724', NULL, 0, 0), +(112, 'go-admin/common/actions.DeleteAction.func1', '分类删除', '/api/v1/syscategory', 'BUS', 'DELETE', '2021-05-13 19:59:06.030', '2021-06-13 20:53:52.237', NULL, 0, 0), +(113, 'go-admin/common/actions.DeleteAction.func1', '内容删除', '/api/v1/syscontent', 'BUS', 'DELETE', '2021-05-13 19:59:06.076', '2021-06-13 20:53:52.278', NULL, 0, 0), +(114, 'go-admin/app/admin/apis.SysLoginLog.Delete-fm', '登录日志删除', '/api/v1/sys-login-log', 'BUS', 'DELETE', '2021-05-13 19:59:06.118', '2021-06-17 11:48:40.732', NULL, 0, 0), +(115, 'go-admin/app/admin/apis.SysOperaLog.Delete-fm', '操作日志删除', '/api/v1/sys-opera-log', 'BUS', 'DELETE', '2021-05-13 19:59:06.162', '2021-06-17 11:48:40.732', NULL, 0, 0), +(116, 'go-admin/common/actions.DeleteAction.func1', 'job删除', '/api/v1/sysjob', 'BUS', 'DELETE', '2021-05-13 19:59:06.206', '2021-06-13 20:53:52.323', NULL, 0, 0), +(117, 'go-admin/app/other/apis.SysChinaAreaData.Delete-fm', '行政区删除', '/api/v1/sys-area-data', 'BUS', 'DELETE', '2021-05-13 19:59:06.249', '2021-06-13 20:53:52.061', NULL, 0, 0), +(120, 'go-admin/app/admin/apis.SysDictData.Delete-fm', '字典数据删除', '/api/v1/dict/data', 'BUS', 'DELETE', '2021-05-13 19:59:06.387', '2021-06-17 11:48:40.732', NULL, 0, 0), +(121, 'go-admin/app/admin/apis.SysDictType.Delete-fm', '字典类型删除', '/api/v1/dict/type', 'BUS', 'DELETE', '2021-05-13 19:59:06.432', '2021-06-17 11:48:40.732', NULL, 0, 0), +(122, 'go-admin/app/admin/apis.SysDept.Delete-fm', '部门删除', '/api/v1/dept/:id', 'BUS', 'DELETE', '2021-05-13 19:59:06.475', '2021-06-17 11:48:40.732', NULL, 0, 0), +(123, 'go-admin/app/other/apis.SysFileDir.Delete-fm', '文件夹删除', '/api/v1/file-dir/:id', 'BUS', 'DELETE', '2021-05-13 19:59:06.520', '2021-06-13 20:53:52.539', NULL, 0, 0), +(124, 'go-admin/app/other/apis.SysFileInfo.Delete-fm', '文件删除', '/api/v1/file-info/:id', 'BUS', 'DELETE', '2021-05-13 19:59:06.566', '2021-06-13 20:53:52.580', NULL, 0, 0), +(125, 'go-admin/app/admin/apis.SysConfig.Delete-fm', '参数删除', '/api/v1/config', 'BUS', 'DELETE', '2021-05-13 19:59:06.612', '2021-06-17 11:48:40.732', NULL, 0, 0), +(126, 'go-admin/app/admin/apis.SysMenu.Delete-fm', '删除菜单', '/api/v1/menu', 'BUS', 'DELETE', '2021-05-13 19:59:06.654', '2021-06-17 11:48:40.732', NULL, 0, 0), +(127, 'go-admin/app/admin/apis.SysPost.Delete-fm', '岗位删除', '/api/v1/post/:id', 'BUS', 'DELETE', '2021-05-13 19:59:06.702', '2021-06-17 11:48:40.732', NULL, 0, 0), +(128, 'go-admin/app/admin/apis.SysRole.Delete-fm', '角色删除', '/api/v1/role', 'BUS', 'DELETE', '2021-05-13 19:59:06.746', '2021-06-17 11:48:40.732', NULL, 0, 0), +(131, 'github.com/go-admin-team/go-admin-core/tools/transfer.Handler.func1', '系统指标', '/api/v1/metrics', 'SYS', 'GET', '2021-05-17 22:13:55.933', '2021-06-13 20:53:49.614', NULL, 0, 0), +(132, 'go-admin/app/other/router.registerMonitorRouter.func1', '健康状态', '/api/v1/health', 'SYS', 'GET', '2021-05-17 22:13:56.285', '2021-06-13 20:53:49.951', NULL, 0, 0), +(133, 'go-admin/app/admin/apis.HelloWorld', '项目默认接口', '/', 'SYS', 'GET', '2021-05-24 10:30:44.553', '2021-06-13 20:53:47.406', NULL, 0, 0), +(134, 'go-admin/app/other/apis.ServerMonitor.ServerInfo-fm', '服务器基本状态', '/api/v1/server-monitor', 'SYS', 'GET', '2021-05-24 10:30:44.937', '2021-06-13 20:53:48.255', NULL, 0, 0), +(135, 'go-admin/app/admin/apis.SysApi.GetPage-fm', '接口列表', '/api/v1/sys-api', 'BUS', 'GET', '2021-05-24 11:37:53.303', '2021-06-17 11:48:40.732', NULL, 0, 0), +(136, 'go-admin/app/admin/apis.SysApi.Get-fm', '接口通过id获取', '/api/v1/sys-api/:id', 'BUS', 'GET', '2021-05-24 11:37:53.359', '2021-06-17 11:48:40.732', NULL, 0, 0), +(137, 'go-admin/app/admin/apis.SysLoginLog.GetPage-fm', '登录日志列表', '/api/v1/sys-login-log', 'BUS', 'GET', '2021-05-24 11:47:30.397', '2021-06-17 11:48:40.732', NULL, 0, 0), +(138, 'go-admin/app/other/apis.File.UploadFile-fm', '文件上传', '/api/v1/public/uploadFile', 'SYS', 'POST', '2021-05-25 19:16:18.493', '2021-06-13 20:53:50.866', NULL, 0, 0), +(139, 'go-admin/app/admin/apis.SysConfig.Update2Set-fm', '参数信息修改【参数配置】', '/api/v1/set-config', 'BUS', 'PUT', '2021-05-27 09:45:14.853', '2021-06-17 11:48:40.732', NULL, 0, 0), +(140, 'go-admin/app/admin/apis.SysConfig.Get2Set-fm', '参数获取全部【配置使用】', '/api/v1/set-config', 'BUS', 'GET', '2021-05-27 11:54:14.384', '2021-06-17 11:48:40.732', NULL, 0, 0), +(141, 'go-admin/app/admin/apis.SysUser.GetPage-fm', '管理员列表', '/api/v1/sys-user', 'BUS', 'GET', '2021-06-13 19:24:57.111', '2021-06-17 20:31:14.318', NULL, 0, 0), +(142, 'go-admin/app/admin/apis.SysUser.Get-fm', '管理员通过id获取', '/api/v1/sys-user/:id', 'BUS', 'GET', '2021-06-13 19:24:57.188', '2021-06-17 20:31:14.318', NULL, 0, 0), +(143, 'go-admin/app/admin/apis/tools.(*SysTable).GetSysTablesInfo-fm', '', '/api/v1/sys/tables/info', '', 'GET', '2021-06-13 19:24:57.437', '2021-06-13 20:53:48.047', NULL, 0, 0), +(144, 'go-admin/app/admin/apis/tools.(*SysTable).GetSysTables-fm', '', '/api/v1/sys/tables/info/:tableId', '', 'GET', '2021-06-13 19:24:57.510', '2021-06-13 20:53:48.088', NULL, 0, 0), +(145, 'go-admin/app/admin/apis/tools.(*SysTable).GetSysTableList-fm', '', '/api/v1/sys/tables/page', '', 'GET', '2021-06-13 19:24:57.582', '2021-06-13 20:53:48.128', NULL, 0, 0), +(146, 'github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1', '', '/static/*filepath', '', 'GET', '2021-06-13 19:24:59.641', '2021-06-13 20:53:50.081', NULL, 0, 0), +(147, 'github.com/swaggo/gin-swagger.CustomWrapHandler.func1', '', '/swagger/*any', '', 'GET', '2021-06-13 19:24:59.713', '2021-06-13 20:53:50.123', NULL, 0, 0), +(148, 'github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1', '', '/form-generator/*filepath', '', 'GET', '2021-06-13 19:24:59.914', '2021-06-13 20:53:50.295', NULL, 0, 0), +(149, 'go-admin/app/admin/apis/tools.(*SysTable).InsertSysTable-fm', '', '/api/v1/sys/tables/info', '', 'POST', '2021-06-13 19:25:00.163', '2021-06-13 20:53:50.539', NULL, 0, 0), +(150, 'go-admin/app/admin/apis.SysUser.Insert-fm', '管理员创建', '/api/v1/sys-user', 'BUS', 'POST', '2021-06-13 19:25:00.233', '2021-06-17 20:31:14.318', NULL, 0, 0), +(151, 'go-admin/app/admin/apis.SysUser.Update-fm', '管理员编辑', '/api/v1/sys-user', 'BUS', 'PUT', '2021-06-13 19:25:00.986', '2021-06-17 20:31:14.318', NULL, 0, 0), +(152, 'go-admin/app/admin/apis/tools.(*SysTable).UpdateSysTable-fm', '', '/api/v1/sys/tables/info', '', 'PUT', '2021-06-13 19:25:01.149', '2021-06-13 20:53:51.375', NULL, 0, 0), +(153, 'go-admin/app/admin/apis.SysRole.Update2Status-fm', '', '/api/v1/role-status', '', 'PUT', '2021-06-13 19:25:01.446', '2021-06-13 20:53:51.636', NULL, 0, 0), +(154, 'go-admin/app/admin/apis.SysUser.ResetPwd-fm', '', '/api/v1/user/pwd/reset', '', 'PUT', '2021-06-13 19:25:01.601', '2021-06-13 20:53:51.764', NULL, 0, 0), +(155, 'go-admin/app/admin/apis.SysUser.UpdateStatus-fm', '', '/api/v1/user/status', '', 'PUT', '2021-06-13 19:25:01.671', '2021-06-13 20:53:51.806', NULL, 0, 0), +(156, 'go-admin/app/admin/apis.SysUser.Delete-fm', '管理员删除', '/api/v1/sys-user', 'BUS', 'DELETE', '2021-06-13 19:25:02.043', '2021-06-17 20:31:14.318', NULL, 0, 0), +(157, 'go-admin/app/admin/apis/tools.(*SysTable).DeleteSysTables-fm', '', '/api/v1/sys/tables/info/:tableId', '', 'DELETE', '2021-06-13 19:25:02.283', '2021-06-13 20:53:52.367', NULL, 0, 0), +(158, 'github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1', '', '/static/*filepath', '', 'HEAD', '2021-06-13 19:25:02.734', '2021-06-13 20:53:52.791', NULL, 0, 0), +(159, 'github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1', '', '/form-generator/*filepath', '', 'HEAD', '2021-06-13 19:25:02.808', '2021-06-13 20:53:52.838', NULL, 0, 0); +SET IDENTITY_INSERT sys_api OFF; + +INSERT INTO sys_config VALUES +(1, '皮肤样式', 'sys_index_skinName', 'skin-green', 'Y', '0', '主框架页-默认皮肤样式名称:蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow', 1, 1, '2021-05-13 19:56:37.913', '2021-06-05 13:50:13.123', NULL), +(2, '初始密码', 'sys_user_initPassword', '123456', 'Y', '0', '用户管理-账号初始密码:123456', 1, 1, '2021-05-13 19:56:37.913', '2021-05-13 19:56:37.913', NULL), +(3, '侧栏主题', 'sys_index_sideTheme', 'theme-dark', 'Y', '0', '主框架页-侧边栏主题:深色主题theme-dark,浅色主题theme-light', 1, 1, '2021-05-13 19:56:37.913', '2021-05-13 19:56:37.913', NULL), +(4, '系统名称', 'sys_app_name', 'go-admin管理系统', 'Y', '1', '', 1, 0, '2021-03-17 08:52:06.067', '2021-05-28 10:08:25.248', NULL), +(5, '系统logo', 'sys_app_logo', 'https://gitee.com/mydearzwj/image/raw/master/img/go-admin.png', 'Y', '1', '', 1, 0, '2021-03-17 08:53:19.462', '2021-03-17 08:53:19.462', NULL); + +SET IDENTITY_INSERT sys_dept ON; +INSERT INTO sys_dept (dept_id, parent_id, dept_path, dept_name, sort, leader, phone, email, status, create_by, update_by, created_at, updated_at, deleted_at)VALUES +(1, 0, '/0/1/', '爱拓科技', 0, 'aituo', '13782218188', 'atuo@aituo.com', '2', 1, 1, '2021-05-13 19:56:37.913', '2021-06-05 17:06:44.960', NULL), +(7, 1, '/0/1/7/', '研发部', 1, 'aituo', '13782218188', 'atuo@aituo.com', '2', 1, 1, '2021-05-13 19:56:37.913', '2021-06-16 21:35:00.109', NULL), +(8, 1, '/0/1/8/', '运维部', 0, 'aituo', '13782218188', 'atuo@aituo.com', '2', 1, 1, '2021-05-13 19:56:37.913', '2021-06-16 21:41:39.747', NULL), +(9, 1, '/0/1/9/', '客服部', 0, 'aituo', '13782218188', 'atuo@aituo.com', '2', 1, 1, '2021-05-13 19:56:37.913', '2021-06-05 17:07:05.993', NULL), +(10, 1, '/0/1/10/', '人力资源', 3, 'aituo', '13782218188', 'atuo@aituo.com', '1', 1, 1, '2021-05-13 19:56:37.913', '2021-06-05 17:07:08.503', NULL); +SET IDENTITY_INSERT sys_dept OFF; + +INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, + status, "default", remark, create_by, update_by, created_at, updated_at, deleted_at)VALUES +(1, 0, '正常', '2', 'sys_normal_disable', '', '', '', '2', '', '系统正常', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:40.168', NULL); +INSERT INTO sys_dict_data VALUES (2, 0, '停用', '1', 'sys_normal_disable', '', '', '', '2', '', '系统停用', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (3, 0, '男', '0', 'sys_user_sex', '', '', '', '2', '', '性别男', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (4, 0, '女', '1', 'sys_user_sex', '', '', '', '2', '', '性别女', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (5, 0, '未知', '2', 'sys_user_sex', '', '', '', '2', '', '性别未知', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (6, 0, '显示', '0', 'sys_show_hide', '', '', '', '2', '', '显示菜单', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (7, 0, '隐藏', '1', 'sys_show_hide', '', '', '', '2', '', '隐藏菜单', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (8, 0, '是', 'Y', 'sys_yes_no', '', '', '', '2', '', '系统默认是', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (9, 0, '否', 'N', 'sys_yes_no', '', '', '', '2', '', '系统默认否', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (10, 0, '正常', '2', 'sys_job_status', '', '', '', '2', '', '正常状态', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (11, 0, '停用', '1', 'sys_job_status', '', '', '', '2', '', '停用状态', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (12, 0, '默认', 'DEFAULT', 'sys_job_group', '', '', '', '2', '', '默认分组', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (13, 0, '系统', 'SYSTEM', 'sys_job_group', '', '', '', '2', '', '系统分组', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (14, 0, '通知', '1', 'sys_notice_type', '', '', '', '2', '', '通知', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (15, 0, '公告', '2', 'sys_notice_type', '', '', '', '2', '', '公告', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (16, 0, '正常', '2', 'sys_common_status', '', '', '', '2', '', '正常状态', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (17, 0, '关闭', '1', 'sys_common_status', '', '', '', '2', '', '关闭状态', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (18, 0, '新增', '1', 'sys_oper_type', '', '', '', '2', '', '新增操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (19, 0, '修改', '2', 'sys_oper_type', '', '', '', '2', '', '修改操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (20, 0, '删除', '3', 'sys_oper_type', '', '', '', '2', '', '删除操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (21, 0, '授权', '4', 'sys_oper_type', '', '', '', '2', '', '授权操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (22, 0, '导出', '5', 'sys_oper_type', '', '', '', '2', '', '导出操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (23, 0, '导入', '6', 'sys_oper_type', '', '', '', '2', '', '导入操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (24, 0, '强退', '7', 'sys_oper_type', '', '', '', '2', '', '强退操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (25, 0, '生成代码', '8', 'sys_oper_type', '', '', '', '2', '', '生成操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (26, 0, '清空数据', '9', 'sys_oper_type', '', '', '', '2', '', '清空操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (27, 0, '成功', '0', 'sys_notice_status', '', '', '', '2', '', '成功状态', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (28, 0, '失败', '1', 'sys_notice_status', '', '', '', '2', '', '失败状态', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (29, 0, '登录', '10', 'sys_oper_type', '', '', '', '2', '', '登录操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (30, 0, '退出', '11', 'sys_oper_type', '', '', '', '2', '', '', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (31, 0, '获取验证码', '12', 'sys_oper_type', '', '', '', '2', '', '获取验证码', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (32, 0, '正常', '1', 'sys_content_status', '', '', '', '1', '', '', 1, 1, '2021-05-13 19:56:40.845', '2021-05-13 19:56:40.845', NULL); +INSERT INTO sys_dict_data VALUES (33, 1, '禁用', '2', 'sys_content_status', '', '', '', '1', '', '', 1, 1, '2021-05-13 19:56:40.845', '2021-05-13 19:56:40.845', NULL); + + +INSERT INTO sys_dict_type (dict_id, dict_name, dict_type, status, remark, create_by, update_by, created_at, updated_at, + deleted_at)VALUES (1, '系统开关', 'sys_normal_disable', '2', '系统开关列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (2, '用户性别', 'sys_user_sex', '2', '用户性别列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (3, '菜单状态', 'sys_show_hide', '2', '菜单状态列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (4, '系统是否', 'sys_yes_no', '2', '系统是否列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (5, '任务状态', 'sys_job_status', '2', '任务状态列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (6, '任务分组', 'sys_job_group', '2', '任务分组列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (7, '通知类型', 'sys_notice_type', '2', '通知类型列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (8, '系统状态', 'sys_common_status', '2', '登录状态列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (9, '操作类型', 'sys_oper_type', '2', '操作类型列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (10, '通知状态', 'sys_notice_status', '2', '通知状态列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (11, '内容状态', 'sys_content_status', '2', '', 1, 1, '2021-05-13 19:56:40.813', '2021-05-13 19:56:40.813', NULL); + + +INSERT INTO sys_job (job_id, job_name, job_group, job_type, cron_expression, invoke_target, args, misfire_policy, concurrent, status, entry_id, created_at, updated_at, deleted_at, create_by, update_by)VALUES +(1, '接口测试', 'DEFAULT', 1, '0/5 * * * * ', 'http://localhost:8000', '', 1, 1, 1, 0, '2021-05-13 19:56:37.914', '2021-06-14 20:59:55.417', NULL, 1, 1), +(2, '函数测试', 'DEFAULT', 2, '0/5 * * * * ', 'ExamplesOne', '参数', 1, 1, 1, 0, '2021-05-13 19:56:37.914', '2021-05-31 23:55:37.221', NULL, 1, 1); + +SET IDENTITY_INSERT sys_menu ON; +INSERT INTO sys_menu (menu_id, menu_name, title, icon, path, paths, menu_type, "action", permission, parent_id, no_cache, breadcrumb, component, sort, visible, is_frame, create_by, update_by, created_at, updated_at, deleted_at)VALUES +(2, 'Admin', '系统管理', 'api-server', '/admin', '/0/2', 'M', '无', '', 0, 1, '', 'Layout', 10, '0', '1', 0, 1, '2021-05-20 21:58:45.679', '2021-06-17 11:48:40.703', NULL), +(3, 'SysUserManage', '用户管理', 'user', '/admin/sys-user', '/0/2/3', 'C', '无', 'admin:sysUser:list', 2, 0, '', '/admin/sys-user/index', 10, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 20:31:14.305', NULL), +(43, '', '新增管理员', 'app-group-fill', '', '/0/2/3/43', 'F', 'POST', 'admin:sysUser:add', 3, 0, '', '', 10, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 20:31:14.305', NULL), +(44, '', '查询管理员', 'app-group-fill', '', '/0/2/3/44', 'F', 'GET', 'admin:sysUser:query', 3, 0, '', '', 40, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 20:31:14.305', NULL), +(45, '', '修改管理员', 'app-group-fill', '', '/0/2/3/45', 'F', 'PUT', 'admin:sysUser:edit', 3, 0, '', '', 30, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 20:31:14.305', NULL), +(46, '', '删除管理员', 'app-group-fill', '', '/0/2/3/46', 'F', 'DELETE', 'admin:sysUser:remove', 3, 0, '', '', 20, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 20:31:14.305', NULL), +(51, 'SysMenuManage', '菜单管理', 'tree-table', '/admin/sys-menu', '/0/2/51', 'C', '无', 'admin:sysMenu:list', 2, 1, '', '/admin/sys-menu/index', 30, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(52, 'SysRoleManage', '角色管理', 'peoples', '/admin/sys-role', '/0/2/52', 'C', '无', 'admin:sysRole:list', 2, 1, '', '/admin/sys-role/index', 20, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(56, 'SysDeptManage', '部门管理', 'tree', '/admin/sys-dept', '/0/2/56', 'C', '无', 'admin:sysDept:list', 2, 0, '', '/admin/sys-dept/index', 40, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(57, 'SysPostManage', '岗位管理', 'pass', '/admin/sys-post', '/0/2/57', 'C', '无', 'admin:sysPost:list', 2, 0, '', '/admin/sys-post/index', 50, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(58, 'Dict', '字典管理', 'education', '/admin/dict', '/0/2/58', 'C', '无', 'admin:sysDictType:list', 2, 0, '', '/admin/dict/index', 60, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(59, 'SysDictDataManage', '字典数据', 'education', '/admin/dict/data/:dictId', '/0/2/59', 'C', '无', 'admin:sysDictData:list', 2, 0, '', '/admin/dict/data', 100, '1', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(60, 'Tools', '开发工具', 'dev-tools', '/dev-tools', '/0/60', 'M', '无', '', 0, 0, '', 'Layout', 40, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-05 22:15:03.465', NULL), +(61, 'Swagger', '系统接口', 'guide', '/dev-tools/swagger', '/0/60/61', 'C', '无', '', 60, 0, '', '/dev-tools/swagger/index', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-05 22:15:03.465', NULL), +(62, 'SysConfigManage', '参数管理', 'swagger', '/admin/sys-config', '/0/2/62', 'C', '无', 'admin:sysConfig:list', 2, 0, '', '/admin/sys-config/index', 70, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(211, 'Log', '日志管理', 'log', '/log', '/0/2/211', 'M', '', '', 2, 0, '', '/log/index', 80, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(212, 'SysLoginLogManage', '登录日志', 'logininfor', '/admin/sys-login-log', '/0/2/211/212', 'C', '', 'admin:sysLoginLog:list', 211, 0, '', '/admin/sys-login-log/index', 1, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(216, 'OperLog', '操作日志', 'skill', '/admin/sys-oper-log', '/0/2/211/216', 'C', '', 'admin:sysOperLog:list', 211, 0, '', '/admin/sys-oper-log/index', 1, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(220, '', '新增菜单', 'app-group-fill', '', '/0/2/51/220', 'F', '', 'admin:sysMenu:add', 51, 0, '', '', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(221, '', '修改菜单', 'app-group-fill', '', '/0/2/51/221', 'F', '', 'admin:sysMenu:edit', 51, 0, '', '', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(222, '', '查询菜单', 'app-group-fill', '', '/0/2/51/222', 'F', '', 'admin:sysMenu:query', 51, 0, '', '', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(223, '', '删除菜单', 'app-group-fill', '', '/0/2/51/223', 'F', '', 'admin:sysMenu:remove', 51, 0, '', '', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(224, '', '新增角色', 'app-group-fill', '', '/0/2/52/224', 'F', '', 'admin:sysRole:add', 52, 0, '', '', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(225, '', '查询角色', 'app-group-fill', '', '/0/2/52/225', 'F', '', 'admin:sysRole:query', 52, 0, '', '', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(226, '', '修改角色', 'app-group-fill', '', '/0/2/52/226', 'F', '', 'admin:sysRole:update', 52, 0, '', '', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(227, '', '删除角色', 'app-group-fill', '', '/0/2/52/227', 'F', '', 'admin:sysRole:remove', 52, 0, '', '', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(228, '', '查询部门', 'app-group-fill', '', '/0/2/56/228', 'F', '', 'admin:sysDept:query', 56, 0, '', '', 40, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(229, '', '新增部门', 'app-group-fill', '', '/0/2/56/229', 'F', '', 'admin:sysDept:add', 56, 0, '', '', 10, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(230, '', '修改部门', 'app-group-fill', '', '/0/2/56/230', 'F', '', 'admin:sysDept:edit', 56, 0, '', '', 30, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(231, '', '删除部门', 'app-group-fill', '', '/0/2/56/231', 'F', '', 'admin:sysDept:remove', 56, 0, '', '', 20, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(232, '', '查询岗位', 'app-group-fill', '', '/0/2/57/232', 'F', '', 'admin:sysPost:query', 57, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(233, '', '新增岗位', 'app-group-fill', '', '/0/2/57/233', 'F', '', 'admin:sysPost:add', 57, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(234, '', '修改岗位', 'app-group-fill', '', '/0/2/57/234', 'F', '', 'admin:sysPost:edit', 57, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(235, '', '删除岗位', 'app-group-fill', '', '/0/2/57/235', 'F', '', 'admin:sysPost:remove', 57, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(236, '', '查询字典', 'app-group-fill', '', '/0/2/58/236', 'F', '', 'admin:sysDictType:query', 58, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(237, '', '新增类型', 'app-group-fill', '', '/0/2/58/237', 'F', '', 'admin:sysDictType:add', 58, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(238, '', '修改类型', 'app-group-fill', '', '/0/2/58/238', 'F', '', 'admin:sysDictType:edit', 58, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(239, '', '删除类型', 'app-group-fill', '', '/0/2/58/239', 'F', '', 'system:sysdicttype:remove', 58, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(240, '', '查询数据', 'app-group-fill', '', '/0/2/59/240', 'F', '', 'admin:sysDictData:query', 59, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(241, '', '新增数据', 'app-group-fill', '', '/0/2/59/241', 'F', '', 'admin:sysDictData:add', 59, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(242, '', '修改数据', 'app-group-fill', '', '/0/2/59/242', 'F', '', 'admin:sysDictData:edit', 59, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(243, '', '删除数据', 'app-group-fill', '', '/0/2/59/243', 'F', '', 'admin:sysDictData:remove', 59, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(244, '', '查询参数', 'app-group-fill', '', '/0/2/62/244', 'F', '', 'admin:sysConfig:query', 62, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(245, '', '新增参数', 'app-group-fill', '', '/0/2/62/245', 'F', '', 'admin:sysConfig:add', 62, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(246, '', '修改参数', 'app-group-fill', '', '/0/2/62/246', 'F', '', 'admin:sysConfig:edit', 62, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(247, '', '删除参数', 'app-group-fill', '', '/0/2/62/247', 'F', '', 'admin:sysConfig:remove', 62, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(248, '', '查询登录日志', 'app-group-fill', '', '/0/2/211/212/248', 'F', '', 'admin:sysLoginLog:query', 212, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(249, '', '删除登录日志', 'app-group-fill', '', '/0/2/211/212/249', 'F', '', 'admin:sysLoginLog:remove', 212, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(250, '', '查询操作日志', 'app-group-fill', '', '/0/2/211/216/250', 'F', '', 'admin:sysOperLog:query', 216, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(251, '', '删除操作日志', 'app-group-fill', '', '/0/2/211/216/251', 'F', '', 'admin:sysOperLog:remove', 216, 0, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL), +(261, 'Gen', '代码生成', 'code', '/dev-tools/gen', '/0/60/261', 'C', '', '', 60, 0, '', '/dev-tools/gen/index', 2, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-16 21:26:12.446', NULL), +(262, 'EditTable', '代码生成修改', 'build', '/dev-tools/editTable', '/0/60/262', 'C', '', '', 60, 0, '', '/dev-tools/gen/editTable', 100, '1', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-16 21:26:12.446', NULL), +(264, 'Build', '表单构建', 'build', '/dev-tools/build', '/0/60/264', 'C', '', '', 60, 0, '', '/dev-tools/build/index', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-16 21:26:12.446', NULL), +(269, 'ServerMonitor', '服务监控', 'druid', '/sys-tools/monitor', '/0/60/269', 'C', '', 'sysTools:serverMonitor:list', 537, 0, '', '/sys-tools/monitor', 0, '0', '1', 1, 1, '2020-04-14 00:28:19.000', '2021-06-16 21:26:12.446', NULL), +(459, 'Schedule', '定时任务', 'time-range', '/schedule', '/0/459', 'M', '无', '', 0, 0, '', 'Layout', 20, '0', '1', 1, 1, '2020-08-03 09:17:37.000', '2021-06-05 22:15:03.465', NULL), +(460, 'ScheduleManage', 'Schedule', 'job', '/schedule/manage', '/0/459/460', 'C', '无', 'job:sysJob:list', 459, 0, '', '/schedule/index', 0, '0', '1', 1, 1, '2020-08-03 09:17:37.000', '2021-06-05 22:15:03.465', NULL), +(461, 'sys_job', '分页获取定时任务', 'app-group-fill', '', '/0/459/460/461', 'F', '无', 'job:sysJob:query', 460, 0, '', '', 0, '0', '1', 1, 1, '2020-08-03 09:17:37.000', '2021-06-05 22:15:03.465', NULL), +(462, 'sys_job', '创建定时任务', 'app-group-fill', '', '/0/459/460/462', 'F', '无', 'job:sysJob:add', 460, 0, '', '', 0, '0', '1', 1, 1, '2020-08-03 09:17:37.000', '2021-06-05 22:15:03.465', NULL), +(463, 'sys_job', '修改定时任务', 'app-group-fill', '', '/0/459/460/463', 'F', '无', 'job:sysJob:edit', 460, 0, '', '', 0, '0', '1', 1, 1, '2020-08-03 09:17:37.000', '2021-06-05 22:15:03.465', NULL), +(464, 'sys_job', '删除定时任务', 'app-group-fill', '', '/0/459/460/464', 'F', '无', 'job:sysJob:remove', 460, 0, '', '', 0, '0', '1', 1, 1, '2020-08-03 09:17:37.000', '2021-06-05 22:15:03.465', NULL), +(471, 'JobLog', '日志', 'bug', '/schedule/log', '/0/459/471', 'C', '', '', 459, 0, '', '/schedule/log', 0, '1', '1', 1, 1, '2020-08-05 21:24:46.000', '2021-06-05 22:15:03.465', NULL), +(528, 'SysApiManage', '接口管理', 'api-doc', '/admin/sys-api', '/0/527/528', 'C', '无', 'admin:sysApi:list', 2, 0, '', '/admin/sys-api/index', 0, '0', '0', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(529, '', '查询接口', 'app-group-fill', '', '/0/527/528/529', 'F', '无', 'admin:sysApi:query', 528, 0, '', '', 40, '0', '0', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(531, '', '修改接口', 'app-group-fill', '', '/0/527/528/531', 'F', '无', 'admin:sysApi:edit', 528, 0, '', '', 30, '0', '0', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL), +(537, 'SysTools', '系统工具', 'system-tools', '/sys-tools', '', 'M', '', '', 0, 0, '', 'Layout', 30, '0', '1', 1, 1, '2021-05-21 11:13:32.166', '2021-06-16 21:26:12.446', NULL), +(540, 'SysConfigSet', '参数设置', 'system-tools', '/admin/sys-config/set', '', 'C', '', 'admin:sysConfigSet:list', 2, 0, '', '/admin/sys-config/set', 0, '0', '1', 1, 1, '2021-05-25 16:06:52.560', '2021-06-17 11:48:40.703', NULL), +(542, '', '修改', 'upload', '', '', 'F', '', 'admin:sysConfigSet:update', 540, 0, '', '', 0, '0', '1', 1, 1, '2021-06-13 11:45:48.670', '2021-06-17 11:48:40.703', NULL); +SET IDENTITY_INSERT sys_menu OFF; +INSERT INTO sys_menu_api_rule (sys_menu_menu_id, sys_api_id)VALUES (216, 6); +(250, 6), +(58, 21), +(236, 21), +(238, 23), +(59, 24), +(240, 24), +(242, 25), +(58, 26), +(236, 26), +(56, 27), +(228, 27), +(230, 28), +(226, 29), +(51, 39), +(51, 135), +(222, 39), +(221, 41), +(52, 44), +(225, 44), +(226, 45), +(226, 46), +(226, 47), +(62, 53), +(244, 53), +(246, 54), +(57, 59), +(232, 59), +(234, 60), +(241, 80), +(237, 81), +(229, 82), +(245, 87), +(220, 88), +(233, 89), +(224, 90), +(531, 92), +(242, 101), +(238, 102), +(230, 103), +(226, 106), +(226, 107), +(246, 108), +(221, 109), +(234, 110), +(249, 114), +(251, 115), +(243, 120), +(239, 121), +(231, 122), +(247, 125), +(223, 126), +(235, 127), +(227, 128), +(528, 135), +(529, 135), +(531, 136), +(212, 137), +(248, 137), +(542, 139), +(540, 140), +(3, 141), +(44, 141), +(45, 142), +(43, 150), +(45, 151), +(46, 156); +INSERT INTO sys_post (post_id, post_name, post_code, sort, status, remark, create_by, update_by, created_at, updated_at, deleted_at)VALUES +(1, '首席执行官', 'CEO', 0, '2','首席执行官', 1, 1, '2021-05-13 19:56:37.913', '2021-05-13 19:56:37.913', NULL), +(2, '首席技术执行官', 'CTO', 2, '2','首席技术执行官', 1, 1,'2021-05-13 19:56:37.913', '2021-05-13 19:56:37.913', NULL), +(3, '首席运营官', 'COO', 3, '2','测试工程师', 1, 1,'2021-05-13 19:56:37.913', '2021-05-13 19:56:37.913', NULL); +INSERT INTO sys_role (role_id, role_name, status, role_key, role_sort, flag, remark, admin, data_scope, create_by, update_by, created_at, updated_at, deleted_at)VALUES +(1, '系统管理员', '2', 'admin', 1, '', '', 1, '', 1, 1, '2021-05-13 19:56:37.913', '2021-05-13 19:56:37.913', NULL); +INSERT INTO sys_user VALUES (1, 'admin', '$2a$10$/Glr4g9Svr6O0kvjsRJCXu3f0W8/dsP3XZyVNi1019ratWpSPMyw.', 'zhangwj', '13818888888', 1, '', '', '1', '1@qq.com', 1, 1, '', '2', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:40.205', NULL); +-- 数据完成 ; \ No newline at end of file diff --git a/config/db.sql b/config/db.sql new file mode 100644 index 0000000..5c84adf --- /dev/null +++ b/config/db.sql @@ -0,0 +1,324 @@ +-- 开始初始化数据 ; +INSERT INTO sys_api VALUES (5, 'go-admin/app/admin/apis.SysLoginLog.Get-fm', '登录日志通过id获取', '/api/v1/sys-login-log/:id', 'BUS', 'GET', '2021-05-13 19:59:00.728', '2021-06-17 11:37:12.331', NULL, 0, 0); +INSERT INTO sys_api VALUES (6, 'go-admin/app/admin/apis.SysOperaLog.GetPage-fm', '操作日志列表', '/api/v1/sys-opera-log', 'BUS', 'GET', '2021-05-13 19:59:00.778', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (7, 'go-admin/app/admin/apis.SysOperaLog.Get-fm', '操作日志通过id获取', '/api/v1/sys-opera-log/:id', 'BUS', 'GET', '2021-05-13 19:59:00.821', '2021-06-16 21:49:48.598', NULL, 0, 0); +INSERT INTO sys_api VALUES (8, 'go-admin/common/actions.IndexAction.func1', '分类列表', '/api/v1/syscategory', 'BUS', 'GET', '2021-05-13 19:59:00.870', '2021-06-13 20:53:47.883', NULL, 0, 0); +INSERT INTO sys_api VALUES (9, 'go-admin/common/actions.ViewAction.func1', '分类通过id获取', '/api/v1/syscategory/:id', 'BUS', 'GET', '2021-05-13 19:59:00.945', '2021-06-13 20:53:47.926', NULL, 0, 0); +INSERT INTO sys_api VALUES (10, 'go-admin/common/actions.IndexAction.func1', '内容列表', '/api/v1/syscontent', 'BUS', 'GET', '2021-05-13 19:59:01.005', '2021-06-13 20:53:47.966', NULL, 0, 0); +INSERT INTO sys_api VALUES (11, 'go-admin/common/actions.ViewAction.func1', '内容通过id获取', '/api/v1/syscontent/:id', 'BUS', 'GET', '2021-05-13 19:59:01.056', '2021-06-13 20:53:48.005', NULL, 0, 0); +INSERT INTO sys_api VALUES (15, 'go-admin/common/actions.IndexAction.func1', 'job列表', '/api/v1/sysjob', 'BUS', 'GET', '2021-05-13 19:59:01.248', '2021-06-13 20:53:48.169', NULL, 0, 0); +INSERT INTO sys_api VALUES (16, 'go-admin/common/actions.ViewAction.func1', 'job通过id获取', '/api/v1/sysjob/:id', 'BUS', 'GET', '2021-05-13 19:59:01.298', '2021-06-13 20:53:48.214', NULL, 0, 0); +INSERT INTO sys_api VALUES (21, 'go-admin/app/admin/apis.SysDictType.GetPage-fm', '字典类型列表', '/api/v1/dict/type', 'BUS', 'GET', '2021-05-13 19:59:01.525', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (22, 'go-admin/app/admin/apis.SysDictType.GetAll-fm', '字典类型查询【代码生成】', '/api/v1/dict/type-option-select', 'SYS', 'GET', '2021-05-13 19:59:01.582', '2021-06-13 20:53:48.388', NULL, 0, 0); +INSERT INTO sys_api VALUES (23, 'go-admin/app/admin/apis.SysDictType.Get-fm', '字典类型通过id获取', '/api/v1/dict/type/:id', 'BUS', 'GET', '2021-05-13 19:59:01.632', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (24, 'go-admin/app/admin/apis.SysDictData.GetPage-fm', '字典数据列表', '/api/v1/dict/data', 'BUS', 'GET', '2021-05-13 19:59:01.684', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (25, 'go-admin/app/admin/apis.SysDictData.Get-fm', '字典数据通过code获取', '/api/v1/dict/data/:dictCode', 'BUS', 'GET', '2021-05-13 19:59:01.732', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (26, 'go-admin/app/admin/apis.SysDictData.GetSysDictDataAll-fm', '数据字典根据key获取', '/api/v1/dict-data/option-select', 'SYS', 'GET', '2021-05-13 19:59:01.832', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (27, 'go-admin/app/admin/apis.SysDept.GetPage-fm', '部门列表', '/api/v1/dept', 'BUS', 'GET', '2021-05-13 19:59:01.940', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (28, 'go-admin/app/admin/apis.SysDept.Get-fm', '部门通过id获取', '/api/v1/dept/:id', 'BUS', 'GET', '2021-05-13 19:59:02.009', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (29, 'go-admin/app/admin/apis.SysDept.Get2Tree-fm', '查询部门下拉树【角色权限-自定权限】', '/api/v1/deptTree', 'SYS', 'GET', '2021-05-13 19:59:02.050', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (30, 'go-admin/app/admin/apis/tools.(*Gen).GetDBTableList-fm', '数据库表列表', '/api/v1/db/tables/page', 'SYS', 'GET', '2021-05-13 19:59:02.098', '2021-06-13 20:53:48.730', NULL, 0, 0); +INSERT INTO sys_api VALUES (31, 'go-admin/app/admin/apis/tools.(*Gen).GetDBColumnList-fm', '数据表列列表', '/api/v1/db/columns/page', 'SYS', 'GET', '2021-05-13 19:59:02.140', '2021-06-13 20:53:48.771', NULL, 0, 0); +INSERT INTO sys_api VALUES (32, 'go-admin/app/admin/apis/tools.Gen.GenCode-fm', '数据库表生成到项目', '/api/v1/gen/toproject/:tableId', 'SYS', 'GET', '2021-05-13 19:59:02.183', '2021-06-13 20:53:48.812', NULL, 0, 0); +INSERT INTO sys_api VALUES (33, 'go-admin/app/admin/apis/tools.Gen.GenMenuAndApi-fm', '数据库表生成到DB', '/api/v1/gen/todb/:tableId', 'SYS', 'GET', '2021-05-13 19:59:02.227', '2021-06-13 20:53:48.853', NULL, 0, 0); +INSERT INTO sys_api VALUES (34, 'go-admin/app/admin/apis/tools.(*SysTable).GetSysTablesTree-fm', '关系表数据【代码生成】', '/api/v1/gen/tabletree', 'SYS', 'GET', '2021-05-13 19:59:02.271', '2021-06-13 20:53:48.893', NULL, 0, 0); +INSERT INTO sys_api VALUES (35, 'go-admin/app/admin/apis/tools.Gen.Preview-fm', '生成预览通过id获取', '/api/v1/gen/preview/:tableId', 'SYS', 'GET', '2021-05-13 19:59:02.315', '2021-06-13 20:53:48.935', NULL, 0, 0); +INSERT INTO sys_api VALUES (36, 'go-admin/app/admin/apis/tools.Gen.GenApiToFile-fm', '生成api带文件', '/api/v1/gen/apitofile/:tableId', 'SYS', 'GET', '2021-05-13 19:59:02.357', '2021-06-13 20:53:48.977', NULL, 0, 0); +INSERT INTO sys_api VALUES (37, 'go-admin/app/admin/apis.System.GenerateCaptchaHandler-fm', '验证码获取', '/api/v1/getCaptcha', 'SYS', 'GET', '2021-05-13 19:59:02.405', '2021-06-13 20:53:49.020', NULL, 0, 0); +INSERT INTO sys_api VALUES (38, 'go-admin/app/admin/apis.SysUser.GetInfo-fm', '用户信息获取', '/api/v1/getinfo', 'SYS', 'GET', '2021-05-13 19:59:02.447', '2021-06-13 20:53:49.065', NULL, 0, 0); +INSERT INTO sys_api VALUES (39, 'go-admin/app/admin/apis.SysMenu.GetPage-fm', '菜单列表', '/api/v1/menu', 'BUS', 'GET', '2021-05-13 19:59:02.497', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (40, 'go-admin/app/admin/apis.SysMenu.GetMenuTreeSelect-fm', '查询菜单下拉树结构【废弃】', '/api/v1/menuTreeselect', 'SYS', 'GET', '2021-05-13 19:59:02.542', '2021-06-03 22:37:21.857', NULL, 0, 0); +INSERT INTO sys_api VALUES (41, 'go-admin/app/admin/apis.SysMenu.Get-fm', '菜单通过id获取', '/api/v1/menu/:id', 'BUS', 'GET', '2021-05-13 19:59:02.584', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (42, 'go-admin/app/admin/apis.SysMenu.GetMenuRole-fm', '角色菜单【顶部左侧菜单】', '/api/v1/menurole', 'SYS', 'GET', '2021-05-13 19:59:02.630', '2021-06-13 20:53:49.574', NULL, 0, 0); +INSERT INTO sys_api VALUES (43, 'go-admin/app/admin/apis.SysMenu.GetMenuIDS-fm', '获取角色对应的菜单id数组【废弃】', '/api/v1/menuids', 'SYS', 'GET', '2021-05-13 19:59:02.675', '2021-06-03 22:39:52.500', NULL, 0, 0); +INSERT INTO sys_api VALUES (44, 'go-admin/app/admin/apis.SysRole.GetPage-fm', '角色列表', '/api/v1/role', 'BUS', 'GET', '2021-05-13 19:59:02.720', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (45, 'go-admin/app/admin/apis.SysMenu.GetMenuTreeSelect-fm', '菜单权限列表【角色配菜单使用】', '/api/v1/roleMenuTreeselect/:roleId', 'SYS', 'GET', '2021-05-13 19:59:02.762', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (46, 'go-admin/app/admin/apis.SysDept.GetDeptTreeRoleSelect-fm', '角色部门结构树【自定义数据权限】', '/api/v1/roleDeptTreeselect/:roleId', 'SYS', 'GET', '2021-05-13 19:59:02.809', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (47, 'go-admin/app/admin/apis.SysRole.Get-fm', '角色通过id获取', '/api/v1/role/:id', 'BUS', 'GET', '2021-05-13 19:59:02.850', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (48, 'github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth.(*GinJWTMiddleware).RefreshHandler-fm', '刷新token', '/api/v1/refresh_token', 'SYS', 'GET', '2021-05-13 19:59:02.892', '2021-06-13 20:53:49.278', NULL, 0, 0); +INSERT INTO sys_api VALUES (53, 'go-admin/app/admin/apis.SysConfig.GetPage-fm', '参数列表', '/api/v1/config', 'BUS', 'GET', '2021-05-13 19:59:03.116', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (54, 'go-admin/app/admin/apis.SysConfig.Get-fm', '参数通过id获取', '/api/v1/config/:id', 'BUS', 'GET', '2021-05-13 19:59:03.157', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (55, 'go-admin/app/admin/apis.SysConfig.GetSysConfigByKEYForService-fm', '参数通过键名搜索【基础默认配置】', '/api/v1/configKey/:configKey', 'SYS', 'GET', '2021-05-13 19:59:03.198', '2021-06-13 20:53:49.745', NULL, 0, 0); +INSERT INTO sys_api VALUES (57, 'go-admin/app/jobs/apis.SysJob.RemoveJobForService-fm', 'job移除', '/api/v1/job/remove/:id', 'BUS', 'GET', '2021-05-13 19:59:03.295', '2021-06-13 20:53:49.786', NULL, 0, 0); +INSERT INTO sys_api VALUES (58, 'go-admin/app/jobs/apis.SysJob.StartJobForService-fm', 'job启动', '/api/v1/job/start/:id', 'BUS', 'GET', '2021-05-13 19:59:03.339', '2021-06-13 20:53:49.829', NULL, 0, 0); +INSERT INTO sys_api VALUES (59, 'go-admin/app/admin/apis.SysPost.GetPage-fm', '岗位列表', '/api/v1/post', 'BUS', 'GET', '2021-05-13 19:59:03.381', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (60, 'go-admin/app/admin/apis.SysPost.Get-fm', '岗位通过id获取', '/api/v1/post/:id', 'BUS', 'GET', '2021-05-13 19:59:03.433', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (62, 'go-admin/app/admin/apis.SysConfig.GetSysConfigBySysApp-fm', '系统前端参数', '/api/v1/app-config', 'SYS', 'GET', '2021-05-13 19:59:03.526', '2021-06-13 20:53:49.994', NULL, 0, 0); +INSERT INTO sys_api VALUES (63, 'go-admin/app/admin/apis.SysUser.GetProfile-fm', '*用户信息获取', '/api/v1/user/profile', 'SYS', 'GET', '2021-05-13 19:59:03.567', '2021-06-13 20:53:50.038', NULL, 0, 0); +INSERT INTO sys_api VALUES (66, 'github.com/go-admin-team/go-admin-core/sdk/pkg/ws.(*Manager).WsClient-fm', '链接ws【定时任务log】', '/ws/:id/:channel', 'BUS', 'GET', '2021-05-13 19:59:03.705', '2021-06-13 20:53:50.167', NULL, 0, 0); +INSERT INTO sys_api VALUES (67, 'github.com/go-admin-team/go-admin-core/sdk/pkg/ws.(*Manager).UnWsClient-fm', '退出ws【定时任务log】', '/wslogout/:id/:channel', 'BUS', 'GET', '2021-05-13 19:59:03.756', '2021-06-13 20:53:50.209', NULL, 0, 0); +INSERT INTO sys_api VALUES (68, 'go-admin/common/middleware/handler.Ping', '*用户基本信息', '/info', 'SYS', 'GET', '2021-05-13 19:59:03.800', '2021-06-13 20:53:50.251', NULL, 0, 0); +INSERT INTO sys_api VALUES (72, 'go-admin/common/actions.CreateAction.func1', '分类创建', '/api/v1/syscategory', 'BUS', 'POST', '2021-05-13 19:59:03.982', '2021-06-13 20:53:50.336', NULL, 0, 0); +INSERT INTO sys_api VALUES (73, 'go-admin/common/actions.CreateAction.func1', '内容创建', '/api/v1/syscontent', 'BUS', 'POST', '2021-05-13 19:59:04.027', '2021-06-13 20:53:50.375', NULL, 0, 0); +INSERT INTO sys_api VALUES (76, 'go-admin/common/actions.CreateAction.func1', 'job创建', '/api/v1/sysjob', 'BUS', 'POST', '2021-05-13 19:59:04.164', '2021-06-13 20:53:50.500', NULL, 0, 0); +INSERT INTO sys_api VALUES (80, 'go-admin/app/admin/apis.SysDictData.Insert-fm', '字典数据创建', '/api/v1/dict/data', 'BUS', 'POST', '2021-05-13 19:59:04.347', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (81, 'go-admin/app/admin/apis.SysDictType.Insert-fm', '字典类型创建', '/api/v1/dict/type', 'BUS', 'POST', '2021-05-13 19:59:04.391', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (82, 'go-admin/app/admin/apis.SysDept.Insert-fm', '部门创建', '/api/v1/dept', 'BUS', 'POST', '2021-05-13 19:59:04.435', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (85, 'github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth.(*GinJWTMiddleware).LoginHandler-fm', '*登录', '/api/v1/login', 'SYS', 'POST', '2021-05-13 19:59:04.597', '2021-06-13 20:53:50.784', NULL, 0, 0); +INSERT INTO sys_api VALUES (86, 'go-admin/common/middleware/handler.LogOut', '*退出', '/api/v1/logout', 'SYS', 'POST', '2021-05-13 19:59:04.642', '2021-06-13 20:53:50.824', NULL, 0, 0); +INSERT INTO sys_api VALUES (87, 'go-admin/app/admin/apis.SysConfig.Insert-fm', '参数创建', '/api/v1/config', 'BUS', 'POST', '2021-05-13 19:59:04.685', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (88, 'go-admin/app/admin/apis.SysMenu.Insert-fm', '菜单创建', '/api/v1/menu', 'BUS', 'POST', '2021-05-13 19:59:04.777', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (89, 'go-admin/app/admin/apis.SysPost.Insert-fm', '岗位创建', '/api/v1/post', 'BUS', 'POST', '2021-05-13 19:59:04.886', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (90, 'go-admin/app/admin/apis.SysRole.Insert-fm', '角色创建', '/api/v1/role', 'BUS', 'POST', '2021-05-13 19:59:04.975', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (91, 'go-admin/app/admin/apis.SysUser.InsetAvatar-fm', '*用户头像编辑', '/api/v1/user/avatar', 'SYS', 'POST', '2021-05-13 19:59:05.058', '2021-06-13 20:53:51.079', NULL, 0, 0); +INSERT INTO sys_api VALUES (92, 'go-admin/app/admin/apis.SysApi.Update-fm', '接口编辑', '/api/v1/sys-api/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.122', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (95, 'go-admin/common/actions.UpdateAction.func1', '分类编辑', '/api/v1/syscategory/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.255', '2021-06-13 20:53:51.247', NULL, 0, 0); +INSERT INTO sys_api VALUES (96, 'go-admin/common/actions.UpdateAction.func1', '内容编辑', '/api/v1/syscontent/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.299', '2021-06-13 20:53:51.289', NULL, 0, 0); +INSERT INTO sys_api VALUES (97, 'go-admin/common/actions.UpdateAction.func1', 'job编辑', '/api/v1/sysjob', 'BUS', 'PUT', '2021-05-13 19:59:05.343', '2021-06-13 20:53:51.331', NULL, 0, 0); +INSERT INTO sys_api VALUES (101, 'go-admin/app/admin/apis.SysDictData.Update-fm', '字典数据编辑', '/api/v1/dict/data/:dictCode', 'BUS', 'PUT', '2021-05-13 19:59:05.519', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (102, 'go-admin/app/admin/apis.SysDictType.Update-fm', '字典类型编辑', '/api/v1/dict/type/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.569', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (103, 'go-admin/app/admin/apis.SysDept.Update-fm', '部门编辑', '/api/v1/dept/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.613', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (104, 'go-admin/app/other/apis.SysFileDir.Update-fm', '文件夹编辑', '/api/v1/file-dir/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.662', '2021-06-13 20:53:51.847', NULL, 0, 0); +INSERT INTO sys_api VALUES (105, 'go-admin/app/other/apis.SysFileInfo.Update-fm', '文件编辑', '/api/v1/file-info/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.709', '2021-06-13 20:53:51.892', NULL, 0, 0); +INSERT INTO sys_api VALUES (106, 'go-admin/app/admin/apis.SysRole.Update-fm', '角色编辑', '/api/v1/role/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.752', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (107, 'go-admin/app/admin/apis.SysRole.Update2DataScope-fm', '角色数据权限修改', '/api/v1/roledatascope', 'BUS', 'PUT', '2021-05-13 19:59:05.803', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (108, 'go-admin/app/admin/apis.SysConfig.Update-fm', '参数编辑', '/api/v1/config/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.848', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (109, 'go-admin/app/admin/apis.SysMenu.Update-fm', '编辑菜单', '/api/v1/menu/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.891', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (110, 'go-admin/app/admin/apis.SysPost.Update-fm', '岗位编辑', '/api/v1/post/:id', 'BUS', 'PUT', '2021-05-13 19:59:05.934', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (111, 'go-admin/app/admin/apis.SysUser.UpdatePwd-fm', '*用户修改密码', '/api/v1/user/pwd', 'SYS', 'PUT', '2021-05-13 19:59:05.987', '2021-06-13 20:53:51.724', NULL, 0, 0); +INSERT INTO sys_api VALUES (112, 'go-admin/common/actions.DeleteAction.func1', '分类删除', '/api/v1/syscategory', 'BUS', 'DELETE', '2021-05-13 19:59:06.030', '2021-06-13 20:53:52.237', NULL, 0, 0); +INSERT INTO sys_api VALUES (113, 'go-admin/common/actions.DeleteAction.func1', '内容删除', '/api/v1/syscontent', 'BUS', 'DELETE', '2021-05-13 19:59:06.076', '2021-06-13 20:53:52.278', NULL, 0, 0); +INSERT INTO sys_api VALUES (114, 'go-admin/app/admin/apis.SysLoginLog.Delete-fm', '登录日志删除', '/api/v1/sys-login-log', 'BUS', 'DELETE', '2021-05-13 19:59:06.118', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (115, 'go-admin/app/admin/apis.SysOperaLog.Delete-fm', '操作日志删除', '/api/v1/sys-opera-log', 'BUS', 'DELETE', '2021-05-13 19:59:06.162', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (116, 'go-admin/common/actions.DeleteAction.func1', 'job删除', '/api/v1/sysjob', 'BUS', 'DELETE', '2021-05-13 19:59:06.206', '2021-06-13 20:53:52.323', NULL, 0, 0); +INSERT INTO sys_api VALUES (117, 'go-admin/app/other/apis.SysChinaAreaData.Delete-fm', '行政区删除', '/api/v1/sys-area-data', 'BUS', 'DELETE', '2021-05-13 19:59:06.249', '2021-06-13 20:53:52.061', NULL, 0, 0); +INSERT INTO sys_api VALUES (120, 'go-admin/app/admin/apis.SysDictData.Delete-fm', '字典数据删除', '/api/v1/dict/data', 'BUS', 'DELETE', '2021-05-13 19:59:06.387', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (121, 'go-admin/app/admin/apis.SysDictType.Delete-fm', '字典类型删除', '/api/v1/dict/type', 'BUS', 'DELETE', '2021-05-13 19:59:06.432', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (122, 'go-admin/app/admin/apis.SysDept.Delete-fm', '部门删除', '/api/v1/dept/:id', 'BUS', 'DELETE', '2021-05-13 19:59:06.475', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (123, 'go-admin/app/other/apis.SysFileDir.Delete-fm', '文件夹删除', '/api/v1/file-dir/:id', 'BUS', 'DELETE', '2021-05-13 19:59:06.520', '2021-06-13 20:53:52.539', NULL, 0, 0); +INSERT INTO sys_api VALUES (124, 'go-admin/app/other/apis.SysFileInfo.Delete-fm', '文件删除', '/api/v1/file-info/:id', 'BUS', 'DELETE', '2021-05-13 19:59:06.566', '2021-06-13 20:53:52.580', NULL, 0, 0); +INSERT INTO sys_api VALUES (125, 'go-admin/app/admin/apis.SysConfig.Delete-fm', '参数删除', '/api/v1/config', 'BUS', 'DELETE', '2021-05-13 19:59:06.612', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (126, 'go-admin/app/admin/apis.SysMenu.Delete-fm', '删除菜单', '/api/v1/menu', 'BUS', 'DELETE', '2021-05-13 19:59:06.654', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (127, 'go-admin/app/admin/apis.SysPost.Delete-fm', '岗位删除', '/api/v1/post/:id', 'BUS', 'DELETE', '2021-05-13 19:59:06.702', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (128, 'go-admin/app/admin/apis.SysRole.Delete-fm', '角色删除', '/api/v1/role', 'BUS', 'DELETE', '2021-05-13 19:59:06.746', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (131, 'github.com/go-admin-team/go-admin-core/tools/transfer.Handler.func1', '系统指标', '/api/v1/metrics', 'SYS', 'GET', '2021-05-17 22:13:55.933', '2021-06-13 20:53:49.614', NULL, 0, 0); +INSERT INTO sys_api VALUES (132, 'go-admin/app/other/router.registerMonitorRouter.func1', '健康状态', '/api/v1/health', 'SYS', 'GET', '2021-05-17 22:13:56.285', '2021-06-13 20:53:49.951', NULL, 0, 0); +INSERT INTO sys_api VALUES (133, 'go-admin/app/admin/apis.HelloWorld', '项目默认接口', '/', 'SYS', 'GET', '2021-05-24 10:30:44.553', '2021-06-13 20:53:47.406', NULL, 0, 0); +INSERT INTO sys_api VALUES (134, 'go-admin/app/other/apis.ServerMonitor.ServerInfo-fm', '服务器基本状态', '/api/v1/server-monitor', 'SYS', 'GET', '2021-05-24 10:30:44.937', '2021-06-13 20:53:48.255', NULL, 0, 0); +INSERT INTO sys_api VALUES (135, 'go-admin/app/admin/apis.SysApi.GetPage-fm', '接口列表', '/api/v1/sys-api', 'BUS', 'GET', '2021-05-24 11:37:53.303', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (136, 'go-admin/app/admin/apis.SysApi.Get-fm', '接口通过id获取', '/api/v1/sys-api/:id', 'BUS', 'GET', '2021-05-24 11:37:53.359', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (137, 'go-admin/app/admin/apis.SysLoginLog.GetPage-fm', '登录日志列表', '/api/v1/sys-login-log', 'BUS', 'GET', '2021-05-24 11:47:30.397', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (138, 'go-admin/app/other/apis.File.UploadFile-fm', '文件上传', '/api/v1/public/uploadFile', 'SYS', 'POST', '2021-05-25 19:16:18.493', '2021-06-13 20:53:50.866', NULL, 0, 0); +INSERT INTO sys_api VALUES (139, 'go-admin/app/admin/apis.SysConfig.Update2Set-fm', '参数信息修改【参数配置】', '/api/v1/set-config', 'BUS', 'PUT', '2021-05-27 09:45:14.853', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (140, 'go-admin/app/admin/apis.SysConfig.Get2Set-fm', '参数获取全部【配置使用】', '/api/v1/set-config', 'BUS', 'GET', '2021-05-27 11:54:14.384', '2021-06-17 11:48:40.732', NULL, 0, 0); +INSERT INTO sys_api VALUES (141, 'go-admin/app/admin/apis.SysUser.GetPage-fm', '管理员列表', '/api/v1/sys-user', 'BUS', 'GET', '2021-06-13 19:24:57.111', '2021-06-17 20:31:14.318', NULL, 0, 0); +INSERT INTO sys_api VALUES (142, 'go-admin/app/admin/apis.SysUser.Get-fm', '管理员通过id获取', '/api/v1/sys-user/:id', 'BUS', 'GET', '2021-06-13 19:24:57.188', '2021-06-17 20:31:14.318', NULL, 0, 0); +INSERT INTO sys_api VALUES (143, 'go-admin/app/admin/apis/tools.(*SysTable).GetSysTablesInfo-fm', '', '/api/v1/sys/tables/info', '', 'GET', '2021-06-13 19:24:57.437', '2021-06-13 20:53:48.047', NULL, 0, 0); +INSERT INTO sys_api VALUES (144, 'go-admin/app/admin/apis/tools.(*SysTable).GetSysTables-fm', '', '/api/v1/sys/tables/info/:tableId', '', 'GET', '2021-06-13 19:24:57.510', '2021-06-13 20:53:48.088', NULL, 0, 0); +INSERT INTO sys_api VALUES (145, 'go-admin/app/admin/apis/tools.(*SysTable).GetSysTableList-fm', '', '/api/v1/sys/tables/page', '', 'GET', '2021-06-13 19:24:57.582', '2021-06-13 20:53:48.128', NULL, 0, 0); +INSERT INTO sys_api VALUES (146, 'github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1', '', '/static/*filepath', '', 'GET', '2021-06-13 19:24:59.641', '2021-06-13 20:53:50.081', NULL, 0, 0); +INSERT INTO sys_api VALUES (147, 'github.com/swaggo/gin-swagger.CustomWrapHandler.func1', '', '/swagger/*any', '', 'GET', '2021-06-13 19:24:59.713', '2021-06-13 20:53:50.123', NULL, 0, 0); +INSERT INTO sys_api VALUES (148, 'github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1', '', '/form-generator/*filepath', '', 'GET', '2021-06-13 19:24:59.914', '2021-06-13 20:53:50.295', NULL, 0, 0); +INSERT INTO sys_api VALUES (149, 'go-admin/app/admin/apis/tools.(*SysTable).InsertSysTable-fm', '', '/api/v1/sys/tables/info', '', 'POST', '2021-06-13 19:25:00.163', '2021-06-13 20:53:50.539', NULL, 0, 0); +INSERT INTO sys_api VALUES (150, 'go-admin/app/admin/apis.SysUser.Insert-fm', '管理员创建', '/api/v1/sys-user', 'BUS', 'POST', '2021-06-13 19:25:00.233', '2021-06-17 20:31:14.318', NULL, 0, 0); +INSERT INTO sys_api VALUES (151, 'go-admin/app/admin/apis.SysUser.Update-fm', '管理员编辑', '/api/v1/sys-user', 'BUS', 'PUT', '2021-06-13 19:25:00.986', '2021-06-17 20:31:14.318', NULL, 0, 0); +INSERT INTO sys_api VALUES (152, 'go-admin/app/admin/apis/tools.(*SysTable).UpdateSysTable-fm', '', '/api/v1/sys/tables/info', '', 'PUT', '2021-06-13 19:25:01.149', '2021-06-13 20:53:51.375', NULL, 0, 0); +INSERT INTO sys_api VALUES (153, 'go-admin/app/admin/apis.SysRole.Update2Status-fm', '', '/api/v1/role-status', '', 'PUT', '2021-06-13 19:25:01.446', '2021-06-13 20:53:51.636', NULL, 0, 0); +INSERT INTO sys_api VALUES (154, 'go-admin/app/admin/apis.SysUser.ResetPwd-fm', '', '/api/v1/user/pwd/reset', '', 'PUT', '2021-06-13 19:25:01.601', '2021-06-13 20:53:51.764', NULL, 0, 0); +INSERT INTO sys_api VALUES (155, 'go-admin/app/admin/apis.SysUser.UpdateStatus-fm', '', '/api/v1/user/status', '', 'PUT', '2021-06-13 19:25:01.671', '2021-06-13 20:53:51.806', NULL, 0, 0); +INSERT INTO sys_api VALUES (156, 'go-admin/app/admin/apis.SysUser.Delete-fm', '管理员删除', '/api/v1/sys-user', 'BUS', 'DELETE', '2021-06-13 19:25:02.043', '2021-06-17 20:31:14.318', NULL, 0, 0); +INSERT INTO sys_api VALUES (157, 'go-admin/app/admin/apis/tools.(*SysTable).DeleteSysTables-fm', '', '/api/v1/sys/tables/info/:tableId', '', 'DELETE', '2021-06-13 19:25:02.283', '2021-06-13 20:53:52.367', NULL, 0, 0); +INSERT INTO sys_api VALUES (158, 'github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1', '', '/static/*filepath', '', 'HEAD', '2021-06-13 19:25:02.734', '2021-06-13 20:53:52.791', NULL, 0, 0); +INSERT INTO sys_api VALUES (159, 'github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1', '', '/form-generator/*filepath', '', 'HEAD', '2021-06-13 19:25:02.808', '2021-06-13 20:53:52.838', NULL, 0, 0); + +INSERT INTO sys_config VALUES (1, '皮肤样式', 'sys_index_skinName', 'skin-green', 'Y', '0', '主框架页-默认皮肤样式名称:蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow', 1, 1, '2021-05-13 19:56:37.913', '2021-06-05 13:50:13.123', NULL); +INSERT INTO sys_config VALUES (2, '初始密码', 'sys_user_initPassword', '123456', 'Y', '0', '用户管理-账号初始密码:123456', 1, 1, '2021-05-13 19:56:37.913', '2021-05-13 19:56:37.913', NULL); +INSERT INTO sys_config VALUES (3, '侧栏主题', 'sys_index_sideTheme', 'theme-dark', 'Y', '0', '主框架页-侧边栏主题:深色主题theme-dark,浅色主题theme-light', 1, 1, '2021-05-13 19:56:37.913', '2021-05-13 19:56:37.913', NULL); +INSERT INTO sys_config VALUES (4, '系统名称', 'sys_app_name', 'go-admin管理系统', 'Y', '1', '', 1, 0, '2021-03-17 08:52:06.067', '2021-05-28 10:08:25.248', NULL); +INSERT INTO sys_config VALUES (5, '系统logo', 'sys_app_logo', 'https://doc-image.zhangwj.com/img/go-admin.png', 'Y', '1', '', 1, 0, '2021-03-17 08:53:19.462', '2021-03-17 08:53:19.462', NULL); + +INSERT INTO sys_dept VALUES (1, 0, '/0/1/', '爱拓科技', 0, 'aituo', '13782218188', 'atuo@aituo.com', '2', 1, 1, '2021-05-13 19:56:37.913', '2021-06-05 17:06:44.960', NULL); +INSERT INTO sys_dept VALUES (7, 1, '/0/1/7/', '研发部', 1, 'aituo', '13782218188', 'atuo@aituo.com', '2', 1, 1, '2021-05-13 19:56:37.913', '2021-06-16 21:35:00.109', NULL); +INSERT INTO sys_dept VALUES (8, 1, '/0/1/8/', '运维部', 0, 'aituo', '13782218188', 'atuo@aituo.com', '2', 1, 1, '2021-05-13 19:56:37.913', '2021-06-16 21:41:39.747', NULL); +INSERT INTO sys_dept VALUES (9, 1, '/0/1/9/', '客服部', 0, 'aituo', '13782218188', 'atuo@aituo.com', '2', 1, 1, '2021-05-13 19:56:37.913', '2021-06-05 17:07:05.993', NULL); +INSERT INTO sys_dept VALUES (10, 1, '/0/1/10/', '人力资源', 3, 'aituo', '13782218188', 'atuo@aituo.com', '1', 1, 1, '2021-05-13 19:56:37.913', '2021-06-05 17:07:08.503', NULL); + +INSERT INTO sys_dict_data VALUES (1, 0, '正常', '2', 'sys_normal_disable', '', '', '', '2', '', '系统正常', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:40.168', NULL); +INSERT INTO sys_dict_data VALUES (2, 0, '停用', '1', 'sys_normal_disable', '', '', '', '2', '', '系统停用', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (3, 0, '男', '0', 'sys_user_sex', '', '', '', '2', '', '性别男', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (4, 0, '女', '1', 'sys_user_sex', '', '', '', '2', '', '性别女', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (5, 0, '未知', '2', 'sys_user_sex', '', '', '', '2', '', '性别未知', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (6, 0, '显示', '0', 'sys_show_hide', '', '', '', '2', '', '显示菜单', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (7, 0, '隐藏', '1', 'sys_show_hide', '', '', '', '2', '', '隐藏菜单', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (8, 0, '是', 'Y', 'sys_yes_no', '', '', '', '2', '', '系统默认是', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (9, 0, '否', 'N', 'sys_yes_no', '', '', '', '2', '', '系统默认否', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (10, 0, '正常', '2', 'sys_job_status', '', '', '', '2', '', '正常状态', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (11, 0, '停用', '1', 'sys_job_status', '', '', '', '2', '', '停用状态', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (12, 0, '默认', 'DEFAULT', 'sys_job_group', '', '', '', '2', '', '默认分组', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (13, 0, '系统', 'SYSTEM', 'sys_job_group', '', '', '', '2', '', '系统分组', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (14, 0, '通知', '1', 'sys_notice_type', '', '', '', '2', '', '通知', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (15, 0, '公告', '2', 'sys_notice_type', '', '', '', '2', '', '公告', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (16, 0, '正常', '2', 'sys_common_status', '', '', '', '2', '', '正常状态', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (17, 0, '关闭', '1', 'sys_common_status', '', '', '', '2', '', '关闭状态', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (18, 0, '新增', '1', 'sys_oper_type', '', '', '', '2', '', '新增操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (19, 0, '修改', '2', 'sys_oper_type', '', '', '', '2', '', '修改操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (20, 0, '删除', '3', 'sys_oper_type', '', '', '', '2', '', '删除操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (21, 0, '授权', '4', 'sys_oper_type', '', '', '', '2', '', '授权操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (22, 0, '导出', '5', 'sys_oper_type', '', '', '', '2', '', '导出操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (23, 0, '导入', '6', 'sys_oper_type', '', '', '', '2', '', '导入操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (24, 0, '强退', '7', 'sys_oper_type', '', '', '', '2', '', '强退操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (25, 0, '生成代码', '8', 'sys_oper_type', '', '', '', '2', '', '生成操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (26, 0, '清空数据', '9', 'sys_oper_type', '', '', '', '2', '', '清空操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (27, 0, '成功', '0', 'sys_notice_status', '', '', '', '2', '', '成功状态', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (28, 0, '失败', '1', 'sys_notice_status', '', '', '', '2', '', '失败状态', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (29, 0, '登录', '10', 'sys_oper_type', '', '', '', '2', '', '登录操作', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (30, 0, '退出', '11', 'sys_oper_type', '', '', '', '2', '', '', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (31, 0, '获取验证码', '12', 'sys_oper_type', '', '', '', '2', '', '获取验证码', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_data VALUES (32, 0, '正常', '1', 'sys_content_status', '', '', '', '1', '', '', 1, 1, '2021-05-13 19:56:40.845', '2021-05-13 19:56:40.845', NULL); +INSERT INTO sys_dict_data VALUES (33, 1, '禁用', '2', 'sys_content_status', '', '', '', '1', '', '', 1, 1, '2021-05-13 19:56:40.845', '2021-05-13 19:56:40.845', NULL); + +INSERT INTO sys_dict_type VALUES (1, '系统开关', 'sys_normal_disable', '2', '系统开关列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (2, '用户性别', 'sys_user_sex', '2', '用户性别列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (3, '菜单状态', 'sys_show_hide', '2', '菜单状态列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (4, '系统是否', 'sys_yes_no', '2', '系统是否列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (5, '任务状态', 'sys_job_status', '2', '任务状态列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (6, '任务分组', 'sys_job_group', '2', '任务分组列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (7, '通知类型', 'sys_notice_type', '2', '通知类型列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (8, '系统状态', 'sys_common_status', '2', '登录状态列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (9, '操作类型', 'sys_oper_type', '2', '操作类型列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (10, '通知状态', 'sys_notice_status', '2', '通知状态列表', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:37.914', NULL); +INSERT INTO sys_dict_type VALUES (11, '内容状态', 'sys_content_status', '2', '', 1, 1, '2021-05-13 19:56:40.813', '2021-05-13 19:56:40.813', NULL); + +INSERT INTO sys_job VALUES (1, '接口测试', 'DEFAULT', 1, '0/5 * * * * ', 'http://localhost:8000', '', 1, 1, 1, 0, '2021-05-13 19:56:37.914', '2021-06-14 20:59:55.417', NULL, 1, 1); +INSERT INTO sys_job VALUES (2, '函数测试', 'DEFAULT', 2, '0/5 * * * * ', 'ExamplesOne', '参数', 1, 1, 1, 0, '2021-05-13 19:56:37.914', '2021-05-31 23:55:37.221', NULL, 1, 1); + +INSERT INTO sys_menu VALUES (2, 'Admin', '系统管理', 'api-server', '/admin', '/0/2', 'M', '无', '', 0, true, '', 'Layout', 10, '0', '1', 0, 1, '2021-05-20 21:58:45.679', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (3, 'SysUserManage', '用户管理', 'user', '/admin/sys-user', '/0/2/3', 'C', '无', 'admin:sysUser:list', 2, false, '', '/admin/sys-user/index', 10, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 20:31:14.305', NULL); +INSERT INTO sys_menu VALUES (43, '', '新增管理员', 'app-group-fill', '', '/0/2/3/43', 'F', 'POST', 'admin:sysUser:add', 3, false, '', '', 10, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 20:31:14.305', NULL); +INSERT INTO sys_menu VALUES (44, '', '查询管理员', 'app-group-fill', '', '/0/2/3/44', 'F', 'GET', 'admin:sysUser:query', 3, false, '', '', 40, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 20:31:14.305', NULL); +INSERT INTO sys_menu VALUES (45, '', '修改管理员', 'app-group-fill', '', '/0/2/3/45', 'F', 'PUT', 'admin:sysUser:edit', 3, false, '', '', 30, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 20:31:14.305', NULL); +INSERT INTO sys_menu VALUES (46, '', '删除管理员', 'app-group-fill', '', '/0/2/3/46', 'F', 'DELETE', 'admin:sysUser:remove', 3, false, '', '', 20, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 20:31:14.305', NULL); +INSERT INTO sys_menu VALUES (51, 'SysMenuManage', '菜单管理', 'tree-table', '/admin/sys-menu', '/0/2/51', 'C', '无', 'admin:sysMenu:list', 2, true, '', '/admin/sys-menu/index', 30, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (52, 'SysRoleManage', '角色管理', 'peoples', '/admin/sys-role', '/0/2/52', 'C', '无', 'admin:sysRole:list', 2, true, '', '/admin/sys-role/index', 20, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (56, 'SysDeptManage', '部门管理', 'tree', '/admin/sys-dept', '/0/2/56', 'C', '无', 'admin:sysDept:list', 2, false, '', '/admin/sys-dept/index', 40, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (57, 'SysPostManage', '岗位管理', 'pass', '/admin/sys-post', '/0/2/57', 'C', '无', 'admin:sysPost:list', 2, false, '', '/admin/sys-post/index', 50, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (58, 'Dict', '字典管理', 'education', '/admin/dict', '/0/2/58', 'C', '无', 'admin:sysDictType:list', 2, false, '', '/admin/dict/index', 60, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (59, 'SysDictDataManage', '字典数据', 'education', '/admin/dict/data/:dictId', '/0/2/59', 'C', '无', 'admin:sysDictData:list', 2, false, '', '/admin/dict/data', 100, '1', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (60, 'Tools', '开发工具', 'dev-tools', '/dev-tools', '/0/60', 'M', '无', '', 0, false, '', 'Layout', 40, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-05 22:15:03.465', NULL); +INSERT INTO sys_menu VALUES (61, 'Swagger', '系统接口', 'guide', '/dev-tools/swagger', '/0/60/61', 'C', '无', '', 60, false, '', '/dev-tools/swagger/index', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-05 22:15:03.465', NULL); +INSERT INTO sys_menu VALUES (62, 'SysConfigManage', '参数管理', 'swagger', '/admin/sys-config', '/0/2/62', 'C', '无', 'admin:sysConfig:list', 2, false, '', '/admin/sys-config/index', 70, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (211, 'Log', '日志管理', 'log', '/log', '/0/2/211', 'M', '', '', 2, false, '', '/log/index', 80, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (212, 'SysLoginLogManage', '登录日志', 'logininfor', '/admin/sys-login-log', '/0/2/211/212', 'C', '', 'admin:sysLoginLog:list', 211, false, '', '/admin/sys-login-log/index', 1, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (216, 'OperLog', '操作日志', 'skill', '/admin/sys-oper-log', '/0/2/211/216', 'C', '', 'admin:sysOperLog:list', 211, false, '', '/admin/sys-oper-log/index', 1, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (220, '', '新增菜单', 'app-group-fill', '', '/0/2/51/220', 'F', '', 'admin:sysMenu:add', 51, false, '', '', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (221, '', '修改菜单', 'app-group-fill', '', '/0/2/51/221', 'F', '', 'admin:sysMenu:edit', 51, false, '', '', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (222, '', '查询菜单', 'app-group-fill', '', '/0/2/51/222', 'F', '', 'admin:sysMenu:query', 51, false, '', '', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (223, '', '删除菜单', 'app-group-fill', '', '/0/2/51/223', 'F', '', 'admin:sysMenu:remove', 51, false, '', '', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (224, '', '新增角色', 'app-group-fill', '', '/0/2/52/224', 'F', '', 'admin:sysRole:add', 52, false, '', '', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (225, '', '查询角色', 'app-group-fill', '', '/0/2/52/225', 'F', '', 'admin:sysRole:query', 52, false, '', '', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (226, '', '修改角色', 'app-group-fill', '', '/0/2/52/226', 'F', '', 'admin:sysRole:update', 52, false, '', '', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (227, '', '删除角色', 'app-group-fill', '', '/0/2/52/227', 'F', '', 'admin:sysRole:remove', 52, false, '', '', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (228, '', '查询部门', 'app-group-fill', '', '/0/2/56/228', 'F', '', 'admin:sysDept:query', 56, false, '', '', 40, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (229, '', '新增部门', 'app-group-fill', '', '/0/2/56/229', 'F', '', 'admin:sysDept:add', 56, false, '', '', 10, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (230, '', '修改部门', 'app-group-fill', '', '/0/2/56/230', 'F', '', 'admin:sysDept:edit', 56, false, '', '', 30, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (231, '', '删除部门', 'app-group-fill', '', '/0/2/56/231', 'F', '', 'admin:sysDept:remove', 56, false, '', '', 20, '0', '1', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (232, '', '查询岗位', 'app-group-fill', '', '/0/2/57/232', 'F', '', 'admin:sysPost:query', 57, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (233, '', '新增岗位', 'app-group-fill', '', '/0/2/57/233', 'F', '', 'admin:sysPost:add', 57, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (234, '', '修改岗位', 'app-group-fill', '', '/0/2/57/234', 'F', '', 'admin:sysPost:edit', 57, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (235, '', '删除岗位', 'app-group-fill', '', '/0/2/57/235', 'F', '', 'admin:sysPost:remove', 57, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (236, '', '查询字典', 'app-group-fill', '', '/0/2/58/236', 'F', '', 'admin:sysDictType:query', 58, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (237, '', '新增类型', 'app-group-fill', '', '/0/2/58/237', 'F', '', 'admin:sysDictType:add', 58, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (238, '', '修改类型', 'app-group-fill', '', '/0/2/58/238', 'F', '', 'admin:sysDictType:edit', 58, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (239, '', '删除类型', 'app-group-fill', '', '/0/2/58/239', 'F', '', 'system:sysdicttype:remove', 58, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (240, '', '查询数据', 'app-group-fill', '', '/0/2/59/240', 'F', '', 'admin:sysDictData:query', 59, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (241, '', '新增数据', 'app-group-fill', '', '/0/2/59/241', 'F', '', 'admin:sysDictData:add', 59, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (242, '', '修改数据', 'app-group-fill', '', '/0/2/59/242', 'F', '', 'admin:sysDictData:edit', 59, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (243, '', '删除数据', 'app-group-fill', '', '/0/2/59/243', 'F', '', 'admin:sysDictData:remove', 59, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (244, '', '查询参数', 'app-group-fill', '', '/0/2/62/244', 'F', '', 'admin:sysConfig:query', 62, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (245, '', '新增参数', 'app-group-fill', '', '/0/2/62/245', 'F', '', 'admin:sysConfig:add', 62, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (246, '', '修改参数', 'app-group-fill', '', '/0/2/62/246', 'F', '', 'admin:sysConfig:edit', 62, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (247, '', '删除参数', 'app-group-fill', '', '/0/2/62/247', 'F', '', 'admin:sysConfig:remove', 62, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (248, '', '查询登录日志', 'app-group-fill', '', '/0/2/211/212/248', 'F', '', 'admin:sysLoginLog:query', 212, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (249, '', '删除登录日志', 'app-group-fill', '', '/0/2/211/212/249', 'F', '', 'admin:sysLoginLog:remove', 212, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (250, '', '查询操作日志', 'app-group-fill', '', '/0/2/211/216/250', 'F', '', 'admin:sysOperLog:query', 216, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (251, '', '删除操作日志', 'app-group-fill', '', '/0/2/211/216/251', 'F', '', 'admin:sysOperLog:remove', 216, false, '', '', 0, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (261, 'Gen', '代码生成', 'code', '/dev-tools/gen', '/0/60/261', 'C', '', '', 60, false, '', '/dev-tools/gen/index', 2, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-16 21:26:12.446', NULL); +INSERT INTO sys_menu VALUES (262, 'EditTable', '代码生成修改', 'build', '/dev-tools/editTable', '/0/60/262', 'C', '', '', 60, false, '', '/dev-tools/gen/editTable', 100, '1', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-16 21:26:12.446', NULL); +INSERT INTO sys_menu VALUES (264, 'Build', '表单构建', 'build', '/dev-tools/build', '/0/60/264', 'C', '', '', 60, false, '', '/dev-tools/build/index', 1, '0', '1', 1, 1, '2020-04-11 15:52:48.000', '2021-06-16 21:26:12.446', NULL); +INSERT INTO sys_menu VALUES (269, 'ServerMonitor', '服务监控', 'druid', '/sys-tools/monitor', '/0/60/269', 'C', '', 'sysTools:serverMonitor:list', 537, false, '', '/sys-tools/monitor', 0, '0', '1', 1, 1, '2020-04-14 00:28:19.000', '2021-06-16 21:26:12.446', NULL); +INSERT INTO sys_menu VALUES (459, 'Schedule', '定时任务', 'time-range', '/schedule', '/0/459', 'M', '无', '', 0, false, '', 'Layout', 20, '0', '1', 1, 1, '2020-08-03 09:17:37.000', '2021-06-05 22:15:03.465', NULL); +INSERT INTO sys_menu VALUES (460, 'ScheduleManage', 'Schedule', 'job', '/schedule/manage', '/0/459/460', 'C', '无', 'job:sysJob:list', 459, false, '', '/schedule/index', 0, '0', '1', 1, 1, '2020-08-03 09:17:37.000', '2021-06-05 22:15:03.465', NULL); +INSERT INTO sys_menu VALUES (461, 'sys_job', '分页获取定时任务', 'app-group-fill', '', '/0/459/460/461', 'F', '无', 'job:sysJob:query', 460, false, '', '', 0, '0', '1', 1, 1, '2020-08-03 09:17:37.000', '2021-06-05 22:15:03.465', NULL); +INSERT INTO sys_menu VALUES (462, 'sys_job', '创建定时任务', 'app-group-fill', '', '/0/459/460/462', 'F', '无', 'job:sysJob:add', 460, false, '', '', 0, '0', '1', 1, 1, '2020-08-03 09:17:37.000', '2021-06-05 22:15:03.465', NULL); +INSERT INTO sys_menu VALUES (463, 'sys_job', '修改定时任务', 'app-group-fill', '', '/0/459/460/463', 'F', '无', 'job:sysJob:edit', 460, false, '', '', 0, '0', '1', 1, 1, '2020-08-03 09:17:37.000', '2021-06-05 22:15:03.465', NULL); +INSERT INTO sys_menu VALUES (464, 'sys_job', '删除定时任务', 'app-group-fill', '', '/0/459/460/464', 'F', '无', 'job:sysJob:remove', 460, false, '', '', 0, '0', '1', 1, 1, '2020-08-03 09:17:37.000', '2021-06-05 22:15:03.465', NULL); +INSERT INTO sys_menu VALUES (471, 'JobLog', '日志', 'bug', '/schedule/log', '/0/459/471', 'C', '', '', 459, false, '', '/schedule/log', 0, '1', '1', 1, 1, '2020-08-05 21:24:46.000', '2021-06-05 22:15:03.465', NULL); +INSERT INTO sys_menu VALUES (528, 'SysApiManage', '接口管理', 'api-doc', '/admin/sys-api', '/0/527/528', 'C', '无', 'admin:sysApi:list', 2, false, '', '/admin/sys-api/index', 0, '0', '0', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (529, '', '查询接口', 'app-group-fill', '', '/0/527/528/529', 'F', '无', 'admin:sysApi:query', 528, false, '', '', 40, '0', '0', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (531, '', '修改接口', 'app-group-fill', '', '/0/527/528/531', 'F', '无', 'admin:sysApi:edit', 528, false, '', '', 30, '0', '0', 0, 1, '2021-05-20 22:08:44.526', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (537, 'SysTools', '系统工具', 'system-tools', '/sys-tools', '', 'M', '', '', 0, false, '', 'Layout', 30, '0', '1', 1, 1, '2021-05-21 11:13:32.166', '2021-06-16 21:26:12.446', NULL); +INSERT INTO sys_menu VALUES (540, 'SysConfigSet', '参数设置', 'system-tools', '/admin/sys-config/set', '', 'C', '', 'admin:sysConfigSet:list', 2, false, '', '/admin/sys-config/set', 0, '0', '1', 1, 1, '2021-05-25 16:06:52.560', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu VALUES (542, '', '修改', 'upload', '', '', 'F', '', 'admin:sysConfigSet:update', 540, false, '', '', 0, '0', '1', 1, 1, '2021-06-13 11:45:48.670', '2021-06-17 11:48:40.703', NULL); +INSERT INTO sys_menu_api_rule VALUES (216, 6); +INSERT INTO sys_menu_api_rule VALUES (250, 6); +INSERT INTO sys_menu_api_rule VALUES (58, 21); +INSERT INTO sys_menu_api_rule VALUES (236, 21); +INSERT INTO sys_menu_api_rule VALUES (238, 23); +INSERT INTO sys_menu_api_rule VALUES (59, 24); +INSERT INTO sys_menu_api_rule VALUES (240, 24); +INSERT INTO sys_menu_api_rule VALUES (242, 25); +INSERT INTO sys_menu_api_rule VALUES (58, 26); +INSERT INTO sys_menu_api_rule VALUES (236, 26); +INSERT INTO sys_menu_api_rule VALUES (56, 27); +INSERT INTO sys_menu_api_rule VALUES (228, 27); +INSERT INTO sys_menu_api_rule VALUES (230, 28); +INSERT INTO sys_menu_api_rule VALUES (226, 29); +INSERT INTO sys_menu_api_rule VALUES (51, 39); +INSERT INTO sys_menu_api_rule VALUES (51, 135); +INSERT INTO sys_menu_api_rule VALUES (222, 39); +INSERT INTO sys_menu_api_rule VALUES (221, 41); +INSERT INTO sys_menu_api_rule VALUES (52, 44); +INSERT INTO sys_menu_api_rule VALUES (225, 44); +INSERT INTO sys_menu_api_rule VALUES (226, 45); +INSERT INTO sys_menu_api_rule VALUES (226, 46); +INSERT INTO sys_menu_api_rule VALUES (226, 47); +INSERT INTO sys_menu_api_rule VALUES (62, 53); +INSERT INTO sys_menu_api_rule VALUES (244, 53); +INSERT INTO sys_menu_api_rule VALUES (246, 54); +INSERT INTO sys_menu_api_rule VALUES (57, 59); +INSERT INTO sys_menu_api_rule VALUES (232, 59); +INSERT INTO sys_menu_api_rule VALUES (234, 60); +INSERT INTO sys_menu_api_rule VALUES (241, 80); +INSERT INTO sys_menu_api_rule VALUES (237, 81); +INSERT INTO sys_menu_api_rule VALUES (229, 82); +INSERT INTO sys_menu_api_rule VALUES (245, 87); +INSERT INTO sys_menu_api_rule VALUES (220, 88); +INSERT INTO sys_menu_api_rule VALUES (233, 89); +INSERT INTO sys_menu_api_rule VALUES (224, 90); +INSERT INTO sys_menu_api_rule VALUES (531, 92); +INSERT INTO sys_menu_api_rule VALUES (242, 101); +INSERT INTO sys_menu_api_rule VALUES (238, 102); +INSERT INTO sys_menu_api_rule VALUES (230, 103); +INSERT INTO sys_menu_api_rule VALUES (226, 106); +INSERT INTO sys_menu_api_rule VALUES (226, 107); +INSERT INTO sys_menu_api_rule VALUES (246, 108); +INSERT INTO sys_menu_api_rule VALUES (221, 109); +INSERT INTO sys_menu_api_rule VALUES (234, 110); +INSERT INTO sys_menu_api_rule VALUES (249, 114); +INSERT INTO sys_menu_api_rule VALUES (251, 115); +INSERT INTO sys_menu_api_rule VALUES (243, 120); +INSERT INTO sys_menu_api_rule VALUES (239, 121); +INSERT INTO sys_menu_api_rule VALUES (231, 122); +INSERT INTO sys_menu_api_rule VALUES (247, 125); +INSERT INTO sys_menu_api_rule VALUES (223, 126); +INSERT INTO sys_menu_api_rule VALUES (235, 127); +INSERT INTO sys_menu_api_rule VALUES (227, 128); +INSERT INTO sys_menu_api_rule VALUES (528, 135); +INSERT INTO sys_menu_api_rule VALUES (529, 135); +INSERT INTO sys_menu_api_rule VALUES (531, 136); +INSERT INTO sys_menu_api_rule VALUES (212, 137); +INSERT INTO sys_menu_api_rule VALUES (248, 137); +INSERT INTO sys_menu_api_rule VALUES (542, 139); +INSERT INTO sys_menu_api_rule VALUES (540, 140); +INSERT INTO sys_menu_api_rule VALUES (3, 141); +INSERT INTO sys_menu_api_rule VALUES (44, 141); +INSERT INTO sys_menu_api_rule VALUES (45, 142); +INSERT INTO sys_menu_api_rule VALUES (43, 150); +INSERT INTO sys_menu_api_rule VALUES (45, 151); +INSERT INTO sys_menu_api_rule VALUES (46, 156); +INSERT INTO sys_post VALUES (1, '首席执行官', 'CEO', 0, '2','首席执行官', 1, 1, '2021-05-13 19:56:37.913', '2021-05-13 19:56:37.913', NULL); +INSERT INTO sys_post VALUES (2, '首席技术执行官', 'CTO', 2, '2','首席技术执行官', 1, 1,'2021-05-13 19:56:37.913', '2021-05-13 19:56:37.913', NULL); +INSERT INTO sys_post VALUES (3, '首席运营官', 'COO', 3, '2','测试工程师', 1, 1,'2021-05-13 19:56:37.913', '2021-05-13 19:56:37.913', NULL); +INSERT INTO sys_role VALUES (1, '系统管理员', '2', 'admin', 1, '', '', true, '', 1, 1, '2021-05-13 19:56:37.913', '2021-05-13 19:56:37.913', NULL); +INSERT INTO sys_user VALUES (1, 'admin', '$2a$10$/Glr4g9Svr6O0kvjsRJCXu3f0W8/dsP3XZyVNi1019ratWpSPMyw.', 'zhangwj', '13818888888', 1, '', '', '1', '1@qq.com', 1, 1, '', '2', 1, 1, '2021-05-13 19:56:37.914', '2021-05-13 19:56:40.205', NULL); +-- 数据完成 ; \ No newline at end of file diff --git a/config/extend.go b/config/extend.go new file mode 100644 index 0000000..bd06e03 --- /dev/null +++ b/config/extend.go @@ -0,0 +1,16 @@ +package config + +var ExtConfig Extend + +// Extend 扩展配置 +// extend: +// demo: +// name: demo-name +// 使用方法: config.ExtConfig......即可!! +type Extend struct { + AMap AMap // 这里配置对应配置文件的结构即可 +} + +type AMap struct { + Key string +} diff --git a/config/pg.sql b/config/pg.sql new file mode 100644 index 0000000..ba3c0c8 --- /dev/null +++ b/config/pg.sql @@ -0,0 +1,21 @@ +-- 开始初始化数据 ; +create sequence if not exists sys_role_role_id_seq; +create sequence if not exists sys_user_user_id_seq; +create sequence if not exists sys_post_post_id_seq; +create sequence if not exists sys_menu_menu_id_seq; +create sequence if not exists sys_dict_type_dict_id_seq; +create sequence if not exists sys_dict_data_dict_code_seq; +create sequence if not exists sys_dept_dept_id_seq; +create sequence if not exists sys_config_config_id_seq; +create sequence if not exists sys_job_id_seq; + +select setval('sys_role_role_id_seq',4); +select setval('sys_user_user_id_seq',5); +select setval('sys_post_post_id_seq',4); +select setval('sys_menu_menu_id_seq',543); +select setval('sys_dict_type_dict_id_seq',12); +select setval('sys_dict_data_dict_code_seq',34); +select setval('sys_dept_dept_id_seq',11); +select setval('sys_config_config_id_seq',6); +select setval('sys_job_id_seq',3); +-- 数据完成 ; diff --git a/config/settings.demo.yml b/config/settings.demo.yml new file mode 100644 index 0000000..9b297e6 --- /dev/null +++ b/config/settings.demo.yml @@ -0,0 +1,34 @@ +settings: + application: + demomsg: "谢谢您的参与,但为了大家更好的体验,所以本次提交就算了吧!\U0001F600\U0001F600\U0001F600" + enabledp: true + host: 0.0.0.0 + mode: demo + name: testApp + port: 8000 + readtimeout: 10000 + writertimeout: 20000 + database: + driver: sqlite3 + source: ./go-admin-db.db + gen: + dbname: testhhh + frontpath: ../go-admin-ui/src + jwt: + secret: go-admin + timeout: 3600 + logger: + # 日志存放路径 + path: temp/logs + # 日志输出,file:文件,default:命令行,其他:命令行 + stdout: '' #控制台日志,启用后,不输出到文件 + # 日志等级, trace, debug, info, warn, error, fatal + level: trace + # 数据库日志开关 + enableddb: true + queue: + memory: + poolSize: 100 + extend: + amap: + key: de7a062c984bf828d5d1b3a631a517e4 \ No newline at end of file diff --git a/config/settings.full.yml b/config/settings.full.yml new file mode 100644 index 0000000..bcca7e2 --- /dev/null +++ b/config/settings.full.yml @@ -0,0 +1,58 @@ +settings: + application: + # dev开发环境 test测试环境 prod线上环境 + mode: dev + # 服务器ip,默认使用 0.0.0.0 + host: 0.0.0.0 + # 服务名称 + name: testApp + # 端口号 + port: 8000 # 服务端口号 + readtimeout: 1 + writertimeout: 2 + # 数据权限功能开关 + enabledp: false + ssl: + # https对应的域名 + domain: localhost:8000 + # https开关 + enable: false + # ssl 证书key + key: keystring + # ssl 证书路径 + pem: temp/pem.pem + logger: + # 日志存放路径 + path: temp/logs + # 日志输出,file:文件,default:命令行,其他:命令行 + stdout: '' #控制台日志,启用后,不输出到文件 + # 日志等级, trace, debug, info, warn, error, fatal + level: trace + # 数据库日志开关 + enableddb: false + jwt: + # token 密钥,生产环境时及的修改 + secret: go-admin + # token 过期时间 单位:秒 + timeout: 3600 + database: + # 数据库类型 mysql,sqlite3, postgres + driver: mysql + # 数据库连接字符串 mysql 缺省信息 charset=utf8&parseTime=True&loc=Local&timeout=1000ms + source: user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8&parseTime=True&loc=Local&timeout=1000ms + # source: sqlite3.db + # source: host=myhost port=myport user=gorm dbname=gorm password=mypassword + registers: + - sources: + - user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8&parseTime=True&loc=Local&timeout=1000ms + gen: + # 代码生成读取的数据库名称 + dbname: dbname + # 代码生成是使用前端代码存放位置,需要指定到src文件夹,相对路径 + frontpath: ../go-admin-ui/src + queue: + memory: + poolSize: 100 + extend: # 扩展项使用说明 + demo: + name: data diff --git a/config/settings.sqlite.yml b/config/settings.sqlite.yml new file mode 100644 index 0000000..90e98e2 --- /dev/null +++ b/config/settings.sqlite.yml @@ -0,0 +1,38 @@ +settings: + application: + # dev开发环境 test测试环境 prod线上环境 + mode: dev + # 服务器ip,默认使用 0.0.0.0 + host: 0.0.0.0 + # 服务名称 + name: testApp + # 端口号 + port: 8000 # 服务端口号 + readtimeout: 3000 + writertimeout: 2000 + # 数据权限功能开关 + enabledp: false + logger: + # 日志存放路径 + path: temp/logs + # 日志输出,file:文件,default:命令行,其他:命令行 + stdout: '' #控制台日志,启用后,不输出到文件 + # 日志等级, trace, debug, info, warn, error, fatal + level: trace + # 数据库日志开关 + enableddb: false + jwt: + # token 密钥,生产环境时及的修改 + secret: go-admin + # token 过期时间 单位:秒 + timeout: 3600 + database: + # 数据库类型 mysql,sqlite3, postgres + driver: sqlite3 + # 数据库连接sqlite3数据文件的路径 + source: go-admin-db.db + gen: + # 代码生成读取的数据库名称 + dbname: dbname + # 代码生成是使用前端代码存放位置,需要指定到src文件夹,相对路径 + frontpath: ../go-admin-ui/src diff --git a/config/settings.yml b/config/settings.yml new file mode 100644 index 0000000..8e7ed87 --- /dev/null +++ b/config/settings.yml @@ -0,0 +1,74 @@ +settings: + application: + # dev开发环境 test测试环境 prod线上环境 + mode: dev + # 服务器ip,默认使用 0.0.0.0 + host: 0.0.0.0 + # 服务名称 + name: testApp + # 端口号 + port: 8000 # 服务端口号 + readtimeout: 1 + writertimeout: 2 + # 数据权限功能开关 + enabledp: false + logger: + # 日志存放路径 + path: temp/logs + # 日志输出,file:文件,default:命令行,其他:命令行 + stdout: '' #控制台日志,启用后,不输出到文件 + # 日志等级, trace, debug, info, warn, error, fatal + level: trace + # 数据库日志开关 + enableddb: false + jwt: + # token 密钥,生产环境时及的修改 + secret: go-admin + # token 过期时间 单位:秒 + timeout: 3600 + database: + # 数据库类型 mysql, sqlite3, postgres, sqlserver + # sqlserver: sqlserver://用户名:密码@地址?database=数据库名 + driver: mysql + # 数据库连接字符串 mysql 缺省信息 charset=utf8&parseTime=True&loc=Local&timeout=1000ms + source: user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8&parseTime=True&loc=Local&timeout=1000ms +# databases: +# 'locaohost:8000': +# driver: mysql +# # 数据库连接字符串 mysql 缺省信息 charset=utf8&parseTime=True&loc=Local&timeout=1000ms +# source: user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8&parseTime=True&loc=Local&timeout=1000ms +# registers: +# - sources: +# - user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8&parseTime=True&loc=Local&timeout=1000ms + gen: + # 代码生成读取的数据库名称 + dbname: dbname + # 代码生成是使用前端代码存放位置,需要指定到src文件夹,相对路径 + frontpath: ../go-admin-ui/src + extend: # 扩展项使用说明 + demo: + name: data + cache: +# redis: +# addr: 127.0.0.1:6379 +# password: xxxxxx +# db: 2 + # key存在即可 + memory: '' + queue: + memory: + poolSize: 100 +# redis: +# addr: 127.0.0.1:6379 +# password: xxxxxx +# producer: +# streamMaxLength: 100 +# approximateMaxLength: true +# consumer: +# visibilityTimeout: 60 +# bufferSize: 100 +# concurrency: 10 +# blockingTimeout: 5 +# reclaimInterval: 1 + locker: + redis: \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..41d94de --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,19 @@ +version: '3.8' +services: + go-admin-api: + container_name: go-admin + image: go-admin:latest + privileged: true + restart: always + ports: + - 8000:8000 + volumes: + - ./config/:/go-admin-api/config/ + - ./static/:/go-admin-api/static/ + - ./temp/:/go-admin-api/temp/ + networks: + - myweb +networks: + myweb: + driver: bridge + diff --git a/docs/admin/admin_docs.go b/docs/admin/admin_docs.go new file mode 100644 index 0000000..31c596a --- /dev/null +++ b/docs/admin/admin_docs.go @@ -0,0 +1,4373 @@ +// Package admin GENERATED BY SWAG; DO NOT EDIT +// This file was generated by swaggo/swag +package admin + +import "github.com/swaggo/swag" + +const docTemplateadmin = `{ + "schemes": {{ marshal .Schemes }}, + "swagger": "2.0", + "info": { + "description": "{{escape .Description}}", + "title": "{{.Title}}", + "contact": {}, + "license": { + "name": "MIT", + "url": "https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md" + }, + "version": "{{.Version}}" + }, + "host": "{{.Host}}", + "basePath": "{{.BasePath}}", + "paths": { + "/api/v1/app-config": { + "get": { + "description": "获取系统配置信息,主要注意这里不在验证权限", + "tags": [ + "配置管理" + ], + "summary": "获取系统前台配置信息,主要注意这里不在验证权限", + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + ] + } + } + } + } + }, + "/api/v1/captcha": { + "get": { + "description": "获取验证码", + "tags": [ + "登陆" + ], + "summary": "获取验证码", + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "string" + }, + "id": { + "type": "string" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/api/v1/db/columns/page": { + "get": { + "description": "数据库表列分页列表 / database table column page list", + "tags": [ + "工具 / 生成工具" + ], + "summary": "分页列表数据 / page list data", + "parameters": [ + { + "type": "string", + "description": "tableName / 数据表名称", + "name": "tableName", + "in": "query" + }, + { + "type": "integer", + "description": "pageSize / 页条数", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "pageIndex / 页码", + "name": "pageIndex", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/db/tables/page": { + "get": { + "description": "数据库表分页列表 / database table page list", + "tags": [ + "工具 / 生成工具" + ], + "summary": "分页列表数据 / page list data", + "parameters": [ + { + "type": "string", + "description": "tableName / 数据表名称", + "name": "tableName", + "in": "query" + }, + { + "type": "integer", + "description": "pageSize / 页条数", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "pageIndex / 页码", + "name": "pageIndex", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/dept": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "分页列表", + "tags": [ + "部门" + ], + "summary": "分页部门列表数据", + "parameters": [ + { + "type": "string", + "description": "deptName", + "name": "deptName", + "in": "query" + }, + { + "type": "string", + "description": "deptId", + "name": "deptId", + "in": "query" + }, + { + "type": "string", + "description": "position", + "name": "position", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "部门" + ], + "summary": "添加部门", + "parameters": [ + { + "description": "data", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDeptInsertReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": -1, \"message\": \"添加失败\"}", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除数据", + "tags": [ + "部门" + ], + "summary": "删除部门", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDeptDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": -1, \"message\": \"删除失败\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/dept/{deptId}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "部门" + ], + "summary": "获取部门数据", + "parameters": [ + { + "type": "string", + "description": "deptId", + "name": "deptId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "部门" + ], + "summary": "修改部门", + "parameters": [ + { + "type": "integer", + "description": "id", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDeptUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": -1, \"message\": \"添加失败\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/dict-data/option-select": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "数据字典根据key获取", + "tags": [ + "字典数据" + ], + "summary": "数据字典根据key获取", + "parameters": [ + { + "type": "integer", + "description": "dictType", + "name": "dictType", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.SysDictDataGetAllResp" + } + } + } + } + ] + } + } + } + } + }, + "/api/v1/dict/data": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "字典数据" + ], + "summary": "字典数据列表", + "parameters": [ + { + "type": "string", + "description": "status", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "dictCode", + "name": "dictCode", + "in": "query" + }, + { + "type": "string", + "description": "dictType", + "name": "dictType", + "in": "query" + }, + { + "type": "integer", + "description": "页条数", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "pageIndex", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "字典数据" + ], + "summary": "添加字典数据", + "parameters": [ + { + "description": "data", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDictDataInsertReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"添加成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除数据", + "tags": [ + "字典数据" + ], + "summary": "删除字典数据", + "parameters": [ + { + "description": "body", + "name": "dictCode", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDictDataDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"删除成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/dict/data/{dictCode}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "字典数据" + ], + "summary": "通过编码获取字典数据", + "parameters": [ + { + "type": "integer", + "description": "字典编码", + "name": "dictCode", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "字典数据" + ], + "summary": "修改字典数据", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDictDataUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"修改成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/dict/type": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "字典类型" + ], + "summary": "字典类型列表数据", + "parameters": [ + { + "type": "string", + "description": "dictName", + "name": "dictName", + "in": "query" + }, + { + "type": "string", + "description": "dictId", + "name": "dictId", + "in": "query" + }, + { + "type": "string", + "description": "dictType", + "name": "dictType", + "in": "query" + }, + { + "type": "integer", + "description": "页条数", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "pageIndex", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "字典类型" + ], + "summary": "添加字典类型", + "parameters": [ + { + "description": "data", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDictTypeInsertReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除数据", + "tags": [ + "字典类型" + ], + "summary": "删除字典类型", + "parameters": [ + { + "description": "body", + "name": "dictCode", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDictTypeDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/dict/type-option-select": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "字典类型" + ], + "summary": "字典类型全部数据 代码生成使用接口", + "parameters": [ + { + "type": "string", + "description": "dictName", + "name": "dictName", + "in": "query" + }, + { + "type": "string", + "description": "dictId", + "name": "dictId", + "in": "query" + }, + { + "type": "string", + "description": "dictType", + "name": "dictType", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/dict/type/{dictId}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "字典类型" + ], + "summary": "字典类型通过字典id获取", + "parameters": [ + { + "type": "integer", + "description": "字典类型编码", + "name": "dictId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "字典类型" + ], + "summary": "修改字典类型", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDictTypeUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/getinfo": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "个人中心" + ], + "summary": "获取个人信息", + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/login": { + "post": { + "description": "获取token\nLoginHandler can be used by clients to get a jwt token.\nPayload needs to be json in the form of {\"username\": \"USERNAME\", \"password\": \"PASSWORD\"}.\nReply will be of the form {\"token\": \"TOKEN\"}.\ndev mode:It should be noted that all fields cannot be empty, and a value of 0 can be passed in addition to the account password\n注意:开发模式:需要注意全部字段不能为空,账号密码外可以传入0值", + "consumes": [ + "application/json" + ], + "tags": [ + "登陆" + ], + "summary": "登陆", + "parameters": [ + { + "description": "account", + "name": "account", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/handler.Login" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"expire\": \"2019-08-07T12:45:48+08:00\", \"token\": \".eyJleHAiOjE1NjUxNTMxNDgsImlkIjoiYWRtaW4iLCJvcmlnX2lhdCI6MTU2NTE0OTU0OH0.-zvzHvbg0A\" }", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/menu": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "菜单" + ], + "summary": "Menu列表数据", + "parameters": [ + { + "type": "string", + "description": "menuName", + "name": "menuName", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "菜单" + ], + "summary": "创建菜单", + "parameters": [ + { + "description": "data", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysMenuInsertReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除数据", + "tags": [ + "菜单" + ], + "summary": "删除菜单", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysMenuDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/menu/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "菜单" + ], + "summary": "Menu详情数据", + "parameters": [ + { + "type": "string", + "description": "id", + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "菜单" + ], + "summary": "修改菜单", + "parameters": [ + { + "type": "integer", + "description": "id", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysMenuUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/menuTreeselect/{roleId}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "菜单" + ], + "summary": "角色修改使用的菜单列表", + "parameters": [ + { + "type": "integer", + "description": "roleId", + "name": "roleId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/menurole": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "菜单" + ], + "summary": "根据登录角色名称获取菜单列表数据(左菜单使用)", + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/post": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "岗位" + ], + "summary": "岗位列表数据", + "parameters": [ + { + "type": "string", + "description": "postName", + "name": "postName", + "in": "query" + }, + { + "type": "string", + "description": "postCode", + "name": "postCode", + "in": "query" + }, + { + "type": "string", + "description": "postId", + "name": "postId", + "in": "query" + }, + { + "type": "string", + "description": "status", + "name": "status", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "岗位" + ], + "summary": "添加岗位", + "parameters": [ + { + "description": "data", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysPostInsertReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除数据", + "tags": [ + "岗位" + ], + "summary": "删除岗位", + "parameters": [ + { + "description": "请求参数", + "name": "id", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysPostDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/post/{id}": { + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "岗位" + ], + "summary": "修改岗位", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysPostUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/post/{postId}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "岗位" + ], + "summary": "获取岗位信息", + "parameters": [ + { + "type": "integer", + "description": "编码", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/public/uploadFile": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "multipart/form-data" + ], + "tags": [ + "公共接口" + ], + "summary": "上传图片", + "parameters": [ + { + "type": "string", + "description": "type", + "name": "type", + "in": "query", + "required": true + }, + { + "type": "file", + "description": "file", + "name": "file", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": -1, \"message\": \"添加失败\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/role": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Get JSON", + "tags": [ + "角色/Role" + ], + "summary": "角色列表数据", + "parameters": [ + { + "type": "string", + "description": "roleName", + "name": "roleName", + "in": "query" + }, + { + "type": "string", + "description": "status", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "roleKey", + "name": "roleKey", + "in": "query" + }, + { + "type": "integer", + "description": "页条数", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "pageIndex", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "角色/Role" + ], + "summary": "创建角色", + "parameters": [ + { + "description": "data", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysRoleInsertReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除数据", + "tags": [ + "角色/Role" + ], + "summary": "删除用户角色", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysRoleDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/role-status/{id}": { + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "角色/Role" + ], + "summary": "更新角色数据权限", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.RoleDataScopeReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/role/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "角色/Role" + ], + "summary": "获取Role数据", + "parameters": [ + { + "type": "string", + "description": "roleId", + "name": "roleId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "角色/Role" + ], + "summary": "修改用户角色", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysRoleUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/server-monitor": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "系统信息" + ], + "summary": "系统信息", + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/set-config": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "界面操作设置配置值的获取", + "consumes": [ + "application/json" + ], + "tags": [ + "配置管理" + ], + "summary": "获取配置", + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"修改成功\"}", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": true + } + } + } + ] + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "界面操作设置配置值", + "consumes": [ + "application/json" + ], + "tags": [ + "配置管理" + ], + "summary": "设置配置", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.GetSetSysConfigReq" + } + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"修改成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-api": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取接口管理列表", + "tags": [ + "接口管理" + ], + "summary": "获取接口管理列表", + "parameters": [ + { + "type": "string", + "description": "名称", + "name": "name", + "in": "query" + }, + { + "type": "string", + "description": "标题", + "name": "title", + "in": "query" + }, + { + "type": "string", + "description": "地址", + "name": "path", + "in": "query" + }, + { + "type": "string", + "description": "类型", + "name": "action", + "in": "query" + }, + { + "type": "integer", + "description": "页条数", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "pageIndex", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/definitions/response.Page" + }, + { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysApi" + } + } + } + } + ] + } + } + } + ] + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除接口管理", + "tags": [ + "接口管理" + ], + "summary": "删除接口管理", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysApiDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"删除成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-api/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取接口管理", + "tags": [ + "接口管理" + ], + "summary": "获取接口管理", + "parameters": [ + { + "type": "string", + "description": "id", + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/models.SysApi" + } + } + } + ] + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "修改接口管理", + "consumes": [ + "application/json" + ], + "tags": [ + "接口管理" + ], + "summary": "修改接口管理", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysApiUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"修改成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-config": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取配置管理列表", + "tags": [ + "配置管理" + ], + "summary": "获取配置管理列表", + "parameters": [ + { + "type": "string", + "description": "名称", + "name": "configName", + "in": "query" + }, + { + "type": "string", + "description": "key", + "name": "configKey", + "in": "query" + }, + { + "type": "string", + "description": "类型", + "name": "configType", + "in": "query" + }, + { + "type": "integer", + "description": "是否前端", + "name": "isFrontend", + "in": "query" + }, + { + "type": "integer", + "description": "页条数", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "pageIndex", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/definitions/response.Page" + }, + { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysApi" + } + } + } + } + ] + } + } + } + ] + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "创建配置管理", + "consumes": [ + "application/json" + ], + "tags": [ + "配置管理" + ], + "summary": "创建配置管理", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysConfigControl" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"创建成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除配置管理", + "tags": [ + "配置管理" + ], + "summary": "删除配置管理", + "parameters": [ + { + "description": "ids", + "name": "ids", + "in": "body", + "schema": { + "type": "array", + "items": { + "type": "integer" + } + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"删除成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-config/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "根据Key获取SysConfig的Service", + "tags": [ + "配置管理" + ], + "summary": "根据Key获取SysConfig的Service", + "parameters": [ + { + "type": "string", + "description": "configKey", + "name": "configKey", + "in": "path" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/dto.SysConfigByKeyReq" + } + } + } + ] + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "修改配置管理", + "consumes": [ + "application/json" + ], + "tags": [ + "配置管理" + ], + "summary": "修改配置管理", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysConfigControl" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"修改成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-login-log": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "登录日志" + ], + "summary": "登录日志列表", + "parameters": [ + { + "type": "string", + "description": "用户名", + "name": "username", + "in": "query" + }, + { + "type": "string", + "description": "ip地址", + "name": "ipaddr", + "in": "query" + }, + { + "type": "string", + "description": "归属地", + "name": "loginLocation", + "in": "query" + }, + { + "type": "string", + "description": "状态", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "开始时间", + "name": "beginTime", + "in": "query" + }, + { + "type": "string", + "description": "结束时间", + "name": "endTime", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "登录日志删除", + "tags": [ + "登录日志" + ], + "summary": "登录日志删除", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysLoginLogDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-login-log/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "登录日志" + ], + "summary": "登录日志通过id获取", + "parameters": [ + { + "type": "string", + "description": "id", + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-opera-log": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "操作日志" + ], + "summary": "操作日志列表", + "parameters": [ + { + "type": "string", + "description": "title", + "name": "title", + "in": "query" + }, + { + "type": "string", + "description": "method", + "name": "method", + "in": "query" + }, + { + "type": "string", + "description": "requestMethod", + "name": "requestMethod", + "in": "query" + }, + { + "type": "string", + "description": "operUrl", + "name": "operUrl", + "in": "query" + }, + { + "type": "string", + "description": "operIp", + "name": "operIp", + "in": "query" + }, + { + "type": "string", + "description": "status", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "beginTime", + "name": "beginTime", + "in": "query" + }, + { + "type": "string", + "description": "endTime", + "name": "endTime", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除数据", + "tags": [ + "操作日志" + ], + "summary": "删除操作日志", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysOperaLogDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-opera-log/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "操作日志" + ], + "summary": "操作日志通过id获取", + "parameters": [ + { + "type": "string", + "description": "id", + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-user": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "用户" + ], + "summary": "列表用户信息数据", + "parameters": [ + { + "type": "string", + "description": "username", + "name": "username", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "创建用户", + "parameters": [ + { + "description": "用户数据", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysUserInsertReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-user/{userId}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "用户" + ], + "summary": "获取用户", + "parameters": [ + { + "type": "integer", + "description": "用户编码", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "修改用户数据", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysUserUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除数据", + "tags": [ + "用户" + ], + "summary": "删除用户数据", + "parameters": [ + { + "type": "integer", + "description": "userId", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys/tables/info": { + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "修改表结构", + "consumes": [ + "application/json" + ], + "tags": [ + "工具 / 生成工具" + ], + "summary": "修改表结构", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/tools.SysTables" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": -1, \"message\": \"添加失败\"}", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "添加表结构", + "consumes": [ + "application/json" + ], + "tags": [ + "工具 / 生成工具" + ], + "summary": "添加表结构", + "parameters": [ + { + "type": "string", + "description": "tableName / 数据表名称", + "name": "tables", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": -1, \"message\": \"添加失败\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/sys/tables/info/{tableId}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "工具 / 生成工具" + ], + "summary": "获取配置", + "parameters": [ + { + "type": "integer", + "description": "configKey", + "name": "configKey", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "description": "删除表结构", + "tags": [ + "工具 / 生成工具" + ], + "summary": "删除表结构", + "parameters": [ + { + "type": "integer", + "description": "tableId", + "name": "tableId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": -1, \"message\": \"删除失败\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/sys/tables/page": { + "get": { + "description": "生成表分页列表", + "tags": [ + "工具 / 生成工具" + ], + "summary": "分页列表数据", + "parameters": [ + { + "type": "string", + "description": "tableName / 数据表名称", + "name": "tableName", + "in": "query" + }, + { + "type": "integer", + "description": "pageSize / 页条数", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "pageIndex / 页码", + "name": "pageIndex", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/user/avatar": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "multipart/form-data" + ], + "tags": [ + "个人中心" + ], + "summary": "修改头像", + "parameters": [ + { + "type": "file", + "description": "file", + "name": "file", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/user/profile": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "个人中心" + ], + "summary": "获取个人中心用户", + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/user/pwd/reset": { + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "重置用户密码", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.ResetSysUserPwdReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/user/pwd/set": { + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "修改密码", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.PassWord" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/user/status": { + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "修改用户状态", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.UpdateSysUserStatusReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/logout": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取token", + "consumes": [ + "application/json" + ], + "summary": "退出登录", + "responses": { + "200": { + "description": "{\"code\": 200, \"msg\": \"成功退出系统\" }", + "schema": { + "type": "string" + } + } + } + } + } + }, + "definitions": { + "dto.GetSetSysConfigReq": { + "type": "object", + "properties": { + "configKey": { + "type": "string" + }, + "configValue": { + "type": "string" + } + } + }, + "dto.PassWord": { + "type": "object", + "properties": { + "newPassword": { + "type": "string" + }, + "oldPassword": { + "type": "string" + } + } + }, + "dto.ResetSysUserPwdReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "password": { + "type": "string" + }, + "updateBy": { + "type": "integer" + }, + "userId": { + "description": "用户ID", + "type": "integer" + } + } + }, + "dto.RoleDataScopeReq": { + "type": "object", + "required": [ + "dataScope", + "roleId" + ], + "properties": { + "dataScope": { + "type": "string" + }, + "deptIds": { + "type": "array", + "items": { + "type": "integer" + } + }, + "roleId": { + "type": "integer" + } + } + }, + "dto.SysApiDeleteReq": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "dto.SysApiUpdateReq": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "handle": { + "type": "string" + }, + "id": { + "description": "编码", + "type": "integer" + }, + "path": { + "type": "string" + }, + "title": { + "type": "string" + }, + "type": { + "type": "string" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysConfigByKeyReq": { + "type": "object", + "properties": { + "configKey": { + "type": "string" + } + } + }, + "dto.SysConfigControl": { + "type": "object", + "properties": { + "configKey": { + "type": "string" + }, + "configName": { + "type": "string" + }, + "configType": { + "type": "string" + }, + "configValue": { + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "id": { + "description": "编码", + "type": "integer" + }, + "isFrontend": { + "type": "string" + }, + "remark": { + "type": "string" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysDeptDeleteReq": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "dto.SysDeptInsertReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "deptId": { + "description": "编码", + "type": "integer" + }, + "deptName": { + "description": "部门名称", + "type": "string" + }, + "deptPath": { + "description": "路径", + "type": "string" + }, + "email": { + "description": "邮箱", + "type": "string" + }, + "leader": { + "description": "负责人", + "type": "string" + }, + "parentId": { + "description": "上级部门", + "type": "integer" + }, + "phone": { + "description": "手机", + "type": "string" + }, + "sort": { + "description": "排序", + "type": "integer" + }, + "status": { + "description": "状态", + "type": "integer" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysDeptUpdateReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "deptId": { + "description": "编码", + "type": "integer" + }, + "deptName": { + "description": "部门名称", + "type": "string" + }, + "deptPath": { + "description": "路径", + "type": "string" + }, + "email": { + "description": "邮箱", + "type": "string" + }, + "leader": { + "description": "负责人", + "type": "string" + }, + "parentId": { + "description": "上级部门", + "type": "integer" + }, + "phone": { + "description": "手机", + "type": "string" + }, + "sort": { + "description": "排序", + "type": "integer" + }, + "status": { + "description": "状态", + "type": "integer" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysDictDataDeleteReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysDictDataGetAllResp": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, + "dto.SysDictDataInsertReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "cssClass": { + "type": "string" + }, + "default": { + "type": "string" + }, + "dictLabel": { + "type": "string" + }, + "dictSort": { + "type": "integer" + }, + "dictType": { + "type": "string" + }, + "dictValue": { + "type": "string" + }, + "isDefault": { + "type": "string" + }, + "listClass": { + "type": "string" + }, + "remark": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysDictDataUpdateReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "cssClass": { + "type": "string" + }, + "default": { + "type": "string" + }, + "dictLabel": { + "type": "string" + }, + "dictSort": { + "type": "integer" + }, + "dictType": { + "type": "string" + }, + "dictValue": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "isDefault": { + "type": "string" + }, + "listClass": { + "type": "string" + }, + "remark": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysDictTypeDeleteReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysDictTypeInsertReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "dictName": { + "type": "string" + }, + "dictType": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "remark": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysDictTypeUpdateReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "dictName": { + "type": "string" + }, + "dictType": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "remark": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysLoginLogDeleteReq": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "dto.SysMenuDeleteReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysMenuInsertReq": { + "type": "object", + "properties": { + "action": { + "description": "请求方式", + "type": "string" + }, + "apis": { + "type": "array", + "items": { + "type": "integer" + } + }, + "breadcrumb": { + "description": "是否面包屑", + "type": "string" + }, + "component": { + "description": "组件", + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "icon": { + "description": "图标", + "type": "string" + }, + "isFrame": { + "description": "是否frame", + "type": "string" + }, + "menuId": { + "description": "编码", + "type": "integer" + }, + "menuName": { + "description": "菜单name", + "type": "string" + }, + "menuType": { + "description": "菜单类型", + "type": "string" + }, + "noCache": { + "description": "是否缓存", + "type": "boolean" + }, + "parentId": { + "description": "上级菜单", + "type": "integer" + }, + "path": { + "description": "路径", + "type": "string" + }, + "paths": { + "description": "id路径", + "type": "string" + }, + "permission": { + "description": "权限编码", + "type": "string" + }, + "sort": { + "description": "排序", + "type": "integer" + }, + "sysApi": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysApi" + } + }, + "title": { + "description": "显示名称", + "type": "string" + }, + "updateBy": { + "type": "integer" + }, + "visible": { + "description": "是否显示", + "type": "string" + } + } + }, + "dto.SysMenuUpdateReq": { + "type": "object", + "properties": { + "action": { + "description": "请求方式", + "type": "string" + }, + "apis": { + "type": "array", + "items": { + "type": "integer" + } + }, + "breadcrumb": { + "description": "是否面包屑", + "type": "string" + }, + "component": { + "description": "组件", + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "icon": { + "description": "图标", + "type": "string" + }, + "isFrame": { + "description": "是否frame", + "type": "string" + }, + "menuId": { + "description": "编码", + "type": "integer" + }, + "menuName": { + "description": "菜单name", + "type": "string" + }, + "menuType": { + "description": "菜单类型", + "type": "string" + }, + "noCache": { + "description": "是否缓存", + "type": "boolean" + }, + "parentId": { + "description": "上级菜单", + "type": "integer" + }, + "path": { + "description": "路径", + "type": "string" + }, + "paths": { + "description": "id路径", + "type": "string" + }, + "permission": { + "description": "权限编码", + "type": "string" + }, + "sort": { + "description": "排序", + "type": "integer" + }, + "sysApi": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysApi" + } + }, + "title": { + "description": "显示名称", + "type": "string" + }, + "updateBy": { + "type": "integer" + }, + "visible": { + "description": "是否显示", + "type": "string" + } + } + }, + "dto.SysOperaLogDeleteReq": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "dto.SysPostDeleteReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysPostInsertReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "postCode": { + "type": "string" + }, + "postId": { + "type": "integer" + }, + "postName": { + "type": "string" + }, + "remark": { + "type": "string" + }, + "sort": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysPostUpdateReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "postCode": { + "type": "string" + }, + "postId": { + "type": "integer" + }, + "postName": { + "type": "string" + }, + "remark": { + "type": "string" + }, + "sort": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysRoleDeleteReq": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "dto.SysRoleInsertReq": { + "type": "object", + "properties": { + "admin": { + "type": "boolean" + }, + "createBy": { + "type": "integer" + }, + "dataScope": { + "type": "string" + }, + "deptIds": { + "type": "array", + "items": { + "type": "integer" + } + }, + "flag": { + "description": "标记", + "type": "string" + }, + "menuIds": { + "type": "array", + "items": { + "type": "integer" + } + }, + "remark": { + "description": "备注", + "type": "string" + }, + "roleId": { + "description": "角色编码", + "type": "integer" + }, + "roleKey": { + "description": "角色代码", + "type": "string" + }, + "roleName": { + "description": "角色名称", + "type": "string" + }, + "roleSort": { + "description": "角色排序", + "type": "integer" + }, + "status": { + "description": "状态 1禁用 2正常", + "type": "string" + }, + "sysDept": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysDept" + } + }, + "sysMenu": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysMenu" + } + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysRoleUpdateReq": { + "type": "object", + "properties": { + "admin": { + "type": "boolean" + }, + "createBy": { + "type": "integer" + }, + "dataScope": { + "type": "string" + }, + "deptIds": { + "type": "array", + "items": { + "type": "integer" + } + }, + "flag": { + "description": "标记", + "type": "string" + }, + "menuIds": { + "type": "array", + "items": { + "type": "integer" + } + }, + "remark": { + "description": "备注", + "type": "string" + }, + "roleId": { + "description": "角色编码", + "type": "integer" + }, + "roleKey": { + "description": "角色代码", + "type": "string" + }, + "roleName": { + "description": "角色名称", + "type": "string" + }, + "roleSort": { + "description": "角色排序", + "type": "integer" + }, + "status": { + "description": "状态", + "type": "string" + }, + "sysDept": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysDept" + } + }, + "sysMenu": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysMenu" + } + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysUserInsertReq": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "deptId": { + "type": "integer" + }, + "email": { + "type": "string" + }, + "nickName": { + "type": "string" + }, + "password": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "postId": { + "type": "integer" + }, + "remark": { + "type": "string" + }, + "roleId": { + "type": "integer" + }, + "sex": { + "type": "string" + }, + "status": { + "type": "string", + "default": "1" + }, + "updateBy": { + "type": "integer" + }, + "userId": { + "description": "用户ID", + "type": "integer" + }, + "username": { + "type": "string" + } + } + }, + "dto.SysUserUpdateReq": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "deptId": { + "type": "integer" + }, + "email": { + "type": "string" + }, + "nickName": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "postId": { + "type": "integer" + }, + "remark": { + "type": "string" + }, + "roleId": { + "type": "integer" + }, + "sex": { + "type": "string" + }, + "status": { + "type": "string", + "default": "1" + }, + "updateBy": { + "type": "integer" + }, + "userId": { + "description": "用户ID", + "type": "integer" + }, + "username": { + "type": "string" + } + } + }, + "dto.UpdateStatusReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "roleId": { + "description": "角色编码", + "type": "integer" + }, + "status": { + "description": "状态", + "type": "string" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.UpdateSysUserStatusReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "status": { + "type": "string" + }, + "updateBy": { + "type": "integer" + }, + "userId": { + "description": "用户ID", + "type": "integer" + } + } + }, + "handler.Login": { + "type": "object", + "required": [ + "code", + "password", + "username", + "uuid" + ], + "properties": { + "code": { + "type": "string" + }, + "password": { + "type": "string" + }, + "username": { + "type": "string" + }, + "uuid": { + "type": "string" + } + } + }, + "models.SysApi": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "handle": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "path": { + "type": "string" + }, + "title": { + "type": "string" + }, + "type": { + "type": "string" + }, + "updateBy": { + "type": "integer" + }, + "updatedAt": { + "type": "string" + } + } + }, + "models.SysConfig": { + "type": "object", + "properties": { + "configKey": { + "type": "string" + }, + "configName": { + "type": "string" + }, + "configType": { + "type": "string" + }, + "configValue": { + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "isFrontend": { + "type": "string" + }, + "remark": { + "type": "string" + }, + "updateBy": { + "type": "integer" + }, + "updatedAt": { + "type": "string" + } + } + }, + "models.SysDept": { + "type": "object", + "properties": { + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysDept" + } + }, + "createBy": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "dataScope": { + "type": "string" + }, + "deptId": { + "description": "部门编码", + "type": "integer" + }, + "deptName": { + "description": "部门名称", + "type": "string" + }, + "deptPath": { + "type": "string" + }, + "email": { + "description": "邮箱", + "type": "string" + }, + "leader": { + "description": "负责人", + "type": "string" + }, + "params": { + "type": "string" + }, + "parentId": { + "description": "上级部门", + "type": "integer" + }, + "phone": { + "description": "手机", + "type": "string" + }, + "sort": { + "description": "排序", + "type": "integer" + }, + "status": { + "description": "状态", + "type": "integer" + }, + "updateBy": { + "type": "integer" + }, + "updatedAt": { + "type": "string" + } + } + }, + "models.SysMenu": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "apis": { + "type": "array", + "items": { + "type": "integer" + } + }, + "breadcrumb": { + "type": "string" + }, + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysMenu" + } + }, + "component": { + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "dataScope": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "isFrame": { + "type": "string" + }, + "is_select": { + "type": "boolean" + }, + "menuId": { + "type": "integer" + }, + "menuName": { + "type": "string" + }, + "menuType": { + "type": "string" + }, + "noCache": { + "type": "boolean" + }, + "params": { + "type": "string" + }, + "parentId": { + "type": "integer" + }, + "path": { + "type": "string" + }, + "paths": { + "type": "string" + }, + "permission": { + "type": "string" + }, + "roleId": { + "type": "integer" + }, + "sort": { + "type": "integer" + }, + "sysApi": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysApi" + } + }, + "title": { + "type": "string" + }, + "updateBy": { + "type": "integer" + }, + "updatedAt": { + "type": "string" + }, + "visible": { + "type": "string" + } + } + }, + "response.Page": { + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "pageIndex": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + } + } + }, + "response.Response": { + "type": "object", + "properties": { + "code": { + "type": "integer" + }, + "msg": { + "type": "string" + }, + "requestId": { + "description": "数据集", + "type": "string" + }, + "status": { + "type": "string" + } + } + }, + "tools.Params": { + "type": "object", + "properties": { + "treeCode": { + "type": "string" + }, + "treeName": { + "type": "string" + }, + "treeParentCode": { + "type": "string" + } + } + }, + "tools.SysColumns": { + "type": "object", + "properties": { + "columnComment": { + "type": "string" + }, + "columnId": { + "type": "integer" + }, + "columnName": { + "type": "string" + }, + "columnType": { + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "dictType": { + "type": "string" + }, + "edit": { + "type": "boolean" + }, + "fkCol": { + "type": "array", + "items": { + "$ref": "#/definitions/tools.SysColumns" + } + }, + "fkLabelId": { + "type": "string" + }, + "fkLabelName": { + "type": "string" + }, + "fkTableName": { + "type": "string" + }, + "fkTableNameClass": { + "type": "string" + }, + "fkTableNamePackage": { + "type": "string" + }, + "goField": { + "type": "string" + }, + "goType": { + "type": "string" + }, + "htmlType": { + "type": "string" + }, + "increment": { + "type": "boolean" + }, + "insert": { + "type": "boolean" + }, + "isEdit": { + "type": "string" + }, + "isIncrement": { + "type": "string" + }, + "isInsert": { + "type": "string" + }, + "isList": { + "type": "string" + }, + "isPk": { + "type": "string" + }, + "isQuery": { + "type": "string" + }, + "isRequired": { + "type": "string" + }, + "jsonField": { + "type": "string" + }, + "list": { + "type": "string" + }, + "pk": { + "type": "boolean" + }, + "query": { + "type": "boolean" + }, + "queryType": { + "type": "string" + }, + "remark": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "sort": { + "type": "integer" + }, + "superColumn": { + "type": "boolean" + }, + "tableId": { + "type": "integer" + }, + "updateBy": { + "type": "integer" + }, + "updatedAt": { + "type": "string" + }, + "usableColumn": { + "type": "boolean" + } + } + }, + "tools.SysTables": { + "type": "object", + "properties": { + "businessName": { + "type": "string" + }, + "className": { + "description": "类名", + "type": "string" + }, + "columns": { + "type": "array", + "items": { + "$ref": "#/definitions/tools.SysColumns" + } + }, + "createBy": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "crud": { + "type": "boolean" + }, + "dataScope": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "functionAuthor": { + "description": "功能作者", + "type": "string" + }, + "functionName": { + "description": "功能名称", + "type": "string" + }, + "isActions": { + "type": "integer" + }, + "isAuth": { + "type": "integer" + }, + "isDataScope": { + "type": "integer" + }, + "isLogicalDelete": { + "type": "string" + }, + "logicalDelete": { + "type": "boolean" + }, + "logicalDeleteColumn": { + "type": "string" + }, + "moduleFrontName": { + "description": "前端文件名", + "type": "string" + }, + "moduleName": { + "description": "go文件名", + "type": "string" + }, + "options": { + "type": "string" + }, + "packageName": { + "description": "包名", + "type": "string" + }, + "params": { + "$ref": "#/definitions/tools.Params" + }, + "pkColumn": { + "type": "string" + }, + "pkGoField": { + "type": "string" + }, + "pkJsonField": { + "type": "string" + }, + "remark": { + "type": "string" + }, + "tableComment": { + "description": "表备注", + "type": "string" + }, + "tableId": { + "description": "表编码", + "type": "integer" + }, + "tableName": { + "description": "表名称", + "type": "string" + }, + "tplCategory": { + "type": "string" + }, + "tree": { + "type": "boolean" + }, + "treeCode": { + "type": "string" + }, + "treeName": { + "type": "string" + }, + "treeParentCode": { + "type": "string" + }, + "updateBy": { + "type": "integer" + }, + "updatedAt": { + "type": "string" + } + } + } + }, + "securityDefinitions": { + "Bearer": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + } +}` + +// SwaggerInfoadmin holds exported Swagger Info so clients can modify it +var SwaggerInfoadmin = &swag.Spec{ + Version: "2.0.0", + Host: "", + BasePath: "", + Schemes: []string{}, + Title: "go-admin API", + Description: "基于Gin + Vue + Element UI的前后端分离权限管理系统的接口文档\n添加qq群: 521386980 进入技术交流群 请先star,谢谢!", + InfoInstanceName: "admin", + SwaggerTemplate: docTemplateadmin, +} + +func init() { + swag.Register(SwaggerInfoadmin.InstanceName(), SwaggerInfoadmin) +} diff --git a/docs/admin/admin_swagger.json b/docs/admin/admin_swagger.json new file mode 100644 index 0000000..d3c32a1 --- /dev/null +++ b/docs/admin/admin_swagger.json @@ -0,0 +1,4348 @@ +{ + "swagger": "2.0", + "info": { + "description": "基于Gin + Vue + Element UI的前后端分离权限管理系统的接口文档\n添加qq群: 521386980 进入技术交流群 请先star,谢谢!", + "title": "go-admin API", + "contact": {}, + "license": { + "name": "MIT", + "url": "https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md" + }, + "version": "2.0.0" + }, + "paths": { + "/api/v1/app-config": { + "get": { + "description": "获取系统配置信息,主要注意这里不在验证权限", + "tags": [ + "配置管理" + ], + "summary": "获取系统前台配置信息,主要注意这里不在验证权限", + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + ] + } + } + } + } + }, + "/api/v1/captcha": { + "get": { + "description": "获取验证码", + "tags": [ + "登陆" + ], + "summary": "获取验证码", + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "string" + }, + "id": { + "type": "string" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/api/v1/db/columns/page": { + "get": { + "description": "数据库表列分页列表 / database table column page list", + "tags": [ + "工具 / 生成工具" + ], + "summary": "分页列表数据 / page list data", + "parameters": [ + { + "type": "string", + "description": "tableName / 数据表名称", + "name": "tableName", + "in": "query" + }, + { + "type": "integer", + "description": "pageSize / 页条数", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "pageIndex / 页码", + "name": "pageIndex", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/db/tables/page": { + "get": { + "description": "数据库表分页列表 / database table page list", + "tags": [ + "工具 / 生成工具" + ], + "summary": "分页列表数据 / page list data", + "parameters": [ + { + "type": "string", + "description": "tableName / 数据表名称", + "name": "tableName", + "in": "query" + }, + { + "type": "integer", + "description": "pageSize / 页条数", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "pageIndex / 页码", + "name": "pageIndex", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/dept": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "分页列表", + "tags": [ + "部门" + ], + "summary": "分页部门列表数据", + "parameters": [ + { + "type": "string", + "description": "deptName", + "name": "deptName", + "in": "query" + }, + { + "type": "string", + "description": "deptId", + "name": "deptId", + "in": "query" + }, + { + "type": "string", + "description": "position", + "name": "position", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "部门" + ], + "summary": "添加部门", + "parameters": [ + { + "description": "data", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDeptInsertReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": -1, \"message\": \"添加失败\"}", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除数据", + "tags": [ + "部门" + ], + "summary": "删除部门", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDeptDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": -1, \"message\": \"删除失败\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/dept/{deptId}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "部门" + ], + "summary": "获取部门数据", + "parameters": [ + { + "type": "string", + "description": "deptId", + "name": "deptId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "部门" + ], + "summary": "修改部门", + "parameters": [ + { + "type": "integer", + "description": "id", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDeptUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": -1, \"message\": \"添加失败\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/dict-data/option-select": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "数据字典根据key获取", + "tags": [ + "字典数据" + ], + "summary": "数据字典根据key获取", + "parameters": [ + { + "type": "integer", + "description": "dictType", + "name": "dictType", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.SysDictDataGetAllResp" + } + } + } + } + ] + } + } + } + } + }, + "/api/v1/dict/data": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "字典数据" + ], + "summary": "字典数据列表", + "parameters": [ + { + "type": "string", + "description": "status", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "dictCode", + "name": "dictCode", + "in": "query" + }, + { + "type": "string", + "description": "dictType", + "name": "dictType", + "in": "query" + }, + { + "type": "integer", + "description": "页条数", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "pageIndex", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "字典数据" + ], + "summary": "添加字典数据", + "parameters": [ + { + "description": "data", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDictDataInsertReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"添加成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除数据", + "tags": [ + "字典数据" + ], + "summary": "删除字典数据", + "parameters": [ + { + "description": "body", + "name": "dictCode", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDictDataDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"删除成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/dict/data/{dictCode}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "字典数据" + ], + "summary": "通过编码获取字典数据", + "parameters": [ + { + "type": "integer", + "description": "字典编码", + "name": "dictCode", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "字典数据" + ], + "summary": "修改字典数据", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDictDataUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"修改成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/dict/type": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "字典类型" + ], + "summary": "字典类型列表数据", + "parameters": [ + { + "type": "string", + "description": "dictName", + "name": "dictName", + "in": "query" + }, + { + "type": "string", + "description": "dictId", + "name": "dictId", + "in": "query" + }, + { + "type": "string", + "description": "dictType", + "name": "dictType", + "in": "query" + }, + { + "type": "integer", + "description": "页条数", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "pageIndex", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "字典类型" + ], + "summary": "添加字典类型", + "parameters": [ + { + "description": "data", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDictTypeInsertReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除数据", + "tags": [ + "字典类型" + ], + "summary": "删除字典类型", + "parameters": [ + { + "description": "body", + "name": "dictCode", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDictTypeDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/dict/type-option-select": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "字典类型" + ], + "summary": "字典类型全部数据 代码生成使用接口", + "parameters": [ + { + "type": "string", + "description": "dictName", + "name": "dictName", + "in": "query" + }, + { + "type": "string", + "description": "dictId", + "name": "dictId", + "in": "query" + }, + { + "type": "string", + "description": "dictType", + "name": "dictType", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/dict/type/{dictId}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "字典类型" + ], + "summary": "字典类型通过字典id获取", + "parameters": [ + { + "type": "integer", + "description": "字典类型编码", + "name": "dictId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "字典类型" + ], + "summary": "修改字典类型", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysDictTypeUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/getinfo": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "个人中心" + ], + "summary": "获取个人信息", + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/login": { + "post": { + "description": "获取token\nLoginHandler can be used by clients to get a jwt token.\nPayload needs to be json in the form of {\"username\": \"USERNAME\", \"password\": \"PASSWORD\"}.\nReply will be of the form {\"token\": \"TOKEN\"}.\ndev mode:It should be noted that all fields cannot be empty, and a value of 0 can be passed in addition to the account password\n注意:开发模式:需要注意全部字段不能为空,账号密码外可以传入0值", + "consumes": [ + "application/json" + ], + "tags": [ + "登陆" + ], + "summary": "登陆", + "parameters": [ + { + "description": "account", + "name": "account", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/handler.Login" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"expire\": \"2019-08-07T12:45:48+08:00\", \"token\": \".eyJleHAiOjE1NjUxNTMxNDgsImlkIjoiYWRtaW4iLCJvcmlnX2lhdCI6MTU2NTE0OTU0OH0.-zvzHvbg0A\" }", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/menu": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "菜单" + ], + "summary": "Menu列表数据", + "parameters": [ + { + "type": "string", + "description": "menuName", + "name": "menuName", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "菜单" + ], + "summary": "创建菜单", + "parameters": [ + { + "description": "data", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysMenuInsertReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除数据", + "tags": [ + "菜单" + ], + "summary": "删除菜单", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysMenuDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/menu/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "菜单" + ], + "summary": "Menu详情数据", + "parameters": [ + { + "type": "string", + "description": "id", + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "菜单" + ], + "summary": "修改菜单", + "parameters": [ + { + "type": "integer", + "description": "id", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysMenuUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/menuTreeselect/{roleId}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "菜单" + ], + "summary": "角色修改使用的菜单列表", + "parameters": [ + { + "type": "integer", + "description": "roleId", + "name": "roleId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/menurole": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "菜单" + ], + "summary": "根据登录角色名称获取菜单列表数据(左菜单使用)", + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/post": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "岗位" + ], + "summary": "岗位列表数据", + "parameters": [ + { + "type": "string", + "description": "postName", + "name": "postName", + "in": "query" + }, + { + "type": "string", + "description": "postCode", + "name": "postCode", + "in": "query" + }, + { + "type": "string", + "description": "postId", + "name": "postId", + "in": "query" + }, + { + "type": "string", + "description": "status", + "name": "status", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "岗位" + ], + "summary": "添加岗位", + "parameters": [ + { + "description": "data", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysPostInsertReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除数据", + "tags": [ + "岗位" + ], + "summary": "删除岗位", + "parameters": [ + { + "description": "请求参数", + "name": "id", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysPostDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/post/{id}": { + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "岗位" + ], + "summary": "修改岗位", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysPostUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/post/{postId}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "岗位" + ], + "summary": "获取岗位信息", + "parameters": [ + { + "type": "integer", + "description": "编码", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/public/uploadFile": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "multipart/form-data" + ], + "tags": [ + "公共接口" + ], + "summary": "上传图片", + "parameters": [ + { + "type": "string", + "description": "type", + "name": "type", + "in": "query", + "required": true + }, + { + "type": "file", + "description": "file", + "name": "file", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": -1, \"message\": \"添加失败\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/role": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Get JSON", + "tags": [ + "角色/Role" + ], + "summary": "角色列表数据", + "parameters": [ + { + "type": "string", + "description": "roleName", + "name": "roleName", + "in": "query" + }, + { + "type": "string", + "description": "status", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "roleKey", + "name": "roleKey", + "in": "query" + }, + { + "type": "integer", + "description": "页条数", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "pageIndex", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "角色/Role" + ], + "summary": "创建角色", + "parameters": [ + { + "description": "data", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysRoleInsertReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除数据", + "tags": [ + "角色/Role" + ], + "summary": "删除用户角色", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysRoleDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/role-status/{id}": { + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "角色/Role" + ], + "summary": "更新角色数据权限", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.RoleDataScopeReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/role/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "角色/Role" + ], + "summary": "获取Role数据", + "parameters": [ + { + "type": "string", + "description": "roleId", + "name": "roleId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "角色/Role" + ], + "summary": "修改用户角色", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysRoleUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/server-monitor": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "系统信息" + ], + "summary": "系统信息", + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/set-config": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "界面操作设置配置值的获取", + "consumes": [ + "application/json" + ], + "tags": [ + "配置管理" + ], + "summary": "获取配置", + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"修改成功\"}", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": true + } + } + } + ] + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "界面操作设置配置值", + "consumes": [ + "application/json" + ], + "tags": [ + "配置管理" + ], + "summary": "设置配置", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.GetSetSysConfigReq" + } + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"修改成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-api": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取接口管理列表", + "tags": [ + "接口管理" + ], + "summary": "获取接口管理列表", + "parameters": [ + { + "type": "string", + "description": "名称", + "name": "name", + "in": "query" + }, + { + "type": "string", + "description": "标题", + "name": "title", + "in": "query" + }, + { + "type": "string", + "description": "地址", + "name": "path", + "in": "query" + }, + { + "type": "string", + "description": "类型", + "name": "action", + "in": "query" + }, + { + "type": "integer", + "description": "页条数", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "pageIndex", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/definitions/response.Page" + }, + { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysApi" + } + } + } + } + ] + } + } + } + ] + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除接口管理", + "tags": [ + "接口管理" + ], + "summary": "删除接口管理", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysApiDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"删除成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-api/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取接口管理", + "tags": [ + "接口管理" + ], + "summary": "获取接口管理", + "parameters": [ + { + "type": "string", + "description": "id", + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/models.SysApi" + } + } + } + ] + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "修改接口管理", + "consumes": [ + "application/json" + ], + "tags": [ + "接口管理" + ], + "summary": "修改接口管理", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysApiUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"修改成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-config": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取配置管理列表", + "tags": [ + "配置管理" + ], + "summary": "获取配置管理列表", + "parameters": [ + { + "type": "string", + "description": "名称", + "name": "configName", + "in": "query" + }, + { + "type": "string", + "description": "key", + "name": "configKey", + "in": "query" + }, + { + "type": "string", + "description": "类型", + "name": "configType", + "in": "query" + }, + { + "type": "integer", + "description": "是否前端", + "name": "isFrontend", + "in": "query" + }, + { + "type": "integer", + "description": "页条数", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "pageIndex", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "allOf": [ + { + "$ref": "#/definitions/response.Page" + }, + { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysApi" + } + } + } + } + ] + } + } + } + ] + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "创建配置管理", + "consumes": [ + "application/json" + ], + "tags": [ + "配置管理" + ], + "summary": "创建配置管理", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysConfigControl" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"创建成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除配置管理", + "tags": [ + "配置管理" + ], + "summary": "删除配置管理", + "parameters": [ + { + "description": "ids", + "name": "ids", + "in": "body", + "schema": { + "type": "array", + "items": { + "type": "integer" + } + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"删除成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-config/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "根据Key获取SysConfig的Service", + "tags": [ + "配置管理" + ], + "summary": "根据Key获取SysConfig的Service", + "parameters": [ + { + "type": "string", + "description": "configKey", + "name": "configKey", + "in": "path" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/dto.SysConfigByKeyReq" + } + } + } + ] + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "修改配置管理", + "consumes": [ + "application/json" + ], + "tags": [ + "配置管理" + ], + "summary": "修改配置管理", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysConfigControl" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"message\": \"修改成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-login-log": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "登录日志" + ], + "summary": "登录日志列表", + "parameters": [ + { + "type": "string", + "description": "用户名", + "name": "username", + "in": "query" + }, + { + "type": "string", + "description": "ip地址", + "name": "ipaddr", + "in": "query" + }, + { + "type": "string", + "description": "归属地", + "name": "loginLocation", + "in": "query" + }, + { + "type": "string", + "description": "状态", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "开始时间", + "name": "beginTime", + "in": "query" + }, + { + "type": "string", + "description": "结束时间", + "name": "endTime", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "登录日志删除", + "tags": [ + "登录日志" + ], + "summary": "登录日志删除", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysLoginLogDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-login-log/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "登录日志" + ], + "summary": "登录日志通过id获取", + "parameters": [ + { + "type": "string", + "description": "id", + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-opera-log": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "操作日志" + ], + "summary": "操作日志列表", + "parameters": [ + { + "type": "string", + "description": "title", + "name": "title", + "in": "query" + }, + { + "type": "string", + "description": "method", + "name": "method", + "in": "query" + }, + { + "type": "string", + "description": "requestMethod", + "name": "requestMethod", + "in": "query" + }, + { + "type": "string", + "description": "operUrl", + "name": "operUrl", + "in": "query" + }, + { + "type": "string", + "description": "operIp", + "name": "operIp", + "in": "query" + }, + { + "type": "string", + "description": "status", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "beginTime", + "name": "beginTime", + "in": "query" + }, + { + "type": "string", + "description": "endTime", + "name": "endTime", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除数据", + "tags": [ + "操作日志" + ], + "summary": "删除操作日志", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysOperaLogDeleteReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-opera-log/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "操作日志" + ], + "summary": "操作日志通过id获取", + "parameters": [ + { + "type": "string", + "description": "id", + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-user": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "用户" + ], + "summary": "列表用户信息数据", + "parameters": [ + { + "type": "string", + "description": "username", + "name": "username", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "创建用户", + "parameters": [ + { + "description": "用户数据", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysUserInsertReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys-user/{userId}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "用户" + ], + "summary": "获取用户", + "parameters": [ + { + "type": "integer", + "description": "用户编码", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "修改用户数据", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SysUserUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "删除数据", + "tags": [ + "用户" + ], + "summary": "删除用户数据", + "parameters": [ + { + "type": "integer", + "description": "userId", + "name": "userId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/sys/tables/info": { + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "修改表结构", + "consumes": [ + "application/json" + ], + "tags": [ + "工具 / 生成工具" + ], + "summary": "修改表结构", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/tools.SysTables" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": -1, \"message\": \"添加失败\"}", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "添加表结构", + "consumes": [ + "application/json" + ], + "tags": [ + "工具 / 生成工具" + ], + "summary": "添加表结构", + "parameters": [ + { + "type": "string", + "description": "tableName / 数据表名称", + "name": "tables", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": -1, \"message\": \"添加失败\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/sys/tables/info/{tableId}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "工具 / 生成工具" + ], + "summary": "获取配置", + "parameters": [ + { + "type": "integer", + "description": "configKey", + "name": "configKey", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "description": "删除表结构", + "tags": [ + "工具 / 生成工具" + ], + "summary": "删除表结构", + "parameters": [ + { + "type": "integer", + "description": "tableId", + "name": "tableId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": -1, \"message\": \"删除失败\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/sys/tables/page": { + "get": { + "description": "生成表分页列表", + "tags": [ + "工具 / 生成工具" + ], + "summary": "分页列表数据", + "parameters": [ + { + "type": "string", + "description": "tableName / 数据表名称", + "name": "tableName", + "in": "query" + }, + { + "type": "integer", + "description": "pageSize / 页条数", + "name": "pageSize", + "in": "query" + }, + { + "type": "integer", + "description": "pageIndex / 页码", + "name": "pageIndex", + "in": "query" + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/user/avatar": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "multipart/form-data" + ], + "tags": [ + "个人中心" + ], + "summary": "修改头像", + "parameters": [ + { + "type": "file", + "description": "file", + "name": "file", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/user/profile": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "tags": [ + "个人中心" + ], + "summary": "获取个人中心用户", + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/user/pwd/reset": { + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "重置用户密码", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.ResetSysUserPwdReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/user/pwd/set": { + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "修改密码", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.PassWord" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/api/v1/user/status": { + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取JSON", + "consumes": [ + "application/json" + ], + "tags": [ + "用户" + ], + "summary": "修改用户状态", + "parameters": [ + { + "description": "body", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.UpdateSysUserStatusReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": [...]}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/logout": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "获取token", + "consumes": [ + "application/json" + ], + "summary": "退出登录", + "responses": { + "200": { + "description": "{\"code\": 200, \"msg\": \"成功退出系统\" }", + "schema": { + "type": "string" + } + } + } + } + } + }, + "definitions": { + "dto.GetSetSysConfigReq": { + "type": "object", + "properties": { + "configKey": { + "type": "string" + }, + "configValue": { + "type": "string" + } + } + }, + "dto.PassWord": { + "type": "object", + "properties": { + "newPassword": { + "type": "string" + }, + "oldPassword": { + "type": "string" + } + } + }, + "dto.ResetSysUserPwdReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "password": { + "type": "string" + }, + "updateBy": { + "type": "integer" + }, + "userId": { + "description": "用户ID", + "type": "integer" + } + } + }, + "dto.RoleDataScopeReq": { + "type": "object", + "required": [ + "dataScope", + "roleId" + ], + "properties": { + "dataScope": { + "type": "string" + }, + "deptIds": { + "type": "array", + "items": { + "type": "integer" + } + }, + "roleId": { + "type": "integer" + } + } + }, + "dto.SysApiDeleteReq": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "dto.SysApiUpdateReq": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "handle": { + "type": "string" + }, + "id": { + "description": "编码", + "type": "integer" + }, + "path": { + "type": "string" + }, + "title": { + "type": "string" + }, + "type": { + "type": "string" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysConfigByKeyReq": { + "type": "object", + "properties": { + "configKey": { + "type": "string" + } + } + }, + "dto.SysConfigControl": { + "type": "object", + "properties": { + "configKey": { + "type": "string" + }, + "configName": { + "type": "string" + }, + "configType": { + "type": "string" + }, + "configValue": { + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "id": { + "description": "编码", + "type": "integer" + }, + "isFrontend": { + "type": "string" + }, + "remark": { + "type": "string" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysDeptDeleteReq": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "dto.SysDeptInsertReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "deptId": { + "description": "编码", + "type": "integer" + }, + "deptName": { + "description": "部门名称", + "type": "string" + }, + "deptPath": { + "description": "路径", + "type": "string" + }, + "email": { + "description": "邮箱", + "type": "string" + }, + "leader": { + "description": "负责人", + "type": "string" + }, + "parentId": { + "description": "上级部门", + "type": "integer" + }, + "phone": { + "description": "手机", + "type": "string" + }, + "sort": { + "description": "排序", + "type": "integer" + }, + "status": { + "description": "状态", + "type": "integer" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysDeptUpdateReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "deptId": { + "description": "编码", + "type": "integer" + }, + "deptName": { + "description": "部门名称", + "type": "string" + }, + "deptPath": { + "description": "路径", + "type": "string" + }, + "email": { + "description": "邮箱", + "type": "string" + }, + "leader": { + "description": "负责人", + "type": "string" + }, + "parentId": { + "description": "上级部门", + "type": "integer" + }, + "phone": { + "description": "手机", + "type": "string" + }, + "sort": { + "description": "排序", + "type": "integer" + }, + "status": { + "description": "状态", + "type": "integer" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysDictDataDeleteReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysDictDataGetAllResp": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, + "dto.SysDictDataInsertReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "cssClass": { + "type": "string" + }, + "default": { + "type": "string" + }, + "dictLabel": { + "type": "string" + }, + "dictSort": { + "type": "integer" + }, + "dictType": { + "type": "string" + }, + "dictValue": { + "type": "string" + }, + "isDefault": { + "type": "string" + }, + "listClass": { + "type": "string" + }, + "remark": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysDictDataUpdateReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "cssClass": { + "type": "string" + }, + "default": { + "type": "string" + }, + "dictLabel": { + "type": "string" + }, + "dictSort": { + "type": "integer" + }, + "dictType": { + "type": "string" + }, + "dictValue": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "isDefault": { + "type": "string" + }, + "listClass": { + "type": "string" + }, + "remark": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysDictTypeDeleteReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysDictTypeInsertReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "dictName": { + "type": "string" + }, + "dictType": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "remark": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysDictTypeUpdateReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "dictName": { + "type": "string" + }, + "dictType": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "remark": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysLoginLogDeleteReq": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "dto.SysMenuDeleteReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysMenuInsertReq": { + "type": "object", + "properties": { + "action": { + "description": "请求方式", + "type": "string" + }, + "apis": { + "type": "array", + "items": { + "type": "integer" + } + }, + "breadcrumb": { + "description": "是否面包屑", + "type": "string" + }, + "component": { + "description": "组件", + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "icon": { + "description": "图标", + "type": "string" + }, + "isFrame": { + "description": "是否frame", + "type": "string" + }, + "menuId": { + "description": "编码", + "type": "integer" + }, + "menuName": { + "description": "菜单name", + "type": "string" + }, + "menuType": { + "description": "菜单类型", + "type": "string" + }, + "noCache": { + "description": "是否缓存", + "type": "boolean" + }, + "parentId": { + "description": "上级菜单", + "type": "integer" + }, + "path": { + "description": "路径", + "type": "string" + }, + "paths": { + "description": "id路径", + "type": "string" + }, + "permission": { + "description": "权限编码", + "type": "string" + }, + "sort": { + "description": "排序", + "type": "integer" + }, + "sysApi": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysApi" + } + }, + "title": { + "description": "显示名称", + "type": "string" + }, + "updateBy": { + "type": "integer" + }, + "visible": { + "description": "是否显示", + "type": "string" + } + } + }, + "dto.SysMenuUpdateReq": { + "type": "object", + "properties": { + "action": { + "description": "请求方式", + "type": "string" + }, + "apis": { + "type": "array", + "items": { + "type": "integer" + } + }, + "breadcrumb": { + "description": "是否面包屑", + "type": "string" + }, + "component": { + "description": "组件", + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "icon": { + "description": "图标", + "type": "string" + }, + "isFrame": { + "description": "是否frame", + "type": "string" + }, + "menuId": { + "description": "编码", + "type": "integer" + }, + "menuName": { + "description": "菜单name", + "type": "string" + }, + "menuType": { + "description": "菜单类型", + "type": "string" + }, + "noCache": { + "description": "是否缓存", + "type": "boolean" + }, + "parentId": { + "description": "上级菜单", + "type": "integer" + }, + "path": { + "description": "路径", + "type": "string" + }, + "paths": { + "description": "id路径", + "type": "string" + }, + "permission": { + "description": "权限编码", + "type": "string" + }, + "sort": { + "description": "排序", + "type": "integer" + }, + "sysApi": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysApi" + } + }, + "title": { + "description": "显示名称", + "type": "string" + }, + "updateBy": { + "type": "integer" + }, + "visible": { + "description": "是否显示", + "type": "string" + } + } + }, + "dto.SysOperaLogDeleteReq": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "dto.SysPostDeleteReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysPostInsertReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "postCode": { + "type": "string" + }, + "postId": { + "type": "integer" + }, + "postName": { + "type": "string" + }, + "remark": { + "type": "string" + }, + "sort": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysPostUpdateReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "postCode": { + "type": "string" + }, + "postId": { + "type": "integer" + }, + "postName": { + "type": "string" + }, + "remark": { + "type": "string" + }, + "sort": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysRoleDeleteReq": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "dto.SysRoleInsertReq": { + "type": "object", + "properties": { + "admin": { + "type": "boolean" + }, + "createBy": { + "type": "integer" + }, + "dataScope": { + "type": "string" + }, + "deptIds": { + "type": "array", + "items": { + "type": "integer" + } + }, + "flag": { + "description": "标记", + "type": "string" + }, + "menuIds": { + "type": "array", + "items": { + "type": "integer" + } + }, + "remark": { + "description": "备注", + "type": "string" + }, + "roleId": { + "description": "角色编码", + "type": "integer" + }, + "roleKey": { + "description": "角色代码", + "type": "string" + }, + "roleName": { + "description": "角色名称", + "type": "string" + }, + "roleSort": { + "description": "角色排序", + "type": "integer" + }, + "status": { + "description": "状态 1禁用 2正常", + "type": "string" + }, + "sysDept": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysDept" + } + }, + "sysMenu": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysMenu" + } + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysRoleUpdateReq": { + "type": "object", + "properties": { + "admin": { + "type": "boolean" + }, + "createBy": { + "type": "integer" + }, + "dataScope": { + "type": "string" + }, + "deptIds": { + "type": "array", + "items": { + "type": "integer" + } + }, + "flag": { + "description": "标记", + "type": "string" + }, + "menuIds": { + "type": "array", + "items": { + "type": "integer" + } + }, + "remark": { + "description": "备注", + "type": "string" + }, + "roleId": { + "description": "角色编码", + "type": "integer" + }, + "roleKey": { + "description": "角色代码", + "type": "string" + }, + "roleName": { + "description": "角色名称", + "type": "string" + }, + "roleSort": { + "description": "角色排序", + "type": "integer" + }, + "status": { + "description": "状态", + "type": "string" + }, + "sysDept": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysDept" + } + }, + "sysMenu": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysMenu" + } + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.SysUserInsertReq": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "deptId": { + "type": "integer" + }, + "email": { + "type": "string" + }, + "nickName": { + "type": "string" + }, + "password": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "postId": { + "type": "integer" + }, + "remark": { + "type": "string" + }, + "roleId": { + "type": "integer" + }, + "sex": { + "type": "string" + }, + "status": { + "type": "string", + "default": "1" + }, + "updateBy": { + "type": "integer" + }, + "userId": { + "description": "用户ID", + "type": "integer" + }, + "username": { + "type": "string" + } + } + }, + "dto.SysUserUpdateReq": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "deptId": { + "type": "integer" + }, + "email": { + "type": "string" + }, + "nickName": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "postId": { + "type": "integer" + }, + "remark": { + "type": "string" + }, + "roleId": { + "type": "integer" + }, + "sex": { + "type": "string" + }, + "status": { + "type": "string", + "default": "1" + }, + "updateBy": { + "type": "integer" + }, + "userId": { + "description": "用户ID", + "type": "integer" + }, + "username": { + "type": "string" + } + } + }, + "dto.UpdateStatusReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "roleId": { + "description": "角色编码", + "type": "integer" + }, + "status": { + "description": "状态", + "type": "string" + }, + "updateBy": { + "type": "integer" + } + } + }, + "dto.UpdateSysUserStatusReq": { + "type": "object", + "properties": { + "createBy": { + "type": "integer" + }, + "status": { + "type": "string" + }, + "updateBy": { + "type": "integer" + }, + "userId": { + "description": "用户ID", + "type": "integer" + } + } + }, + "handler.Login": { + "type": "object", + "required": [ + "code", + "password", + "username", + "uuid" + ], + "properties": { + "code": { + "type": "string" + }, + "password": { + "type": "string" + }, + "username": { + "type": "string" + }, + "uuid": { + "type": "string" + } + } + }, + "models.SysApi": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "handle": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "path": { + "type": "string" + }, + "title": { + "type": "string" + }, + "type": { + "type": "string" + }, + "updateBy": { + "type": "integer" + }, + "updatedAt": { + "type": "string" + } + } + }, + "models.SysConfig": { + "type": "object", + "properties": { + "configKey": { + "type": "string" + }, + "configName": { + "type": "string" + }, + "configType": { + "type": "string" + }, + "configValue": { + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "isFrontend": { + "type": "string" + }, + "remark": { + "type": "string" + }, + "updateBy": { + "type": "integer" + }, + "updatedAt": { + "type": "string" + } + } + }, + "models.SysDept": { + "type": "object", + "properties": { + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysDept" + } + }, + "createBy": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "dataScope": { + "type": "string" + }, + "deptId": { + "description": "部门编码", + "type": "integer" + }, + "deptName": { + "description": "部门名称", + "type": "string" + }, + "deptPath": { + "type": "string" + }, + "email": { + "description": "邮箱", + "type": "string" + }, + "leader": { + "description": "负责人", + "type": "string" + }, + "params": { + "type": "string" + }, + "parentId": { + "description": "上级部门", + "type": "integer" + }, + "phone": { + "description": "手机", + "type": "string" + }, + "sort": { + "description": "排序", + "type": "integer" + }, + "status": { + "description": "状态", + "type": "integer" + }, + "updateBy": { + "type": "integer" + }, + "updatedAt": { + "type": "string" + } + } + }, + "models.SysMenu": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "apis": { + "type": "array", + "items": { + "type": "integer" + } + }, + "breadcrumb": { + "type": "string" + }, + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysMenu" + } + }, + "component": { + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "dataScope": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "isFrame": { + "type": "string" + }, + "is_select": { + "type": "boolean" + }, + "menuId": { + "type": "integer" + }, + "menuName": { + "type": "string" + }, + "menuType": { + "type": "string" + }, + "noCache": { + "type": "boolean" + }, + "params": { + "type": "string" + }, + "parentId": { + "type": "integer" + }, + "path": { + "type": "string" + }, + "paths": { + "type": "string" + }, + "permission": { + "type": "string" + }, + "roleId": { + "type": "integer" + }, + "sort": { + "type": "integer" + }, + "sysApi": { + "type": "array", + "items": { + "$ref": "#/definitions/models.SysApi" + } + }, + "title": { + "type": "string" + }, + "updateBy": { + "type": "integer" + }, + "updatedAt": { + "type": "string" + }, + "visible": { + "type": "string" + } + } + }, + "response.Page": { + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "pageIndex": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + } + } + }, + "response.Response": { + "type": "object", + "properties": { + "code": { + "type": "integer" + }, + "msg": { + "type": "string" + }, + "requestId": { + "description": "数据集", + "type": "string" + }, + "status": { + "type": "string" + } + } + }, + "tools.Params": { + "type": "object", + "properties": { + "treeCode": { + "type": "string" + }, + "treeName": { + "type": "string" + }, + "treeParentCode": { + "type": "string" + } + } + }, + "tools.SysColumns": { + "type": "object", + "properties": { + "columnComment": { + "type": "string" + }, + "columnId": { + "type": "integer" + }, + "columnName": { + "type": "string" + }, + "columnType": { + "type": "string" + }, + "createBy": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "dictType": { + "type": "string" + }, + "edit": { + "type": "boolean" + }, + "fkCol": { + "type": "array", + "items": { + "$ref": "#/definitions/tools.SysColumns" + } + }, + "fkLabelId": { + "type": "string" + }, + "fkLabelName": { + "type": "string" + }, + "fkTableName": { + "type": "string" + }, + "fkTableNameClass": { + "type": "string" + }, + "fkTableNamePackage": { + "type": "string" + }, + "goField": { + "type": "string" + }, + "goType": { + "type": "string" + }, + "htmlType": { + "type": "string" + }, + "increment": { + "type": "boolean" + }, + "insert": { + "type": "boolean" + }, + "isEdit": { + "type": "string" + }, + "isIncrement": { + "type": "string" + }, + "isInsert": { + "type": "string" + }, + "isList": { + "type": "string" + }, + "isPk": { + "type": "string" + }, + "isQuery": { + "type": "string" + }, + "isRequired": { + "type": "string" + }, + "jsonField": { + "type": "string" + }, + "list": { + "type": "string" + }, + "pk": { + "type": "boolean" + }, + "query": { + "type": "boolean" + }, + "queryType": { + "type": "string" + }, + "remark": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "sort": { + "type": "integer" + }, + "superColumn": { + "type": "boolean" + }, + "tableId": { + "type": "integer" + }, + "updateBy": { + "type": "integer" + }, + "updatedAt": { + "type": "string" + }, + "usableColumn": { + "type": "boolean" + } + } + }, + "tools.SysTables": { + "type": "object", + "properties": { + "businessName": { + "type": "string" + }, + "className": { + "description": "类名", + "type": "string" + }, + "columns": { + "type": "array", + "items": { + "$ref": "#/definitions/tools.SysColumns" + } + }, + "createBy": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "crud": { + "type": "boolean" + }, + "dataScope": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "functionAuthor": { + "description": "功能作者", + "type": "string" + }, + "functionName": { + "description": "功能名称", + "type": "string" + }, + "isActions": { + "type": "integer" + }, + "isAuth": { + "type": "integer" + }, + "isDataScope": { + "type": "integer" + }, + "isLogicalDelete": { + "type": "string" + }, + "logicalDelete": { + "type": "boolean" + }, + "logicalDeleteColumn": { + "type": "string" + }, + "moduleFrontName": { + "description": "前端文件名", + "type": "string" + }, + "moduleName": { + "description": "go文件名", + "type": "string" + }, + "options": { + "type": "string" + }, + "packageName": { + "description": "包名", + "type": "string" + }, + "params": { + "$ref": "#/definitions/tools.Params" + }, + "pkColumn": { + "type": "string" + }, + "pkGoField": { + "type": "string" + }, + "pkJsonField": { + "type": "string" + }, + "remark": { + "type": "string" + }, + "tableComment": { + "description": "表备注", + "type": "string" + }, + "tableId": { + "description": "表编码", + "type": "integer" + }, + "tableName": { + "description": "表名称", + "type": "string" + }, + "tplCategory": { + "type": "string" + }, + "tree": { + "type": "boolean" + }, + "treeCode": { + "type": "string" + }, + "treeName": { + "type": "string" + }, + "treeParentCode": { + "type": "string" + }, + "updateBy": { + "type": "integer" + }, + "updatedAt": { + "type": "string" + } + } + } + }, + "securityDefinitions": { + "Bearer": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + } +} \ No newline at end of file diff --git a/docs/admin/admin_swagger.yaml b/docs/admin/admin_swagger.yaml new file mode 100644 index 0000000..412817e --- /dev/null +++ b/docs/admin/admin_swagger.yaml @@ -0,0 +1,2771 @@ +definitions: + dto.GetSetSysConfigReq: + properties: + configKey: + type: string + configValue: + type: string + type: object + dto.PassWord: + properties: + newPassword: + type: string + oldPassword: + type: string + type: object + dto.ResetSysUserPwdReq: + properties: + createBy: + type: integer + password: + type: string + updateBy: + type: integer + userId: + description: 用户ID + type: integer + type: object + dto.RoleDataScopeReq: + properties: + dataScope: + type: string + deptIds: + items: + type: integer + type: array + roleId: + type: integer + required: + - dataScope + - roleId + type: object + dto.SysApiDeleteReq: + properties: + ids: + items: + type: integer + type: array + type: object + dto.SysApiUpdateReq: + properties: + action: + type: string + createBy: + type: integer + handle: + type: string + id: + description: 编码 + type: integer + path: + type: string + title: + type: string + type: + type: string + updateBy: + type: integer + type: object + dto.SysConfigByKeyReq: + properties: + configKey: + type: string + type: object + dto.SysConfigControl: + properties: + configKey: + type: string + configName: + type: string + configType: + type: string + configValue: + type: string + createBy: + type: integer + id: + description: 编码 + type: integer + isFrontend: + type: string + remark: + type: string + updateBy: + type: integer + type: object + dto.SysDeptDeleteReq: + properties: + ids: + items: + type: integer + type: array + type: object + dto.SysDeptInsertReq: + properties: + createBy: + type: integer + deptId: + description: 编码 + type: integer + deptName: + description: 部门名称 + type: string + deptPath: + description: 路径 + type: string + email: + description: 邮箱 + type: string + leader: + description: 负责人 + type: string + parentId: + description: 上级部门 + type: integer + phone: + description: 手机 + type: string + sort: + description: 排序 + type: integer + status: + description: 状态 + type: integer + updateBy: + type: integer + type: object + dto.SysDeptUpdateReq: + properties: + createBy: + type: integer + deptId: + description: 编码 + type: integer + deptName: + description: 部门名称 + type: string + deptPath: + description: 路径 + type: string + email: + description: 邮箱 + type: string + leader: + description: 负责人 + type: string + parentId: + description: 上级部门 + type: integer + phone: + description: 手机 + type: string + sort: + description: 排序 + type: integer + status: + description: 状态 + type: integer + updateBy: + type: integer + type: object + dto.SysDictDataDeleteReq: + properties: + createBy: + type: integer + ids: + items: + type: integer + type: array + updateBy: + type: integer + type: object + dto.SysDictDataGetAllResp: + properties: + label: + type: string + value: + type: string + type: object + dto.SysDictDataInsertReq: + properties: + createBy: + type: integer + cssClass: + type: string + default: + type: string + dictLabel: + type: string + dictSort: + type: integer + dictType: + type: string + dictValue: + type: string + isDefault: + type: string + listClass: + type: string + remark: + type: string + status: + type: integer + updateBy: + type: integer + type: object + dto.SysDictDataUpdateReq: + properties: + createBy: + type: integer + cssClass: + type: string + default: + type: string + dictLabel: + type: string + dictSort: + type: integer + dictType: + type: string + dictValue: + type: string + id: + type: integer + isDefault: + type: string + listClass: + type: string + remark: + type: string + status: + type: integer + updateBy: + type: integer + type: object + dto.SysDictTypeDeleteReq: + properties: + createBy: + type: integer + ids: + items: + type: integer + type: array + updateBy: + type: integer + type: object + dto.SysDictTypeInsertReq: + properties: + createBy: + type: integer + dictName: + type: string + dictType: + type: string + id: + type: integer + remark: + type: string + status: + type: integer + updateBy: + type: integer + type: object + dto.SysDictTypeUpdateReq: + properties: + createBy: + type: integer + dictName: + type: string + dictType: + type: string + id: + type: integer + remark: + type: string + status: + type: integer + updateBy: + type: integer + type: object + dto.SysLoginLogDeleteReq: + properties: + ids: + items: + type: integer + type: array + type: object + dto.SysMenuDeleteReq: + properties: + createBy: + type: integer + ids: + items: + type: integer + type: array + updateBy: + type: integer + type: object + dto.SysMenuInsertReq: + properties: + action: + description: 请求方式 + type: string + apis: + items: + type: integer + type: array + breadcrumb: + description: 是否面包屑 + type: string + component: + description: 组件 + type: string + createBy: + type: integer + icon: + description: 图标 + type: string + isFrame: + description: 是否frame + type: string + menuId: + description: 编码 + type: integer + menuName: + description: 菜单name + type: string + menuType: + description: 菜单类型 + type: string + noCache: + description: 是否缓存 + type: boolean + parentId: + description: 上级菜单 + type: integer + path: + description: 路径 + type: string + paths: + description: id路径 + type: string + permission: + description: 权限编码 + type: string + sort: + description: 排序 + type: integer + sysApi: + items: + $ref: '#/definitions/models.SysApi' + type: array + title: + description: 显示名称 + type: string + updateBy: + type: integer + visible: + description: 是否显示 + type: string + type: object + dto.SysMenuUpdateReq: + properties: + action: + description: 请求方式 + type: string + apis: + items: + type: integer + type: array + breadcrumb: + description: 是否面包屑 + type: string + component: + description: 组件 + type: string + createBy: + type: integer + icon: + description: 图标 + type: string + isFrame: + description: 是否frame + type: string + menuId: + description: 编码 + type: integer + menuName: + description: 菜单name + type: string + menuType: + description: 菜单类型 + type: string + noCache: + description: 是否缓存 + type: boolean + parentId: + description: 上级菜单 + type: integer + path: + description: 路径 + type: string + paths: + description: id路径 + type: string + permission: + description: 权限编码 + type: string + sort: + description: 排序 + type: integer + sysApi: + items: + $ref: '#/definitions/models.SysApi' + type: array + title: + description: 显示名称 + type: string + updateBy: + type: integer + visible: + description: 是否显示 + type: string + type: object + dto.SysOperaLogDeleteReq: + properties: + ids: + items: + type: integer + type: array + type: object + dto.SysPostDeleteReq: + properties: + createBy: + type: integer + ids: + items: + type: integer + type: array + updateBy: + type: integer + type: object + dto.SysPostInsertReq: + properties: + createBy: + type: integer + postCode: + type: string + postId: + type: integer + postName: + type: string + remark: + type: string + sort: + type: integer + status: + type: integer + updateBy: + type: integer + type: object + dto.SysPostUpdateReq: + properties: + createBy: + type: integer + postCode: + type: string + postId: + type: integer + postName: + type: string + remark: + type: string + sort: + type: integer + status: + type: integer + updateBy: + type: integer + type: object + dto.SysRoleDeleteReq: + properties: + ids: + items: + type: integer + type: array + type: object + dto.SysRoleInsertReq: + properties: + admin: + type: boolean + createBy: + type: integer + dataScope: + type: string + deptIds: + items: + type: integer + type: array + flag: + description: 标记 + type: string + menuIds: + items: + type: integer + type: array + remark: + description: 备注 + type: string + roleId: + description: 角色编码 + type: integer + roleKey: + description: 角色代码 + type: string + roleName: + description: 角色名称 + type: string + roleSort: + description: 角色排序 + type: integer + status: + description: 状态 1禁用 2正常 + type: string + sysDept: + items: + $ref: '#/definitions/models.SysDept' + type: array + sysMenu: + items: + $ref: '#/definitions/models.SysMenu' + type: array + updateBy: + type: integer + type: object + dto.SysRoleUpdateReq: + properties: + admin: + type: boolean + createBy: + type: integer + dataScope: + type: string + deptIds: + items: + type: integer + type: array + flag: + description: 标记 + type: string + menuIds: + items: + type: integer + type: array + remark: + description: 备注 + type: string + roleId: + description: 角色编码 + type: integer + roleKey: + description: 角色代码 + type: string + roleName: + description: 角色名称 + type: string + roleSort: + description: 角色排序 + type: integer + status: + description: 状态 + type: string + sysDept: + items: + $ref: '#/definitions/models.SysDept' + type: array + sysMenu: + items: + $ref: '#/definitions/models.SysMenu' + type: array + updateBy: + type: integer + type: object + dto.SysUserInsertReq: + properties: + avatar: + type: string + createBy: + type: integer + deptId: + type: integer + email: + type: string + nickName: + type: string + password: + type: string + phone: + type: string + postId: + type: integer + remark: + type: string + roleId: + type: integer + sex: + type: string + status: + default: "1" + type: string + updateBy: + type: integer + userId: + description: 用户ID + type: integer + username: + type: string + type: object + dto.SysUserUpdateReq: + properties: + avatar: + type: string + createBy: + type: integer + deptId: + type: integer + email: + type: string + nickName: + type: string + phone: + type: string + postId: + type: integer + remark: + type: string + roleId: + type: integer + sex: + type: string + status: + default: "1" + type: string + updateBy: + type: integer + userId: + description: 用户ID + type: integer + username: + type: string + type: object + dto.UpdateStatusReq: + properties: + createBy: + type: integer + roleId: + description: 角色编码 + type: integer + status: + description: 状态 + type: string + updateBy: + type: integer + type: object + dto.UpdateSysUserStatusReq: + properties: + createBy: + type: integer + status: + type: string + updateBy: + type: integer + userId: + description: 用户ID + type: integer + type: object + handler.Login: + properties: + code: + type: string + password: + type: string + username: + type: string + uuid: + type: string + required: + - code + - password + - username + - uuid + type: object + models.SysApi: + properties: + action: + type: string + createBy: + type: integer + createdAt: + type: string + handle: + type: string + id: + type: integer + path: + type: string + title: + type: string + type: + type: string + updateBy: + type: integer + updatedAt: + type: string + type: object + models.SysConfig: + properties: + configKey: + type: string + configName: + type: string + configType: + type: string + configValue: + type: string + createBy: + type: integer + createdAt: + type: string + id: + type: integer + isFrontend: + type: string + remark: + type: string + updateBy: + type: integer + updatedAt: + type: string + type: object + models.SysDept: + properties: + children: + items: + $ref: '#/definitions/models.SysDept' + type: array + createBy: + type: integer + createdAt: + type: string + dataScope: + type: string + deptId: + description: 部门编码 + type: integer + deptName: + description: 部门名称 + type: string + deptPath: + type: string + email: + description: 邮箱 + type: string + leader: + description: 负责人 + type: string + params: + type: string + parentId: + description: 上级部门 + type: integer + phone: + description: 手机 + type: string + sort: + description: 排序 + type: integer + status: + description: 状态 + type: integer + updateBy: + type: integer + updatedAt: + type: string + type: object + models.SysMenu: + properties: + action: + type: string + apis: + items: + type: integer + type: array + breadcrumb: + type: string + children: + items: + $ref: '#/definitions/models.SysMenu' + type: array + component: + type: string + createBy: + type: integer + createdAt: + type: string + dataScope: + type: string + icon: + type: string + is_select: + type: boolean + isFrame: + type: string + menuId: + type: integer + menuName: + type: string + menuType: + type: string + noCache: + type: boolean + params: + type: string + parentId: + type: integer + path: + type: string + paths: + type: string + permission: + type: string + roleId: + type: integer + sort: + type: integer + sysApi: + items: + $ref: '#/definitions/models.SysApi' + type: array + title: + type: string + updateBy: + type: integer + updatedAt: + type: string + visible: + type: string + type: object + response.Page: + properties: + count: + type: integer + pageIndex: + type: integer + pageSize: + type: integer + type: object + response.Response: + properties: + code: + type: integer + msg: + type: string + requestId: + description: 数据集 + type: string + status: + type: string + type: object + tools.Params: + properties: + treeCode: + type: string + treeName: + type: string + treeParentCode: + type: string + type: object + tools.SysColumns: + properties: + columnComment: + type: string + columnId: + type: integer + columnName: + type: string + columnType: + type: string + createBy: + type: integer + createdAt: + type: string + deletedAt: + type: string + dictType: + type: string + edit: + type: boolean + fkCol: + items: + $ref: '#/definitions/tools.SysColumns' + type: array + fkLabelId: + type: string + fkLabelName: + type: string + fkTableName: + type: string + fkTableNameClass: + type: string + fkTableNamePackage: + type: string + goField: + type: string + goType: + type: string + htmlType: + type: string + increment: + type: boolean + insert: + type: boolean + isEdit: + type: string + isIncrement: + type: string + isInsert: + type: string + isList: + type: string + isPk: + type: string + isQuery: + type: string + isRequired: + type: string + jsonField: + type: string + list: + type: string + pk: + type: boolean + query: + type: boolean + queryType: + type: string + remark: + type: string + required: + type: boolean + sort: + type: integer + superColumn: + type: boolean + tableId: + type: integer + updateBy: + type: integer + updatedAt: + type: string + usableColumn: + type: boolean + type: object + tools.SysTables: + properties: + businessName: + type: string + className: + description: 类名 + type: string + columns: + items: + $ref: '#/definitions/tools.SysColumns' + type: array + createBy: + type: integer + createdAt: + type: string + crud: + type: boolean + dataScope: + type: string + deletedAt: + type: string + functionAuthor: + description: 功能作者 + type: string + functionName: + description: 功能名称 + type: string + isActions: + type: integer + isAuth: + type: integer + isDataScope: + type: integer + isLogicalDelete: + type: string + logicalDelete: + type: boolean + logicalDeleteColumn: + type: string + moduleFrontName: + description: 前端文件名 + type: string + moduleName: + description: go文件名 + type: string + options: + type: string + packageName: + description: 包名 + type: string + params: + $ref: '#/definitions/tools.Params' + pkColumn: + type: string + pkGoField: + type: string + pkJsonField: + type: string + remark: + type: string + tableComment: + description: 表备注 + type: string + tableId: + description: 表编码 + type: integer + tableName: + description: 表名称 + type: string + tplCategory: + type: string + tree: + type: boolean + treeCode: + type: string + treeName: + type: string + treeParentCode: + type: string + updateBy: + type: integer + updatedAt: + type: string + type: object +info: + contact: {} + description: |- + 基于Gin + Vue + Element UI的前后端分离权限管理系统的接口文档 + 添加qq群: 521386980 进入技术交流群 请先star,谢谢! + license: + name: MIT + url: https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md + title: go-admin API + version: 2.0.0 +paths: + /api/v1/app-config: + get: + description: 获取系统配置信息,主要注意这里不在验证权限 + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + additionalProperties: + type: string + type: object + type: object + summary: 获取系统前台配置信息,主要注意这里不在验证权限 + tags: + - 配置管理 + /api/v1/captcha: + get: + description: 获取验证码 + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + type: string + id: + type: string + msg: + type: string + type: object + summary: 获取验证码 + tags: + - 登陆 + /api/v1/db/columns/page: + get: + description: 数据库表列分页列表 / database table column page list + parameters: + - description: tableName / 数据表名称 + in: query + name: tableName + type: string + - description: pageSize / 页条数 + in: query + name: pageSize + type: integer + - description: pageIndex / 页码 + in: query + name: pageIndex + type: integer + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + summary: 分页列表数据 / page list data + tags: + - 工具 / 生成工具 + /api/v1/db/tables/page: + get: + description: 数据库表分页列表 / database table page list + parameters: + - description: tableName / 数据表名称 + in: query + name: tableName + type: string + - description: pageSize / 页条数 + in: query + name: pageSize + type: integer + - description: pageIndex / 页码 + in: query + name: pageIndex + type: integer + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + summary: 分页列表数据 / page list data + tags: + - 工具 / 生成工具 + /api/v1/dept: + delete: + description: 删除数据 + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysDeptDeleteReq' + responses: + "200": + description: '{"code": -1, "message": "删除失败"}' + schema: + type: string + security: + - Bearer: [] + summary: 删除部门 + tags: + - 部门 + get: + description: 分页列表 + parameters: + - description: deptName + in: query + name: deptName + type: string + - description: deptId + in: query + name: deptId + type: string + - description: position + in: query + name: position + type: string + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 分页部门列表数据 + tags: + - 部门 + post: + consumes: + - application/json + description: 获取JSON + parameters: + - description: data + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysDeptInsertReq' + responses: + "200": + description: '{"code": -1, "message": "添加失败"}' + schema: + type: string + security: + - Bearer: [] + summary: 添加部门 + tags: + - 部门 + /api/v1/dept/{deptId}: + get: + description: 获取JSON + parameters: + - description: deptId + in: path + name: deptId + type: string + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 获取部门数据 + tags: + - 部门 + put: + consumes: + - application/json + description: 获取JSON + parameters: + - description: id + in: path + name: id + required: true + type: integer + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysDeptUpdateReq' + responses: + "200": + description: '{"code": -1, "message": "添加失败"}' + schema: + type: string + security: + - Bearer: [] + summary: 修改部门 + tags: + - 部门 + /api/v1/dict-data/option-select: + get: + description: 数据字典根据key获取 + parameters: + - description: dictType + in: query + name: dictType + required: true + type: integer + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + items: + $ref: '#/definitions/dto.SysDictDataGetAllResp' + type: array + type: object + security: + - Bearer: [] + summary: 数据字典根据key获取 + tags: + - 字典数据 + /api/v1/dict/data: + delete: + description: 删除数据 + parameters: + - description: body + in: body + name: dictCode + required: true + schema: + $ref: '#/definitions/dto.SysDictDataDeleteReq' + responses: + "200": + description: '{"code": 200, "message": "删除成功"}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 删除字典数据 + tags: + - 字典数据 + get: + description: 获取JSON + parameters: + - description: status + in: query + name: status + type: string + - description: dictCode + in: query + name: dictCode + type: string + - description: dictType + in: query + name: dictType + type: string + - description: 页条数 + in: query + name: pageSize + type: integer + - description: 页码 + in: query + name: pageIndex + type: integer + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 字典数据列表 + tags: + - 字典数据 + post: + consumes: + - application/json + description: 获取JSON + parameters: + - description: data + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysDictDataInsertReq' + responses: + "200": + description: '{"code": 200, "message": "添加成功"}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 添加字典数据 + tags: + - 字典数据 + /api/v1/dict/data/{dictCode}: + get: + description: 获取JSON + parameters: + - description: 字典编码 + in: path + name: dictCode + required: true + type: integer + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 通过编码获取字典数据 + tags: + - 字典数据 + put: + consumes: + - application/json + description: 获取JSON + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysDictDataUpdateReq' + responses: + "200": + description: '{"code": 200, "message": "修改成功"}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 修改字典数据 + tags: + - 字典数据 + /api/v1/dict/type: + delete: + description: 删除数据 + parameters: + - description: body + in: body + name: dictCode + required: true + schema: + $ref: '#/definitions/dto.SysDictTypeDeleteReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 删除字典类型 + tags: + - 字典类型 + get: + description: 获取JSON + parameters: + - description: dictName + in: query + name: dictName + type: string + - description: dictId + in: query + name: dictId + type: string + - description: dictType + in: query + name: dictType + type: string + - description: 页条数 + in: query + name: pageSize + type: integer + - description: 页码 + in: query + name: pageIndex + type: integer + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 字典类型列表数据 + tags: + - 字典类型 + post: + consumes: + - application/json + description: 获取JSON + parameters: + - description: data + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysDictTypeInsertReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 添加字典类型 + tags: + - 字典类型 + /api/v1/dict/type-option-select: + get: + description: 获取JSON + parameters: + - description: dictName + in: query + name: dictName + type: string + - description: dictId + in: query + name: dictId + type: string + - description: dictType + in: query + name: dictType + type: string + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 字典类型全部数据 代码生成使用接口 + tags: + - 字典类型 + /api/v1/dict/type/{dictId}: + get: + description: 获取JSON + parameters: + - description: 字典类型编码 + in: path + name: dictId + required: true + type: integer + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 字典类型通过字典id获取 + tags: + - 字典类型 + put: + consumes: + - application/json + description: 获取JSON + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysDictTypeUpdateReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 修改字典类型 + tags: + - 字典类型 + /api/v1/getinfo: + get: + description: 获取JSON + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 获取个人信息 + tags: + - 个人中心 + /api/v1/login: + post: + consumes: + - application/json + description: |- + 获取token + LoginHandler can be used by clients to get a jwt token. + Payload needs to be json in the form of {"username": "USERNAME", "password": "PASSWORD"}. + Reply will be of the form {"token": "TOKEN"}. + dev mode:It should be noted that all fields cannot be empty, and a value of 0 can be passed in addition to the account password + 注意:开发模式:需要注意全部字段不能为空,账号密码外可以传入0值 + parameters: + - description: account + in: body + name: account + required: true + schema: + $ref: '#/definitions/handler.Login' + responses: + "200": + description: '{"code": 200, "expire": "2019-08-07T12:45:48+08:00", "token": + ".eyJleHAiOjE1NjUxNTMxNDgsImlkIjoiYWRtaW4iLCJvcmlnX2lhdCI6MTU2NTE0OTU0OH0.-zvzHvbg0A" + }' + schema: + type: string + summary: 登陆 + tags: + - 登陆 + /api/v1/menu: + delete: + description: 删除数据 + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysMenuDeleteReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 删除菜单 + tags: + - 菜单 + get: + description: 获取JSON + parameters: + - description: menuName + in: query + name: menuName + type: string + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: Menu列表数据 + tags: + - 菜单 + post: + consumes: + - application/json + description: 获取JSON + parameters: + - description: data + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysMenuInsertReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 创建菜单 + tags: + - 菜单 + /api/v1/menu/{id}: + get: + description: 获取JSON + parameters: + - description: id + in: path + name: id + type: string + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: Menu详情数据 + tags: + - 菜单 + put: + consumes: + - application/json + description: 获取JSON + parameters: + - description: id + in: path + name: id + required: true + type: integer + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysMenuUpdateReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 修改菜单 + tags: + - 菜单 + /api/v1/menuTreeselect/{roleId}: + get: + consumes: + - application/json + description: 获取JSON + parameters: + - description: roleId + in: path + name: roleId + required: true + type: integer + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 角色修改使用的菜单列表 + tags: + - 菜单 + /api/v1/menurole: + get: + description: 获取JSON + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 根据登录角色名称获取菜单列表数据(左菜单使用) + tags: + - 菜单 + /api/v1/post: + delete: + description: 删除数据 + parameters: + - description: 请求参数 + in: body + name: id + required: true + schema: + $ref: '#/definitions/dto.SysPostDeleteReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 删除岗位 + tags: + - 岗位 + get: + description: 获取JSON + parameters: + - description: postName + in: query + name: postName + type: string + - description: postCode + in: query + name: postCode + type: string + - description: postId + in: query + name: postId + type: string + - description: status + in: query + name: status + type: string + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 岗位列表数据 + tags: + - 岗位 + post: + consumes: + - application/json + description: 获取JSON + parameters: + - description: data + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysPostInsertReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 添加岗位 + tags: + - 岗位 + /api/v1/post/{id}: + put: + consumes: + - application/json + description: 获取JSON + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysPostUpdateReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 修改岗位 + tags: + - 岗位 + /api/v1/post/{postId}: + get: + description: 获取JSON + parameters: + - description: 编码 + in: path + name: id + required: true + type: integer + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 获取岗位信息 + tags: + - 岗位 + /api/v1/public/uploadFile: + post: + consumes: + - multipart/form-data + description: 获取JSON + parameters: + - description: type + in: query + name: type + required: true + type: string + - description: file + in: formData + name: file + required: true + type: file + responses: + "200": + description: '{"code": -1, "message": "添加失败"}' + schema: + type: string + security: + - Bearer: [] + summary: 上传图片 + tags: + - 公共接口 + /api/v1/role: + delete: + description: 删除数据 + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysRoleDeleteReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 删除用户角色 + tags: + - 角色/Role + get: + description: Get JSON + parameters: + - description: roleName + in: query + name: roleName + type: string + - description: status + in: query + name: status + type: string + - description: roleKey + in: query + name: roleKey + type: string + - description: 页条数 + in: query + name: pageSize + type: integer + - description: 页码 + in: query + name: pageIndex + type: integer + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 角色列表数据 + tags: + - 角色/Role + post: + consumes: + - application/json + description: 获取JSON + parameters: + - description: data + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysRoleInsertReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 创建角色 + tags: + - 角色/Role + /api/v1/role-status/{id}: + put: + consumes: + - application/json + description: 获取JSON + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.RoleDataScopeReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 更新角色数据权限 + tags: + - 角色/Role + /api/v1/role/{id}: + get: + description: 获取JSON + parameters: + - description: roleId + in: path + name: roleId + type: string + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 获取Role数据 + tags: + - 角色/Role + put: + consumes: + - application/json + description: 获取JSON + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysRoleUpdateReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 修改用户角色 + tags: + - 角色/Role + /api/v1/server-monitor: + get: + description: 获取JSON + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 系统信息 + tags: + - 系统信息 + /api/v1/set-config: + get: + consumes: + - application/json + description: 界面操作设置配置值的获取 + responses: + "200": + description: '{"code": 200, "message": "修改成功"}' + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + additionalProperties: true + type: object + type: object + security: + - Bearer: [] + summary: 获取配置 + tags: + - 配置管理 + put: + consumes: + - application/json + description: 界面操作设置配置值 + parameters: + - description: body + in: body + name: data + required: true + schema: + items: + $ref: '#/definitions/dto.GetSetSysConfigReq' + type: array + responses: + "200": + description: '{"code": 200, "message": "修改成功"}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 设置配置 + tags: + - 配置管理 + /api/v1/sys-api: + delete: + description: 删除接口管理 + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysApiDeleteReq' + responses: + "200": + description: '{"code": 200, "message": "删除成功"}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 删除接口管理 + tags: + - 接口管理 + get: + description: 获取接口管理列表 + parameters: + - description: 名称 + in: query + name: name + type: string + - description: 标题 + in: query + name: title + type: string + - description: 地址 + in: query + name: path + type: string + - description: 类型 + in: query + name: action + type: string + - description: 页条数 + in: query + name: pageSize + type: integer + - description: 页码 + in: query + name: pageIndex + type: integer + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + allOf: + - $ref: '#/definitions/response.Page' + - properties: + list: + items: + $ref: '#/definitions/models.SysApi' + type: array + type: object + type: object + security: + - Bearer: [] + summary: 获取接口管理列表 + tags: + - 接口管理 + /api/v1/sys-api/{id}: + get: + description: 获取接口管理 + parameters: + - description: id + in: path + name: id + type: string + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/models.SysApi' + type: object + security: + - Bearer: [] + summary: 获取接口管理 + tags: + - 接口管理 + put: + consumes: + - application/json + description: 修改接口管理 + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysApiUpdateReq' + responses: + "200": + description: '{"code": 200, "message": "修改成功"}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 修改接口管理 + tags: + - 接口管理 + /api/v1/sys-config: + delete: + description: 删除配置管理 + parameters: + - description: ids + in: body + name: ids + schema: + items: + type: integer + type: array + responses: + "200": + description: '{"code": 200, "message": "删除成功"}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 删除配置管理 + tags: + - 配置管理 + get: + description: 获取配置管理列表 + parameters: + - description: 名称 + in: query + name: configName + type: string + - description: key + in: query + name: configKey + type: string + - description: 类型 + in: query + name: configType + type: string + - description: 是否前端 + in: query + name: isFrontend + type: integer + - description: 页条数 + in: query + name: pageSize + type: integer + - description: 页码 + in: query + name: pageIndex + type: integer + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + allOf: + - $ref: '#/definitions/response.Page' + - properties: + list: + items: + $ref: '#/definitions/models.SysApi' + type: array + type: object + type: object + security: + - Bearer: [] + summary: 获取配置管理列表 + tags: + - 配置管理 + post: + consumes: + - application/json + description: 创建配置管理 + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysConfigControl' + responses: + "200": + description: '{"code": 200, "message": "创建成功"}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 创建配置管理 + tags: + - 配置管理 + /api/v1/sys-config/{id}: + get: + description: 根据Key获取SysConfig的Service + parameters: + - description: configKey + in: path + name: configKey + type: string + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/dto.SysConfigByKeyReq' + type: object + security: + - Bearer: [] + summary: 根据Key获取SysConfig的Service + tags: + - 配置管理 + put: + consumes: + - application/json + description: 修改配置管理 + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysConfigControl' + responses: + "200": + description: '{"code": 200, "message": "修改成功"}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 修改配置管理 + tags: + - 配置管理 + /api/v1/sys-login-log: + delete: + description: 登录日志删除 + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysLoginLogDeleteReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 登录日志删除 + tags: + - 登录日志 + get: + description: 获取JSON + parameters: + - description: 用户名 + in: query + name: username + type: string + - description: ip地址 + in: query + name: ipaddr + type: string + - description: 归属地 + in: query + name: loginLocation + type: string + - description: 状态 + in: query + name: status + type: string + - description: 开始时间 + in: query + name: beginTime + type: string + - description: 结束时间 + in: query + name: endTime + type: string + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 登录日志列表 + tags: + - 登录日志 + /api/v1/sys-login-log/{id}: + get: + description: 获取JSON + parameters: + - description: id + in: path + name: id + type: string + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 登录日志通过id获取 + tags: + - 登录日志 + /api/v1/sys-opera-log: + delete: + description: 删除数据 + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysOperaLogDeleteReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 删除操作日志 + tags: + - 操作日志 + get: + description: 获取JSON + parameters: + - description: title + in: query + name: title + type: string + - description: method + in: query + name: method + type: string + - description: requestMethod + in: query + name: requestMethod + type: string + - description: operUrl + in: query + name: operUrl + type: string + - description: operIp + in: query + name: operIp + type: string + - description: status + in: query + name: status + type: string + - description: beginTime + in: query + name: beginTime + type: string + - description: endTime + in: query + name: endTime + type: string + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 操作日志列表 + tags: + - 操作日志 + /api/v1/sys-opera-log/{id}: + get: + description: 获取JSON + parameters: + - description: id + in: path + name: id + type: string + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 操作日志通过id获取 + tags: + - 操作日志 + /api/v1/sys-user: + get: + description: 获取JSON + parameters: + - description: username + in: query + name: username + type: string + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + type: string + security: + - Bearer: [] + summary: 列表用户信息数据 + tags: + - 用户 + post: + consumes: + - application/json + description: 获取JSON + parameters: + - description: 用户数据 + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysUserInsertReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 创建用户 + tags: + - 用户 + /api/v1/sys-user/{userId}: + delete: + description: 删除数据 + parameters: + - description: userId + in: path + name: userId + required: true + type: integer + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 删除用户数据 + tags: + - 用户 + get: + description: 获取JSON + parameters: + - description: 用户编码 + in: path + name: userId + required: true + type: integer + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 获取用户 + tags: + - 用户 + put: + consumes: + - application/json + description: 获取JSON + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.SysUserUpdateReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 修改用户数据 + tags: + - 用户 + /api/v1/sys/tables/info: + post: + consumes: + - application/json + description: 添加表结构 + parameters: + - description: tableName / 数据表名称 + in: query + name: tables + type: string + responses: + "200": + description: '{"code": -1, "message": "添加失败"}' + schema: + type: string + security: + - Bearer: [] + summary: 添加表结构 + tags: + - 工具 / 生成工具 + put: + consumes: + - application/json + description: 修改表结构 + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/tools.SysTables' + responses: + "200": + description: '{"code": -1, "message": "添加失败"}' + schema: + type: string + security: + - Bearer: [] + summary: 修改表结构 + tags: + - 工具 / 生成工具 + /api/v1/sys/tables/info/{tableId}: + delete: + description: 删除表结构 + parameters: + - description: tableId + in: path + name: tableId + required: true + type: integer + responses: + "200": + description: '{"code": -1, "message": "删除失败"}' + schema: + type: string + summary: 删除表结构 + tags: + - 工具 / 生成工具 + get: + description: 获取JSON + parameters: + - description: configKey + in: path + name: configKey + required: true + type: integer + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 获取配置 + tags: + - 工具 / 生成工具 + /api/v1/sys/tables/page: + get: + description: 生成表分页列表 + parameters: + - description: tableName / 数据表名称 + in: query + name: tableName + type: string + - description: pageSize / 页条数 + in: query + name: pageSize + type: integer + - description: pageIndex / 页码 + in: query + name: pageIndex + type: integer + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + summary: 分页列表数据 + tags: + - 工具 / 生成工具 + /api/v1/user/avatar: + post: + consumes: + - multipart/form-data + description: 获取JSON + parameters: + - description: file + in: formData + name: file + required: true + type: file + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 修改头像 + tags: + - 个人中心 + /api/v1/user/profile: + get: + description: 获取JSON + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 获取个人中心用户 + tags: + - 个人中心 + /api/v1/user/pwd/reset: + put: + consumes: + - application/json + description: 获取JSON + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.ResetSysUserPwdReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 重置用户密码 + tags: + - 用户 + /api/v1/user/pwd/set: + put: + consumes: + - application/json + description: 获取JSON + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.PassWord' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 修改密码 + tags: + - 用户 + /api/v1/user/status: + put: + consumes: + - application/json + description: 获取JSON + parameters: + - description: body + in: body + name: data + required: true + schema: + $ref: '#/definitions/dto.UpdateSysUserStatusReq' + responses: + "200": + description: '{"code": 200, "data": [...]}' + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: 修改用户状态 + tags: + - 用户 + /logout: + post: + consumes: + - application/json + description: 获取token + responses: + "200": + description: '{"code": 200, "msg": "成功退出系统" }' + schema: + type: string + security: + - Bearer: [] + summary: 退出登录 +securityDefinitions: + Bearer: + in: header + name: Authorization + type: apiKey +swagger: "2.0" diff --git a/examples/run.go b/examples/run.go new file mode 100644 index 0000000..2bb61e2 --- /dev/null +++ b/examples/run.go @@ -0,0 +1,28 @@ +// +build examples + +package main + +import ( + "github.com/go-admin-team/go-admin-core/sdk" + "log" + + "github.com/gin-gonic/gin" + "gorm.io/gorm" + + myCasbin "github.com/go-admin-team/go-admin-core/sdk/pkg/casbin" + "gorm.io/driver/mysql" +) + +func main() { + db, err := gorm.Open(mysql.Open("root:123456@tcp/inmg?charset=utf8&parseTime=True&loc=Local"), &gorm.Config{}) + if err != nil { + panic(err) + } + syncEnforce := myCasbin.Setup(db, "sys_") + sdk.Runtime.SetDb("*", db) + sdk.Runtime.SetCasbin("*", syncEnforce) + + e := gin.Default() + sdk.Runtime.SetEngine(e) + log.Fatal(e.Run(":8000")) +} diff --git a/go-admin-db.db b/go-admin-db.db new file mode 100644 index 0000000000000000000000000000000000000000..fe73e037485b8b47f69bed124e4162c331c895cb GIT binary patch literal 348160 zcmeFa349yJdH25n4-h1Ql`KoNEX#r4@Bv2|ESY&A|uh*(iDK>!9o zN^E+CPhSRPzAt;TgQJ3Bnu1pWs2a;LY$*0FM>hQF32Ntu4{uX zkZaRMUbuMB(CQ)mc0=y`LR-h>5br`$kyq}bJ(V8qyt>h97gUK=4|C_wuM??;O^;Np z8>x0dl}Pn4_u)MYY#qy&TkehVr_)I4@i;3jk^&7~qzGr}`wxv!yQ8Vr$Ma&*~x#@77I#zo7nU|XOy3!117R+cLjeF<0)QJrou{?$=&7TJ3@=vFc&&{Jc7m zYSi>d+v-NDT~H-bJj?t)>BNgf=aW^oJZf~{HS7ZyJM}*9UE3z1eS97TT{^M8-!Xl!+x{g(^zsO z7iU$lgn+f5wxZQ;>sYnQQta1KK?^jU*=$OW6{fHikSG&!E)Vsu3Mrn=ruGeD6V}j} zHJ2y#3b(sxx7s=aYb?b+Q{Een=XWO4gE?q?V04C`4T_lU8`s~kUG4X&-9E#4*y=31 z)U`T`Ca7z|*EJz^P58Se0$mfqu8C0BM7V1r;x1lmv30CjW4YrR4T#}}WjC{$pzzM4 zE*d+KrYy-~RtZh`v?ED7@@q!{?I@@ng|wrvb`(*LkS+A0*F?ctv>KfAI~>@no`(+o zBLYN#2oM1xKm>>Y5g-CYfCvx)B0vPrRRXQ}VATIVSCf~XiwF<_B0vO)01+SpM1Tko z0U|&IhyWvi^Z!kb|0ReIh%236a9#t4^p6M-0U|&IhyW2F0z`la5CI}U1kM%$*;Y}o zFYUB+taRJ$_TFB>>+?!p$>%-w#v7%3K0f`0Lz8bDYltTc;~6OsiTeFgREkF7jfKor z%+mv}1^Rt{soNLomI5v*))NZ%1R|c86yV-r2ysb~9v}P{^@MzZlpSJRvaAJSwCFL$ zyrmP*Og?_!>4PuUkIXvj*g~FIERbrc7F*Oi{r0h`lb`>MW0S%zztj_ydIB*|Bp6BA zSZsFlvqij9PaQ8Eec)Y+EfDJQ`8<*@Hf9lpmX6Lcl2b=MJ9+PeQ!hL)dC!4&1!cG= z81%%#KAit=5~l_6-^E{wKNWunhxCsK5CI}U1c(3;AOb{y2oM1xKm>>Y5jaZ;G&Ts9 zR&?y>w4h^aXb|k``~Tus#mCRmM&qwA&YRNw6Zr*W;5s5x-9g2iEwauz<-Kx8wSM zJFfq?+o}J5E~Yj;6A>T+M1Tko0U|&IhyW2F0z`la{Js*X)&FPv|F?fv5a&A&IsV46 z6AtMg5g-CYfCvx)B0vO)01+SpMBwZoa9mj4S+t3w!`{-{TeLJe;CE8_DNMa`a_Z!h zsmw?wzb`)+&t?blcz2%f?<3)8+OdE@J=>5gwD>8SwiX9eN!*Itcpm-$7D5% zsS{669lMhYt%%Cs;|qIyVR+@6Z_e+Jx+HiBJlf+AdHlg>G1%Y~Is?l^vABxu!hh;Z zFHAml^weu7Pe1c0MwUz`e^To#Z@j_fX|`l^0BpyHbX#a1gIiYykz9ZYrU z$R|oK+*^9-&Z(!0sCqmv=RkV0usNR3@5$s6l0Og(g?IR-j=wm0g3y+7rPhweg2O%zwCG}n_?%v@r>q~lM`^- z>63>vpM7#FmDyAGaruWE0zDyLj}-6#A8r00cK+wz0605}IjJN9M1Tko0U|&IhyW2F z0z`la5CI}U1S$zMHndop&}qb#01fC^Y5jjCC-NZzM1Tko0U|&IhyW2F0z`la5CI}^ zHWR=OKlK0Y)c-%5Q<1b20U|&IhyW2F0z`la5CI}U1c(3;s867=LBRgMfc<{~=l=zq z{}=4|{=YD<{>Y5g-CYfC!x31n~WT>i?hJX-Mjc01+Sp zM1Tko0U|&IhyW2F0z`la%tV0t|1%Mya3VkihyW2F0z`la5CI}U1c(3;AOdGU0qXys z{b@)~Km>>Y5g-CYfCvx)B0vO)01+SpL|`TY^#1=$geaT{5CI}U1c(3;AOb{y2oM1x zKm>@u*-wDx|Ihw3q$eN(M1Tko0U|&IhyW2F0z`la5CI}E69I?gv>;jpK@2(nsQrm{ zPurigZL|N_{vmsF%l%Eqo0c_xs?l!|@PEQx4Yrx?#=`fUXY06frKPwynNG-ilZm~9 z`F;7p;Y@0LES(=5&nDspd2r`GgXe;NxNzTGuh}xtw{5_+e&gDKn_NRRqZx8-+UOcG zL^iZ~NYgOnzSG-b>sYzc@{!I$d}m5FoM$*Zub;=Yt?%mV2h2Bftsde}HkeEdxsvIE zJR;}1hS<%_Udn0d_?SH8D#&{aUFwy?nXxfBT`2P{?8|B=j${VQe(p-jDTt8Y=azgX zJ!tYt<_EK*YB2mrriXK~F%t00$+wOtbFy|9c3NJ}X+pq5P9%*#Q^~yX=dI&%Zl4+p z`(cu~yD*kAc_fm<1(QcUgRyDUjJHSm>G3f+mmKaI(xqx%`SGlrQ*xEz%<()XW2L_V zfOd;ynm?`P!Jk(9sXU(c8wkd88r5B+gFKauDQfZ@98Sgad6kbjC>tLhjgM#v41uZm zPC3Q03{O9lNWa2PV$NJcN|O5Qb{Hs)p4yISl74x`faXV@l+m)<8W>qjH+Tb zw7^1c9Ky^t1S~9+;`m^GID^JsGlbwDXEZ>n$rCV`eNvf`>Fi_Eqh zb};Pv-Swl^O53791KVP10=j?c|Ec^bmKt-PX|y zPd2~u$#jFD#@19PHvR01=nO&bJFacBbu3+KIW(;0RwSUt&{&yM86e1~44^5qDrVi} z$Ii;e(Wvr@gn1YZeR&I2jwfWj9@?ErYjp=S4wEVMKKVktFm5#7dWvaQ(9jLh{odvL zsA6!tp@;S54XZ2yOS$~5sU&p5pjOSW->io=mK@2&SrsfHVC^UN`VM!jT4gErYpI|G zn$B!CrN;_W*a}FL2|1UC`d5V%&t_Bm2C)fiXv~_+lX`{QU9?+m9f38LVxKAR4af64 zlj*@6G(Ipo!_Njq%=V4zZ`iK(6SZ!lei`-;%Pw`T&Y}tGn(%c^NL>^Du8Ba`M6hcj z)HMmtQYq?|D%0x+k|kk?WOk1;eyJ4jW1fP z{V+nb+%!0YvkmD%aLwbMn)fBj&`8j7KZ{&h@$+W3=CbGPt2y` zg?b zQjF`B_*}L+9L*oRd_tM4EcZ1e$8S2#%nZTk#nooZSV_>*1970wlIpC@C+o1$A2Pgl z8rH8G_sguU^8Y=I*>v z%SsrT8p8#ZnTY{{+{84QvJ~?%&bpa$RTAcs)x2ZOVR#Jn6rZ?bx2T=xV6E6#GH;xG zsx}>%&cFoH@NUT5+JcFlFkzd31s!8M)tF$(Octj7^!0jWQ-l-Ad=eS}>gjCaT3hp{ ztp-`)TY(EjaPs-LK1r=6fZKiBg|?19SgN_yWZ~4MntF0$sw%!6)w53JHG1w*!k}>I zcN}u>SzK?KsD{Q6^}_m5YnN1uSr3GnP)qyoWUVPi%-5Rkztq-I*<6M-K)HBjb6N9V zRsH$3aJ^d6321?4)3o2s1?;(?ULt7b#gGUKs*6z5U%Nz?peMf`=sw)Anl+d29?;B( zCKY4Tesn7F8P?uvVHI_gVmHjKPHnlFd07cxCt?aTw0e2ym<-F#3=2-UFRn&~hAvbR z)k2xNLMEpybXB$ROEFMc;bsmnEIcp=uq(!Mu(Ck)=k0ptpUmpsh6qxb^47i~5DZ_u zq8VSUKfz+CXxXzxbvZddo`NN)W=Z8Mag+`Sn7H(?I?u0O!3AOWW)POaqA^uNl$Ahp zSeK)hZG9bup4Buza|4_;2llV3Ru0uJ(|=93)zn1T|DO5+w8y|Qq3K##y$ovM`XYP1 z6l#HB2(-HnxoQ5taxjB@hyW2F0z`la5CI}U1c(3;AOb{y2%KvKn&5$~;?MB0Hi`cx z{><^-_Aj-IZNsf^w9dC@TfW%RV|%9gN6oi2eX*&r@nEB+;dbk=7 zP)YFQs4pT^CW0l$oHcy7IHXDN8WUsk;g?I#JW*dluuK9hdziBT$PR;=f@;~}=;NjP z9;%idB*+c{UBL#J^ir}zV9wb=D1J~AQ7t9vitv|-U@0+Y4f~59&?HF4lu&YHT?tZ| z1l&Mj&I&$UyjfFFEicqn;44!Ad11~1ik{+4i-aYe9f3~K5wW&7u7m=??9(O~uD?Dr zGWp&k{3);H;$5b!{912Sbhm|hZOGDES7SE9^BbN_!?hN1PT$4-{sdWdTWnaOlA4eNLe zN|OL*^bEHaw=NPEbS_x9RD=ql#j#wi6d*<}ck0B`Q^)RvXuSA; ztPp_j1}po;qTD=ZZqgNtgf*Q@yi3FdSm=AzI00Kfdt;eHD;>RK@}ZY`{P{ic5!lnk zK#afJ%mjt~{gaP8r6o7N2Sa78yntz5H)qWYFK3xkS}HC;PM53JdMg(;^~%YqlTS|G z|6J+lCr8GU3E7*FC%OxnOe*hHwfnqb_)kKumsJVY)307#<_lpx3$>gt;0cC9w_UbK z=;&OwyaQylv^W+6N>-h2!>m_bd_?b}n0~DEF$$F`g0=%d=fov8+)Ptya=l4M;~G`RLe{ENlZLnO zXV4K?w|UdnG9l2kYiONK4l&8-Y~WU6aiuxKiCP3M_%Qca7}_CE3=rM{I&QC@h9Rxi&NtF#qWsU62C5fRs2iw zPsO*zH^eW9FNuF7ep38|_=xy`c&~U^+%N7E^WvB|BF4q{i`&Ib;(D=Pyj+ZklDJ0f z6rntd3q*%#6D`hPJAdwc$9dZM1Lt>~-*o=1^RJwL=6u`vy7Lw1XPhrMpLTxS`H=Id z^KR!skU{^501+SpM1Tko0U|&IhyW2F0z}|kB+%3#SgjW`_af#lX6^#!&S&mCbS>Xx z?*C-&*O>cN=Kc+H|C+gf#ast-TbSF-+$MB|Uo-dLnES8H{S|Y6$=qKs_vg(08FT-I zxj$v@Pni2-=Dx$+A2Iib%>8HP{u6Wmk-4XtJI&lF=1wxV#N1QN{Q+~o&)k1t?)RAc z_ssn+bHBsfzhmyVnEMUpe!a0luv~%8<>*|7PA@t==)};8q7y_XfQ|>9ZgjfPS%Xdk zI#%lcpNj>Ho{0z$0U|&IhyW2F0z`la5CJ0a-;6+0gPryN!G-=mxX}Lx7yAF;LjNCJ z=>OYU{~uiF|APzte{iAy4=(io!G-=mxX}Lx7yAF;LjNCJ=>LNY{eL^_|APzte{iAy z4=(io!G-=mxX}Lx7yAF;LjNCJ=>LNY{eN(w{|_$o|G|a+Ke*8U2N(MP;6nc&T9sB=w?El-b|8K|sza9JkcI^M#vHx$!{=Xgj|90&E+p+&| z$Ns+^`~UV?^#9ele`T(p&(^b50p+U!ezR2oH2?qKtZR@@vccgwMT;`Cv}B zDlWgIUC2o57c78x_gh*TcUTRvO*t%mYyc45tHXsFD zQmiKw>+$(Lflx$yt0Lfnw@yL1Pg2zi{OA zfsakUeOEFuegCVaqYoQpX8HNE5h;bLiVTE`!4(dnXxkK-mCDtZ!V7@g@Y4ovAX-p= zdPWxC#;eWNA5mVcgpC{w zY@@M2amDg>;nvWb_Jyd% zHW~^PJ6(_g`sb8M`{6_6wd9?C`t_-gpD;_z<}$a)@CNJ58C8k~s_K;dMc1-+;X_jI ztYEIb6mYWCUwd_bCN(~mz8>C^)FcDW(ve5tKR8g80!C%~UvCy(Mz5XTQc&MB!;s#Q zh*Z4z;&x%56q~a|mRU^-d74)!WZ5x4gFs&_T8&{O;46BUwhP1K-Sq`}pv2&trC50U zN}(}se{$-zdnfO`d-ACVpy=>-K_@?P@bqKHx~K2@RO!UW_zy!l!WUBUHnoxZLON38 zUMK;7vGt;MVMk~ViXoBto3zzU5_>zgCz-fG=TG1evRLcFtc_V_kK zPSOOGr6y3RB|`GV44JHqi2uTN;r9OPW+6g(y<9PZ>g(Zssgza__-ovgPrVNBoWlpu z&DI-V9q(o@ooBN6MHYCOF9oHzRx(N+D7#w5D-*qZF_0VRpPOiqsR(2*#q$Im2HR7q z)9`XU8mHP|BegZozo1=6O5V9?R8rWevn-u~B2!meQ#cx|#cgp1aO<0)-eUz8qQRHz zF|jpnQ=dIqdg9(11p#&8KI7gxr9tw9YxD9gY8OVf&oU#b+Ia3$whv(PxM`_f4YM5# zP$+C*GOKJDit5?WV4wrhXmS3+IV7Pw`6u!PgmHh0K)1gs=s;-;g^C%L2MTWm$_$9 zvp$`W_m;^qGvP971Mvr|R#H+pRy?l_fP^Y)(HVf0?mS#N@p?@ruoDVw?hZ|m+NNLf z_(J-gT!x(EgIDHlt-z&orc|on!c|qEQPkAN15s)wK~oa(#KPg?0z2ZVXa~)N=g6Iq zb!+2+t?x%NxqbEc_@Gv*uF4-SwzMFhz+Cf9iOH(uqsXZR$mfYh^d^G=P&67SF14Y} zoT1f?HWRlzio+g0ip@0com3MP+eInPHX*8$l|Y|g?-hhye%RhEhCQxOELvRHj7De{ zHr=RCF+xU-71VTXwYfzidbukzL`$1y$qkUPZJQKs#(kS=bAyeMlIfYbMf{)-df8iw zBDgnX!MW~QaNc_fuK(ZXI6Tw)|1XPwEIuzjEj|uA0DM%uPdp+X6h91m02IWGc#9~D zL$C|L`@|c>>&0utt6?92s2C7EqFcNKb^^FiTqw>H+r(zr3*g_KzjXf8`9tS4>;~{% z=eM2TaDL7C71$5p%g&R|FFHT#{50$c@Qm{l&PSaOI`4-)0S-C$J8yH2JG0JF=Pqa5 zd9(9I=N9J%=e5p$=M~PFGvMrYu5vDSE^#h&icY(;!SR0_zjXY>@lTGDv`_cI@I=7?qhv<9=o!ijaht6Jf#?dLD zlSe0q&aLQV(aE5bMrRD26gs2m+=5OLo!#h+ptB1d8J##fL+A{mb2B>cN9PaF*@4bY z=-i0T`_S2r&K7iTKxZ>L*Q2u@oomrqi%vf}SEF+!I4bXKFY3Z3_$(}~U{=&VF%1v<;oaiOyeor}>~iq1voEJ5c&bQYs?0XiM% zEJ9}?I`hyG(P=}c6&*V|E$G>Y5jf`wuwC7u{}21r!~8$EF#iuO z%>RQ6^Z($&{6Dxb{|_$A|APzj|KP&>Ke#ae4=&9AgA4Qj;KKYrxG?_@F3kUf3-kZr z!u&tDF#iuO%>RQ6^Z($&{6Dxb{|_$A|APzj|KP&>Ke#ae4=&9AgA4Qj;KKaBfb;(X z&i@NI|1aSDzku`q0?z*nIR7u;{J((n{{qhc3poET;QYUU^Zx?Q{|h+(FW~&Yfc<{~ z=l=zq{}*unU%>f)0q6e(oc|Ya{$IfPe*x$J1)TpEaQf)0q6e(oc|Ya{$IfPe*x$J1)TpEaQf)0q6e(oc|Ya{$IfPe*x$J1)TpEaQg@)8a1igRstjBdqej62A546IY8a@d8-g-y#amUpapa>-xXv{Fd{7I{yMz^uOkO z+4-XLDOk&Y%z4Clz_}Mz@$YsH!3zG3&H?9Tuy+4aSh;_JbDp!sDL8)R_%X!^}>PhE8%Wi4<3924q_OzKsaKH;=z33E?Wc- z=D|T2&-sCHpgGiFwFv*Tzd4A1|Ng_x0sQ;R+nfFPcj~rg3ID#cui1xx|7CBp7yte` z-|WG^|C(#=#=rlVZtlXr-x+IOgMWXKYQ7Zzet)#t&Hmofyc+*bjx?{rzdzd5{2u)K zQ@Obl{#qB@+qV+BGlZ0Kfmv7Uc~--nisOa z-OcCY-+$<8S^%d7yPD6#pWkse&&R*tUDZ4fpa)>YMTFqMs%9sU=w zEoo|l;OLU(R{Z(T7dF}9XU~PrE%@`Ni<@ou_s17BHG_BW1`6=gS@lTz<7Ed}~aqbXTIlm`f?7Y)?h2zK0QSlw;P8b1jI^T3QI{wZv`5R_( zx||3Q0U|&IhyW2F0z`la5CI}^))Q!Hv{)_Bd+%ol(0#v}9YFuRPw~0`Ds})p_$%1~ zbm6bCH(H_Z3w`*@`4M#DFJnj8i|^$}(2eimq0oE-+wsB4}N)jfFDfV=I00R?34JxzwGt#gJ0*p{NP`69)9qT>27}Tov|){@Qc(M ze(?R#OO=CL-27m2WHmqd(XLhe;HUC?*a7tIJGsyI{@@aRaC*l|e(-lUt>6bgzi~M~ zC~a}^gCE|oj34}D^Tqt&A1_K93)Kch!8BM9|@%$4&{X5|xXWI{CrmMGk&&YDqgg zCAy@Id;If-t<0n6LOb{P>EafC@Z$??ECjm#+~Y?bP0BS38~HU08@R{6HCt_vmUig> z>Y5g-CYfCvx)B0vO)Kpg@&|4;q@I)EsM2oM1xKm>>Y z5g-CYfCvx)B0vO)z&SvG`v2!ZBGMxe0U|&IhyW2F0z`la5CI}U1c(3;n1KMT|DOR6 z1rq@xKm>>Y5g-CYfCvx)B0vO)01-F`2+;ihIgp6-2thz208uazAOb{y2oM1xKm>>Y5g-CYfCvzQbASM?|33#3ksg5v5CI}U1c(3; zAOb{y2oM1xKm>@u3la>0?<)`?trlW%n5mi(6Y_TMxf*yX!1>P_S~2X6X{2zIkoaH=Ay0_=hI1^-rza z9Pc>N?LQPg(4K0WYTE@D&E{X*2Q9zsShdP>Fkgu8Ov(9u`N2eTxG-4Qmo@*myno9; z-?jnQw!W*cA8-wsP8@Qr9%5G|6GN_Kx*(6pxi0RLj*rPhu7bR`pm^YoRS$@>FrGJD zl9R{cxluKEI48#o^5D*WhBL;qi3&e{UScp_7;<4~Avq>@4e>L}eG_s@F34rRo42gr z(6?oW>$-s*h9_~mf#Ls-EwvOK$#g>An@sE-#K+EN@`XW7o9Yu)_^jW!cHk!0Q1z3C zT$?s>c6gJa)kE5ChTNkuTStw^w1-wBi`0osJGmkvu+nNCQJEnFuy z{p^b93__@H*Rwc?HXk{UW-KgHRM{iY0JR+Yc?unM!k{SwPj%4z?OlH{R3Nh zM#m7y=-LT0-yfxv-(QngaesF9YF)oO7H;m?u*xE^oSnZll>`$KA1`FsZ|wmX+(F5N zH#i!sRs@-Jt)Qw`_^THR^T~RdP%vn>f$|=x8JSj4)ySkek!dGaM5c$h)BbAZor%?p zsT!NFPHg(w710@j+;^;(czKsiSz3+3TRkIJ&%;cmvAnD0nb#^TcvOZ;!tgt9wg9_Q z@ewWDRL8J-e#n&`ACq&*VW^|xh4^58IHOlmdXniDMJKEK@$<@RmNTz~*keJ-b-PD> z)iTO>Ue1|oA@uQ7Pdf9-ddi`HSuNzP8JYIbn2LC1cb&+zlPeXkwOq->>X}K6 zt*cIK`q>rH8G_sgw|BE#dFSm~uEfaH7%r{Ml?)JAR;I~lN0|@LloRpX@a}kSbvWqm z8p_7=`8}B&w1ZS{$sYy(baHrf(0o1*$nMUhq2kicmf&PH?Oi*QBT$QV4dvr0sL<4N z{Gkw>6rX^snk)Cs%X`bcAipP5x+jk|A!iG$Vo;+{t0OH=wJm0jRV{m}FFy0{sD!9# z;&#WnW@Yl(GwUWFf4ZTK+;AQ?l=ok4>*!x)DK0m)h_trwpq6bhw`ks1RnL@KxPFlv+(m1jtz!Tbbk6(Hs`?bPq&7*oVkQaNWz`kv z!H^ye3u+_-GtJtmngH~^td0QlWn}^|&};zrUtW^{yOWk;CIP)O3D7R9E1C48Gm`}Uy6PI#@M7B<)*LOCHAk_$V2sQ<;g8iyjD{|u7FN9~XC=^RMr$=k z)f3(B{g+lt52&AW@xfGP#9Rex-m9v^(8Bf0bQW4*S%z@e7oa5_veEAGo|yz_msJ;_ z2fK0ozeW6a0sf>Y5g-CY;Orx?#Ucu8#17a?(C%RS z2u{6na_Z!hQzxFDI(BF2fk*vpzoCka{@DJ1fg0Yl{{QUD2c(z?5CI}U1c(3;AOb{y z2oM1xKm>@uTnNzn|8t>5=Mn)TKm>>Y5g-CYfCvx)B0vO)01-Gl3DEohXJ@*RY9c@c zhyW2F0z`la5CI}U1c(3;AOdqCpuYbv%$v(qbS@Df0z`la5CI}U1c(3;AOb{y2oM1x zaJCV^_y4K?f3~F>=_LY0fCvx)B0vO)01+SpM1Tko0U|Ir0=WNwgY#R0_>35VKlG0X z5CI}U1c(3;AOb{y2oM1xKm>@uSw-Lj4ei331s2O1wo(4+=N~S;_L=Fok4+zYu5{wj z{!N=2tdn23clxD=O0PaQ_2Rvy*N)WKAHRlo(%LRW;Pw&2?I-U!F!}gPlXt%`{q#pL zl5Lx;RvvL#NR4~e@V?oCPtsy~5>Y5g-CYfCvx)B0vO)01-GR2sAbbmIidJ>i+-K|34=ZmL7r#5CI}U1c(3;AOb{y z2oM1xKm>?@fk0z}9sB=w?El;CH2-fvLx)6w2oM1xKm>>Y5g-CYfCvx)B0vPr83N}1 zKfeFJykWZ_J|_B|-*o<=bBW`1$Bpg3YJaRf-1hah(YD6c=UcC}f8YLx_6u8HYk8mT zXSR>pe9d2N-qrLUO^-JD8^6}Lx6$7465N9R5dk8A1a4YBU$8G0C5OXdhyU!oy~5P< z#i`>j`t$qpgTtA0K~5J2^M!a}JYVr%PSEFx217NxZ*t8STFiHz{LCjyue~Pyrgt7& z26tXFe-&u9IQUyr)AzqxI{NVGPkm(irQ+06MTx1;WaZpoVP96ZmIYTR4n#aLDOkgM z`^ESmN^~62=>rE!cfBF8C(&c6aeWQ%_)^1dJ30BsPL|$!Nb(^d{kBugck;pePQCSb zjeFJbPF%#2z{^1KC`!+McKY+rG2!V zo+sIJm}B7qXA;Y<3n7+HktaHTmdV!+PyNvwlMlT-dEbecnVAxF2F!LXu83#q_>-Xf z)X7gm&Wf7j;X!ATHbWOMYR2a&z4-=YtcW=V?s-NrbX3Oh(wn8j&xOlkV4i0b!=kD& z-1SDNGKRa}IHMRAR>UxQ|B=a091NOc;GSm`!}%34l#V=g`mtvN<`}r=8O5-mB8F3M zpO`%UdYO^po@W%pc@;5CKKyd&nJ3B&6!$!n7!vbY3?@r*_?6R-d`2u9Shb;e`}|V3FVrms zTvDtj6z-{8Tioodxclh?ADep8WOLcwxpxhtTEkm*;N2G+t;WfBu6B%Oi7}efCm)?Y@$A}xb$#2f-)4@72c1bg z@iqp_ZLFY*k3;K&Wh;CV-tw@PnD3dScD%JB3PYYUL~-UB>H~I&Vu85a&>krrdwwHA z+9&4+(-|ct6i&yUuR*4E6?choxCQ+q0z`la5CI}U1c(3;AOb{y2oM1x z@Ow!BU$S40jtiY-=v<7>QgkjtX9+qNqO%yC3()C6XAwFJ(K#QT1?ZfI&U|#{p(CQ> zM8|>Y5g-CYfCvx)B0vO) z01OZX|8K|sza9JkcI^M#vHx$!{=Xgj|90&E+p+&|$Ns+^`~P9sB=w?El-b|8K|sza9JkcI^M#vHx$!{=Xgj|90&E+p+&|$Ns+^`~P3Km>>Y5g-CYfCvx)B0vQGiwWG+)+TgH7QQP^>CVHY z6R-1^^zrR<^X@^`inoVx`yeS$!#mjuclKH&_O3PGDnY-qc~covnNYW+=~yP@55sZIg@CTEruuJdo$=yG@LPRZo#+w;h|>|)rbwE zT4RQ%J&|#T3k4kuJClgyW&^rYCr_5{d7AG7f#~#|D2yRz63wnAh{mlv55Jj?&aj7r zG3ZR<+1Uv3ELY;;Nd)^Tz-A5=n=NqfGl@fPFd*Zb9q7-ZZ-!tDIg@A-R*0rkeU#%b zP9AxcZ-0P~qHQbyTWx3oXA;XT7KlYsV_`dyl-@j0I{XU8QuWP$9(*Qo;rst>;#X?C z|NmcX=;-!DfCvx)B0vO)01+SpM1Tko0U|&Ih`<~P;A(?2TmMh}|2d+j(}@5PAOb{y z2oM1xKm>>Y5g-CYfC&7~2;jbcXSV+z_5XioiAE6<0U|&IhyW2F0z`la5CI}U1c(3; zm?MERoBzl6|E=O;LA)0n`bPwa01+SpM1Tko0U|&IhyW2F0z}~VjX>5qU+7$7>0G(k zZnwAe_6l};>8`gXA9{K63-?aH^w8RYb$#2f-)8lBL#|7e{|)Sok7ZMGep6a59lZli zongm}faLNAdP1Qd*hs_gm+}^j(cT$>jX#taC+~l*bo7&^7>yC`E)=poUT-Qh98c}e zV+ZVL{qIKN7COtSK_ZGT_ z;@NC!-(Vp*CJ(t1@q&y;U7NS8-_W;ZhwHk59fm91ZeV=Rj(|l-rW5ks{H>{EK^}~c z7c%VkV3i05r7E7A;Wqu4T(Ql~9UE57?sn!IZ7y0j**aFOvK0FZ@p3?>D9un-n8H>V z9_~zV-11&qM{J3u=wQ#EOza&j>>NzUV;OK#azRcE#tVwidL?bvZ(KWYlWVB@xkIi^ z8(l-n6+^3s^t%kXN7maqA`q9oBCg?_4CywwbDwhIwY8(tPA!i~4{(oMTPvdREM^cr zqHAhLq@7wGksjbK-f)erW62WB9s5`kD(aO#>&$ssWdaG7Oboe_>4H2W=emZ{am=?9 z@!at4cy6`ikGi{t__H8;LyjKe5tsWK2;_wHwLJjDYd-s`hgyM@94e^?C1$ywD!EGG=9?50Kv#QZUkHWqzWF0Lh z4d=kJ%6qdpId3$N$@D~KR30qEb0ae3C&gywM)KznN)Jvm|9QHHmD_-$@{A6 zNnhnMJp*Wgkh8VB4!MigK3m5CDCn%Az+9HJyIeVw1pT_|8Vup?{a4kepp_33g)3%~ zpj}p7fgbF>{)c4CJ8+=NzkvWuE7xQK4|Y{ zdGzoN<~)i5OtHplOWY-={z@Y;N~x4>UcN8XKdS0$J#C zn@a=wM5|{4^T~ShqrW-(kH%_7rsYvJ`beF~w390$(?i_2|DRR-CENcGyAAY@2oM1x zKm>>Y5g-CYfCvx)B0vO)01-H62;j>C)`kYVo%;XhOq$Yz5CI}U1c(3;AOb{y2oM1x zKm>>Y5hy1>{r_?z^qU9}0U|&IhyW2F0z`la5CI}U1c<=7M*u$-0Q3KX9pC>K=AC;F zNKZrrhyW2F0z`la5CI}U1c(3;AOb{y2>Y z5g-CY;9Mj?{r__@Rq2_C01+SpM1Tko0U|&IhyW2F0z`lam>Y5jYnK;QRlJh0h7%kn=B`s~w+k*xGMzn{Ja^zuDSvKi2ZImLc1l zHe2%@O+RnyZ+xcVKO1hee$Mi1%lqJx-_gI~@=Mxr3)=DmeXCYASGBd78Iec9x;%(`Ss?%p*vb^OW6Bgf*|Wa+i%Cm+7+)X6WxrAhCE z7o6$sVV~VxpV+!%>oo)0{64?b?F)5F0hbi(3B`JReor72;of2N_WOE5 zfu3O06N^NOD^|7(a^JwLHEzzy6G?fGChzn!ho)aRa{9o>rr*9RnV7!+)zZ<2jWXd= z%6R^4L`tEmA_JjfaD_uC+BQXIrE>M9TleL+;n#BAK(wI#$ZyNZNVRnMm8n-wPCxzP z}%vAkWlwfD+dsaDc| zgPb1kOD7;3fK;xq^u~jrmdh(0d3o*CCV`p6&RMYa`>SSvXedzZbU_B_pHn97hflQD zl6U&)*QY*y!YnbH%iJOl7iOVTiUz8}l>9~4vUcG^Qtzx_uD%p-veaLDb$=!`K9;^7 zKK80f2AriMkHCL$pehB7!|cqwHyaR_rlxME<(PLjx^$uB(P0A zL7yiQ@E2PzY8Q5d=Aal7naiwhl2DAdCz-fBCok0>)S6fp!8my&haR+ego1xxg z1s0;&wl6DVVr$%{K6|qC#Jx2N0_wu=W7jJUk|$i7mv2$KFtUA?8Bx{7b05dW<#E$e zyBfwcWkS1WnGHixJ&6sCoj^2NoWF1mNvujXB{A1rC5aJb?IaHQ^|nn}d2XB6E_}c% zm1n!*%-C24T6x1*^zxqfK^v-%9eZ|-r-!9mGCQlMD|~Mo!s;igzj_Vfmx4t>Y!?QX zxo1$bKAn*FmdP82l87f34i^{L5l=-sXeK;I?u4vc z8&A9-k7RQD>g5|B)JoM=`NPGQ7UUC{YrZKlS(SVgIkf=!Jkf~WWYCf-;)zBB#icg1 znKQJy(PnPS%DMRUnGwZiPCj_wska`VeB`;(+mF-)1x5%i>P}@w>Z6MK^}`44_+^8V*)%STHw8{t)KJ_wh>k>dGRLQ^XcDo=a!KoXj? z?RiLeXaa7|v7sSgtKW^P49lZlaJ=8J-cj|_^60WVI&tIj| zj(K9SV6pYGS#};bXY#DOi!JBRJ#y-;`>NajESy%)><2u-fIfavW?rqmXiH|%c~r%y z?M^1hZ0u1;?Gg}(>UB?3nx!M_NhqCU++Prdavw9*V^9u=#1n(b3W!g~HF%iq?nSynul1g!DEM=g0Gn2Q-ot5wMS z9&9ME*(aE0Dig704YXiJ*UX$Rj40Qy-HMrk%_%8rUV6Rs#__3-9pdPc3CIXjCl8?& zedEc}n+FXP#~>||iG1xM6^>}e-v?Eazb63GWqwb{=PRzb6uM~JwRWPhO429p(DobE zB0eqea($rd^wVF2@#xa4&!76z3#zAP-BBYVts^p^BQ?~Up$N2Y+_NnAsz?;aa$NOt zk7DYV`%vwHN@+C|mG@Vz#A_2X6%{@X$OURs47~8yN?yFa{-87@XHY8`N-9Ts{4iD> ziWIG@W?3*)fJ*(tHJS?s!mC{{f-$`fT~;vK-UA|}SriPlX}=!2Z;+C_V^^(NKOz_E zb@BY3U{F_M$Wy*>sJOTj%=emEv=R#P7?_GQjD-~B{&=wJJN>DTOutlwIaPCi z1B5B3*3R$2DxDyx=b#Wc8vlpTAzayD^$5Rg`Ci+S)_cWK;mSs5!_AH^>*v~&mKU8@ zwtd>3Z8_hz!}-1D|ED?J^kUP}hSwW{)|ad=3B^!gk+76JmWAf448%?Tfjja8JP37_^%LYv3HPMVQK9)ZJpzjah>0=DC6EX5Bho=uk2HiHZXz!FX+jV0JDO+&Wjmfrwub+;G_F5KcSDz~#el;OabhE_|Uj4}D4f{3#*z4o_pv%9S zsql6Cg58qjl0smgaTLwR#we;_^T7xuSFzuUB9<>+h$8Gv1WWBcT!FzmoSYW)cwk~H zHvwH?&J0lL0?IH*Jt0W9kS83$-b^(C5nqH0XuDDE%tW6*N6b=0$r83r!uthBr`xeo zguKw=aM)SN=oO$(P`sgxqm>-PuOG2v)yn7()-5!6dZ(N-K< zROQ|q-i3S5s^oQklg>_! z6jAIz(O&$ZrY2xiV{C8KQsXaEbL+UA+c#G+!B{k^6tkA%2Q)Eg%#|FlK{)mHiOJ)y z*GD6jiIEe@!ko24q6!%M4~5o6!jjI8KrvFhi63=}j)=9zaV6wSW-M_60>=4`lMeY& z%$0f>!s!q;s*i==FF_JY;eIWrDmP$-N%(rT%UFq;Q-O;3q^SB3#cPY(775HoJ~_GHKbvd0>+b*X>22@HXp44^DKK5zy2ud-723&zwnG6CLB{Thhq)o zjWuq^GI1fZ4r*<|tphh=r3W6Zl2-%XU|=22C}`kW?G7fQp{xR%vEdPjL=-)@6}K)D z7IZFHxKwmFAg?Z0^#BPz*~2Bl<9qS{N(R_qWxp7T&2viFa4aAN6!Y%*uJ8nAPH8FB z-w^rbs;S(%Cq4ob2)qV|QTNi(PmVx0Pc}3m^86GK6o&s;Gwre}!FpoVXkS3J6o!SA z*jj^@hYtpK!y(YsEO?8KZZ)Y`o6Mo2;l+4{qzbLuyuB=?uqZdowT&2*B5Gym?9%iw z8>i~wHf{zz!F8}|)SPpeookqD?Hqvhq)J}yxnhy9rgMoG+7nm>^s0iOcJ626`Mgl_ z;YF@bO*Y-OCR5Wa03- zwFB1=Y#T7=V%~OW;O({I#h0^6uFRr9|L?bFQ7SqN5opi))OM4tc(c|xFf?gGx#XIM1Wn6JuhiEx6x2F=pT54+g?vE(+)Wt>WW?_*HP| z9}yq|M1Tko0U|&IhyW2F0z`la5CJ0aTPNVNHmuqpg+qZbyk!Nm*X*US%FzxO9tta? z9X<l;7V@V5?6S1uBkb}nBA zQ~IVE@~y+WVHhzb8yCSBl4EjrE}kBNmGnw5j3fp_F@2Jn4{*UKHmo8DxO}l5Dbf>& zc#3Vsf;ONO!P%x3WhR~v3-iI(Dg#Pkn8^tm<{OpKRyHVn1smb3F=Aes;yzzArq0B* z6lG0Ll?e_$yIe(1C=BCUF@1asC!~8|d@DNFxs7ljtPXJ5i*Zd$wOK(nZ(L0apz()v zEo>^5fiXXCaQ~JV3?R_jiGy(4NX*w>N??FkE-U< zmawD@=z*AFO^jip_&Rl>xNagu^yg-Yzz2KhoC+~@(7&~~vzi!fYPPPJaG99#ER5gF za~2a(7yW?g*a2!Jx1(EhTn_V^O3~GZ!wr*}RdOkxhs9ECC^j%{mrNHgEbgmzV{K^n zOm7T#@8L-xd}EF#!XJ>-`SHcYy_&jS{jp&Pob5kgeABG%V;c$udu&w43dY>U`Ly}j z_TnBbhv0G^&7AUe4fV~bA-gK(l+&84J(Ysm%7)hBgr?Vr;!|`M^O~N^D^rUvAg_{%LNO>d zhE*uq6dg~m-Z^FNa4Z&$sf5~#IZcr%|M2vxugI_xMN@<+HfKHIsA}=rinnTd%*_Lq zV)gYH7Ncl-AkF41C#cqfMMp8K$>}vF7%%(vFG&!um&smTZQ>!Pjn9&4XX%xiE zJKqVQS`LbO{ejpzm>GpdvbbI=0h7kKJ%C~$VTC8Ilb`jX#;D$eYA>cWNma5?eMttR zh>X}mLd-&Q)&nmDD)WSG#W77!l`K?WkHI8rdLRqUSxz9TrkJCc(&SXhLVU?(trRm@ zL`@FMLUR@*X^RwFi+an>WTKTSgH6C!6BL0gWH5?s+MOGq*c@|D1Uh6&YT1gnXn5G_ zGj5`-MG4uzR8q7I!)}qy=wqjC~!ukSbwMAVp2J6hEK&F|q5?BJSP_Y+x zYf{V=7i)9Wr(!V6ObW{|a~1;&akT<9qKPpqgHW4ib-MxqqfN#>63;Nv^I49W{ggYb z!%~-|*^9e0IV{JhOJR7GRbP(LCZin8G0}_XDkiLs7&w|*gay{a)&_4&W82S~zuFvZ z+S7Qu^{{xe^UKbajzhK&HT+fE&ep$ed8)P9zQ1K~hJCoQ3QoW#0=&`8mQ`8)N+0DhEl@NM z?bLVyA|k>2)N0wipm-aUUEYPnrLkIfMQKkNb~~wJ^OdE%UVq3?jMe45yesvsIn_iF zSO%|kT|9^8EfP9Am$+ehCz}5dP*h*WfvpcYL%zC`FE+xrG!mI%!wO>X;VbI==659E z@`?p&crK@@yi7OCw{T$B4V9+t;B~)^F}oTG3qz{DfYOh!uMwbKx(e3DE)yO7kgyWZ zg1rL1r4KIzWzw)QXm0ZH`(O)=sgFM}dH)NE94wLb;!-{Sx(#eBg{J^NSRv~V$NC|N zy`9s;--JH z1YUxVsRIg&?r6dHfI7N?6|N(W@pZ%-gsaDssRZr=32)~=#cC5Oid6BS8>If;yE{Cd>y(TpP)g;>x(zq=tuW!pWVvWj9 zRa4S$(uupoYNznUq_gdHfK+(Ln>R}Aj~AN`-nd9uym-MX$O8_@a;sFU2X+g_R`_!8 zo#P|A@k+53;V?|?4MwDXqgjIxwyu?rSHtpZsmCAe35IK@XEda}r*uK_Lz+=D3=pY9 zhQ>D)>KZjeQ%N;yytO3E)v87H^_zzlqlti*&H$3}#kZ|W=~DJNVeh^{iG$vuQXch^ z>GMJn*}z|ZGd7jrJ7pogM&8m_EYZ=yN zXq<=UYl0-BAf?H`Ubm8Z^Dhg>G=y`WE;Y%nB-HMeAsa6u+JvQ1$ z+!fSdywUP0rdz5oiOg_Y4Ry-QZQatbAW?0A$ z?K-!TYt-r=GWsAiCzYWE!#-LSDaOn)RQ12wMJHrBl}IEH0@Y`3B*) z5P8k&KA=?(iw|zn*kJ2iYx64dl#%h-u?dv1!QxeuOigi;q^|G3;NV70oV$v+(h=M) z&N%m5C*k~M;$RG9&f20d`L0-1*TD^-?Q)i>x~pot^YqhS;IH$~QX#WXhOEVm!Q3@Q ze2PZ={-0I+jv&4R4*eqnM1Tko0U|&IhyW2F0z`la5CI}U1kOGJ^BY!KOz#g^=QXUd zo8Aw=_x~>vZV|+S^Bw2=9e?h)y8URov+Z!3(E1_!FYF&|`9{lH+ZSw7^YNzt(=^`r zgT^flUujrn{kV03_!L3qHjyC-HhB#eo6`8Tk69?fMKOvZki*x~OuhN= z^p~_PP_uA`vg>Fq9f6vkM`{|Ir4HOnOxM8`@ZGjl9&BSr{$a2hI$*erW2)TU)}Dgz zs#Sg+2FCA{8EcqCOKJ0l~3zx6vR`^Y~%re;w5;b9F zSSY4`_JLh~YbBdA37ZmkRz;O5?8Y4-m1M&Ya^k+LdcyJVahkQ@cNDsDTd^4g88)0& zw_k;F1v`8f#obWS*Hrz^L#3d#Nwu&88?LAH?CVt|C6c-NieN@jLu6DGj1-$jW|>s@ z@`;XzuM9J5VcR~|&DCLeajeGv(dX}iq?*k~bJVq)x)$Td#>y1IGFam`&}!u55X{=w zkaeMqvgYz#J8quQ7#cQ@sv-+ZnAiA0yISI;n&K>RsK#demKPUf{CW)x+M5MI9R_~2 zi+Uiar<)=Fz(;$E?L%0VR_qI1_640v4gAAd6*9m!8b0Gy0|~5w($dQy#~+Oq9fK%m zrjKV;k;A@IRVhdLpilkcMN1_dO=-vs2*9AstnD?`tIzI5=Y84_z| z#Mz11(y02?qY!*}P5-l-!3R%>f{w_LeDQlUe!D^S-jjj0s<#gEp{lJA5{zZ^}5RjTo>$|C6 z%3pgkXilcbnjQUzHD) z!`H?Fkr4L(mk75BV$S(3=M|1u9ZT8|x4qMrX#HAiul;4ayXA?NMYeqN_nLP%{l86D zG@fW&*if{7%j&m0XPF0={RaPv=M_aL>o!NPV?n)I$jesO!k2)yR{j1wb|9c;Qp+*m z@G9T)#y$h=!D>hZDTa$8LlO9(m~M*Iw80(lq3tlg=!6e|^j7UH@O5r#_k~s2@Oc`D zUE8~{`Zqv86#rlVZ>QG~1sgDHS|cvMuO|SD6N4Ujj~CwQc0i6$TGFWsJo=HZn;U!iefwTr?$`Ha~4W%1&sW#4iY#iD+t-AXG(`(1QUqga$#TR zs`y?HG=-F})EQO6@;g?dLqW!-_NP-ii}1nQ(K)E(%~O+5{v8nBPsgvN@XvOYe@x6I z)X;bap|EQNEb@dzjE3~Ke3?a>SA>t?#yhVpw+7f2Gjva}vkYxjw#F2D#A@gC)NA*g zdh;nY`)9{@rjo;6Wi2Y4S5~Frs!G_&BHSZIJ;9i+Ni76m6r%7o+=WH>9PX^Xrpjtn za138KGQLk+GS(g7{ixF|Ym zkNsR+gwNmRBNaWuvP@)pxxmAJDF&3k*-(1yMgCROse8USc|aT1gyuiI1JSL#;Q)E6 zj1<@^AAWfyR^6^bS8coq-@&~>5@+~S)wOaemANsKOC?S}{rdlH?|OdQD8i^koYrmZ z)`?5f(5AUTNwK}_A8R`ZP)JK#)D}n)h@%zKq!MWpdm|`68qKK^$_0rV7m(n}6;Tcx zIdkK}F@-;XD-v&Jc4ogF?{2mcAXS=3Pq7`#etGll%zSTV=lkQU?`8cysa8Gtd)wsl zQlZ>JH}81tB+D0bAI4Y2lb09DLilia2W#snG^6kISdp)avf%sdyZwhhL?zi+>wn;H zL@6OU__5~A#kN<&$=A9!*OX8|6BS?Q*%$`CN*FcSCb{x16CbD63~zyNFqM^s%Y&2K z_Z~d@`hn^THrM>Y?Nzf>m!=3Snv~Tf6g?Cy&$FDI)EZ{}=yfI%L}}WiPf`gY_3DEJ zG1;W=v=Xzk!Y-##HP;MAX^0e2(@-fQr9mw56e`$et|o0p*OR}WQ4x_ShEzy-j<97! zqL@s>!$$uE8imhfs(4_-1cPr#B&hF5HPNYJ3Kh5;2~;LO#rz&dZwwVOaADe}jb2SA zFjj>&N)^-SP3F`VH*3faSp_byG1qn2)F;yG&BTd&y(Xn^f0SFjBdkKNH-!{rQbJKu z%^oX!oH2?;hNu~-43V}Nv3rxL;4~9W#faj{J(-im=o6jY>O4`?iROtBQY24IVI|Hl ziycNQA3X*uktrIiRHit>D##R*SvAReoT1h1PBFKAAwzsGZ`{7qUqZd|D78Po*?aWm z&-;51qY=d?->4|wuO7$^Ck^R#Bq8N^F3bBek2TuSNFk+4h6_EyM!L|+5;dH#el=uey~2DC+dcyca@D$s$vmr(C2kyFda%}hVrvoAfxeS1{s-wlqhHu zGK)@NX-M&=qZ8N^X1Hls^#%sBiEWwvKW@{h?B5_1X8*}-927EDY)A{D&MnXX%SZmo zoxFA8*Ap+5ek#ouKcDz}V*B{-$KN~l+p%{FzZ9N5`UT!#f2;yl0jq#jz$);BE5K&i zJQ8r+a9s+P0Z0N4b7~z2Ijq((D}d=NZGg+Xbma53Rm|G_wVOVwimpb|?>dU!ZB}uA zEU(;)BOn%dF0m_5>63xV8ym~p`LlP*CR2ae|P?;4bQ`D-jFACrO>icvWBX5;g zsx`VXj%B0P^g1||_bhTOIOM7PcyV#zkn33}G02U1m2m8h*=LlFLpEqc4f|bo2Ih0A znZB~2*+}b|$JGuMNUZYn#@iWcTbVLIN#jnqc}}+&Ha$7sefA7|f>JLdgB4W#_T}zI z)jZN0zp$IpYq1=gE#@|}Xdo;kWxtyuaQCR1Dng6c zM??giOU%mbG{Sc55KBx!lLTR#9JL7zU#L!(!<=AxHpHJ6b!QO!lKiqe2_u=6&&gbgy2?CGGf zQrX1xF_M?+V^SI`ffUY9C!KT<#ZIja>*h2&C3@pm)P?k)4Heo_*MecG5{9uGT7f#c zp<}PT%PMfTOV5om6Gb2I@)4{W)PJlk?+pFBo9_<#ThW0_)rVZ@-?^8-phNZ#5(X~P z|1z5r>eNR$@Gn2aKx&Rv37ouEOvmTcoUV)Ua}u1!4{^<7xk$y(H7o_h$I(`QeJz$$ z2mWK|Mkt}Ms_ZtpY?_sexm^sOsTX}rXcJC!Xuwq;J9Z{9b4R^NzTVvx`G2nbgiq)! zeXD>~z$#!BunJfOtO8a6tAJI&Dqt0`3RnfQC@_XMy$u`%jsR~0Hv+tY-#393;4R=f za1G$EtLOajMPM1Y5-_y4zyrHz044&;H?0sfi%@l$~Pu?koPtO8a6tAJI&Dqt0`3RnfK0#*U5!2hQ}hV%da0Wc1{ Ad;kCd literal 0 HcmV?d00001 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..2a36339 --- /dev/null +++ b/go.mod @@ -0,0 +1,146 @@ +module go-admin + +go 1.18 + +require ( + github.com/alibaba/sentinel-golang v1.0.4 + github.com/alibaba/sentinel-golang/pkg/adapters/gin v0.0.0-20220808015021-c5f1f1d055c5 + github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5 + github.com/bitly/go-simplejson v0.5.0 + github.com/bytedance/go-tagexpr/v2 v2.7.12 + github.com/casbin/casbin/v2 v2.51.2 + github.com/gin-gonic/gin v1.9.1 + github.com/go-admin-team/go-admin-core v1.4.1-0.20220809101213-21187928f7d9 + github.com/go-admin-team/go-admin-core/sdk v1.4.1-0.20220809101213-21187928f7d9 + github.com/google/uuid v1.3.0 + github.com/huaweicloud/huaweicloud-sdk-go-obs v3.21.12+incompatible + github.com/mssola/user_agent v0.5.2 + github.com/opentracing/opentracing-go v1.1.0 + github.com/pkg/errors v0.9.1 + github.com/prometheus/client_golang v1.11.1 + github.com/qiniu/go-sdk/v7 v7.11.1 + github.com/robfig/cron/v3 v3.0.1 + github.com/shirou/gopsutil/v3 v3.22.1 + github.com/spf13/cobra v1.0.0 + github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a + github.com/swaggo/gin-swagger v1.5.0 + github.com/swaggo/swag v1.8.3 + github.com/unrolled/secure v1.0.8 + golang.org/x/crypto v0.9.0 + gorm.io/driver/mysql v1.3.5 + gorm.io/driver/postgres v1.3.8 + gorm.io/driver/sqlite v1.3.6 + gorm.io/driver/sqlserver v1.3.2 + gorm.io/gorm v1.23.8 +) + +require ( + github.com/BurntSushi/toml v0.3.1 // indirect + github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect + github.com/KyleBanks/depth v1.2.1 // indirect + github.com/PuerkitoBio/purell v1.1.1 // indirect + github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect + github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bsm/redislock v0.5.0 // indirect + github.com/casbin/redis-watcher/v2 v2.0.0-20220614104201-0e70bf2be930 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/chanxuehong/rand v0.0.0-20201110082127-2f19a1bdd973 // indirect + github.com/chanxuehong/wechat v0.0.0-20201110083048-0180211b69fd // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect + github.com/denisenkom/go-mssqldb v0.12.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fatih/color v1.9.0 // indirect + github.com/fsnotify/fsnotify v1.4.9 // indirect + github.com/ghodss/yaml v1.0.0 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/git-chglog/git-chglog v0.0.0-20190611050339-63a4e637021f // indirect + github.com/go-admin-team/go-admin-core/plugins/logger/zap v0.0.0-20210610020726-2db73adb505d // indirect + github.com/go-admin-team/gorm-adapter/v3 v3.7.8-0.20220809100335-eaf9f67b3d21 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.19.6 // indirect + github.com/go-openapi/spec v0.20.4 // indirect + github.com/go-openapi/swag v0.19.15 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.14.0 // indirect + github.com/go-redis/redis/v7 v7.4.0 // indirect + github.com/go-redis/redis/v8 v8.11.5 // indirect + github.com/go-sql-driver/mysql v1.6.0 // indirect + github.com/golang-jwt/jwt/v4 v4.4.2 // indirect + github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect + github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 // indirect + github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect + github.com/golang/protobuf v1.5.0 // indirect + github.com/golang/snappy v0.0.1 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/henrylee2cn/ameda v1.4.10 // indirect + github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8 // indirect + github.com/imdario/mergo v0.3.9 // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/jackc/chunkreader/v2 v2.0.1 // indirect + github.com/jackc/pgconn v1.12.1 // indirect + github.com/jackc/pgio v1.0.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgproto3/v2 v2.3.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect + github.com/jackc/pgtype v1.11.0 // indirect + github.com/jackc/pgx/v4 v4.16.1 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/leodido/go-urn v1.2.4 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/mailru/easyjson v0.7.6 // indirect + github.com/mattn/go-colorable v0.1.7 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-sqlite3 v1.14.12 // indirect + github.com/mattn/goveralls v0.0.2 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mojocn/base64Captcha v1.3.1 // indirect + github.com/nsqio/go-nsq v1.0.8 // indirect + github.com/nyaruka/phonenumbers v1.0.55 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/prometheus/client_model v0.2.0 // indirect + github.com/prometheus/common v0.26.0 // indirect + github.com/prometheus/procfs v0.6.0 // indirect + github.com/robinjoseph08/redisqueue/v2 v2.1.0 // indirect + github.com/russross/blackfriday/v2 v2.0.1 // indirect + github.com/shamsher31/goimgext v1.0.0 // indirect + github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect + github.com/spf13/cast v1.3.1 // indirect + github.com/spf13/pflag v1.0.3 // indirect + github.com/tklauser/go-sysconf v0.3.9 // indirect + github.com/tklauser/numcpus v0.3.0 // indirect + github.com/tsuyoshiwada/go-gitcmd v0.0.0-20180205145712-5f1f5f9475df // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + github.com/urfave/cli v1.22.1 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + go.uber.org/atomic v1.6.0 // indirect + go.uber.org/multierr v1.5.0 // indirect + go.uber.org/zap v1.15.0 // indirect + golang.org/x/image v0.1.0 // indirect + golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect + golang.org/x/tools v0.6.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/AlecAivazis/survey.v1 v1.8.5 // indirect + gopkg.in/kyokomi/emoji.v1 v1.5.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gorm.io/plugin/dbresolver v1.2.2 // indirect +) + +//replace ( +// github.com/go-admin-team/go-admin-core v1.4.0 => ../../go-admin-core +// github.com/go-admin-team/go-admin-core/sdk v1.4.0 => ../../go-admin-core/sdk +//) diff --git a/main.go b/main.go new file mode 100644 index 0000000..e25407e --- /dev/null +++ b/main.go @@ -0,0 +1,21 @@ +package main + +import ( + "go-admin/cmd" +) + +//go:generate swag init --parseDependency --parseDepth=6 --instanceName admin -o ./docs/admin + +// @title go-admin API +// @version 2.0.0 +// @description 基于Gin + Vue + Element UI的前后端分离权限管理系统的接口文档 +// @description 添加qq群: 521386980 进入技术交流群 请先star,谢谢! +// @license.name MIT +// @license.url https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md + +// @securityDefinitions.apikey Bearer +// @in header +// @name Authorization +func main() { + cmd.Execute() +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..48e341a --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3 @@ +{ + "lockfileVersion": 1 +} diff --git a/restart.sh b/restart.sh new file mode 100644 index 0000000..ef8c4c1 --- /dev/null +++ b/restart.sh @@ -0,0 +1,10 @@ +#!/bin/bash +echo "go build" +go mod tidy +go build -o go-admin main.go +chmod +x ./go-admin +echo "kill go-admin service" +killall go-admin # kill go-admin service +nohup ./go-admin server -c=config/settings.dev.yml >> access.log 2>&1 & #后台启动服务将日志写入access.log文件 +echo "run go-admin success" +ps -aux | grep go-admin diff --git a/scripts/Dockerfile b/scripts/Dockerfile new file mode 100644 index 0000000..01bdeb8 --- /dev/null +++ b/scripts/Dockerfile @@ -0,0 +1,6 @@ +FROM alpine + +COPY ./go-admin / +EXPOSE 8000 + +CMD ["/go-admin","server","-c", "/config/settings.yml"] diff --git a/scripts/k8s/deploy.yml b/scripts/k8s/deploy.yml new file mode 100644 index 0000000..4479227 --- /dev/null +++ b/scripts/k8s/deploy.yml @@ -0,0 +1,57 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: go-admin + labels: + app: go-admin + service: go-admin +spec: + ports: + - port: 8000 + name: http + protocol: TCP + selector: + app: go-admin +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: go-admin-v1 + labels: + app: go-admin + version: v1 +spec: + replicas: 1 + selector: + matchLabels: + app: go-admin + version: v1 + template: + metadata: + labels: + app: go-admin + version: v1 + spec: + containers: + - name: go-admin + image: registry.cn-shanghai.aliyuncs.com/go-admin-team/go-admin + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8000 + volumeMounts: + - name: go-admin + mountPath: /temp + - name: go-admin + mountPath: /static + - name: go-admin-config + mountPath: /config/ + readOnly: true + volumes: + - name: go-admin + persistentVolumeClaim: + claimName: go-admin + - name: go-admin-config + configMap: + name: settings-admin +--- diff --git a/scripts/k8s/prerun.sh b/scripts/k8s/prerun.sh new file mode 100644 index 0000000..f7bb046 --- /dev/null +++ b/scripts/k8s/prerun.sh @@ -0,0 +1,3 @@ +#!/bin/bash +kubectl create ns go-admin +kubectl create configmap settings-admin --from-file=../../config/settings.yml -n go-admin diff --git a/scripts/k8s/storage.yml b/scripts/k8s/storage.yml new file mode 100644 index 0000000..2866a90 --- /dev/null +++ b/scripts/k8s/storage.yml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: go-admin + namespace: go-admin +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: "1Mi" + volumeName: + storageClassName: nfs-csi \ No newline at end of file diff --git a/ssh/swag.sh b/ssh/swag.sh new file mode 100644 index 0000000..48139df --- /dev/null +++ b/ssh/swag.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +swag i -g init_router.go -dir app/admin/router --instanceName admin --parseDependency -o docs/admin diff --git a/static/form-generator/css/index.1a124643.css b/static/form-generator/css/index.1a124643.css new file mode 100644 index 0000000..0aa38db --- /dev/null +++ b/static/form-generator/css/index.1a124643.css @@ -0,0 +1 @@ +.add-item[data-v-60dcec16]{margin-top:8px}.url-item[data-v-60dcec16]{margin-bottom:12px}.tab-editor[data-v-3157a144]{position:absolute;top:33px;bottom:0;left:0;right:0;font-size:14px}.left-editor[data-v-3157a144]{position:relative;height:100%;background:#1e1e1e;overflow:hidden}.setting[data-v-3157a144]{position:absolute;right:15px;top:3px;color:#a9f122;font-size:18px;cursor:pointer;z-index:1}.right-preview[data-v-3157a144]{height:100%}.right-preview .result-wrapper[data-v-3157a144]{height:calc(100vh - 33px);width:100%;overflow:auto;padding:12px;-webkit-box-sizing:border-box;box-sizing:border-box}.action-bar[data-v-3157a144]{height:33px;background:#f2fafb;padding:0 15px;-webkit-box-sizing:border-box;box-sizing:border-box}.action-bar .bar-btn[data-v-3157a144]{display:inline-block;padding:0 6px;line-height:32px;color:#8285f5;cursor:pointer;font-size:14px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.action-bar .bar-btn i[data-v-3157a144]{font-size:20px}.action-bar .bar-btn[data-v-3157a144]:hover{color:#4348d4}.action-bar .bar-btn+.bar-btn[data-v-3157a144]{margin-left:8px}.action-bar .delete-btn[data-v-3157a144]{color:#f56c6c}.action-bar .delete-btn[data-v-3157a144]:hover{color:#ea0b30}[data-v-3157a144] .el-drawer__header,[data-v-44793736] .el-drawer__header{display:none}.action-bar[data-v-44793736]{height:33px;background:#f2fafb;padding:0 15px;-webkit-box-sizing:border-box;box-sizing:border-box}.action-bar .bar-btn[data-v-44793736]{display:inline-block;padding:0 6px;line-height:32px;color:#8285f5;cursor:pointer;font-size:14px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.action-bar .bar-btn i[data-v-44793736]{font-size:20px}.action-bar .bar-btn[data-v-44793736]:hover{color:#4348d4}.action-bar .bar-btn+.bar-btn[data-v-44793736]{margin-left:8px}.action-bar .delete-btn[data-v-44793736]{color:#f56c6c}.action-bar .delete-btn[data-v-44793736]:hover{color:#ea0b30}.json-editor[data-v-44793736]{height:calc(100vh - 33px)}.icon-ul[data-v-3ba3d51c]{margin:0;padding:0;font-size:0}.icon-ul li[data-v-3ba3d51c]{list-style-type:none;text-align:center;font-size:14px;display:inline-block;width:16.66%;-webkit-box-sizing:border-box;box-sizing:border-box;height:108px;padding:15px 6px 6px 6px;cursor:pointer;overflow:hidden}.icon-ul li[data-v-3ba3d51c]:hover{background:#f2f2f2}.icon-ul li.active-item[data-v-3ba3d51c]{background:#e1f3fb;color:#7a6df0}.icon-ul li>i[data-v-3ba3d51c]{font-size:30px;line-height:50px}.icon-dialog[data-v-3ba3d51c] .el-dialog{border-radius:8px;margin-bottom:0;margin-top:4vh!important;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-height:92vh;overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box}.icon-dialog[data-v-3ba3d51c] .el-dialog .el-dialog__header{padding-top:14px}.icon-dialog[data-v-3ba3d51c] .el-dialog .el-dialog__body{margin:0 20px 20px 20px;padding:0;overflow:auto}.right-board[data-v-0c0004cd]{width:350px;position:absolute;right:0;top:0;padding-top:3px}.right-board .field-box[data-v-0c0004cd]{position:relative;height:calc(100vh - 42px);-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden}.right-board .el-scrollbar[data-v-0c0004cd]{height:100%}.select-item[data-v-0c0004cd]{display:-webkit-box;display:-ms-flexbox;display:flex;border:1px dashed #fff;-webkit-box-sizing:border-box;box-sizing:border-box}.select-item .close-btn[data-v-0c0004cd]{cursor:pointer;color:#f56c6c}.select-item .el-input+.el-input[data-v-0c0004cd]{margin-left:4px}.select-item+.select-item[data-v-0c0004cd]{margin-top:4px}.select-item.sortable-chosen[data-v-0c0004cd]{border:1px dashed #409eff}.select-line-icon[data-v-0c0004cd]{line-height:32px;font-size:22px;padding:0 4px;color:#777}.option-drag[data-v-0c0004cd]{cursor:move}.time-range .el-date-editor[data-v-0c0004cd]{width:227px}.time-range[data-v-0c0004cd] .el-icon-time{display:none}.document-link[data-v-0c0004cd]{position:absolute;display:block;width:26px;height:26px;top:0;left:0;cursor:pointer;background:#409eff;z-index:1;border-radius:0 0 6px 0;text-align:center;line-height:26px;color:#fff;font-size:18px}.node-label[data-v-0c0004cd]{font-size:14px}.node-icon[data-v-0c0004cd]{color:#bebfc3}.container{position:relative;width:100%;height:100%}.components-list{padding:8px;-webkit-box-sizing:border-box;box-sizing:border-box;height:100%}.components-list .components-item{display:inline-block;width:48%;margin:1%;-webkit-transition:-webkit-transform 0ms!important;transition:-webkit-transform 0ms!important;transition:transform 0ms!important;transition:transform 0ms,-webkit-transform 0ms!important}.components-draggable{padding-bottom:20px}.components-title{font-size:14px;color:#222;margin:6px 2px}.components-title .svg-icon{color:#666;font-size:18px}.components-body{padding:8px 10px;background:#f6f7ff;font-size:12px;cursor:move;border:1px dashed #f6f7ff;border-radius:3px}.components-body .svg-icon{color:#777;font-size:15px}.components-body:hover{border:1px dashed #787be8;color:#787be8}.components-body:hover .svg-icon{color:#787be8}.left-board{width:260px;position:absolute;left:0;top:0;height:100vh}.center-scrollbar,.left-scrollbar{height:calc(100vh - 42px);overflow:hidden}.center-scrollbar{border-left:1px solid #f1e8e8;border-right:1px solid #f1e8e8}.center-board,.center-scrollbar{-webkit-box-sizing:border-box;box-sizing:border-box}.center-board{height:100vh;width:auto;margin:0 350px 0 260px}.empty-info{position:absolute;top:46%;left:0;right:0;text-align:center;font-size:18px;color:#ccb1ea;letter-spacing:4px}.action-bar{position:relative;height:42px;text-align:right;padding:0 15px;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid #f1e8e8;border-top:none;border-left:none}.action-bar .delete-btn{color:#f56c6c}.logo-wrapper{position:relative;height:42px;background:#fff;border-bottom:1px solid #f1e8e8;-webkit-box-sizing:border-box;box-sizing:border-box}.logo{position:absolute;left:12px;top:6px;line-height:30px;color:#00afff;font-weight:600;font-size:17px;white-space:nowrap}.logo>img{width:30px;height:30px;vertical-align:top}.logo .github{display:inline-block;vertical-align:sub;margin-left:15px}.logo .github>img{height:22px}.center-board-row{padding:12px 12px 15px 12px;-webkit-box-sizing:border-box;box-sizing:border-box}.center-board-row>.el-form{height:calc(100vh - 69px)}.drawing-board{height:100%;position:relative}.drawing-board .components-body{padding:0;margin:0;font-size:0}.drawing-board .sortable-ghost{position:relative;display:block;overflow:hidden}.drawing-board .sortable-ghost:before{content:" ";position:absolute;left:0;right:0;top:0;height:3px;background:#5959df;z-index:2}.drawing-board .components-item.sortable-ghost{width:100%;height:60px;background-color:#f6f7ff}.drawing-board .active-from-item>.el-form-item{background:#f6f7ff;border-radius:6px}.drawing-board .active-from-item>.drawing-item-copy,.drawing-board .active-from-item>.drawing-item-delete{display:initial}.drawing-board .active-from-item>.component-name{color:#409eff}.drawing-board .el-form-item{margin-bottom:15px}.drawing-item{position:relative;cursor:move}.drawing-item.unfocus-bordered:not(.active-from-item)>div:first-child{border:1px dashed #ccc}.drawing-item .el-form-item{padding:12px 10px}.drawing-row-item{position:relative;cursor:move;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px dashed #ccc;border-radius:3px;padding:0 2px;margin-bottom:15px}.drawing-row-item .drawing-row-item{margin-bottom:2px}.drawing-row-item .el-col{margin-top:22px}.drawing-row-item .el-form-item{margin-bottom:0}.drawing-row-item .drag-wrapper{min-height:80px}.drawing-row-item.active-from-item{border:1px dashed #409eff}.drawing-row-item .component-name{position:absolute;top:0;left:0;font-size:12px;color:#bbb;display:inline-block;padding:0 6px}.drawing-item:hover>.el-form-item,.drawing-row-item:hover>.el-form-item{background:#f6f7ff;border-radius:6px}.drawing-item:hover>.drawing-item-copy,.drawing-item:hover>.drawing-item-delete,.drawing-row-item:hover>.drawing-item-copy,.drawing-row-item:hover>.drawing-item-delete{display:initial}.drawing-item>.drawing-item-copy,.drawing-item>.drawing-item-delete,.drawing-row-item>.drawing-item-copy,.drawing-row-item>.drawing-item-delete{display:none;position:absolute;top:-10px;width:22px;height:22px;line-height:22px;text-align:center;border-radius:50%;font-size:12px;border:1px solid;cursor:pointer;z-index:1}.drawing-item>.drawing-item-copy,.drawing-row-item>.drawing-item-copy{right:56px;border-color:#409eff;color:#409eff;background:#fff}.drawing-item>.drawing-item-copy:hover,.drawing-row-item>.drawing-item-copy:hover{background:#409eff;color:#fff}.drawing-item>.drawing-item-delete,.drawing-row-item>.drawing-item-delete{right:24px;border-color:#f56c6c;color:#f56c6c;background:#fff}.drawing-item>.drawing-item-delete:hover,.drawing-row-item>.drawing-item-delete:hover{background:#f56c6c;color:#fff}body,html{margin:0;padding:0;background:#fff;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}body,html,input,textarea{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji}.editor-tabs{background:#121315}.editor-tabs .el-tabs__header{margin:0;border-bottom-color:#121315}.editor-tabs .el-tabs__header .el-tabs__nav{border-color:#121315}.editor-tabs .el-tabs__item{height:32px;line-height:32px;color:#888a8e;border-left:1px solid #121315!important;background:#363636;margin-right:5px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.editor-tabs .el-tabs__item.is-active{background:#1e1e1e;border-bottom-color:#1e1e1e!important;color:#fff}.editor-tabs .el-icon-edit{color:#f1fa8c}.editor-tabs .el-icon-document{color:#a95812}.right-scrollbar .el-scrollbar__view{padding:12px 18px 15px 15px}.el-scrollbar__wrap{-webkit-box-sizing:border-box;box-sizing:border-box;overflow-x:hidden!important}.center-tabs .el-tabs__header,.el-scrollbar__wrap{margin-bottom:0!important}.center-tabs .el-tabs__item{width:50%;text-align:center}.center-tabs .el-tabs__nav{width:100%}.reg-item{padding:12px 6px;background:#f8f8f8;position:relative;border-radius:4px}.reg-item .close-btn{position:absolute;right:-6px;top:-6px;display:block;width:16px;height:16px;line-height:16px;background:rgba(0,0,0,.2);border-radius:50%;color:#fff;text-align:center;z-index:1;cursor:pointer;font-size:12px}.reg-item .close-btn:hover{background:rgba(210,23,23,.5)}.reg-item+.reg-item{margin-top:18px}.action-bar .el-button+.el-button{margin-left:15px}.action-bar i{font-size:20px;vertical-align:middle;position:relative;top:-1px}.custom-tree-node{width:100%;font-size:14px}.custom-tree-node .node-operation{float:right}.custom-tree-node i[class*=el-icon]+i[class*=el-icon]{margin-left:6px}.custom-tree-node .el-icon-plus{color:#409eff}.custom-tree-node .el-icon-delete{color:#157a0c}.el-scrollbar__view{overflow-x:hidden}.el-rate{display:inline-block;vertical-align:text-top}.el-upload__tip{line-height:1.2}.svg-icon[data-v-19957a58]{width:1em;height:1em;vertical-align:-.15em;fill:currentColor;overflow:hidden}.svg-external-icon[data-v-19957a58]{background-color:currentColor;-webkit-mask-size:cover!important;mask-size:cover!important;display:inline-block} \ No newline at end of file diff --git a/static/form-generator/css/parser-example.69e16e51.css b/static/form-generator/css/parser-example.69e16e51.css new file mode 100644 index 0000000..09cac88 --- /dev/null +++ b/static/form-generator/css/parser-example.69e16e51.css @@ -0,0 +1 @@ +.test-form[data-v-77b1aafa]{margin:15px auto;width:800px;padding:15px} \ No newline at end of file diff --git a/static/form-generator/img/logo.e1bc3747.png b/static/form-generator/img/logo.e1bc3747.png new file mode 100644 index 0000000000000000000000000000000000000000..9838306b47f1bc31966393bd51a71864f2c6776b GIT binary patch literal 10543 zcmV+~DbUu5P)PyI=}AOERCodHT?u#`#g(q=o*CVeZ{tHI26GyGVJ;t%flWw4vX(L83(GDGA%Ty8 z4+*jhUv@X%-2_;6@l6O2h=Z5QT1z%JfnZCvIgBwl#s=Gf@og;IIxLMwGd*4VYV479 z%#3EbtEP{6^;-2*7uj5%YvZ`bcLNs82t`m>`X@J z89=OnQdUS9DI}Eo7-1S*(m{Pg}6#ffB*$$@DFI1K6 zxOmFkZ{|^|OKuy^L2G$EGK8kNW*T)R}$*jL6r)$eSPM(KKJC?Ub-xFgy4H z8vewi(v3<^?ngMnr@0$!-W)1+w+<@XuwWbs>31+n{vM{&1>J7j^C!&xVHU9iM)(gI zBO5&)vax@5-j*jP-Wjqd!^o9v1W>U7VHlmgNBsVqK{@VXj9n%h^fb{A5JEqN_4|iJ zp&u%YtgSAoIFzQgu^EdI$Y{kbe{X(HNTWX^O#dZ}bj23;MH-r?+hA0GTcP9~wZE^n zYV_SLX=oIiumFLKRP0m6uvxlJ?j?i`wg7j_n*;^t)ASEu68{d2>~D`P9rw{ZdKI_e zV{rij8K>A~>lWMu*6oL3+C9Pr{U=TYN}J(jSOeQ}?|7N_wW`utyTuVlO6f)*V-$Pl zx`mf(VSOQt&{w1zWGA)MmgllspVdUJK$p zPYUVERpTofT_T#}#c-Ws!xq-4P>@u?`jESQVo4hUv>lZEb(PZR3yb@_x@_cau#b+# zDg<1m*w@!BxFO8g)3BB_v3?=~5Tqd! z0s1AJRQp42mb&bPE9QPHv!zU@?P$fG@!`_`tgU?&7|Et&dPh1*{!?CWFEgqGF}YXNm^4i_KXdW4`N!|da#0@V@zDEo0% zK6MiBR`co@#V+6WSbpeeU@eT)mskxNwr>Ffl&%5S;03EnD_+F|DZS(G2*r*>IB9L+ zhY+sqT_k+M%?N-}?}GPWVPW3^e_B5FmR2{*YDPBOEA~m}lZDG5%E>Ke1jV{8Lx7S7 zIC1u*$IF($L6ie7lg_j_wpZ*KwF@4GNTL61T2dt7N(A_xIGhVu0e-CiwYs!&t1E>x zAe5~Y8{9-^F zxvMkHl5RW2K6##+Z36%AA`zX7G!OxBS=|mw{?NFo6JE@eNUXL}>`0vNAbB5*A!G4% zLPxDyv;^2ltPN z-g4WgZANUcfZqxh@ISf@V3fzk2vE8g>^KjOFPZSP+otHYQ0(co^DhQQAfX(~vGHqw zthp8e9sol5msKTmR=CB;X1QYjbp6u>$HR@AU|S1MYq?f&oFNz(*gjSj<$gD8lUc6V zWosW@0T%FbXLLPsnF$Dhg1_aZ-pZdn|~QZ68eCMcvc5#WbS7@0S=bi(hPWMH#Iv3X?CeFwEqz*u&HGkY7k z&NKvI^!}VGq_Spe<(p2B-I9ImeFs9nLZx=X>w!E*5#aBu9%gTp)y{uy#=51pH}s}` z#6GpP^)UeDTIYc1%YdJ5MF7$n5%M47OUFNA*Xem$6}z0RP(yY5-iLMdrEcwVlq+)( zfS`+?Dhj^+lW1L z-GZ|;ooxk6c&-dVkR~EvB?4ev+XbPTepX#Nx6VpFqHU*b#18BFlc>~D*zwbC2!PG# zoG{VXf(_|$?oDa6d}$f6XRMol8(0*dv07Mc9}!3g0^qr}lX^TeYbMY6EFJB|YD2nW z^C17a=Klg>Lidfu0A51`T!{dseuc2RYD({Y)(ZKgPsJf~$FEVTt>{{8(^3S$mZUTC zC)oFXf;(iTn-{4gb|lPEh-}9_>vVT3wr3{lEh=@o zx)R&5D*~Vc6G9}kDRMp{O-xD~v1hKIKT!*ljbI6v)<&8z!e$TwF$hp{f-rjB>S>kh z#1M>6McRlR4wL^vrH&6g-pN1&7%6~=sc+6$yYRcRrI(`E)9V&q3)7FQWiyZT5dp^` zz>R7|e`WgG`9GG)yKuz@g{D;3AC}29(nbWFjR4Dnz3!D@F~3ok9Ksd*`nrXG$9-sJ zF^qH(0XHBJF)B0i{ET%Ae0jMRpI;ay z`1(^C_B8xX1XUr5>7L*ei$tA|MQbY!cG{uYA)JMMf!lj8=@+W1%pN*6uy% z!P>)wz`8 z0UOq$iZXjuNyU;>Su-~kXYCbkRB94t;DJeAvp25rAuxdBa8iJ|zgQK2r`S1v7 zdTkHUnu0_RfMRpy4#7+Ya5JjZ9DvY~0BL^bfTOUG%`E8G!(|&5pPgzuh83I7|6#cQ zd8!RM;d$L3ioB>scx4(RE$}n$6R&z8=F(A3J9*`)T$M7pDS!xT(Gg5MW?fhA(a9|uo z#(tJcLr!{D4;ow~o)VHzO^?6yB?;_oicC|TBzrQv>TO_9lvF4f(6IDGK&SMfRHo#H ztQ35Y4c1f>dN%KlE1tgQQ+8|h0n$*jI|7K3>md}ZziE0_ z6JRE1H1YW7e^3kmW_Y~YcpawXkbL9jWPnI%LCy)n36z{rkQ{{db)RG!aO^W+;r4Gi zMgm_p!+IHvX<+>gH;4G|4X93bUBPtA-JpjeY=$yM-Po>^tDRAGu;X1yW-qcsbeAF;Kg^0te5mBHi#&Fc=OL?Lvr)%E-ODFGtj zVc7b*@A?f(&rC!rr4f5(?V@uurj;Zj=*D~D6Cu+2aXo2+sX2GZ=w7`2vq|=7NKMA4 z?^}p&ozwjl|68sV1&+`%c#5!kr zr)l6bANaC~voE}~Y&z;{haTa8ogzp{_*e00C#~39)^GVfn1nNK&Xmj{khaeoNz)s9 zN$aM15<2Wp%COe@@evX_1kXC8oOthBX`J$taTHF*VMz@ESZn`qX5GRuv1%o)*eo2L z8H<41ujwtY#U-PFRlVuW{X(|SWU$wnW~d%U>z%Qu(w(0(`aNe%Kce6^mm&BxU4I}} z#iSIQPs8EB@!!TG;Pz`WN0QJHKMDJL8sqGSY0G+fqcwq%I{%7{n+OW)VwmTY$8t4I zO0l=D|8yD*`@%w_3X>`gguKJ@q_!f47JW+ovh_ z`nGP_uy_(Ye#Yr4nfHw!3Xyg=0V0pswXk;J&46z_h0sQW=Zqn~k?})B@z`+rlQa6Y z658$H5&93E3HGYkx)#2^bA?R(o^x?O;^~_uTzuWeip}Gh87bW1gnOF>_cX_?o_E{+-W7iAfBX7u89&&sMsW|XRI|m3Q+V@?E}+r?jj|)@a--h_0yImENA_neXjdY z{aVtWG+D(addJXi38OY@lv{6eE|l{^@-yDjJlsrR7;%p^Q9o`~bRUfijhP!@=Pc$Y zFgcC5Ble69j}L;0*hOXQxTM@^VxNlu=wefzh2v8cC zWyggW6dOnESSZ5!Fz+%shZfql#*WYuiw&9A_?ll<;m#{qWFo-MD`zXzn2ODl?SaeD zD4ESWnYJu9NS+?3ZCh%ghh*R=W4}Jir)NNR^ecW!KmZ10AK7qlR7}NINIQ!dbwW|GJ0sQYyUgh%kFCbfX^6uQ z&bPW`6t$0eTx9U&Mw*bbucu;zHN4b~!pe}T@VmnaKdBTg{Ag$YzdzS>{;5dZaf3%D zqr9a232xyn>r>0}kxCm%4(8-a1ut{Y(pZX3E;UCqb82(zxM$$WL;+lCp2Y9SQ(r_9 z_?bb0`;9lh3;Ds)ShS{gsi}Bm28B!`OipPkx64%g<_{JZf`2&fU#HN0v|B!B?qe;Y z@B{=rSwXsr-YUlu&iUuN2tLU{A=8DE6WW0_c3T(4_6N1`5DG{9*+eIxVUR~}|I;J3 zK@xGR8BM7ZmtcY$G8MaE3Y@>r!l`%y_(k7p>7v*~rpJl{C>i|kpu!9cz@FkM> z`>)43UlR5`50e21!!l_?ly+5Y$fSuQcGBpbelYLSfv10n{w61gNf$2t5S}S4A(at# z;^BYzu%sIScC2G6UcT+Ie2DyWZn{};Lwh-p%|emniKaD+F~-Hk8RD9?NJ_YuH7b7i z;kf+Z4buoPLU(p3w$`AH18Z8xZ`0H>hydTp$s5~Wio~sw&uF*rIYD$2(MaP84VdI# zF6Ve_+&1w>1ObmqPAfKK)5K}Gi5Da5Tsfl?-|`CVG?tAc8F2z%pGfAhl%L6;IFP7) zFeg{azzL|3?eUyeY+PTPLsZF;cPNBAtMIehGD_&6ITupyLYsF78Xhva&E-8Kmw1PE z-SW#X87eK;nP3Q9M~+gunG4nNDl$sXa-Edv6bO*?4$hUJXD+GJ7y?jhIs z%APKAXP+-8Ommk;@JBoZ-sLwUiha`u3kQS8nY_0$9t$qJo;zNS0gb~XL$TX;HoB|_ zP#ieDa9Xhg0fwWsfOjHiG$ihm6d^0I89LZ4jWO;o_26TR1N-i1^GM-8Hg`2%4M*&(0wt z(4bZyfJiCgt?Z)YL^=i#pyY(dLsmy?Mid)<;D{YXM8KyTIGd>;7j^d5}y%aA7&+)}m@0uwgiKBJ?q`|m{ZKiV! z)}>Tg-nptWkFD{*R9s%j&Cac5$agB~KnRBq{P_uiD5-`E{7s1LUmGS6zakH)P%w2! z{0H!k90VxcJGNx*+Rnt4ZFQgVP{XGq@^!w8-wh$aT`JXna-wp22j>toX=p=71CjIB zh6GDcNiFhW-0%eW$h@U6x+rQ5kG7*|M8oxU6b*r&h10~3T)yFXq|bFDOmXS|q~28h zc$IU;^y}ou81E^(E*b%tyEXOo6h76Rt_RZjNQ@HDy}8W!&9}X>&MGABUpJc;+E<)U zioRcL+WAF;^g(Ul0xF~Ac8jqtqYb3l69HIT|NfaNxA!=r2UeaiI`;O&OURY{E6txr z=0N}pN`{zLYA#UZl$b95loGEhU(0^oxk z2tX9l`Jp<)TZvq@XHe=D3F&6OZpIi&_}PY zF0FjNw-!OM8BWD}L&@a*g2{u4jBJzKn3ill>u|I9oZC_pC78tAjn(12bz`>b{dqF7 z;fS3KN+zFC3VbBzA~~aW^O~5u9bGsM)wjV}?#3?H%>LjB5_mpvEa^i4*4A_5ZEtnw z0u{SEB9eaRjqe(wS5z}Rd~je#Q$ljh@4z{3!Hy~1`G$J<>w_g72!NI5)tb`EKPB51 z?-|^LOcpH@&w1eRh60B}WRw%NFlxt9T%K@1bm(GkH^}2gK`d!O0H)yky^8mzsWb*r zk>H3nmb4(CSo~-DH87Ti6b~z}Dw&&g_~XK$1vEmLot(W%ZPMKS&h}a8SV!J5|t( zKA(MVk$q879d)Ed!KgBAb)LRSs47el3Y8{U&KmZlH0}lCLioQFH5J)jA zx+pPd26y*3rfa%c?)%OUwqTKm0O;f)MzXG3KK7Q_>#HQ12CF!Z*h%0d>=Ev*XM4hX1T=?+bn_x>dVOQ)j5AQ({$3Z;adZo z#jnDTXcm1RgW1MMNWdM1%&nO^_f-LuU^f!i*dlODi3XpJi!OSnSmP}lj}V?yTV%<( zs4wvjG#?R0Bu{RlMHS`Wj9S2B;Q%qkF?>oaU}RoX`}l;D*IPnFgM8QAb+qL@v7Hm? zSreALIyj*G9H!sTn5C6WeF!_xz%LbxRS2jO_OwOGLLtw09wY?7Vj6(}BkHZIO6R_0 zno^PkJd6^Eo0H_z_?U16eBh>O*TVCLVfZ7Hy+g@Cm8oUbrE@tala;v-cHRVgW-^Ar^d_at z-0JX0@g<*+lq4HfR5Vf^N*{aDEpIXI3_jXSzHle84-I1~2ckY<}BvC%?AOt6D ze02{A9r2UUVZZQ108x>%NB50>#m`<40Hyv@@lelIFI+KK{8`yv+D>%)l-m>gJkdjV zFHHzQK*GEU14yELTq6aG(T@eRcTAHCvBsUMPU%mMe%KlJ*n1rMBDM0wPYEod8? zjDbMTXh?Kt@zPc;6dwp8hN#ZHM9C*URhh8brb^9$jl4phNkjOEZ8+4ab9=~sob&u% zStBf7-(vcn*e?d(%A)j9-+SGdvBlEgC*p`XHc%uT$C{$@Drexk=&=a&i4c-2ciV{4|(eY^8@JAdyuGpHzJquw<%wVnBPHE-TN zy+<+S**FTW9tui$@^3T$XnbuC~ z+moHOHs}`{T+bqz9N($$0B@|@3{h)Ks(yy~*M4};JDb|(tqHlF!W$%2w0amC`!Be6mi6$Reb9)JiZ->546`O2vk?>Jqou7BSZ zm1S6C)#^SO?QK z{sL?1ui$U!?GTHs*2Zk6%vzUMWYzeJMp$3erA!4YNJF6Ds?+(jbH@)L{9m-NFau>i zLXJGXoizXDfMKQP^mt~HOe&zvI;G0OLHYS(+@{o#{_N42l&*r5*;n_tju$LJfS-%z z5ms6^*OSN|^C>QP(!GY7-7(kTsWO@k>+(!eY*J^eknyk8Wa&T+;InUa<;+;O=H}Y{l2Yn=b@UvrGsv3<~{e9*@M=@@a zS&+GB@hYC@z+V`njrWAcvMV0gqZS?GI~$S$x^?dwjAKD?vwZ}%ur8>cmRU;8U(%RU zaekw$cK%-&8qqiuwkd7f8%Wa|dm*T-n7_G2*A}~S#0I5)iz->OYo^|_(>9%#W=3L9 z#eoUX_-EnuLF;&$J0wwaIT!Yg>}v-Pw36@%*snHeJIgw&Fi~^PyGO}x$beA++gGcd z$GljM0GL_(1V6&-tj-y>~&cBlbMD#`9_2=C8pMt+;n`_yiLHB=4U59Z zA?Da`t4e0qi>2;fYP~8p7rm@*{ylKkcZqvpK*{We04OwU=F#Pf$M@^%$@lEB8-I4^ zC!z5y%6#z<&r|yjX#dOzgAkTj5CORe!1mQ@RVBY#Ii+%&+?L!+J*g3!i(gi^;4Y@? zzjH4XD4Ep=fI`>82G#>L(<QPr#YN8Tga9hEyxvGju{j%XR{I^WkY6K@C8X?n z1SqLf8JSl-?cO!6m(?NxlQN!l<_+BU?hb{+e+A_>mWQS@G5nrU2=Fzu!q~r8m!d+; z?)a2PY|ha1+DCr_ff#-zn>nQK4g^4<-vH;5-&U7YY;cD}_Lm~%5u1xNVyO2&_a4-K z42HBZ_7@R3v;u)s`_MHi@%(mW>1@p8n&wV0G-7ieXVfmZKqqVyD0gm}dB*1KjerIg z?iXN`eh94GJnuRd3lK1@*qqn0+68woraxf;-`J$>5TNaF2>6da;(es5bk=U$v6o>C znNntdMVBJEv&ixo@4Ho)_KyI9P`BM1mnY~J{cb@RWkhY6$zVp&F*!8-Os0A7$iRG|+KAL9Ar zl5=La+mA!!C>8=j6`MBz&MQA8j8>y^$Aa5Q*XWnvRPxZkyxiqaPP{YZB+il7UZRv5 z1qhYfC~`KaN6B`DC=Yr{hP_xtZw%XjBV@q<0>Ve^C=X?87yN)x_J8QW5=F$upFEut zBX21xSyVlx;w>ym~fq+!S=Iveo!Q$cJcI`FvE02M`MVFw{_dp2WrL>UzVb%DGMvK_MW+fsZ zU9mauKVAQH!SQg@au~U%OOypkCq_U6hmzO9Aoh%B>hM=_{hSyqr{7JBVn;zb747uD z;dgfQ8h*+~fbM|(=V!dRzGtg0yPM}?!;%3Aq*bvwo-^wfj?q~71u)iJm;v}&A|fbq z3wVdEP^j_@o`JTc3oLIm?TXDMzGKr9xkp-C{{yDxbKs|Ge|5`Iv;_mS9nL_%3Fhn- zz5!V;SB<{A#TINK6P6%giDE}3onAZtV)*_z7}h37ui;g4g*!pO>z|Lm1ug!Jj=4u#I9zIg5la<8>)~I5 zf|o?EXVNE6L6D$7G}2)O3OgWbE5a0 z_<3?WioC}aS!b+n#4yiBJQC@|p0qE|j!^8*@IkbeoKTQXBSilJjO0H6^V_J-_wDwb zD>0*F3-I-^Lda&w4ZGP_GJHFFe%Y<3+{KUM6uUe8py;Et5WN;g@hiZxJ`qOr^T5=e ze!1X86lH8Lw7&zU)t>T6^$4HA|WG!Np7Q&jnK%t}%M%O}Kk0~q!Cy_%C0VYV{JFI{G xaA@K%{9!o6Sk|Gzd7i@A2{6F5J{2##j3=jYS002ovPDHLkV1kRKKOX=9 literal 0 HcmV?d00001 diff --git a/static/form-generator/index.html b/static/form-generator/index.html new file mode 100644 index 0000000..b888095 --- /dev/null +++ b/static/form-generator/index.html @@ -0,0 +1 @@ +form-generator
\ No newline at end of file diff --git a/static/form-generator/js/chunk-vendors.971555db.js b/static/form-generator/js/chunk-vendors.971555db.js new file mode 100644 index 0000000..762db7c --- /dev/null +++ b/static/form-generator/js/chunk-vendors.971555db.js @@ -0,0 +1,19 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-vendors"],{"00ee":function(t,e,s){var i=s("b622"),r=i("toStringTag"),n={};n[r]="z",t.exports="[object z]"===String(n)},"0366":function(t,e,s){var i=s("1c0b");t.exports=function(t,e,s){if(i(t),void 0===e)return t;switch(s){case 0:return function(){return t.call(e)};case 1:return function(s){return t.call(e,s)};case 2:return function(s,i){return t.call(e,s,i)};case 3:return function(s,i,r){return t.call(e,s,i,r)}}return function(){return t.apply(e,arguments)}}},"057f":function(t,e,s){var i=s("fc6a"),r=s("241c").f,n={}.toString,a="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],o=function(t){try{return r(t)}catch(e){return a.slice()}};t.exports.f=function(t){return a&&"[object Window]"==n.call(t)?o(t):r(i(t))}},"06cf":function(t,e,s){var i=s("83ab"),r=s("d1e7"),n=s("5c6c"),a=s("fc6a"),o=s("c04e"),c=s("5135"),h=s("0cfb"),l=Object.getOwnPropertyDescriptor;e.f=i?l:function(t,e){if(t=a(t),e=o(e,!0),h)try{return l(t,e)}catch(s){}if(c(t,e))return n(!r.f.call(t,e),t[e])}},"0cfb":function(t,e,s){var i=s("83ab"),r=s("d039"),n=s("cc12");t.exports=!i&&!r((function(){return 7!=Object.defineProperty(n("div"),"a",{get:function(){return 7}}).a}))},1276:function(t,e,s){"use strict";var i=s("d784"),r=s("44e7"),n=s("825a"),a=s("1d80"),o=s("4840"),c=s("8aa5"),h=s("50c4"),l=s("14c3"),p=s("9263"),u=s("d039"),d=[].push,f=Math.min,m=4294967295,y=!u((function(){return!RegExp(m,"y")}));i("split",2,(function(t,e,s){var i;return i="c"=="abbc".split(/(b)*/)[1]||4!="test".split(/(?:)/,-1).length||2!="ab".split(/(?:ab)*/).length||4!=".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length?function(t,s){var i=String(a(this)),n=void 0===s?m:s>>>0;if(0===n)return[];if(void 0===t)return[i];if(!r(t))return e.call(i,t,n);var o,c,h,l=[],u=(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":""),f=0,y=new RegExp(t.source,u+"g");while(o=p.call(y,i)){if(c=y.lastIndex,c>f&&(l.push(i.slice(f,o.index)),o.length>1&&o.index=n))break;y.lastIndex===o.index&&y.lastIndex++}return f===i.length?!h&&y.test("")||l.push(""):l.push(i.slice(f)),l.length>n?l.slice(0,n):l}:"0".split(void 0,0).length?function(t,s){return void 0===t&&0===s?[]:e.call(this,t,s)}:e,[function(e,s){var r=a(this),n=void 0==e?void 0:e[t];return void 0!==n?n.call(e,r,s):i.call(String(r),e,s)},function(t,r){var a=s(i,t,this,r,i!==e);if(a.done)return a.value;var p=n(t),u=String(this),d=o(p,RegExp),g=p.unicode,x=(p.ignoreCase?"i":"")+(p.multiline?"m":"")+(p.unicode?"u":"")+(y?"y":"g"),b=new d(y?p:"^(?:"+p.source+")",x),v=void 0===r?m:r>>>0;if(0===v)return[];if(0===u.length)return null===l(b,u)?[u]:[];var w=0,P=0,T=[];while(P1?arguments[1]:void 0)}},1861:function(t,e,s){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const i=!0,r=!0,n=!0,a=!0,o=!0,c=!0;class h{constructor(t,e={}){this.label=t,this.keyword=e.keyword,this.beforeExpr=!!e.beforeExpr,this.startsExpr=!!e.startsExpr,this.rightAssociative=!!e.rightAssociative,this.isLoop=!!e.isLoop,this.isAssign=!!e.isAssign,this.prefix=!!e.prefix,this.postfix=!!e.postfix,this.binop=null!=e.binop?e.binop:null,this.updateContext=null}}const l=new Map;function p(t,e={}){e.keyword=t;const s=new h(t,e);return l.set(t,s),s}function u(t,e){return new h(t,{beforeExpr:i,binop:e})}const d={num:new h("num",{startsExpr:r}),bigint:new h("bigint",{startsExpr:r}),regexp:new h("regexp",{startsExpr:r}),string:new h("string",{startsExpr:r}),name:new h("name",{startsExpr:r}),eof:new h("eof"),bracketL:new h("[",{beforeExpr:i,startsExpr:r}),bracketHashL:new h("#[",{beforeExpr:i,startsExpr:r}),bracketBarL:new h("[|",{beforeExpr:i,startsExpr:r}),bracketR:new h("]"),bracketBarR:new h("|]"),braceL:new h("{",{beforeExpr:i,startsExpr:r}),braceBarL:new h("{|",{beforeExpr:i,startsExpr:r}),braceHashL:new h("#{",{beforeExpr:i,startsExpr:r}),braceR:new h("}"),braceBarR:new h("|}"),parenL:new h("(",{beforeExpr:i,startsExpr:r}),parenR:new h(")"),comma:new h(",",{beforeExpr:i}),semi:new h(";",{beforeExpr:i}),colon:new h(":",{beforeExpr:i}),doubleColon:new h("::",{beforeExpr:i}),dot:new h("."),question:new h("?",{beforeExpr:i}),questionDot:new h("?."),arrow:new h("=>",{beforeExpr:i}),template:new h("template"),ellipsis:new h("...",{beforeExpr:i}),backQuote:new h("`",{startsExpr:r}),dollarBraceL:new h("${",{beforeExpr:i,startsExpr:r}),at:new h("@"),hash:new h("#",{startsExpr:r}),interpreterDirective:new h("#!..."),eq:new h("=",{beforeExpr:i,isAssign:a}),assign:new h("_=",{beforeExpr:i,isAssign:a}),incDec:new h("++/--",{prefix:o,postfix:c,startsExpr:r}),bang:new h("!",{beforeExpr:i,prefix:o,startsExpr:r}),tilde:new h("~",{beforeExpr:i,prefix:o,startsExpr:r}),pipeline:u("|>",0),nullishCoalescing:u("??",1),logicalOR:u("||",1),logicalAND:u("&&",2),bitwiseOR:u("|",3),bitwiseXOR:u("^",4),bitwiseAND:u("&",5),equality:u("==/!=/===/!==",6),relational:u("/<=/>=",7),bitShift:u("<>/>>>",8),plusMin:new h("+/-",{beforeExpr:i,binop:9,prefix:o,startsExpr:r}),modulo:new h("%",{beforeExpr:i,binop:10,startsExpr:r}),star:u("*",10),slash:u("/",10),exponent:new h("**",{beforeExpr:i,binop:11,rightAssociative:!0}),_break:p("break"),_case:p("case",{beforeExpr:i}),_catch:p("catch"),_continue:p("continue"),_debugger:p("debugger"),_default:p("default",{beforeExpr:i}),_do:p("do",{isLoop:n,beforeExpr:i}),_else:p("else",{beforeExpr:i}),_finally:p("finally"),_for:p("for",{isLoop:n}),_function:p("function",{startsExpr:r}),_if:p("if"),_return:p("return",{beforeExpr:i}),_switch:p("switch"),_throw:p("throw",{beforeExpr:i,prefix:o,startsExpr:r}),_try:p("try"),_var:p("var"),_const:p("const"),_while:p("while",{isLoop:n}),_with:p("with"),_new:p("new",{beforeExpr:i,startsExpr:r}),_this:p("this",{startsExpr:r}),_super:p("super",{startsExpr:r}),_class:p("class",{startsExpr:r}),_extends:p("extends",{beforeExpr:i}),_export:p("export"),_import:p("import",{startsExpr:r}),_null:p("null",{startsExpr:r}),_true:p("true",{startsExpr:r}),_false:p("false",{startsExpr:r}),_in:p("in",{beforeExpr:i,binop:7}),_instanceof:p("instanceof",{beforeExpr:i,binop:7}),_typeof:p("typeof",{beforeExpr:i,prefix:o,startsExpr:r}),_void:p("void",{beforeExpr:i,prefix:o,startsExpr:r}),_delete:p("delete",{beforeExpr:i,prefix:o,startsExpr:r})},f=0,m=1,y=2,g=4,x=8,b=16,v=32,w=64,P=128,T=m|y|P,E=1,A=2,S=4,C=8,k=16,N=64,I=128,O=256,D=512,M=1024,L=E|A|C|I,_=0|E|C|0,R=0|E|S|0,j=0|E|k|0,F=0|A|I,B=0|A,U=E|A|C|O,q=0|M,V=0|N,H=0|E|N,z=U|D,W=0|M,K=4,$=2,X=1,G=$|X,Y=$|K,J=X|K,Q=$,Z=X,tt=0,et=/\r\n?|[\n\u2028\u2029]/,st=new RegExp(et.source,"g");function it(t){switch(t){case 10:case 13:case 8232:case 8233:return!0;default:return!1}}const rt=/(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;function nt(t){switch(t){case 9:case 11:case 12:case 32:case 160:case 5760:case 8192:case 8193:case 8194:case 8195:case 8196:case 8197:case 8198:case 8199:case 8200:case 8201:case 8202:case 8239:case 8287:case 12288:case 65279:return!0;default:return!1}}class at{constructor(t,e){this.line=t,this.column=e}}class ot{constructor(t,e){this.start=t,this.end=e}}function ct(t,e){let s,i=1,r=0;st.lastIndex=0;while((s=st.exec(t))&&s.index0)i=e[--r];if(null===i)return;for(let a=0;a0?i.trailingComments=n:void 0!==i.trailingComments&&(i.trailingComments=[])}processComment(t){if("Program"===t.type&&t.body.length>0)return;const e=this.state.commentStack;let s,i,r,n,a;if(this.state.trailingComments.length>0)this.state.trailingComments[0].start>=t.end?(r=this.state.trailingComments,this.state.trailingComments=[]):this.state.trailingComments.length=0;else if(e.length>0){const s=lt(e);s.trailingComments&&s.trailingComments[0].start>=t.end&&(r=s.trailingComments,delete s.trailingComments)}e.length>0&<(e).start>=t.start&&(s=e.pop());while(e.length>0&<(e).start>=t.start)i=e.pop();if(!i&&s&&(i=s),s)switch(t.type){case"ObjectExpression":this.adjustCommentsAfterTrailingComma(t,t.properties);break;case"ObjectPattern":this.adjustCommentsAfterTrailingComma(t,t.properties,!0);break;case"CallExpression":this.adjustCommentsAfterTrailingComma(t,t.arguments);break;case"ArrayExpression":this.adjustCommentsAfterTrailingComma(t,t.elements);break;case"ArrayPattern":this.adjustCommentsAfterTrailingComma(t,t.elements,!0);break}else this.state.commentPreviousNode&&("ImportSpecifier"===this.state.commentPreviousNode.type&&"ImportSpecifier"!==t.type||"ExportSpecifier"===this.state.commentPreviousNode.type&&"ExportSpecifier"!==t.type)&&this.adjustCommentsAfterTrailingComma(t,[this.state.commentPreviousNode]);if(i){if(i.leadingComments)if(i!==t&&i.leadingComments.length>0&<(i.leadingComments).end<=t.start)t.leadingComments=i.leadingComments,delete i.leadingComments;else for(n=i.leadingComments.length-2;n>=0;--n)if(i.leadingComments[n].end<=t.start){t.leadingComments=i.leadingComments.splice(0,n+1);break}}else if(this.state.leadingComments.length>0)if(lt(this.state.leadingComments).end<=t.start){if(this.state.commentPreviousNode)for(a=0;a0&&(t.leadingComments=this.state.leadingComments,this.state.leadingComments=[])}else{for(n=0;nt.start)break;const e=this.state.leadingComments.slice(0,n);e.length&&(t.leadingComments=e),r=this.state.leadingComments.slice(n),0===r.length&&(r=null)}if(this.state.commentPreviousNode=t,r)if(r.length&&r[0].start>=t.start&<(r).end<=t.end)t.innerComments=r;else{const e=r.findIndex(e=>e.end>=t.end);e>0?(t.innerComments=r.slice(0,e),t.trailingComments=r.slice(e)):t.trailingComments=r}e.push(t)}}const ut=Object.freeze({ArgumentsDisallowedInInitializer:"'arguments' is not allowed in class field initializer",AsyncFunctionInSingleStatementContext:"Async functions can only be declared at the top level or inside a block",AwaitBindingIdentifier:"Can not use 'await' as identifier inside an async function",AwaitExpressionFormalParameter:"await is not allowed in async function parameters",AwaitNotInAsyncFunction:"Can not use keyword 'await' outside an async function",BadGetterArity:"getter must not have any formal parameters",BadSetterArity:"setter must have exactly one formal parameter",BadSetterRestParameter:"setter function argument must not be a rest parameter",ConstructorClassField:"Classes may not have a field named 'constructor'",ConstructorClassPrivateField:"Classes may not have a private field named '#constructor'",ConstructorIsAccessor:"Class constructor may not be an accessor",ConstructorIsAsync:"Constructor can't be an async function",ConstructorIsGenerator:"Constructor can't be a generator",DeclarationMissingInitializer:"%0 require an initialization value",DecoratorBeforeExport:"Decorators must be placed *before* the 'export' keyword. You can set the 'decoratorsBeforeExport' option to false to use the 'export @decorator class {}' syntax",DecoratorConstructor:"Decorators can't be used with a constructor. Did you mean '@dec class { ... }'?",DecoratorExportClass:"Using the export keyword between a decorator and a class is not allowed. Please use `export @dec class` instead.",DecoratorSemicolon:"Decorators must not be followed by a semicolon",DeletePrivateField:"Deleting a private field is not allowed",DestructureNamedImport:"ES2015 named imports do not destructure. Use another statement for destructuring after the import.",DuplicateConstructor:"Duplicate constructor in the same class",DuplicateDefaultExport:"Only one default export allowed per module.",DuplicateExport:"`%0` has already been exported. Exported identifiers must be unique.",DuplicateProto:"Redefinition of __proto__ property",DuplicateRegExpFlags:"Duplicate regular expression flag",ElementAfterRest:"Rest element must be last element",EscapedCharNotAnIdentifier:"Invalid Unicode escape",ExportDefaultFromAsIdentifier:"'from' is not allowed as an identifier after 'export default'",ForInOfLoopInitializer:"%0 loop variable declaration may not have an initializer",GeneratorInSingleStatementContext:"Generators can only be declared at the top level or inside a block",IllegalBreakContinue:"Unsyntactic %0",IllegalLanguageModeDirective:"Illegal 'use strict' directive in function with non-simple parameter list",IllegalReturn:"'return' outside of function",ImportCallArgumentTrailingComma:"Trailing comma is disallowed inside import(...) arguments",ImportCallArity:"import() requires exactly %0",ImportCallNotNewExpression:"Cannot use new with import(...)",ImportCallSpreadArgument:"... is not allowed in import()",ImportMetaOutsideModule:"import.meta may appear only with 'sourceType: \"module\"'",ImportOutsideModule:"'import' and 'export' may appear only with 'sourceType: \"module\"'",InvalidBigIntLiteral:"Invalid BigIntLiteral",InvalidCodePoint:"Code point out of bounds",InvalidDigit:"Expected number in radix %0",InvalidEscapeSequence:"Bad character escape sequence",InvalidEscapeSequenceTemplate:"Invalid escape sequence in template",InvalidEscapedReservedWord:"Escape sequence in keyword %0",InvalidIdentifier:"Invalid identifier %0",InvalidLhs:"Invalid left-hand side in %0",InvalidLhsBinding:"Binding invalid left-hand side in %0",InvalidNumber:"Invalid number",InvalidOrUnexpectedToken:"Unexpected character '%0'",InvalidParenthesizedAssignment:"Invalid parenthesized assignment pattern",InvalidPrivateFieldResolution:"Private name #%0 is not defined",InvalidPropertyBindingPattern:"Binding member expression",InvalidRecordProperty:"Only properties and spread elements are allowed in record definitions",InvalidRestAssignmentPattern:"Invalid rest operator's argument",LabelRedeclaration:"Label '%0' is already declared",LetInLexicalBinding:"'let' is not allowed to be used as a name in 'let' or 'const' declarations.",MalformedRegExpFlags:"Invalid regular expression flag",MissingClassName:"A class name is required",MissingEqInAssignment:"Only '=' operator can be used for specifying default value.",MissingUnicodeEscape:"Expecting Unicode escape sequence \\uXXXX",MixingCoalesceWithLogical:"Nullish coalescing operator(??) requires parens when mixing with logical operators",ModuleAttributeDifferentFromType:"The only accepted module attribute is `type`",ModuleAttributeInvalidValue:"Only string literals are allowed as module attribute values",ModuleAttributesWithDuplicateKeys:'Duplicate key "%0" is not allowed in module attributes',ModuleExportUndefined:"Export '%0' is not defined",MultipleDefaultsInSwitch:"Multiple default clauses",NewlineAfterThrow:"Illegal newline after throw",NoCatchOrFinally:"Missing catch or finally clause",NumberIdentifier:"Identifier directly after number",NumericSeparatorInEscapeSequence:"Numeric separators are not allowed inside unicode escape sequences or hex escape sequences",ObsoleteAwaitStar:"await* has been removed from the async functions proposal. Use Promise.all() instead.",OptionalChainingNoNew:"constructors in/after an Optional Chain are not allowed",OptionalChainingNoTemplate:"Tagged Template Literals are not allowed in optionalChain",ParamDupe:"Argument name clash",PatternHasAccessor:"Object pattern can't contain getter or setter",PatternHasMethod:"Object pattern can't contain methods",PipelineBodyNoArrow:'Unexpected arrow "=>" after pipeline body; arrow function in pipeline body must be parenthesized',PipelineBodySequenceExpression:"Pipeline body may not be a comma-separated sequence expression",PipelineHeadSequenceExpression:"Pipeline head should not be a comma-separated sequence expression",PipelineTopicUnused:"Pipeline is in topic style but does not use topic reference",PrimaryTopicNotAllowed:"Topic reference was used in a lexical context without topic binding",PrimaryTopicRequiresSmartPipeline:"Primary Topic Reference found but pipelineOperator not passed 'smart' for 'proposal' option.",PrivateInExpectedIn:"Private names are only allowed in property accesses (`obj.#%0`) or in `in` expressions (`#%0 in obj`)",PrivateNameRedeclaration:"Duplicate private name #%0",RecordExpressionBarIncorrectEndSyntaxType:"Record expressions ending with '|}' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'",RecordExpressionBarIncorrectStartSyntaxType:"Record expressions starting with '{|' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'",RecordExpressionHashIncorrectStartSyntaxType:"Record expressions starting with '#{' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'hash'",RecordNoProto:"'__proto__' is not allowed in Record expressions",RestTrailingComma:"Unexpected trailing comma after rest element",SloppyFunction:"In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement",StaticPrototype:"Classes may not have static property named prototype",StrictDelete:"Deleting local variable in strict mode",StrictEvalArguments:"Assigning to '%0' in strict mode",StrictEvalArgumentsBinding:"Binding '%0' in strict mode",StrictFunction:"In strict mode code, functions can only be declared at top level or inside a block",StrictOctalLiteral:"Legacy octal literals are not allowed in strict mode",StrictWith:"'with' in strict mode",SuperNotAllowed:"super() is only valid inside a class constructor of a subclass. Maybe a typo in the method name ('constructor') or not extending another class?",SuperPrivateField:"Private fields can't be accessed on super",TrailingDecorator:"Decorators must be attached to a class element",TupleExpressionBarIncorrectEndSyntaxType:"Tuple expressions ending with '|]' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'",TupleExpressionBarIncorrectStartSyntaxType:"Tuple expressions starting with '[|' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'",TupleExpressionHashIncorrectStartSyntaxType:"Tuple expressions starting with '#[' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'hash'",UnexpectedArgumentPlaceholder:"Unexpected argument placeholder",UnexpectedAwaitAfterPipelineBody:'Unexpected "await" after pipeline body; await must have parentheses in minimal proposal',UnexpectedDigitAfterHash:"Unexpected digit after hash token",UnexpectedImportExport:"'import' and 'export' may only appear at the top level",UnexpectedKeyword:"Unexpected keyword '%0'",UnexpectedLeadingDecorator:"Leading decorators must be attached to a class declaration",UnexpectedLexicalDeclaration:"Lexical declaration cannot appear in a single-statement context",UnexpectedNewTarget:"new.target can only be used in functions",UnexpectedNumericSeparator:"A numeric separator is only allowed between two digits",UnexpectedPrivateField:"Private names can only be used as the name of a class element (i.e. class C { #p = 42; #m() {} } )\n or a property of member expression (i.e. this.#p).",UnexpectedReservedWord:"Unexpected reserved word '%0'",UnexpectedSuper:"super is only allowed in object methods and classes",UnexpectedToken:"Unexpected token '%0'",UnexpectedTokenUnaryExponentiation:"Illegal expression. Wrap left hand side or entire exponentiation in parentheses.",UnsupportedBind:"Binding should be performed on object property.",UnsupportedDecoratorExport:"A decorated export must export a class declaration",UnsupportedDefaultExport:"Only expressions, functions or classes are allowed as the `default` export.",UnsupportedImport:"import can only be used in import() or import.meta",UnsupportedMetaProperty:"The only valid meta property for %0 is %0.%1",UnsupportedParameterDecorator:"Decorators cannot be used to decorate parameters",UnsupportedPropertyDecorator:"Decorators cannot be used to decorate object literal properties",UnsupportedSuper:"super can only be used with function calls (i.e. super()) or in property accesses (i.e. super.prop or super[prop])",UnterminatedComment:"Unterminated comment",UnterminatedRegExp:"Unterminated regular expression",UnterminatedString:"Unterminated string constant",UnterminatedTemplate:"Unterminated template",VarRedeclaration:"Identifier '%0' has already been declared",YieldBindingIdentifier:"Can not use 'yield' as identifier inside a generator",YieldInParameter:"yield is not allowed in generator parameters",ZeroDigitNumericSeparator:"Numeric separator can not be used after leading 0"});class dt extends pt{getLocationForPosition(t){let e;return e=t===this.state.start?this.state.startLoc:t===this.state.lastTokStart?this.state.lastTokStartLoc:t===this.state.end?this.state.endLoc:t===this.state.lastTokEnd?this.state.lastTokEndLoc:ct(this.input,t),e}raise(t,e,...s){return this.raiseWithData(t,void 0,e,...s)}raiseWithData(t,e,s,...i){const r=this.getLocationForPosition(t),n=s.replace(/%(\d+)/g,(t,e)=>i[e])+` (${r.line}:${r.column})`;return this._raise(Object.assign({loc:r,pos:t},e),n)}_raise(t,e){const s=new SyntaxError(e);if(Object.assign(s,t),this.options.errorRecovery)return this.isLookahead||this.state.errors.push(s),s;throw s}}function ft(t){return null!=t&&"Property"===t.type&&"init"===t.kind&&!1===t.method}var mt=t=>class extends t{estreeParseRegExpLiteral({pattern:t,flags:e}){let s=null;try{s=new RegExp(t,e)}catch(r){}const i=this.estreeParseLiteral(s);return i.regex={pattern:t,flags:e},i}estreeParseBigIntLiteral(t){const e="undefined"!==typeof BigInt?BigInt(t):null,s=this.estreeParseLiteral(e);return s.bigint=String(s.value||t),s}estreeParseLiteral(t){return this.parseLiteral(t,"Literal")}directiveToStmt(t){const e=t.value,s=this.startNodeAt(t.start,t.loc.start),i=this.startNodeAt(e.start,e.loc.start);return i.value=e.value,i.raw=e.extra.raw,s.expression=this.finishNodeAt(i,"Literal",e.end,e.loc.end),s.directive=e.extra.raw.slice(1,-1),this.finishNodeAt(s,"ExpressionStatement",t.end,t.loc.end)}initFunction(t,e){super.initFunction(t,e),t.expression=!1}checkDeclaration(t){ft(t)?this.checkDeclaration(t.value):super.checkDeclaration(t)}checkGetterSetterParams(t){const e=t,s="get"===e.kind?0:1,i=e.start;e.value.params.length!==s?"get"===t.kind?this.raise(i,ut.BadGetterArity):this.raise(i,ut.BadSetterArity):"set"===e.kind&&"RestElement"===e.value.params[0].type&&this.raise(i,ut.BadSetterRestParameter)}checkLVal(t,e=V,s,i,r){switch(t.type){case"ObjectPattern":t.properties.forEach(t=>{this.checkLVal("Property"===t.type?t.value:t,e,s,"object destructuring pattern",r)});break;default:super.checkLVal(t,e,s,i,r)}}checkProto(t,e,s,i){t.method||super.checkProto(t,e,s,i)}isValidDirective(t){var e;return"ExpressionStatement"===t.type&&"Literal"===t.expression.type&&"string"===typeof t.expression.value&&!(null==(e=t.expression.extra)?void 0:e.parenthesized)}stmtToDirective(t){const e=super.stmtToDirective(t),s=t.expression.value;return e.value.value=s,e}parseBlockBody(t,e,s,i){super.parseBlockBody(t,e,s,i);const r=t.directives.map(t=>this.directiveToStmt(t));t.body=r.concat(t.body),delete t.directives}pushClassMethod(t,e,s,i,r,n){this.parseMethod(e,s,i,r,n,"ClassMethod",!0),e.typeParameters&&(e.value.typeParameters=e.typeParameters,delete e.typeParameters),t.body.push(e)}parseExprAtom(t){switch(this.state.type){case d.num:case d.string:return this.estreeParseLiteral(this.state.value);case d.regexp:return this.estreeParseRegExpLiteral(this.state.value);case d.bigint:return this.estreeParseBigIntLiteral(this.state.value);case d._null:return this.estreeParseLiteral(null);case d._true:return this.estreeParseLiteral(!0);case d._false:return this.estreeParseLiteral(!1);default:return super.parseExprAtom(t)}}parseLiteral(t,e,s,i){const r=super.parseLiteral(t,e,s,i);return r.raw=r.extra.raw,delete r.extra,r}parseFunctionBody(t,e,s=!1){super.parseFunctionBody(t,e,s),t.expression="BlockStatement"!==t.body.type}parseMethod(t,e,s,i,r,n,a=!1){let o=this.startNode();return o.kind=t.kind,o=super.parseMethod(o,e,s,i,r,n,a),o.type="FunctionExpression",delete o.kind,t.value=o,n="ClassMethod"===n?"MethodDefinition":n,this.finishNode(t,n)}parseObjectMethod(t,e,s,i,r){const n=super.parseObjectMethod(t,e,s,i,r);return n&&(n.type="Property","method"===n.kind&&(n.kind="init"),n.shorthand=!1),n}parseObjectProperty(t,e,s,i,r){const n=super.parseObjectProperty(t,e,s,i,r);return n&&(n.kind="init",n.type="Property"),n}toAssignable(t){return ft(t)?(this.toAssignable(t.value),t):super.toAssignable(t)}toAssignableObjectExpressionProp(t,e){if("get"===t.kind||"set"===t.kind)throw this.raise(t.key.start,ut.PatternHasAccessor);if(t.method)throw this.raise(t.key.start,ut.PatternHasMethod);super.toAssignableObjectExpressionProp(t,e)}finishCallExpression(t,e){return super.finishCallExpression(t,e),"Import"===t.callee.type?(t.type="ImportExpression",t.source=t.arguments[0],delete t.arguments,delete t.callee):"CallExpression"===t.type&&(t.optional=!1),t}toReferencedListDeep(t,e){t&&super.toReferencedListDeep(t,e)}parseExport(t){switch(super.parseExport(t),t.type){case"ExportAllDeclaration":t.exported=null;break;case"ExportNamedDeclaration":1===t.specifiers.length&&"ExportNamespaceSpecifier"===t.specifiers[0].type&&(t.type="ExportAllDeclaration",t.exported=t.specifiers[0].exported,delete t.specifiers);break}return t}parseSubscript(...t){const e=super.parseSubscript(...t);return"MemberExpression"===e.type&&(e.optional=!1),e}};class yt{constructor(t,e,s,i){this.token=t,this.isExpr=!!e,this.preserveSpace=!!s,this.override=i}}const gt={braceStatement:new yt("{",!1),braceExpression:new yt("{",!0),templateQuasi:new yt("${",!1),parenStatement:new yt("(",!1),parenExpression:new yt("(",!0),template:new yt("`",!0,!0,t=>t.readTmplToken()),functionExpression:new yt("function",!0),functionStatement:new yt("function",!1)};d.parenR.updateContext=d.braceR.updateContext=function(){if(1===this.state.context.length)return void(this.state.exprAllowed=!0);let t=this.state.context.pop();t===gt.braceStatement&&"function"===this.curContext().token&&(t=this.state.context.pop()),this.state.exprAllowed=!t.isExpr},d.name.updateContext=function(t){let e=!1;t!==d.dot&&("of"===this.state.value&&!this.state.exprAllowed&&t!==d._function&&t!==d._class||"yield"===this.state.value&&this.prodParam.hasYield)&&(e=!0),this.state.exprAllowed=e,this.state.isIterator&&(this.state.isIterator=!1)},d.braceL.updateContext=function(t){this.state.context.push(this.braceIsBlock(t)?gt.braceStatement:gt.braceExpression),this.state.exprAllowed=!0},d.dollarBraceL.updateContext=function(){this.state.context.push(gt.templateQuasi),this.state.exprAllowed=!0},d.parenL.updateContext=function(t){const e=t===d._if||t===d._for||t===d._with||t===d._while;this.state.context.push(e?gt.parenStatement:gt.parenExpression),this.state.exprAllowed=!0},d.incDec.updateContext=function(){},d._function.updateContext=d._class.updateContext=function(t){t===d.dot||t===d.questionDot||(!t.beforeExpr||t===d.semi||t===d._else||t===d._return&&et.test(this.input.slice(this.state.lastTokEnd,this.state.start))||(t===d.colon||t===d.braceL)&&this.curContext()===gt.b_stat?this.state.context.push(gt.functionStatement):this.state.context.push(gt.functionExpression)),this.state.exprAllowed=!1},d.backQuote.updateContext=function(){this.curContext()===gt.template?this.state.context.pop():this.state.context.push(gt.template),this.state.exprAllowed=!1},d.star.updateContext=function(){this.state.exprAllowed=!1};let xt="ªµºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬˮͰ-ʹͶͷͺ-ͽͿΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙՠ-ֈא-תׯ-ײؠ-يٮٯٱ-ۓەۥۦۮۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪߴߵߺࠀ-ࠕࠚࠤࠨࡀ-ࡘࡠ-ࡪࢠ-ࢴࢶ-ࣇऄ-हऽॐक़-ॡॱ-ঀঅ-ঌএঐও-নপ-রলশ-হঽৎড়ঢ়য়-ৡৰৱৼਅ-ਊਏਐਓ-ਨਪ-ਰਲਲ਼ਵਸ਼ਸਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલળવ-હઽૐૠૡૹଅ-ଌଏଐଓ-ନପ-ରଲଳଵ-ହଽଡ଼ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கஙசஜஞடணதந-பம-ஹௐఅ-ఌఎ-ఐఒ-నప-హఽౘ-ౚౠౡಀಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠೡೱೲഄ-ഌഎ-ഐഒ-ഺഽൎൔ-ൖൟ-ൡൺ-ൿඅ-ඖක-නඳ-රලව-ෆก-ะาำเ-ๆກຂຄຆ-ຊຌ-ຣລວ-ະາຳຽເ-ໄໆໜ-ໟༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿၐ-ၕၚ-ၝၡၥၦၮ-ၰၵ-ႁႎႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛮ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡸᢀ-ᢨᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᲀ-ᲈᲐ-ᲺᲽ-Ჿᳩ-ᳬᳮ-ᳳᳵᳶᳺᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕ℘-ℝℤΩℨK-ℹℼ-ℿⅅ-ⅉⅎⅠ-ↈⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞ々-〇〡-〩〱-〵〸-〼ぁ-ゖ゛-ゟァ-ヺー-ヿㄅ-ㄯㄱ-ㆎㆠ-ㆿㇰ-ㇿ㐀-䶿一-鿼ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪꘫꙀ-ꙮꙿ-ꚝꚠ-ꛯꜗ-ꜟꜢ-ꞈꞋ-ꞿꟂ-ꟊꟵ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻꣽꣾꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺꩾ-ꪯꪱꪵꪶꪹ-ꪽꫀꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭩꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּסּףּפּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ",bt="‌‍·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-٩ٰۖ-ۜ۟-۪ۤۧۨ-ۭ۰-۹ܑܰ-݊ަ-ް߀-߉߫-߽߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛࣓-ࣣ࣡-ःऺ-़ा-ॏ॑-ॗॢॣ०-९ঁ-ঃ়া-ৄেৈো-্ৗৢৣ০-৯৾ਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑ੦-ੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣ૦-૯ૺ-૿ଁ-ଃ଼ା-ୄେୈୋ-୍୕-ୗୢୣ୦-୯ஂா-ூெ-ைொ-்ௗ௦-௯ఀ-ఄా-ౄె-ైొ-్ౕౖౢౣ౦-౯ಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣ೦-೯ഀ-ഃ഻഼ാ-ൄെ-ൈൊ-്ൗൢൣ൦-൯ඁ-ඃ්ා-ුූෘ-ෟ෦-෯ෲෳัิ-ฺ็-๎๐-๙ັິ-ຼ່-ໍ໐-໙༘༙༠-༩༹༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှ၀-၉ၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏ-ႝ፝-፟፩-፱ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝០-៩᠋-᠍᠐-᠙ᢩᤠ-ᤫᤰ-᤻᥆-᥏᧐-᧚ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼-᪉᪐-᪙᪰-᪽ᪿᫀᬀ-ᬄ᬴-᭄᭐-᭙᭫-᭳ᮀ-ᮂᮡ-ᮭ᮰-᮹᯦-᯳ᰤ-᰷᱀-᱉᱐-᱙᳐-᳔᳒-᳨᳭᳴᳷-᳹᷀-᷹᷻-᷿‿⁀⁔⃐-⃥⃜⃡-⃰⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꘠-꘩꙯ꙴ-꙽ꚞꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧ꠬ꢀꢁꢴ-ꣅ꣐-꣙꣠-꣱ꣿ-꤉ꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀꧐-꧙ꧥ꧰-꧹ꨩ-ꨶꩃꩌꩍ꩐-꩙ꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭꯰-꯹ﬞ︀-️︠-︯︳︴﹍-﹏0-9_";const vt=new RegExp("["+xt+"]"),wt=new RegExp("["+xt+bt+"]");xt=bt=null;const Pt=[0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,28,43,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,14,35,349,41,7,1,79,28,11,0,9,21,107,20,28,22,13,52,76,44,33,24,27,35,30,0,3,0,9,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,21,2,31,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,14,0,72,26,230,43,117,63,32,7,3,0,3,7,2,1,2,23,16,0,2,0,95,7,3,38,17,0,2,0,29,0,11,39,8,0,22,0,12,45,20,0,35,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,26,5,2,1,2,31,15,0,328,18,190,0,80,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,689,63,129,74,6,0,67,12,65,1,2,0,29,6135,9,1237,43,8,8952,286,50,2,18,3,9,395,2309,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,2357,44,11,6,17,0,370,43,1301,196,60,67,8,0,1205,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42717,35,4148,12,221,3,5761,15,7472,3104,541,1507,4938],Tt=[509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,370,1,154,10,176,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,6,1,45,0,13,2,49,13,9,3,2,11,83,11,7,0,161,11,6,9,7,3,56,1,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,5,0,82,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,243,14,166,9,71,5,2,1,3,3,2,0,2,1,13,9,120,6,3,6,4,0,29,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,49,4,2,1,2,4,9,9,330,3,19306,9,135,4,60,6,26,9,1014,0,2,54,8,3,82,0,12,1,19628,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,262,6,10,9,419,13,1495,6,110,6,6,9,4759,9,787719,239];function Et(t,e){let s=65536;for(let i=0,r=e.length;it)return!1;if(s+=e[i+1],s>=t)return!0}return!1}function At(t){return t<65?36===t:t<=90||(t<97?95===t:t<=122||(t<=65535?t>=170&&vt.test(String.fromCharCode(t)):Et(t,Pt)))}function St(t){return t<48?36===t:t<58||!(t<65)&&(t<=90||(t<97?95===t:t<=122||(t<=65535?t>=170&&wt.test(String.fromCharCode(t)):Et(t,Pt)||Et(t,Tt))))}const Ct={keyword:["break","case","catch","continue","debugger","default","do","else","finally","for","function","if","return","switch","throw","try","var","const","while","with","new","this","super","class","extends","export","import","null","true","false","in","instanceof","typeof","void","delete"],strict:["implements","interface","let","package","private","protected","public","static","yield"],strictBind:["eval","arguments"]},kt=new Set(Ct.keyword),Nt=new Set(Ct.strict),It=new Set(Ct.strictBind);function Ot(t,e){return e&&"await"===t||"enum"===t}function Dt(t,e){return Ot(t,e)||Nt.has(t)}function Mt(t){return It.has(t)}function Lt(t,e){return Dt(t,e)||Mt(t)}function _t(t){return kt.has(t)}const Rt=/^in(stanceof)?$/;function jt(t,e){return 64===t&&64===e}const Ft=new Set(["_","any","bool","boolean","empty","extends","false","interface","mixed","null","number","static","string","true","typeof","void"]),Bt=Object.freeze({AmbiguousConditionalArrow:"Ambiguous expression: wrap the arrow functions in parentheses to disambiguate.",AmbiguousDeclareModuleKind:"Found both `declare module.exports` and `declare export` in the same module. Modules can only have 1 since they are either an ES module or they are a CommonJS module",AssignReservedType:"Cannot overwrite reserved type %0",DeclareClassElement:"The `declare` modifier can only appear on class fields.",DeclareClassFieldInitializer:"Initializers are not allowed in fields with the `declare` modifier.",DuplicateDeclareModuleExports:"Duplicate `declare module.exports` statement",EnumBooleanMemberNotInitialized:"Boolean enum members need to be initialized. Use either `%0 = true,` or `%0 = false,` in enum `%1`.",EnumDuplicateMemberName:"Enum member names need to be unique, but the name `%0` has already been used before in enum `%1`.",EnumInconsistentMemberValues:"Enum `%0` has inconsistent member initializers. Either use no initializers, or consistently use literals (either booleans, numbers, or strings) for all member initializers.",EnumInvalidExplicitType:"Enum type `%1` is not valid. Use one of `boolean`, `number`, `string`, or `symbol` in enum `%0`.",EnumInvalidExplicitTypeUnknownSupplied:"Supplied enum type is not valid. Use one of `boolean`, `number`, `string`, or `symbol` in enum `%0`.",EnumInvalidMemberInitializerPrimaryType:"Enum `%0` has type `%2`, so the initializer of `%1` needs to be a %2 literal.",EnumInvalidMemberInitializerSymbolType:"Symbol enum members cannot be initialized. Use `%1,` in enum `%0`.",EnumInvalidMemberInitializerUnknownType:"The enum member initializer for `%1` needs to be a literal (either a boolean, number, or string) in enum `%0`.",EnumInvalidMemberName:"Enum member names cannot start with lowercase 'a' through 'z'. Instead of using `%0`, consider using `%1`, in enum `%2`.",EnumNumberMemberNotInitialized:"Number enum members need to be initialized, e.g. `%1 = 1` in enum `%0`.",EnumStringMemberInconsistentlyInitailized:"String enum members need to consistently either all use initializers, or use no initializers, in enum `%0`.",ImportTypeShorthandOnlyInPureImport:"The `type` and `typeof` keywords on named imports can only be used on regular `import` statements. It cannot be used with `import type` or `import typeof` statements",InexactInsideExact:"Explicit inexact syntax cannot appear inside an explicit exact object type",InexactInsideNonObject:"Explicit inexact syntax cannot appear in class or interface definitions",InexactVariance:"Explicit inexact syntax cannot have variance",InvalidNonTypeImportInDeclareModule:"Imports within a `declare module` body must always be `import type` or `import typeof`",MissingTypeParamDefault:"Type parameter declaration needs a default, since a preceding type parameter declaration has a default.",NestedDeclareModule:"`declare module` cannot be used inside another `declare module`",NestedFlowComment:"Cannot have a flow comment inside another flow comment",OptionalBindingPattern:"A binding pattern parameter cannot be optional in an implementation signature.",SpreadVariance:"Spread properties cannot have variance",TypeBeforeInitializer:"Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`",TypeCastInPattern:"The type cast expression is expected to be wrapped with parenthesis",UnexpectedExplicitInexactInObject:"Explicit inexact syntax must appear at the end of an inexact object",UnexpectedReservedType:"Unexpected reserved type %0",UnexpectedReservedUnderscore:"`_` is only allowed as a type argument to call or new",UnexpectedSpaceBetweenModuloChecks:"Spaces between `%` and `checks` are not allowed here.",UnexpectedSpreadType:"Spread operator cannot appear in class or interface definitions",UnexpectedSubtractionOperand:'Unexpected token, expected "number" or "bigint"',UnexpectedTokenAfterTypeParameter:"Expected an arrow function after this type parameter declaration",UnsupportedDeclareExportKind:"`declare export %0` is not supported. Use `%1` instead",UnsupportedStatementInDeclareModule:"Only declares and type imports are allowed inside declare module",UnterminatedFlowComment:"Unterminated flow-comment"});function Ut(t){return"DeclareExportAllDeclaration"===t.type||"DeclareExportDeclaration"===t.type&&(!t.declaration||"TypeAlias"!==t.declaration.type&&"InterfaceDeclaration"!==t.declaration.type)}function qt(t){return"type"===t.importKind||"typeof"===t.importKind}function Vt(t){return(t.type===d.name||!!t.type.keyword)&&"from"!==t.value}const Ht={const:"declare export var",let:"declare export var",type:"export type",interface:"export interface"};function zt(t,e){const s=[],i=[];for(let r=0;rclass extends t{constructor(t,e){super(t,e),this.flowPragma=void 0}shouldParseTypes(){return this.getPluginOption("flow","all")||"flow"===this.flowPragma}shouldParseEnums(){return!!this.getPluginOption("flow","enums")}finishToken(t,e){return t!==d.string&&t!==d.semi&&t!==d.interpreterDirective&&void 0===this.flowPragma&&(this.flowPragma=null),super.finishToken(t,e)}addComment(t){if(void 0===this.flowPragma){const e=Wt.exec(t.value);if(e)if("flow"===e[1])this.flowPragma="flow";else{if("noflow"!==e[1])throw new Error("Unexpected flow pragma");this.flowPragma="noflow"}else;}return super.addComment(t)}flowParseTypeInitialiser(t){const e=this.state.inType;this.state.inType=!0,this.expect(t||d.colon);const s=this.flowParseType();return this.state.inType=e,s}flowParsePredicate(){const t=this.startNode(),e=this.state.startLoc,s=this.state.start;this.expect(d.modulo);const i=this.state.startLoc;return this.expectContextual("checks"),e.line===i.line&&e.column===i.column-1||this.raise(s,Bt.UnexpectedSpaceBetweenModuloChecks),this.eat(d.parenL)?(t.value=this.parseExpression(),this.expect(d.parenR),this.finishNode(t,"DeclaredPredicate")):this.finishNode(t,"InferredPredicate")}flowParseTypeAndPredicateInitialiser(){const t=this.state.inType;this.state.inType=!0,this.expect(d.colon);let e=null,s=null;return this.match(d.modulo)?(this.state.inType=t,s=this.flowParsePredicate()):(e=this.flowParseType(),this.state.inType=t,this.match(d.modulo)&&(s=this.flowParsePredicate())),[e,s]}flowParseDeclareClass(t){return this.next(),this.flowParseInterfaceish(t,!0),this.finishNode(t,"DeclareClass")}flowParseDeclareFunction(t){this.next();const e=t.id=this.parseIdentifier(),s=this.startNode(),i=this.startNode();this.isRelational("<")?s.typeParameters=this.flowParseTypeParameterDeclaration():s.typeParameters=null,this.expect(d.parenL);const r=this.flowParseFunctionTypeParams();return s.params=r.params,s.rest=r.rest,this.expect(d.parenR),[s.returnType,t.predicate]=this.flowParseTypeAndPredicateInitialiser(),i.typeAnnotation=this.finishNode(s,"FunctionTypeAnnotation"),e.typeAnnotation=this.finishNode(i,"TypeAnnotation"),this.resetEndLocation(e),this.semicolon(),this.finishNode(t,"DeclareFunction")}flowParseDeclare(t,e){if(this.match(d._class))return this.flowParseDeclareClass(t);if(this.match(d._function))return this.flowParseDeclareFunction(t);if(this.match(d._var))return this.flowParseDeclareVariable(t);if(this.eatContextual("module"))return this.match(d.dot)?this.flowParseDeclareModuleExports(t):(e&&this.raise(this.state.lastTokStart,Bt.NestedDeclareModule),this.flowParseDeclareModule(t));if(this.isContextual("type"))return this.flowParseDeclareTypeAlias(t);if(this.isContextual("opaque"))return this.flowParseDeclareOpaqueType(t);if(this.isContextual("interface"))return this.flowParseDeclareInterface(t);if(this.match(d._export))return this.flowParseDeclareExportDeclaration(t,e);throw this.unexpected()}flowParseDeclareVariable(t){return this.next(),t.id=this.flowParseTypeAnnotatableIdentifier(!0),this.scope.declareName(t.id.name,R,t.id.start),this.semicolon(),this.finishNode(t,"DeclareVariable")}flowParseDeclareModule(t){this.scope.enter(f),this.match(d.string)?t.id=this.parseExprAtom():t.id=this.parseIdentifier();const e=t.body=this.startNode(),s=e.body=[];this.expect(d.braceL);while(!this.match(d.braceR)){let t=this.startNode();this.match(d._import)?(this.next(),this.isContextual("type")||this.match(d._typeof)||this.raise(this.state.lastTokStart,Bt.InvalidNonTypeImportInDeclareModule),this.parseImport(t)):(this.expectContextual("declare",Bt.UnsupportedStatementInDeclareModule),t=this.flowParseDeclare(t,!0)),s.push(t)}this.scope.exit(),this.expect(d.braceR),this.finishNode(e,"BlockStatement");let i=null,r=!1;return s.forEach(t=>{Ut(t)?("CommonJS"===i&&this.raise(t.start,Bt.AmbiguousDeclareModuleKind),i="ES"):"DeclareModuleExports"===t.type&&(r&&this.raise(t.start,Bt.DuplicateDeclareModuleExports),"ES"===i&&this.raise(t.start,Bt.AmbiguousDeclareModuleKind),i="CommonJS",r=!0)}),t.kind=i||"CommonJS",this.finishNode(t,"DeclareModule")}flowParseDeclareExportDeclaration(t,e){if(this.expect(d._export),this.eat(d._default))return this.match(d._function)||this.match(d._class)?t.declaration=this.flowParseDeclare(this.startNode()):(t.declaration=this.flowParseType(),this.semicolon()),t.default=!0,this.finishNode(t,"DeclareExportDeclaration");if(this.match(d._const)||this.isLet()||(this.isContextual("type")||this.isContextual("interface"))&&!e){const t=this.state.value,e=Ht[t];throw this.raise(this.state.start,Bt.UnsupportedDeclareExportKind,t,e)}if(this.match(d._var)||this.match(d._function)||this.match(d._class)||this.isContextual("opaque"))return t.declaration=this.flowParseDeclare(this.startNode()),t.default=!1,this.finishNode(t,"DeclareExportDeclaration");if(this.match(d.star)||this.match(d.braceL)||this.isContextual("interface")||this.isContextual("type")||this.isContextual("opaque"))return t=this.parseExport(t),"ExportNamedDeclaration"===t.type&&(t.type="ExportDeclaration",t.default=!1,delete t.exportKind),t.type="Declare"+t.type,t;throw this.unexpected()}flowParseDeclareModuleExports(t){return this.next(),this.expectContextual("exports"),t.typeAnnotation=this.flowParseTypeAnnotation(),this.semicolon(),this.finishNode(t,"DeclareModuleExports")}flowParseDeclareTypeAlias(t){return this.next(),this.flowParseTypeAlias(t),t.type="DeclareTypeAlias",t}flowParseDeclareOpaqueType(t){return this.next(),this.flowParseOpaqueType(t,!0),t.type="DeclareOpaqueType",t}flowParseDeclareInterface(t){return this.next(),this.flowParseInterfaceish(t),this.finishNode(t,"DeclareInterface")}flowParseInterfaceish(t,e=!1){if(t.id=this.flowParseRestrictedIdentifier(!e,!0),this.scope.declareName(t.id.name,e?j:_,t.id.start),this.isRelational("<")?t.typeParameters=this.flowParseTypeParameterDeclaration():t.typeParameters=null,t.extends=[],t.implements=[],t.mixins=[],this.eat(d._extends))do{t.extends.push(this.flowParseInterfaceExtends())}while(!e&&this.eat(d.comma));if(this.isContextual("mixins")){this.next();do{t.mixins.push(this.flowParseInterfaceExtends())}while(this.eat(d.comma))}if(this.isContextual("implements")){this.next();do{t.implements.push(this.flowParseInterfaceExtends())}while(this.eat(d.comma))}t.body=this.flowParseObjectType({allowStatic:e,allowExact:!1,allowSpread:!1,allowProto:e,allowInexact:!1})}flowParseInterfaceExtends(){const t=this.startNode();return t.id=this.flowParseQualifiedTypeIdentifier(),this.isRelational("<")?t.typeParameters=this.flowParseTypeParameterInstantiation():t.typeParameters=null,this.finishNode(t,"InterfaceExtends")}flowParseInterface(t){return this.flowParseInterfaceish(t),this.finishNode(t,"InterfaceDeclaration")}checkNotUnderscore(t){"_"===t&&this.raise(this.state.start,Bt.UnexpectedReservedUnderscore)}checkReservedType(t,e,s){Ft.has(t)&&this.raise(e,s?Bt.AssignReservedType:Bt.UnexpectedReservedType,t)}flowParseRestrictedIdentifier(t,e){return this.checkReservedType(this.state.value,this.state.start,e),this.parseIdentifier(t)}flowParseTypeAlias(t){return t.id=this.flowParseRestrictedIdentifier(!1,!0),this.scope.declareName(t.id.name,_,t.id.start),this.isRelational("<")?t.typeParameters=this.flowParseTypeParameterDeclaration():t.typeParameters=null,t.right=this.flowParseTypeInitialiser(d.eq),this.semicolon(),this.finishNode(t,"TypeAlias")}flowParseOpaqueType(t,e){return this.expectContextual("type"),t.id=this.flowParseRestrictedIdentifier(!0,!0),this.scope.declareName(t.id.name,_,t.id.start),this.isRelational("<")?t.typeParameters=this.flowParseTypeParameterDeclaration():t.typeParameters=null,t.supertype=null,this.match(d.colon)&&(t.supertype=this.flowParseTypeInitialiser(d.colon)),t.impltype=null,e||(t.impltype=this.flowParseTypeInitialiser(d.eq)),this.semicolon(),this.finishNode(t,"OpaqueType")}flowParseTypeParameter(t=!1){const e=this.state.start,s=this.startNode(),i=this.flowParseVariance(),r=this.flowParseTypeAnnotatableIdentifier();return s.name=r.name,s.variance=i,s.bound=r.typeAnnotation,this.match(d.eq)?(this.eat(d.eq),s.default=this.flowParseType()):t&&this.raise(e,Bt.MissingTypeParamDefault),this.finishNode(s,"TypeParameter")}flowParseTypeParameterDeclaration(){const t=this.state.inType,e=this.startNode();e.params=[],this.state.inType=!0,this.isRelational("<")||this.match(d.jsxTagStart)?this.next():this.unexpected();let s=!1;do{const t=this.flowParseTypeParameter(s);e.params.push(t),t.default&&(s=!0),this.isRelational(">")||this.expect(d.comma)}while(!this.isRelational(">"));return this.expectRelational(">"),this.state.inType=t,this.finishNode(e,"TypeParameterDeclaration")}flowParseTypeParameterInstantiation(){const t=this.startNode(),e=this.state.inType;t.params=[],this.state.inType=!0,this.expectRelational("<");const s=this.state.noAnonFunctionType;this.state.noAnonFunctionType=!1;while(!this.isRelational(">"))t.params.push(this.flowParseType()),this.isRelational(">")||this.expect(d.comma);return this.state.noAnonFunctionType=s,this.expectRelational(">"),this.state.inType=e,this.finishNode(t,"TypeParameterInstantiation")}flowParseTypeParameterInstantiationCallOrNew(){const t=this.startNode(),e=this.state.inType;t.params=[],this.state.inType=!0,this.expectRelational("<");while(!this.isRelational(">"))t.params.push(this.flowParseTypeOrImplicitInstantiation()),this.isRelational(">")||this.expect(d.comma);return this.expectRelational(">"),this.state.inType=e,this.finishNode(t,"TypeParameterInstantiation")}flowParseInterfaceType(){const t=this.startNode();if(this.expectContextual("interface"),t.extends=[],this.eat(d._extends))do{t.extends.push(this.flowParseInterfaceExtends())}while(this.eat(d.comma));return t.body=this.flowParseObjectType({allowStatic:!1,allowExact:!1,allowSpread:!1,allowProto:!1,allowInexact:!1}),this.finishNode(t,"InterfaceTypeAnnotation")}flowParseObjectPropertyKey(){return this.match(d.num)||this.match(d.string)?this.parseExprAtom():this.parseIdentifier(!0)}flowParseObjectTypeIndexer(t,e,s){return t.static=e,this.lookahead().type===d.colon?(t.id=this.flowParseObjectPropertyKey(),t.key=this.flowParseTypeInitialiser()):(t.id=null,t.key=this.flowParseType()),this.expect(d.bracketR),t.value=this.flowParseTypeInitialiser(),t.variance=s,this.finishNode(t,"ObjectTypeIndexer")}flowParseObjectTypeInternalSlot(t,e){return t.static=e,t.id=this.flowParseObjectPropertyKey(),this.expect(d.bracketR),this.expect(d.bracketR),this.isRelational("<")||this.match(d.parenL)?(t.method=!0,t.optional=!1,t.value=this.flowParseObjectTypeMethodish(this.startNodeAt(t.start,t.loc.start))):(t.method=!1,this.eat(d.question)&&(t.optional=!0),t.value=this.flowParseTypeInitialiser()),this.finishNode(t,"ObjectTypeInternalSlot")}flowParseObjectTypeMethodish(t){t.params=[],t.rest=null,t.typeParameters=null,this.isRelational("<")&&(t.typeParameters=this.flowParseTypeParameterDeclaration()),this.expect(d.parenL);while(!this.match(d.parenR)&&!this.match(d.ellipsis))t.params.push(this.flowParseFunctionTypeParam()),this.match(d.parenR)||this.expect(d.comma);return this.eat(d.ellipsis)&&(t.rest=this.flowParseFunctionTypeParam()),this.expect(d.parenR),t.returnType=this.flowParseTypeInitialiser(),this.finishNode(t,"FunctionTypeAnnotation")}flowParseObjectTypeCallProperty(t,e){const s=this.startNode();return t.static=e,t.value=this.flowParseObjectTypeMethodish(s),this.finishNode(t,"ObjectTypeCallProperty")}flowParseObjectType({allowStatic:t,allowExact:e,allowSpread:s,allowProto:i,allowInexact:r}){const n=this.state.inType;this.state.inType=!0;const a=this.startNode();let o,c;a.callProperties=[],a.properties=[],a.indexers=[],a.internalSlots=[];let h=!1;e&&this.match(d.braceBarL)?(this.expect(d.braceBarL),o=d.braceBarR,c=!0):(this.expect(d.braceL),o=d.braceR,c=!1),a.exact=c;while(!this.match(o)){let e=!1,n=null,o=null;const l=this.startNode();if(i&&this.isContextual("proto")){const e=this.lookahead();e.type!==d.colon&&e.type!==d.question&&(this.next(),n=this.state.start,t=!1)}if(t&&this.isContextual("static")){const t=this.lookahead();t.type!==d.colon&&t.type!==d.question&&(this.next(),e=!0)}const p=this.flowParseVariance();if(this.eat(d.bracketL))null!=n&&this.unexpected(n),this.eat(d.bracketL)?(p&&this.unexpected(p.start),a.internalSlots.push(this.flowParseObjectTypeInternalSlot(l,e))):a.indexers.push(this.flowParseObjectTypeIndexer(l,e,p));else if(this.match(d.parenL)||this.isRelational("<"))null!=n&&this.unexpected(n),p&&this.unexpected(p.start),a.callProperties.push(this.flowParseObjectTypeCallProperty(l,e));else{let t="init";if(this.isContextual("get")||this.isContextual("set")){const e=this.lookahead();e.type!==d.name&&e.type!==d.string&&e.type!==d.num||(t=this.state.value,this.next())}const i=this.flowParseObjectTypeProperty(l,e,n,p,t,s,null!=r?r:!c);null===i?(h=!0,o=this.state.lastTokStart):a.properties.push(i)}this.flowObjectTypeSemicolon(),!o||this.match(d.braceR)||this.match(d.braceBarR)||this.raise(o,Bt.UnexpectedExplicitInexactInObject)}this.expect(o),s&&(a.inexact=h);const l=this.finishNode(a,"ObjectTypeAnnotation");return this.state.inType=n,l}flowParseObjectTypeProperty(t,e,s,i,r,n,a){if(this.eat(d.ellipsis)){const e=this.match(d.comma)||this.match(d.semi)||this.match(d.braceR)||this.match(d.braceBarR);return e?(n?a||this.raise(this.state.lastTokStart,Bt.InexactInsideExact):this.raise(this.state.lastTokStart,Bt.InexactInsideNonObject),i&&this.raise(i.start,Bt.InexactVariance),null):(n||this.raise(this.state.lastTokStart,Bt.UnexpectedSpreadType),null!=s&&this.unexpected(s),i&&this.raise(i.start,Bt.SpreadVariance),t.argument=this.flowParseType(),this.finishNode(t,"ObjectTypeSpreadProperty"))}{t.key=this.flowParseObjectPropertyKey(),t.static=e,t.proto=null!=s,t.kind=r;let n=!1;return this.isRelational("<")||this.match(d.parenL)?(t.method=!0,null!=s&&this.unexpected(s),i&&this.unexpected(i.start),t.value=this.flowParseObjectTypeMethodish(this.startNodeAt(t.start,t.loc.start)),"get"!==r&&"set"!==r||this.flowCheckGetterSetterParams(t)):("init"!==r&&this.unexpected(),t.method=!1,this.eat(d.question)&&(n=!0),t.value=this.flowParseTypeInitialiser(),t.variance=i),t.optional=n,this.finishNode(t,"ObjectTypeProperty")}}flowCheckGetterSetterParams(t){const e="get"===t.kind?0:1,s=t.start,i=t.value.params.length+(t.value.rest?1:0);i!==e&&("get"===t.kind?this.raise(s,ut.BadGetterArity):this.raise(s,ut.BadSetterArity)),"set"===t.kind&&t.value.rest&&this.raise(s,ut.BadSetterRestParameter)}flowObjectTypeSemicolon(){this.eat(d.semi)||this.eat(d.comma)||this.match(d.braceR)||this.match(d.braceBarR)||this.unexpected()}flowParseQualifiedTypeIdentifier(t,e,s){t=t||this.state.start,e=e||this.state.startLoc;let i=s||this.flowParseRestrictedIdentifier(!0);while(this.eat(d.dot)){const s=this.startNodeAt(t,e);s.qualification=i,s.id=this.flowParseRestrictedIdentifier(!0),i=this.finishNode(s,"QualifiedTypeIdentifier")}return i}flowParseGenericType(t,e,s){const i=this.startNodeAt(t,e);return i.typeParameters=null,i.id=this.flowParseQualifiedTypeIdentifier(t,e,s),this.isRelational("<")&&(i.typeParameters=this.flowParseTypeParameterInstantiation()),this.finishNode(i,"GenericTypeAnnotation")}flowParseTypeofType(){const t=this.startNode();return this.expect(d._typeof),t.argument=this.flowParsePrimaryType(),this.finishNode(t,"TypeofTypeAnnotation")}flowParseTupleType(){const t=this.startNode();t.types=[],this.expect(d.bracketL);while(this.state.possuper.parseFunctionBody(t,!0,s)):super.parseFunctionBody(t,!1,s)}parseFunctionBodyAndFinish(t,e,s=!1){if(this.match(d.colon)){const e=this.startNode();[e.typeAnnotation,t.predicate]=this.flowParseTypeAndPredicateInitialiser(),t.returnType=e.typeAnnotation?this.finishNode(e,"TypeAnnotation"):null}super.parseFunctionBodyAndFinish(t,e,s)}parseStatement(t,e){if(this.state.strict&&this.match(d.name)&&"interface"===this.state.value){const t=this.startNode();return this.next(),this.flowParseInterface(t)}if(this.shouldParseEnums()&&this.isContextual("enum")){const t=this.startNode();return this.next(),this.flowParseEnumDeclaration(t)}{const s=super.parseStatement(t,e);return void 0!==this.flowPragma||this.isValidDirective(s)||(this.flowPragma=null),s}}parseExpressionStatement(t,e){if("Identifier"===e.type)if("declare"===e.name){if(this.match(d._class)||this.match(d.name)||this.match(d._function)||this.match(d._var)||this.match(d._export))return this.flowParseDeclare(t)}else if(this.match(d.name)){if("interface"===e.name)return this.flowParseInterface(t);if("type"===e.name)return this.flowParseTypeAlias(t);if("opaque"===e.name)return this.flowParseOpaqueType(t,!1)}return super.parseExpressionStatement(t,e)}shouldParseExportDeclaration(){return this.isContextual("type")||this.isContextual("interface")||this.isContextual("opaque")||this.shouldParseEnums()&&this.isContextual("enum")||super.shouldParseExportDeclaration()}isExportDefaultSpecifier(){return(!this.match(d.name)||!("type"===this.state.value||"interface"===this.state.value||"opaque"===this.state.value||this.shouldParseEnums()&&"enum"===this.state.value))&&super.isExportDefaultSpecifier()}parseExportDefaultExpression(){if(this.shouldParseEnums()&&this.isContextual("enum")){const t=this.startNode();return this.next(),this.flowParseEnumDeclaration(t)}return super.parseExportDefaultExpression()}parseConditional(t,e,s,i,r){if(!this.match(d.question))return t;if(r){const n=this.tryParse(()=>super.parseConditional(t,e,s,i));return n.node?(n.error&&(this.state=n.failState),n.node):(r.start=n.error.pos||this.state.start,t)}this.expect(d.question);const n=this.state.clone(),a=this.state.noArrowAt,o=this.startNodeAt(s,i);let{consequent:c,failed:h}=this.tryParseConditionalConsequent(),[l,p]=this.getArrowLikeExpressions(c);if(h||p.length>0){const t=[...a];if(p.length>0){this.state=n,this.state.noArrowAt=t;for(let e=0;e1&&this.raise(n.start,Bt.AmbiguousConditionalArrow),h&&1===l.length&&(this.state=n,this.state.noArrowAt=t.concat(l[0].start),({consequent:c,failed:h}=this.tryParseConditionalConsequent()))}return this.getArrowLikeExpressions(c,!0),this.state.noArrowAt=a,this.expect(d.colon),o.test=t,o.consequent=c,o.alternate=this.forwardNoArrowParamsConversionAt(o,()=>this.parseMaybeAssign(e,void 0,void 0,void 0)),this.finishNode(o,"ConditionalExpression")}tryParseConditionalConsequent(){this.state.noArrowParamsConversionAt.push(this.state.start);const t=this.parseMaybeAssign(),e=!this.match(d.colon);return this.state.noArrowParamsConversionAt.pop(),{consequent:t,failed:e}}getArrowLikeExpressions(t,e){const s=[t],i=[];while(0!==s.length){const t=s.pop();"ArrowFunctionExpression"===t.type?(t.typeParameters||!t.returnType?this.finishArrowValidation(t):i.push(t),s.push(t.body)):"ConditionalExpression"===t.type&&(s.push(t.consequent),s.push(t.alternate))}return e?(i.forEach(t=>this.finishArrowValidation(t)),[i,[]]):zt(i,t=>t.params.every(t=>this.isAssignable(t,!0)))}finishArrowValidation(t){var e;this.toAssignableList(t.params,null==(e=t.extra)?void 0:e.trailingComma),this.scope.enter(y|g),super.checkParams(t,!1,!0),this.scope.exit()}forwardNoArrowParamsConversionAt(t,e){let s;return-1!==this.state.noArrowParamsConversionAt.indexOf(t.start)?(this.state.noArrowParamsConversionAt.push(this.state.start),s=e(),this.state.noArrowParamsConversionAt.pop()):s=e(),s}parseParenItem(t,e,s){if(t=super.parseParenItem(t,e,s),this.eat(d.question)&&(t.optional=!0,this.resetEndLocation(t)),this.match(d.colon)){const i=this.startNodeAt(e,s);return i.expression=t,i.typeAnnotation=this.flowParseTypeAnnotation(),this.finishNode(i,"TypeCastExpression")}return t}assertModuleNodeAllowed(t){"ImportDeclaration"===t.type&&("type"===t.importKind||"typeof"===t.importKind)||"ExportNamedDeclaration"===t.type&&"type"===t.exportKind||"ExportAllDeclaration"===t.type&&"type"===t.exportKind||super.assertModuleNodeAllowed(t)}parseExport(t){const e=super.parseExport(t);return"ExportNamedDeclaration"!==e.type&&"ExportAllDeclaration"!==e.type||(e.exportKind=e.exportKind||"value"),e}parseExportDeclaration(t){if(this.isContextual("type")){t.exportKind="type";const e=this.startNode();return this.next(),this.match(d.braceL)?(t.specifiers=this.parseExportSpecifiers(),this.parseExportFrom(t),null):this.flowParseTypeAlias(e)}if(this.isContextual("opaque")){t.exportKind="type";const e=this.startNode();return this.next(),this.flowParseOpaqueType(e,!1)}if(this.isContextual("interface")){t.exportKind="type";const e=this.startNode();return this.next(),this.flowParseInterface(e)}if(this.shouldParseEnums()&&this.isContextual("enum")){t.exportKind="value";const e=this.startNode();return this.next(),this.flowParseEnumDeclaration(e)}return super.parseExportDeclaration(t)}eatExportStar(t){return!!super.eatExportStar(...arguments)||!(!this.isContextual("type")||this.lookahead().type!==d.star)&&(t.exportKind="type",this.next(),this.next(),!0)}maybeParseExportNamespaceSpecifier(t){const e=this.state.start,s=super.maybeParseExportNamespaceSpecifier(t);return s&&"type"===t.exportKind&&this.unexpected(e),s}parseClassId(t,e,s){super.parseClassId(t,e,s),this.isRelational("<")&&(t.typeParameters=this.flowParseTypeParameterDeclaration())}parseClassMember(t,e,s,i){const r=this.state.start;if(this.isContextual("declare")){if(this.parseClassMemberFromModifier(t,e))return;e.declare=!0}super.parseClassMember(t,e,s,i),e.declare&&("ClassProperty"!==e.type&&"ClassPrivateProperty"!==e.type?this.raise(r,Bt.DeclareClassElement):e.value&&this.raise(e.value.start,Bt.DeclareClassFieldInitializer))}getTokenFromCode(t){const e=this.input.charCodeAt(this.state.pos+1);return 123===t&&124===e?this.finishOp(d.braceBarL,2):!this.state.inType||62!==t&&60!==t?jt(t,e)?(this.state.isIterator=!0,super.readWord()):super.getTokenFromCode(t):this.finishOp(d.relational,1)}isAssignable(t,e){switch(t.type){case"Identifier":case"ObjectPattern":case"ArrayPattern":case"AssignmentPattern":return!0;case"ObjectExpression":{const e=t.properties.length-1;return t.properties.every((t,s)=>"ObjectMethod"!==t.type&&(s===e||"SpreadElement"===t.type)&&this.isAssignable(t))}case"ObjectProperty":return this.isAssignable(t.value);case"SpreadElement":return this.isAssignable(t.argument);case"ArrayExpression":return t.elements.every(t=>this.isAssignable(t));case"AssignmentExpression":return"="===t.operator;case"ParenthesizedExpression":case"TypeCastExpression":return this.isAssignable(t.expression);case"MemberExpression":case"OptionalMemberExpression":return!e;default:return!1}}toAssignable(t){return"TypeCastExpression"===t.type?super.toAssignable(this.typeCastToParameter(t)):super.toAssignable(t)}toAssignableList(t,e){for(let s=0;s1||!e)&&this.raise(r.typeAnnotation.start,Bt.TypeCastInPattern)}return t}checkLVal(t,e=V,s,i){if("TypeCastExpression"!==t.type)return super.checkLVal(t,e,s,i)}parseClassProperty(t){return this.match(d.colon)&&(t.typeAnnotation=this.flowParseTypeAnnotation()),super.parseClassProperty(t)}parseClassPrivateProperty(t){return this.match(d.colon)&&(t.typeAnnotation=this.flowParseTypeAnnotation()),super.parseClassPrivateProperty(t)}isClassMethod(){return this.isRelational("<")||super.isClassMethod()}isClassProperty(){return this.match(d.colon)||super.isClassProperty()}isNonstaticConstructor(t){return!this.match(d.colon)&&super.isNonstaticConstructor(t)}pushClassMethod(t,e,s,i,r,n){e.variance&&this.unexpected(e.variance.start),delete e.variance,this.isRelational("<")&&(e.typeParameters=this.flowParseTypeParameterDeclaration()),super.pushClassMethod(t,e,s,i,r,n)}pushClassPrivateMethod(t,e,s,i){e.variance&&this.unexpected(e.variance.start),delete e.variance,this.isRelational("<")&&(e.typeParameters=this.flowParseTypeParameterDeclaration()),super.pushClassPrivateMethod(t,e,s,i)}parseClassSuper(t){if(super.parseClassSuper(t),t.superClass&&this.isRelational("<")&&(t.superTypeParameters=this.flowParseTypeParameterInstantiation()),this.isContextual("implements")){this.next();const e=t.implements=[];do{const t=this.startNode();t.id=this.flowParseRestrictedIdentifier(!0),this.isRelational("<")?t.typeParameters=this.flowParseTypeParameterInstantiation():t.typeParameters=null,e.push(this.finishNode(t,"ClassImplements"))}while(this.eat(d.comma))}}parsePropertyName(t,e){const s=this.flowParseVariance(),i=super.parsePropertyName(t,e);return t.variance=s,i}parseObjPropValue(t,e,s,i,r,n,a,o){let c;t.variance&&this.unexpected(t.variance.start),delete t.variance,this.isRelational("<")&&(c=this.flowParseTypeParameterDeclaration(),this.match(d.parenL)||this.unexpected()),super.parseObjPropValue(t,e,s,i,r,n,a,o),c&&((t.value||t).typeParameters=c)}parseAssignableListItemTypes(t){return this.eat(d.question)&&("Identifier"!==t.type&&this.raise(t.start,Bt.OptionalBindingPattern),t.optional=!0),this.match(d.colon)&&(t.typeAnnotation=this.flowParseTypeAnnotation()),this.resetEndLocation(t),t}parseMaybeDefault(t,e,s){const i=super.parseMaybeDefault(t,e,s);return"AssignmentPattern"===i.type&&i.typeAnnotation&&i.right.startsuper.parseMaybeAssign(t,e,s,i),a),!n.error)return n.node;const{context:r}=this.state;r[r.length-1]===gt.j_oTag?r.length-=2:r[r.length-1]===gt.j_expr&&(r.length-=1)}if((null==(r=n)?void 0:r.error)||this.isRelational("<")){var o,c,h;let r;a=a||this.state.clone();const l=this.tryParse(()=>{r=this.flowParseTypeParameterDeclaration();const n=this.forwardNoArrowParamsConversionAt(r,()=>super.parseMaybeAssign(t,e,s,i));return n.typeParameters=r,this.resetStartLocationFromNode(n,r),n},a),p="ArrowFunctionExpression"===(null==(o=l.node)?void 0:o.type)?l.node:null;if(!l.error&&p)return p;if(null==(c=n)?void 0:c.node)return this.state=n.failState,n.node;if(p)return this.state=l.failState,p;if(null==(h=n)?void 0:h.thrown)throw n.error;if(l.thrown)throw l.error;throw this.raise(r.start,Bt.UnexpectedTokenAfterTypeParameter)}return super.parseMaybeAssign(t,e,s,i)}parseArrow(t){if(this.match(d.colon)){const e=this.tryParse(()=>{const e=this.state.noAnonFunctionType;this.state.noAnonFunctionType=!0;const s=this.startNode();return[s.typeAnnotation,t.predicate]=this.flowParseTypeAndPredicateInitialiser(),this.state.noAnonFunctionType=e,this.canInsertSemicolon()&&this.unexpected(),this.match(d.arrow)||this.unexpected(),s});if(e.thrown)return null;e.error&&(this.state=e.failState),t.returnType=e.node.typeAnnotation?this.finishNode(e.node,"TypeAnnotation"):null}return super.parseArrow(t)}shouldParseArrow(){return this.match(d.colon)||super.shouldParseArrow()}setArrowFunctionParameters(t,e){-1!==this.state.noArrowParamsConversionAt.indexOf(t.start)?t.params=e:super.setArrowFunctionParameters(t,e)}checkParams(t,e,s){if(!s||-1===this.state.noArrowParamsConversionAt.indexOf(t.start))return super.checkParams(...arguments)}parseParenAndDistinguishExpression(t){return super.parseParenAndDistinguishExpression(t&&-1===this.state.noArrowAt.indexOf(this.state.start))}parseSubscripts(t,e,s,i){if("Identifier"===t.type&&"async"===t.name&&-1!==this.state.noArrowAt.indexOf(e)){this.next();const i=this.startNodeAt(e,s);i.callee=t,i.arguments=this.parseCallExpressionArguments(d.parenR,!1),t=this.finishNode(i,"CallExpression")}else if("Identifier"===t.type&&"async"===t.name&&this.isRelational("<")){const r=this.state.clone(),n=this.tryParse(t=>this.parseAsyncArrowWithTypeParameters(e,s)||t(),r);if(!n.error&&!n.aborted)return n.node;const a=this.tryParse(()=>super.parseSubscripts(t,e,s,i),r);if(a.node&&!a.error)return a.node;if(n.node)return this.state=n.failState,n.node;if(a.node)return this.state=a.failState,a.node;throw n.error||a.error}return super.parseSubscripts(t,e,s,i)}parseSubscript(t,e,s,i,r){if(this.match(d.questionDot)&&this.isLookaheadRelational("<")){if(r.optionalChainMember=!0,i)return r.stop=!0,t;this.next();const n=this.startNodeAt(e,s);return n.callee=t,n.typeArguments=this.flowParseTypeParameterInstantiation(),this.expect(d.parenL),n.arguments=this.parseCallExpressionArguments(d.parenR,!1),n.optional=!0,this.finishCallExpression(n,!0)}if(!i&&this.shouldParseTypes()&&this.isRelational("<")){const i=this.startNodeAt(e,s);i.callee=t;const n=this.tryParse(()=>(i.typeArguments=this.flowParseTypeParameterInstantiationCallOrNew(),this.expect(d.parenL),i.arguments=this.parseCallExpressionArguments(d.parenR,!1),r.optionalChainMember&&(i.optional=!1),this.finishCallExpression(i,r.optionalChainMember)));if(n.node)return n.error&&(this.state=n.failState),n.node}return super.parseSubscript(t,e,s,i,r)}parseNewArguments(t){let e=null;this.shouldParseTypes()&&this.isRelational("<")&&(e=this.tryParse(()=>this.flowParseTypeParameterInstantiationCallOrNew()).node),t.typeArguments=e,super.parseNewArguments(t)}parseAsyncArrowWithTypeParameters(t,e){const s=this.startNodeAt(t,e);if(this.parseFunctionParams(s),this.parseArrow(s))return this.parseArrowExpression(s,void 0,!0)}readToken_mult_modulo(t){const e=this.input.charCodeAt(this.state.pos+1);if(42===t&&47===e&&this.state.hasFlowComment)return this.state.hasFlowComment=!1,this.state.pos+=2,void this.nextToken();super.readToken_mult_modulo(t)}readToken_pipe_amp(t){const e=this.input.charCodeAt(this.state.pos+1);124!==t||125!==e?super.readToken_pipe_amp(t):this.finishOp(d.braceBarR,2)}parseTopLevel(t,e){const s=super.parseTopLevel(t,e);return this.state.hasFlowComment&&this.raise(this.state.pos,Bt.UnterminatedFlowComment),s}skipBlockComment(){if(this.hasPlugin("flowComments")&&this.skipFlowComment())return this.state.hasFlowComment&&this.unexpected(null,Bt.NestedFlowComment),this.hasFlowCommentCompletion(),this.state.pos+=this.skipFlowComment(),void(this.state.hasFlowComment=!0);if(this.state.hasFlowComment){const t=this.input.indexOf("*-/",this.state.pos+=2);if(-1===t)throw this.raise(this.state.pos-2,ut.UnterminatedComment);this.state.pos=t+3}else super.skipBlockComment()}skipFlowComment(){const{pos:t}=this.state;let e=2;while([32,9].includes(this.input.charCodeAt(t+e)))e++;const s=this.input.charCodeAt(e+t),i=this.input.charCodeAt(e+t+1);return 58===s&&58===i?e+2:"flow-include"===this.input.slice(e+t,e+t+12)?e+12:58===s&&58!==i&&e}hasFlowCommentCompletion(){const t=this.input.indexOf("*/",this.state.pos);if(-1===t)throw this.raise(this.state.pos,ut.UnterminatedComment)}flowEnumErrorBooleanMemberNotInitialized(t,{enumName:e,memberName:s}){this.raise(t,Bt.EnumBooleanMemberNotInitialized,s,e)}flowEnumErrorInvalidMemberName(t,{enumName:e,memberName:s}){const i=s[0].toUpperCase()+s.slice(1);this.raise(t,Bt.EnumInvalidMemberName,s,i,e)}flowEnumErrorDuplicateMemberName(t,{enumName:e,memberName:s}){this.raise(t,Bt.EnumDuplicateMemberName,s,e)}flowEnumErrorInconsistentMemberValues(t,{enumName:e}){this.raise(t,Bt.EnumInconsistentMemberValues,e)}flowEnumErrorInvalidExplicitType(t,{enumName:e,suppliedType:s}){return this.raise(t,null===s?Bt.EnumInvalidExplicitTypeUnknownSupplied:Bt.EnumInvalidExplicitType,e,s)}flowEnumErrorInvalidMemberInitializer(t,{enumName:e,explicitType:s,memberName:i}){let r=null;switch(s){case"boolean":case"number":case"string":r=Bt.EnumInvalidMemberInitializerPrimaryType;break;case"symbol":r=Bt.EnumInvalidMemberInitializerSymbolType;break;default:r=Bt.EnumInvalidMemberInitializerUnknownType}return this.raise(t,r,e,i,s)}flowEnumErrorNumberMemberNotInitialized(t,{enumName:e,memberName:s}){this.raise(t,Bt.EnumNumberMemberNotInitialized,e,s)}flowEnumErrorStringMemberInconsistentlyInitailized(t,{enumName:e}){this.raise(t,Bt.EnumStringMemberInconsistentlyInitailized,e)}flowEnumMemberInit(){const t=this.state.start,e=()=>this.match(d.comma)||this.match(d.braceR);switch(this.state.type){case d.num:{const s=this.parseLiteral(this.state.value,"NumericLiteral");return e()?{type:"number",pos:s.start,value:s}:{type:"invalid",pos:t}}case d.string:{const s=this.parseLiteral(this.state.value,"StringLiteral");return e()?{type:"string",pos:s.start,value:s}:{type:"invalid",pos:t}}case d._true:case d._false:{const s=this.parseBooleanLiteral();return e()?{type:"boolean",pos:s.start,value:s}:{type:"invalid",pos:t}}default:return{type:"invalid",pos:t}}}flowEnumMemberRaw(){const t=this.state.start,e=this.parseIdentifier(!0),s=this.eat(d.eq)?this.flowEnumMemberInit():{type:"none",pos:t};return{id:e,init:s}}flowEnumCheckExplicitTypeMismatch(t,e,s){const{explicitType:i}=e;null!==i&&i!==s&&this.flowEnumErrorInvalidMemberInitializer(t,e)}flowEnumMembers({enumName:t,explicitType:e}){const s=new Set,i={booleanMembers:[],numberMembers:[],stringMembers:[],defaultedMembers:[]};while(!this.match(d.braceR)){const r=this.startNode(),{id:n,init:a}=this.flowEnumMemberRaw(),o=n.name;if(""===o)continue;/^[a-z]/.test(o)&&this.flowEnumErrorInvalidMemberName(n.start,{enumName:t,memberName:o}),s.has(o)&&this.flowEnumErrorDuplicateMemberName(n.start,{enumName:t,memberName:o}),s.add(o);const c={enumName:t,explicitType:e,memberName:o};switch(r.id=n,a.type){case"boolean":this.flowEnumCheckExplicitTypeMismatch(a.pos,c,"boolean"),r.init=a.value,i.booleanMembers.push(this.finishNode(r,"EnumBooleanMember"));break;case"number":this.flowEnumCheckExplicitTypeMismatch(a.pos,c,"number"),r.init=a.value,i.numberMembers.push(this.finishNode(r,"EnumNumberMember"));break;case"string":this.flowEnumCheckExplicitTypeMismatch(a.pos,c,"string"),r.init=a.value,i.stringMembers.push(this.finishNode(r,"EnumStringMember"));break;case"invalid":throw this.flowEnumErrorInvalidMemberInitializer(a.pos,c);case"none":switch(e){case"boolean":this.flowEnumErrorBooleanMemberNotInitialized(a.pos,c);break;case"number":this.flowEnumErrorNumberMemberNotInitialized(a.pos,c);break;default:i.defaultedMembers.push(this.finishNode(r,"EnumDefaultedMember"))}}this.match(d.braceR)||this.expect(d.comma)}return i}flowEnumStringMembers(t,e,{enumName:s}){if(0===t.length)return e;if(0===e.length)return t;if(e.length>t.length){for(let e=0;e(t.members=[],this.expect(d.braceR),this.finishNode(t,"EnumStringBody"));t.explicitType=!1;const n=r.booleanMembers.length,a=r.numberMembers.length,o=r.stringMembers.length,c=r.defaultedMembers.length;if(n||a||o||c){if(n||a){if(!a&&!o&&n>=c){for(let t=0,s=r.defaultedMembers;t=c){for(let t=0,s=r.defaultedMembers;t",nbsp:" ",iexcl:"¡",cent:"¢",pound:"£",curren:"¤",yen:"¥",brvbar:"¦",sect:"§",uml:"¨",copy:"©",ordf:"ª",laquo:"«",not:"¬",shy:"­",reg:"®",macr:"¯",deg:"°",plusmn:"±",sup2:"²",sup3:"³",acute:"´",micro:"µ",para:"¶",middot:"·",cedil:"¸",sup1:"¹",ordm:"º",raquo:"»",frac14:"¼",frac12:"½",frac34:"¾",iquest:"¿",Agrave:"À",Aacute:"Á",Acirc:"Â",Atilde:"Ã",Auml:"Ä",Aring:"Å",AElig:"Æ",Ccedil:"Ç",Egrave:"È",Eacute:"É",Ecirc:"Ê",Euml:"Ë",Igrave:"Ì",Iacute:"Í",Icirc:"Î",Iuml:"Ï",ETH:"Ð",Ntilde:"Ñ",Ograve:"Ò",Oacute:"Ó",Ocirc:"Ô",Otilde:"Õ",Ouml:"Ö",times:"×",Oslash:"Ø",Ugrave:"Ù",Uacute:"Ú",Ucirc:"Û",Uuml:"Ü",Yacute:"Ý",THORN:"Þ",szlig:"ß",agrave:"à",aacute:"á",acirc:"â",atilde:"ã",auml:"ä",aring:"å",aelig:"æ",ccedil:"ç",egrave:"è",eacute:"é",ecirc:"ê",euml:"ë",igrave:"ì",iacute:"í",icirc:"î",iuml:"ï",eth:"ð",ntilde:"ñ",ograve:"ò",oacute:"ó",ocirc:"ô",otilde:"õ",ouml:"ö",divide:"÷",oslash:"ø",ugrave:"ù",uacute:"ú",ucirc:"û",uuml:"ü",yacute:"ý",thorn:"þ",yuml:"ÿ",OElig:"Œ",oelig:"œ",Scaron:"Š",scaron:"š",Yuml:"Ÿ",fnof:"ƒ",circ:"ˆ",tilde:"˜",Alpha:"Α",Beta:"Β",Gamma:"Γ",Delta:"Δ",Epsilon:"Ε",Zeta:"Ζ",Eta:"Η",Theta:"Θ",Iota:"Ι",Kappa:"Κ",Lambda:"Λ",Mu:"Μ",Nu:"Ν",Xi:"Ξ",Omicron:"Ο",Pi:"Π",Rho:"Ρ",Sigma:"Σ",Tau:"Τ",Upsilon:"Υ",Phi:"Φ",Chi:"Χ",Psi:"Ψ",Omega:"Ω",alpha:"α",beta:"β",gamma:"γ",delta:"δ",epsilon:"ε",zeta:"ζ",eta:"η",theta:"θ",iota:"ι",kappa:"κ",lambda:"λ",mu:"μ",nu:"ν",xi:"ξ",omicron:"ο",pi:"π",rho:"ρ",sigmaf:"ς",sigma:"σ",tau:"τ",upsilon:"υ",phi:"φ",chi:"χ",psi:"ψ",omega:"ω",thetasym:"ϑ",upsih:"ϒ",piv:"ϖ",ensp:" ",emsp:" ",thinsp:" ",zwnj:"‌",zwj:"‍",lrm:"‎",rlm:"‏",ndash:"–",mdash:"—",lsquo:"‘",rsquo:"’",sbquo:"‚",ldquo:"“",rdquo:"”",bdquo:"„",dagger:"†",Dagger:"‡",bull:"•",hellip:"…",permil:"‰",prime:"′",Prime:"″",lsaquo:"‹",rsaquo:"›",oline:"‾",frasl:"⁄",euro:"€",image:"ℑ",weierp:"℘",real:"ℜ",trade:"™",alefsym:"ℵ",larr:"←",uarr:"↑",rarr:"→",darr:"↓",harr:"↔",crarr:"↵",lArr:"⇐",uArr:"⇑",rArr:"⇒",dArr:"⇓",hArr:"⇔",forall:"∀",part:"∂",exist:"∃",empty:"∅",nabla:"∇",isin:"∈",notin:"∉",ni:"∋",prod:"∏",sum:"∑",minus:"−",lowast:"∗",radic:"√",prop:"∝",infin:"∞",ang:"∠",and:"∧",or:"∨",cap:"∩",cup:"∪",int:"∫",there4:"∴",sim:"∼",cong:"≅",asymp:"≈",ne:"≠",equiv:"≡",le:"≤",ge:"≥",sub:"⊂",sup:"⊃",nsub:"⊄",sube:"⊆",supe:"⊇",oplus:"⊕",otimes:"⊗",perp:"⊥",sdot:"⋅",lceil:"⌈",rceil:"⌉",lfloor:"⌊",rfloor:"⌋",lang:"〈",rang:"〉",loz:"◊",spades:"♠",clubs:"♣",hearts:"♥",diams:"♦"},Xt=/^[\da-fA-F]+$/,Gt=/^\d+$/,Yt=Object.freeze({AttributeIsEmpty:"JSX attributes must only be assigned a non-empty expression",MissingClosingTagFragment:"Expected corresponding JSX closing tag for <>",MissingClosingTagElement:"Expected corresponding JSX closing tag for <%0>",UnsupportedJsxValue:"JSX value should be either an expression or a quoted JSX text",UnterminatedJsxContent:"Unterminated JSX contents",UnwrappedAdjacentJSXElements:"Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...?"});function Jt(t){return!!t&&("JSXOpeningFragment"===t.type||"JSXClosingFragment"===t.type)}function Qt(t){if("JSXIdentifier"===t.type)return t.name;if("JSXNamespacedName"===t.type)return t.namespace.name+":"+t.name.name;if("JSXMemberExpression"===t.type)return Qt(t.object)+"."+Qt(t.property);throw new Error("Node had unexpected type: "+t.type)}gt.j_oTag=new yt("...",!0,!0),d.jsxName=new h("jsxName"),d.jsxText=new h("jsxText",{beforeExpr:!0}),d.jsxTagStart=new h("jsxTagStart",{startsExpr:!0}),d.jsxTagEnd=new h("jsxTagEnd"),d.jsxTagStart.updateContext=function(){this.state.context.push(gt.j_expr),this.state.context.push(gt.j_oTag),this.state.exprAllowed=!1},d.jsxTagEnd.updateContext=function(t){const e=this.state.context.pop();e===gt.j_oTag&&t===d.slash||e===gt.j_cTag?(this.state.context.pop(),this.state.exprAllowed=this.curContext()===gt.j_expr):this.state.exprAllowed=!0};var Zt=t=>class extends t{jsxReadToken(){let t="",e=this.state.pos;for(;;){if(this.state.pos>=this.length)throw this.raise(this.state.start,Yt.UnterminatedJsxContent);const s=this.input.charCodeAt(this.state.pos);switch(s){case 60:case 123:return this.state.pos===this.state.start?60===s&&this.state.exprAllowed?(++this.state.pos,this.finishToken(d.jsxTagStart)):super.getTokenFromCode(s):(t+=this.input.slice(e,this.state.pos),this.finishToken(d.jsxText,t));case 38:t+=this.input.slice(e,this.state.pos),t+=this.jsxReadEntity(),e=this.state.pos;break;default:it(s)?(t+=this.input.slice(e,this.state.pos),t+=this.jsxReadNewLine(!0),e=this.state.pos):++this.state.pos}}}jsxReadNewLine(t){const e=this.input.charCodeAt(this.state.pos);let s;return++this.state.pos,13===e&&10===this.input.charCodeAt(this.state.pos)?(++this.state.pos,s=t?"\n":"\r\n"):s=String.fromCharCode(e),++this.state.curLine,this.state.lineStart=this.state.pos,s}jsxReadString(t){let e="",s=++this.state.pos;for(;;){if(this.state.pos>=this.length)throw this.raise(this.state.start,ut.UnterminatedString);const i=this.input.charCodeAt(this.state.pos);if(i===t)break;38===i?(e+=this.input.slice(s,this.state.pos),e+=this.jsxReadEntity(),s=this.state.pos):it(i)?(e+=this.input.slice(s,this.state.pos),e+=this.jsxReadNewLine(!1),s=this.state.pos):++this.state.pos}return e+=this.input.slice(s,this.state.pos++),this.finishToken(d.string,e)}jsxReadEntity(){let t,e="",s=0,i=this.input[this.state.pos];const r=++this.state.pos;while(this.state.pos0}get allowSuper(){return(this.currentThisScope().flags&b)>0}get allowDirectSuper(){return(this.currentThisScope().flags&v)>0}get inClass(){return(this.currentThisScope().flags&w)>0}get inNonArrowFunction(){return(this.currentThisScope().flags&y)>0}get treatFunctionsAsVar(){return this.treatFunctionsAsVarInScope(this.currentScope())}createScope(t){return new te(t)}enter(t){this.scopeStack.push(this.createScope(t))}exit(){this.scopeStack.pop()}treatFunctionsAsVarInScope(t){return!!(t.flags&y||!this.inModule&&t.flags&m)}declareName(t,e,s){let i=this.currentScope();if(e&C||e&k)this.checkRedeclarationInScope(i,t,e,s),e&k?i.functions.push(t):i.lexical.push(t),e&C&&this.maybeExportDefined(i,t);else if(e&S)for(let r=this.scopeStack.length-1;r>=0;--r)if(i=this.scopeStack[r],this.checkRedeclarationInScope(i,t,e,s),i.var.push(t),this.maybeExportDefined(i,t),i.flags&T)break;this.inModule&&i.flags&m&&this.undefinedExports.delete(t)}maybeExportDefined(t,e){this.inModule&&t.flags&m&&this.undefinedExports.delete(e)}checkRedeclarationInScope(t,e,s,i){this.isRedeclaredInScope(t,e,s)&&this.raise(i,ut.VarRedeclaration,e)}isRedeclaredInScope(t,e,s){return!!(s&E)&&(s&C?t.lexical.indexOf(e)>-1||t.functions.indexOf(e)>-1||t.var.indexOf(e)>-1:s&k?t.lexical.indexOf(e)>-1||!this.treatFunctionsAsVarInScope(t)&&t.var.indexOf(e)>-1:t.lexical.indexOf(e)>-1&&!(t.flags&x&&t.lexical[0]===e)||!this.treatFunctionsAsVarInScope(t)&&t.functions.indexOf(e)>-1)}checkLocalExport(t){-1===this.scopeStack[0].lexical.indexOf(t.name)&&-1===this.scopeStack[0].var.indexOf(t.name)&&-1===this.scopeStack[0].functions.indexOf(t.name)&&this.undefinedExports.set(t.name,t.start)}currentScope(){return this.scopeStack[this.scopeStack.length-1]}currentVarScope(){for(let t=this.scopeStack.length-1;;t--){const e=this.scopeStack[t];if(e.flags&T)return e}}currentThisScope(){for(let t=this.scopeStack.length-1;;t--){const e=this.scopeStack[t];if((e.flags&T||e.flags&w)&&!(e.flags&g))return e}}}class se extends te{constructor(...t){super(...t),this.types=[],this.enums=[],this.constEnums=[],this.classes=[],this.exportOnlyBindings=[]}}class ie extends ee{createScope(t){return new se(t)}declareName(t,e,s){const i=this.currentScope();if(e&M)return this.maybeExportDefined(i,t),void i.exportOnlyBindings.push(t);super.declareName(...arguments),e&A&&(e&E||(this.checkRedeclarationInScope(i,t,e,s),this.maybeExportDefined(i,t)),i.types.push(t)),e&O&&i.enums.push(t),e&D&&i.constEnums.push(t),e&I&&i.classes.push(t)}isRedeclaredInScope(t,e,s){if(t.enums.indexOf(e)>-1){if(s&O){const i=!!(s&D),r=t.constEnums.indexOf(e)>-1;return i!==r}return!0}return s&I&&t.classes.indexOf(e)>-1?t.lexical.indexOf(e)>-1&&!!(s&E):!!(s&A&&t.types.indexOf(e)>-1)||super.isRedeclaredInScope(...arguments)}checkLocalExport(t){-1===this.scopeStack[0].types.indexOf(t.name)&&-1===this.scopeStack[0].exportOnlyBindings.indexOf(t.name)&&super.checkLocalExport(t)}}const re=0,ne=1,ae=2,oe=4;class ce{constructor(){this.stacks=[]}enter(t){this.stacks.push(t)}exit(){this.stacks.pop()}currentFlags(){return this.stacks[this.stacks.length-1]}get hasAwait(){return(this.currentFlags()&ae)>0}get hasYield(){return(this.currentFlags()&ne)>0}get hasReturn(){return(this.currentFlags()&oe)>0}}function he(t,e){return(t?ae:0)|(e?ne:0)}function le(t){if(null==t)throw new Error(`Unexpected ${t} value.`);return t}function pe(t){if(!t)throw new Error("Assert fail")}const ue=Object.freeze({ClassMethodHasDeclare:"Class methods cannot have the 'declare' modifier",ClassMethodHasReadonly:"Class methods cannot have the 'readonly' modifier",DeclareClassFieldHasInitializer:"'declare' class fields cannot have an initializer",DuplicateModifier:"Duplicate modifier: '%0'",EmptyHeritageClauseType:"'%0' list cannot be empty.",IndexSignatureHasAbstract:"Index signatures cannot have the 'abstract' modifier",IndexSignatureHasAccessibility:"Index signatures cannot have an accessibility modifier ('%0')",IndexSignatureHasStatic:"Index signatures cannot have the 'static' modifier",OptionalTypeBeforeRequired:"A required element cannot follow an optional element.",PatternIsOptional:"A binding pattern parameter cannot be optional in an implementation signature.",PrivateElementHasAbstract:"Private elements cannot have the 'abstract' modifier.",PrivateElementHasAccessibility:"Private elements cannot have an accessibility modifier ('%0')",TemplateTypeHasSubstitution:"Template literal types cannot have any substitution",TypeAnnotationAfterAssign:"Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`",UnexpectedReadonly:"'readonly' type modifier is only permitted on array and tuple literal types.",UnexpectedTypeAnnotation:"Did not expect a type annotation here.",UnexpectedTypeCastInParameter:"Unexpected type cast in parameter position.",UnsupportedImportTypeArgument:"Argument in a type import must be a string literal",UnsupportedParameterPropertyKind:"A parameter property may not be declared using a binding pattern.",UnsupportedSignatureParameterKind:"Name in a signature must be an Identifier, ObjectPattern or ArrayPattern, instead got %0"});function de(t){switch(t){case"any":return"TSAnyKeyword";case"boolean":return"TSBooleanKeyword";case"bigint":return"TSBigIntKeyword";case"never":return"TSNeverKeyword";case"number":return"TSNumberKeyword";case"object":return"TSObjectKeyword";case"string":return"TSStringKeyword";case"symbol":return"TSSymbolKeyword";case"undefined":return"TSUndefinedKeyword";case"unknown":return"TSUnknownKeyword";default:return}}var fe=t=>class extends t{getScopeHandler(){return ie}tsIsIdentifier(){return this.match(d.name)}tsNextTokenCanFollowModifier(){return this.next(),!this.hasPrecedingLineBreak()&&!this.match(d.parenL)&&!this.match(d.parenR)&&!this.match(d.colon)&&!this.match(d.eq)&&!this.match(d.question)&&!this.match(d.bang)}tsParseModifier(t){if(!this.match(d.name))return;const e=this.state.value;return-1!==t.indexOf(e)&&this.tsTryParse(this.tsNextTokenCanFollowModifier.bind(this))?e:void 0}tsParseModifiers(t,e){for(;;){const s=this.state.start,i=this.tsParseModifier(e);if(!i)break;Object.hasOwnProperty.call(t,i)&&this.raise(s,ue.DuplicateModifier,i),t[i]=!0}}tsIsListTerminator(t){switch(t){case"EnumMembers":case"TypeMembers":return this.match(d.braceR);case"HeritageClauseElement":return this.match(d.braceL);case"TupleElementTypes":return this.match(d.bracketR);case"TypeParametersOrArguments":return this.isRelational(">")}throw new Error("Unreachable")}tsParseList(t,e){const s=[];while(!this.tsIsListTerminator(t))s.push(e());return s}tsParseDelimitedList(t,e){return le(this.tsParseDelimitedListWorker(t,e,!0))}tsParseDelimitedListWorker(t,e,s){const i=[];for(;;){if(this.tsIsListTerminator(t))break;const r=e();if(null==r)return;if(i.push(r),!this.eat(d.comma)){if(this.tsIsListTerminator(t))break;return void(s&&this.expect(d.comma))}}return i}tsParseBracketedList(t,e,s,i){i||(s?this.expect(d.bracketL):this.expectRelational("<"));const r=this.tsParseDelimitedList(t,e);return s?this.expect(d.bracketR):this.expectRelational(">"),r}tsParseImportType(){const t=this.startNode();return this.expect(d._import),this.expect(d.parenL),this.match(d.string)||this.raise(this.state.start,ue.UnsupportedImportTypeArgument),t.argument=this.parseExprAtom(),this.expect(d.parenR),this.eat(d.dot)&&(t.qualifier=this.tsParseEntityName(!0)),this.isRelational("<")&&(t.typeParameters=this.tsParseTypeArguments()),this.finishNode(t,"TSImportType")}tsParseEntityName(t){let e=this.parseIdentifier();while(this.eat(d.dot)){const s=this.startNodeAtNode(e);s.left=e,s.right=this.parseIdentifier(t),e=this.finishNode(s,"TSQualifiedName")}return e}tsParseTypeReference(){const t=this.startNode();return t.typeName=this.tsParseEntityName(!1),!this.hasPrecedingLineBreak()&&this.isRelational("<")&&(t.typeParameters=this.tsParseTypeArguments()),this.finishNode(t,"TSTypeReference")}tsParseThisTypePredicate(t){this.next();const e=this.startNodeAtNode(t);return e.parameterName=t,e.typeAnnotation=this.tsParseTypeAnnotation(!1),this.finishNode(e,"TSTypePredicate")}tsParseThisTypeNode(){const t=this.startNode();return this.next(),this.finishNode(t,"TSThisType")}tsParseTypeQuery(){const t=this.startNode();return this.expect(d._typeof),this.match(d._import)?t.exprName=this.tsParseImportType():t.exprName=this.tsParseEntityName(!0),this.finishNode(t,"TSTypeQuery")}tsParseTypeParameter(){const t=this.startNode();return t.name=this.parseIdentifierName(t.start),t.constraint=this.tsEatThenParseType(d._extends),t.default=this.tsEatThenParseType(d.eq),this.finishNode(t,"TSTypeParameter")}tsTryParseTypeParameters(){if(this.isRelational("<"))return this.tsParseTypeParameters()}tsParseTypeParameters(){const t=this.startNode();return this.isRelational("<")||this.match(d.jsxTagStart)?this.next():this.unexpected(),t.params=this.tsParseBracketedList("TypeParametersOrArguments",this.tsParseTypeParameter.bind(this),!1,!0),this.finishNode(t,"TSTypeParameterDeclaration")}tsTryNextParseConstantContext(){return this.lookahead().type===d._const?(this.next(),this.tsParseTypeReference()):null}tsFillSignature(t,e){const s=t===d.arrow;e.typeParameters=this.tsTryParseTypeParameters(),this.expect(d.parenL),e.parameters=this.tsParseBindingListForSignature(),(s||this.match(t))&&(e.typeAnnotation=this.tsParseTypeOrTypePredicateAnnotation(t))}tsParseBindingListForSignature(){return this.parseBindingList(d.parenR,41).map(t=>("Identifier"!==t.type&&"RestElement"!==t.type&&"ObjectPattern"!==t.type&&"ArrayPattern"!==t.type&&this.raise(t.start,ue.UnsupportedSignatureParameterKind,t.type),t))}tsParseTypeMemberSemicolon(){this.eat(d.comma)||this.semicolon()}tsParseSignatureMember(t,e){return this.tsFillSignature(d.colon,e),this.tsParseTypeMemberSemicolon(),this.finishNode(e,t)}tsIsUnambiguouslyIndexSignature(){return this.next(),this.eat(d.name)&&this.match(d.colon)}tsTryParseIndexSignature(t){if(!this.match(d.bracketL)||!this.tsLookAhead(this.tsIsUnambiguouslyIndexSignature.bind(this)))return;this.expect(d.bracketL);const e=this.parseIdentifier();e.typeAnnotation=this.tsParseTypeAnnotation(),this.resetEndLocation(e),this.expect(d.bracketR),t.parameters=[e];const s=this.tsTryParseTypeAnnotation();return s&&(t.typeAnnotation=s),this.tsParseTypeMemberSemicolon(),this.finishNode(t,"TSIndexSignature")}tsParsePropertyOrMethodSignature(t,e){this.eat(d.question)&&(t.optional=!0);const s=t;if(e||!this.match(d.parenL)&&!this.isRelational("<")){const t=s;e&&(t.readonly=!0);const i=this.tsTryParseTypeAnnotation();return i&&(t.typeAnnotation=i),this.tsParseTypeMemberSemicolon(),this.finishNode(t,"TSPropertySignature")}{const t=s;return this.tsFillSignature(d.colon,t),this.tsParseTypeMemberSemicolon(),this.finishNode(t,"TSMethodSignature")}}tsParseTypeMember(){const t=this.startNode();if(this.match(d.parenL)||this.isRelational("<"))return this.tsParseSignatureMember("TSCallSignatureDeclaration",t);if(this.match(d._new)){const e=this.startNode();return this.next(),this.match(d.parenL)||this.isRelational("<")?this.tsParseSignatureMember("TSConstructSignatureDeclaration",t):(t.key=this.createIdentifier(e,"new"),this.tsParsePropertyOrMethodSignature(t,!1))}const e=!!this.tsParseModifier(["readonly"]),s=this.tsTryParseIndexSignature(t);return s?(e&&(t.readonly=!0),s):(this.parsePropertyName(t,!1),this.tsParsePropertyOrMethodSignature(t,e))}tsParseTypeLiteral(){const t=this.startNode();return t.members=this.tsParseObjectTypeMembers(),this.finishNode(t,"TSTypeLiteral")}tsParseObjectTypeMembers(){this.expect(d.braceL);const t=this.tsParseList("TypeMembers",this.tsParseTypeMember.bind(this));return this.expect(d.braceR),t}tsIsStartOfMappedType(){return this.next(),this.eat(d.plusMin)?this.isContextual("readonly"):(this.isContextual("readonly")&&this.next(),!!this.match(d.bracketL)&&(this.next(),!!this.tsIsIdentifier()&&(this.next(),this.match(d._in))))}tsParseMappedTypeParameter(){const t=this.startNode();return t.name=this.parseIdentifierName(t.start),t.constraint=this.tsExpectThenParseType(d._in),this.finishNode(t,"TSTypeParameter")}tsParseMappedType(){const t=this.startNode();return this.expect(d.braceL),this.match(d.plusMin)?(t.readonly=this.state.value,this.next(),this.expectContextual("readonly")):this.eatContextual("readonly")&&(t.readonly=!0),this.expect(d.bracketL),t.typeParameter=this.tsParseMappedTypeParameter(),this.expect(d.bracketR),this.match(d.plusMin)?(t.optional=this.state.value,this.next(),this.expect(d.question)):this.eat(d.question)&&(t.optional=!0),t.typeAnnotation=this.tsTryParseType(),this.semicolon(),this.expect(d.braceR),this.finishNode(t,"TSMappedType")}tsParseTupleType(){const t=this.startNode();t.elementTypes=this.tsParseBracketedList("TupleElementTypes",this.tsParseTupleElementType.bind(this),!0,!1);let e=!1;return t.elementTypes.forEach(t=>{"TSOptionalType"===t.type?e=!0:e&&"TSRestType"!==t.type&&this.raise(t.start,ue.OptionalTypeBeforeRequired)}),this.finishNode(t,"TSTupleType")}tsParseTupleElementType(){if(this.match(d.ellipsis)){const t=this.startNode();return this.next(),t.typeAnnotation=this.tsParseType(),this.match(d.comma)&&93!==this.lookaheadCharCode()&&this.raiseRestNotLast(this.state.start),this.finishNode(t,"TSRestType")}const t=this.tsParseType();if(this.eat(d.question)){const e=this.startNodeAtNode(t);return e.typeAnnotation=t,this.finishNode(e,"TSOptionalType")}return t}tsParseParenthesizedType(){const t=this.startNode();return this.expect(d.parenL),t.typeAnnotation=this.tsParseType(),this.expect(d.parenR),this.finishNode(t,"TSParenthesizedType")}tsParseFunctionOrConstructorType(t){const e=this.startNode();return"TSConstructorType"===t&&this.expect(d._new),this.tsFillSignature(d.arrow,e),this.finishNode(e,t)}tsParseLiteralTypeNode(){const t=this.startNode();return t.literal=(()=>{switch(this.state.type){case d.num:case d.bigint:case d.string:case d._true:case d._false:return this.parseExprAtom();default:throw this.unexpected()}})(),this.finishNode(t,"TSLiteralType")}tsParseTemplateLiteralType(){const t=this.startNode(),e=this.parseTemplate(!1);return e.expressions.length>0&&this.raise(e.expressions[0].start,ue.TemplateTypeHasSubstitution),t.literal=e,this.finishNode(t,"TSLiteralType")}tsParseThisTypeOrThisTypePredicate(){const t=this.tsParseThisTypeNode();return this.isContextual("is")&&!this.hasPrecedingLineBreak()?this.tsParseThisTypePredicate(t):t}tsParseNonArrayType(){switch(this.state.type){case d.name:case d._void:case d._null:{const t=this.match(d._void)?"TSVoidKeyword":this.match(d._null)?"TSNullKeyword":de(this.state.value);if(void 0!==t&&46!==this.lookaheadCharCode()){const e=this.startNode();return this.next(),this.finishNode(e,t)}return this.tsParseTypeReference()}case d.string:case d.num:case d.bigint:case d._true:case d._false:return this.tsParseLiteralTypeNode();case d.plusMin:if("-"===this.state.value){const t=this.startNode(),e=this.lookahead();if(e.type!==d.num&&e.type!==d.bigint)throw this.unexpected();return t.literal=this.parseMaybeUnary(),this.finishNode(t,"TSLiteralType")}break;case d._this:return this.tsParseThisTypeOrThisTypePredicate();case d._typeof:return this.tsParseTypeQuery();case d._import:return this.tsParseImportType();case d.braceL:return this.tsLookAhead(this.tsIsStartOfMappedType.bind(this))?this.tsParseMappedType():this.tsParseTypeLiteral();case d.bracketL:return this.tsParseTupleType();case d.parenL:return this.tsParseParenthesizedType();case d.backQuote:return this.tsParseTemplateLiteralType()}throw this.unexpected()}tsParseArrayTypeOrHigher(){let t=this.tsParseNonArrayType();while(!this.hasPrecedingLineBreak()&&this.eat(d.bracketL))if(this.match(d.bracketR)){const e=this.startNodeAtNode(t);e.elementType=t,this.expect(d.bracketR),t=this.finishNode(e,"TSArrayType")}else{const e=this.startNodeAtNode(t);e.objectType=t,e.indexType=this.tsParseType(),this.expect(d.bracketR),t=this.finishNode(e,"TSIndexedAccessType")}return t}tsParseTypeOperator(t){const e=this.startNode();return this.expectContextual(t),e.operator=t,e.typeAnnotation=this.tsParseTypeOperatorOrHigher(),"readonly"===t&&this.tsCheckTypeAnnotationForReadOnly(e),this.finishNode(e,"TSTypeOperator")}tsCheckTypeAnnotationForReadOnly(t){switch(t.typeAnnotation.type){case"TSTupleType":case"TSArrayType":return;default:this.raise(t.start,ue.UnexpectedReadonly)}}tsParseInferType(){const t=this.startNode();this.expectContextual("infer");const e=this.startNode();return e.name=this.parseIdentifierName(e.start),t.typeParameter=this.finishNode(e,"TSTypeParameter"),this.finishNode(t,"TSInferType")}tsParseTypeOperatorOrHigher(){const t=["keyof","unique","readonly"].find(t=>this.isContextual(t));return t?this.tsParseTypeOperator(t):this.isContextual("infer")?this.tsParseInferType():this.tsParseArrayTypeOrHigher()}tsParseUnionOrIntersectionType(t,e,s){this.eat(s);let i=e();if(this.match(s)){const r=[i];while(this.eat(s))r.push(e());const n=this.startNodeAtNode(i);n.types=r,i=this.finishNode(n,t)}return i}tsParseIntersectionTypeOrHigher(){return this.tsParseUnionOrIntersectionType("TSIntersectionType",this.tsParseTypeOperatorOrHigher.bind(this),d.bitwiseAND)}tsParseUnionTypeOrHigher(){return this.tsParseUnionOrIntersectionType("TSUnionType",this.tsParseIntersectionTypeOrHigher.bind(this),d.bitwiseOR)}tsIsStartOfFunctionType(){return!!this.isRelational("<")||this.match(d.parenL)&&this.tsLookAhead(this.tsIsUnambiguouslyStartOfFunctionType.bind(this))}tsSkipParameterStart(){if(this.match(d.name)||this.match(d._this))return this.next(),!0;if(this.match(d.braceL)){let t=1;this.next();while(t>0)this.match(d.braceL)?++t:this.match(d.braceR)&&--t,this.next();return!0}if(this.match(d.bracketL)){let t=1;this.next();while(t>0)this.match(d.bracketL)?++t:this.match(d.bracketR)&&--t,this.next();return!0}return!1}tsIsUnambiguouslyStartOfFunctionType(){if(this.next(),this.match(d.parenR)||this.match(d.ellipsis))return!0;if(this.tsSkipParameterStart()){if(this.match(d.colon)||this.match(d.comma)||this.match(d.question)||this.match(d.eq))return!0;if(this.match(d.parenR)&&(this.next(),this.match(d.arrow)))return!0}return!1}tsParseTypeOrTypePredicateAnnotation(t){return this.tsInType(()=>{const e=this.startNode();this.expect(t);const s=this.tsTryParse(this.tsParseTypePredicateAsserts.bind(this));if(s&&this.match(d._this)){let t=this.tsParseThisTypeOrThisTypePredicate();if("TSThisType"===t.type){const s=this.startNodeAtNode(e);s.parameterName=t,s.asserts=!0,t=this.finishNode(s,"TSTypePredicate")}else t.asserts=!0;return e.typeAnnotation=t,this.finishNode(e,"TSTypeAnnotation")}const i=this.tsIsIdentifier()&&this.tsTryParse(this.tsParseTypePredicatePrefix.bind(this));if(!i){if(!s)return this.tsParseTypeAnnotation(!1,e);const t=this.startNodeAtNode(e);return t.parameterName=this.parseIdentifier(),t.asserts=s,e.typeAnnotation=this.finishNode(t,"TSTypePredicate"),this.finishNode(e,"TSTypeAnnotation")}const r=this.tsParseTypeAnnotation(!1),n=this.startNodeAtNode(e);return n.parameterName=i,n.typeAnnotation=r,n.asserts=s,e.typeAnnotation=this.finishNode(n,"TSTypePredicate"),this.finishNode(e,"TSTypeAnnotation")})}tsTryParseTypeOrTypePredicateAnnotation(){return this.match(d.colon)?this.tsParseTypeOrTypePredicateAnnotation(d.colon):void 0}tsTryParseTypeAnnotation(){return this.match(d.colon)?this.tsParseTypeAnnotation():void 0}tsTryParseType(){return this.tsEatThenParseType(d.colon)}tsParseTypePredicatePrefix(){const t=this.parseIdentifier();if(this.isContextual("is")&&!this.hasPrecedingLineBreak())return this.next(),t}tsParseTypePredicateAsserts(){if(!this.match(d.name)||"asserts"!==this.state.value||this.hasPrecedingLineBreak())return!1;const t=this.state.containsEsc;return this.next(),!(!this.match(d.name)&&!this.match(d._this))&&(t&&this.raise(this.state.lastTokStart,ut.InvalidEscapedReservedWord,"asserts"),!0)}tsParseTypeAnnotation(t=!0,e=this.startNode()){return this.tsInType(()=>{t&&this.expect(d.colon),e.typeAnnotation=this.tsParseType()}),this.finishNode(e,"TSTypeAnnotation")}tsParseType(){pe(this.state.inType);const t=this.tsParseNonConditionalType();if(this.hasPrecedingLineBreak()||!this.eat(d._extends))return t;const e=this.startNodeAtNode(t);return e.checkType=t,e.extendsType=this.tsParseNonConditionalType(),this.expect(d.question),e.trueType=this.tsParseType(),this.expect(d.colon),e.falseType=this.tsParseType(),this.finishNode(e,"TSConditionalType")}tsParseNonConditionalType(){return this.tsIsStartOfFunctionType()?this.tsParseFunctionOrConstructorType("TSFunctionType"):this.match(d._new)?this.tsParseFunctionOrConstructorType("TSConstructorType"):this.tsParseUnionTypeOrHigher()}tsParseTypeAssertion(){const t=this.startNode(),e=this.tsTryNextParseConstantContext();return t.typeAnnotation=e||this.tsNextThenParseType(),this.expectRelational(">"),t.expression=this.parseMaybeUnary(),this.finishNode(t,"TSTypeAssertion")}tsParseHeritageClause(t){const e=this.state.start,s=this.tsParseDelimitedList("HeritageClauseElement",this.tsParseExpressionWithTypeArguments.bind(this));return s.length||this.raise(e,ue.EmptyHeritageClauseType,t),s}tsParseExpressionWithTypeArguments(){const t=this.startNode();return t.expression=this.tsParseEntityName(!1),this.isRelational("<")&&(t.typeParameters=this.tsParseTypeArguments()),this.finishNode(t,"TSExpressionWithTypeArguments")}tsParseInterfaceDeclaration(t){t.id=this.parseIdentifier(),this.checkLVal(t.id,F,void 0,"typescript interface declaration"),t.typeParameters=this.tsTryParseTypeParameters(),this.eat(d._extends)&&(t.extends=this.tsParseHeritageClause("extends"));const e=this.startNode();return e.body=this.tsInType(this.tsParseObjectTypeMembers.bind(this)),t.body=this.finishNode(e,"TSInterfaceBody"),this.finishNode(t,"TSInterfaceDeclaration")}tsParseTypeAliasDeclaration(t){return t.id=this.parseIdentifier(),this.checkLVal(t.id,B,void 0,"typescript type alias"),t.typeParameters=this.tsTryParseTypeParameters(),t.typeAnnotation=this.tsExpectThenParseType(d.eq),this.semicolon(),this.finishNode(t,"TSTypeAliasDeclaration")}tsInNoContext(t){const e=this.state.context;this.state.context=[e[0]];try{return t()}finally{this.state.context=e}}tsInType(t){const e=this.state.inType;this.state.inType=!0;try{return t()}finally{this.state.inType=e}}tsEatThenParseType(t){return this.match(t)?this.tsNextThenParseType():void 0}tsExpectThenParseType(t){return this.tsDoThenParseType(()=>this.expect(t))}tsNextThenParseType(){return this.tsDoThenParseType(()=>this.next())}tsDoThenParseType(t){return this.tsInType(()=>(t(),this.tsParseType()))}tsParseEnumMember(){const t=this.startNode();return t.id=this.match(d.string)?this.parseExprAtom():this.parseIdentifier(!0),this.eat(d.eq)&&(t.initializer=this.parseMaybeAssign()),this.finishNode(t,"TSEnumMember")}tsParseEnumDeclaration(t,e){return e&&(t.const=!0),t.id=this.parseIdentifier(),this.checkLVal(t.id,e?z:U,void 0,"typescript enum declaration"),this.expect(d.braceL),t.members=this.tsParseDelimitedList("EnumMembers",this.tsParseEnumMember.bind(this)),this.expect(d.braceR),this.finishNode(t,"TSEnumDeclaration")}tsParseModuleBlock(){const t=this.startNode();return this.scope.enter(f),this.expect(d.braceL),this.parseBlockOrModuleBlockBody(t.body=[],void 0,!0,d.braceR),this.scope.exit(),this.finishNode(t,"TSModuleBlock")}tsParseModuleOrNamespaceDeclaration(t,e=!1){if(t.id=this.parseIdentifier(),e||this.checkLVal(t.id,W,null,"module or namespace declaration"),this.eat(d.dot)){const e=this.startNode();this.tsParseModuleOrNamespaceDeclaration(e,!0),t.body=e}else this.scope.enter(P),this.prodParam.enter(re),t.body=this.tsParseModuleBlock(),this.prodParam.exit(),this.scope.exit();return this.finishNode(t,"TSModuleDeclaration")}tsParseAmbientExternalModuleDeclaration(t){return this.isContextual("global")?(t.global=!0,t.id=this.parseIdentifier()):this.match(d.string)?t.id=this.parseExprAtom():this.unexpected(),this.match(d.braceL)?(this.scope.enter(P),this.prodParam.enter(re),t.body=this.tsParseModuleBlock(),this.prodParam.exit(),this.scope.exit()):this.semicolon(),this.finishNode(t,"TSModuleDeclaration")}tsParseImportEqualsDeclaration(t,e){return t.isExport=e||!1,t.id=this.parseIdentifier(),this.checkLVal(t.id,_,void 0,"import equals declaration"),this.expect(d.eq),t.moduleReference=this.tsParseModuleReference(),this.semicolon(),this.finishNode(t,"TSImportEqualsDeclaration")}tsIsExternalModuleReference(){return this.isContextual("require")&&40===this.lookaheadCharCode()}tsParseModuleReference(){return this.tsIsExternalModuleReference()?this.tsParseExternalModuleReference():this.tsParseEntityName(!1)}tsParseExternalModuleReference(){const t=this.startNode();if(this.expectContextual("require"),this.expect(d.parenL),!this.match(d.string))throw this.unexpected();return t.expression=this.parseExprAtom(),this.expect(d.parenR),this.finishNode(t,"TSExternalModuleReference")}tsLookAhead(t){const e=this.state.clone(),s=t();return this.state=e,s}tsTryParseAndCatch(t){const e=this.tryParse(e=>t()||e());if(!e.aborted&&e.node)return e.error&&(this.state=e.failState),e.node}tsTryParse(t){const e=this.state.clone(),s=t();return void 0!==s&&!1!==s?s:void(this.state=e)}tsTryParseDeclare(t){if(this.isLineTerminator())return;let e,s=this.state.type;switch(this.isContextual("let")&&(s=d._var,e="let"),s){case d._function:return this.parseFunctionStatement(t,!1,!0);case d._class:return t.declare=!0,this.parseClass(t,!0,!1);case d._const:if(this.match(d._const)&&this.isLookaheadContextual("enum"))return this.expect(d._const),this.expectContextual("enum"),this.tsParseEnumDeclaration(t,!0);case d._var:return e=e||this.state.value,this.parseVarStatement(t,e);case d.name:{const e=this.state.value;return"global"===e?this.tsParseAmbientExternalModuleDeclaration(t):this.tsParseDeclaration(t,e,!0)}}}tsTryParseExportDeclaration(){return this.tsParseDeclaration(this.startNode(),this.state.value,!0)}tsParseExpressionStatement(t,e){switch(e.name){case"declare":{const e=this.tsTryParseDeclare(t);if(e)return e.declare=!0,e;break}case"global":if(this.match(d.braceL)){this.scope.enter(P),this.prodParam.enter(re);const s=t;return s.global=!0,s.id=e,s.body=this.tsParseModuleBlock(),this.scope.exit(),this.prodParam.exit(),this.finishNode(s,"TSModuleDeclaration")}break;default:return this.tsParseDeclaration(t,e.name,!1)}}tsParseDeclaration(t,e,s){switch(e){case"abstract":if(this.tsCheckLineTerminatorAndMatch(d._class,s)){const e=t;return e.abstract=!0,s&&(this.next(),this.match(d._class)||this.unexpected(null,d._class)),this.parseClass(e,!0,!1)}break;case"enum":if(s||this.match(d.name))return s&&this.next(),this.tsParseEnumDeclaration(t,!1);break;case"interface":if(this.tsCheckLineTerminatorAndMatch(d.name,s))return s&&this.next(),this.tsParseInterfaceDeclaration(t);break;case"module":if(s&&this.next(),this.match(d.string))return this.tsParseAmbientExternalModuleDeclaration(t);if(this.tsCheckLineTerminatorAndMatch(d.name,s))return this.tsParseModuleOrNamespaceDeclaration(t);break;case"namespace":if(this.tsCheckLineTerminatorAndMatch(d.name,s))return s&&this.next(),this.tsParseModuleOrNamespaceDeclaration(t);break;case"type":if(this.tsCheckLineTerminatorAndMatch(d.name,s))return s&&this.next(),this.tsParseTypeAliasDeclaration(t);break}}tsCheckLineTerminatorAndMatch(t,e){return(e||this.match(t))&&!this.isLineTerminator()}tsTryParseGenericAsyncArrowFunction(t,e){if(!this.isRelational("<"))return;const s=this.state.maybeInArrowParameters,i=this.state.yieldPos,r=this.state.awaitPos;this.state.maybeInArrowParameters=!0,this.state.yieldPos=-1,this.state.awaitPos=-1;const n=this.tsTryParseAndCatch(()=>{const s=this.startNodeAt(t,e);return s.typeParameters=this.tsParseTypeParameters(),super.parseFunctionParams(s),s.returnType=this.tsTryParseTypeOrTypePredicateAnnotation(),this.expect(d.arrow),s});return this.state.maybeInArrowParameters=s,this.state.yieldPos=i,this.state.awaitPos=r,n?this.parseArrowExpression(n,null,!0):void 0}tsParseTypeArguments(){const t=this.startNode();return t.params=this.tsInType(()=>this.tsInNoContext(()=>(this.expectRelational("<"),this.tsParseDelimitedList("TypeParametersOrArguments",this.tsParseType.bind(this))))),this.state.exprAllowed=!1,this.expectRelational(">"),this.finishNode(t,"TSTypeParameterInstantiation")}tsIsDeclarationStart(){if(this.match(d.name))switch(this.state.value){case"abstract":case"declare":case"enum":case"interface":case"module":case"namespace":case"type":return!0}return!1}isExportDefaultSpecifier(){return!this.tsIsDeclarationStart()&&super.isExportDefaultSpecifier()}parseAssignableListItem(t,e){const s=this.state.start,i=this.state.startLoc;let r,n=!1;t&&(r=this.parseAccessModifier(),n=!!this.tsParseModifier(["readonly"]));const a=this.parseMaybeDefault();this.parseAssignableListItemTypes(a);const o=this.parseMaybeDefault(a.start,a.loc.start,a);if(r||n){const t=this.startNodeAt(s,i);return e.length&&(t.decorators=e),r&&(t.accessibility=r),n&&(t.readonly=n),"Identifier"!==o.type&&"AssignmentPattern"!==o.type&&this.raise(t.start,ue.UnsupportedParameterPropertyKind),t.parameter=o,this.finishNode(t,"TSParameterProperty")}return e.length&&(a.decorators=e),o}parseFunctionBodyAndFinish(t,e,s=!1){this.match(d.colon)&&(t.returnType=this.tsParseTypeOrTypePredicateAnnotation(d.colon));const i="FunctionDeclaration"===e?"TSDeclareFunction":"ClassMethod"===e?"TSDeclareMethod":void 0;i&&!this.match(d.braceL)&&this.isLineTerminator()?this.finishNode(t,i):super.parseFunctionBodyAndFinish(t,e,s)}registerFunctionStatementId(t){!t.body&&t.id?this.checkLVal(t.id,q,null,"function name"):super.registerFunctionStatementId(...arguments)}parseSubscript(t,e,s,i,r){if(!this.hasPrecedingLineBreak()&&this.match(d.bang)){this.state.exprAllowed=!1,this.next();const i=this.startNodeAt(e,s);return i.expression=t,this.finishNode(i,"TSNonNullExpression")}if(this.isRelational("<")){const n=this.tsTryParseAndCatch(()=>{if(!i&&this.atPossibleAsyncArrow(t)){const t=this.tsTryParseGenericAsyncArrowFunction(e,s);if(t)return t}const n=this.startNodeAt(e,s);n.callee=t;const a=this.tsParseTypeArguments();if(a){if(!i&&this.eat(d.parenL))return n.arguments=this.parseCallExpressionArguments(d.parenR,!1),n.typeParameters=a,this.finishCallExpression(n,r.optionalChainMember);if(this.match(d.backQuote))return this.parseTaggedTemplateExpression(e,s,t,r,a)}this.unexpected()});if(n)return n}return super.parseSubscript(t,e,s,i,r)}parseNewArguments(t){if(this.isRelational("<")){const e=this.tsTryParseAndCatch(()=>{const t=this.tsParseTypeArguments();return this.match(d.parenL)||this.unexpected(),t});e&&(t.typeParameters=e)}super.parseNewArguments(t)}parseExprOp(t,e,s,i,r){if(le(d._in.binop)>i&&!this.hasPrecedingLineBreak()&&this.isContextual("as")){const n=this.startNodeAt(e,s);n.expression=t;const a=this.tsTryNextParseConstantContext();return n.typeAnnotation=a||this.tsNextThenParseType(),this.finishNode(n,"TSAsExpression"),this.parseExprOp(n,e,s,i,r)}return super.parseExprOp(t,e,s,i,r)}checkReservedWord(t,e,s,i){}checkDuplicateExports(){}parseImport(t){if(this.match(d.name)||this.match(d.star)||this.match(d.braceL)){const e=this.lookahead();if(this.match(d.name)&&e.type===d.eq)return this.tsParseImportEqualsDeclaration(t);!this.isContextual("type")||e.type===d.comma||e.type===d.name&&"from"===e.value?t.importKind="value":(t.importKind="type",this.next())}const e=super.parseImport(t);return"type"===e.importKind&&e.specifiers.length>1&&"ImportDefaultSpecifier"===e.specifiers[0].type&&this.raise(e.start,"A type-only import can specify a default import or named bindings, but not both."),e}parseExport(t){if(this.match(d._import))return this.expect(d._import),this.tsParseImportEqualsDeclaration(t,!0);if(this.eat(d.eq)){const e=t;return e.expression=this.parseExpression(),this.semicolon(),this.finishNode(e,"TSExportAssignment")}if(this.eatContextual("as")){const e=t;return this.expectContextual("namespace"),e.id=this.parseIdentifier(),this.semicolon(),this.finishNode(e,"TSNamespaceExportDeclaration")}return this.isContextual("type")&&this.lookahead().type===d.braceL?(this.next(),t.exportKind="type"):t.exportKind="value",super.parseExport(t)}isAbstractClass(){return this.isContextual("abstract")&&this.lookahead().type===d._class}parseExportDefaultExpression(){if(this.isAbstractClass()){const t=this.startNode();return this.next(),this.parseClass(t,!0,!0),t.abstract=!0,t}if("interface"===this.state.value){const t=this.tsParseDeclaration(this.startNode(),this.state.value,!0);if(t)return t}return super.parseExportDefaultExpression()}parseStatementContent(t,e){if(this.state.type===d._const){const t=this.lookahead();if(t.type===d.name&&"enum"===t.value){const t=this.startNode();return this.expect(d._const),this.expectContextual("enum"),this.tsParseEnumDeclaration(t,!0)}}return super.parseStatementContent(t,e)}parseAccessModifier(){return this.tsParseModifier(["public","protected","private"])}parseClassMember(t,e,s,i){this.tsParseModifiers(e,["declare"]);const r=this.parseAccessModifier();r&&(e.accessibility=r),this.tsParseModifiers(e,["declare"]),super.parseClassMember(t,e,s,i)}parseClassMemberWithIsStatic(t,e,s,i,r){this.tsParseModifiers(e,["abstract","readonly","declare"]);const n=this.tsTryParseIndexSignature(e);if(n)return t.body.push(n),e.abstract&&this.raise(e.start,ue.IndexSignatureHasAbstract),i&&this.raise(e.start,ue.IndexSignatureHasStatic),void(e.accessibility&&this.raise(e.start,ue.IndexSignatureHasAccessibility,e.accessibility));super.parseClassMemberWithIsStatic(t,e,s,i,r)}parsePostMemberNameModifiers(t){const e=this.eat(d.question);e&&(t.optional=!0),t.readonly&&this.match(d.parenL)&&this.raise(t.start,ue.ClassMethodHasReadonly),t.declare&&this.match(d.parenL)&&this.raise(t.start,ue.ClassMethodHasDeclare)}parseExpressionStatement(t,e){const s="Identifier"===e.type?this.tsParseExpressionStatement(t,e):void 0;return s||super.parseExpressionStatement(t,e)}shouldParseExportDeclaration(){return!!this.tsIsDeclarationStart()||super.shouldParseExportDeclaration()}parseConditional(t,e,s,i,r){if(!r||!this.match(d.question))return super.parseConditional(t,e,s,i,r);const n=this.tryParse(()=>super.parseConditional(t,e,s,i));return n.node?(n.error&&(this.state=n.failState),n.node):(r.start=n.error.pos||this.state.start,t)}parseParenItem(t,e,s){if(t=super.parseParenItem(t,e,s),this.eat(d.question)&&(t.optional=!0,this.resetEndLocation(t)),this.match(d.colon)){const i=this.startNodeAt(e,s);return i.expression=t,i.typeAnnotation=this.tsParseTypeAnnotation(),this.finishNode(i,"TSTypeCastExpression")}return t}parseExportDeclaration(t){const e=this.state.start,s=this.state.startLoc,i=this.eatContextual("declare");let r;return this.match(d.name)&&(r=this.tsTryParseExportDeclaration()),r||(r=super.parseExportDeclaration(t)),r&&("TSInterfaceDeclaration"===r.type||"TSTypeAliasDeclaration"===r.type||i)&&(t.exportKind="type"),r&&i&&(this.resetStartLocation(r,e,s),r.declare=!0),r}parseClassId(t,e,s){if((!e||s)&&this.isContextual("implements"))return;super.parseClassId(t,e,s,t.declare?q:L);const i=this.tsTryParseTypeParameters();i&&(t.typeParameters=i)}parseClassPropertyAnnotation(t){!t.optional&&this.eat(d.bang)&&(t.definite=!0);const e=this.tsTryParseTypeAnnotation();e&&(t.typeAnnotation=e)}parseClassProperty(t){return this.parseClassPropertyAnnotation(t),t.declare&&this.match(d.equal)&&this.raise(this.state.start,ue.DeclareClassFieldHasInitializer),super.parseClassProperty(t)}parseClassPrivateProperty(t){return t.abstract&&this.raise(t.start,ue.PrivateElementHasAbstract),t.accessibility&&this.raise(t.start,ue.PrivateElementHasAccessibility,t.accessibility),this.parseClassPropertyAnnotation(t),super.parseClassPrivateProperty(t)}pushClassMethod(t,e,s,i,r,n){const a=this.tsTryParseTypeParameters();a&&(e.typeParameters=a),super.pushClassMethod(t,e,s,i,r,n)}pushClassPrivateMethod(t,e,s,i){const r=this.tsTryParseTypeParameters();r&&(e.typeParameters=r),super.pushClassPrivateMethod(t,e,s,i)}parseClassSuper(t){super.parseClassSuper(t),t.superClass&&this.isRelational("<")&&(t.superTypeParameters=this.tsParseTypeArguments()),this.eatContextual("implements")&&(t.implements=this.tsParseHeritageClause("implements"))}parseObjPropValue(t,...e){const s=this.tsTryParseTypeParameters();s&&(t.typeParameters=s),super.parseObjPropValue(t,...e)}parseFunctionParams(t,e){const s=this.tsTryParseTypeParameters();s&&(t.typeParameters=s),super.parseFunctionParams(t,e)}parseVarId(t,e){super.parseVarId(t,e),"Identifier"===t.id.type&&this.eat(d.bang)&&(t.definite=!0);const s=this.tsTryParseTypeAnnotation();s&&(t.id.typeAnnotation=s,this.resetEndLocation(t.id))}parseAsyncArrowFromCallExpression(t,e){return this.match(d.colon)&&(t.returnType=this.tsParseTypeAnnotation()),super.parseAsyncArrowFromCallExpression(t,e)}parseMaybeAssign(...t){var e,s,i,r,n,a,o;let c,h,l,p;if(this.match(d.jsxTagStart)){if(c=this.state.clone(),h=this.tryParse(()=>super.parseMaybeAssign(...t),c),!h.error)return h.node;const{context:e}=this.state;e[e.length-1]===gt.j_oTag?e.length-=2:e[e.length-1]===gt.j_expr&&(e.length-=1)}if(!(null==(e=h)?void 0:e.error)&&!this.isRelational("<"))return super.parseMaybeAssign(...t);c=c||this.state.clone();const u=this.tryParse(e=>{var s;p=this.tsParseTypeParameters();const i=super.parseMaybeAssign(...t);return("ArrowFunctionExpression"!==i.type||i.extra&&i.extra.parenthesized)&&e(),0!==(null==(s=p)?void 0:s.params.length)&&this.resetStartLocationFromNode(i,p),i.typeParameters=p,i},c);if(!u.error&&!u.aborted)return u.node;if(!h&&(pe(!this.hasPlugin("jsx")),l=this.tryParse(()=>super.parseMaybeAssign(...t),c),!l.error))return l.node;if(null==(s=h)?void 0:s.node)return this.state=h.failState,h.node;if(u.node)return this.state=u.failState,u.node;if(null==(i=l)?void 0:i.node)return this.state=l.failState,l.node;if(null==(r=h)?void 0:r.thrown)throw h.error;if(u.thrown)throw u.error;if(null==(n=l)?void 0:n.thrown)throw l.error;throw(null==(a=h)?void 0:a.error)||u.error||(null==(o=l)?void 0:o.error)}parseMaybeUnary(t){return!this.hasPlugin("jsx")&&this.isRelational("<")?this.tsParseTypeAssertion():super.parseMaybeUnary(t)}parseArrow(t){if(this.match(d.colon)){const e=this.tryParse(t=>{const e=this.tsParseTypeOrTypePredicateAnnotation(d.colon);return!this.canInsertSemicolon()&&this.match(d.arrow)||t(),e});if(e.aborted)return;e.thrown||(e.error&&(this.state=e.failState),t.returnType=e.node)}return super.parseArrow(t)}parseAssignableListItemTypes(t){this.eat(d.question)&&("Identifier"!==t.type&&this.raise(t.start,ue.PatternIsOptional),t.optional=!0);const e=this.tsTryParseTypeAnnotation();return e&&(t.typeAnnotation=e),this.resetEndLocation(t),t}toAssignable(t){switch(t.type){case"TSTypeCastExpression":return super.toAssignable(this.typeCastToParameter(t));case"TSParameterProperty":return super.toAssignable(t);case"TSAsExpression":case"TSNonNullExpression":case"TSTypeAssertion":return t.expression=this.toAssignable(t.expression),t;default:return super.toAssignable(t)}}checkLVal(t,e=V,s,i){switch(t.type){case"TSTypeCastExpression":return;case"TSParameterProperty":return void this.checkLVal(t.parameter,e,s,"parameter property");case"TSAsExpression":case"TSNonNullExpression":case"TSTypeAssertion":return void this.checkLVal(t.expression,e,s,i);default:return void super.checkLVal(t,e,s,i)}}parseBindingAtom(){switch(this.state.type){case d._this:return this.parseIdentifier(!0);default:return super.parseBindingAtom()}}parseMaybeDecoratorArguments(t){if(this.isRelational("<")){const e=this.tsParseTypeArguments();if(this.match(d.parenL)){const s=super.parseMaybeDecoratorArguments(t);return s.typeParameters=e,s}this.unexpected(this.state.start,d.parenL)}return super.parseMaybeDecoratorArguments(t)}isClassMethod(){return this.isRelational("<")||super.isClassMethod()}isClassProperty(){return this.match(d.bang)||this.match(d.colon)||super.isClassProperty()}parseMaybeDefault(...t){const e=super.parseMaybeDefault(...t);return"AssignmentPattern"===e.type&&e.typeAnnotation&&e.right.startthis.tsParseTypeArguments());e&&(t.typeParameters=e)}return super.jsxParseOpeningElementAfterName(t)}getGetterSetterExpectedParamCount(t){const e=super.getGetterSetterExpectedParamCount(t),s=t.params[0],i=s&&"Identifier"===s.type&&"this"===s.name;return i?e+1:e}};d.placeholder=new h("%%",{startsExpr:!0});var me=t=>class extends t{parsePlaceholder(t){if(this.match(d.placeholder)){const e=this.startNode();return this.next(),this.assertNoSpace("Unexpected space in placeholder."),e.name=super.parseIdentifier(!0),this.assertNoSpace("Unexpected space in placeholder."),this.expect(d.placeholder),this.finishPlaceholder(e,t)}}finishPlaceholder(t,e){const s=!(!t.expectedNode||"Placeholder"!==t.type);return t.expectedNode=e,s?t:this.finishNode(t,"Placeholder")}getTokenFromCode(t){return 37===t&&37===this.input.charCodeAt(this.state.pos+1)?this.finishOp(d.placeholder,2):super.getTokenFromCode(...arguments)}parseExprAtom(){return this.parsePlaceholder("Expression")||super.parseExprAtom(...arguments)}parseIdentifier(){return this.parsePlaceholder("Identifier")||super.parseIdentifier(...arguments)}checkReservedWord(t){void 0!==t&&super.checkReservedWord(...arguments)}parseBindingAtom(){return this.parsePlaceholder("Pattern")||super.parseBindingAtom(...arguments)}checkLVal(t){"Placeholder"!==t.type&&super.checkLVal(...arguments)}toAssignable(t){return t&&"Placeholder"===t.type&&"Expression"===t.expectedNode?(t.expectedNode="Pattern",t):super.toAssignable(...arguments)}verifyBreakContinue(t){t.label&&"Placeholder"===t.label.type||super.verifyBreakContinue(...arguments)}parseExpressionStatement(t,e){if("Placeholder"!==e.type||e.extra&&e.extra.parenthesized)return super.parseExpressionStatement(...arguments);if(this.match(d.colon)){const s=t;return s.label=this.finishPlaceholder(e,"Identifier"),this.next(),s.body=this.parseStatement("label"),this.finishNode(s,"LabeledStatement")}return this.semicolon(),t.name=e.name,this.finishPlaceholder(t,"Statement")}parseBlock(){return this.parsePlaceholder("BlockStatement")||super.parseBlock(...arguments)}parseFunctionId(){return this.parsePlaceholder("Identifier")||super.parseFunctionId(...arguments)}parseClass(t,e,s){const i=e?"ClassDeclaration":"ClassExpression";this.next(),this.takeDecorators(t);const r=this.parsePlaceholder("Identifier");if(r)if(this.match(d._extends)||this.match(d.placeholder)||this.match(d.braceL))t.id=r;else{if(s||!e)return t.id=null,t.body=this.finishPlaceholder(r,"ClassBody"),this.finishNode(t,i);this.unexpected(null,"A class name is required")}else this.parseClassId(t,e,s);return this.parseClassSuper(t),t.body=this.parsePlaceholder("ClassBody")||this.parseClassBody(!!t.superClass),this.finishNode(t,i)}parseExport(t){const e=this.parsePlaceholder("Identifier");if(!e)return super.parseExport(...arguments);if(!this.isContextual("from")&&!this.match(d.comma))return t.specifiers=[],t.source=null,t.declaration=this.finishPlaceholder(e,"Declaration"),this.finishNode(t,"ExportNamedDeclaration");this.expectPlugin("exportDefaultFrom");const s=this.startNode();return s.exported=e,t.specifiers=[this.finishNode(s,"ExportDefaultSpecifier")],super.parseExport(t)}isExportDefaultSpecifier(){if(this.match(d._default)){const t=this.nextTokenStart();if(this.isUnparsedContextual(t,"from")&&this.input.startsWith(d.placeholder.label,this.nextTokenStartSince(t+4)))return!0}return super.isExportDefaultSpecifier()}maybeParseExportDefaultSpecifier(t){return!!(t.specifiers&&t.specifiers.length>0)||super.maybeParseExportDefaultSpecifier(...arguments)}checkExport(t){const{specifiers:e}=t;(null==e?void 0:e.length)&&(t.specifiers=e.filter(t=>"Placeholder"===t.exported.type)),super.checkExport(t),t.specifiers=e}parseImport(t){const e=this.parsePlaceholder("Identifier");if(!e)return super.parseImport(...arguments);if(t.specifiers=[],!this.isContextual("from")&&!this.match(d.comma))return t.source=this.finishPlaceholder(e,"StringLiteral"),this.semicolon(),this.finishNode(t,"ImportDeclaration");const s=this.startNodeAtNode(e);if(s.local=e,this.finishNode(s,"ImportDefaultSpecifier"),t.specifiers.push(s),this.eat(d.comma)){const e=this.maybeParseStarImportSpecifier(t);e||this.parseNamedImportSpecifiers(t)}return this.expectContextual("from"),t.source=this.parseImportSource(),this.semicolon(),this.finishNode(t,"ImportDeclaration")}parseImportSource(){return this.parsePlaceholder("StringLiteral")||super.parseImportSource(...arguments)}},ye=t=>class extends t{parseV8Intrinsic(){if(this.match(d.modulo)){const t=this.state.start,e=this.startNode();if(this.eat(d.modulo),this.match(d.name)){const t=this.parseIdentifierName(this.state.start),s=this.createIdentifier(e,t);if(s.type="V8IntrinsicIdentifier",this.match(d.parenL))return s}this.unexpected(t)}}parseExprAtom(){return this.parseV8Intrinsic()||super.parseExprAtom(...arguments)}};function ge(t,e){return t.some(t=>Array.isArray(t)?t[0]===e:t===e)}function xe(t,e,s){const i=t.find(t=>Array.isArray(t)?t[0]===e:t===e);return i&&Array.isArray(i)?i[1][s]:null}const be=["minimal","smart","fsharp"],ve=["hash","bar"];function we(t){if(ge(t,"decorators")){if(ge(t,"decorators-legacy"))throw new Error("Cannot use the decorators and decorators-legacy plugin together");const e=xe(t,"decorators","decoratorsBeforeExport");if(null==e)throw new Error("The 'decorators' plugin requires a 'decoratorsBeforeExport' option, whose value must be a boolean. If you are migrating from Babylon/Babel 6 or want to use the old decorators proposal, you should use the 'decorators-legacy' plugin instead of 'decorators'.");if("boolean"!==typeof e)throw new Error("'decoratorsBeforeExport' must be a boolean.")}if(ge(t,"flow")&&ge(t,"typescript"))throw new Error("Cannot combine flow and typescript plugins.");if(ge(t,"placeholders")&&ge(t,"v8intrinsic"))throw new Error("Cannot combine placeholders and v8intrinsic plugins.");if(ge(t,"pipelineOperator")&&!be.includes(xe(t,"pipelineOperator","proposal")))throw new Error("'pipelineOperator' requires 'proposal' option whose value should be one of: "+be.map(t=>`'${t}'`).join(", "));if(ge(t,"moduleAttributes")){const e=xe(t,"moduleAttributes","version");if("may-2020"!==e)throw new Error("The 'moduleAttributes' plugin requires a 'version' option, representing the last proposal update. Currently, the only supported value is 'may-2020'.")}if(ge(t,"recordAndTuple")&&!ve.includes(xe(t,"recordAndTuple","syntaxType")))throw new Error("'recordAndTuple' requires 'syntaxType' option whose value should be one of: "+ve.map(t=>`'${t}'`).join(", "))}const Pe={estree:mt,jsx:Zt,flow:Kt,typescript:fe,v8intrinsic:ye,placeholders:me},Te=Object.keys(Pe),Ee={sourceType:"script",sourceFilename:void 0,startLine:1,allowAwaitOutsideFunction:!1,allowReturnOutsideFunction:!1,allowImportExportEverywhere:!1,allowSuperOutsideMethod:!1,allowUndeclaredExports:!1,plugins:[],strictMode:null,ranges:!1,tokens:!1,createParenthesizedExpressions:!1,errorRecovery:!1};function Ae(t){const e={};for(let s=0,i=Object.keys(Ee);s=48&&t<=57};const ke=new Set(["g","m","s","i","y","u"]),Ne={decBinOct:[46,66,69,79,95,98,101,111],hex:[46,88,95,120]},Ie={bin:[48,49]};Ie.oct=[...Ie.bin,50,51,52,53,54,55],Ie.dec=[...Ie.oct,56,57],Ie.hex=[...Ie.dec,65,66,67,68,69,70,97,98,99,100,101,102];class Oe{constructor(t){this.type=t.type,this.value=t.value,this.start=t.start,this.end=t.end,this.loc=new ot(t.startLoc,t.endLoc)}}class De extends dt{constructor(t,e){super(),this.tokens=[],this.state=new Se,this.state.init(t),this.input=e,this.length=e.length,this.isLookahead=!1}pushToken(t){this.tokens.length=this.state.tokensLength,this.tokens.push(t),++this.state.tokensLength}next(){this.isLookahead||(this.checkKeywordEscapes(),this.options.tokens&&this.pushToken(new Oe(this.state))),this.state.lastTokEnd=this.state.end,this.state.lastTokStart=this.state.start,this.state.lastTokEndLoc=this.state.endLoc,this.state.lastTokStartLoc=this.state.startLoc,this.nextToken()}eat(t){return!!this.match(t)&&(this.next(),!0)}match(t){return this.state.type===t}lookahead(){const t=this.state;this.state=t.clone(!0),this.isLookahead=!0,this.next(),this.isLookahead=!1;const e=this.state;return this.state=t,e}nextTokenStart(){return this.nextTokenStartSince(this.state.pos)}nextTokenStartSince(t){rt.lastIndex=t;const e=rt.exec(this.input);return t+e[0].length}lookaheadCharCode(){return this.input.charCodeAt(this.nextTokenStart())}setStrict(t){if(this.state.strict=t,this.match(d.num)||this.match(d.string)){this.state.pos=this.state.start;while(this.state.pos=this.length)return void this.finishToken(d.eof);const e=null==t?void 0:t.override;e?e(this):this.getTokenFromCode(this.input.codePointAt(this.state.pos))}pushComment(t,e,s,i,r,n){const a={type:t?"CommentBlock":"CommentLine",value:e,start:s,end:i,loc:new ot(r,n)};this.options.tokens&&this.pushToken(a),this.state.comments.push(a),this.addComment(a)}skipBlockComment(){const t=this.state.curPosition(),e=this.state.pos,s=this.input.indexOf("*/",this.state.pos+2);if(-1===s)throw this.raise(e,ut.UnterminatedComment);let i;this.state.pos=s+2,st.lastIndex=e;while((i=st.exec(this.input))&&i.index=48&&e<=57)throw this.raise(this.state.pos,ut.UnexpectedDigitAfterHash);if(123===e||91===e&&this.hasPlugin("recordAndTuple")){if(this.expectPlugin("recordAndTuple"),"hash"!==this.getPluginOption("recordAndTuple","syntaxType"))throw this.raise(this.state.pos,123===e?ut.RecordExpressionHashIncorrectStartSyntaxType:ut.TupleExpressionHashIncorrectStartSyntaxType);123===e?this.finishToken(d.braceHashL):this.finishToken(d.bracketHashL),this.state.pos+=2}else this.finishOp(d.hash,1)}readToken_dot(){const t=this.input.charCodeAt(this.state.pos+1);t>=48&&t<=57?this.readNumber(!0):46===t&&46===this.input.charCodeAt(this.state.pos+2)?(this.state.pos+=3,this.finishToken(d.ellipsis)):(++this.state.pos,this.finishToken(d.dot))}readToken_slash(){if(this.state.exprAllowed&&!this.state.inType)return++this.state.pos,void this.readRegexp();const t=this.input.charCodeAt(this.state.pos+1);61===t?this.finishOp(d.assign,2):this.finishOp(d.slash,1)}readToken_interpreter(){if(0!==this.state.pos||this.length<2)return!1;let t=this.input.charCodeAt(this.state.pos+1);if(33!==t)return!1;const e=this.state.pos;this.state.pos+=1;while(!it(t)&&++this.state.pos=48&&e<=57?(++this.state.pos,this.finishToken(d.question)):(this.state.pos+=2,this.finishToken(d.questionDot)):61===e?this.finishOp(d.assign,3):this.finishOp(d.nullishCoalescing,2)}getTokenFromCode(t){switch(t){case 46:return void this.readToken_dot();case 40:return++this.state.pos,void this.finishToken(d.parenL);case 41:return++this.state.pos,void this.finishToken(d.parenR);case 59:return++this.state.pos,void this.finishToken(d.semi);case 44:return++this.state.pos,void this.finishToken(d.comma);case 91:if(this.hasPlugin("recordAndTuple")&&124===this.input.charCodeAt(this.state.pos+1)){if("bar"!==this.getPluginOption("recordAndTuple","syntaxType"))throw this.raise(this.state.pos,ut.TupleExpressionBarIncorrectStartSyntaxType);this.finishToken(d.bracketBarL),this.state.pos+=2}else++this.state.pos,this.finishToken(d.bracketL);return;case 93:return++this.state.pos,void this.finishToken(d.bracketR);case 123:if(this.hasPlugin("recordAndTuple")&&124===this.input.charCodeAt(this.state.pos+1)){if("bar"!==this.getPluginOption("recordAndTuple","syntaxType"))throw this.raise(this.state.pos,ut.RecordExpressionBarIncorrectStartSyntaxType);this.finishToken(d.braceBarL),this.state.pos+=2}else++this.state.pos,this.finishToken(d.braceL);return;case 125:return++this.state.pos,void this.finishToken(d.braceR);case 58:return void(this.hasPlugin("functionBind")&&58===this.input.charCodeAt(this.state.pos+1)?this.finishOp(d.doubleColon,2):(++this.state.pos,this.finishToken(d.colon)));case 63:return void this.readToken_question();case 96:return++this.state.pos,void this.finishToken(d.backQuote);case 48:{const t=this.input.charCodeAt(this.state.pos+1);if(120===t||88===t)return void this.readRadixNumber(16);if(111===t||79===t)return void this.readRadixNumber(8);if(98===t||66===t)return void this.readRadixNumber(2)}case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return void this.readNumber(!1);case 34:case 39:return void this.readString(t);case 47:return void this.readToken_slash();case 37:case 42:return void this.readToken_mult_modulo(t);case 124:case 38:return void this.readToken_pipe_amp(t);case 94:return void this.readToken_caret();case 43:case 45:return void this.readToken_plus_min(t);case 60:case 62:return void this.readToken_lt_gt(t);case 61:case 33:return void this.readToken_eq_excl(t);case 126:return void this.finishOp(d.tilde,1);case 64:return++this.state.pos,void this.finishToken(d.at);case 35:return void this.readToken_numberSign();case 92:return void this.readWord();default:if(At(t))return void this.readWord()}throw this.raise(this.state.pos,ut.InvalidOrUnexpectedToken,String.fromCodePoint(t))}finishOp(t,e){const s=this.input.slice(this.state.pos,this.state.pos+e);this.state.pos+=e,this.finishToken(t,s)}readRegexp(){const t=this.state.pos;let e,s;for(;;){if(this.state.pos>=this.length)throw this.raise(t,ut.UnterminatedRegExp);const i=this.input.charAt(this.state.pos);if(et.test(i))throw this.raise(t,ut.UnterminatedRegExp);if(e)e=!1;else{if("["===i)s=!0;else if("]"===i&&s)s=!1;else if("/"===i&&!s)break;e="\\"===i}++this.state.pos}const i=this.input.slice(t,this.state.pos);++this.state.pos;let r="";while(this.state.pos-1&&this.raise(this.state.pos+1,ut.DuplicateRegExpFlags);else{if(!St(e)&&92!==e)break;this.raise(this.state.pos+1,ut.MalformedRegExpFlags)}++this.state.pos,r+=t}this.finishToken(d.regexp,{pattern:i,flags:r})}readInt(t,e,s,i=!0){const r=this.state.pos,n=16===t?Ne.hex:Ne.decBinOct,a=16===t?Ie.hex:10===t?Ie.dec:8===t?Ie.oct:Ie.bin;let o=!1,c=0;for(let h=0,l=null==e?1/0:e;h-1||n.indexOf(e)>-1||Number.isNaN(e))&&this.raise(this.state.pos,ut.UnexpectedNumericSeparator),i||this.raise(this.state.pos,ut.NumericSeparatorInEscapeSequence),++this.state.pos}else{if(r=e>=97?e-97+10:e>=65?e-65+10:Ce(e)?e-48:1/0,r>=t)if(this.options.errorRecovery&&r<=9)r=0,this.raise(this.state.start+h+2,ut.InvalidDigit,t);else{if(!s)break;r=0,o=!0}++this.state.pos,c=c*t+r}}return this.state.pos===r||null!=e&&this.state.pos-r!==e||o?null:c}readRadixNumber(t){const e=this.state.pos;let s=!1;this.state.pos+=2;const i=this.readInt(t);null==i&&this.raise(this.state.start+2,ut.InvalidDigit,t);const r=this.input.charCodeAt(this.state.pos);if(95===r&&this.expectPlugin("numericSeparator",this.state.pos),110===r&&(++this.state.pos,s=!0),At(this.input.codePointAt(this.state.pos)))throw this.raise(this.state.pos,ut.NumberIdentifier);if(s){const t=this.input.slice(e,this.state.pos).replace(/[_n]/g,"");this.finishToken(d.bigint,t)}else this.finishToken(d.num,i)}readNumber(t){const e=this.state.pos;let s=!1,i=!1,r=!1;t||null!==this.readInt(10)||this.raise(e,ut.InvalidNumber);let n=this.state.pos-e>=2&&48===this.input.charCodeAt(e);n&&(this.state.strict&&this.raise(e,ut.StrictOctalLiteral),/[89]/.test(this.input.slice(e,this.state.pos))&&(n=!1,r=!0));let a=this.input.charCodeAt(this.state.pos);if(46!==a||n||(++this.state.pos,this.readInt(10),s=!0,a=this.input.charCodeAt(this.state.pos)),69!==a&&101!==a||n||(a=this.input.charCodeAt(++this.state.pos),43!==a&&45!==a||++this.state.pos,null===this.readInt(10)&&this.raise(e,ut.InvalidNumber),s=!0,a=this.input.charCodeAt(this.state.pos)),this.hasPlugin("numericSeparator")&&(n||r)){const t=this.input.slice(e,this.state.pos).indexOf("_");t>0&&this.raise(t+e,ut.ZeroDigitNumericSeparator)}if(95===a&&this.expectPlugin("numericSeparator",this.state.pos),110===a&&((s||n||r)&&this.raise(e,ut.InvalidBigIntLiteral),++this.state.pos,i=!0),At(this.input.codePointAt(this.state.pos)))throw this.raise(this.state.pos,ut.NumberIdentifier);const o=this.input.slice(e,this.state.pos).replace(/[_n]/g,"");if(i)return void this.finishToken(d.bigint,o);const c=n?parseInt(o,8):parseFloat(o);this.finishToken(d.num,c)}readCodePoint(t){const e=this.input.charCodeAt(this.state.pos);let s;if(123===e){const e=++this.state.pos;if(s=this.readHexChar(this.input.indexOf("}",this.state.pos)-this.state.pos,!0,t),++this.state.pos,null!==s&&s>1114111){if(!t)return null;this.raise(e,ut.InvalidCodePoint)}}else s=this.readHexChar(4,!1,t);return s}readString(t){let e="",s=++this.state.pos;for(;;){if(this.state.pos>=this.length)throw this.raise(this.state.start,ut.UnterminatedString);const i=this.input.charCodeAt(this.state.pos);if(i===t)break;if(92===i)e+=this.input.slice(s,this.state.pos),e+=this.readEscapedChar(!1),s=this.state.pos;else if(8232===i||8233===i)++this.state.pos,++this.state.curLine,this.state.lineStart=this.state.pos;else{if(it(i))throw this.raise(this.state.start,ut.UnterminatedString);++this.state.pos}}e+=this.input.slice(s,this.state.pos++),this.finishToken(d.string,e)}readTmplToken(){let t="",e=this.state.pos,s=!1;for(;;){if(this.state.pos>=this.length)throw this.raise(this.state.start,ut.UnterminatedTemplate);const i=this.input.charCodeAt(this.state.pos);if(96===i||36===i&&123===this.input.charCodeAt(this.state.pos+1))return this.state.pos===this.state.start&&this.match(d.template)?36===i?(this.state.pos+=2,void this.finishToken(d.dollarBraceL)):(++this.state.pos,void this.finishToken(d.backQuote)):(t+=this.input.slice(e,this.state.pos),void this.finishToken(d.template,s?null:t));if(92===i){t+=this.input.slice(e,this.state.pos);const i=this.readEscapedChar(!0);null===i?s=!0:t+=i,e=this.state.pos}else if(it(i)){switch(t+=this.input.slice(e,this.state.pos),++this.state.pos,i){case 13:10===this.input.charCodeAt(this.state.pos)&&++this.state.pos;case 10:t+="\n";break;default:t+=String.fromCharCode(i);break}++this.state.curLine,this.state.lineStart=this.state.pos,e=this.state.pos}else++this.state.pos}}readEscapedChar(t){const e=!t,s=this.input.charCodeAt(++this.state.pos);switch(++this.state.pos,s){case 110:return"\n";case 114:return"\r";case 120:{const t=this.readHexChar(2,!1,e);return null===t?null:String.fromCharCode(t)}case 117:{const t=this.readCodePoint(e);return null===t?null:String.fromCodePoint(t)}case 116:return"\t";case 98:return"\b";case 118:return"\v";case 102:return"\f";case 13:10===this.input.charCodeAt(this.state.pos)&&++this.state.pos;case 10:this.state.lineStart=this.state.pos,++this.state.curLine;case 8232:case 8233:return"";case 56:case 57:if(t)return null;default:if(s>=48&&s<=55){const e=this.state.pos-1,s=this.input.substr(this.state.pos-1,3).match(/^[0-7]+/);let i=s[0],r=parseInt(i,8);r>255&&(i=i.slice(0,-1),r=parseInt(i,8)),this.state.pos+=i.length-1;const n=this.input.charCodeAt(this.state.pos);if("0"!==i||56===n||57===n){if(t)return null;this.state.strict?this.raise(e,ut.StrictOctalLiteral):this.state.octalPositions.push(e)}return String.fromCharCode(r)}return String.fromCharCode(s)}}readHexChar(t,e,s){const i=this.state.pos,r=this.readInt(16,t,e,!1);return null===r&&(s?this.raise(i,ut.InvalidEscapeSequence):this.state.pos=i-1),r}readWord1(){let t="";this.state.containsEsc=!1;const e=this.state.pos;let s=this.state.pos;while(this.state.posthis.state.lastTokEnd&&this.raise(this.state.lastTokEnd,t)}unexpected(t,e="Unexpected token"){throw"string"!==typeof e&&(e=`Unexpected token, expected "${e.label}"`),this.raise(null!=t?t:this.state.start,e)}expectPlugin(t,e){if(!this.hasPlugin(t))throw this.raiseWithData(null!=e?e:this.state.start,{missingPlugin:[t]},`This experimental syntax requires enabling the parser plugin: '${t}'`);return!0}expectOnePlugin(t,e){if(!t.some(t=>this.hasPlugin(t)))throw this.raiseWithData(null!=e?e:this.state.start,{missingPlugin:t},`This experimental syntax requires enabling one of the following parser plugin(s): '${t.join(", ")}'`)}checkYieldAwaitInDefaultParams(){-1!==this.state.yieldPos&&(-1===this.state.awaitPos||this.state.yieldPos{throw s.node=t,s});if(this.state.errors.length>e.errors.length){const t=this.state;return this.state=e,{node:i,error:t.errors[e.errors.length],thrown:!1,aborted:!1,failState:t}}return{node:i,error:null,thrown:!1,aborted:!1,failState:null}}catch(i){const t=this.state;if(this.state=e,i instanceof SyntaxError)return{node:null,error:i,thrown:!0,aborted:!1,failState:t};if(i===s)return{node:s.node,error:null,thrown:!1,aborted:!0,failState:t};throw i}}checkExpressionErrors(t,e){if(!t)return!1;const{shorthandAssign:s,doubleProto:i}=t;if(!e)return s>=0||i>=0;s>=0&&this.unexpected(s),i>=0&&this.raise(i,ut.DuplicateProto)}isLiteralPropertyName(){return this.match(d.name)||!!this.state.type.keyword||this.match(d.string)||this.match(d.num)||this.match(d.bigint)}}class Le{constructor(){this.shorthandAssign=-1,this.doubleProto=-1}}class _e{constructor(t,e,s){this.type="",this.start=e,this.end=0,this.loc=new ot(s),(null==t?void 0:t.options.ranges)&&(this.range=[e,0]),(null==t?void 0:t.filename)&&(this.loc.filename=t.filename)}__clone(){const t=new _e,e=Object.keys(this);for(let s=0,i=e.length;s"ParenthesizedExpression"===t.type?je(t.expression):t;class Fe extends Re{toAssignable(t){var e,s;let i=void 0;switch(("ParenthesizedExpression"===t.type||(null==(e=t.extra)?void 0:e.parenthesized))&&(i=je(t),"Identifier"!==i.type&&"MemberExpression"!==i.type&&this.raise(t.start,ut.InvalidParenthesizedAssignment)),t.type){case"Identifier":case"ObjectPattern":case"ArrayPattern":case"AssignmentPattern":break;case"ObjectExpression":t.type="ObjectPattern";for(let e=0,s=t.properties.length,i=s-1;e=s.left.start&&(e.shorthandAssign=-1),this.checkLVal(o,void 0,void 0,"assignment expression"),this.next(),s.right=this.parseMaybeAssign(t),this.finishNode(s,"AssignmentExpression")}return a&&this.checkExpressionErrors(e,!0),o}parseMaybeConditional(t,e,s){const i=this.state.start,r=this.state.startLoc,n=this.state.potentialArrowAt,a=this.parseExprOps(t,e);return"ArrowFunctionExpression"===a.type&&a.start===n||this.checkExpressionErrors(e,!1)?a:this.parseConditional(a,t,i,r,s)}parseConditional(t,e,s,i,r){if(this.eat(d.question)){const r=this.startNodeAt(s,i);return r.test=t,r.consequent=this.parseMaybeAssign(),this.expect(d.colon),r.alternate=this.parseMaybeAssign(e),this.finishNode(r,"ConditionalExpression")}return t}parseExprOps(t,e){const s=this.state.start,i=this.state.startLoc,r=this.state.potentialArrowAt,n=this.parseMaybeUnary(e);return"ArrowFunctionExpression"===n.type&&n.start===r||this.checkExpressionErrors(e,!1)?n:this.parseExprOp(n,s,i,-1,t)}parseExprOp(t,e,s,i,r){let n=this.state.type.binop;if(null!=n&&(!r||!this.match(d._in))&&n>i){const a=this.state.value;if("|>"===a&&this.state.inFSharpPipelineDirectBody)return t;const o=this.startNodeAt(e,s);o.left=t,o.operator=a,"**"!==a||"UnaryExpression"!==t.type||!this.options.createParenthesizedExpressions&&t.extra&&t.extra.parenthesized||this.raise(t.argument.start,ut.UnexpectedTokenUnaryExponentiation);const c=this.state.type,h=c===d.logicalOR||c===d.logicalAND,l=c===d.nullishCoalescing;if(c===d.pipeline?(this.expectPlugin("pipelineOperator"),this.state.inPipeline=!0,this.checkPipelineAtInfixOperator(t,e)):l&&(n=d.logicalAND.binop),this.next(),c===d.pipeline&&"minimal"===this.getPluginOption("pipelineOperator","proposal")&&this.match(d.name)&&"await"===this.state.value&&this.prodParam.hasAwait)throw this.raise(this.state.start,ut.UnexpectedAwaitAfterPipelineBody);o.right=this.parseExprOpRightExpr(c,n,r),this.finishNode(o,h||l?"LogicalExpression":"BinaryExpression");const p=this.state.type;if(l&&(p===d.logicalOR||p===d.logicalAND)||h&&p===d.nullishCoalescing)throw this.raise(this.state.start,ut.MixingCoalesceWithLogical);return this.parseExprOp(o,e,s,i,r)}return t}parseExprOpRightExpr(t,e,s){const i=this.state.start,r=this.state.startLoc;switch(t){case d.pipeline:switch(this.getPluginOption("pipelineOperator","proposal")){case"smart":return this.withTopicPermittingContext(()=>this.parseSmartPipelineBody(this.parseExprOpBaseRightExpr(t,e,s),i,r));case"fsharp":return this.withSoloAwaitPermittingContext(()=>this.parseFSharpPipelineBody(e,s))}default:return this.parseExprOpBaseRightExpr(t,e,s)}}parseExprOpBaseRightExpr(t,e,s){const i=this.state.start,r=this.state.startLoc;return this.parseExprOp(this.parseMaybeUnary(),i,r,t.rightAssociative?e-1:e,s)}parseMaybeUnary(t){if(this.isContextual("await")&&this.isAwaitAllowed())return this.parseAwait();if(this.state.type.prefix){const e=this.startNode(),s=this.match(d.incDec);if(e.operator=this.state.value,e.prefix=!0,"throw"===e.operator&&this.expectPlugin("throwExpressions"),this.next(),e.argument=this.parseMaybeUnary(),this.checkExpressionErrors(t,!0),s)this.checkLVal(e.argument,void 0,void 0,"prefix operation");else if(this.state.strict&&"delete"===e.operator){const t=e.argument;"Identifier"===t.type?this.raise(e.start,ut.StrictDelete):"MemberExpression"!==t.type&&"OptionalMemberExpression"!==t.type||"PrivateName"!==t.property.type||this.raise(e.start,ut.DeletePrivateField)}return this.finishNode(e,s?"UpdateExpression":"UnaryExpression")}const e=this.state.start,s=this.state.startLoc;let i=this.parseExprSubscripts(t);if(this.checkExpressionErrors(t,!1))return i;while(this.state.type.postfix&&!this.canInsertSemicolon()){const t=this.startNodeAt(e,s);t.operator=this.state.value,t.prefix=!1,t.argument=i,this.checkLVal(i,void 0,void 0,"postfix operation"),this.next(),i=this.finishNode(t,"UpdateExpression")}return i}parseExprSubscripts(t){const e=this.state.start,s=this.state.startLoc,i=this.state.potentialArrowAt,r=this.parseExprAtom(t);return"ArrowFunctionExpression"===r.type&&r.start===i?r:this.parseSubscripts(r,e,s)}parseSubscripts(t,e,s,i){const r={optionalChainMember:!1,maybeAsyncArrow:this.atPossibleAsyncArrow(t),stop:!1};do{const n=this.state.maybeInAsyncArrowHead;r.maybeAsyncArrow&&(this.state.maybeInAsyncArrowHead=!0),t=this.parseSubscript(t,e,s,i,r),r.maybeAsyncArrow=!1,this.state.maybeInAsyncArrowHead=n}while(!r.stop);return t}parseSubscript(t,e,s,i,r){if(!i&&this.eat(d.doubleColon)){const n=this.startNodeAt(e,s);return n.object=t,n.callee=this.parseNoCallExpr(),r.stop=!0,this.parseSubscripts(this.finishNode(n,"BindExpression"),e,s,i)}let n=!1;if(this.match(d.questionDot)){if(r.optionalChainMember=n=!0,i&&40===this.lookaheadCharCode())return r.stop=!0,t;this.next()}const a=this.eat(d.bracketL);if(n&&!this.match(d.parenL)&&!this.match(d.backQuote)||a||this.eat(d.dot)){const i=this.startNodeAt(e,s);return i.object=t,i.property=a?this.parseExpression():this.parseMaybePrivateName(!0),i.computed=a,"PrivateName"===i.property.type&&("Super"===i.object.type&&this.raise(e,ut.SuperPrivateField),this.classScope.usePrivateName(i.property.id.name,i.property.start)),a&&this.expect(d.bracketR),r.optionalChainMember?(i.optional=n,this.finishNode(i,"OptionalMemberExpression")):this.finishNode(i,"MemberExpression")}if(!i&&this.match(d.parenL)){const i=this.state.maybeInArrowParameters,a=this.state.yieldPos,o=this.state.awaitPos;this.state.maybeInArrowParameters=!0,this.state.yieldPos=-1,this.state.awaitPos=-1,this.next();let c=this.startNodeAt(e,s);return c.callee=t,r.optionalChainMember&&(c.optional=n),c.arguments=n?this.parseCallExpressionArguments(d.parenR,!1):this.parseCallExpressionArguments(d.parenR,r.maybeAsyncArrow,"Import"===t.type,"Super"!==t.type,c),this.finishCallExpression(c,r.optionalChainMember),r.maybeAsyncArrow&&this.shouldParseAsyncArrow()&&!n?(r.stop=!0,c=this.parseAsyncArrowFromCallExpression(this.startNodeAt(e,s),c),this.checkYieldAwaitInDefaultParams(),this.state.yieldPos=a,this.state.awaitPos=o):(this.toReferencedListDeep(c.arguments),-1!==a&&(this.state.yieldPos=a),(this.isAwaitAllowed()||i)&&-1===o||(this.state.awaitPos=o)),this.state.maybeInArrowParameters=i,c}return this.match(d.backQuote)?this.parseTaggedTemplateExpression(e,s,t,r):(r.stop=!0,t)}parseTaggedTemplateExpression(t,e,s,i,r){const n=this.startNodeAt(t,e);return n.tag=s,n.quasi=this.parseTemplate(!0),r&&(n.typeParameters=r),i.optionalChainMember&&this.raise(t,ut.OptionalChainingNoTemplate),this.finishNode(n,"TaggedTemplateExpression")}atPossibleAsyncArrow(t){return"Identifier"===t.type&&"async"===t.name&&this.state.lastTokEnd===t.end&&!this.canInsertSemicolon()&&t.end-t.start===5&&t.start===this.state.potentialArrowAt}finishCallExpression(t,e){if("Import"===t.callee.type)if(2===t.arguments.length&&this.expectPlugin("moduleAttributes"),0===t.arguments.length||t.arguments.length>2)this.raise(t.start,ut.ImportCallArity,this.hasPlugin("moduleAttributes")?"one or two arguments":"one argument");else for(let s=0,i=t.arguments;s1?(i=this.startNodeAt(c,h),i.expressions=l,this.finishNodeAt(i,"SequenceExpression",g,x)):i=l[0],!this.options.createParenthesizedExpressions)return this.addExtra(i,"parenthesized",!0),this.addExtra(i,"parenStart",e),i;const v=this.startNodeAt(e,s);return v.expression=i,this.finishNode(v,"ParenthesizedExpression"),v}shouldParseArrow(){return!this.canInsertSemicolon()}parseArrow(t){if(this.eat(d.arrow))return t}parseParenItem(t,e,s){return t}parseNew(){const t=this.startNode();let e=this.startNode();if(this.next(),e=this.createIdentifier(e,"new"),this.eat(d.dot)){const s=this.parseMetaProperty(t,e,"target");if(!this.scope.inNonArrowFunction&&!this.scope.inClass){let t=ut.UnexpectedNewTarget;this.hasPlugin("classProperties")&&(t+=" or class properties"),this.raise(s.start,t)}return s}return t.callee=this.parseNoCallExpr(),"Import"===t.callee.type?this.raise(t.callee.start,ut.ImportCallNotNewExpression):"OptionalMemberExpression"===t.callee.type||"OptionalCallExpression"===t.callee.type?this.raise(this.state.lastTokEnd,ut.OptionalChainingNoNew):this.eat(d.questionDot)&&this.raise(this.state.start,ut.OptionalChainingNoNew),this.parseNewArguments(t),this.finishNode(t,"NewExpression")}parseNewArguments(t){if(this.eat(d.parenL)){const e=this.parseExprList(d.parenR);this.toReferencedList(e),t.arguments=e}else t.arguments=[]}parseTemplateElement(t){const e=this.startNode();return null===this.state.value&&(t||this.raise(this.state.start+1,ut.InvalidEscapeSequenceTemplate)),e.value={raw:this.input.slice(this.state.start,this.state.end).replace(/\r\n?/g,"\n"),cooked:this.state.value},this.next(),e.tail=this.match(d.backQuote),this.finishNode(e,"TemplateElement")}parseTemplate(t){const e=this.startNode();this.next(),e.expressions=[];let s=this.parseTemplateElement(t);e.quasis=[s];while(!s.tail)this.expect(d.dollarBraceL),e.expressions.push(this.parseExpression()),this.expect(d.braceR),e.quasis.push(s=this.parseTemplateElement(t));return this.next(),this.finishNode(e,"TemplateLiteral")}parseObj(t,e,s,i){const r=Object.create(null);let n=!0;const a=this.startNode();a.properties=[],this.next();while(!this.eat(t)){if(n)n=!1;else if(this.expect(d.comma),this.match(t)){this.addExtra(a,"trailingComma",this.state.lastTokStart),this.next();break}const o=this.parseObjectMember(e,i);e||this.checkProto(o,s,r,i),s&&"ObjectProperty"!==o.type&&"SpreadElement"!==o.type&&this.raise(o.start,ut.InvalidRecordProperty),o.shorthand&&this.addExtra(o,"shorthand",!0),a.properties.push(o)}let o="ObjectExpression";return e?o="ObjectPattern":s&&(o="RecordExpression"),this.finishNode(a,o)}isAsyncProp(t){return!t.computed&&"Identifier"===t.key.type&&"async"===t.key.name&&(this.isLiteralPropertyName()||this.match(d.bracketL)||this.match(d.star))&&!this.hasPrecedingLineBreak()}parseObjectMember(t,e){let s=[];if(this.match(d.at)){this.hasPlugin("decorators")&&this.raise(this.state.start,ut.UnsupportedPropertyDecorator);while(this.match(d.at))s.push(this.parseDecorator())}const i=this.startNode();let r,n,a=!1,o=!1;if(this.match(d.ellipsis))return s.length&&this.unexpected(),t?(this.next(),i.argument=this.parseIdentifier(),this.checkCommaAfterRest(125),this.finishNode(i,"RestElement")):this.parseSpread();s.length&&(i.decorators=s,s=[]),i.method=!1,(t||e)&&(r=this.state.start,n=this.state.startLoc),t||(a=this.eat(d.star));const c=this.state.containsEsc;return this.parsePropertyName(i,!1),t||c||a||!this.isAsyncProp(i)?o=!1:(o=!0,a=this.eat(d.star),this.parsePropertyName(i,!1)),this.parseObjPropValue(i,r,n,a,o,t,e,c),i}isGetterOrSetterMethod(t,e){return!e&&!t.computed&&"Identifier"===t.key.type&&("get"===t.key.name||"set"===t.key.name)&&(this.isLiteralPropertyName()||this.match(d.bracketL))}getGetterSetterExpectedParamCount(t){return"get"===t.kind?0:1}checkGetterSetterParams(t){const e=this.getGetterSetterExpectedParamCount(t),s=t.start;t.params.length!==e&&("get"===t.kind?this.raise(s,ut.BadGetterArity):this.raise(s,ut.BadSetterArity)),"set"===t.kind&&"RestElement"===t.params[t.params.length-1].type&&this.raise(s,ut.BadSetterRestParameter)}parseObjectMethod(t,e,s,i,r){return s||e||this.match(d.parenL)?(i&&this.unexpected(),t.kind="method",t.method=!0,this.parseMethod(t,e,s,!1,!1,"ObjectMethod")):!r&&this.isGetterOrSetterMethod(t,i)?((e||s)&&this.unexpected(),t.kind=t.key.name,this.parsePropertyName(t,!1),this.parseMethod(t,!1,!1,!1,!1,"ObjectMethod"),this.checkGetterSetterParams(t),t):void 0}parseObjectProperty(t,e,s,i,r){return t.shorthand=!1,this.eat(d.colon)?(t.value=i?this.parseMaybeDefault(this.state.start,this.state.startLoc):this.parseMaybeAssign(!1,r),this.finishNode(t,"ObjectProperty")):t.computed||"Identifier"!==t.key.type?void 0:(this.checkReservedWord(t.key.name,t.key.start,!0,!0),i?t.value=this.parseMaybeDefault(e,s,t.key.__clone()):this.match(d.eq)&&r?(-1===r.shorthandAssign&&(r.shorthandAssign=this.state.start),t.value=this.parseMaybeDefault(e,s,t.key.__clone())):t.value=t.key.__clone(),t.shorthand=!0,this.finishNode(t,"ObjectProperty"))}parseObjPropValue(t,e,s,i,r,n,a,o){const c=this.parseObjectMethod(t,i,r,n,o)||this.parseObjectProperty(t,e,s,n,a);return c||this.unexpected(),c}parsePropertyName(t,e){if(this.eat(d.bracketL))t.computed=!0,t.key=this.parseMaybeAssign(),this.expect(d.bracketR);else{const s=this.state.inPropertyName;this.state.inPropertyName=!0,t.key=this.match(d.num)||this.match(d.string)||this.match(d.bigint)?this.parseExprAtom():this.parseMaybePrivateName(e),"PrivateName"!==t.key.type&&(t.computed=!1),this.state.inPropertyName=s}return t.key}initFunction(t,e){t.id=null,t.generator=!1,t.async=!!e}parseMethod(t,e,s,i,r,n,a=!1){const o=this.state.yieldPos,c=this.state.awaitPos;this.state.yieldPos=-1,this.state.awaitPos=-1,this.initFunction(t,s),t.generator=!!e;const h=i;return this.scope.enter(y|b|(a?w:0)|(r?v:0)),this.prodParam.enter(he(s,t.generator)),this.parseFunctionParams(t,h),this.parseFunctionBodyAndFinish(t,n,!0),this.prodParam.exit(),this.scope.exit(),this.state.yieldPos=o,this.state.awaitPos=c,t}parseArrowExpression(t,e,s,i){this.scope.enter(y|g),this.prodParam.enter(he(s,!1)),this.initFunction(t,s);const r=this.state.maybeInArrowParameters,n=this.state.yieldPos,a=this.state.awaitPos;return e&&(this.state.maybeInArrowParameters=!0,this.setArrowFunctionParameters(t,e,i)),this.state.maybeInArrowParameters=!1,this.state.yieldPos=-1,this.state.awaitPos=-1,this.parseFunctionBody(t,!0),this.prodParam.exit(),this.scope.exit(),this.state.maybeInArrowParameters=r,this.state.yieldPos=n,this.state.awaitPos=a,this.finishNode(t,"ArrowFunctionExpression")}setArrowFunctionParameters(t,e,s){t.params=this.toAssignableList(e,s)}parseFunctionBodyAndFinish(t,e,s=!1){this.parseFunctionBody(t,!1,s),this.finishNode(t,e)}parseFunctionBody(t,e,s=!1){const i=e&&!this.match(d.braceL),r=this.state.inParameters;if(this.state.inParameters=!1,i)t.body=this.parseMaybeAssign(),this.checkParams(t,!1,e,!1);else{const i=this.state.strict,r=this.state.labels;this.state.labels=[],this.prodParam.enter(this.prodParam.currentFlags()|oe),t.body=this.parseBlock(!0,!1,r=>{const n=!this.isSimpleParamList(t.params);if(r&&n){const e="method"!==t.kind&&"constructor"!==t.kind||!t.key?t.start:t.key.end;this.raise(e,ut.IllegalLanguageModeDirective)}const a=!i&&this.state.strict;this.checkParams(t,!this.state.strict&&!e&&!s&&!n,e,a),this.state.strict&&t.id&&this.checkLVal(t.id,H,void 0,"function name",void 0,a)}),this.prodParam.exit(),this.state.labels=r}this.state.inParameters=r}isSimpleParamList(t){for(let e=0,s=t.length;e=1}topicReferenceWasUsedInCurrentTopicContext(){return null!=this.state.topicContext.maxTopicIndex&&this.state.topicContext.maxTopicIndex>=0}parseFSharpPipelineBody(t,e){const s=this.state.start,i=this.state.startLoc;this.state.potentialArrowAt=this.state.start;const r=this.state.inFSharpPipelineDirectBody;this.state.inFSharpPipelineDirectBody=!0;const n=this.parseExprOp(this.parseMaybeUnary(),s,i,t,e);return this.state.inFSharpPipelineDirectBody=r,n}}const Ue={kind:"loop"},qe={kind:"switch"},Ve=0,He=1,ze=2,We=4;class Ke extends Be{parseTopLevel(t,e){if(e.sourceType=this.options.sourceType,e.interpreter=this.parseInterpreterDirective(),this.parseBlockBody(e,!0,!0,d.eof),this.inModule&&!this.options.allowUndeclaredExports&&this.scope.undefinedExports.size>0)for(let s=0,i=Array.from(this.scope.undefinedExports);sthis.parseStatement("do")),this.state.labels.pop(),this.expect(d._while),t.test=this.parseHeaderExpression(),this.eat(d.semi),this.finishNode(t,"DoWhileStatement")}parseForStatement(t){this.next(),this.state.labels.push(Ue);let e=-1;if(this.isAwaitAllowed()&&this.eatContextual("await")&&(e=this.state.lastTokStart),this.scope.enter(f),this.expect(d.parenL),this.match(d.semi))return e>-1&&this.unexpected(e),this.parseFor(t,null);const s=this.isLet();if(this.match(d._var)||this.match(d._const)||s){const i=this.startNode(),r=s?"let":this.state.value;return this.next(),this.parseVar(i,!0,r),this.finishNode(i,"VariableDeclaration"),(this.match(d._in)||this.isContextual("of"))&&1===i.declarations.length?this.parseForIn(t,i,e):(e>-1&&this.unexpected(e),this.parseFor(t,i))}const i=new Le,r=this.parseExpression(!0,i);if(this.match(d._in)||this.isContextual("of")){this.toAssignable(r);const s=this.isContextual("of")?"for-of statement":"for-in statement";return this.checkLVal(r,void 0,void 0,s),this.parseForIn(t,r,e)}return this.checkExpressionErrors(i,!0),e>-1&&this.unexpected(e),this.parseFor(t,r)}parseFunctionStatement(t,e,s){return this.next(),this.parseFunction(t,He|(s?0:ze),e)}parseIfStatement(t){return this.next(),t.test=this.parseHeaderExpression(),t.consequent=this.parseStatement("if"),t.alternate=this.eat(d._else)?this.parseStatement("if"):null,this.finishNode(t,"IfStatement")}parseReturnStatement(t){return this.prodParam.hasReturn||this.options.allowReturnOutsideFunction||this.raise(this.state.start,ut.IllegalReturn),this.next(),this.isLineTerminator()?t.argument=null:(t.argument=this.parseExpression(),this.semicolon()),this.finishNode(t,"ReturnStatement")}parseSwitchStatement(t){this.next(),t.discriminant=this.parseHeaderExpression();const e=t.cases=[];let s,i;for(this.expect(d.braceL),this.state.labels.push(qe),this.scope.enter(f);!this.match(d.braceR);)if(this.match(d._case)||this.match(d._default)){const t=this.match(d._case);s&&this.finishNode(s,"SwitchCase"),e.push(s=this.startNode()),s.consequent=[],this.next(),t?s.test=this.parseExpression():(i&&this.raise(this.state.lastTokStart,ut.MultipleDefaultsInSwitch),i=!0,s.test=null),this.expect(d.colon)}else s?s.consequent.push(this.parseStatement(null)):this.unexpected();return this.scope.exit(),s&&this.finishNode(s,"SwitchCase"),this.next(),this.state.labels.pop(),this.finishNode(t,"SwitchStatement")}parseThrowStatement(t){return this.next(),et.test(this.input.slice(this.state.lastTokEnd,this.state.start))&&this.raise(this.state.lastTokEnd,ut.NewlineAfterThrow),t.argument=this.parseExpression(),this.semicolon(),this.finishNode(t,"ThrowStatement")}parseTryStatement(t){if(this.next(),t.block=this.parseBlock(),t.handler=null,this.match(d._catch)){const e=this.startNode();if(this.next(),this.match(d.parenL)){this.expect(d.parenL),e.param=this.parseBindingAtom();const t="Identifier"===e.param.type;this.scope.enter(t?x:0),this.checkLVal(e.param,_,null,"catch clause"),this.expect(d.parenR)}else e.param=null,this.scope.enter(f);e.body=this.withTopicForbiddingContext(()=>this.parseBlock(!1,!1)),this.scope.exit(),t.handler=this.finishNode(e,"CatchClause")}return t.finalizer=this.eat(d._finally)?this.parseBlock():null,t.handler||t.finalizer||this.raise(t.start,ut.NoCatchOrFinally),this.finishNode(t,"TryStatement")}parseVarStatement(t,e){return this.next(),this.parseVar(t,!1,e),this.semicolon(),this.finishNode(t,"VariableDeclaration")}parseWhileStatement(t){return this.next(),t.test=this.parseHeaderExpression(),this.state.labels.push(Ue),t.body=this.withTopicForbiddingContext(()=>this.parseStatement("while")),this.state.labels.pop(),this.finishNode(t,"WhileStatement")}parseWithStatement(t){return this.state.strict&&this.raise(this.state.start,ut.StrictWith),this.next(),t.object=this.parseHeaderExpression(),t.body=this.withTopicForbiddingContext(()=>this.parseStatement("with")),this.finishNode(t,"WithStatement")}parseEmptyStatement(t){return this.next(),this.finishNode(t,"EmptyStatement")}parseLabeledStatement(t,e,s,i){for(let n=0,a=this.state.labels;n=0;n--){const e=this.state.labels[n];if(e.statementStart!==t.start)break;e.statementStart=this.state.start,e.kind=r}return this.state.labels.push({name:e,kind:r,statementStart:this.state.start}),t.body=this.parseStatement(i?-1===i.indexOf("label")?i+"label":i:"label"),this.state.labels.pop(),t.label=s,this.finishNode(t,"LabeledStatement")}parseExpressionStatement(t,e){return t.expression=e,this.semicolon(),this.finishNode(t,"ExpressionStatement")}parseBlock(t=!1,e=!0,s){const i=this.startNode();return this.expect(d.braceL),e&&this.scope.enter(f),this.parseBlockBody(i,t,!1,d.braceR,s),e&&this.scope.exit(),this.finishNode(i,"BlockStatement")}isValidDirective(t){return"ExpressionStatement"===t.type&&"StringLiteral"===t.expression.type&&!t.expression.extra.parenthesized}parseBlockBody(t,e,s,i,r){const n=t.body=[],a=t.directives=[];this.parseBlockOrModuleBlockBody(n,e?a:void 0,s,i,r)}parseBlockOrModuleBlockBody(t,e,s,i,r){const n=[],a=this.state.strict;let o=!1,c=!1;while(!this.match(i)){!c&&this.state.octalPositions.length&&n.push(...this.state.octalPositions);const i=this.parseStatement(null,s);if(e&&!c&&this.isValidDirective(i)){const t=this.stmtToDirective(i);e.push(t),o||"use strict"!==t.value.value||(o=!0,this.setStrict(!0))}else c=!0,t.push(i)}if(this.state.strict&&n.length)for(let h=0;hthis.parseStatement("for")),this.scope.exit(),this.state.labels.pop(),this.finishNode(t,"ForStatement")}parseForIn(t,e,s){const i=this.match(d._in);return this.next(),i?s>-1&&this.unexpected(s):t.await=s>-1,"VariableDeclaration"!==e.type||null==e.declarations[0].init||i&&!this.state.strict&&"var"===e.kind&&"Identifier"===e.declarations[0].id.type?"AssignmentPattern"===e.type&&this.raise(e.start,ut.InvalidLhs,"for-loop"):this.raise(e.start,ut.ForInOfLoopInitializer,i?"for-in":"for-of"),t.left=e,t.right=i?this.parseExpression():this.parseMaybeAssign(),this.expect(d.parenR),t.body=this.withTopicForbiddingContext(()=>this.parseStatement("for")),this.scope.exit(),this.state.labels.pop(),this.finishNode(t,i?"ForInStatement":"ForOfStatement")}parseVar(t,e,s){const i=t.declarations=[],r=this.hasPlugin("typescript");for(t.kind=s;;){const t=this.startNode();if(this.parseVarId(t,s),this.eat(d.eq)?t.init=this.parseMaybeAssign(e):("const"!==s||this.match(d._in)||this.isContextual("of")?"Identifier"===t.id.type||e&&(this.match(d._in)||this.isContextual("of"))||this.raise(this.state.lastTokEnd,ut.DeclarationMissingInitializer,"Complex binding patterns"):r||this.unexpected(),t.init=null),i.push(this.finishNode(t,"VariableDeclarator")),!this.eat(d.comma))break}return t}parseVarId(t,e){t.id=this.parseBindingAtom(),this.checkLVal(t.id,"var"===e?R:_,void 0,"variable declaration","var"!==e)}parseFunction(t,e=Ve,s=!1){const i=e&He,r=e&ze,n=!!i&&!(e&We);this.initFunction(t,s),this.match(d.star)&&r&&this.raise(this.state.start,ut.GeneratorInSingleStatementContext),t.generator=this.eat(d.star),i&&(t.id=this.parseFunctionId(n));const a=this.state.maybeInArrowParameters,o=this.state.yieldPos,c=this.state.awaitPos;return this.state.maybeInArrowParameters=!1,this.state.yieldPos=-1,this.state.awaitPos=-1,this.scope.enter(y),this.prodParam.enter(he(s,t.generator)),i||(t.id=this.parseFunctionId()),this.parseFunctionParams(t),this.withTopicForbiddingContext(()=>{this.parseFunctionBodyAndFinish(t,i?"FunctionDeclaration":"FunctionExpression")}),this.prodParam.exit(),this.scope.exit(),i&&!r&&this.registerFunctionStatementId(t),this.state.maybeInArrowParameters=a,this.state.yieldPos=o,this.state.awaitPos=c,t}parseFunctionId(t){return t||this.match(d.name)?this.parseIdentifier():null}parseFunctionParams(t,e){const s=this.state.inParameters;this.state.inParameters=!0,this.expect(d.parenL),t.params=this.parseBindingList(d.parenR,41,!1,e),this.state.inParameters=s,this.checkYieldAwaitInDefaultParams()}registerFunctionStatementId(t){t.id&&this.scope.declareName(t.id.name,this.state.strict||t.generator||t.async?this.scope.treatFunctionsAsVar?R:_:j,t.id.start)}parseClass(t,e,s){this.next(),this.takeDecorators(t);const i=this.state.strict;return this.state.strict=!0,this.parseClassId(t,e,s),this.parseClassSuper(t),t.body=this.parseClassBody(!!t.superClass,i),this.state.strict=i,this.finishNode(t,e?"ClassDeclaration":"ClassExpression")}isClassProperty(){return this.match(d.eq)||this.match(d.semi)||this.match(d.braceR)}isClassMethod(){return this.match(d.parenL)}isNonstaticConstructor(t){return!t.computed&&!t.static&&("constructor"===t.key.name||"constructor"===t.key.value)}parseClassBody(t,e){this.classScope.enter();const s={hadConstructor:!1};let i=[];const r=this.startNode();if(r.body=[],this.expect(d.braceL),this.withTopicForbiddingContext(()=>{while(!this.match(d.braceR)){if(this.eat(d.semi)){if(i.length>0)throw this.raise(this.state.lastTokEnd,ut.DecoratorSemicolon);continue}if(this.match(d.at)){i.push(this.parseDecorator());continue}const e=this.startNode();i.length&&(e.decorators=i,this.resetStartLocationFromNode(e,i[0]),i=[]),this.parseClassMember(r,e,s,t),"constructor"===e.kind&&e.decorators&&e.decorators.length>0&&this.raise(e.start,ut.DecoratorConstructor)}}),e||(this.state.strict=!1),this.next(),i.length)throw this.raise(this.state.start,ut.TrailingDecorator);return this.classScope.exit(),this.finishNode(r,"ClassBody")}parseClassMemberFromModifier(t,e){const s=this.state.containsEsc,i=this.parseIdentifier(!0);if(this.isClassMethod()){const s=e;return s.kind="method",s.computed=!1,s.key=i,s.static=!1,this.pushClassMethod(t,s,!1,!1,!1,!1),!0}if(this.isClassProperty()){const s=e;return s.computed=!1,s.key=i,s.static=!1,t.body.push(this.parseClassProperty(s)),!0}if(s)throw this.unexpected();return!1}parseClassMember(t,e,s,i){const r=this.isContextual("static");r&&this.parseClassMemberFromModifier(t,e)||this.parseClassMemberWithIsStatic(t,e,s,r,i)}parseClassMemberWithIsStatic(t,e,s,i,r){const n=e,a=e,o=e,c=e,h=n,l=n;if(e.static=i,this.eat(d.star))return h.kind="method",this.parseClassPropertyName(h),"PrivateName"===h.key.type?void this.pushClassPrivateMethod(t,a,!0,!1):(this.isNonstaticConstructor(n)&&this.raise(n.key.start,ut.ConstructorIsGenerator),void this.pushClassMethod(t,n,!0,!1,!1,!1));const p=this.state.containsEsc,u=this.parseClassPropertyName(e),f="PrivateName"===u.type,m="Identifier"===u.type,y=this.state.start;if(this.parsePostMemberNameModifiers(l),this.isClassMethod()){if(h.kind="method",f)return void this.pushClassPrivateMethod(t,a,!1,!1);const e=this.isNonstaticConstructor(n);let i=!1;e&&(n.kind="constructor",s.hadConstructor&&!this.hasPlugin("typescript")&&this.raise(u.start,ut.DuplicateConstructor),s.hadConstructor=!0,i=r),this.pushClassMethod(t,n,!1,!1,e,i)}else if(this.isClassProperty())f?this.pushClassPrivateProperty(t,c):this.pushClassProperty(t,o);else if(!m||"async"!==u.name||p||this.isLineTerminator())!m||"get"!==u.name&&"set"!==u.name||p||this.match(d.star)&&this.isLineTerminator()?this.isLineTerminator()?f?this.pushClassPrivateProperty(t,c):this.pushClassProperty(t,o):this.unexpected():(h.kind=u.name,this.parseClassPropertyName(n),"PrivateName"===h.key.type?this.pushClassPrivateMethod(t,a,!1,!1):(this.isNonstaticConstructor(n)&&this.raise(n.key.start,ut.ConstructorIsAccessor),this.pushClassMethod(t,n,!1,!1,!1,!1)),this.checkGetterSetterParams(n));else{const e=this.eat(d.star);l.optional&&this.unexpected(y),h.kind="method",this.parseClassPropertyName(h),this.parsePostMemberNameModifiers(l),"PrivateName"===h.key.type?this.pushClassPrivateMethod(t,a,e,!0):(this.isNonstaticConstructor(n)&&this.raise(n.key.start,ut.ConstructorIsAsync),this.pushClassMethod(t,n,e,!0,!1,!1))}}parseClassPropertyName(t){const e=this.parsePropertyName(t,!0);return t.computed||!t.static||"prototype"!==e.name&&"prototype"!==e.value||this.raise(e.start,ut.StaticPrototype),"PrivateName"===e.type&&"constructor"===e.id.name&&this.raise(e.start,ut.ConstructorClassPrivateField),e}pushClassProperty(t,e){e.computed||"constructor"!==e.key.name&&"constructor"!==e.key.value||this.raise(e.key.start,ut.ConstructorClassField),t.body.push(this.parseClassProperty(e))}pushClassPrivateProperty(t,e){this.expectPlugin("classPrivateProperties",e.key.start);const s=this.parseClassPrivateProperty(e);t.body.push(s),this.classScope.declarePrivateName(s.key.id.name,tt,s.key.start)}pushClassMethod(t,e,s,i,r,n){t.body.push(this.parseMethod(e,s,i,r,n,"ClassMethod",!0))}pushClassPrivateMethod(t,e,s,i){this.expectPlugin("classPrivateMethods",e.key.start);const r=this.parseMethod(e,s,i,!1,!1,"ClassPrivateMethod",!0);t.body.push(r);const n="get"===r.kind?r.static?Y:Q:"set"===r.kind?r.static?J:Z:tt;this.classScope.declarePrivateName(r.key.id.name,n,r.key.start)}parsePostMemberNameModifiers(t){}parseAccessModifier(){}parseClassPrivateProperty(t){return this.scope.enter(w|b),this.prodParam.enter(re),t.value=this.eat(d.eq)?this.parseMaybeAssign():null,this.semicolon(),this.prodParam.exit(),this.scope.exit(),this.finishNode(t,"ClassPrivateProperty")}parseClassProperty(t){return t.typeAnnotation||this.expectPlugin("classProperties"),this.scope.enter(w|b),this.prodParam.enter(re),this.match(d.eq)?(this.expectPlugin("classProperties"),this.next(),t.value=this.parseMaybeAssign()):t.value=null,this.semicolon(),this.prodParam.exit(),this.scope.exit(),this.finishNode(t,"ClassProperty")}parseClassId(t,e,s,i=L){this.match(d.name)?(t.id=this.parseIdentifier(),e&&this.checkLVal(t.id,i,void 0,"class name")):s||!e?t.id=null:this.unexpected(null,ut.MissingClassName)}parseClassSuper(t){t.superClass=this.eat(d._extends)?this.parseExprSubscripts():null}parseExport(t){const e=this.maybeParseExportDefaultSpecifier(t),s=!e||this.eat(d.comma),i=s&&this.eatExportStar(t),r=i&&this.maybeParseExportNamespaceSpecifier(t),n=s&&(!r||this.eat(d.comma)),a=e||i;if(i&&!r)return e&&this.unexpected(),this.parseExportFrom(t,!0),this.finishNode(t,"ExportAllDeclaration");const o=this.maybeParseExportNamedSpecifiers(t);if(e&&s&&!i&&!o||r&&n&&!o)throw this.unexpected(null,d.braceL);let c;if(a||o?(c=!1,this.parseExportFrom(t,a)):c=this.maybeParseExportDeclaration(t),a||o||c)return this.checkExport(t,!0,!1,!!t.source),this.finishNode(t,"ExportNamedDeclaration");if(this.eat(d._default))return t.declaration=this.parseExportDefaultExpression(),this.checkExport(t,!0,!0),this.finishNode(t,"ExportDefaultDeclaration");throw this.unexpected(null,d.braceL)}eatExportStar(t){return this.eat(d.star)}maybeParseExportDefaultSpecifier(t){if(this.isExportDefaultSpecifier()){this.expectPlugin("exportDefaultFrom");const e=this.startNode();return e.exported=this.parseIdentifier(!0),t.specifiers=[this.finishNode(e,"ExportDefaultSpecifier")],!0}return!1}maybeParseExportNamespaceSpecifier(t){if(this.isContextual("as")){t.specifiers||(t.specifiers=[]);const e=this.startNodeAt(this.state.lastTokStart,this.state.lastTokStartLoc);return this.next(),e.exported=this.parseIdentifier(!0),t.specifiers.push(this.finishNode(e,"ExportNamespaceSpecifier")),!0}return!1}maybeParseExportNamedSpecifiers(t){return!!this.match(d.braceL)&&(t.specifiers||(t.specifiers=[]),t.specifiers.push(...this.parseExportSpecifiers()),t.source=null,t.declaration=null,!0)}maybeParseExportDeclaration(t){if(this.shouldParseExportDeclaration()){if(this.isContextual("async")){const t=this.nextTokenStart();this.isUnparsedContextual(t,"function")||this.unexpected(t,d._function)}return t.specifiers=[],t.source=null,t.declaration=this.parseExportDeclaration(t),!0}return!1}isAsyncFunction(){if(!this.isContextual("async"))return!1;const t=this.nextTokenStart();return!et.test(this.input.slice(this.state.pos,t))&&this.isUnparsedContextual(t,"function")}parseExportDefaultExpression(){const t=this.startNode(),e=this.isAsyncFunction();if(this.match(d._function)||e)return this.next(),e&&this.next(),this.parseFunction(t,He|We,e);if(this.match(d._class))return this.parseClass(t,!0,!0);if(this.match(d.at))return this.hasPlugin("decorators")&&this.getPluginOption("decorators","decoratorsBeforeExport")&&this.raise(this.state.start,ut.DecoratorBeforeExport),this.parseDecorators(!1),this.parseClass(t,!0,!0);if(this.match(d._const)||this.match(d._var)||this.isLet())throw this.raise(this.state.start,ut.UnsupportedDefaultExport);{const t=this.parseMaybeAssign();return this.semicolon(),t}}parseExportDeclaration(t){return this.parseStatement(null)}isExportDefaultSpecifier(){if(this.match(d.name)){const t=this.state.value;if("async"===t||"let"===t)return!1;if(("type"===t||"interface"===t)&&!this.state.containsEsc){const t=this.lookahead();if(t.type===d.name&&"from"!==t.value||t.type===d.braceL)return this.expectOnePlugin(["flow","typescript"]),!1}}else if(!this.match(d._default))return!1;const t=this.nextTokenStart(),e=this.isUnparsedContextual(t,"from");if(44===this.input.charCodeAt(t)||this.match(d.name)&&e)return!0;if(this.match(d._default)&&e){const e=this.input.charCodeAt(this.nextTokenStartSince(t+4));return 34===e||39===e}return!1}parseExportFrom(t,e){this.eatContextual("from")?(t.source=this.parseImportSource(),this.checkExport(t)):e?this.unexpected():t.source=null,this.semicolon()}shouldParseExportDeclaration(){if(this.match(d.at)&&(this.expectOnePlugin(["decorators","decorators-legacy"]),this.hasPlugin("decorators"))){if(!this.getPluginOption("decorators","decoratorsBeforeExport"))return!0;this.unexpected(this.state.start,ut.DecoratorBeforeExport)}return"var"===this.state.type.keyword||"const"===this.state.type.keyword||"function"===this.state.type.keyword||"class"===this.state.type.keyword||this.isLet()||this.isAsyncFunction()}checkExport(t,e,s,i){if(e)if(s){if(this.checkDuplicateExports(t,"default"),this.hasPlugin("exportDefaultFrom")){var r;const e=t.declaration;"Identifier"!==e.type||"from"!==e.name||e.end-e.start!==4||(null==(r=e.extra)?void 0:r.parenthesized)||this.raise(e.start,ut.ExportDefaultFromAsIdentifier)}}else if(t.specifiers&&t.specifiers.length)for(let a=0,o=t.specifiers;a-1&&this.raise(t.start,"default"===e?ut.DuplicateDefaultExport:ut.DuplicateExport,e),this.state.exportedIdentifiers.push(e)}parseExportSpecifiers(){const t=[];let e=!0;this.expect(d.braceL);while(!this.eat(d.braceR)){if(e)e=!1;else if(this.expect(d.comma),this.eat(d.braceR))break;const s=this.startNode();s.local=this.parseIdentifier(!0),s.exported=this.eatContextual("as")?this.parseIdentifier(!0):s.local.__clone(),t.push(this.finishNode(s,"ExportSpecifier"))}return t}parseImport(t){if(t.specifiers=[],!this.match(d.string)){const e=this.maybeParseDefaultImportSpecifier(t),s=!e||this.eat(d.comma),i=s&&this.maybeParseStarImportSpecifier(t);s&&!i&&this.parseNamedImportSpecifiers(t),this.expectContextual("from")}t.source=this.parseImportSource();const e=this.maybeParseModuleAttributes();return e&&(t.attributes=e),this.semicolon(),this.finishNode(t,"ImportDeclaration")}parseImportSource(){return this.match(d.string)||this.unexpected(),this.parseExprAtom()}shouldParseDefaultImport(t){return this.match(d.name)}parseImportSpecifierLocal(t,e,s,i){e.local=this.parseIdentifier(),this.checkLVal(e.local,_,void 0,i),t.specifiers.push(this.finishNode(e,s))}maybeParseModuleAttributes(){if(!this.match(d._with)||this.hasPrecedingLineBreak())return this.hasPlugin("moduleAttributes")?[]:null;this.expectPlugin("moduleAttributes"),this.next();const t=[],e=new Set;do{const s=this.startNode();if(s.key=this.parseIdentifier(!0),"type"!==s.key.name&&this.raise(s.key.start,ut.ModuleAttributeDifferentFromType,s.key.name),e.has(s.key.name)&&this.raise(s.key.start,ut.ModuleAttributesWithDuplicateKeys,s.key.name),e.add(s.key.name),this.expect(d.colon),!this.match(d.string))throw this.unexpected(this.state.start,ut.ModuleAttributeInvalidValue);s.value=this.parseLiteral(this.state.value,"StringLiteral"),this.finishNode(s,"ImportAttribute"),t.push(s)}while(this.eat(d.comma));return t}maybeParseDefaultImportSpecifier(t){return!!this.shouldParseDefaultImport(t)&&(this.parseImportSpecifierLocal(t,this.startNode(),"ImportDefaultSpecifier","default import specifier"),!0)}maybeParseStarImportSpecifier(t){if(this.match(d.star)){const e=this.startNode();return this.next(),this.expectContextual("as"),this.parseImportSpecifierLocal(t,e,"ImportNamespaceSpecifier","import namespace specifier"),!0}return!1}parseNamedImportSpecifiers(t){let e=!0;this.expect(d.braceL);while(!this.eat(d.braceR)){if(e)e=!1;else{if(this.eat(d.colon))throw this.raise(this.state.start,ut.DestructureNamedImport);if(this.expect(d.comma),this.eat(d.braceR))break}this.parseImportSpecifier(t)}}parseImportSpecifier(t){const e=this.startNode();e.imported=this.parseIdentifier(!0),this.eatContextual("as")?e.local=this.parseIdentifier():(this.checkReservedWord(e.imported.name,e.start,!0,!0),e.local=e.imported.__clone()),this.checkLVal(e.local,_,void 0,"import specifier"),t.specifiers.push(this.finishNode(e,"ImportSpecifier"))}}class $e{constructor(){this.privateNames=new Set,this.loneAccessors=new Map,this.undefinedPrivateNames=new Map}}class Xe{constructor(t){this.stack=[],this.undefinedPrivateNames=new Map,this.raise=t}current(){return this.stack[this.stack.length-1]}enter(){this.stack.push(new $e)}exit(){const t=this.stack.pop(),e=this.current();for(let s=0,i=Array.from(t.undefinedPrivateNames);sge(t,e)),s=e.join("/");let i=ts[s];if(!i){i=Ge;for(let t=0;t=51||!i((function(){var e=[],s=e.constructor={};return s[a]=function(){return{foo:1}},1!==e[t](Boolean).foo}))}},"21a1":function(t,e,s){(function(e){(function(e,s){t.exports=s()})(0,(function(){"use strict";"undefined"!==typeof window?window:"undefined"!==typeof e||"undefined"!==typeof self&&self;function t(t,e){return e={exports:{}},t(e,e.exports),e.exports}var s=t((function(t,e){(function(e,s){t.exports=s()})(0,(function(){function t(t){var e=t&&"object"===typeof t;return e&&"[object RegExp]"!==Object.prototype.toString.call(t)&&"[object Date]"!==Object.prototype.toString.call(t)}function e(t){return Array.isArray(t)?[]:{}}function s(s,i){var r=i&&!0===i.clone;return r&&t(s)?n(e(s),s,i):s}function i(e,i,r){var a=e.slice();return i.forEach((function(i,o){"undefined"===typeof a[o]?a[o]=s(i,r):t(i)?a[o]=n(e[o],i,r):-1===e.indexOf(i)&&a.push(s(i,r))})),a}function r(e,i,r){var a={};return t(e)&&Object.keys(e).forEach((function(t){a[t]=s(e[t],r)})),Object.keys(i).forEach((function(o){t(i[o])&&e[o]?a[o]=n(e[o],i[o],r):a[o]=s(i[o],r)})),a}function n(t,e,n){var a=Array.isArray(e),o=n||{arrayMerge:i},c=o.arrayMerge||i;return a?Array.isArray(t)?c(t,e,n):s(e,n):r(t,e,n)}return n.all=function(t,e){if(!Array.isArray(t)||t.length<2)throw new Error("first argument should be an array with at least two elements");return t.reduce((function(t,s){return n(t,s,e)}))},n}))}));function i(t){return t=t||Object.create(null),{on:function(e,s){(t[e]||(t[e]=[])).push(s)},off:function(e,s){t[e]&&t[e].splice(t[e].indexOf(s)>>>0,1)},emit:function(e,s){(t[e]||[]).map((function(t){t(s)})),(t["*"]||[]).map((function(t){t(e,s)}))}}}var r=t((function(t,e){var s={svg:{name:"xmlns",uri:"http://www.w3.org/2000/svg"},xlink:{name:"xmlns:xlink",uri:"http://www.w3.org/1999/xlink"}};e.default=s,t.exports=e.default})),n=function(t){return Object.keys(t).map((function(e){var s=t[e].toString().replace(/"/g,""");return e+'="'+s+'"'})).join(" ")},a=r.svg,o=r.xlink,c={};c[a.name]=a.uri,c[o.name]=o.uri;var h,l=function(t,e){void 0===t&&(t="");var i=s(c,e||{}),r=n(i);return""+t+""},p=r.svg,u=r.xlink,d={attrs:(h={style:["position: absolute","width: 0","height: 0"].join("; "),"aria-hidden":"true"},h[p.name]=p.uri,h[u.name]=u.uri,h)},f=function(t){this.config=s(d,t||{}),this.symbols=[]};f.prototype.add=function(t){var e=this,s=e.symbols,i=this.find(t.id);return i?(s[s.indexOf(i)]=t,!1):(s.push(t),!0)},f.prototype.remove=function(t){var e=this,s=e.symbols,i=this.find(t);return!!i&&(s.splice(s.indexOf(i),1),i.destroy(),!0)},f.prototype.find=function(t){return this.symbols.filter((function(e){return e.id===t}))[0]||null},f.prototype.has=function(t){return null!==this.find(t)},f.prototype.stringify=function(){var t=this.config,e=t.attrs,s=this.symbols.map((function(t){return t.stringify()})).join("");return l(s,e)},f.prototype.toString=function(){return this.stringify()},f.prototype.destroy=function(){this.symbols.forEach((function(t){return t.destroy()}))};var m=function(t){var e=t.id,s=t.viewBox,i=t.content;this.id=e,this.viewBox=s,this.content=i};m.prototype.stringify=function(){return this.content},m.prototype.toString=function(){return this.stringify()},m.prototype.destroy=function(){var t=this;["id","viewBox","content"].forEach((function(e){return delete t[e]}))};var y=function(t){var e=!!document.importNode,s=(new DOMParser).parseFromString(t,"image/svg+xml").documentElement;return e?document.importNode(s,!0):s},g=function(t){function e(){t.apply(this,arguments)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var s={isMounted:{}};return s.isMounted.get=function(){return!!this.node},e.createFromExistingNode=function(t){return new e({id:t.getAttribute("id"),viewBox:t.getAttribute("viewBox"),content:t.outerHTML})},e.prototype.destroy=function(){this.isMounted&&this.unmount(),t.prototype.destroy.call(this)},e.prototype.mount=function(t){if(this.isMounted)return this.node;var e="string"===typeof t?document.querySelector(t):t,s=this.render();return this.node=s,e.appendChild(s),s},e.prototype.render=function(){var t=this.stringify();return y(l(t)).childNodes[0]},e.prototype.unmount=function(){this.node.parentNode.removeChild(this.node)},Object.defineProperties(e.prototype,s),e}(m),x={autoConfigure:!0,mountTo:"body",syncUrlsWithBaseTag:!1,listenLocationChangeEvent:!0,locationChangeEvent:"locationChange",locationChangeAngularEmitter:!1,usagesToUpdate:"use[*|href]",moveGradientsOutsideSymbol:!1},b=function(t){return Array.prototype.slice.call(t,0)},v={isChrome:function(){return/chrome/i.test(navigator.userAgent)},isFirefox:function(){return/firefox/i.test(navigator.userAgent)},isIE:function(){return/msie/i.test(navigator.userAgent)||/trident/i.test(navigator.userAgent)},isEdge:function(){return/edge/i.test(navigator.userAgent)}},w=function(t,e){var s=document.createEvent("CustomEvent");s.initCustomEvent(t,!1,!1,e),window.dispatchEvent(s)},P=function(t){var e=[];return b(t.querySelectorAll("style")).forEach((function(t){t.textContent+="",e.push(t)})),e},T=function(t){return(t||window.location.href).split("#")[0]},E=function(t){angular.module("ng").run(["$rootScope",function(e){e.$on("$locationChangeSuccess",(function(e,s,i){w(t,{oldUrl:i,newUrl:s})}))}])},A="linearGradient, radialGradient, pattern, mask, clipPath",S=function(t,e){return void 0===e&&(e=A),b(t.querySelectorAll("symbol")).forEach((function(t){b(t.querySelectorAll(e)).forEach((function(e){t.parentNode.insertBefore(e,t)}))})),t};function C(t,e){var s=b(t).reduce((function(t,s){if(!s.attributes)return t;var i=b(s.attributes),r=e?i.filter(e):i;return t.concat(r)}),[]);return s}var k=r.xlink.uri,N="xlink:href",I=/[{}|\\\^\[\]`"<>]/g;function O(t){return t.replace(I,(function(t){return"%"+t[0].charCodeAt(0).toString(16).toUpperCase()}))}function D(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function M(t,e,s){return b(t).forEach((function(t){var i=t.getAttribute(N);if(i&&0===i.indexOf(e)){var r=i.replace(e,s);t.setAttributeNS(k,N,r)}})),t}var L,_=["clipPath","colorProfile","src","cursor","fill","filter","marker","markerStart","markerMid","markerEnd","mask","stroke","style"],R=_.map((function(t){return"["+t+"]"})).join(","),j=function(t,e,s,i){var r=O(s),n=O(i),a=t.querySelectorAll(R),o=C(a,(function(t){var e=t.localName,s=t.value;return-1!==_.indexOf(e)&&-1!==s.indexOf("url("+r)}));o.forEach((function(t){return t.value=t.value.replace(new RegExp(D(r),"g"),n)})),M(e,r,n)},F={MOUNT:"mount",SYMBOL_MOUNT:"symbol_mount"},B=function(t){function e(e){var r=this;void 0===e&&(e={}),t.call(this,s(x,e));var n=i();this._emitter=n,this.node=null;var a=this,o=a.config;if(o.autoConfigure&&this._autoConfigure(e),o.syncUrlsWithBaseTag){var c=document.getElementsByTagName("base")[0].getAttribute("href");n.on(F.MOUNT,(function(){return r.updateUrls("#",c)}))}var h=this._handleLocationChange.bind(this);this._handleLocationChange=h,o.listenLocationChangeEvent&&window.addEventListener(o.locationChangeEvent,h),o.locationChangeAngularEmitter&&E(o.locationChangeEvent),n.on(F.MOUNT,(function(t){o.moveGradientsOutsideSymbol&&S(t)})),n.on(F.SYMBOL_MOUNT,(function(t){o.moveGradientsOutsideSymbol&&S(t.parentNode),(v.isIE()||v.isEdge())&&P(t)}))}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={isMounted:{}};return r.isMounted.get=function(){return!!this.node},e.prototype._autoConfigure=function(t){var e=this,s=e.config;"undefined"===typeof t.syncUrlsWithBaseTag&&(s.syncUrlsWithBaseTag="undefined"!==typeof document.getElementsByTagName("base")[0]),"undefined"===typeof t.locationChangeAngularEmitter&&(s.locationChangeAngularEmitter="undefined"!==typeof window.angular),"undefined"===typeof t.moveGradientsOutsideSymbol&&(s.moveGradientsOutsideSymbol=v.isFirefox())},e.prototype._handleLocationChange=function(t){var e=t.detail,s=e.oldUrl,i=e.newUrl;this.updateUrls(s,i)},e.prototype.add=function(e){var s=this,i=t.prototype.add.call(this,e);return this.isMounted&&i&&(e.mount(s.node),this._emitter.emit(F.SYMBOL_MOUNT,e.node)),i},e.prototype.attach=function(t){var e=this,s=this;if(s.isMounted)return s.node;var i="string"===typeof t?document.querySelector(t):t;return s.node=i,this.symbols.forEach((function(t){t.mount(s.node),e._emitter.emit(F.SYMBOL_MOUNT,t.node)})),b(i.querySelectorAll("symbol")).forEach((function(t){var e=g.createFromExistingNode(t);e.node=t,s.add(e)})),this._emitter.emit(F.MOUNT,i),i},e.prototype.destroy=function(){var t=this,e=t.config,s=t.symbols,i=t._emitter;s.forEach((function(t){return t.destroy()})),i.off("*"),window.removeEventListener(e.locationChangeEvent,this._handleLocationChange),this.isMounted&&this.unmount()},e.prototype.mount=function(t,e){void 0===t&&(t=this.config.mountTo),void 0===e&&(e=!1);var s=this;if(s.isMounted)return s.node;var i="string"===typeof t?document.querySelector(t):t,r=s.render();return this.node=r,e&&i.childNodes[0]?i.insertBefore(r,i.childNodes[0]):i.appendChild(r),this._emitter.emit(F.MOUNT,r),r},e.prototype.render=function(){return y(this.stringify())},e.prototype.unmount=function(){this.node.parentNode.removeChild(this.node)},e.prototype.updateUrls=function(t,e){if(!this.isMounted)return!1;var s=document.querySelectorAll(this.config.usagesToUpdate);return j(this.node,s,T(t)+"#",T(e)+"#"),!0},Object.defineProperties(e.prototype,r),e}(f),U=t((function(t){ +/*! + * domready (c) Dustin Diaz 2014 - License MIT + */ +!function(e,s){t.exports=s()}(0,(function(){var t,e=[],s=document,i=s.documentElement.doScroll,r="DOMContentLoaded",n=(i?/^loaded|^c/:/^loaded|^i|^c/).test(s.readyState);return n||s.addEventListener(r,t=function(){s.removeEventListener(r,t),n=1;while(t=e.shift())t()}),function(t){n?setTimeout(t,0):e.push(t)}}))})),q="__SVG_SPRITE_NODE__",V="__SVG_SPRITE__",H=!!window[V];H?L=window[V]:(L=new B({attrs:{id:q}}),window[V]=L);var z=function(){var t=document.getElementById(q);t?L.attach(t):L.mount(document.body,!0)};document.body?z():U(z);var W=L;return W}))}).call(this,s("c8ba"))},"21a6":function(t,e,s){(function(s){var i,r,n;(function(s,a){r=[],i=a,n="function"===typeof i?i.apply(e,r):i,void 0===n||(t.exports=n)})(0,(function(){"use strict";function e(t,e){return"undefined"==typeof e?e={autoBom:!1}:"object"!=typeof e&&(console.warn("Deprecated: Expected third argument to be a object"),e={autoBom:!e}),e.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(t.type)?new Blob(["\ufeff",t],{type:t.type}):t}function i(t,e,s){var i=new XMLHttpRequest;i.open("GET",t),i.responseType="blob",i.onload=function(){o(i.response,e,s)},i.onerror=function(){console.error("could not download file")},i.send()}function r(t){var e=new XMLHttpRequest;e.open("HEAD",t,!1);try{e.send()}catch(t){}return 200<=e.status&&299>=e.status}function n(t){try{t.dispatchEvent(new MouseEvent("click"))}catch(i){var e=document.createEvent("MouseEvents");e.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),t.dispatchEvent(e)}}var a="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof s&&s.global===s?s:void 0,o=a.saveAs||("object"!=typeof window||window!==a?function(){}:"download"in HTMLAnchorElement.prototype?function(t,e,s){var o=a.URL||a.webkitURL,c=document.createElement("a");e=e||t.name||"download",c.download=e,c.rel="noopener","string"==typeof t?(c.href=t,c.origin===location.origin?n(c):r(c.href)?i(t,e,s):n(c,c.target="_blank")):(c.href=o.createObjectURL(t),setTimeout((function(){o.revokeObjectURL(c.href)}),4e4),setTimeout((function(){n(c)}),0))}:"msSaveOrOpenBlob"in navigator?function(t,s,a){if(s=s||t.name||"download","string"!=typeof t)navigator.msSaveOrOpenBlob(e(t,a),s);else if(r(t))i(t,s,a);else{var o=document.createElement("a");o.href=t,o.target="_blank",setTimeout((function(){n(o)}))}}:function(t,e,s,r){if(r=r||open("","_blank"),r&&(r.document.title=r.document.body.innerText="downloading..."),"string"==typeof t)return i(t,e,s);var n="application/octet-stream"===t.type,o=/constructor/i.test(a.HTMLElement)||a.safari,c=/CriOS\/[\d]+/.test(navigator.userAgent);if((c||n&&o)&&"object"==typeof FileReader){var h=new FileReader;h.onloadend=function(){var t=h.result;t=c?t:t.replace(/^data:[^;]*;/,"data:attachment/file;"),r?r.location.href=t:location=t,r=null},h.readAsDataURL(t)}else{var l=a.URL||a.webkitURL,p=l.createObjectURL(t);r?r.location=p:location.href=p,r=null,setTimeout((function(){l.revokeObjectURL(p)}),4e4)}});a.saveAs=o.saveAs=o,t.exports=o}))}).call(this,s("c8ba"))},2266:function(t,e,s){var i=s("825a"),r=s("e95a"),n=s("50c4"),a=s("0366"),o=s("35a1"),c=s("9bdd"),h=function(t,e){this.stopped=t,this.result=e},l=t.exports=function(t,e,s,l,p){var u,d,f,m,y,g,x,b=a(e,s,l?2:1);if(p)u=t;else{if(d=o(t),"function"!=typeof d)throw TypeError("Target is not iterable");if(r(d)){for(f=0,m=n(t.length);m>f;f++)if(y=l?b(i(x=t[f])[0],x[1]):b(t[f]),y&&y instanceof h)return y;return new h(!1)}u=d.call(t)}g=u.next;while(!(x=g.call(u)).done)if(y=c(u,b,x.value,l),"object"==typeof y&&y&&y instanceof h)return y;return new h(!1)};l.stop=function(t){return new h(!0,t)}},"23cb":function(t,e,s){var i=s("a691"),r=Math.max,n=Math.min;t.exports=function(t,e){var s=i(t);return s<0?r(s+e,0):n(s,e)}},"23e7":function(t,e,s){var i=s("da84"),r=s("06cf").f,n=s("9112"),a=s("6eeb"),o=s("ce4e"),c=s("e893"),h=s("94ca");t.exports=function(t,e){var s,l,p,u,d,f,m=t.target,y=t.global,g=t.stat;if(l=y?i:g?i[m]||o(m,{}):(i[m]||{}).prototype,l)for(p in e){if(d=e[p],t.noTargetGet?(f=r(l,p),u=f&&f.value):u=l[p],s=h(y?p:m+(g?".":"#")+p,t.forced),!s&&void 0!==u){if(typeof d===typeof u)continue;c(d,u)}(t.sham||u&&u.sham)&&n(d,"sham",!0),a(l,p,d,t)}}},"241c":function(t,e,s){var i=s("ca84"),r=s("7839"),n=r.concat("length","prototype");e.f=Object.getOwnPropertyNames||function(t){return i(t,n)}},"25f0":function(t,e,s){"use strict";var i=s("6eeb"),r=s("825a"),n=s("d039"),a=s("ad6d"),o="toString",c=RegExp.prototype,h=c[o],l=n((function(){return"/a/b"!=h.call({source:"a",flags:"b"})})),p=h.name!=o;(l||p)&&i(RegExp.prototype,o,(function(){var t=r(this),e=String(t.source),s=t.flags,i=String(void 0===s&&t instanceof RegExp&&!("flags"in c)?a.call(t):s);return"/"+e+"/"+i}),{unsafe:!0})},2626:function(t,e,s){"use strict";var i=s("d066"),r=s("9bf2"),n=s("b622"),a=s("83ab"),o=n("species");t.exports=function(t){var e=i(t),s=r.f;a&&e&&!e[o]&&s(e,o,{configurable:!0,get:function(){return this}})}},2877:function(t,e,s){"use strict";function i(t,e,s,i,r,n,a,o){var c,h="function"===typeof t?t.options:t;if(e&&(h.render=e,h.staticRenderFns=s,h._compiled=!0),i&&(h.functional=!0),n&&(h._scopeId="data-v-"+n),a?(c=function(t){t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,t||"undefined"===typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),r&&r.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(a)},h._ssrRegister=c):r&&(c=o?function(){r.call(this,(h.functional?this.parent:this).$root.$options.shadowRoot)}:r),c)if(h.functional){h._injectStyles=c;var l=h.render;h.render=function(t,e){return c.call(e),l(t,e)}}else{var p=h.beforeCreate;h.beforeCreate=p?[].concat(p,c):[c]}return{exports:t,options:h}}s.d(e,"a",(function(){return i}))},"28a0":function(t,e){"function"===typeof Object.create?t.exports=function(t,e){t.super_=e,t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}})}:t.exports=function(t,e){t.super_=e;var s=function(){};s.prototype=e.prototype,t.prototype=new s,t.prototype.constructor=t}},"2cf4":function(t,e,s){var i,r,n,a=s("da84"),o=s("d039"),c=s("c6b6"),h=s("0366"),l=s("1be4"),p=s("cc12"),u=s("1cdc"),d=a.location,f=a.setImmediate,m=a.clearImmediate,y=a.process,g=a.MessageChannel,x=a.Dispatch,b=0,v={},w="onreadystatechange",P=function(t){if(v.hasOwnProperty(t)){var e=v[t];delete v[t],e()}},T=function(t){return function(){P(t)}},E=function(t){P(t.data)},A=function(t){a.postMessage(t+"",d.protocol+"//"+d.host)};f&&m||(f=function(t){var e=[],s=1;while(arguments.length>s)e.push(arguments[s++]);return v[++b]=function(){("function"==typeof t?t:Function(t)).apply(void 0,e)},i(b),b},m=function(t){delete v[t]},"process"==c(y)?i=function(t){y.nextTick(T(t))}:x&&x.now?i=function(t){x.now(T(t))}:g&&!u?(r=new g,n=r.port2,r.port1.onmessage=E,i=h(n.postMessage,n,1)):!a.addEventListener||"function"!=typeof postMessage||a.importScripts||o(A)||"file:"===d.protocol?i=w in p("script")?function(t){l.appendChild(p("script"))[w]=function(){l.removeChild(this),P(t)}}:function(t){setTimeout(T(t),0)}:(i=A,a.addEventListener("message",E,!1))),t.exports={set:f,clear:m}},"2d00":function(t,e,s){var i,r,n=s("da84"),a=s("342f"),o=n.process,c=o&&o.versions,h=c&&c.v8;h?(i=h.split("."),r=i[0]+i[1]):a&&(i=a.match(/Edge\/(\d+)/),(!i||i[1]>=74)&&(i=a.match(/Chrome\/(\d+)/),i&&(r=i[1]))),t.exports=r&&+r},3022:function(t,e,s){(function(t){var i=Object.getOwnPropertyDescriptors||function(t){for(var e=Object.keys(t),s={},i=0;i=n)return t;switch(t){case"%s":return String(i[s++]);case"%d":return Number(i[s++]);case"%j":try{return JSON.stringify(i[s++])}catch(e){return"[Circular]"}default:return t}})),c=i[s];s=3&&(i.depth=arguments[2]),arguments.length>=4&&(i.colors=arguments[3]),x(s)?i.showHidden=s:s&&e._extend(i,s),E(i.showHidden)&&(i.showHidden=!1),E(i.depth)&&(i.depth=2),E(i.colors)&&(i.colors=!1),E(i.customInspect)&&(i.customInspect=!0),i.colors&&(i.stylize=c),p(i,t,i.depth)}function c(t,e){var s=o.styles[e];return s?"["+o.colors[s][0]+"m"+t+"["+o.colors[s][1]+"m":t}function h(t,e){return t}function l(t){var e={};return t.forEach((function(t,s){e[t]=!0})),e}function p(t,s,i){if(t.customInspect&&s&&N(s.inspect)&&s.inspect!==e.inspect&&(!s.constructor||s.constructor.prototype!==s)){var r=s.inspect(i,t);return P(r)||(r=p(t,r,i)),r}var n=u(t,s);if(n)return n;var a=Object.keys(s),o=l(a);if(t.showHidden&&(a=Object.getOwnPropertyNames(s)),k(s)&&(a.indexOf("message")>=0||a.indexOf("description")>=0))return d(s);if(0===a.length){if(N(s)){var c=s.name?": "+s.name:"";return t.stylize("[Function"+c+"]","special")}if(A(s))return t.stylize(RegExp.prototype.toString.call(s),"regexp");if(C(s))return t.stylize(Date.prototype.toString.call(s),"date");if(k(s))return d(s)}var h,x="",b=!1,v=["{","}"];if(g(s)&&(b=!0,v=["[","]"]),N(s)){var w=s.name?": "+s.name:"";x=" [Function"+w+"]"}return A(s)&&(x=" "+RegExp.prototype.toString.call(s)),C(s)&&(x=" "+Date.prototype.toUTCString.call(s)),k(s)&&(x=" "+d(s)),0!==a.length||b&&0!=s.length?i<0?A(s)?t.stylize(RegExp.prototype.toString.call(s),"regexp"):t.stylize("[Object]","special"):(t.seen.push(s),h=b?f(t,s,i,o,a):a.map((function(e){return m(t,s,i,o,e,b)})),t.seen.pop(),y(h,x,v)):v[0]+x+v[1]}function u(t,e){if(E(e))return t.stylize("undefined","undefined");if(P(e)){var s="'"+JSON.stringify(e).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return t.stylize(s,"string")}return w(e)?t.stylize(""+e,"number"):x(e)?t.stylize(""+e,"boolean"):b(e)?t.stylize("null","null"):void 0}function d(t){return"["+Error.prototype.toString.call(t)+"]"}function f(t,e,s,i,r){for(var n=[],a=0,o=e.length;a-1&&(o=n?o.split("\n").map((function(t){return" "+t})).join("\n").substr(2):"\n"+o.split("\n").map((function(t){return" "+t})).join("\n"))):o=t.stylize("[Circular]","special")),E(a)){if(n&&r.match(/^\d+$/))return o;a=JSON.stringify(""+r),a.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(a=a.substr(1,a.length-2),a=t.stylize(a,"name")):(a=a.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),a=t.stylize(a,"string"))}return a+": "+o}function y(t,e,s){var i=t.reduce((function(t,e){return e.indexOf("\n")>=0&&0,t+e.replace(/\u001b\[\d\d?m/g,"").length+1}),0);return i>60?s[0]+(""===e?"":e+"\n ")+" "+t.join(",\n ")+" "+s[1]:s[0]+e+" "+t.join(", ")+" "+s[1]}function g(t){return Array.isArray(t)}function x(t){return"boolean"===typeof t}function b(t){return null===t}function v(t){return null==t}function w(t){return"number"===typeof t}function P(t){return"string"===typeof t}function T(t){return"symbol"===typeof t}function E(t){return void 0===t}function A(t){return S(t)&&"[object RegExp]"===O(t)}function S(t){return"object"===typeof t&&null!==t}function C(t){return S(t)&&"[object Date]"===O(t)}function k(t){return S(t)&&("[object Error]"===O(t)||t instanceof Error)}function N(t){return"function"===typeof t}function I(t){return null===t||"boolean"===typeof t||"number"===typeof t||"string"===typeof t||"symbol"===typeof t||"undefined"===typeof t}function O(t){return Object.prototype.toString.call(t)}function D(t){return t<10?"0"+t.toString(10):t.toString(10)}e.debuglog=function(s){if(E(n)&&(n=Object({NODE_ENV:"production",BASE_URL:"/form-generator/"}).NODE_DEBUG||""),s=s.toUpperCase(),!a[s])if(new RegExp("\\b"+s+"\\b","i").test(n)){var i=t.pid;a[s]=function(){var t=e.format.apply(e,arguments);console.error("%s %d: %s",s,i,t)}}else a[s]=function(){};return a[s]},e.inspect=o,o.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},o.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},e.isArray=g,e.isBoolean=x,e.isNull=b,e.isNullOrUndefined=v,e.isNumber=w,e.isString=P,e.isSymbol=T,e.isUndefined=E,e.isRegExp=A,e.isObject=S,e.isDate=C,e.isError=k,e.isFunction=N,e.isPrimitive=I,e.isBuffer=s("d60a");var M=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function L(){var t=new Date,e=[D(t.getHours()),D(t.getMinutes()),D(t.getSeconds())].join(":");return[t.getDate(),M[t.getMonth()],e].join(" ")}function _(t,e){return Object.prototype.hasOwnProperty.call(t,e)}e.log=function(){console.log("%s - %s",L(),e.format.apply(e,arguments))},e.inherits=s("28a0"),e._extend=function(t,e){if(!e||!S(e))return t;var s=Object.keys(e),i=s.length;while(i--)t[s[i]]=e[s[i]];return t};var R="undefined"!==typeof Symbol?Symbol("util.promisify.custom"):void 0;function j(t,e){if(!t){var s=new Error("Promise was rejected with a falsy value");s.reason=t,t=s}return e(t)}function F(e){if("function"!==typeof e)throw new TypeError('The "original" argument must be of type Function');function s(){for(var s=[],i=0;i=h?t?"":void 0:(n=o.charCodeAt(c),n<55296||n>56319||c+1===h||(a=o.charCodeAt(c+1))<56320||a>57343?t?o.charAt(c):n:t?o.slice(c,c+2):a-56320+(n-55296<<10)+65536)}}},"0390":function(t,e,s){"use strict";var i=s("02f4")(!0);t.exports=function(t,e,s){return e+(s?i(t,e).length:1)}},"0bfb":function(t,e,s){"use strict";var i=s("cb7c");t.exports=function(){var t=i(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},"0d58":function(t,e,s){var i=s("ce10"),r=s("e11e");t.exports=Object.keys||function(t){return i(t,r)}},1495:function(t,e,s){var i=s("86cc"),r=s("cb7c"),n=s("0d58");t.exports=s("9e1e")?Object.defineProperties:function(t,e){r(t);var s,a=n(e),o=a.length,c=0;while(o>c)i.f(t,s=a[c++],e[s]);return t}},"214f":function(t,e,s){"use strict";s("b0c5");var i=s("2aba"),r=s("32e9"),n=s("79e5"),a=s("be13"),o=s("2b4c"),c=s("520a"),h=o("species"),l=!n((function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$")})),p=function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var s="ab".split(t);return 2===s.length&&"a"===s[0]&&"b"===s[1]}();t.exports=function(t,e,s){var u=o(t),d=!n((function(){var e={};return e[u]=function(){return 7},7!=""[t](e)})),f=d?!n((function(){var e=!1,s=/a/;return s.exec=function(){return e=!0,null},"split"===t&&(s.constructor={},s.constructor[h]=function(){return s}),s[u](""),!e})):void 0;if(!d||!f||"replace"===t&&!l||"split"===t&&!p){var m=/./[u],y=s(a,u,""[t],(function(t,e,s,i,r){return e.exec===c?d&&!r?{done:!0,value:m.call(e,s,i)}:{done:!0,value:t.call(s,e,i)}:{done:!1}})),g=y[0],x=y[1];i(String.prototype,t,g),r(RegExp.prototype,u,2==e?function(t,e){return x.call(t,this,e)}:function(t){return x.call(t,this)})}}},"230e":function(t,e,s){var i=s("d3f4"),r=s("7726").document,n=i(r)&&i(r.createElement);t.exports=function(t){return n?r.createElement(t):{}}},"23c6":function(t,e,s){var i=s("2d95"),r=s("2b4c")("toStringTag"),n="Arguments"==i(function(){return arguments}()),a=function(t,e){try{return t[e]}catch(s){}};t.exports=function(t){var e,s,o;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(s=a(e=Object(t),r))?s:n?i(e):"Object"==(o=i(e))&&"function"==typeof e.callee?"Arguments":o}},2621:function(t,e){e.f=Object.getOwnPropertySymbols},"2aba":function(t,e,s){var i=s("7726"),r=s("32e9"),n=s("69a8"),a=s("ca5a")("src"),o=s("fa5b"),c="toString",h=(""+o).split(c);s("8378").inspectSource=function(t){return o.call(t)},(t.exports=function(t,e,s,o){var c="function"==typeof s;c&&(n(s,"name")||r(s,"name",e)),t[e]!==s&&(c&&(n(s,a)||r(s,a,t[e]?""+t[e]:h.join(String(e)))),t===i?t[e]=s:o?t[e]?t[e]=s:r(t,e,s):(delete t[e],r(t,e,s)))})(Function.prototype,c,(function(){return"function"==typeof this&&this[a]||o.call(this)}))},"2aeb":function(t,e,s){var i=s("cb7c"),r=s("1495"),n=s("e11e"),a=s("613b")("IE_PROTO"),o=function(){},c="prototype",h=function(){var t,e=s("230e")("iframe"),i=n.length,r="<",a=">";e.style.display="none",s("fab2").appendChild(e),e.src="javascript:",t=e.contentWindow.document,t.open(),t.write(r+"script"+a+"document.F=Object"+r+"/script"+a),t.close(),h=t.F;while(i--)delete h[c][n[i]];return h()};t.exports=Object.create||function(t,e){var s;return null!==t?(o[c]=i(t),s=new o,o[c]=null,s[a]=t):s=h(),void 0===e?s:r(s,e)}},"2b4c":function(t,e,s){var i=s("5537")("wks"),r=s("ca5a"),n=s("7726").Symbol,a="function"==typeof n,o=t.exports=function(t){return i[t]||(i[t]=a&&n[t]||(a?n:r)("Symbol."+t))};o.store=i},"2d00":function(t,e){t.exports=!1},"2d95":function(t,e){var s={}.toString;t.exports=function(t){return s.call(t).slice(8,-1)}},"2fdb":function(t,e,s){"use strict";var i=s("5ca1"),r=s("d2c8"),n="includes";i(i.P+i.F*s("5147")(n),"String",{includes:function(t){return!!~r(this,t,n).indexOf(t,arguments.length>1?arguments[1]:void 0)}})},"32e9":function(t,e,s){var i=s("86cc"),r=s("4630");t.exports=s("9e1e")?function(t,e,s){return i.f(t,e,r(1,s))}:function(t,e,s){return t[e]=s,t}},"38fd":function(t,e,s){var i=s("69a8"),r=s("4bf8"),n=s("613b")("IE_PROTO"),a=Object.prototype;t.exports=Object.getPrototypeOf||function(t){return t=r(t),i(t,n)?t[n]:"function"==typeof t.constructor&&t instanceof t.constructor?t.constructor.prototype:t instanceof Object?a:null}},"41a0":function(t,e,s){"use strict";var i=s("2aeb"),r=s("4630"),n=s("7f20"),a={};s("32e9")(a,s("2b4c")("iterator"),(function(){return this})),t.exports=function(t,e,s){t.prototype=i(a,{next:r(1,s)}),n(t,e+" Iterator")}},"456d":function(t,e,s){var i=s("4bf8"),r=s("0d58");s("5eda")("keys",(function(){return function(t){return r(i(t))}}))},4588:function(t,e){var s=Math.ceil,i=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?i:s)(t)}},4630:function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},"4bf8":function(t,e,s){var i=s("be13");t.exports=function(t){return Object(i(t))}},5147:function(t,e,s){var i=s("2b4c")("match");t.exports=function(t){var e=/./;try{"/./"[t](e)}catch(s){try{return e[i]=!1,!"/./"[t](e)}catch(r){}}return!0}},"520a":function(t,e,s){"use strict";var i=s("0bfb"),r=RegExp.prototype.exec,n=String.prototype.replace,a=r,o="lastIndex",c=function(){var t=/a/,e=/b*/g;return r.call(t,"a"),r.call(e,"a"),0!==t[o]||0!==e[o]}(),h=void 0!==/()??/.exec("")[1],l=c||h;l&&(a=function(t){var e,s,a,l,p=this;return h&&(s=new RegExp("^"+p.source+"$(?!\\s)",i.call(p))),c&&(e=p[o]),a=r.call(p,t),c&&a&&(p[o]=p.global?a.index+a[0].length:e),h&&a&&a.length>1&&n.call(a[0],s,(function(){for(l=1;l1?arguments[1]:void 0)}}),s("9c6c")("includes")},6821:function(t,e,s){var i=s("626a"),r=s("be13");t.exports=function(t){return i(r(t))}},"69a8":function(t,e){var s={}.hasOwnProperty;t.exports=function(t,e){return s.call(t,e)}},"6a99":function(t,e,s){var i=s("d3f4");t.exports=function(t,e){if(!i(t))return t;var s,r;if(e&&"function"==typeof(s=t.toString)&&!i(r=s.call(t)))return r;if("function"==typeof(s=t.valueOf)&&!i(r=s.call(t)))return r;if(!e&&"function"==typeof(s=t.toString)&&!i(r=s.call(t)))return r;throw TypeError("Can't convert object to primitive value")}},7333:function(t,e,s){"use strict";var i=s("9e1e"),r=s("0d58"),n=s("2621"),a=s("52a7"),o=s("4bf8"),c=s("626a"),h=Object.assign;t.exports=!h||s("79e5")((function(){var t={},e={},s=Symbol(),i="abcdefghijklmnopqrst";return t[s]=7,i.split("").forEach((function(t){e[t]=t})),7!=h({},t)[s]||Object.keys(h({},e)).join("")!=i}))?function(t,e){var s=o(t),h=arguments.length,l=1,p=n.f,u=a.f;while(h>l){var d,f=c(arguments[l++]),m=p?r(f).concat(p(f)):r(f),y=m.length,g=0;while(y>g)d=m[g++],i&&!u.call(f,d)||(s[d]=f[d])}return s}:h},7726:function(t,e){var s=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=s)},"77f1":function(t,e,s){var i=s("4588"),r=Math.max,n=Math.min;t.exports=function(t,e){return t=i(t),t<0?r(t+e,0):n(t,e)}},"79e5":function(t,e){t.exports=function(t){try{return!!t()}catch(e){return!0}}},"7f20":function(t,e,s){var i=s("86cc").f,r=s("69a8"),n=s("2b4c")("toStringTag");t.exports=function(t,e,s){t&&!r(t=s?t:t.prototype,n)&&i(t,n,{configurable:!0,value:e})}},8378:function(t,e){var s=t.exports={version:"2.6.11"};"number"==typeof __e&&(__e=s)},"84f2":function(t,e){t.exports={}},"86cc":function(t,e,s){var i=s("cb7c"),r=s("c69a"),n=s("6a99"),a=Object.defineProperty;e.f=s("9e1e")?Object.defineProperty:function(t,e,s){if(i(t),e=n(e,!0),i(s),r)try{return a(t,e,s)}catch(o){}if("get"in s||"set"in s)throw TypeError("Accessors not supported!");return"value"in s&&(t[e]=s.value),t}},"9b43":function(t,e,s){var i=s("d8e8");t.exports=function(t,e,s){if(i(t),void 0===e)return t;switch(s){case 1:return function(s){return t.call(e,s)};case 2:return function(s,i){return t.call(e,s,i)};case 3:return function(s,i,r){return t.call(e,s,i,r)}}return function(){return t.apply(e,arguments)}}},"9c6c":function(t,e,s){var i=s("2b4c")("unscopables"),r=Array.prototype;void 0==r[i]&&s("32e9")(r,i,{}),t.exports=function(t){r[i][t]=!0}},"9def":function(t,e,s){var i=s("4588"),r=Math.min;t.exports=function(t){return t>0?r(i(t),9007199254740991):0}},"9e1e":function(t,e,s){t.exports=!s("79e5")((function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a}))},a352:function(t,e){t.exports=s("aa47")},a481:function(t,e,s){"use strict";var i=s("cb7c"),r=s("4bf8"),n=s("9def"),a=s("4588"),o=s("0390"),c=s("5f1b"),h=Math.max,l=Math.min,p=Math.floor,u=/\$([$&`']|\d\d?|<[^>]*>)/g,d=/\$([$&`']|\d\d?)/g,f=function(t){return void 0===t?t:String(t)};s("214f")("replace",2,(function(t,e,s,m){return[function(i,r){var n=t(this),a=void 0==i?void 0:i[e];return void 0!==a?a.call(i,n,r):s.call(String(n),i,r)},function(t,e){var r=m(s,t,this,e);if(r.done)return r.value;var p=i(t),u=String(this),d="function"===typeof e;d||(e=String(e));var g=p.global;if(g){var x=p.unicode;p.lastIndex=0}var b=[];while(1){var v=c(p,u);if(null===v)break;if(b.push(v),!g)break;var w=String(v[0]);""===w&&(p.lastIndex=o(u,n(p.lastIndex),x))}for(var P="",T=0,E=0;E=T&&(P+=u.slice(T,S)+O,T=S+A.length)}return P+u.slice(T)}];function y(t,e,i,n,a,o){var c=i+t.length,h=n.length,l=d;return void 0!==a&&(a=r(a),l=u),s.call(o,l,(function(s,r){var o;switch(r.charAt(0)){case"$":return"$";case"&":return t;case"`":return e.slice(0,i);case"'":return e.slice(c);case"<":o=a[r.slice(1,-1)];break;default:var l=+r;if(0===l)return s;if(l>h){var u=p(l/10);return 0===u?s:u<=h?void 0===n[u-1]?r.charAt(1):n[u-1]+r.charAt(1):s}o=n[l-1]}return void 0===o?"":o}))}}))},aae3:function(t,e,s){var i=s("d3f4"),r=s("2d95"),n=s("2b4c")("match");t.exports=function(t){var e;return i(t)&&(void 0!==(e=t[n])?!!e:"RegExp"==r(t))}},ac6a:function(t,e,s){for(var i=s("cadf"),r=s("0d58"),n=s("2aba"),a=s("7726"),o=s("32e9"),c=s("84f2"),h=s("2b4c"),l=h("iterator"),p=h("toStringTag"),u=c.Array,d={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},f=r(d),m=0;ml)if(o=c[l++],o!=o)return!0}else for(;h>l;l++)if((t||l in c)&&c[l]===s)return t||l||0;return!t&&-1}}},c649:function(t,e,s){"use strict";(function(t){s.d(e,"c",(function(){return h})),s.d(e,"a",(function(){return o})),s.d(e,"b",(function(){return r})),s.d(e,"d",(function(){return c}));s("a481");function i(){return"undefined"!==typeof window?window.console:t.console}var r=i();function n(t){var e=Object.create(null);return function(s){var i=e[s];return i||(e[s]=t(s))}}var a=/-(\w)/g,o=n((function(t){return t.replace(a,(function(t,e){return e?e.toUpperCase():""}))}));function c(t){null!==t.parentElement&&t.parentElement.removeChild(t)}function h(t,e,s){var i=0===s?t.children[0]:t.children[s-1].nextSibling;t.insertBefore(e,i)}}).call(this,s("c8ba"))},c69a:function(t,e,s){t.exports=!s("9e1e")&&!s("79e5")((function(){return 7!=Object.defineProperty(s("230e")("div"),"a",{get:function(){return 7}}).a}))},c8ba:function(t,e){var s;s=function(){return this}();try{s=s||new Function("return this")()}catch(i){"object"===typeof window&&(s=window)}t.exports=s},ca5a:function(t,e){var s=0,i=Math.random();t.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++s+i).toString(36))}},cadf:function(t,e,s){"use strict";var i=s("9c6c"),r=s("d53b"),n=s("84f2"),a=s("6821");t.exports=s("01f9")(Array,"Array",(function(t,e){this._t=a(t),this._i=0,this._k=e}),(function(){var t=this._t,e=this._k,s=this._i++;return!t||s>=t.length?(this._t=void 0,r(1)):r(0,"keys"==e?s:"values"==e?t[s]:[s,t[s]])}),"values"),n.Arguments=n.Array,i("keys"),i("values"),i("entries")},cb7c:function(t,e,s){var i=s("d3f4");t.exports=function(t){if(!i(t))throw TypeError(t+" is not an object!");return t}},ce10:function(t,e,s){var i=s("69a8"),r=s("6821"),n=s("c366")(!1),a=s("613b")("IE_PROTO");t.exports=function(t,e){var s,o=r(t),c=0,h=[];for(s in o)s!=a&&i(o,s)&&h.push(s);while(e.length>c)i(o,s=e[c++])&&(~n(h,s)||h.push(s));return h}},d2c8:function(t,e,s){var i=s("aae3"),r=s("be13");t.exports=function(t,e,s){if(i(e))throw TypeError("String#"+s+" doesn't accept regex!");return String(r(t))}},d3f4:function(t,e){t.exports=function(t){return"object"===typeof t?null!==t:"function"===typeof t}},d53b:function(t,e){t.exports=function(t,e){return{value:e,done:!!t}}},d8e8:function(t,e){t.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},e11e:function(t,e){t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},f559:function(t,e,s){"use strict";var i=s("5ca1"),r=s("9def"),n=s("d2c8"),a="startsWith",o=""[a];i(i.P+i.F*s("5147")(a),"String",{startsWith:function(t){var e=n(this,t,a),s=r(Math.min(arguments.length>1?arguments[1]:void 0,e.length)),i=String(t);return o?o.call(e,i,s):e.slice(s,s+i.length)===i}})},f6fd:function(t,e){(function(t){var e="currentScript",s=t.getElementsByTagName("script");e in t||Object.defineProperty(t,e,{get:function(){try{throw new Error}catch(i){var t,e=(/.*at [^\(]*\((.*):.+:.+\)$/gi.exec(i.stack)||[!1])[1];for(t in s)if(s[t].src==e||"interactive"==s[t].readyState)return s[t];return null}}})})(document)},f751:function(t,e,s){var i=s("5ca1");i(i.S+i.F,"Object",{assign:s("7333")})},fa5b:function(t,e,s){t.exports=s("5537")("native-function-to-string",Function.toString)},fab2:function(t,e,s){var i=s("7726").document;t.exports=i&&i.documentElement},fb15:function(t,e,s){"use strict";var i;(s.r(e),"undefined"!==typeof window)&&(s("f6fd"),(i=window.document.currentScript)&&(i=i.src.match(/(.+\/)[^/]+\.js(\?.*)?$/))&&(s.p=i[1]));s("f751"),s("f559"),s("ac6a"),s("cadf"),s("456d");function r(t){if(Array.isArray(t))return t}function n(t,e){if("undefined"!==typeof Symbol&&Symbol.iterator in Object(t)){var s=[],i=!0,r=!1,n=void 0;try{for(var a,o=t[Symbol.iterator]();!(i=(a=o.next()).done);i=!0)if(s.push(a.value),e&&s.length===e)break}catch(c){r=!0,n=c}finally{try{i||null==o["return"]||o["return"]()}finally{if(r)throw n}}return s}}function a(t,e){(null==e||e>t.length)&&(e=t.length);for(var s=0,i=new Array(e);s=n?r.length:r.indexOf(t)}));return s?a.filter((function(t){return-1!==t})):a}function v(t,e){var s=this;this.$nextTick((function(){return s.$emit(t.toLowerCase(),e)}))}function w(t){var e=this;return function(s){null!==e.realList&&e["onDrag"+t](s),v.call(e,t,s)}}function P(t){return["transition-group","TransitionGroup"].includes(t)}function T(t){if(!t||1!==t.length)return!1;var e=h(t,1),s=e[0].componentOptions;return!!s&&P(s.tag)}function E(t,e,s){return t[s]||(e[s]?e[s]():void 0)}function A(t,e,s){var i=0,r=0,n=E(e,s,"header");n&&(i=n.length,t=t?[].concat(d(n),d(t)):d(n));var a=E(e,s,"footer");return a&&(r=a.length,t=t?[].concat(d(t),d(a)):d(a)),{children:t,headerOffset:i,footerOffset:r}}function S(t,e){var s=null,i=function(t,e){s=g(s,t,e)},r=Object.keys(t).filter((function(t){return"id"===t||t.startsWith("data-")})).reduce((function(e,s){return e[s]=t[s],e}),{});if(i("attrs",r),!e)return s;var n=e.on,a=e.props,o=e.attrs;return i("on",n),i("props",a),Object.assign(s.attrs,o),s}var C=["Start","Add","Remove","Update","End"],k=["Choose","Unchoose","Sort","Filter","Clone"],N=["Move"].concat(C,k).map((function(t){return"on"+t})),I=null,O={options:Object,list:{type:Array,required:!1,default:null},value:{type:Array,required:!1,default:null},noTransitionOnDrag:{type:Boolean,default:!1},clone:{type:Function,default:function(t){return t}},element:{type:String,default:"div"},tag:{type:String,default:null},move:{type:Function,default:null},componentData:{type:Object,required:!1,default:null}},D={name:"draggable",inheritAttrs:!1,props:O,data:function(){return{transitionMode:!1,noneFunctionalComponentMode:!1}},render:function(t){var e=this.$slots.default;this.transitionMode=T(e);var s=A(e,this.$slots,this.$scopedSlots),i=s.children,r=s.headerOffset,n=s.footerOffset;this.headerOffset=r,this.footerOffset=n;var a=S(this.$attrs,this.componentData);return t(this.getTag(),a,i)},created:function(){null!==this.list&&null!==this.value&&y["b"].error("Value and list props are mutually exclusive! Please set one or another."),"div"!==this.element&&y["b"].warn("Element props is deprecated please use tag props instead. See https://github.com/SortableJS/Vue.Draggable/blob/master/documentation/migrate.md#element-props"),void 0!==this.options&&y["b"].warn("Options props is deprecated, add sortable options directly as vue.draggable item, or use v-bind. See https://github.com/SortableJS/Vue.Draggable/blob/master/documentation/migrate.md#options-props")},mounted:function(){var t=this;if(this.noneFunctionalComponentMode=this.getTag().toLowerCase()!==this.$el.nodeName.toLowerCase()&&!this.getIsFunctional(),this.noneFunctionalComponentMode&&this.transitionMode)throw new Error("Transition-group inside component is not supported. Please alter tag value or remove transition-group. Current tag value: ".concat(this.getTag()));var e={};C.forEach((function(s){e["on"+s]=w.call(t,s)})),k.forEach((function(s){e["on"+s]=v.bind(t,s)}));var s=Object.keys(this.$attrs).reduce((function(e,s){return e[Object(y["a"])(s)]=t.$attrs[s],e}),{}),i=Object.assign({},this.options,s,e,{onMove:function(e,s){return t.onDragMove(e,s)}});!("draggable"in i)&&(i.draggable=">*"),this._sortable=new m.a(this.rootContainer,i),this.computeIndexes()},beforeDestroy:function(){void 0!==this._sortable&&this._sortable.destroy()},computed:{rootContainer:function(){return this.transitionMode?this.$el.children[0]:this.$el},realList:function(){return this.list?this.list:this.value}},watch:{options:{handler:function(t){this.updateOptions(t)},deep:!0},$attrs:{handler:function(t){this.updateOptions(t)},deep:!0},realList:function(){this.computeIndexes()}},methods:{getIsFunctional:function(){var t=this._vnode.fnOptions;return t&&t.functional},getTag:function(){return this.tag||this.element},updateOptions:function(t){for(var e in t){var s=Object(y["a"])(e);-1===N.indexOf(s)&&this._sortable.option(s,t[e])}},getChildrenNodes:function(){if(this.noneFunctionalComponentMode)return this.$children[0].$slots.default;var t=this.$slots.default;return this.transitionMode?t[0].child.$slots.default:t},computeIndexes:function(){var t=this;this.$nextTick((function(){t.visibleIndexes=b(t.getChildrenNodes(),t.rootContainer.children,t.transitionMode,t.footerOffset)}))},getUnderlyingVm:function(t){var e=x(this.getChildrenNodes()||[],t);if(-1===e)return null;var s=this.realList[e];return{index:e,element:s}},getUnderlyingPotencialDraggableComponent:function(t){var e=t.__vue__;return e&&e.$options&&P(e.$options._componentTag)?e.$parent:!("realList"in e)&&1===e.$children.length&&"realList"in e.$children[0]?e.$children[0]:e},emitChanges:function(t){var e=this;this.$nextTick((function(){e.$emit("change",t)}))},alterList:function(t){if(this.list)t(this.list);else{var e=d(this.value);t(e),this.$emit("input",e)}},spliceList:function(){var t=arguments,e=function(e){return e.splice.apply(e,d(t))};this.alterList(e)},updatePosition:function(t,e){var s=function(s){return s.splice(e,0,s.splice(t,1)[0])};this.alterList(s)},getRelatedContextFromMoveEvent:function(t){var e=t.to,s=t.related,i=this.getUnderlyingPotencialDraggableComponent(e);if(!i)return{component:i};var r=i.realList,n={list:r,component:i};if(e!==s&&r&&i.getUnderlyingVm){var a=i.getUnderlyingVm(s);if(a)return Object.assign(a,n)}return n},getVmIndex:function(t){var e=this.visibleIndexes,s=e.length;return t>s-1?s:e[t]},getComponent:function(){return this.$slots.default[0].componentInstance},resetTransitionData:function(t){if(this.noTransitionOnDrag&&this.transitionMode){var e=this.getChildrenNodes();e[t].data=null;var s=this.getComponent();s.children=[],s.kept=void 0}},onDragStart:function(t){this.context=this.getUnderlyingVm(t.item),t.item._underlying_vm_=this.clone(this.context.element),I=t.item},onDragAdd:function(t){var e=t.item._underlying_vm_;if(void 0!==e){Object(y["d"])(t.item);var s=this.getVmIndex(t.newIndex);this.spliceList(s,0,e),this.computeIndexes();var i={element:e,newIndex:s};this.emitChanges({added:i})}},onDragRemove:function(t){if(Object(y["c"])(this.rootContainer,t.item,t.oldIndex),"clone"!==t.pullMode){var e=this.context.index;this.spliceList(e,1);var s={element:this.context.element,oldIndex:e};this.resetTransitionData(e),this.emitChanges({removed:s})}else Object(y["d"])(t.clone)},onDragUpdate:function(t){Object(y["d"])(t.item),Object(y["c"])(t.from,t.item,t.oldIndex);var e=this.context.index,s=this.getVmIndex(t.newIndex);this.updatePosition(e,s);var i={element:this.context.element,oldIndex:e,newIndex:s};this.emitChanges({moved:i})},updateProperty:function(t,e){t.hasOwnProperty(e)&&(t[e]+=this.headerOffset)},computeFutureIndex:function(t,e){if(!t.element)return 0;var s=d(e.to.children).filter((function(t){return"none"!==t.style["display"]})),i=s.indexOf(e.related),r=t.component.getVmIndex(i),n=-1!==s.indexOf(I);return n||!e.willInsertAfter?r:r+1},onDragMove:function(t,e){var s=this.move;if(!s||!this.realList)return!0;var i=this.getRelatedContextFromMoveEvent(t),r=this.context,n=this.computeFutureIndex(i,t);Object.assign(r,{futureIndex:n});var a=Object.assign({},t,{relatedContext:i,draggedContext:r});return s(a,e)},onDragEnd:function(){this.computeIndexes(),I=null}}};"undefined"!==typeof window&&"Vue"in window&&window.Vue.component("draggable",D);var M=D;e["default"]=M}})["default"]},"342f":function(t,e,s){var i=s("d066");t.exports=i("navigator","userAgent")||""},"35a1":function(t,e,s){var i=s("f5df"),r=s("3f8c"),n=s("b622"),a=n("iterator");t.exports=function(t){if(void 0!=t)return t[a]||t["@@iterator"]||r[i(t)]}},"37e8":function(t,e,s){var i=s("83ab"),r=s("9bf2"),n=s("825a"),a=s("df75");t.exports=i?Object.defineProperties:function(t,e){n(t);var s,i=a(e),o=i.length,c=0;while(o>c)r.f(t,s=i[c++],e[s]);return t}},"3bbe":function(t,e,s){var i=s("861d");t.exports=function(t){if(!i(t)&&null!==t)throw TypeError("Can't set "+String(t)+" as a prototype");return t}},"3ca3":function(t,e,s){"use strict";var i=s("6547").charAt,r=s("69f3"),n=s("7dd0"),a="String Iterator",o=r.set,c=r.getterFor(a);n(String,"String",(function(t){o(this,{type:a,string:String(t),index:0})}),(function(){var t,e=c(this),s=e.string,r=e.index;return r>=s.length?{value:void 0,done:!0}:(t=i(s,r),e.index+=t.length,{value:t,done:!1})}))},"3f8c":function(t,e){t.exports={}},4160:function(t,e,s){"use strict";var i=s("23e7"),r=s("17c2");i({target:"Array",proto:!0,forced:[].forEach!=r},{forEach:r})},"428f":function(t,e,s){var i=s("da84");t.exports=i},4362:function(t,e,s){e.nextTick=function(t){var e=Array.prototype.slice.call(arguments);e.shift(),setTimeout((function(){t.apply(null,e)}),0)},e.platform=e.arch=e.execPath=e.title="browser",e.pid=1,e.browser=!0,e.env={},e.argv=[],e.binding=function(t){throw new Error("No such module. (Possibly not yet loaded)")},function(){var t,i="/";e.cwd=function(){return i},e.chdir=function(e){t||(t=s("df7c")),i=t.resolve(e,i)}}(),e.exit=e.kill=e.umask=e.dlopen=e.uptime=e.memoryUsage=e.uvCounters=function(){},e.features={}},"44ad":function(t,e,s){var i=s("d039"),r=s("c6b6"),n="".split;t.exports=i((function(){return!Object("z").propertyIsEnumerable(0)}))?function(t){return"String"==r(t)?n.call(t,""):Object(t)}:Object},"44d2":function(t,e,s){var i=s("b622"),r=s("7c73"),n=s("9bf2"),a=i("unscopables"),o=Array.prototype;void 0==o[a]&&n.f(o,a,{configurable:!0,value:r(null)}),t.exports=function(t){o[a][t]=!0}},"44de":function(t,e,s){var i=s("da84");t.exports=function(t,e){var s=i.console;s&&s.error&&(1===arguments.length?s.error(t):s.error(t,e))}},"44e7":function(t,e,s){var i=s("861d"),r=s("c6b6"),n=s("b622"),a=n("match");t.exports=function(t){var e;return i(t)&&(void 0!==(e=t[a])?!!e:"RegExp"==r(t))}},"45fc":function(t,e,s){"use strict";var i=s("23e7"),r=s("b727").some,n=s("a640"),a=s("ae40"),o=n("some"),c=a("some");i({target:"Array",proto:!0,forced:!o||!c},{some:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}})},4840:function(t,e,s){var i=s("825a"),r=s("1c0b"),n=s("b622"),a=n("species");t.exports=function(t,e){var s,n=i(t).constructor;return void 0===n||void 0==(s=i(n)[a])?e:r(s)}},4930:function(t,e,s){var i=s("d039");t.exports=!!Object.getOwnPropertySymbols&&!i((function(){return!String(Symbol())}))},"4d63":function(t,e,s){var i=s("83ab"),r=s("da84"),n=s("94ca"),a=s("7156"),o=s("9bf2").f,c=s("241c").f,h=s("44e7"),l=s("ad6d"),p=s("9f7f"),u=s("6eeb"),d=s("d039"),f=s("69f3").set,m=s("2626"),y=s("b622"),g=y("match"),x=r.RegExp,b=x.prototype,v=/a/g,w=/a/g,P=new x(v)!==v,T=p.UNSUPPORTED_Y,E=i&&n("RegExp",!P||T||d((function(){return w[g]=!1,x(v)!=v||x(w)==w||"/a/i"!=x(v,"i")})));if(E){var A=function(t,e){var s,i=this instanceof A,r=h(t),n=void 0===e;if(!i&&r&&t.constructor===A&&n)return t;P?r&&!n&&(t=t.source):t instanceof A&&(n&&(e=l.call(t)),t=t.source),T&&(s=!!e&&e.indexOf("y")>-1,s&&(e=e.replace(/y/g,"")));var o=a(P?new x(t,e):x(t,e),i?this:b,A);return T&&s&&f(o,{sticky:s}),o},S=function(t){t in A||o(A,t,{configurable:!0,get:function(){return x[t]},set:function(e){x[t]=e}})},C=c(x),k=0;while(C.length>k)S(C[k++]);b.constructor=A,A.prototype=b,u(r,"RegExp",A)}m("RegExp")},"4d64":function(t,e,s){var i=s("fc6a"),r=s("50c4"),n=s("23cb"),a=function(t){return function(e,s,a){var o,c=i(e),h=r(c.length),l=n(a,h);if(t&&s!=s){while(h>l)if(o=c[l++],o!=o)return!0}else for(;h>l;l++)if((t||l in c)&&c[l]===s)return t||l||0;return!t&&-1}};t.exports={includes:a(!0),indexOf:a(!1)}},"4de4":function(t,e,s){"use strict";var i=s("23e7"),r=s("b727").filter,n=s("1dde"),a=s("ae40"),o=n("filter"),c=a("filter");i({target:"Array",proto:!0,forced:!o||!c},{filter:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}})},"50c4":function(t,e,s){var i=s("a691"),r=Math.min;t.exports=function(t){return t>0?r(i(t),9007199254740991):0}},5135:function(t,e){var s={}.hasOwnProperty;t.exports=function(t,e){return s.call(t,e)}},5319:function(t,e,s){"use strict";var i=s("d784"),r=s("825a"),n=s("7b0b"),a=s("50c4"),o=s("a691"),c=s("1d80"),h=s("8aa5"),l=s("14c3"),p=Math.max,u=Math.min,d=Math.floor,f=/\$([$&'`]|\d\d?|<[^>]*>)/g,m=/\$([$&'`]|\d\d?)/g,y=function(t){return void 0===t?t:String(t)};i("replace",2,(function(t,e,s,i){var g=i.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE,x=i.REPLACE_KEEPS_$0,b=g?"$":"$0";return[function(s,i){var r=c(this),n=void 0==s?void 0:s[t];return void 0!==n?n.call(s,r,i):e.call(String(r),s,i)},function(t,i){if(!g&&x||"string"===typeof i&&-1===i.indexOf(b)){var n=s(e,t,this,i);if(n.done)return n.value}var c=r(t),d=String(this),f="function"===typeof i;f||(i=String(i));var m=c.global;if(m){var w=c.unicode;c.lastIndex=0}var P=[];while(1){var T=l(c,d);if(null===T)break;if(P.push(T),!m)break;var E=String(T[0]);""===E&&(c.lastIndex=h(d,a(c.lastIndex),w))}for(var A="",S=0,C=0;C=S&&(A+=d.slice(S,N)+L,S=N+k.length)}return A+d.slice(S)}];function v(t,s,i,r,a,o){var c=i+t.length,h=r.length,l=m;return void 0!==a&&(a=n(a),l=f),e.call(o,l,(function(e,n){var o;switch(n.charAt(0)){case"$":return"$";case"&":return t;case"`":return s.slice(0,i);case"'":return s.slice(c);case"<":o=a[n.slice(1,-1)];break;default:var l=+n;if(0===l)return e;if(l>h){var p=d(l/10);return 0===p?e:p<=h?void 0===r[p-1]?n.charAt(1):r[p-1]+n.charAt(1):e}o=r[l-1]}return void 0===o?"":o}))}}))},"53ca":function(t,e,s){"use strict";s.d(e,"a",(function(){return i}));s("a4d3"),s("e01a"),s("d28b"),s("d3b7"),s("3ca3"),s("ddb0");function i(t){return i="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"===typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i(t)}},5530:function(t,e,s){"use strict";s.d(e,"a",(function(){return n}));s("a4d3"),s("4de4"),s("4160"),s("e439"),s("dbb4"),s("b64b"),s("159b");var i=s("ade3");function r(t,e){var s=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),s.push.apply(s,i)}return s}function n(t){for(var e=1;el){var d,f=h(arguments[l++]),m=p?n(f).concat(p(f)):n(f),y=m.length,g=0;while(y>g)d=m[g++],i&&!u.call(f,d)||(s[d]=f[d])}return s}:l},6547:function(t,e,s){var i=s("a691"),r=s("1d80"),n=function(t){return function(e,s){var n,a,o=String(r(e)),c=i(s),h=o.length;return c<0||c>=h?t?"":void 0:(n=o.charCodeAt(c),n<55296||n>56319||c+1===h||(a=o.charCodeAt(c+1))<56320||a>57343?t?o.charAt(c):n:t?o.slice(c,c+2):a-56320+(n-55296<<10)+65536)}};t.exports={codeAt:n(!1),charAt:n(!0)}},"65f0":function(t,e,s){var i=s("861d"),r=s("e8b5"),n=s("b622"),a=n("species");t.exports=function(t,e){var s;return r(t)&&(s=t.constructor,"function"!=typeof s||s!==Array&&!r(s.prototype)?i(s)&&(s=s[a],null===s&&(s=void 0)):s=void 0),new(void 0===s?Array:s)(0===e?0:e)}},"69f3":function(t,e,s){var i,r,n,a=s("7f9a"),o=s("da84"),c=s("861d"),h=s("9112"),l=s("5135"),p=s("f772"),u=s("d012"),d=o.WeakMap,f=function(t){return n(t)?r(t):i(t,{})},m=function(t){return function(e){var s;if(!c(e)||(s=r(e)).type!==t)throw TypeError("Incompatible receiver, "+t+" required");return s}};if(a){var y=new d,g=y.get,x=y.has,b=y.set;i=function(t,e){return b.call(y,t,e),e},r=function(t){return g.call(y,t)||{}},n=function(t){return x.call(y,t)}}else{var v=p("state");u[v]=!0,i=function(t,e){return h(t,v,e),e},r=function(t){return l(t,v)?t[v]:{}},n=function(t){return l(t,v)}}t.exports={set:i,get:r,has:n,enforce:f,getterFor:m}},"6eeb":function(t,e,s){var i=s("da84"),r=s("9112"),n=s("5135"),a=s("ce4e"),o=s("8925"),c=s("69f3"),h=c.get,l=c.enforce,p=String(String).split("String");(t.exports=function(t,e,s,o){var c=!!o&&!!o.unsafe,h=!!o&&!!o.enumerable,u=!!o&&!!o.noTargetGet;"function"==typeof s&&("string"!=typeof e||n(s,"name")||r(s,"name",e),l(s).source=p.join("string"==typeof e?e:"")),t!==i?(c?!u&&t[e]&&(h=!0):delete t[e],h?t[e]=s:r(t,e,s)):h?t[e]=s:a(e,s)})(Function.prototype,"toString",(function(){return"function"==typeof this&&h(this).source||o(this)}))},7156:function(t,e,s){var i=s("861d"),r=s("d2bb");t.exports=function(t,e,s){var n,a;return r&&"function"==typeof(n=e.constructor)&&n!==s&&i(a=n.prototype)&&a!==s.prototype&&r(t,a),t}},7418:function(t,e){e.f=Object.getOwnPropertySymbols},"746f":function(t,e,s){var i=s("428f"),r=s("5135"),n=s("e538"),a=s("9bf2").f;t.exports=function(t){var e=i.Symbol||(i.Symbol={});r(e,t)||a(e,t,{value:n.f(t)})}},7839:function(t,e){t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},"7b0b":function(t,e,s){var i=s("1d80");t.exports=function(t){return Object(i(t))}},"7c73":function(t,e,s){var i,r=s("825a"),n=s("37e8"),a=s("7839"),o=s("d012"),c=s("1be4"),h=s("cc12"),l=s("f772"),p=">",u="<",d="prototype",f="script",m=l("IE_PROTO"),y=function(){},g=function(t){return u+f+p+t+u+"/"+f+p},x=function(t){t.write(g("")),t.close();var e=t.parentWindow.Object;return t=null,e},b=function(){var t,e=h("iframe"),s="java"+f+":";return e.style.display="none",c.appendChild(e),e.src=String(s),t=e.contentWindow.document,t.open(),t.write(g("document.F=Object")),t.close(),t.F},v=function(){try{i=document.domain&&new ActiveXObject("htmlfile")}catch(e){}v=i?x(i):b();var t=a.length;while(t--)delete v[d][a[t]];return v()};o[m]=!0,t.exports=Object.create||function(t,e){var s;return null!==t?(y[d]=r(t),s=new y,y[d]=null,s[m]=t):s=v(),void 0===e?s:n(s,e)}},"7db0":function(t,e,s){"use strict";var i=s("23e7"),r=s("b727").find,n=s("44d2"),a=s("ae40"),o="find",c=!0,h=a(o);o in[]&&Array(1)[o]((function(){c=!1})),i({target:"Array",proto:!0,forced:c||!h},{find:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}}),n(o)},"7dd0":function(t,e,s){"use strict";var i=s("23e7"),r=s("9ed3"),n=s("e163"),a=s("d2bb"),o=s("d44e"),c=s("9112"),h=s("6eeb"),l=s("b622"),p=s("c430"),u=s("3f8c"),d=s("ae93"),f=d.IteratorPrototype,m=d.BUGGY_SAFARI_ITERATORS,y=l("iterator"),g="keys",x="values",b="entries",v=function(){return this};t.exports=function(t,e,s,l,d,w,P){r(s,e,l);var T,E,A,S=function(t){if(t===d&&O)return O;if(!m&&t in N)return N[t];switch(t){case g:return function(){return new s(this,t)};case x:return function(){return new s(this,t)};case b:return function(){return new s(this,t)}}return function(){return new s(this)}},C=e+" Iterator",k=!1,N=t.prototype,I=N[y]||N["@@iterator"]||d&&N[d],O=!m&&I||S(d),D="Array"==e&&N.entries||I;if(D&&(T=n(D.call(new t)),f!==Object.prototype&&T.next&&(p||n(T)===f||(a?a(T,f):"function"!=typeof T[y]&&c(T,y,v)),o(T,C,!0,!0),p&&(u[C]=v))),d==x&&I&&I.name!==x&&(k=!0,O=function(){return I.call(this)}),p&&!P||N[y]===O||c(N,y,O),u[e]=O,d)if(E={values:S(x),keys:w?O:S(g),entries:S(b)},P)for(A in E)(m||k||!(A in N))&&h(N,A,E[A]);else i({target:e,proto:!0,forced:m||k},E);return E}},"7f9a":function(t,e,s){var i=s("da84"),r=s("8925"),n=i.WeakMap;t.exports="function"===typeof n&&/native code/.test(r(n))},"825a":function(t,e,s){var i=s("861d");t.exports=function(t){if(!i(t))throw TypeError(String(t)+" is not an object");return t}},"83ab":function(t,e,s){var i=s("d039");t.exports=!i((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},8418:function(t,e,s){"use strict";var i=s("c04e"),r=s("9bf2"),n=s("5c6c");t.exports=function(t,e,s){var a=i(e);a in t?r.f(t,a,n(0,s)):t[a]=s}},"861d":function(t,e){t.exports=function(t){return"object"===typeof t?null!==t:"function"===typeof t}},8925:function(t,e,s){var i=s("c6cd"),r=Function.toString;"function"!=typeof i.inspectSource&&(i.inspectSource=function(t){return r.call(t)}),t.exports=i.inspectSource},"8a79":function(t,e,s){"use strict";var i=s("23e7"),r=s("06cf").f,n=s("50c4"),a=s("5a34"),o=s("1d80"),c=s("ab13"),h=s("c430"),l="".endsWith,p=Math.min,u=c("endsWith"),d=!h&&!u&&!!function(){var t=r(String.prototype,"endsWith");return t&&!t.writable}();i({target:"String",proto:!0,forced:!d&&!u},{endsWith:function(t){var e=String(o(this));a(t);var s=arguments.length>1?arguments[1]:void 0,i=n(e.length),r=void 0===s?i:p(n(s),i),c=String(t);return l?l.call(e,c,r):e.slice(r-c.length,r)===c}})},"8aa5":function(t,e,s){"use strict";var i=s("6547").charAt;t.exports=function(t,e,s){return e+(s?i(t,e).length:1)}},"90e3":function(t,e){var s=0,i=Math.random();t.exports=function(t){return"Symbol("+String(void 0===t?"":t)+")_"+(++s+i).toString(36)}},9112:function(t,e,s){var i=s("83ab"),r=s("9bf2"),n=s("5c6c");t.exports=i?function(t,e,s){return r.f(t,e,n(1,s))}:function(t,e,s){return t[e]=s,t}},9263:function(t,e,s){"use strict";var i=s("ad6d"),r=s("9f7f"),n=RegExp.prototype.exec,a=String.prototype.replace,o=n,c=function(){var t=/a/,e=/b*/g;return n.call(t,"a"),n.call(e,"a"),0!==t.lastIndex||0!==e.lastIndex}(),h=r.UNSUPPORTED_Y||r.BROKEN_CARET,l=void 0!==/()??/.exec("")[1],p=c||l||h;p&&(o=function(t){var e,s,r,o,p=this,u=h&&p.sticky,d=i.call(p),f=p.source,m=0,y=t;return u&&(d=d.replace("y",""),-1===d.indexOf("g")&&(d+="g"),y=String(t).slice(p.lastIndex),p.lastIndex>0&&(!p.multiline||p.multiline&&"\n"!==t[p.lastIndex-1])&&(f="(?: "+f+")",y=" "+y,m++),s=new RegExp("^(?:"+f+")",d)),l&&(s=new RegExp("^"+f+"$(?!\\s)",d)),c&&(e=p.lastIndex),r=n.call(u?s:p,y),u?r?(r.input=r.input.slice(m),r[0]=r[0].slice(m),r.index=p.lastIndex,p.lastIndex+=r[0].length):p.lastIndex=0:c&&r&&(p.lastIndex=p.global?r.index+r[0].length:e),l&&r&&r.length>1&&a.call(r[0],s,(function(){for(o=1;o=51||!r((function(){var t=[];return t[f]=!1,t.concat()[0]!==t})),x=p("concat"),b=function(t){if(!a(t))return!1;var e=t[f];return void 0!==e?!!e:n(t)},v=!g||!x;i({target:"Array",proto:!0,forced:v},{concat:function(t){var e,s,i,r,n,a=o(this),p=l(a,0),u=0;for(e=-1,i=arguments.length;em)throw TypeError(y);for(s=0;s=m)throw TypeError(y);h(p,u++,n)}return p.length=u,p}})},"9bdd":function(t,e,s){var i=s("825a");t.exports=function(t,e,s,r){try{return r?e(i(s)[0],s[1]):e(s)}catch(a){var n=t["return"];throw void 0!==n&&i(n.call(t)),a}}},"9bf2":function(t,e,s){var i=s("83ab"),r=s("0cfb"),n=s("825a"),a=s("c04e"),o=Object.defineProperty;e.f=i?o:function(t,e,s){if(n(t),e=a(e,!0),n(s),r)try{return o(t,e,s)}catch(i){}if("get"in s||"set"in s)throw TypeError("Accessors not supported");return"value"in s&&(t[e]=s.value),t}},"9ed3":function(t,e,s){"use strict";var i=s("ae93").IteratorPrototype,r=s("7c73"),n=s("5c6c"),a=s("d44e"),o=s("3f8c"),c=function(){return this};t.exports=function(t,e,s){var h=e+" Iterator";return t.prototype=r(i,{next:n(1,s)}),a(t,h,!1,!0),o[h]=c,t}},"9f7f":function(t,e,s){"use strict";var i=s("d039");function r(t,e){return RegExp(t,e)}e.UNSUPPORTED_Y=i((function(){var t=r("a","y");return t.lastIndex=2,null!=t.exec("abcd")})),e.BROKEN_CARET=i((function(){var t=r("^r","gy");return t.lastIndex=2,null!=t.exec("str")}))},a15b:function(t,e,s){"use strict";var i=s("23e7"),r=s("44ad"),n=s("fc6a"),a=s("a640"),o=[].join,c=r!=Object,h=a("join",",");i({target:"Array",proto:!0,forced:c||!h},{join:function(t){return o.call(n(this),void 0===t?",":t)}})},a434:function(t,e,s){"use strict";var i=s("23e7"),r=s("23cb"),n=s("a691"),a=s("50c4"),o=s("7b0b"),c=s("65f0"),h=s("8418"),l=s("1dde"),p=s("ae40"),u=l("splice"),d=p("splice",{ACCESSORS:!0,0:0,1:2}),f=Math.max,m=Math.min,y=9007199254740991,g="Maximum allowed length exceeded";i({target:"Array",proto:!0,forced:!u||!d},{splice:function(t,e){var s,i,l,p,u,d,x=o(this),b=a(x.length),v=r(t,b),w=arguments.length;if(0===w?s=i=0:1===w?(s=0,i=b-v):(s=w-2,i=m(f(n(e),0),b-v)),b+s-i>y)throw TypeError(g);for(l=c(x,i),p=0;pb-i+s;p--)delete x[p-1]}else if(s>i)for(p=b-i;p>v;p--)u=p+i-1,d=p+s-1,u in x?x[d]=x[u]:delete x[d];for(p=0;pn)r.push(arguments[n++]);if(i=e,(d(e)||void 0!==t)&&!ot(t))return u(e)||(e=function(t,e){if("function"==typeof i&&(e=i.call(this,t,e)),!ot(e))return e}),r[1]=e,$.apply(null,r)}})}K[q][V]||C(K[q],V,K[q].valueOf),R(K,U),O[B]=!0},a640:function(t,e,s){"use strict";var i=s("d039");t.exports=function(t,e){var s=[][t];return!!s&&i((function(){s.call(null,e||function(){throw 1},1)}))}},a691:function(t,e){var s=Math.ceil,i=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?i:s)(t)}},a79d:function(t,e,s){"use strict";var i=s("23e7"),r=s("c430"),n=s("fea9"),a=s("d039"),o=s("d066"),c=s("4840"),h=s("cdf9"),l=s("6eeb"),p=!!n&&a((function(){n.prototype["finally"].call({then:function(){}},(function(){}))}));i({target:"Promise",proto:!0,real:!0,forced:p},{finally:function(t){var e=c(this,o("Promise")),s="function"==typeof t;return this.then(s?function(s){return h(e,t()).then((function(){return s}))}:t,s?function(s){return h(e,t()).then((function(){throw s}))}:t)}}),r||"function"!=typeof n||n.prototype["finally"]||l(n.prototype,"finally",o("Promise").prototype["finally"])},aa47:function(t,e,s){"use strict"; +/**! + * Sortable 1.10.2 + * @author RubaXa + * @author owenm + * @license MIT + */ +function i(t){return i="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"===typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i(t)}function r(t,e,s){return e in t?Object.defineProperty(t,e,{value:s,enumerable:!0,configurable:!0,writable:!0}):t[e]=s,t}function n(){return n=Object.assign||function(t){for(var e=1;e=0||(r[s]=t[s]);return r}function c(t,e){if(null==t)return{};var s,i,r=o(t,e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(t,s)&&(r[s]=t[s])}return r}function h(t){return l(t)||p(t)||u()}function l(t){if(Array.isArray(t)){for(var e=0,s=new Array(t.length);e"===e[0]&&(e=e.substring(1)),t)try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(s){return!1}return!1}}function A(t){return t.host&&t!==document&&t.host.nodeType?t.host:t.parentNode}function S(t,e,s,i){if(t){s=s||document;do{if(null!=e&&(">"===e[0]?t.parentNode===s&&E(t,e):E(t,e))||i&&t===s)return t;if(t===s)break}while(t=A(t))}return null}var C,k=/\s+/g;function N(t,e,s){if(t&&e)if(t.classList)t.classList[s?"add":"remove"](e);else{var i=(" "+t.className+" ").replace(k," ").replace(" "+e+" "," ");t.className=(i+(s?" "+e:"")).replace(k," ")}}function I(t,e,s){var i=t&&t.style;if(i){if(void 0===s)return document.defaultView&&document.defaultView.getComputedStyle?s=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(s=t.currentStyle),void 0===e?s:s[e];e in i||-1!==e.indexOf("webkit")||(e="-webkit-"+e),i[e]=s+("string"===typeof s?"":"px")}}function O(t,e){var s="";if("string"===typeof t)s=t;else do{var i=I(t,"transform");i&&"none"!==i&&(s=i+" "+s)}while(!e&&(t=t.parentNode));var r=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return r&&new r(s)}function D(t,e,s){if(t){var i=t.getElementsByTagName(e),r=0,n=i.length;if(s)for(;r=n:r<=n,!a)return i;if(i===M())break;i=q(i,!1)}return!1}function R(t,e,s){var i=0,r=0,n=t.children;while(r2&&void 0!==arguments[2]?arguments[2]:{},i=s.evt,r=c(s,["evt"]);st.pluginEvent.bind(Qt)(t,e,a({dragEl:at,parentEl:ot,ghostEl:ct,rootEl:ht,nextEl:lt,lastDownEl:pt,cloneEl:ut,cloneHidden:dt,dragStarted:St,putSortable:bt,activeSortable:Qt.active,originalEvent:i,oldIndex:ft,oldDraggableIndex:yt,newIndex:mt,newDraggableIndex:gt,hideGhostForTarget:Xt,unhideGhostForTarget:Gt,cloneNowHidden:function(){dt=!0},cloneNowShown:function(){dt=!1},dispatchSortableEvent:function(t){nt({sortable:e,name:t,originalEvent:i})}},r))};function nt(t){it(a({putSortable:bt,cloneEl:ut,targetEl:at,rootEl:ht,oldIndex:ft,oldDraggableIndex:yt,newIndex:mt,newDraggableIndex:gt},t))}var at,ot,ct,ht,lt,pt,ut,dt,ft,mt,yt,gt,xt,bt,vt,wt,Pt,Tt,Et,At,St,Ct,kt,Nt,It,Ot=!1,Dt=!1,Mt=[],Lt=!1,_t=!1,Rt=[],jt=!1,Ft=[],Bt="undefined"!==typeof document,Ut=b,qt=y||m?"cssFloat":"float",Vt=Bt&&!v&&!b&&"draggable"in document.createElement("div"),Ht=function(){if(Bt){if(m)return!1;var t=document.createElement("x");return t.style.cssText="pointer-events:auto","auto"===t.style.pointerEvents}}(),zt=function(t,e){var s=I(t),i=parseInt(s.width)-parseInt(s.paddingLeft)-parseInt(s.paddingRight)-parseInt(s.borderLeftWidth)-parseInt(s.borderRightWidth),r=R(t,0,e),n=R(t,1,e),a=r&&I(r),o=n&&I(n),c=a&&parseInt(a.marginLeft)+parseInt(a.marginRight)+L(r).width,h=o&&parseInt(o.marginLeft)+parseInt(o.marginRight)+L(n).width;if("flex"===s.display)return"column"===s.flexDirection||"column-reverse"===s.flexDirection?"vertical":"horizontal";if("grid"===s.display)return s.gridTemplateColumns.split(" ").length<=1?"vertical":"horizontal";if(r&&a["float"]&&"none"!==a["float"]){var l="left"===a["float"]?"left":"right";return!n||"both"!==o.clear&&o.clear!==l?"horizontal":"vertical"}return r&&("block"===a.display||"flex"===a.display||"table"===a.display||"grid"===a.display||c>=i&&"none"===s[qt]||n&&"none"===s[qt]&&c+h>i)?"vertical":"horizontal"},Wt=function(t,e,s){var i=s?t.left:t.top,r=s?t.right:t.bottom,n=s?t.width:t.height,a=s?e.left:e.top,o=s?e.right:e.bottom,c=s?e.width:e.height;return i===a||r===o||i+n/2===a+c/2},Kt=function(t,e){var s;return Mt.some((function(i){if(!j(i)){var r=L(i),n=i[Y].options.emptyInsertThreshold,a=t>=r.left-n&&t<=r.right+n,o=e>=r.top-n&&e<=r.bottom+n;return n&&a&&o?s=i:void 0}})),s},$t=function(t){function e(t,s){return function(i,r,n,a){var o=i.options.group.name&&r.options.group.name&&i.options.group.name===r.options.group.name;if(null==t&&(s||o))return!0;if(null==t||!1===t)return!1;if(s&&"clone"===t)return t;if("function"===typeof t)return e(t(i,r,n,a),s)(i,r,n,a);var c=(s?i:r).options.group.name;return!0===t||"string"===typeof t&&t===c||t.join&&t.indexOf(c)>-1}}var s={},r=t.group;r&&"object"==i(r)||(r={name:r}),s.name=r.name,s.checkPull=e(r.pull,!0),s.checkPut=e(r.put),s.revertClone=r.revertClone,t.group=s},Xt=function(){!Ht&&ct&&I(ct,"display","none")},Gt=function(){!Ht&&ct&&I(ct,"display","")};Bt&&document.addEventListener("click",(function(t){if(Dt)return t.preventDefault(),t.stopPropagation&&t.stopPropagation(),t.stopImmediatePropagation&&t.stopImmediatePropagation(),Dt=!1,!1}),!0);var Yt=function(t){if(at){t=t.touches?t.touches[0]:t;var e=Kt(t.clientX,t.clientY);if(e){var s={};for(var i in t)t.hasOwnProperty(i)&&(s[i]=t[i]);s.target=s.rootEl=e,s.preventDefault=void 0,s.stopPropagation=void 0,e[Y]._onDragOver(s)}}},Jt=function(t){at&&at.parentNode[Y]._isOutsideThisEl(t.target)};function Qt(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.el=t,this.options=e=n({},e),t[Y]=this;var s={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(t.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return zt(t,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==Qt.supportPointer&&"PointerEvent"in window,emptyInsertThreshold:5};for(var i in st.initializePlugins(this,t,s),s)!(i in e)&&(e[i]=s[i]);for(var r in $t(e),this)"_"===r.charAt(0)&&"function"===typeof this[r]&&(this[r]=this[r].bind(this));this.nativeDraggable=!e.forceFallback&&Vt,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?P(t,"pointerdown",this._onTapStart):(P(t,"mousedown",this._onTapStart),P(t,"touchstart",this._onTapStart)),this.nativeDraggable&&(P(t,"dragover",this),P(t,"dragenter",this)),Mt.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),n(this,J())}function Zt(t){t.dataTransfer&&(t.dataTransfer.dropEffect="move"),t.cancelable&&t.preventDefault()}function te(t,e,s,i,r,n,a,o){var c,h,l=t[Y],p=l.options.onMove;return!window.CustomEvent||m||y?(c=document.createEvent("Event"),c.initEvent("move",!0,!0)):c=new CustomEvent("move",{bubbles:!0,cancelable:!0}),c.to=e,c.from=t,c.dragged=s,c.draggedRect=i,c.related=r||e,c.relatedRect=n||L(e),c.willInsertAfter=o,c.originalEvent=a,t.dispatchEvent(c),p&&(h=p.call(l,c,a)),h}function ee(t){t.draggable=!1}function se(){jt=!1}function ie(t,e,s){var i=L(j(s.el,s.options.draggable)),r=10;return e?t.clientX>i.right+r||t.clientX<=i.right&&t.clientY>i.bottom&&t.clientX>=i.left:t.clientX>i.right&&t.clientY>i.top||t.clientX<=i.right&&t.clientY>i.bottom+r}function re(t,e,s,i,r,n,a,o){var c=i?t.clientY:t.clientX,h=i?s.height:s.width,l=i?s.top:s.left,p=i?s.bottom:s.right,u=!1;if(!a)if(o&&Ntl+h*n/2:cp-Nt)return-kt}else if(c>l+h*(1-r)/2&&cp-h*n/2)?c>l+h/2?1:-1:0}function ne(t){return F(at)=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){at&&ee(at),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var t=this.el.ownerDocument;T(t,"mouseup",this._disableDelayedDrag),T(t,"touchend",this._disableDelayedDrag),T(t,"touchcancel",this._disableDelayedDrag),T(t,"mousemove",this._delayedDragTouchMoveHandler),T(t,"touchmove",this._delayedDragTouchMoveHandler),T(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){e=e||"touch"==t.pointerType&&t,!this.nativeDraggable||e?this.options.supportPointer?P(document,"pointermove",this._onTouchMove):P(document,e?"touchmove":"mousemove",this._onTouchMove):(P(at,"dragend",this),P(ht,"dragstart",this._onDragStart));try{document.selection?ce((function(){document.selection.empty()})):window.getSelection().removeAllRanges()}catch(s){}},_dragStarted:function(t,e){if(Ot=!1,ht&&at){rt("dragStarted",this,{evt:e}),this.nativeDraggable&&P(document,"dragover",Jt);var s=this.options;!t&&N(at,s.dragClass,!1),N(at,s.ghostClass,!0),Qt.active=this,t&&this._appendGhost(),nt({sortable:this,name:"start",originalEvent:e})}else this._nulling()},_emulateDragOver:function(){if(wt){this._lastX=wt.clientX,this._lastY=wt.clientY,Xt();var t=document.elementFromPoint(wt.clientX,wt.clientY),e=t;while(t&&t.shadowRoot){if(t=t.shadowRoot.elementFromPoint(wt.clientX,wt.clientY),t===e)break;e=t}if(at.parentNode[Y]._isOutsideThisEl(t),e)do{if(e[Y]){var s=void 0;if(s=e[Y]._onDragOver({clientX:wt.clientX,clientY:wt.clientY,target:t,rootEl:e}),s&&!this.options.dragoverBubble)break}t=e}while(e=e.parentNode);Gt()}},_onTouchMove:function(t){if(vt){var e=this.options,s=e.fallbackTolerance,i=e.fallbackOffset,r=t.touches?t.touches[0]:t,n=ct&&O(ct,!0),a=ct&&n&&n.a,o=ct&&n&&n.d,c=Ut&&It&&B(It),h=(r.clientX-vt.clientX+i.x)/(a||1)+(c?c[0]-Rt[0]:0)/(a||1),l=(r.clientY-vt.clientY+i.y)/(o||1)+(c?c[1]-Rt[1]:0)/(o||1);if(!Qt.active&&!Ot){if(s&&Math.max(Math.abs(r.clientX-this._lastX),Math.abs(r.clientY-this._lastY))=0&&(nt({rootEl:ot,name:"add",toEl:ot,fromEl:ht,originalEvent:t}),nt({sortable:this,name:"remove",toEl:ot,originalEvent:t}),nt({rootEl:ot,name:"sort",toEl:ot,fromEl:ht,originalEvent:t}),nt({sortable:this,name:"sort",toEl:ot,originalEvent:t})),bt&&bt.save()):mt!==ft&&mt>=0&&(nt({sortable:this,name:"update",toEl:ot,originalEvent:t}),nt({sortable:this,name:"sort",toEl:ot,originalEvent:t})),Qt.active&&(null!=mt&&-1!==mt||(mt=ft,gt=yt),nt({sortable:this,name:"end",toEl:ot,originalEvent:t}),this.save())))),this._nulling()},_nulling:function(){rt("nulling",this),ht=at=ot=ct=lt=ut=pt=dt=vt=wt=St=mt=gt=ft=yt=Ct=kt=bt=xt=Qt.dragged=Qt.ghost=Qt.clone=Qt.active=null,Ft.forEach((function(t){t.checked=!0})),Ft.length=Pt=Tt=0},handleEvent:function(t){switch(t.type){case"drop":case"dragend":this._onDrop(t);break;case"dragenter":case"dragover":at&&(this._onDragOver(t),Zt(t));break;case"selectstart":t.preventDefault();break}},toArray:function(){for(var t,e=[],s=this.el.children,i=0,r=s.length,n=this.options;i1&&(Me.forEach((function(t){i.addAnimationState({target:t,rect:Re?L(t):r}),G(t),t.fromRect=r,e.removeAnimationState(t)})),Re=!1,Be(!this.options.removeCloneOnHide,s))},dragOverCompleted:function(t){var e=t.sortable,s=t.isOwner,i=t.insertion,r=t.activeSortable,n=t.parentEl,a=t.putSortable,o=this.options;if(i){if(s&&r._hideClone(),_e=!1,o.animation&&Me.length>1&&(Re||!s&&!r.options.sort&&!a)){var c=L(Ie,!1,!0,!0);Me.forEach((function(t){t!==Ie&&(X(t,c),n.appendChild(t))})),Re=!0}if(!s)if(Re||qe(),Me.length>1){var h=De;r._showClone(e),r.options.animation&&!De&&h&&Le.forEach((function(t){r.addAnimationState({target:t,rect:Oe}),t.fromRect=Oe,t.thisAnimationDuration=null}))}else r._showClone(e)}},dragOverAnimationCapture:function(t){var e=t.dragRect,s=t.isOwner,i=t.activeSortable;if(Me.forEach((function(t){t.thisAnimationDuration=null})),i.options.animation&&!s&&i.multiDrag.isMultiDrag){Oe=n({},e);var r=O(Ie,!0);Oe.top-=r.f,Oe.left-=r.e}},dragOverAnimationComplete:function(){Re&&(Re=!1,qe())},drop:function(t){var e=t.originalEvent,s=t.rootEl,i=t.parentEl,r=t.sortable,n=t.dispatchSortableEvent,a=t.oldIndex,o=t.putSortable,c=o||this.sortable;if(e){var h=this.options,l=i.children;if(!je)if(h.multiDragKey&&!this.multiDragKeyDown&&this._deselectMultiDrag(),N(Ie,h.selectedClass,!~Me.indexOf(Ie)),~Me.indexOf(Ie))Me.splice(Me.indexOf(Ie),1),ke=null,it({sortable:r,rootEl:s,name:"deselect",targetEl:Ie,originalEvt:e});else{if(Me.push(Ie),it({sortable:r,rootEl:s,name:"select",targetEl:Ie,originalEvt:e}),e.shiftKey&&ke&&r.el.contains(ke)){var p,u,d=F(ke),f=F(Ie);if(~d&&~f&&d!==f)for(f>d?(u=d,p=f):(u=f,p=d+1);u1){var m=L(Ie),y=F(Ie,":not(."+this.options.selectedClass+")");if(!_e&&h.animation&&(Ie.thisAnimationDuration=null),c.captureAnimationState(),!_e&&(h.animation&&(Ie.fromRect=m,Me.forEach((function(t){if(t.thisAnimationDuration=null,t!==Ie){var e=Re?L(t):m;t.fromRect=e,c.addAnimationState({target:t,rect:e})}}))),qe(),Me.forEach((function(t){l[y]?i.insertBefore(t,l[y]):i.appendChild(t),y++})),a===F(Ie))){var g=!1;Me.forEach((function(t){t.sortableIndex===F(t)||(g=!0)})),g&&n("update")}Me.forEach((function(t){G(t)})),c.animateAll()}Ne=c}(s===i||o&&"clone"!==o.lastPutMode)&&Le.forEach((function(t){t.parentNode&&t.parentNode.removeChild(t)}))}},nullingGlobal:function(){this.isMultiDrag=je=!1,Le.length=0},destroyGlobal:function(){this._deselectMultiDrag(),T(document,"pointerup",this._deselectMultiDrag),T(document,"mouseup",this._deselectMultiDrag),T(document,"touchend",this._deselectMultiDrag),T(document,"keydown",this._checkKeyDown),T(document,"keyup",this._checkKeyUp)},_deselectMultiDrag:function(t){if(("undefined"===typeof je||!je)&&Ne===this.sortable&&(!t||!S(t.target,this.options.draggable,this.sortable.el,!1))&&(!t||0===t.button))while(Me.length){var e=Me[0];N(e,this.options.selectedClass,!1),Me.shift(),it({sortable:this.sortable,rootEl:this.sortable.el,name:"deselect",targetEl:e,originalEvt:t})}},_checkKeyDown:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!0)},_checkKeyUp:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!1)}},n(t,{pluginName:"multiDrag",utils:{select:function(t){var e=t.parentNode[Y];e&&e.options.multiDrag&&!~Me.indexOf(t)&&(Ne&&Ne!==e&&(Ne.multiDrag._deselectMultiDrag(),Ne=e),N(t,e.options.selectedClass,!0),Me.push(t))},deselect:function(t){var e=t.parentNode[Y],s=Me.indexOf(t);e&&e.options.multiDrag&&~s&&(N(t,e.options.selectedClass,!1),Me.splice(s,1))}},eventProperties:function(){var t=this,e=[],s=[];return Me.forEach((function(i){var r;e.push({multiDragElement:i,index:i.sortableIndex}),r=Re&&i!==Ie?-1:Re?F(i,":not(."+t.options.selectedClass+")"):F(i),s.push({multiDragElement:i,index:r})})),{items:h(Me),clones:[].concat(Le),oldIndicies:e,newIndicies:s}},optionListeners:{multiDragKey:function(t){return t=t.toLowerCase(),"ctrl"===t?t="Control":t.length>1&&(t=t.charAt(0).toUpperCase()+t.substr(1)),t}}})}function Be(t,e){Me.forEach((function(s,i){var r=e.children[s.sortableIndex+(t?Number(i):0)];r?e.insertBefore(s,r):e.appendChild(s)}))}function Ue(t,e){Le.forEach((function(s,i){var r=e.children[s.sortableIndex+(t?Number(i):0)];r?e.insertBefore(s,r):e.appendChild(s)}))}function qe(){Me.forEach((function(t){t!==Ie&&t.parentNode&&t.parentNode.removeChild(t)}))}Qt.mount(new xe),Qt.mount(Ae,Ee),e["default"]=Qt},ab13:function(t,e,s){var i=s("b622"),r=i("match");t.exports=function(t){var e=/./;try{"/./"[t](e)}catch(s){try{return e[r]=!1,"/./"[t](e)}catch(i){}}return!1}},ac1f:function(t,e,s){"use strict";var i=s("23e7"),r=s("9263");i({target:"RegExp",proto:!0,forced:/./.exec!==r},{exec:r})},ad6d:function(t,e,s){"use strict";var i=s("825a");t.exports=function(){var t=i(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.dotAll&&(e+="s"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},ade3:function(t,e,s){"use strict";function i(t,e,s){return e in t?Object.defineProperty(t,e,{value:s,enumerable:!0,configurable:!0,writable:!0}):t[e]=s,t}s.d(e,"a",(function(){return i}))},ae40:function(t,e,s){var i=s("83ab"),r=s("d039"),n=s("5135"),a=Object.defineProperty,o={},c=function(t){throw t};t.exports=function(t,e){if(n(o,t))return o[t];e||(e={});var s=[][t],h=!!n(e,"ACCESSORS")&&e.ACCESSORS,l=n(e,0)?e[0]:c,p=n(e,1)?e[1]:void 0;return o[t]=!!s&&!r((function(){if(h&&!i)return!0;var t={length:-1};h?a(t,1,{enumerable:!0,get:c}):t[1]=1,s.call(t,l,p)}))}},ae93:function(t,e,s){"use strict";var i,r,n,a=s("e163"),o=s("9112"),c=s("5135"),h=s("b622"),l=s("c430"),p=h("iterator"),u=!1,d=function(){return this};[].keys&&(n=[].keys(),"next"in n?(r=a(a(n)),r!==Object.prototype&&(i=r)):u=!0),void 0==i&&(i={}),l||c(i,p)||o(i,p,d),t.exports={IteratorPrototype:i,BUGGY_SAFARI_ITERATORS:u}},b041:function(t,e,s){"use strict";var i=s("00ee"),r=s("f5df");t.exports=i?{}.toString:function(){return"[object "+r(this)+"]"}},b0c0:function(t,e,s){var i=s("83ab"),r=s("9bf2").f,n=Function.prototype,a=n.toString,o=/^\s*function ([^ (]*)/,c="name";i&&!(c in n)&&r(n,c,{configurable:!0,get:function(){try{return a.call(this).match(o)[1]}catch(t){return""}}})},b311:function(t,e,s){ +/*! + * clipboard.js v2.0.6 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +(function(e,s){t.exports=s()})(0,(function(){return function(t){var e={};function s(i){if(e[i])return e[i].exports;var r=e[i]={i:i,l:!1,exports:{}};return t[i].call(r.exports,r,r.exports,s),r.l=!0,r.exports}return s.m=t,s.c=e,s.d=function(t,e,i){s.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},s.r=function(t){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},s.t=function(t,e){if(1&e&&(t=s(t)),8&e)return t;if(4&e&&"object"===typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(s.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)s.d(i,r,function(e){return t[e]}.bind(null,r));return i},s.n=function(t){var e=t&&t.__esModule?function(){return t["default"]}:function(){return t};return s.d(e,"a",e),e},s.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},s.p="",s(s.s=6)}([function(t,e){function s(t){var e;if("SELECT"===t.nodeName)t.focus(),e=t.value;else if("INPUT"===t.nodeName||"TEXTAREA"===t.nodeName){var s=t.hasAttribute("readonly");s||t.setAttribute("readonly",""),t.select(),t.setSelectionRange(0,t.value.length),s||t.removeAttribute("readonly"),e=t.value}else{t.hasAttribute("contenteditable")&&t.focus();var i=window.getSelection(),r=document.createRange();r.selectNodeContents(t),i.removeAllRanges(),i.addRange(r),e=i.toString()}return e}t.exports=s},function(t,e){function s(){}s.prototype={on:function(t,e,s){var i=this.e||(this.e={});return(i[t]||(i[t]=[])).push({fn:e,ctx:s}),this},once:function(t,e,s){var i=this;function r(){i.off(t,r),e.apply(s,arguments)}return r._=e,this.on(t,r,s)},emit:function(t){var e=[].slice.call(arguments,1),s=((this.e||(this.e={}))[t]||[]).slice(),i=0,r=s.length;for(i;i0&&void 0!==arguments[0]?arguments[0]:{};this.action=t.action,this.container=t.container,this.emitter=t.emitter,this.target=t.target,this.text=t.text,this.trigger=t.trigger,this.selectedText=""}},{key:"initSelection",value:function(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function(){var t=this,e="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return t.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[e?"right":"left"]="-9999px";var s=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=s+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=r()(this.fakeElem),this.copyText()}},{key:"removeFake",value:function(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function(){this.selectedText=r()(this.target),this.copyText()}},{key:"copyText",value:function(){var t=void 0;try{t=document.execCommand(this.action)}catch(e){t=!1}this.handleResult(t)}},{key:"handleResult",value:function(t){this.emitter.emit(t?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function(){this.trigger&&this.trigger.focus(),document.activeElement.blur(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function(){this.removeFake()}},{key:"action",set:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=t,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function(){return this._action}},{key:"target",set:function(t){if(void 0!==t){if(!t||"object"!==("undefined"===typeof t?"undefined":n(t))||1!==t.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&t.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(t.hasAttribute("readonly")||t.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=t}},get:function(){return this._target}}]),t}(),h=c,l=s(1),p=s.n(l),u=s(2),d=s.n(u),f="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"===typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},m=function(){function t(t,e){for(var s=0;s0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"===typeof t.action?t.action:this.defaultAction,this.target="function"===typeof t.target?t.target:this.defaultTarget,this.text="function"===typeof t.text?t.text:this.defaultText,this.container="object"===f(t.container)?t.container:document.body}},{key:"listenClick",value:function(t){var e=this;this.listener=d()(t,"click",(function(t){return e.onClick(t)}))}},{key:"onClick",value:function(t){var e=t.delegateTarget||t.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new h({action:this.action(e),target:this.target(e),text:this.text(e),container:this.container,trigger:e,emitter:this})}},{key:"defaultAction",value:function(t){return v("action",t)}},{key:"defaultTarget",value:function(t){var e=v("target",t);if(e)return document.querySelector(e)}},{key:"defaultText",value:function(t){return v("text",t)}},{key:"destroy",value:function(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],e="string"===typeof t?[t]:t,s=!!document.queryCommandSupported;return e.forEach((function(t){s=s&&!!document.queryCommandSupported(t)})),s}}]),e}(p.a);function v(t,e){var s="data-clipboard-"+t;if(e.hasAttribute(s))return e.getAttribute(s)}e["default"]=b}])["default"]}))},b575:function(t,e,s){var i,r,n,a,o,c,h,l,p=s("da84"),u=s("06cf").f,d=s("c6b6"),f=s("2cf4").set,m=s("1cdc"),y=p.MutationObserver||p.WebKitMutationObserver,g=p.process,x=p.Promise,b="process"==d(g),v=u(p,"queueMicrotask"),w=v&&v.value;w||(i=function(){var t,e;b&&(t=g.domain)&&t.exit();while(r){e=r.fn,r=r.next;try{e()}catch(s){throw r?a():n=void 0,s}}n=void 0,t&&t.enter()},b?a=function(){g.nextTick(i)}:y&&!m?(o=!0,c=document.createTextNode(""),new y(i).observe(c,{characterData:!0}),a=function(){c.data=o=!o}):x&&x.resolve?(h=x.resolve(void 0),l=h.then,a=function(){l.call(h,i)}):a=function(){f.call(p,i)}),t.exports=w||function(t){var e={fn:t,next:void 0};n&&(n.next=e),r||(r=e,a()),n=e}},b622:function(t,e,s){var i=s("da84"),r=s("5692"),n=s("5135"),a=s("90e3"),o=s("4930"),c=s("fdbf"),h=r("wks"),l=i.Symbol,p=c?l:l&&l.withoutSetter||a;t.exports=function(t){return n(h,t)||(o&&n(l,t)?h[t]=l[t]:h[t]=p("Symbol."+t)),h[t]}},b64b:function(t,e,s){var i=s("23e7"),r=s("7b0b"),n=s("df75"),a=s("d039"),o=a((function(){n(1)}));i({target:"Object",stat:!0,forced:o},{keys:function(t){return n(r(t))}})},b727:function(t,e,s){var i=s("0366"),r=s("44ad"),n=s("7b0b"),a=s("50c4"),o=s("65f0"),c=[].push,h=function(t){var e=1==t,s=2==t,h=3==t,l=4==t,p=6==t,u=5==t||p;return function(d,f,m,y){for(var g,x,b=n(d),v=r(b),w=i(f,m,3),P=a(v.length),T=0,E=y||o,A=e?E(d,P):s?E(d,0):void 0;P>T;T++)if((u||T in v)&&(g=v[T],x=w(g,T,b),t))if(e)A[T]=x;else if(x)switch(t){case 3:return!0;case 5:return g;case 6:return T;case 2:c.call(A,g)}else if(l)return!1;return p?-1:h||l?l:A}};t.exports={forEach:h(0),map:h(1),filter:h(2),some:h(3),every:h(4),find:h(5),findIndex:h(6)}},c04e:function(t,e,s){var i=s("861d");t.exports=function(t,e){if(!i(t))return t;var s,r;if(e&&"function"==typeof(s=t.toString)&&!i(r=s.call(t)))return r;if("function"==typeof(s=t.valueOf)&&!i(r=s.call(t)))return r;if(!e&&"function"==typeof(s=t.toString)&&!i(r=s.call(t)))return r;throw TypeError("Can't convert object to primitive value")}},c430:function(t,e){t.exports=!1},c6b6:function(t,e){var s={}.toString;t.exports=function(t){return s.call(t).slice(8,-1)}},c6cd:function(t,e,s){var i=s("da84"),r=s("ce4e"),n="__core-js_shared__",a=i[n]||r(n,{});t.exports=a},c740:function(t,e,s){"use strict";var i=s("23e7"),r=s("b727").findIndex,n=s("44d2"),a=s("ae40"),o="findIndex",c=!0,h=a(o);o in[]&&Array(1)[o]((function(){c=!1})),i({target:"Array",proto:!0,forced:c||!h},{findIndex:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}}),n(o)},c8ba:function(t,e){var s;s=function(){return this}();try{s=s||new Function("return this")()}catch(i){"object"===typeof window&&(s=window)}t.exports=s},c975:function(t,e,s){"use strict";var i=s("23e7"),r=s("4d64").indexOf,n=s("a640"),a=s("ae40"),o=[].indexOf,c=!!o&&1/[1].indexOf(1,-0)<0,h=n("indexOf"),l=a("indexOf",{ACCESSORS:!0,1:0});i({target:"Array",proto:!0,forced:c||!h||!l},{indexOf:function(t){return c?o.apply(this,arguments)||0:r(this,t,arguments.length>1?arguments[1]:void 0)}})},ca84:function(t,e,s){var i=s("5135"),r=s("fc6a"),n=s("4d64").indexOf,a=s("d012");t.exports=function(t,e){var s,o=r(t),c=0,h=[];for(s in o)!i(a,s)&&i(o,s)&&h.push(s);while(e.length>c)i(o,s=e[c++])&&(~n(h,s)||h.push(s));return h}},caad:function(t,e,s){"use strict";var i=s("23e7"),r=s("4d64").includes,n=s("44d2"),a=s("ae40"),o=a("indexOf",{ACCESSORS:!0,1:0});i({target:"Array",proto:!0,forced:!o},{includes:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}}),n("includes")},cc06:function(t,e,s){"use strict";function i(t,e,s,i){var r,n=!1,a=0;function o(){r&&clearTimeout(r)}function c(){o(),n=!0}function h(){for(var c=arguments.length,h=new Array(c),l=0;lt?d():!0!==e&&(r=setTimeout(i?f:d,void 0===i?t-u:t)))}return"boolean"!==typeof e&&(i=s,s=e,e=void 0),h.cancel=c,h}function r(t,e,s){return void 0===s?i(t,e,!1):i(t,s,!1!==e)}s.d(e,"a",(function(){return r}))},cc12:function(t,e,s){var i=s("da84"),r=s("861d"),n=i.document,a=r(n)&&r(n.createElement);t.exports=function(t){return a?n.createElement(t):{}}},cca6:function(t,e,s){var i=s("23e7"),r=s("60da");i({target:"Object",stat:!0,forced:Object.assign!==r},{assign:r})},cdf9:function(t,e,s){var i=s("825a"),r=s("861d"),n=s("f069");t.exports=function(t,e){if(i(t),r(e)&&e.constructor===t)return e;var s=n.f(t),a=s.resolve;return a(e),s.promise}},ce4e:function(t,e,s){var i=s("da84"),r=s("9112");t.exports=function(t,e){try{r(i,t,e)}catch(s){i[t]=e}return e}},d012:function(t,e){t.exports={}},d039:function(t,e){t.exports=function(t){try{return!!t()}catch(e){return!0}}},d066:function(t,e,s){var i=s("428f"),r=s("da84"),n=function(t){return"function"==typeof t?t:void 0};t.exports=function(t,e){return arguments.length<2?n(i[t])||n(r[t]):i[t]&&i[t][e]||r[t]&&r[t][e]}},d1e7:function(t,e,s){"use strict";var i={}.propertyIsEnumerable,r=Object.getOwnPropertyDescriptor,n=r&&!i.call({1:2},1);e.f=n?function(t){var e=r(this,t);return!!e&&e.enumerable}:i},d28b:function(t,e,s){var i=s("746f");i("iterator")},d2bb:function(t,e,s){var i=s("825a"),r=s("3bbe");t.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,s={};try{t=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set,t.call(s,[]),e=s instanceof Array}catch(n){}return function(s,n){return i(s),r(n),e?t.call(s,n):s.__proto__=n,s}}():void 0)},d3b7:function(t,e,s){var i=s("00ee"),r=s("6eeb"),n=s("b041");i||r(Object.prototype,"toString",n,{unsafe:!0})},d44e:function(t,e,s){var i=s("9bf2").f,r=s("5135"),n=s("b622"),a=n("toStringTag");t.exports=function(t,e,s){t&&!r(t=s?t:t.prototype,a)&&i(t,a,{configurable:!0,value:e})}},d60a:function(t,e){t.exports=function(t){return t&&"object"===typeof t&&"function"===typeof t.copy&&"function"===typeof t.fill&&"function"===typeof t.readUInt8}},d784:function(t,e,s){"use strict";s("ac1f");var i=s("6eeb"),r=s("d039"),n=s("b622"),a=s("9263"),o=s("9112"),c=n("species"),h=!r((function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$")})),l=function(){return"$0"==="a".replace(/./,"$0")}(),p=n("replace"),u=function(){return!!/./[p]&&""===/./[p]("a","$0")}(),d=!r((function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var s="ab".split(t);return 2!==s.length||"a"!==s[0]||"b"!==s[1]}));t.exports=function(t,e,s,p){var f=n(t),m=!r((function(){var e={};return e[f]=function(){return 7},7!=""[t](e)})),y=m&&!r((function(){var e=!1,s=/a/;return"split"===t&&(s={},s.constructor={},s.constructor[c]=function(){return s},s.flags="",s[f]=/./[f]),s.exec=function(){return e=!0,null},s[f](""),!e}));if(!m||!y||"replace"===t&&(!h||!l||u)||"split"===t&&!d){var g=/./[f],x=s(f,""[t],(function(t,e,s,i,r){return e.exec===a?m&&!r?{done:!0,value:g.call(e,s,i)}:{done:!0,value:t.call(s,e,i)}:{done:!1}}),{REPLACE_KEEPS_$0:l,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:u}),b=x[0],v=x[1];i(String.prototype,t,b),i(RegExp.prototype,f,2==e?function(t,e){return v.call(t,this,e)}:function(t){return v.call(t,this)})}p&&o(RegExp.prototype[f],"sham",!0)}},d81d:function(t,e,s){"use strict";var i=s("23e7"),r=s("b727").map,n=s("1dde"),a=s("ae40"),o=n("map"),c=a("map");i({target:"Array",proto:!0,forced:!o||!c},{map:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}})},da84:function(t,e,s){(function(e){var s=function(t){return t&&t.Math==Math&&t};t.exports=s("object"==typeof globalThis&&globalThis)||s("object"==typeof window&&window)||s("object"==typeof self&&self)||s("object"==typeof e&&e)||Function("return this")()}).call(this,s("c8ba"))},dbb4:function(t,e,s){var i=s("23e7"),r=s("83ab"),n=s("56ef"),a=s("fc6a"),o=s("06cf"),c=s("8418");i({target:"Object",stat:!0,sham:!r},{getOwnPropertyDescriptors:function(t){var e,s,i=a(t),r=o.f,h=n(i),l={},p=0;while(h.length>p)s=r(i,e=h[p++]),void 0!==s&&c(l,e,s);return l}})},ddb0:function(t,e,s){var i=s("da84"),r=s("fdbc"),n=s("e260"),a=s("9112"),o=s("b622"),c=o("iterator"),h=o("toStringTag"),l=n.values;for(var p in r){var u=i[p],d=u&&u.prototype;if(d){if(d[c]!==l)try{a(d,c,l)}catch(m){d[c]=l}if(d[h]||a(d,h,p),r[p])for(var f in n)if(d[f]!==n[f])try{a(d,f,n[f])}catch(m){d[f]=n[f]}}}},df75:function(t,e,s){var i=s("ca84"),r=s("7839");t.exports=Object.keys||function(t){return i(t,r)}},df7c:function(t,e,s){(function(t){function s(t,e){for(var s=0,i=t.length-1;i>=0;i--){var r=t[i];"."===r?t.splice(i,1):".."===r?(t.splice(i,1),s++):s&&(t.splice(i,1),s--)}if(e)for(;s--;s)t.unshift("..");return t}function i(t){"string"!==typeof t&&(t+="");var e,s=0,i=-1,r=!0;for(e=t.length-1;e>=0;--e)if(47===t.charCodeAt(e)){if(!r){s=e+1;break}}else-1===i&&(r=!1,i=e+1);return-1===i?"":t.slice(s,i)}function r(t,e){if(t.filter)return t.filter(e);for(var s=[],i=0;i=-1&&!i;n--){var a=n>=0?arguments[n]:t.cwd();if("string"!==typeof a)throw new TypeError("Arguments to path.resolve must be strings");a&&(e=a+"/"+e,i="/"===a.charAt(0))}return e=s(r(e.split("/"),(function(t){return!!t})),!i).join("/"),(i?"/":"")+e||"."},e.normalize=function(t){var i=e.isAbsolute(t),a="/"===n(t,-1);return t=s(r(t.split("/"),(function(t){return!!t})),!i).join("/"),t||i||(t="."),t&&a&&(t+="/"),(i?"/":"")+t},e.isAbsolute=function(t){return"/"===t.charAt(0)},e.join=function(){var t=Array.prototype.slice.call(arguments,0);return e.normalize(r(t,(function(t,e){if("string"!==typeof t)throw new TypeError("Arguments to path.join must be strings");return t})).join("/"))},e.relative=function(t,s){function i(t){for(var e=0;e=0;s--)if(""!==t[s])break;return e>s?[]:t.slice(e,s-e+1)}t=e.resolve(t).substr(1),s=e.resolve(s).substr(1);for(var r=i(t.split("/")),n=i(s.split("/")),a=Math.min(r.length,n.length),o=a,c=0;c=1;--n)if(e=t.charCodeAt(n),47===e){if(!r){i=n;break}}else r=!1;return-1===i?s?"/":".":s&&1===i?"/":t.slice(0,i)},e.basename=function(t,e){var s=i(t);return e&&s.substr(-1*e.length)===e&&(s=s.substr(0,s.length-e.length)),s},e.extname=function(t){"string"!==typeof t&&(t+="");for(var e=-1,s=0,i=-1,r=!0,n=0,a=t.length-1;a>=0;--a){var o=t.charCodeAt(a);if(47!==o)-1===i&&(r=!1,i=a+1),46===o?-1===e?e=a:1!==n&&(n=1):-1!==e&&(n=-1);else if(!r){s=a+1;break}}return-1===e||-1===i||0===n||1===n&&e===i-1&&e===s+1?"":t.slice(e,i)};var n="b"==="ab".substr(-1)?function(t,e,s){return t.substr(e,s)}:function(t,e,s){return e<0&&(e=t.length+e),t.substr(e,s)}}).call(this,s("4362"))},e017:function(t,e,s){(function(e){(function(e,s){t.exports=s()})(0,(function(){"use strict";var t=function(t){var e=t.id,s=t.viewBox,i=t.content;this.id=e,this.viewBox=s,this.content=i};t.prototype.stringify=function(){return this.content},t.prototype.toString=function(){return this.stringify()},t.prototype.destroy=function(){var t=this;["id","viewBox","content"].forEach((function(e){return delete t[e]}))};var s=function(t){var e=!!document.importNode,s=(new DOMParser).parseFromString(t,"image/svg+xml").documentElement;return e?document.importNode(s,!0):s};"undefined"!==typeof window?window:"undefined"!==typeof e||"undefined"!==typeof self&&self;function i(t,e){return e={exports:{}},t(e,e.exports),e.exports}var r=i((function(t,e){(function(e,s){t.exports=s()})(0,(function(){function t(t){var e=t&&"object"===typeof t;return e&&"[object RegExp]"!==Object.prototype.toString.call(t)&&"[object Date]"!==Object.prototype.toString.call(t)}function e(t){return Array.isArray(t)?[]:{}}function s(s,i){var r=i&&!0===i.clone;return r&&t(s)?n(e(s),s,i):s}function i(e,i,r){var a=e.slice();return i.forEach((function(i,o){"undefined"===typeof a[o]?a[o]=s(i,r):t(i)?a[o]=n(e[o],i,r):-1===e.indexOf(i)&&a.push(s(i,r))})),a}function r(e,i,r){var a={};return t(e)&&Object.keys(e).forEach((function(t){a[t]=s(e[t],r)})),Object.keys(i).forEach((function(o){t(i[o])&&e[o]?a[o]=n(e[o],i[o],r):a[o]=s(i[o],r)})),a}function n(t,e,n){var a=Array.isArray(e),o=n||{arrayMerge:i},c=o.arrayMerge||i;return a?Array.isArray(t)?c(t,e,n):s(e,n):r(t,e,n)}return n.all=function(t,e){if(!Array.isArray(t)||t.length<2)throw new Error("first argument should be an array with at least two elements");return t.reduce((function(t,s){return n(t,s,e)}))},n}))})),n=i((function(t,e){var s={svg:{name:"xmlns",uri:"http://www.w3.org/2000/svg"},xlink:{name:"xmlns:xlink",uri:"http://www.w3.org/1999/xlink"}};e.default=s,t.exports=e.default})),a=function(t){return Object.keys(t).map((function(e){var s=t[e].toString().replace(/"/g,""");return e+'="'+s+'"'})).join(" ")},o=n.svg,c=n.xlink,h={};h[o.name]=o.uri,h[c.name]=c.uri;var l=function(t,e){void 0===t&&(t="");var s=r(h,e||{}),i=a(s);return""+t+""},p=function(t){function e(){t.apply(this,arguments)}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var i={isMounted:{}};return i.isMounted.get=function(){return!!this.node},e.createFromExistingNode=function(t){return new e({id:t.getAttribute("id"),viewBox:t.getAttribute("viewBox"),content:t.outerHTML})},e.prototype.destroy=function(){this.isMounted&&this.unmount(),t.prototype.destroy.call(this)},e.prototype.mount=function(t){if(this.isMounted)return this.node;var e="string"===typeof t?document.querySelector(t):t,s=this.render();return this.node=s,e.appendChild(s),s},e.prototype.render=function(){var t=this.stringify();return s(l(t)).childNodes[0]},e.prototype.unmount=function(){this.node.parentNode.removeChild(this.node)},Object.defineProperties(e.prototype,i),e}(t);return p}))}).call(this,s("c8ba"))},e01a:function(t,e,s){"use strict";var i=s("23e7"),r=s("83ab"),n=s("da84"),a=s("5135"),o=s("861d"),c=s("9bf2").f,h=s("e893"),l=n.Symbol;if(r&&"function"==typeof l&&(!("description"in l.prototype)||void 0!==l().description)){var p={},u=function(){var t=arguments.length<1||void 0===arguments[0]?void 0:String(arguments[0]),e=this instanceof u?new l(t):void 0===t?l():l(t);return""===t&&(p[e]=!0),e};h(u,l);var d=u.prototype=l.prototype;d.constructor=u;var f=d.toString,m="Symbol(test)"==String(l("test")),y=/^Symbol\((.*)\)[^)]+$/;c(d,"description",{configurable:!0,get:function(){var t=o(this)?this.valueOf():this,e=f.call(t);if(a(p,t))return"";var s=m?e.slice(7,-1):e.replace(y,"$1");return""===s?void 0:s}}),i({global:!0,forced:!0},{Symbol:u})}},e163:function(t,e,s){var i=s("5135"),r=s("7b0b"),n=s("f772"),a=s("e177"),o=n("IE_PROTO"),c=Object.prototype;t.exports=a?Object.getPrototypeOf:function(t){return t=r(t),i(t,o)?t[o]:"function"==typeof t.constructor&&t instanceof t.constructor?t.constructor.prototype:t instanceof Object?c:null}},e177:function(t,e,s){var i=s("d039");t.exports=!i((function(){function t(){}return t.prototype.constructor=null,Object.getPrototypeOf(new t)!==t.prototype}))},e260:function(t,e,s){"use strict";var i=s("fc6a"),r=s("44d2"),n=s("3f8c"),a=s("69f3"),o=s("7dd0"),c="Array Iterator",h=a.set,l=a.getterFor(c);t.exports=o(Array,"Array",(function(t,e){h(this,{type:c,target:i(t),index:0,kind:e})}),(function(){var t=l(this),e=t.target,s=t.kind,i=t.index++;return!e||i>=e.length?(t.target=void 0,{value:void 0,done:!0}):"keys"==s?{value:i,done:!1}:"values"==s?{value:e[i],done:!1}:{value:[i,e[i]],done:!1}}),"values"),n.Arguments=n.Array,r("keys"),r("values"),r("entries")},e2cc:function(t,e,s){var i=s("6eeb");t.exports=function(t,e,s){for(var r in e)i(t,r,e[r],s);return t}},e439:function(t,e,s){var i=s("23e7"),r=s("d039"),n=s("fc6a"),a=s("06cf").f,o=s("83ab"),c=r((function(){a(1)})),h=!o||c;i({target:"Object",stat:!0,forced:h,sham:!o},{getOwnPropertyDescriptor:function(t,e){return a(n(t),e)}})},e538:function(t,e,s){var i=s("b622");e.f=i},e667:function(t,e){t.exports=function(t){try{return{error:!1,value:t()}}catch(e){return{error:!0,value:e}}}},e6cf:function(t,e,s){"use strict";var i,r,n,a,o=s("23e7"),c=s("c430"),h=s("da84"),l=s("d066"),p=s("fea9"),u=s("6eeb"),d=s("e2cc"),f=s("d44e"),m=s("2626"),y=s("861d"),g=s("1c0b"),x=s("19aa"),b=s("c6b6"),v=s("8925"),w=s("2266"),P=s("1c7e"),T=s("4840"),E=s("2cf4").set,A=s("b575"),S=s("cdf9"),C=s("44de"),k=s("f069"),N=s("e667"),I=s("69f3"),O=s("94ca"),D=s("b622"),M=s("2d00"),L=D("species"),_="Promise",R=I.get,j=I.set,F=I.getterFor(_),B=p,U=h.TypeError,q=h.document,V=h.process,H=l("fetch"),z=k.f,W=z,K="process"==b(V),$=!!(q&&q.createEvent&&h.dispatchEvent),X="unhandledrejection",G="rejectionhandled",Y=0,J=1,Q=2,Z=1,tt=2,et=O(_,(function(){var t=v(B)!==String(B);if(!t){if(66===M)return!0;if(!K&&"function"!=typeof PromiseRejectionEvent)return!0}if(c&&!B.prototype["finally"])return!0;if(M>=51&&/native code/.test(B))return!1;var e=B.resolve(1),s=function(t){t((function(){}),(function(){}))},i=e.constructor={};return i[L]=s,!(e.then((function(){}))instanceof s)})),st=et||!P((function(t){B.all(t)["catch"]((function(){}))})),it=function(t){var e;return!(!y(t)||"function"!=typeof(e=t.then))&&e},rt=function(t,e,s){if(!e.notified){e.notified=!0;var i=e.reactions;A((function(){var r=e.value,n=e.state==J,a=0;while(i.length>a){var o,c,h,l=i[a++],p=n?l.ok:l.fail,u=l.resolve,d=l.reject,f=l.domain;try{p?(n||(e.rejection===tt&&ct(t,e),e.rejection=Z),!0===p?o=r:(f&&f.enter(),o=p(r),f&&(f.exit(),h=!0)),o===l.promise?d(U("Promise-chain cycle")):(c=it(o))?c.call(o,u,d):u(o)):d(r)}catch(m){f&&!h&&f.exit(),d(m)}}e.reactions=[],e.notified=!1,s&&!e.rejection&&at(t,e)}))}},nt=function(t,e,s){var i,r;$?(i=q.createEvent("Event"),i.promise=e,i.reason=s,i.initEvent(t,!1,!0),h.dispatchEvent(i)):i={promise:e,reason:s},(r=h["on"+t])?r(i):t===X&&C("Unhandled promise rejection",s)},at=function(t,e){E.call(h,(function(){var s,i=e.value,r=ot(e);if(r&&(s=N((function(){K?V.emit("unhandledRejection",i,t):nt(X,t,i)})),e.rejection=K||ot(e)?tt:Z,s.error))throw s.value}))},ot=function(t){return t.rejection!==Z&&!t.parent},ct=function(t,e){E.call(h,(function(){K?V.emit("rejectionHandled",t):nt(G,t,e.value)}))},ht=function(t,e,s,i){return function(r){t(e,s,r,i)}},lt=function(t,e,s,i){e.done||(e.done=!0,i&&(e=i),e.value=s,e.state=Q,rt(t,e,!0))},pt=function(t,e,s,i){if(!e.done){e.done=!0,i&&(e=i);try{if(t===s)throw U("Promise can't be resolved itself");var r=it(s);r?A((function(){var i={done:!1};try{r.call(s,ht(pt,t,i,e),ht(lt,t,i,e))}catch(n){lt(t,i,n,e)}})):(e.value=s,e.state=J,rt(t,e,!1))}catch(n){lt(t,{done:!1},n,e)}}};et&&(B=function(t){x(this,B,_),g(t),i.call(this);var e=R(this);try{t(ht(pt,this,e),ht(lt,this,e))}catch(s){lt(this,e,s)}},i=function(t){j(this,{type:_,done:!1,notified:!1,parent:!1,reactions:[],rejection:!1,state:Y,value:void 0})},i.prototype=d(B.prototype,{then:function(t,e){var s=F(this),i=z(T(this,B));return i.ok="function"!=typeof t||t,i.fail="function"==typeof e&&e,i.domain=K?V.domain:void 0,s.parent=!0,s.reactions.push(i),s.state!=Y&&rt(this,s,!1),i.promise},catch:function(t){return this.then(void 0,t)}}),r=function(){var t=new i,e=R(t);this.promise=t,this.resolve=ht(pt,t,e),this.reject=ht(lt,t,e)},k.f=z=function(t){return t===B||t===n?new r(t):W(t)},c||"function"!=typeof p||(a=p.prototype.then,u(p.prototype,"then",(function(t,e){var s=this;return new B((function(t,e){a.call(s,t,e)})).then(t,e)}),{unsafe:!0}),"function"==typeof H&&o({global:!0,enumerable:!0,forced:!0},{fetch:function(t){return S(B,H.apply(h,arguments))}}))),o({global:!0,wrap:!0,forced:et},{Promise:B}),f(B,_,!1,!0),m(_),n=l(_),o({target:_,stat:!0,forced:et},{reject:function(t){var e=z(this);return e.reject.call(void 0,t),e.promise}}),o({target:_,stat:!0,forced:c||et},{resolve:function(t){return S(c&&this===n?B:this,t)}}),o({target:_,stat:!0,forced:st},{all:function(t){var e=this,s=z(e),i=s.resolve,r=s.reject,n=N((function(){var s=g(e.resolve),n=[],a=0,o=1;w(t,(function(t){var c=a++,h=!1;n.push(void 0),o++,s.call(e,t).then((function(t){h||(h=!0,n[c]=t,--o||i(n))}),r)})),--o||i(n)}));return n.error&&r(n.value),s.promise},race:function(t){var e=this,s=z(e),i=s.reject,r=N((function(){var r=g(e.resolve);w(t,(function(t){r.call(e,t).then(s.resolve,i)}))}));return r.error&&i(r.value),s.promise}})},e893:function(t,e,s){var i=s("5135"),r=s("56ef"),n=s("06cf"),a=s("9bf2");t.exports=function(t,e){for(var s=r(e),o=a.f,c=n.f,h=0;h'});l.a.add(c);t["default"]=c},"064a":function(e,t,a){"use strict";a.r(t);var o=a("e017"),n=a.n(o),i=a("21a1"),l=a.n(i),c=new n.a({id:"icon-select",use:"icon-select-usage",viewBox:"0 0 1024 1024",content:''});l.a.add(c);t["default"]=c},"0f05":function(e,t,a){},"0f88":function(e,t,a){"use strict";a.r(t),t["default"]={"list-type":function(e,t,a){var o=[],n=t.__config__;return"picture-card"===t["list-type"]?o.push(e("i",{class:"el-icon-plus"})):o.push(e("el-button",{attrs:{size:"small",type:"primary",icon:"el-icon-upload"}},[n.buttonText])),n.showTip&&o.push(e("div",{slot:"tip",class:"el-upload__tip"},["只能上传不超过 ",n.fileSize,n.sizeUnit," 的",t.accept,"文件"])),o}}},"128d":function(e,t,a){"use strict";a.r(t);var o=a("e017"),n=a.n(o),i=a("21a1"),l=a.n(i),c=new n.a({id:"icon-textarea",use:"icon-textarea-usage",viewBox:"0 0 1024 1024",content:''});l.a.add(c);t["default"]=c},"167d":function(e,t,a){"use strict";a.r(t),t["default"]={prepend:function(e,t,a){return e("template",{slot:"prepend"},[t.__slot__[a]])},append:function(e,t,a){return e("template",{slot:"append"},[t.__slot__[a]])}}},"1fce":function(e,t,a){"use strict";a.r(t);var o=a("e017"),n=a.n(o),i=a("21a1"),l=a.n(i),c=new n.a({id:"icon-number",use:"icon-number-usage",viewBox:"0 0 1024 1024",content:''});l.a.add(c);t["default"]=c},"235f":function(e,t,a){"use strict";a.r(t);var o=a("e017"),n=a.n(o),i=a("21a1"),l=a.n(i),c=new n.a({id:"icon-date",use:"icon-date-usage",viewBox:"0 0 1024 1024",content:''});l.a.add(c);t["default"]=c},2384:function(e,t,a){"use strict";a.r(t);var o=a("e017"),n=a.n(o),i=a("21a1"),l=a.n(i),c=new n.a({id:"icon-switch",use:"icon-switch-usage",viewBox:"0 0 1024 1024",content:''});l.a.add(c);t["default"]=c},"2a3d":function(e,t,a){"use strict";a.r(t);var o=a("e017"),n=a.n(o),i=a("21a1"),l=a.n(i),c=new n.a({id:"icon-password",use:"icon-password-usage",viewBox:"0 0 1024 1024",content:''});l.a.add(c);t["default"]=c},"2cfa":function(e,t,a){"use strict";a.r(t);a("4160"),a("159b");t["default"]={options:function(e,t,a){var o=[];return t.__slot__.options.forEach((function(a){"button"===t.__config__.optionType?o.push(e("el-radio-button",{attrs:{label:a.value}},[a.label])):o.push(e("el-radio",{attrs:{label:a.value,border:t.border}},[a.label]))})),o}}},"2db0":function(e,t,a){},"2dba":function(e,t,a){"use strict";var o=a("6f47"),n=a.n(o);n.a},"31c6":function(e,t,a){"use strict";var o,n=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("textarea",{staticStyle:{visibility:"hidden"},attrs:{id:e.tinymceId}})},i=[],l=(a("99af"),a("d3b7"),a("25f0"),a("c88b")),c=a("5f72"),r=a.n(c);function s(e){if(o)e(o);else{var t=r.a.Loading.service({fullscreen:!0,lock:!0,text:"富文本资源加载中...",spinner:"el-icon-loading",background:"rgba(255, 255, 255, 0.5)"});Object(l["a"])("https://lib.baomitu.com/tinymce/5.3.2/tinymce.min.js",(function(){t.close(),o=tinymce,e(o)}))}}var u=["advlist anchor autolink autosave code codesample directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textpattern visualblocks visualchars wordcount"],d=["code searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote removeformat subscript superscript codesample hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen"],_=a("cc06"),p=1,m={props:{id:{type:String,default:function(){return 1e4===p&&(p=1),"tinymce".concat(+new Date).concat(p++)}},value:{default:""}},data:function(){return{tinymceId:this.id}},mounted:function(){var e=this;s((function(t){a("afc4");var o={selector:"#".concat(e.tinymceId),language:"zh_CN",menubar:"file edit insert view format table",plugins:u,toolbar:d,height:300,branding:!1,object_resizing:!1,end_container_on_empty_block:!0,powerpaste_word_import:"clean",code_dialog_height:450,code_dialog_width:1e3,advlist_bullet_styles:"square",advlist_number_styles:"default",default_link_target:"_blank",link_title:!1,nonbreaking_force_tab:!0};o=Object.assign(o,e.$attrs),o.init_instance_callback=function(t){e.value&&t.setContent(e.value),e.vModel(t)},t.init(o)}))},destroyed:function(){this.destroyTinymce()},methods:{vModel:function(e){var t=this,a=Object(_["a"])(250,e.setContent);this.$watch("value",(function(t,o){e&&t!==o&&t!==e.getContent()&&("string"!==typeof t&&(t=t.toString()),a.call(e,t))})),e.on("change keyup undo redo",(function(){t.$emit("input",e.getContent())}))},destroyTinymce:function(){if(window.tinymce){var e=window.tinymce.get(this.tinymceId);e&&e.destroy()}}}},f=m,v=a("2877"),h=Object(v["a"])(f,n,i,!1,null,null,null);t["a"]=h.exports},"3add":function(e,t,a){"use strict";a.r(t);var o=a("e017"),n=a.n(o),i=a("21a1"),l=a.n(i),c=new n.a({id:"icon-time",use:"icon-time-usage",viewBox:"0 0 1024 1024",content:''});l.a.add(c);t["default"]=c},4758:function(e,t,a){"use strict";a("4160"),a("b64b"),a("d3b7"),a("ac1f"),a("5319"),a("159b"),a("ddb0");var o=a("5530"),n=a("ed08"),i={},l=a("9977"),c=l.keys()||[];function r(e,t){var a=this;e.props.value=t,e.on.input=function(e){a.$emit("input",e)}}function s(e,t,a){var o=i[t.__config__.tag];o&&Object.keys(o).forEach((function(n){var i=o[n];t.__slot__&&t.__slot__[n]&&a.push(i(e,t,n))}))}function u(e){var t=this;["on","nativeOn"].forEach((function(a){var o=Object.keys(e[a]||{});o.forEach((function(o){var n=e[a][o];"string"===typeof n&&(e[a][o]=function(e){return t.$emit(n,e)})}))}))}function d(e,t){var a=this;Object.keys(e).forEach((function(n){var i=e[n];"__vModel__"===n?r.call(a,t,e.__config__.defaultValue):t[n]?t[n]=Object(o["a"])(Object(o["a"])({},t[n]),i):t.attrs[n]=i})),_(t)}function _(e){delete e.attrs.__config__,delete e.attrs.__slot__,delete e.attrs.__methods__}function p(){return{attrs:{},props:{},nativeOn:{},on:{},style:{}}}c.forEach((function(e){var t=e.replace(/^\.\/(.*)\.\w+$/,"$1"),a=l(e).default;i[t]=a})),t["a"]={props:{conf:{type:Object,required:!0}},render:function(e){var t=p(),a=Object(n["b"])(this.conf),o=[];return s.call(this,e,a,o),u.call(this,a),d.call(this,a,t),e(this.conf.__config__.tag,t,o)}}},"475a":function(e,t,a){},"4ed4":function(e,t,a){"use strict";a.r(t);var o=a("e017"),n=a.n(o),i=a("21a1"),l=a.n(i),c=new n.a({id:"icon-button",use:"icon-button-usage",viewBox:"0 0 1024 1024",content:''});l.a.add(c);t["default"]=c},"51ff":function(e,t,a){var o={"./button.svg":"4ed4","./cascader.svg":"a393","./checkbox.svg":"8963","./color.svg":"03ab","./component.svg":"56d6","./date-range.svg":"e6df","./date.svg":"235f","./input.svg":"81d6","./number.svg":"1fce","./password.svg":"2a3d","./radio.svg":"d8dc","./rate.svg":"6786","./rich-text.svg":"c630","./row.svg":"c95d","./select.svg":"064a","./slider.svg":"eb1c","./switch.svg":"2384","./textarea.svg":"128d","./time-range.svg":"861c","./time.svg":"3add","./upload.svg":"9d82"};function n(e){var t=i(e);return a(t)}function i(e){if(!a.o(o,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return o[e]}n.keys=function(){return Object.keys(o)},n.resolve=i,e.exports=n,n.id="51ff"},"56d6":function(e,t,a){"use strict";a.r(t);var o=a("e017"),n=a.n(o),i=a("21a1"),l=a.n(i),c=new n.a({id:"icon-component",use:"icon-component-usage",viewBox:"0 0 1024 1024",content:''});l.a.add(c);t["default"]=c},"5f72":function(e,t){e.exports=ELEMENT},"627e":function(e,t,a){},6389:function(e,t){e.exports=VueRouter},"66a2":function(e,t,a){"use strict";var o=a("475a"),n=a.n(o);n.a},6786:function(e,t,a){"use strict";a.r(t);var o=a("e017"),n=a.n(o),i=a("21a1"),l=a.n(i),c=new n.a({id:"icon-rate",use:"icon-rate-usage",viewBox:"0 0 1069 1024",content:''});l.a.add(c);t["default"]=c},6828:function(e,t,a){"use strict";var o=a("627e"),n=a.n(o);n.a},"6f47":function(e,t,a){},"7f29":function(e,t,a){"use strict";a.r(t);a("4160"),a("159b");t["default"]={options:function(e,t,a){var o=[];return t.__slot__.options.forEach((function(t){o.push(e("el-option",{attrs:{label:t.label,value:t.value,disabled:t.disabled}}))})),o}}},"80e9":function(e,t,a){"use strict";var o=a("fca0"),n=a.n(o);n.a},"81d6":function(e,t,a){"use strict";a.r(t);var o=a("e017"),n=a.n(o),i=a("21a1"),l=a.n(i),c=new n.a({id:"icon-input",use:"icon-input-usage",viewBox:"0 0 1024 1024",content:''});l.a.add(c);t["default"]=c},"861c":function(e,t,a){"use strict";a.r(t);var o=a("e017"),n=a.n(o),i=a("21a1"),l=a.n(i),c=new n.a({id:"icon-time-range",use:"icon-time-range-usage",viewBox:"0 0 1024 1024",content:''});l.a.add(c);t["default"]=c},8963:function(e,t,a){"use strict";a.r(t);var o=a("e017"),n=a.n(o),i=a("21a1"),l=a.n(i),c=new n.a({id:"icon-checkbox",use:"icon-checkbox-usage",viewBox:"0 0 1024 1024",content:''});l.a.add(c);t["default"]=c},"8a8a":function(e,t,a){"use strict";a.r(t);a("e260"),a("e6cf"),a("cca6"),a("a79d");var o,n,i=a("8bbf"),l=a.n(i),c=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",[a("router-view")],1)},r=[],s={mounted:function(){var e=document.querySelector("#pre-loader");e.style.display="none",document.body.ondrop=function(e){e.preventDefault(),e.stopPropagation()}}},u=s,d=a("2877"),_=Object(d["a"])(u,c,r,!1,null,null,null),p=_.exports,m=(a("d3b7"),a("6389")),f=a.n(m),v=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticClass:"container"},[a("div",{staticClass:"left-board"},[a("div",{staticClass:"logo-wrapper"},[a("div",{staticClass:"logo"},[a("img",{attrs:{src:e.logo,alt:"logo"}}),e._v(" 表单构建 ")])]),a("el-scrollbar",{staticClass:"left-scrollbar"},[a("div",{staticClass:"components-list"},e._l(e.leftComponents,(function(t,o){return a("div",{key:o},[a("div",{staticClass:"components-title"},[a("svg-icon",{attrs:{"icon-class":"component"}}),e._v(" "+e._s(t.title)+" ")],1),a("draggable",{staticClass:"components-draggable",attrs:{list:t.list,group:{name:"componentsGroup",pull:"clone",put:!1},clone:e.cloneComponent,draggable:".components-item",sort:!1},on:{end:e.onEnd}},e._l(t.list,(function(t,o){return a("div",{key:o,staticClass:"components-item",on:{click:function(a){return e.addComponent(t)}}},[a("div",{staticClass:"components-body"},[a("svg-icon",{attrs:{"icon-class":t.__config__.tagIcon}}),e._v(" "+e._s(t.__config__.label)+" ")],1)])})),0)],1)})),0)])],1),a("div",{staticClass:"center-board"},[a("div",{staticClass:"action-bar"},[a("el-button",{attrs:{icon:"el-icon-video-play",type:"text"},on:{click:e.run}},[e._v(" 运行 ")]),a("el-button",{attrs:{icon:"el-icon-view",type:"text"},on:{click:e.showJson}},[e._v(" 查看json ")]),a("el-button",{attrs:{icon:"el-icon-download",type:"text"},on:{click:e.download}},[e._v(" 导出vue文件 ")]),a("el-button",{staticClass:"copy-btn-main",attrs:{icon:"el-icon-document-copy",type:"text"},on:{click:e.copy}},[e._v(" 复制代码 ")]),a("el-button",{staticClass:"delete-btn",attrs:{icon:"el-icon-delete",type:"text"},on:{click:e.empty}},[e._v(" 清空 ")])],1),a("el-scrollbar",{staticClass:"center-scrollbar"},[a("el-row",{staticClass:"center-board-row",attrs:{gutter:e.formConf.gutter}},[a("el-form",{attrs:{size:e.formConf.size,"label-position":e.formConf.labelPosition,disabled:e.formConf.disabled,"label-width":e.formConf.labelWidth+"px"}},[a("draggable",{staticClass:"drawing-board",attrs:{list:e.drawingList,animation:340,group:"componentsGroup"}},e._l(e.drawingList,(function(t,o){return a("draggable-item",{key:t.renderKey,attrs:{"drawing-list":e.drawingList,element:t,index:o,"active-id":e.activeId,"form-conf":e.formConf},on:{activeItem:e.activeFormItem,copyItem:e.drawingItemCopy,deleteItem:e.drawingItemDelete}})})),1),a("div",{directives:[{name:"show",rawName:"v-show",value:!e.drawingList.length,expression:"!drawingList.length"}],staticClass:"empty-info"},[e._v(" 从左侧拖入或点选组件进行表单设计 ")])],1)],1)],1)],1),a("right-panel",{attrs:{"active-data":e.activeData,"form-conf":e.formConf,"show-field":!!e.drawingList.length},on:{"tag-change":e.tagChange}}),a("form-drawer",{attrs:{visible:e.drawerVisible,"form-data":e.formData,size:"100%","generate-conf":e.generateConf},on:{"update:visible":function(t){e.drawerVisible=t}}}),a("json-drawer",{attrs:{size:"60%",visible:e.jsonDrawerVisible,"json-str":JSON.stringify(e.formData)},on:{"update:visible":function(t){e.jsonDrawerVisible=t},refresh:e.refreshJson}}),a("code-type-dialog",{attrs:{visible:e.dialogVisible,title:"选择生成类型","show-file-name":e.showFileName},on:{"update:visible":function(t){e.dialogVisible=t},confirm:e.generate}}),a("input",{attrs:{id:"copyNode",type:"hidden"}})],1)},h=[],b=(a("c740"),a("4160"),a("d81d"),a("a434"),a("b64b"),a("ac1f"),a("5319"),a("159b"),a("53ca")),g=a("5530"),w=a("310e"),y=a.n(w),D=a("cc06"),x=a("21a6"),k=a("b311"),C=a.n(k),O=a("4758"),M=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",[a("el-drawer",e._g(e._b({on:{opened:e.onOpen,close:e.onClose}},"el-drawer",e.$attrs,!1),e.$listeners),[a("div",{staticStyle:{height:"100%"}},[a("el-row",{staticStyle:{height:"100%",overflow:"auto"}},[a("el-col",{staticClass:"left-editor",attrs:{md:24,lg:12}},[a("div",{staticClass:"setting",attrs:{title:"资源引用"},on:{click:e.showResource}},[a("el-badge",{staticClass:"item",attrs:{"is-dot":!!e.resources.length}},[a("i",{staticClass:"el-icon-setting"})])],1),a("el-tabs",{staticClass:"editor-tabs",attrs:{type:"card"},model:{value:e.activeTab,callback:function(t){e.activeTab=t},expression:"activeTab"}},[a("el-tab-pane",{attrs:{name:"html"}},[a("span",{attrs:{slot:"label"},slot:"label"},["html"===e.activeTab?a("i",{staticClass:"el-icon-edit"}):a("i",{staticClass:"el-icon-document"}),e._v(" template ")])]),a("el-tab-pane",{attrs:{name:"js"}},[a("span",{attrs:{slot:"label"},slot:"label"},["js"===e.activeTab?a("i",{staticClass:"el-icon-edit"}):a("i",{staticClass:"el-icon-document"}),e._v(" script ")])]),a("el-tab-pane",{attrs:{name:"css"}},[a("span",{attrs:{slot:"label"},slot:"label"},["css"===e.activeTab?a("i",{staticClass:"el-icon-edit"}):a("i",{staticClass:"el-icon-document"}),e._v(" css ")])])],1),a("div",{directives:[{name:"show",rawName:"v-show",value:"html"===e.activeTab,expression:"activeTab==='html'"}],staticClass:"tab-editor",attrs:{id:"editorHtml"}}),a("div",{directives:[{name:"show",rawName:"v-show",value:"js"===e.activeTab,expression:"activeTab==='js'"}],staticClass:"tab-editor",attrs:{id:"editorJs"}}),a("div",{directives:[{name:"show",rawName:"v-show",value:"css"===e.activeTab,expression:"activeTab==='css'"}],staticClass:"tab-editor",attrs:{id:"editorCss"}})],1),a("el-col",{staticClass:"right-preview",attrs:{md:24,lg:12}},[a("div",{staticClass:"action-bar",style:{"text-align":"left"}},[a("span",{staticClass:"bar-btn",on:{click:e.runCode}},[a("i",{staticClass:"el-icon-refresh"}),e._v(" 刷新 ")]),a("span",{staticClass:"bar-btn",on:{click:e.exportFile}},[a("i",{staticClass:"el-icon-download"}),e._v(" 导出vue文件 ")]),a("span",{ref:"copyBtn",staticClass:"bar-btn copy-btn"},[a("i",{staticClass:"el-icon-document-copy"}),e._v(" 复制代码 ")]),a("span",{staticClass:"bar-btn delete-btn",on:{click:function(t){return e.$emit("update:visible",!1)}}},[a("i",{staticClass:"el-icon-circle-close"}),e._v(" 关闭 ")])]),a("iframe",{directives:[{name:"show",rawName:"v-show",value:e.isIframeLoaded,expression:"isIframeLoaded"}],ref:"previewPage",staticClass:"result-wrapper",attrs:{frameborder:"0",src:"preview.html"},on:{load:e.iframeLoad}}),a("div",{directives:[{name:"show",rawName:"v-show",value:!e.isIframeLoaded,expression:"!isIframeLoaded"},{name:"loading",rawName:"v-loading",value:!0,expression:"true"}],staticClass:"result-wrapper"})])],1)],1)]),a("resource-dialog",{attrs:{visible:e.resourceVisible,"origin-resource":e.resources},on:{"update:visible":function(t){e.resourceVisible=t},save:e.setResource}})],1)},E=[],I=(a("99af"),a("8a79"),a("1861")),L=(a("a15b"),a("45fc"),a("b0c0"),a("beaa"));function j(e){return'\n '.concat(e,'\n
\n 取消\n 确定\n
\n
')}function T(e){return"")}function z(e){return"
\ No newline at end of file diff --git a/stop.sh b/stop.sh new file mode 100644 index 0000000..6dd9dc4 --- /dev/null +++ b/stop.sh @@ -0,0 +1,4 @@ +#!/bin/bash +killall go-admin # kill go-admin service +echo "stop go-admin success" +ps -aux | grep go-admin \ No newline at end of file diff --git a/template/api_migrate.template b/template/api_migrate.template new file mode 100644 index 0000000..6f39164 --- /dev/null +++ b/template/api_migrate.template @@ -0,0 +1,326 @@ +package version + +import ( + "gorm.io/gorm" + "runtime" + "time" + + "github.com/go-admin-team/go-admin-core/sdk/pkg" + + "go-admin/cmd/migrate/migration" + common "go-admin/common/models" +) + +type Menu struct { + MenuId int `json:"menuId" gorm:"primaryKey;autoIncrement"` + MenuName string `json:"menuName" gorm:"size:128;"` + Title string `json:"title" gorm:"size:128;"` + Icon string `json:"icon" gorm:"size:128;"` + Path string `json:"path" gorm:"size:128;"` + Paths string `json:"paths" gorm:"size:128;"` + MenuType string `json:"menuType" gorm:"size:1;"` + Action string `json:"action" gorm:"size:16;"` + Permission string `json:"permission" gorm:"size:255;"` + ParentId int `json:"parentId" gorm:"size:11;"` + NoCache bool `json:"noCache" gorm:"size:8;"` + Breadcrumb string `json:"breadcrumb" gorm:"size:255;"` + Component string `json:"component" gorm:"size:255;"` + Sort int `json:"sort" gorm:"size:4;"` + Visible string `json:"visible" gorm:"size:1;"` + CreateBy string `json:"createBy" gorm:"size:128;"` + UpdateBy string `json:"updateBy" gorm:"size:128;"` + IsFrame string `json:"isFrame" gorm:"size:1;DEFAULT:0;"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` +} + +func (Menu) TableName() string { + return "sys_menu" +} + +func init() { + _, fileName, _, _ := runtime.Caller(0) + migration.Migrate.SetVersion(migration.GetFilename(fileName), _{{.GenerateTime}}Test) +} + +func _{{.GenerateTime}}Test(db *gorm.DB, version string) error { + return db.Transaction(func(tx *gorm.DB) error { + + timeNow := pkg.GetCurrentTime() + Mmenu := Menu{} + Mmenu.MenuName = "{{.TBName}}Manage" + Mmenu.Title = "{{.TableComment}}" + Mmenu.Icon = "pass" + Mmenu.Path = "/{{.TBName}}" + Mmenu.MenuType = "M" + Mmenu.Action = "无" + Mmenu.ParentId = 0 + Mmenu.NoCache = false + Mmenu.Component = "Layout" + Mmenu.Sort = 0 + Mmenu.Visible = "0" + Mmenu.IsFrame = "0" + Mmenu.CreateBy = "1" + Mmenu.UpdateBy = "1" + Mmenu.CreatedAt = timeNow + Mmenu.UpdatedAt = timeNow + // Mmenu.MenuId, err = Mmenu.Create(db) + err := tx.Create(&Mmenu).Error + if err != nil { + return err + } + Cmenu := Menu{} + Cmenu.MenuName = "{{.TBName}}" + Cmenu.Title = "{{.TableComment}}" + Cmenu.Icon = "pass" + Cmenu.Path = "{{.TBName}}" + Cmenu.MenuType = "C" + Cmenu.Action = "无" + Cmenu.Permission = "{{.PackageName}}:{{.BusinessName}}:list" + Cmenu.ParentId = Mmenu.MenuId + Cmenu.NoCache = false + Cmenu.Component = "/{{.BusinessName}}/index" + Cmenu.Sort = 0 + Cmenu.Visible = "0" + Cmenu.IsFrame = "0" + Cmenu.CreateBy = "1" + Cmenu.UpdateBy = "1" + Cmenu.CreatedAt = timeNow + Cmenu.UpdatedAt = timeNow + // Cmenu.MenuId, err = Cmenu.Create(db) + err = tx.Create(&Cmenu).Error + if err != nil { + return err + } + + MList := Menu{} + MList.MenuName = "" + MList.Title = "分页获取{{.TableComment}}" + MList.Icon = "" + MList.Path = "{{.TBName}}" + MList.MenuType = "F" + MList.Action = "无" + MList.Permission = "{{.PackageName}}:{{.BusinessName}}:query" + MList.ParentId = Cmenu.MenuId + MList.NoCache = false + MList.Sort = 0 + MList.Visible = "0" + MList.IsFrame = "0" + MList.CreateBy = "1" + MList.UpdateBy = "1" + MList.CreatedAt = timeNow + MList.UpdatedAt = timeNow + // MList.MenuId, err = MList.Create(db) + err = tx.Create(&MList).Error + if err != nil { + return err + } + + MCreate := Menu{} + MCreate.MenuName = "" + MCreate.Title = "创建{{.TableComment}}" + MCreate.Icon = "" + MCreate.Path = "{{.TBName}}" + MCreate.MenuType = "F" + MCreate.Action = "无" + MCreate.Permission = "{{.PackageName}}:{{.BusinessName}}:add" + MCreate.ParentId = Cmenu.MenuId + MCreate.NoCache = false + MCreate.Sort = 0 + MCreate.Visible = "0" + MCreate.IsFrame = "0" + MCreate.CreateBy = "1" + MCreate.UpdateBy = "1" + MCreate.CreatedAt = timeNow + MCreate.UpdatedAt = timeNow + // MCreate.MenuId, err = MCreate.Create(db) + err = tx.Create(&MCreate).Error + if err != nil { + return err + } + + MUpdate := Menu{} + MUpdate.MenuName = "" + MUpdate.Title = "修改{{.TableComment}}" + MUpdate.Icon = "" + MUpdate.Path = "{{.TBName}}" + MUpdate.MenuType = "F" + MUpdate.Action = "无" + MUpdate.Permission ="{{.PackageName}}:{{.BusinessName}}:edit" + MUpdate.ParentId = Cmenu.MenuId + MUpdate.NoCache = false + MUpdate.Sort = 0 + MUpdate.Visible = "0" + MUpdate.IsFrame = "0" + MUpdate.CreateBy = "1" + MUpdate.UpdateBy = "1" + MUpdate.CreatedAt = timeNow + MUpdate.UpdatedAt = timeNow + // MUpdate.MenuId, err = MUpdate.Create(db) + err = tx.Create(&MUpdate).Error + if err != nil { + return err + } + + MDelete := Menu{} + MDelete.MenuName = "" + MDelete.Title = "删除{{.TableComment}}" + MDelete.Icon = "" + MDelete.Path = "{{.TBName}}" + MDelete.MenuType = "F" + MDelete.Action = "无" + MDelete.Permission = "{{.PackageName}}:{{.BusinessName}}:remove" + MDelete.ParentId = Cmenu.MenuId + MDelete.NoCache = false + MDelete.Sort = 0 + MDelete.Visible = "0" + MDelete.IsFrame = "0" + MDelete.CreateBy = "1" + MDelete.UpdateBy = "1" + MDelete.CreatedAt = timeNow + MDelete.UpdatedAt = timeNow + // MDelete.MenuId, err = MDelete.Create(db) + err = tx.Create(&MDelete).Error + if err != nil { + return err + } + + var InterfaceId = 63 + Amenu := Menu{} + Amenu.MenuName = "{{.TBName}}" + Amenu.Title = "{{.TableComment}}" + Amenu.Icon = "bug" + Amenu.Path = "{{.TBName}}" + Amenu.MenuType = "M" + Amenu.Action = "无" + Amenu.ParentId = InterfaceId + Amenu.NoCache = false + Amenu.Sort = 0 + Amenu.Visible = "1" + Amenu.IsFrame = "0" + Amenu.CreateBy = "1" + Amenu.UpdateBy = "1" + Amenu.CreatedAt = timeNow + Amenu.UpdatedAt = timeNow + // Amenu.MenuId, err = Amenu.Create(db) + err = tx.Create(&Amenu).Error + if err != nil { + return err + } + + AList := Menu{} + AList.MenuName = "" + AList.Title = "分页获取{{.TableComment}}" + AList.Icon = "bug" + AList.Path = "/api/v1/{{.ModuleName}}" + AList.MenuType = "A" + AList.Action = "GET" + AList.ParentId = Amenu.MenuId + AList.NoCache = false + AList.Sort = 0 + AList.Visible = "1" + AList.IsFrame = "0" + AList.CreateBy = "1" + AList.UpdateBy = "1" + AList.CreatedAt = timeNow + AList.UpdatedAt = timeNow + // AList.MenuId, err = AList.Create(db) + err = tx.Create(&AList).Error + if err != nil { + return err + } + + AGet := Menu{} + AGet.MenuName = "" + AGet.Title = "根据id获取{{.TableComment}}" + AGet.Icon = "bug" + AGet.Path = "/api/v1/{{.ModuleName}}/:id" + AGet.MenuType = "A" + AGet.Action = "GET" + AGet.ParentId = Amenu.MenuId + AGet.NoCache = false + AGet.Sort = 0 + AGet.Visible = "1" + AGet.IsFrame = "0" + AGet.CreateBy = "1" + AGet.UpdateBy = "1" + AGet.CreatedAt = timeNow + AGet.UpdatedAt = timeNow + // AGet.MenuId, err = AGet.Create(db) + err = tx.Create(&AGet).Error + if err != nil { + return err + } + + ACreate := Menu{} + ACreate.MenuName = "" + ACreate.Title = "创建{{.TableComment}}" + ACreate.Icon = "bug" + ACreate.Path = "/api/v1/{{.ModuleName}}" + ACreate.MenuType = "A" + ACreate.Action = "POST" + ACreate.ParentId = Amenu.MenuId + ACreate.NoCache = false + ACreate.Sort = 0 + ACreate.Visible = "1" + ACreate.IsFrame = "0" + ACreate.CreateBy = "1" + ACreate.UpdateBy = "1" + ACreate.CreatedAt = timeNow + ACreate.UpdatedAt = timeNow + // ACreate.MenuId, err = ACreate.Create(db) + err = tx.Create(&ACreate).Error + if err != nil { + return err + } + + AUpdate := Menu{} + AUpdate.MenuName = "" + AUpdate.Title = "修改{{.TableComment}}" + AUpdate.Icon = "bug" + AUpdate.Path = "/api/v1/{{.ModuleName}}/:id" + AUpdate.MenuType = "A" + AUpdate.Action = "PUT" + AUpdate.ParentId = Amenu.MenuId + AUpdate.NoCache = false + AUpdate.Sort = 0 + AUpdate.Visible = "1" + AUpdate.IsFrame = "0" + AUpdate.CreateBy = "1" + AUpdate.UpdateBy = "1" + AUpdate.CreatedAt = timeNow + AUpdate.UpdatedAt = timeNow + // AUpdate.MenuId, err = AUpdate.Create(db) + err = tx.Create(&AUpdate).Error + if err != nil { + return err + } + + ADelete := Menu{} + ADelete.MenuName = "" + ADelete.Title = "删除{{.TableComment}}" + ADelete.Icon = "bug" + ADelete.Path = "/api/v1/{{.ModuleName}}" + ADelete.MenuType = "A" + ADelete.Action = "DELETE" + ADelete.ParentId = Amenu.MenuId + ADelete.NoCache = false + ADelete.Sort = 0 + ADelete.Visible = "1" + ADelete.IsFrame = "0" + ADelete.CreateBy = "1" + ADelete.UpdateBy = "1" + ADelete.CreatedAt = timeNow + ADelete.UpdatedAt = timeNow + //ADelete.MenuId, err = ADelete.Create(db) + err = tx.Create(&ADelete).Error + if err != nil { + return err + } + + return tx.Create(&common.Migration{ + Version: version, + }).Error + }) +} \ No newline at end of file diff --git a/template/cmd_api.template b/template/cmd_api.template new file mode 100644 index 0000000..f58e37f --- /dev/null +++ b/template/cmd_api.template @@ -0,0 +1,8 @@ +package api + +import "go-admin/app/{{.appName}}/router" + +func init() { + //注册路由 fixme 其他应用的路由,在本目录新建文件放在init方法 + AppRouters = append(AppRouters, router.InitRouter) +} \ No newline at end of file diff --git a/template/migrate.template b/template/migrate.template new file mode 100644 index 0000000..f30de78 --- /dev/null +++ b/template/migrate.template @@ -0,0 +1,40 @@ +package {{.Package}} + +import ( + "gorm.io/gorm" + "runtime" + + "go-admin/cmd/migrate/migration" + common "go-admin/common/models" +) + +func init() { + _, fileName, _, _ := runtime.Caller(0) + migration.Migrate.SetVersion(migration.GetFilename(fileName), _{{.GenerateTime}}Test) +} + +func _{{.GenerateTime}}Test(db *gorm.DB, version string) error { + return db.Transaction(func(tx *gorm.DB) error { + + // TODO: 这里开始写入要变更的内容 + + // TODO: 例如 修改表字段 使用过程中请删除此段代码 + //err := tx.Migrator().RenameColumn(&models.SysConfig{}, "config_id", "id") + //if err != nil { + // return err + //} + + // TODO: 例如 新增表结构 使用过程中请删除此段代码 + //err = tx.Debug().Migrator().AutoMigrate( + // new(models.CasbinRule), + // ) + //if err != nil { + // return err + //} + + + return tx.Create(&common.Migration{ + Version: version, + }).Error + }) +} diff --git a/template/router.template b/template/router.template new file mode 100644 index 0000000..b11e9b9 --- /dev/null +++ b/template/router.template @@ -0,0 +1,75 @@ +package router + + +import ( + "github.com/gin-gonic/gin" + _ "github.com/gin-gonic/gin" + log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk" + // "github.com/go-admin-team/go-admin-core/sdk/pkg" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + common "go-admin/common/middleware" + "os" +) + +var ( + routerNoCheckRole = make([]func(*gin.RouterGroup), 0) + routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0) +) + +// InitRouter 路由初始化 +func InitRouter() { + var r *gin.Engine + h := sdk.Runtime.GetEngine() + if h == nil { + h = gin.New() + sdk.Runtime.SetEngine(h) + } + switch h.(type) { + case *gin.Engine: + r = h.(*gin.Engine) + default: + log.Fatal("not support other engine") + os.Exit(-1) + } + + // the jwt middleware + authMiddleware, err := common.AuthInit() + if err != nil { + log.Fatalf("JWT Init Error, %s", err.Error()) + } + + // 注册业务路由 + InitBusinessRouter(r, authMiddleware) +} + +func InitBusinessRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine { + + // 无需认证的路由 + noCheckRoleRouter(r) + // 需要认证的路由 + checkRoleRouter(r, authMiddleware) + + return r +} + +// noCheckRoleRouter 无需认证的路由 +func noCheckRoleRouter(r *gin.Engine) { + // 可根据业务需求来设置接口版本 + v := r.Group("/api/v1") + + for _, f := range routerNoCheckRole { + f(v) + } +} + +// checkRoleRouter 需要认证的路由 +func checkRoleRouter(r *gin.Engine, authMiddleware *jwtauth.GinJWTMiddleware) { + // 可根据业务需求来设置接口版本 + v := r.Group("/api/v1") + + for _, f := range routerCheckRole { + f(v, authMiddleware) + } +} diff --git a/template/v4/actions/router_check_role.go.template b/template/v4/actions/router_check_role.go.template new file mode 100644 index 0000000..3c3c069 --- /dev/null +++ b/template/v4/actions/router_check_role.go.template @@ -0,0 +1,31 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + + "go-admin/app/{{.PackageName}}/models" + "go-admin/app/{{.PackageName}}/service/dto" + "go-admin/common/actions" + "go-admin/common/middleware" +) + +func init() { + routerCheckRole = append(routerCheckRole, register{{.ClassName}}Router) +} + +// 需认证的路由代码 +func register{{.ClassName}}Router(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + r := v1.Group("/{{.ModuleName}}").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + model := &models.{{.ClassName}}{} + r.GET("", actions.PermissionAction(), actions.IndexAction(model, new(dto.{{.ClassName}}Search), func() interface{} { + list := make([]models.{{.ClassName}}, 0) + return &list + })) + r.GET("/:id", actions.PermissionAction(), actions.ViewAction(new(dto.{{.ClassName}}ById), nil)) + r.POST("", actions.CreateAction(new(dto.{{.ClassName}}Control))) + r.PUT("/:id", actions.PermissionAction(), actions.UpdateAction(new(dto.{{.ClassName}}Control))) + r.DELETE("", actions.PermissionAction(), actions.DeleteAction(new(dto.{{.ClassName}}ById))) + } +} diff --git a/template/v4/actions/router_no_check_role.go.template b/template/v4/actions/router_no_check_role.go.template new file mode 100644 index 0000000..0154557 --- /dev/null +++ b/template/v4/actions/router_no_check_role.go.template @@ -0,0 +1,30 @@ +package router + +import ( + "github.com/gin-gonic/gin" + + "go-admin/app/{{.PackageName}}/middleware" + "go-admin/app/{{.PackageName}}/models" + "go-admin/app/{{.PackageName}}/service/dto" + "go-admin/common/actions" +) + +func init() { + routerNoCheckRole = append(routerNoCheckRole, register{{.ClassName}}Router) +} + +// 无需认证的路由代码 +func register{{.ClassName}}Router(v1 *gin.RouterGroup) { + r := v1.Group("/{{.ModuleName}}") + { + model := &models.{{.ClassName}}{} + r.GET("", actions.IndexAction(model, new(dto.{{.ClassName}}Search), func() interface{} { + list := make([]models.{{.ClassName}}, 0) + return &list + })) + r.GET("/:id", actions.ViewAction(new(dto.{{.ClassName}}ById), nil)) + r.POST("", actions.CreateAction(new(dto.{{.ClassName}}Control))) + r.PUT("/:id", actions.UpdateAction(new(dto.{{.ClassName}}Control))) + r.DELETE("", actions.DeleteAction(new(dto.{{.ClassName}}ById))) + } +} diff --git a/template/v4/dto.go.template b/template/v4/dto.go.template new file mode 100644 index 0000000..428b89a --- /dev/null +++ b/template/v4/dto.go.template @@ -0,0 +1,151 @@ +package dto + +import ( + {{- $bb := false -}} + {{- range .Columns -}} + {{- $z := .IsQuery -}} + {{- if ($z) -}} + {{- if eq .GoType "time.Time" -}}{{- $bb = true -}}{{- end -}} + {{- end -}} + {{- end -}} + {{- range .Columns -}} + {{- if eq .GoField "CreatedAt" -}} + {{- else if eq .GoField "UpdatedAt" -}} + {{- else if eq .GoField "DeletedAt" -}} + {{- else -}} + {{- if eq .GoType "time.Time" -}}{{- $bb = true -}}{{- end -}} + {{- end -}} + {{- end -}} + {{- if eq $bb true }} + "time" + {{- end }} + + "go-admin/app/{{.PackageName}}/models" + "go-admin/common/dto" + common "go-admin/common/models" +) + +type {{.ClassName}}GetPageReq struct { + dto.Pagination `search:"-"` + {{- $tablename := .TBName -}} + {{- range .Columns -}} + {{$z := .IsQuery}} + {{- if ($z) }} + {{.GoField}} {{.GoType}} `form:"{{.JsonField}}" search:"type:{{if eq .QueryType "EQ"}}exact{{ else if eq .QueryType "NE"}}iexact{{ else if eq .QueryType "LIKE"}}contains{{ else if eq .QueryType "GT"}}gt{{ else if eq .QueryType "GTE"}}gte{{ else if eq .QueryType "LT"}}lt{{ else if eq .QueryType "LTE"}}lte{{- end }};column:{{.ColumnName}};table:{{$tablename}}" comment:"{{.ColumnComment}}"` + {{- end }} + {{- end }} + {{.ClassName}}Order +} + +type {{.ClassName}}Order struct { + {{ $tablename := .TBName }} + {{- range .Columns -}} + {{.GoField}} string `form:"{{.JsonField}}Order" search:"type:order;column:{{.ColumnName}};table:{{$tablename}}"` + {{ end }} +} + +func (m *{{.ClassName}}GetPageReq) GetNeedSearch() interface{} { + return *m +} + +type {{.ClassName}}InsertReq struct { + {{- range .Columns -}} + {{$x := .Pk}} + {{- if ($x) }} + {{.GoField}} {{.GoType}} `json:"-" comment:"{{.ColumnComment}}"` // {{.ColumnComment}} + {{- else if eq .GoField "CreatedAt" -}} + {{- else if eq .GoField "UpdatedAt" -}} + {{- else if eq .GoField "DeletedAt" -}} + {{- else if eq .GoField "CreateBy" -}} + {{- else if eq .GoField "UpdateBy" -}} + {{- else }} + {{.GoField}} {{.GoType}} `json:"{{.JsonField}}" comment:"{{.ColumnComment}}"` + {{- end -}} + {{- end }} + common.ControlBy +} + +func (s *{{.ClassName}}InsertReq) Generate(model *models.{{.ClassName}}) { + {{- range .Columns -}} + {{$x := .Pk}} + {{- if ($x) }} + if s.{{.GoField}} == 0 { + model.Model = common.Model{ {{.GoField}}: s.{{.GoField}} } + } + {{- else if eq .GoField "CreatedAt" -}} + {{- else if eq .GoField "UpdatedAt" -}} + {{- else if eq .GoField "DeletedAt" -}} + {{- else if eq .GoField "CreateBy"}} + model.{{.GoField}} = s.{{.GoField}} // 添加这而,需要记录是被谁创建的 + {{- else if eq .GoField "UpdateBy" -}} + {{- else }} + model.{{.GoField}} = s.{{.GoField}} + {{- end -}} + {{- end }} +} + +func (s *{{.ClassName}}InsertReq) GetId() interface{} { + return s.{{.PkGoField}} +} + +type {{.ClassName}}UpdateReq struct { + {{- range .Columns -}} + {{$x := .Pk}} + {{- if ($x) }} + {{.GoField}} {{.GoType}} `uri:"{{.JsonField}}" comment:"{{.ColumnComment}}"` // {{.ColumnComment}} + {{- else if eq .GoField "CreatedAt" -}} + {{- else if eq .GoField "UpdatedAt" -}} + {{- else if eq .GoField "DeletedAt" -}} + {{- else if eq .GoField "CreateBy" -}} + {{- else if eq .GoField "UpdateBy" -}} + {{- else }} + {{.GoField}} {{.GoType}} `json:"{{.JsonField}}" comment:"{{.ColumnComment}}"` + {{- end -}} + {{- end }} + common.ControlBy +} + +func (s *{{.ClassName}}UpdateReq) Generate(model *models.{{.ClassName}}) { + {{- range .Columns -}} + {{$x := .Pk}} + {{- if ($x) }} + if s.{{.GoField}} == 0 { + model.Model = common.Model{ {{.GoField}}: s.{{.GoField}} } + } + {{- else if eq .GoField "CreatedAt" -}} + {{- else if eq .GoField "UpdatedAt" -}} + {{- else if eq .GoField "DeletedAt" -}} + {{- else if eq .GoField "CreateBy" -}} + {{- else if eq .GoField "UpdateBy"}} + model.{{.GoField}} = s.{{.GoField}} // 添加这而,需要记录是被谁更新的 + {{- else }} + model.{{.GoField}} = s.{{.GoField}} + {{- end -}} + {{- end }} +} + +func (s *{{.ClassName}}UpdateReq) GetId() interface{} { + return s.{{.PkGoField}} +} + +// {{.ClassName}}GetReq 功能获取请求参数 +type {{.ClassName}}GetReq struct { + {{- range .Columns -}} + {{$x := .Pk}} + {{- if ($x) }} + {{.GoField}} {{.GoType}} `uri:"{{.JsonField}}"` + {{- end }} + {{- end }} +} +func (s *{{.ClassName}}GetReq) GetId() interface{} { + return s.{{.PkGoField}} +} + +// {{.ClassName}}DeleteReq 功能删除请求参数 +type {{.ClassName}}DeleteReq struct { + Ids []int `json:"ids"` +} + +func (s *{{.ClassName}}DeleteReq) GetId() interface{} { + return s.Ids +} diff --git a/template/v4/js.go.template b/template/v4/js.go.template new file mode 100644 index 0000000..db3d4a2 --- /dev/null +++ b/template/v4/js.go.template @@ -0,0 +1,47 @@ +import request from '@/utils/request' + +// 查询{{.ClassName}}列表 +export function list{{.ClassName}}(query) { + return request({ + url: '/api/v1/{{.ModuleName}}', + method: 'get', + params: query + }) +} + +// 查询{{.ClassName}}详细 +export function get{{.ClassName}} ({{.PkJsonField}}) { + return request({ + url: '/api/v1/{{.ModuleName}}/' + {{.PkJsonField}}, + method: 'get' + }) +} + + +// 新增{{.ClassName}} +export function add{{.ClassName}}(data) { + return request({ + url: '/api/v1/{{.ModuleName}}', + method: 'post', + data: data + }) +} + +// 修改{{.ClassName}} +export function update{{.ClassName}}(data) { + return request({ + url: '/api/v1/{{.ModuleName}}/'+data.{{.PkJsonField}}, + method: 'put', + data: data + }) +} + +// 删除{{.ClassName}} +export function del{{.ClassName}}(data) { + return request({ + url: '/api/v1/{{.ModuleName}}', + method: 'delete', + data: data + }) +} + diff --git a/template/v4/model.go.template b/template/v4/model.go.template new file mode 100644 index 0000000..2f56123 --- /dev/null +++ b/template/v4/model.go.template @@ -0,0 +1,55 @@ +package models + +import ( + {{- $bb := false -}} + {{- range .Columns -}} + {{- $z := .IsQuery -}} + {{- if ($z) -}} + {{- if eq .GoType "time.Time" -}}{{- $bb = true -}}{{- end -}} + {{- end -}} + {{- end -}} + {{- range .Columns -}} + {{- if eq .GoField "CreatedAt" -}} + {{- else if eq .GoField "UpdatedAt" -}} + {{- else if eq .GoField "DeletedAt" -}} + {{- else -}} + {{- if eq .GoType "time.Time" -}}{{- $bb = true -}}{{- end -}} + {{- end -}} + {{- end -}} + {{- if eq $bb true }} + "time" + {{- end }} + + "go-admin/common/models" + +) + +type {{.ClassName}} struct { + models.Model + {{ range .Columns -}} + {{$x := .Pk}} + {{- if ($x) }} + {{- else if eq .GoField "CreatedAt" -}} + {{- else if eq .GoField "UpdatedAt" -}} + {{- else if eq .GoField "DeletedAt" -}} + {{- else if eq .GoField "CreateBy" -}} + {{- else if eq .GoField "UpdateBy" -}} + {{- else }} + {{.GoField}} {{.GoType}} `json:"{{.JsonField}}" gorm:"type:{{.ColumnType}};comment:{{- if eq .ColumnComment "" -}}{{.GoField}}{{- else -}}{{.ColumnComment}}{{end -}}"` {{end -}} + {{- end }} + models.ModelTime + models.ControlBy +} + +func ({{.ClassName}}) TableName() string { + return "{{.TBName}}" +} + +func (e *{{.ClassName}}) Generate() models.ActiveRecord { + o := *e + return &o +} + +func (e *{{.ClassName}}) GetId() interface{} { + return e.{{.PkGoField}} +} \ No newline at end of file diff --git a/template/v4/no_actions/apis.go.template b/template/v4/no_actions/apis.go.template new file mode 100644 index 0000000..7878776 --- /dev/null +++ b/template/v4/no_actions/apis.go.template @@ -0,0 +1,198 @@ +package apis + +import ( + "fmt" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + + "go-admin/app/{{.PackageName}}/models" + "go-admin/app/{{.PackageName}}/service" + "go-admin/app/{{.PackageName}}/service/dto" + "go-admin/common/actions" +) + +type {{.ClassName}} struct { + api.Api +} + +// GetPage 获取{{.TableComment}}列表 +// @Summary 获取{{.TableComment}}列表 +// @Description 获取{{.TableComment}}列表 +// @Tags {{.TableComment}} +{{- $tablename := .TBName -}} +{{- range .Columns -}} +{{$z := .IsQuery}} +{{- if ($z) }} +// @Param {{.JsonField}} query {{.GoType}} false "{{.ColumnComment}}" +{{- end -}} +{{- end }} +// @Param pageSize query int false "页条数" +// @Param pageIndex query int false "页码" +// @Success 200 {object} response.Response{data=response.Page{list=[]models.{{.ClassName}}}} "{"code": 200, "data": [...]}" +// @Router /api/v1/{{.ModuleName}} [get] +// @Security Bearer +func (e {{.ClassName}}) GetPage(c *gin.Context) { + req := dto.{{.ClassName}}GetPageReq{} + s := service.{{.ClassName}}{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + p := actions.GetPermissionFromContext(c) + list := make([]models.{{.ClassName}}, 0) + var count int64 + + err = s.GetPage(&req, p, &list, &count) + if err != nil { + e.Error(500, err, fmt.Sprintf("获取{{.TableComment}}失败,\r\n失败信息 %s", err.Error())) + return + } + + e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") +} + +// Get 获取{{.TableComment}} +// @Summary 获取{{.TableComment}} +// @Description 获取{{.TableComment}} +// @Tags {{.TableComment}} +// @Param id path int false "id" +// @Success 200 {object} response.Response{data=models.{{.ClassName}}} "{"code": 200, "data": [...]}" +// @Router /api/v1/{{.ModuleName}}/{id} [get] +// @Security Bearer +func (e {{.ClassName}}) Get(c *gin.Context) { + req := dto.{{.ClassName}}GetReq{} + s := service.{{.ClassName}}{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + var object models.{{.ClassName}} + + p := actions.GetPermissionFromContext(c) + err = s.Get(&req, p, &object) + if err != nil { + e.Error(500, err, fmt.Sprintf("获取{{.TableComment}}失败,\r\n失败信息 %s", err.Error())) + return + } + + e.OK( object, "查询成功") +} + +// Insert 创建{{.TableComment}} +// @Summary 创建{{.TableComment}} +// @Description 创建{{.TableComment}} +// @Tags {{.TableComment}} +// @Accept application/json +// @Product application/json +// @Param data body dto.{{.ClassName}}InsertReq true "data" +// @Success 200 {object} response.Response "{"code": 200, "message": "添加成功"}" +// @Router /api/v1/{{.ModuleName}} [post] +// @Security Bearer +func (e {{.ClassName}}) Insert(c *gin.Context) { + req := dto.{{.ClassName}}InsertReq{} + s := service.{{.ClassName}}{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + // 设置创建人 + req.SetCreateBy(user.GetUserId(c)) + + err = s.Insert(&req) + if err != nil { + e.Error(500, err, fmt.Sprintf("创建{{.TableComment}}失败,\r\n失败信息 %s", err.Error())) + return + } + + e.OK(req.GetId(), "创建成功") +} + +// Update 修改{{.TableComment}} +// @Summary 修改{{.TableComment}} +// @Description 修改{{.TableComment}} +// @Tags {{.TableComment}} +// @Accept application/json +// @Product application/json +// @Param id path int true "id" +// @Param data body dto.{{.ClassName}}UpdateReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}" +// @Router /api/v1/{{.ModuleName}}/{id} [put] +// @Security Bearer +func (e {{.ClassName}}) Update(c *gin.Context) { + req := dto.{{.ClassName}}UpdateReq{} + s := service.{{.ClassName}}{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + req.SetUpdateBy(user.GetUserId(c)) + p := actions.GetPermissionFromContext(c) + + err = s.Update(&req, p) + if err != nil { + e.Error(500, err, fmt.Sprintf("修改{{.TableComment}}失败,\r\n失败信息 %s", err.Error())) + return + } + e.OK( req.GetId(), "修改成功") +} + +// Delete 删除{{.TableComment}} +// @Summary 删除{{.TableComment}} +// @Description 删除{{.TableComment}} +// @Tags {{.TableComment}} +// @Param data body dto.{{.ClassName}}DeleteReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}" +// @Router /api/v1/{{.ModuleName}} [delete] +// @Security Bearer +func (e {{.ClassName}}) Delete(c *gin.Context) { + s := service.{{.ClassName}}{} + req := dto.{{.ClassName}}DeleteReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + // req.SetUpdateBy(user.GetUserId(c)) + p := actions.GetPermissionFromContext(c) + + err = s.Remove(&req, p) + if err != nil { + e.Error(500, err, fmt.Sprintf("删除{{.TableComment}}失败,\r\n失败信息 %s", err.Error())) + return + } + e.OK( req.GetId(), "删除成功") +} diff --git a/template/v4/no_actions/router_check_role.go.template b/template/v4/no_actions/router_check_role.go.template new file mode 100644 index 0000000..f8a3c3a --- /dev/null +++ b/template/v4/no_actions/router_check_role.go.template @@ -0,0 +1,27 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + + "go-admin/app/{{.PackageName}}/apis" + "go-admin/common/middleware" + "go-admin/common/actions" +) + +func init() { + routerCheckRole = append(routerCheckRole, register{{.ClassName}}Router) +} + +// register{{.ClassName}}Router +func register{{.ClassName}}Router(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.{{.ClassName}}{} + r := v1.Group("/{{.ModuleName}}").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + r.GET("", actions.PermissionAction(), api.GetPage) + r.GET("/:id", actions.PermissionAction(), api.Get) + r.POST("", api.Insert) + r.PUT("/:id", actions.PermissionAction(), api.Update) + r.DELETE("", api.Delete) + } +} \ No newline at end of file diff --git a/template/v4/no_actions/router_no_check_role.go.template b/template/v4/no_actions/router_no_check_role.go.template new file mode 100644 index 0000000..fc26fe6 --- /dev/null +++ b/template/v4/no_actions/router_no_check_role.go.template @@ -0,0 +1,25 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + + "go-admin/app/{{.PackageName}}/apis" +) + +func init() { + routerCheckRole = append(routerCheckRole, register{{.ClassName}}Router) +} + +// register{{.ClassName}}Router +func register{{.ClassName}}Router(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.{{.ClassName}}{} + r := v1.Group("/{{.ModuleName}}").Use(authMiddleware.MiddlewareFunc()) + { + r.GET("", api.GetPage) + r.GET("/:id", api.Get) + r.POST("", api.Insert) + r.PUT("/:id", api.Update) + r.DELETE("", api.Delete) + } +} \ No newline at end of file diff --git a/template/v4/no_actions/service.go.template b/template/v4/no_actions/service.go.template new file mode 100644 index 0000000..84e8886 --- /dev/null +++ b/template/v4/no_actions/service.go.template @@ -0,0 +1,109 @@ +package service + +import ( + "errors" + + "github.com/go-admin-team/go-admin-core/sdk/service" + "gorm.io/gorm" + + "go-admin/app/{{.PackageName}}/models" + "go-admin/app/{{.PackageName}}/service/dto" + "go-admin/common/actions" + cDto "go-admin/common/dto" +) + +type {{.ClassName}} struct { + service.Service +} + +// GetPage 获取{{.ClassName}}列表 +func (e *{{.ClassName}}) GetPage(c *dto.{{.ClassName}}GetPageReq, p *actions.DataPermission, list *[]models.{{.ClassName}}, count *int64) error { + var err error + var data models.{{.ClassName}} + + err = e.Orm.Model(&data). + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), + actions.Permission(data.TableName(), p), + ). + Find(list).Limit(-1).Offset(-1). + Count(count).Error + if err != nil { + e.Log.Errorf("{{.ClassName}}Service GetPage error:%s \r\n", err) + return err + } + return nil +} + +// Get 获取{{.ClassName}}对象 +func (e *{{.ClassName}}) Get(d *dto.{{.ClassName}}GetReq, p *actions.DataPermission, model *models.{{.ClassName}}) error { + var data models.{{.ClassName}} + + err := e.Orm.Model(&data). + Scopes( + actions.Permission(data.TableName(), p), + ). + First(model, d.GetId()).Error + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = errors.New("查看对象不存在或无权查看") + e.Log.Errorf("Service Get{{.ClassName}} error:%s \r\n", err) + return err + } + if err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + return nil +} + +// Insert 创建{{.ClassName}}对象 +func (e *{{.ClassName}}) Insert(c *dto.{{.ClassName}}InsertReq) error { + var err error + var data models.{{.ClassName}} + c.Generate(&data) + err = e.Orm.Create(&data).Error + if err != nil { + e.Log.Errorf("{{.ClassName}}Service Insert error:%s \r\n", err) + return err + } + return nil +} + +// Update 修改{{.ClassName}}对象 +func (e *{{.ClassName}}) Update(c *dto.{{.ClassName}}UpdateReq, p *actions.DataPermission) error { + var err error + var data = models.{{.ClassName}}{} + e.Orm.Scopes( + actions.Permission(data.TableName(), p), + ).First(&data, c.GetId()) + c.Generate(&data) + + db := e.Orm.Save(&data) + if err = db.Error; err != nil { + e.Log.Errorf("{{.ClassName}}Service Save error:%s \r\n", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + } + return nil +} + +// Remove 删除{{.ClassName}} +func (e *{{.ClassName}}) Remove(d *dto.{{.ClassName}}DeleteReq, p *actions.DataPermission) error { + var data models.{{.ClassName}} + + db := e.Orm.Model(&data). + Scopes( + actions.Permission(data.TableName(), p), + ).Delete(&data, d.GetId()) + if err := db.Error; err != nil { + e.Log.Errorf("Service Remove{{.ClassName}} error:%s \r\n", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权删除该数据") + } + return nil +} diff --git a/template/v4/vue.go.template b/template/v4/vue.go.template new file mode 100644 index 0000000..ff70016 --- /dev/null +++ b/template/v4/vue.go.template @@ -0,0 +1,485 @@ +{{$tableComment:=.TableComment}} + + + diff --git a/test/api.go.template b/test/api.go.template new file mode 100644 index 0000000..1ae26ca --- /dev/null +++ b/test/api.go.template @@ -0,0 +1,126 @@ +package apis + +import ( +"github.com/gin-gonic/gin" +"github.com/gin-gonic/gin/binding" +"go-admin/models" +"github.com/go-admin-team/go-admin-core/sdk/pkg" +"go-admin/utils" +"net/http" +) + +// @Summary 配置列表数据 +// @Description 获取JSON +// @Tags 配置 +// @Param configKey query string false "configKey" +// @Param configName query string false "configName" +// @Param configType query string false "configType" +// @Param pageSize query int false "页条数" +// @Param pageIndex query int false "页码" +// @Success 200 {object} app.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/configList [get] +// @Security Bearer +func Get{{.ClassName}}List(c *gin.Context) { +var data models.{{.ClassName}} +var err error +var pageSize = 10 +var pageIndex = 1 + +if size := c.Request.FormValue("pageSize"); size != "" { +pageSize = pkg.StrToInt(err, size) +} + +if index := c.Request.FormValue("pageIndex"); index != "" { +pageIndex = pkg.StrToInt(err, index) +} + +{{ range .Columns -}} + {{$z := .IsQuery}} + {{- if ($z) -}} + data.{{.GoField}} = c.Request.FormValue("{{.JsonField}}") + {{ end }} +{{- end -}} + +data.DataScope = utils.GetUserIdStr(c) +result, count, err := data.GetPage(pageSize, pageIndex) +pkg.HasError(err, "", -1) + +var mp = make(map[string]interface{}, 3) +mp["list"] = result +mp["count"] = count +mp["pageIndex"] = pageIndex +mp["pageIndex"] = pageSize + +var res app.Response +res.Data = mp + +c.JSON(http.StatusOK, res.ReturnOK()) +} + +// @Summary 获取配置 +// @Description 获取JSON +// @Tags 配置 +// @Param configId path int true "配置编码" +// @Success 200 {object} app.Response "{"code": 200, "data": [...]}" +// @Router /api/v1/config/{configId} [get] +// @Security Bearer +func Get{{.ClassName}}(c *gin.Context) { +var data models.{{.ClassName}} +data.{{.PkGoField}}, _ = utils.StringToInt(c.Param("{{.PkJsonField}}")) +result, err := data.Get() +pkg.HasError(err, "抱歉未找到相关信息", -1) + +var res app.Response +res.Data = result + +c.JSON(http.StatusOK, res.ReturnOK()) +} + +// @Summary 添加配置 +// @Description 获取JSON +// @Tags 配置 +// @Accept application/json +// @Product application/json +// @Param data body models.{{.ClassName}} true "data" +// @Success 200 {string} string "{"code": 200, "message": "添加成功"}" +// @Success 200 {string} string "{"code": -1, "message": "添加失败"}" +// @Router /api/v1/dict/data [post] +// @Security Bearer +func Insert{{.ClassName}}(c *gin.Context) { +var data models.{{.ClassName}} +err := c.BindWith(&data, binding.JSON) +data.CreateBy = utils.GetUserIdStr(c) +pkg.HasError(err, "", 500) +result, err := data.Create() +pkg.HasError(err, "", -1) + +var res app.Response +res.Data = result +c.JSON(http.StatusOK, res.ReturnOK()) + +} + +func Update{{.ClassName}}(c *gin.Context) { +var data models.{{.ClassName}} +err := c.BindWith(&data, binding.JSON) +pkg.HasError(err, "数据解析失败", -1) +data.UpdateBy = utils.GetUserIdStr(c) +result, err := data.Update(data.{{.PkGoField}}) +pkg.HasError(err, "", -1) + +var res app.Response +res.Data = result +c.JSON(http.StatusOK, res.ReturnOK()) +} + +func Delete{{.ClassName}}(c *gin.Context) { +var data models.{{.ClassName}} +id, err := utils.StringToInt(c.Param("{{.PkJsonField}}")) +data.UpdateBy = utils.GetUserIdStr(c) +_, err = data.Delete(id) +pkg.HasError(err, "修改失败", 500) + +var res app.Response +res.Msg = "删除成功" +c.JSON(http.StatusOK, res.ReturnOK()) +} diff --git a/test/gen_test.go b/test/gen_test.go new file mode 100644 index 0000000..99a5c74 --- /dev/null +++ b/test/gen_test.go @@ -0,0 +1,47 @@ +package test + +import ( + //"go-admin/models/tools" + //"os" + "testing" + //"text/template" +) + +func TestGoModelTemplate(t *testing.T) { + //t1, err := template.ParseFiles("model.go.template") + //if err != nil { + // t.Error(err) + //} + //table := tools.SysTables{} + //table.TBName = "sys_tables" + //tab, err := table.Get() + //if err != nil { + // t.Error(err) + //} + //file, err := os.Create("models/" + table.PackageName + ".go") + //if err != nil { + // t.Error(err) + //} + //defer file.Close() + // + //_ = t1.Execute(file, tab) + t.Log("") +} + +func TestGoApiTemplate(t *testing.T) { + //t1, err := template.ParseFiles("api.go.template") + //if err != nil { + // t.Error(err) + //} + //table := tools.SysTables{} + //table.TBName = "sys_tables" + //tab, _ := table.Get() + //file, err := os.Create("apis/" + table.PackageName + ".go") + //if err != nil { + // t.Error(err) + //} + //defer file.Close() + // + //_ = t1.Execute(file, tab) + t.Log("") +} diff --git a/test/model.go.template b/test/model.go.template new file mode 100644 index 0000000..6d9eaaa --- /dev/null +++ b/test/model.go.template @@ -0,0 +1,103 @@ +package models + +import ( +orm "go-admin/global" +"go-admin/utils" +"time" +) + +type {{.ClassName}} struct { + +{{ range .Columns -}} + {{$x := .Pk}} + // {{.ColumnComment}} + {{if ($x)}}{{.GoField}} {{.GoType}} `json:"{{.JsonField}}" gorm:"column:{{.ColumnName}};primary_key"`{{else}}{{.GoField}} {{.GoType}} `json:"{{.JsonField}}" gorm:"column:{{.ColumnName}};"`{{end}} +{{ end -}} +} + +// 创建{{.ClassName}} +func (e *{{.ClassName}}) Create() ({{.ClassName}}, error) { +var doc {{.ClassName}} +doc.IsDel = "0" +e.CreateTime = time.Now().String() +result := orm.Eloquent.Table("{{.TableName}}").Create(&e) +if result.Error != nil { +err := result.Error +return doc, err +} +doc = *e +return doc, nil +} + +// 获取{{.ClassName}} +func (e *{{.ClassName}}) Get() ({{.ClassName}}, error) { +var doc {{.ClassName}} + +table := orm.Eloquent.Table("{{.TableName}}") +{{ range .Columns -}} + {{$z := .IsQuery}} + {{- if ($z) -}}if e.{{.GoField}} != "" { + table = table.Where("{{.ColumnName}} = ?", e.{{.GoField}}) + } + {{ end }} +{{- end -}} + +if err := table.First(&doc).Error; err != nil { +return doc, err +} +return doc, nil +} + +// 获取{{.ClassName}}带分页 +func (e *{{.ClassName}}) GetPage(pageSize int, pageIndex int) ([]{{.ClassName}}, int32, error) { +var doc []{{.ClassName}} + +table := orm.Eloquent.Table("{{.TableName}}") +{{ range .Columns -}} + {{$z := .IsQuery}} + {{- if ($z) -}}if e.{{.GoField}} != "" { + table = table.Where("{{.ColumnName}} = ?", e.{{.GoField}}) + } + {{ end }} +{{- end -}} + +// 数据权限控制 +dataPermission := new(DataPermission) +dataPermission.UserId, _ = utils.StringToInt(e.DataScope) +table,err := dataPermission.GetDataScope("{{.TableName}}", table) +if err != nil { +return nil, 0, err +} +var count int32 +table = table.Offset((pageIndex - 1) * pageSize).Limit(pageSize) +if err := table.Find(&doc).Offset(-1).Limit(-1).Count(&count).Error; err != nil { +return nil, 0, err +} +return doc, count, nil +} + +// 更新{{.ClassName}} +func (e *{{.ClassName}}) Update(id int) (update {{.ClassName}}, err error) { +if err = orm.Eloquent.Table("{{.TableName}}").Where("{{.PkColumn}} = ?", id).First(&update).Error; err != nil { +return +} + +//参数1:是要修改的数据 +//参数2:是修改的数据 +if err = orm.Eloquent.Table("{{.TableName}}").Model(&update).Updates(&e).Error; err != nil { +return +} +return +} + +// 删除{{.ClassName}} +func (e *{{.ClassName}}) Delete(id int) (success bool, err error) { + +if err = orm.Eloquent.Table("{{.TableName}}").Where("{{.PkColumn}} = ?", id).Delete(&{{.ClassName}}{}).Error; err != nil { +success = false +return +} +success = true +return +} +