From c3bc7e520e5d9aa1466050e10af065ddf724514a Mon Sep 17 00:00:00 2001
From: bqy_fe <1743369777@qq.com>
Date: Fri, 10 Dec 2021 22:53:58 +0800
Subject: [PATCH] :sparkles:first commit
---
.browserslistrc | 3 +
.cz-config.js | 91 +
.env.development | 16 +
.env.production | 16 +
.eslintignore | 16 +
.eslintrc.js | 77 +
.github/workflows/gh-pages.yml | 35 +
.gitignore | 29 +
.husky/commit-msg | 6 +
.husky/common.sh | 9 +
.husky/pre-commit | 8 +
.prettierignore | 9 +
.stylelintignore | 2 +
.vscode/extensions.json | 13 +
.vscode/launch.json | 13 +
.vscode/settings.json | 110 +
.yarnrc | 8 +
LICENSE | 21 +
README.md | 59 +
babel.config.js | 16 +
commitlint.config.js | 32 +
package.json | 115 +
prettier.config.js | 10 +
public/favicon.ico | Bin 0 -> 4286 bytes
public/iconfont.js | 1 +
public/index.html | 37 +
src/App.vue | 23 +
src/api/account/index.ts | 38 +
src/api/account/model.d.ts | 41 +
src/api/login/index.ts | 45 +
src/api/login/model.d.ts | 26 +
src/api/system/dept/index.ts | 96 +
src/api/system/dept/model.d.ts | 67 +
src/api/system/log/index.ts | 32 +
src/api/system/log/model.d.ts | 42 +
src/api/system/menu/index.ts | 56 +
src/api/system/menu/model.d.ts | 73 +
src/api/system/online/index.ts | 17 +
src/api/system/online/model.d.ts | 15 +
src/api/system/role/index.ts | 66 +
src/api/system/role/model.d.ts | 55 +
src/api/system/user/index.ts | 83 +
src/api/system/user/model.d.ts | 74 +
src/api/typings.d.ts | 104 +
src/assets/404.gif | Bin 0 -> 164227 bytes
src/assets/analysis.svg | 1 +
src/assets/icons/login.svg | 68 +
src/assets/icons/logo.svg | 48 +
src/assets/images/logo.png | Bin 0 -> 60745 bytes
src/assets/images/tool.png | Bin 0 -> 2629 bytes
src/assets/login.svg | 68 +
.../JSON-schema-form/componentMap.ts | 69 +
src/components/JSON-schema-form/helper.ts | 69 +
.../JSON-schema-form/hooks/useLabelWidth.ts | 39 +
.../JSON-schema-form/hooks/useSchemaForm.ts | 93 +
src/components/JSON-schema-form/index.ts | 9 +
.../JSON-schema-form/schema-form-item.vue | 288 +
.../JSON-schema-form/schema-form.vue | 300 +
src/components/JSON-schema-form/types/form.ts | 215 +
.../JSON-schema-form/types/formItem.ts | 7 +
.../JSON-schema-form/types/hooks.ts | 6 +
.../JSON-schema-form/types/index.ts | 121 +
src/components/SuspenseWithError.vue | 29 +
src/components/a-custom-modal/index.ts | 1 +
src/components/a-custom-modal/index.vue | 105 +
src/components/a-custom-modal/style.less | 161 +
src/components/a-custom-modal/useModal.ts | 240 +
src/components/basic/BasicHelp.vue | 88 +
src/components/button/button.vue | 56 +
src/components/button/index.ts | 1 +
src/components/button/styles/index.less | 2 +
.../button/styles/setButtonColor.less | 57 +
src/components/button/styles/success.less | 11 +
src/components/button/styles/warning.less | 11 +
src/components/context-menu/index.vue | 157 +
src/components/context-menu/props.ts | 40 +
src/components/context-menu/types.ts | 35 +
.../dynamic-table/components/index.ts | 3 +
.../components/query-form/index.vue | 164 +
.../dynamic-table/components/table-action.vue | 27 +
.../table-settings/column-setting.vue | 106 +
.../components/table-settings/index.vue | 14 +
.../table-settings/refresh-setting.vue | 19 +
.../table-settings/size-setting.vue | 44 +
.../components/tool-bar/index.vue | 48 +
.../dynamic-table/dynamic-table.vue | 331 +
src/components/dynamic-table/hooks/index.ts | 3 +
.../dynamic-table/hooks/useCalculate.ts | 86 +
.../dynamic-table/hooks/useDragCol.ts | 63 +
.../dynamic-table/hooks/useExpandLoading.ts | 29 +
.../dynamic-table/hooks/usePagination.ts | 55 +
.../dynamic-table/hooks/useTableContext.ts | 14 +
src/components/dynamic-table/index.ts | 10 +
.../dynamic-table/types/tableAction.ts | 40 +
src/components/dynamic-table/typing.ts | 67 +
src/components/iconfont/icon-font.tsx | 54 +
src/components/iconfont/index.ts | 2 +
src/components/icons-select/icons.ts | 190 +
src/components/icons-select/index.vue | 75 +
src/components/lockscreen/huawei-charge.vue | 192 +
src/components/lockscreen/index.ts | 3 +
src/components/lockscreen/index.vue | 67 +
src/components/lockscreen/lockscreen.vue | 261 +
src/components/lockscreen/xiaomi-charge.vue | 271 +
src/components/operate-row/index.ts | 3 +
src/components/operate-row/operate-row.vue | 57 +
src/components/preview-modal.vue | 262 +
src/components/split-panel/index.ts | 3 +
src/components/split-panel/index.vue | 99 +
src/components/svg-icon/index.ts | 3 +
src/components/svg-icon/svg-icon.vue | 69 +
src/components/transition/index.ts | 3 +
.../transition/router-transition.vue | 23 +
src/core/permission/index.ts | 101 +
src/core/permission/modules/netdisk/manage.ts | 13 +
src/core/permission/modules/sys/dept.ts | 9 +
src/core/permission/modules/sys/log.ts | 5 +
src/core/permission/modules/sys/menu.ts | 7 +
src/core/permission/modules/sys/online.ts | 4 +
src/core/permission/modules/sys/role.ts | 8 +
src/core/permission/modules/sys/task.ts | 10 +
src/core/permission/modules/sys/user.ts | 8 +
src/core/permission/utils.ts | 44 +
src/directives/drag.ts | 0
src/directives/permission.ts | 24 +
src/enums/cacheEnum.ts | 11 +
src/enums/httpEnum.ts | 34 +
src/enums/roleEnum.ts | 7 +
src/hooks/functions/useContextMenu.ts | 41 +
src/hooks/index.ts | 5 +
src/hooks/useBattery.ts | 89 +
src/hooks/useCreateModal.ts | 65 +
src/hooks/useDomWidth.ts | 23 +
src/hooks/useEventbus.ts | 48 +
src/hooks/useModal.tsx | 105 +
src/hooks/useModal/index.ts | 52 +
src/hooks/useModal/modal.tsx | 59 +
src/hooks/useModal/types.ts | 23 +
src/hooks/useModal/useFormModal.tsx | 46 +
src/hooks/useOnline.ts | 30 +
src/hooks/useTime.ts | 55 +
src/layout/footer/index.module.less | 22 +
src/layout/footer/index.tsx | 38 +
src/layout/header/components.ts | 33 +
src/layout/header/index.vue | 208 +
src/layout/index.vue | 81 +
src/layout/logo/index.vue | 33 +
src/layout/menu/menu-item.vue | 51 +
src/layout/menu/menu.vue | 85 +
src/layout/tabs/components.ts | 24 +
src/layout/tabs/index.ts | 3 +
src/layout/tabs/tabs-view.vue | 321 +
src/main.ts | 30 +
src/mock/article.js | 120 +
src/mock/index.js | 56 +
src/mock/log/index.js | 21 +
src/mock/log/reqLog.js | 609 ++
src/mock/mock-server.js | 90 +
src/mock/remote-search.js | 55 +
src/mock/role/index.js | 100 +
src/mock/role/routes.js | 530 +
src/mock/user.js | 83 +
src/mock/utils.js | 48 +
src/plugins/antd.ts | 38 +
src/plugins/customComponents.ts | 13 +
src/plugins/directives.ts | 12 +
src/plugins/globalMethods.ts | 11 +
src/plugins/index.ts | 4 +
src/publicPath.ts | 2 +
src/router/asyncModules/index.ts | 15 +
src/router/asyncModules/system.ts | 15 +
src/router/asyncModules/test.ts | 23 +
src/router/generator-router.tsx | 93 +
src/router/index.ts | 37 +
src/router/router-guards.ts | 89 +
src/router/staticModules/dashboard.ts | 33 +
src/router/staticModules/demos.ts | 108 +
src/router/staticModules/error.ts | 35 +
src/router/staticModules/externa-link.ts | 16 +
src/router/staticModules/index.ts | 6 +
src/router/staticModules/redirect.ts | 29 +
src/router/staticModules/shared.ts | 19 +
src/store/index.ts | 10 +
src/store/modules/lockscreen.ts | 30 +
src/store/modules/tabsView.ts | 63 +
src/store/modules/user.ts | 81 +
src/styles/antdv.override.less | 13 +
src/styles/common.less | 43 +
src/styles/global.less | 2 +
src/utils/Storage.ts | 128 +
src/utils/browser-type.ts | 142 +
src/utils/common.ts | 174 +
src/utils/downloadFile.ts | 90 +
src/utils/helper/tsxHelper.tsx | 35 +
src/utils/is/index.ts | 99 +
src/utils/performanceMonitor.ts | 191 +
src/utils/permission/access.ts | 100 +
src/utils/permission/hasPermission.ts | 41 +
src/utils/request.ts | 121 +
src/utils/urlUtils.ts | 24 +
src/utils/validate.ts | 7 +
src/utils/ws-axios/WsAxios.js | 173 +
src/utils/ws-axios/index.js | 28 +
src/views/shared/dashboard/welcome/index.vue | 77 +
src/views/shared/demos/button.vue | 35 +
src/views/shared/demos/custom-modal.vue | 30 +
.../demos/form/basic-form/form-schema.ts | 183 +
.../shared/demos/form/basic-form/index.vue | 57 +
.../demos/form/rule-form/form-schema.ts | 183 +
.../shared/demos/form/rule-form/index.vue | 57 +
src/views/shared/demos/icons/Iconfont.vue | 87 +
.../demos/tables/summary-table/columns.ts | 103 +
.../demos/tables/summary-table/index.vue | 79 +
.../demos/tables/summary-table/mockData.json | 710 ++
src/views/shared/error/404.vue | 28 +
src/views/shared/icons/icons.ts | 357 +
src/views/shared/icons/index.vue | 73 +
src/views/shared/login/index.vue | 142 +
src/views/shared/redirect/index.vue | 22 +
src/views/system/monitor/login-log/index.vue | 53 +
src/views/system/monitor/online/index.vue | 7 +
src/views/system/monitor/req-log/index.vue | 112 +
src/views/system/permission/menu/columns.tsx | 106 +
.../components/multiple-cascader/index.vue | 168 +
.../multiple-cascader/node-panel.vue | 92 +
.../components/multiple-cascader/utils.ts | 42 +
.../system/permission/menu/formSchemas.ts | 104 +
src/views/system/permission/menu/index.vue | 92 +
src/views/system/permission/role/columns.tsx | 72 +
.../system/permission/role/formSchemas.ts | 65 +
src/views/system/permission/role/index.vue | 96 +
src/views/system/permission/user/columns.tsx | 131 +
.../user/components/OperateUserFormModal.vue | 0
.../system/permission/user/formSchemas.ts | 140 +
src/views/system/permission/user/index.vue | 319 +
src/views/system/schedule/log/index.vue | 7 +
src/views/system/schedule/task/index.vue | 7 +
stylelint.config.js | 93 +
tsconfig.json | 55 +
types/global.d.ts | 101 +
types/index.d.ts | 34 +
types/modules.d.ts | 9 +
types/schema.d.ts | 59 +
types/shims/shims-app.d.ts | 67 +
types/shims/shims-tsx.d.ts | 18 +
types/shims/shims-vue.d.ts | 24 +
types/tableColumn.d.ts | 28 +
types/vue-router.d.ts | 30 +
types/vuex.d.ts | 14 +
vue.config.js | 188 +
windi.config.ts | 24 +
yarn.lock | 8934 +++++++++++++++++
252 files changed, 26134 insertions(+)
create mode 100644 .browserslistrc
create mode 100644 .cz-config.js
create mode 100644 .env.development
create mode 100644 .env.production
create mode 100644 .eslintignore
create mode 100644 .eslintrc.js
create mode 100644 .github/workflows/gh-pages.yml
create mode 100644 .gitignore
create mode 100755 .husky/commit-msg
create mode 100644 .husky/common.sh
create mode 100755 .husky/pre-commit
create mode 100644 .prettierignore
create mode 100644 .stylelintignore
create mode 100644 .vscode/extensions.json
create mode 100644 .vscode/launch.json
create mode 100644 .vscode/settings.json
create mode 100644 .yarnrc
create mode 100644 LICENSE
create mode 100644 README.md
create mode 100644 babel.config.js
create mode 100644 commitlint.config.js
create mode 100644 package.json
create mode 100644 prettier.config.js
create mode 100644 public/favicon.ico
create mode 100644 public/iconfont.js
create mode 100644 public/index.html
create mode 100644 src/App.vue
create mode 100644 src/api/account/index.ts
create mode 100644 src/api/account/model.d.ts
create mode 100644 src/api/login/index.ts
create mode 100644 src/api/login/model.d.ts
create mode 100644 src/api/system/dept/index.ts
create mode 100644 src/api/system/dept/model.d.ts
create mode 100644 src/api/system/log/index.ts
create mode 100644 src/api/system/log/model.d.ts
create mode 100644 src/api/system/menu/index.ts
create mode 100644 src/api/system/menu/model.d.ts
create mode 100644 src/api/system/online/index.ts
create mode 100644 src/api/system/online/model.d.ts
create mode 100644 src/api/system/role/index.ts
create mode 100644 src/api/system/role/model.d.ts
create mode 100644 src/api/system/user/index.ts
create mode 100644 src/api/system/user/model.d.ts
create mode 100644 src/api/typings.d.ts
create mode 100644 src/assets/404.gif
create mode 100644 src/assets/analysis.svg
create mode 100644 src/assets/icons/login.svg
create mode 100644 src/assets/icons/logo.svg
create mode 100644 src/assets/images/logo.png
create mode 100644 src/assets/images/tool.png
create mode 100644 src/assets/login.svg
create mode 100644 src/components/JSON-schema-form/componentMap.ts
create mode 100644 src/components/JSON-schema-form/helper.ts
create mode 100644 src/components/JSON-schema-form/hooks/useLabelWidth.ts
create mode 100644 src/components/JSON-schema-form/hooks/useSchemaForm.ts
create mode 100644 src/components/JSON-schema-form/index.ts
create mode 100644 src/components/JSON-schema-form/schema-form-item.vue
create mode 100644 src/components/JSON-schema-form/schema-form.vue
create mode 100644 src/components/JSON-schema-form/types/form.ts
create mode 100644 src/components/JSON-schema-form/types/formItem.ts
create mode 100644 src/components/JSON-schema-form/types/hooks.ts
create mode 100644 src/components/JSON-schema-form/types/index.ts
create mode 100644 src/components/SuspenseWithError.vue
create mode 100644 src/components/a-custom-modal/index.ts
create mode 100644 src/components/a-custom-modal/index.vue
create mode 100644 src/components/a-custom-modal/style.less
create mode 100644 src/components/a-custom-modal/useModal.ts
create mode 100644 src/components/basic/BasicHelp.vue
create mode 100644 src/components/button/button.vue
create mode 100644 src/components/button/index.ts
create mode 100644 src/components/button/styles/index.less
create mode 100644 src/components/button/styles/setButtonColor.less
create mode 100644 src/components/button/styles/success.less
create mode 100644 src/components/button/styles/warning.less
create mode 100644 src/components/context-menu/index.vue
create mode 100644 src/components/context-menu/props.ts
create mode 100644 src/components/context-menu/types.ts
create mode 100644 src/components/dynamic-table/components/index.ts
create mode 100644 src/components/dynamic-table/components/query-form/index.vue
create mode 100644 src/components/dynamic-table/components/table-action.vue
create mode 100644 src/components/dynamic-table/components/table-settings/column-setting.vue
create mode 100644 src/components/dynamic-table/components/table-settings/index.vue
create mode 100644 src/components/dynamic-table/components/table-settings/refresh-setting.vue
create mode 100644 src/components/dynamic-table/components/table-settings/size-setting.vue
create mode 100644 src/components/dynamic-table/components/tool-bar/index.vue
create mode 100644 src/components/dynamic-table/dynamic-table.vue
create mode 100644 src/components/dynamic-table/hooks/index.ts
create mode 100644 src/components/dynamic-table/hooks/useCalculate.ts
create mode 100644 src/components/dynamic-table/hooks/useDragCol.ts
create mode 100644 src/components/dynamic-table/hooks/useExpandLoading.ts
create mode 100644 src/components/dynamic-table/hooks/usePagination.ts
create mode 100644 src/components/dynamic-table/hooks/useTableContext.ts
create mode 100644 src/components/dynamic-table/index.ts
create mode 100644 src/components/dynamic-table/types/tableAction.ts
create mode 100644 src/components/dynamic-table/typing.ts
create mode 100644 src/components/iconfont/icon-font.tsx
create mode 100644 src/components/iconfont/index.ts
create mode 100644 src/components/icons-select/icons.ts
create mode 100644 src/components/icons-select/index.vue
create mode 100644 src/components/lockscreen/huawei-charge.vue
create mode 100644 src/components/lockscreen/index.ts
create mode 100644 src/components/lockscreen/index.vue
create mode 100644 src/components/lockscreen/lockscreen.vue
create mode 100644 src/components/lockscreen/xiaomi-charge.vue
create mode 100644 src/components/operate-row/index.ts
create mode 100644 src/components/operate-row/operate-row.vue
create mode 100644 src/components/preview-modal.vue
create mode 100644 src/components/split-panel/index.ts
create mode 100644 src/components/split-panel/index.vue
create mode 100644 src/components/svg-icon/index.ts
create mode 100644 src/components/svg-icon/svg-icon.vue
create mode 100644 src/components/transition/index.ts
create mode 100644 src/components/transition/router-transition.vue
create mode 100644 src/core/permission/index.ts
create mode 100644 src/core/permission/modules/netdisk/manage.ts
create mode 100644 src/core/permission/modules/sys/dept.ts
create mode 100644 src/core/permission/modules/sys/log.ts
create mode 100644 src/core/permission/modules/sys/menu.ts
create mode 100644 src/core/permission/modules/sys/online.ts
create mode 100644 src/core/permission/modules/sys/role.ts
create mode 100644 src/core/permission/modules/sys/task.ts
create mode 100644 src/core/permission/modules/sys/user.ts
create mode 100644 src/core/permission/utils.ts
create mode 100644 src/directives/drag.ts
create mode 100644 src/directives/permission.ts
create mode 100644 src/enums/cacheEnum.ts
create mode 100644 src/enums/httpEnum.ts
create mode 100644 src/enums/roleEnum.ts
create mode 100644 src/hooks/functions/useContextMenu.ts
create mode 100644 src/hooks/index.ts
create mode 100644 src/hooks/useBattery.ts
create mode 100644 src/hooks/useCreateModal.ts
create mode 100644 src/hooks/useDomWidth.ts
create mode 100644 src/hooks/useEventbus.ts
create mode 100644 src/hooks/useModal.tsx
create mode 100644 src/hooks/useModal/index.ts
create mode 100644 src/hooks/useModal/modal.tsx
create mode 100644 src/hooks/useModal/types.ts
create mode 100644 src/hooks/useModal/useFormModal.tsx
create mode 100644 src/hooks/useOnline.ts
create mode 100644 src/hooks/useTime.ts
create mode 100644 src/layout/footer/index.module.less
create mode 100644 src/layout/footer/index.tsx
create mode 100644 src/layout/header/components.ts
create mode 100644 src/layout/header/index.vue
create mode 100644 src/layout/index.vue
create mode 100644 src/layout/logo/index.vue
create mode 100644 src/layout/menu/menu-item.vue
create mode 100644 src/layout/menu/menu.vue
create mode 100644 src/layout/tabs/components.ts
create mode 100644 src/layout/tabs/index.ts
create mode 100644 src/layout/tabs/tabs-view.vue
create mode 100644 src/main.ts
create mode 100644 src/mock/article.js
create mode 100644 src/mock/index.js
create mode 100644 src/mock/log/index.js
create mode 100644 src/mock/log/reqLog.js
create mode 100644 src/mock/mock-server.js
create mode 100644 src/mock/remote-search.js
create mode 100644 src/mock/role/index.js
create mode 100644 src/mock/role/routes.js
create mode 100644 src/mock/user.js
create mode 100644 src/mock/utils.js
create mode 100644 src/plugins/antd.ts
create mode 100644 src/plugins/customComponents.ts
create mode 100644 src/plugins/directives.ts
create mode 100644 src/plugins/globalMethods.ts
create mode 100644 src/plugins/index.ts
create mode 100644 src/publicPath.ts
create mode 100644 src/router/asyncModules/index.ts
create mode 100644 src/router/asyncModules/system.ts
create mode 100644 src/router/asyncModules/test.ts
create mode 100644 src/router/generator-router.tsx
create mode 100644 src/router/index.ts
create mode 100644 src/router/router-guards.ts
create mode 100644 src/router/staticModules/dashboard.ts
create mode 100644 src/router/staticModules/demos.ts
create mode 100644 src/router/staticModules/error.ts
create mode 100644 src/router/staticModules/externa-link.ts
create mode 100644 src/router/staticModules/index.ts
create mode 100644 src/router/staticModules/redirect.ts
create mode 100644 src/router/staticModules/shared.ts
create mode 100644 src/store/index.ts
create mode 100644 src/store/modules/lockscreen.ts
create mode 100644 src/store/modules/tabsView.ts
create mode 100644 src/store/modules/user.ts
create mode 100644 src/styles/antdv.override.less
create mode 100644 src/styles/common.less
create mode 100644 src/styles/global.less
create mode 100644 src/utils/Storage.ts
create mode 100644 src/utils/browser-type.ts
create mode 100644 src/utils/common.ts
create mode 100644 src/utils/downloadFile.ts
create mode 100644 src/utils/helper/tsxHelper.tsx
create mode 100644 src/utils/is/index.ts
create mode 100644 src/utils/performanceMonitor.ts
create mode 100644 src/utils/permission/access.ts
create mode 100644 src/utils/permission/hasPermission.ts
create mode 100644 src/utils/request.ts
create mode 100644 src/utils/urlUtils.ts
create mode 100644 src/utils/validate.ts
create mode 100644 src/utils/ws-axios/WsAxios.js
create mode 100644 src/utils/ws-axios/index.js
create mode 100644 src/views/shared/dashboard/welcome/index.vue
create mode 100644 src/views/shared/demos/button.vue
create mode 100644 src/views/shared/demos/custom-modal.vue
create mode 100644 src/views/shared/demos/form/basic-form/form-schema.ts
create mode 100644 src/views/shared/demos/form/basic-form/index.vue
create mode 100644 src/views/shared/demos/form/rule-form/form-schema.ts
create mode 100644 src/views/shared/demos/form/rule-form/index.vue
create mode 100644 src/views/shared/demos/icons/Iconfont.vue
create mode 100644 src/views/shared/demos/tables/summary-table/columns.ts
create mode 100644 src/views/shared/demos/tables/summary-table/index.vue
create mode 100644 src/views/shared/demos/tables/summary-table/mockData.json
create mode 100644 src/views/shared/error/404.vue
create mode 100644 src/views/shared/icons/icons.ts
create mode 100644 src/views/shared/icons/index.vue
create mode 100644 src/views/shared/login/index.vue
create mode 100644 src/views/shared/redirect/index.vue
create mode 100644 src/views/system/monitor/login-log/index.vue
create mode 100644 src/views/system/monitor/online/index.vue
create mode 100644 src/views/system/monitor/req-log/index.vue
create mode 100644 src/views/system/permission/menu/columns.tsx
create mode 100644 src/views/system/permission/menu/components/multiple-cascader/index.vue
create mode 100644 src/views/system/permission/menu/components/multiple-cascader/node-panel.vue
create mode 100644 src/views/system/permission/menu/components/multiple-cascader/utils.ts
create mode 100644 src/views/system/permission/menu/formSchemas.ts
create mode 100644 src/views/system/permission/menu/index.vue
create mode 100644 src/views/system/permission/role/columns.tsx
create mode 100644 src/views/system/permission/role/formSchemas.ts
create mode 100644 src/views/system/permission/role/index.vue
create mode 100644 src/views/system/permission/user/columns.tsx
create mode 100644 src/views/system/permission/user/components/OperateUserFormModal.vue
create mode 100644 src/views/system/permission/user/formSchemas.ts
create mode 100644 src/views/system/permission/user/index.vue
create mode 100644 src/views/system/schedule/log/index.vue
create mode 100644 src/views/system/schedule/task/index.vue
create mode 100644 stylelint.config.js
create mode 100644 tsconfig.json
create mode 100644 types/global.d.ts
create mode 100644 types/index.d.ts
create mode 100644 types/modules.d.ts
create mode 100644 types/schema.d.ts
create mode 100644 types/shims/shims-app.d.ts
create mode 100644 types/shims/shims-tsx.d.ts
create mode 100644 types/shims/shims-vue.d.ts
create mode 100644 types/tableColumn.d.ts
create mode 100644 types/vue-router.d.ts
create mode 100644 types/vuex.d.ts
create mode 100644 vue.config.js
create mode 100644 windi.config.ts
create mode 100644 yarn.lock
diff --git a/.browserslistrc b/.browserslistrc
new file mode 100644
index 000000000..214388fe4
--- /dev/null
+++ b/.browserslistrc
@@ -0,0 +1,3 @@
+> 1%
+last 2 versions
+not dead
diff --git a/.cz-config.js b/.cz-config.js
new file mode 100644
index 000000000..23bcae1ae
--- /dev/null
+++ b/.cz-config.js
@@ -0,0 +1,91 @@
+module.exports = {
+ // type 类型(定义之后,可通过上下键选择)
+ types: [
+ { value: 'feat', name: 'feat: 新增功能' },
+ { value: 'fix', name: 'fix: 修复 bug' },
+ { value: 'docs', name: 'docs: 文档变更' },
+ {
+ value: 'style',
+ name: 'style: 代码格式(不影响功能,例如空格、分号等格式修正)',
+ },
+ {
+ value: 'refactor',
+ name: 'refactor: 代码重构(不包括 bug 修复、功能新增)',
+ },
+ { value: 'perf', name: 'perf: 性能优化' },
+ { value: 'test', name: 'test: 添加、修改测试用例' },
+ {
+ value: 'build',
+ name: 'build: 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)',
+ },
+ { value: 'ci', name: 'ci: 修改 CI 配置、脚本' },
+ {
+ value: 'chore',
+ name: 'chore: 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)',
+ },
+ { value: 'revert', name: 'revert: 回滚 commit' },
+ ],
+
+ // scope 类型(定义之后,可通过上下键选择)
+ scopes: [
+ ['components', '组件相关'],
+ ['hooks', 'hook 相关'],
+ ['utils', 'utils 相关'],
+ ['element-ui', '对 element-ui 的调整'],
+ ['styles', '样式相关'],
+ ['deps', '项目依赖'],
+ ['auth', '对 auth 修改'],
+ ['other', '其他修改'],
+ // 如果选择 custom,后面会让你再输入一个自定义的 scope。也可以不设置此项,把后面的 allowCustomScopes 设置为 true
+ ['custom', '以上都不是?我要自定义'],
+ ].map(([value, description]) => {
+ return {
+ value,
+ name: `${value.padEnd(30)} (${description})`,
+ };
+ }),
+
+ // 是否允许自定义填写 scope,在 scope 选择的时候,会有 empty 和 custom 可以选择。
+ // allowCustomScopes: true,
+
+ // allowTicketNumber: false,
+ // isTicketNumberRequired: false,
+ // ticketNumberPrefix: 'TICKET-',
+ // ticketNumberRegExp: '\\d{1,5}',
+
+ // 针对每一个 type 去定义对应的 scopes,例如 fix
+ /*
+ scopeOverrides: {
+ fix: [
+ { name: 'merge' },
+ { name: 'style' },
+ { name: 'e2eTest' },
+ { name: 'unitTest' }
+ ]
+ },
+ */
+
+ // 交互提示信息
+ messages: {
+ type: '确保本次提交遵循 Angular 规范!\n选择你要提交的类型:',
+ scope: '\n选择一个 scope(可选):',
+ // 选择 scope: custom 时会出下面的提示
+ customScope: '请输入自定义的 scope:',
+ subject: '填写简短精炼的变更描述:\n',
+ body: '填写更加详细的变更描述(可选)。使用 "|" 换行:\n',
+ breaking: '列举非兼容性重大的变更(可选):\n',
+ footer: '列举出所有变更的 ISSUES CLOSED(可选)。 例如: #31, #34:\n',
+ confirmCommit: '确认提交?',
+ },
+
+ // 设置只有 type 选择了 feat 或 fix,才询问 breaking message
+ allowBreakingChanges: ['feat', 'fix'],
+
+ // 跳过要询问的步骤
+ // skipQuestions: ['body', 'footer'],
+
+ subjectLimit: 100, // subject 限制长度
+ breaklineChar: '|', // 换行符,支持 body 和 footer
+ // footerPrefix : 'ISSUES CLOSED:'
+ // askForBreakingChangeFirst : true,
+};
diff --git a/.env.development b/.env.development
new file mode 100644
index 000000000..aa56976b5
--- /dev/null
+++ b/.env.development
@@ -0,0 +1,16 @@
+# 只在开发模式中被载入
+ENV = 'development'
+
+# 网站前缀
+BASE_URL = /
+
+# base api
+VUE_APP_BASE_API = '/api/admin/'
+VUE_APP_BASE_SOCKET_PATH = '/ws'
+VUE_APP_BASE_SOCKET_NSP = '/admin'
+
+# mock api
+VUE_APP_MOCK_API = '/mock-api/'
+
+# API
+VUE_APP_API_URL = http://29135jo738.zicp.vip/api/v1
diff --git a/.env.production b/.env.production
new file mode 100644
index 000000000..ffab27bfc
--- /dev/null
+++ b/.env.production
@@ -0,0 +1,16 @@
+# 只在开发模式中被载入
+ENV = 'production'
+
+# base api
+VUE_APP_BASE_API = '/api/admin/'
+VUE_APP_BASE_SOCKET_PATH = '/ws'
+VUE_APP_BASE_SOCKET_NSP = '/admin'
+
+# 网站前缀
+BASE_URL = /vue3-antd-admin/
+
+# mock api
+VUE_APP_MOCK_API = '/mock-api/'
+
+# API
+VUE_APP_API_URL = http://29135jo738.zicp.vip/api/v1
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 000000000..ce9628dc6
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,16 @@
+
+*.sh
+node_modules
+*.md
+*.woff
+*.ttf
+.vscode
+.idea
+dist
+/public
+/docs
+.husky
+.local
+/bin
+/src/mock
+Dockerfile
diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 000000000..f2900fc87
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,77 @@
+module.exports = {
+ root: true,
+ env: {
+ browser: true,
+ node: true,
+ es6: true,
+ },
+ parser: 'vue-eslint-parser',
+ parserOptions: {
+ parser: '@typescript-eslint/parser',
+ ecmaVersion: 2020,
+ sourceType: 'module',
+ jsxPragma: 'React',
+ ecmaFeatures: {
+ jsx: true,
+ },
+ },
+ extends: [
+ 'plugin:vue/vue3-recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'prettier',
+ 'plugin:prettier/recommended',
+ ],
+ rules: {
+ 'vue/script-setup-uses-vars': 'error',
+ '@typescript-eslint/ban-ts-ignore': 'off',
+ '@typescript-eslint/explicit-function-return-type': 'off',
+ '@typescript-eslint/no-explicit-any': 'off',
+ '@typescript-eslint/no-var-requires': 'off',
+ '@typescript-eslint/no-empty-function': 'off',
+ 'vue/custom-event-name-casing': 'off',
+ 'no-use-before-define': 'off',
+ '@typescript-eslint/no-use-before-define': 'off',
+ '@typescript-eslint/ban-ts-comment': 'off',
+ '@typescript-eslint/ban-types': 'off',
+ '@typescript-eslint/no-non-null-assertion': 'off',
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
+ '@typescript-eslint/no-unused-vars': [
+ 'error',
+ {
+ argsIgnorePattern: '^_',
+ varsIgnorePattern: '^_',
+ },
+ ],
+ 'no-unused-vars': [
+ 'error',
+ {
+ argsIgnorePattern: '^_',
+ varsIgnorePattern: '^_',
+ },
+ ],
+ 'space-before-function-paren': 'off',
+
+ 'vue/attributes-order': 'off',
+ 'vue/one-component-per-file': 'off',
+ 'vue/html-closing-bracket-newline': 'off',
+ 'vue/max-attributes-per-line': 'off',
+ 'vue/multiline-html-element-content-newline': 'off',
+ 'vue/singleline-html-element-content-newline': 'off',
+ 'vue/attribute-hyphenation': 'off',
+ 'vue/require-default-prop': 'off',
+ 'vue/require-explicit-emits': 'off',
+ 'vue/html-self-closing': [
+ 'error',
+ {
+ html: {
+ void: 'always',
+ normal: 'never',
+ component: 'always',
+ },
+ svg: 'always',
+ math: 'always',
+ },
+ ],
+ 'vue/multi-word-component-names': 'off',
+ },
+};
diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml
new file mode 100644
index 000000000..65f829831
--- /dev/null
+++ b/.github/workflows/gh-pages.yml
@@ -0,0 +1,35 @@
+name: deploy
+
+env:
+ # 7 GiB by default on GitHub, setting to 6 GiB
+ # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
+ NODE_OPTIONS: --max-old-space-size=6144
+
+on:
+ push:
+ branches: [main]
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Setup Node.js v14.x
+ uses: actions/setup-node@v1
+ with:
+ node-version: '14.x'
+
+ - name: Install
+ run: yarn install --frozen-lockfile
+
+ - name: Build
+ run: yarn build
+
+ - name: Deploy
+ uses: peaceiris/actions-gh-pages@v3
+ with:
+ publish_dir: ./dist
+ personal_token: ${{ secrets.PERSONAL_TOKEN }}
+ commit_message: Update ghPages
+ force_orphan: true
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..a4b670db7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,29 @@
+node_modules
+.DS_Store
+dist
+.npmrc
+.cache
+
+tests/server/static
+tests/server/static/upload
+
+.local
+# local env files
+.env.local
+.env.*.local
+.eslintcache
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# Editor directories and files
+.idea
+# .vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/.husky/commit-msg b/.husky/commit-msg
new file mode 100755
index 000000000..567ff71f0
--- /dev/null
+++ b/.husky/commit-msg
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# shellcheck source=./_/husky.sh
+. "$(dirname "$0")/_/husky.sh"
+
+npx --no-install commitlint --edit "$1"
diff --git a/.husky/common.sh b/.husky/common.sh
new file mode 100644
index 000000000..9d5129bd7
--- /dev/null
+++ b/.husky/common.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+command_exists () {
+ command -v "$1" >/dev/null 2>&1
+}
+
+# Workaround for Windows 10, Git Bash and Yarn
+if command_exists winpty && test -t 1; then
+ exec < /dev/tty
+fi
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100755
index 000000000..35f92427c
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,8 @@
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+. "$(dirname "$0")/common.sh"
+
+[ -n "$CI" ] && exit 0
+
+# Format and submit code according to lintstagedrc.js configuration
+npm run lint:lint-staged
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 000000000..f7e39e60b
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,9 @@
+/dist/*
+.local
+.output.js
+/node_modules/**
+
+**/*.svg
+**/*.sh
+
+/public/*
diff --git a/.stylelintignore b/.stylelintignore
new file mode 100644
index 000000000..46e88b05d
--- /dev/null
+++ b/.stylelintignore
@@ -0,0 +1,2 @@
+/dist/*
+/public/*
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 000000000..b8a0a97d0
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,13 @@
+{
+ "recommendations": [
+ "johnsoncodehk.volar",
+ "dbaeumer.vscode-eslint",
+ "stylelint.vscode-stylelint",
+ "esbenp.prettier-vscode",
+ "mrmlnc.vscode-less",
+ "lokalise.i18n-ally",
+ "antfu.iconify",
+ "mikestead.dotenv",
+ "heybourn.headwind"
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 000000000..2dd66e881
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,13 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "chrome",
+ "request": "launch",
+ "name": "Launch Chrome",
+ "url": "http://localhost:8080",
+ "webRoot": "${workspaceFolder}/src",
+ "sourceMaps": true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..ed5df1889
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,110 @@
+{
+ "typescript.tsdk": "./node_modules/typescript/lib",
+ "volar.tsPlugin": true,
+ "volar.tsPluginStatus": false,
+ "npm.packageManager": "pnpm",
+ "editor.tabSize": 2,
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
+ "files.eol": "\n",
+ "search.exclude": {
+ "**/node_modules": true,
+ "**/*.log": true,
+ "**/*.log*": true,
+ "**/bower_components": true,
+ "**/dist": true,
+ "**/elehukouben": true,
+ "**/.git": true,
+ "**/.gitignore": true,
+ "**/.svn": true,
+ "**/.DS_Store": true,
+ "**/.idea": true,
+ "**/.vscode": false,
+ "**/yarn.lock": true,
+ "**/tmp": true,
+ "out": true,
+ "dist": true,
+ "node_modules": true,
+ "CHANGELOG.md": true,
+ "examples": true,
+ "res": true,
+ "screenshots": true,
+ "yarn-error.log": true,
+ "**/.yarn": true
+ },
+ "files.exclude": {
+ "**/.cache": true,
+ "**/.editorconfig": true,
+ "**/.eslintcache": true,
+ "**/bower_components": true,
+ "**/.idea": true,
+ "**/tmp": true,
+ "**/.git": true,
+ "**/.svn": true,
+ "**/.hg": true,
+ "**/CVS": true,
+ "**/.DS_Store": true
+ },
+ "files.watcherExclude": {
+ "**/.git/objects/**": true,
+ "**/.git/subtree-cache/**": true,
+ "**/.vscode/**": true,
+ "**/node_modules/**": true,
+ "**/tmp/**": true,
+ "**/bower_components/**": true,
+ "**/dist/**": true,
+ "**/yarn.lock": true
+ },
+ "stylelint.enable": true,
+ "stylelint.packageManager": "yarn",
+ "path-intellisense.mappings": {
+ "@/": "${workspaceRoot}/src"
+ },
+ "[javascriptreact]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[typescript]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[typescriptreact]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[html]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[css]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[less]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[scss]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[markdown]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": true
+ },
+ "[vue]": {
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": false
+ }
+ },
+ "i18n-ally.localesPaths": [
+ "src/locales/lang"
+ ],
+ "i18n-ally.keystyle": "nested",
+ "i18n-ally.sortKeys": true,
+ "i18n-ally.namespace": true,
+ "i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
+ "i18n-ally.enabledParsers": [
+ "ts"
+ ],
+ "i18n-ally.sourceLanguage": "en",
+ "i18n-ally.displayLanguage": "zh-CN",
+ "i18n-ally.enabledFrameworks": [
+ "vue",
+ "react"
+ ]
+}
diff --git a/.yarnrc b/.yarnrc
new file mode 100644
index 000000000..d82a8f232
--- /dev/null
+++ b/.yarnrc
@@ -0,0 +1,8 @@
+registry "https://registry.npm.taobao.org"
+
+sass_binary_site "https://npm.taobao.org/mirrors/node-sass/"
+phantomjs_cdnurl "http://cnpmjs.org/downloads"
+electron_mirror "https://npm.taobao.org/mirrors/electron/"
+sqlite3_binary_host_mirror "https://foxgis.oss-cn-shanghai.aliyuncs.com/"
+profiler_binary_host_mirror "https://npm.taobao.org/mirrors/node-inspector/"
+chromedriver_cdnurl "https://cdn.npm.taobao.org/dist/chromedriver"
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 000000000..0c4a7146a
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 bqy
+
+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/README.md b/README.md
new file mode 100644
index 000000000..7d21dd95d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,59 @@
+# vue3-antd-admin
+
+> 即将基于 vue-cli5.x 重构整个前后端项目,完善后端权限控制细粒度,封装更多场景化组件...
+
+基于 vue-cli / vite2.x + vue3.x + antd-design-vue2.x + typescript4.x 的后台管理系统模板
+
+- 账号:admin,密码:123456
+- [在线预览](http://buqiyuan.gitee.io/vue3-antd-admin/)
+- [API 文档](http://29135jo738.zicp.vip/api/v1/docs/)
+- [后台地址](https://github.com/buqiyuan/nestjs-mysql-api)
+- [react 版 coding](https://github.com/buqiyuan/react-antd-admin)
+- [vite 踩坑版](https://github.com/buqiyuan/vite-vue3-admin)
+- [gitee 地址](https://gitee.com/buqiyuan/vue3-antd-admin)
+
+## vscode 配置
+
+安装项目根目录.vscode 推荐的插件,再安装 Volar,并禁用 Vetur,重启 vscode 即可。
+
+> 使用了 Vue3.0 全家桶、ant-design-vue2.0 和 typescript4.0,实践 vue3.0 的新特性以及玩法,不得不说 vue3.0 的 Composition API 相比于 vue2.0 的 Options API
+> 灵活很多,让我们可以灵活地组合组件逻辑,我们可以很轻松的使用 hooks 的形式去代替以前 mixins 等的写法。更多 hooks 可以参考[vueuse](https://vueuse.org/functions.html)
+
+## 克隆项目
+
+```bash
+git clone --single-branch https://github.com/buqiyuan/vite-vue3-lowcode.git
+or
+git clone --depth=1 https://github.com/buqiyuan/vite-vue3-lowcode.git
+```
+
+## Project setup
+
+```shell
+yarn install
+# 或
+yarn --frozen-lockfile
+```
+
+### Compiles and hot-reloads for development
+
+```shell
+yarn serve
+```
+
+### Compiles and minifies for production
+
+```shell
+yarn build
+```
+
+### Lints and fixes files
+
+```shell
+yarn lint
+```
+
+## 感谢 JetBrains 免费的开源授权
+
+
+
diff --git a/babel.config.js b/babel.config.js
new file mode 100644
index 000000000..bc26531b8
--- /dev/null
+++ b/babel.config.js
@@ -0,0 +1,16 @@
+module.exports = {
+ presets: ['@vue/cli-plugin-babel/preset'],
+ plugins: [
+ 'lodash',
+ [
+ 'import',
+ {
+ libraryName: 'ant-design-vue',
+ libraryDirectory: 'es',
+ style: true,
+ css: true,
+ },
+ 'ant-design-vue',
+ ],
+ ],
+};
diff --git a/commitlint.config.js b/commitlint.config.js
new file mode 100644
index 000000000..ac977af17
--- /dev/null
+++ b/commitlint.config.js
@@ -0,0 +1,32 @@
+module.exports = {
+ ignores: [(commit) => commit.includes('init')],
+ extends: ['@commitlint/config-conventional'],
+ rules: {
+ 'body-leading-blank': [2, 'always'],
+ 'footer-leading-blank': [1, 'always'],
+ 'header-max-length': [2, 'always', 108],
+ 'subject-empty': [2, 'never'],
+ 'type-empty': [2, 'never'],
+ 'type-enum': [
+ 2,
+ 'always',
+ [
+ 'feat',
+ 'fix',
+ 'perf',
+ 'style',
+ 'docs',
+ 'test',
+ 'refactor',
+ 'build',
+ 'ci',
+ 'chore',
+ 'revert',
+ 'wip',
+ 'workflow',
+ 'types',
+ 'release',
+ ],
+ ],
+ },
+};
diff --git a/package.json b/package.json
new file mode 100644
index 000000000..221421bd2
--- /dev/null
+++ b/package.json
@@ -0,0 +1,115 @@
+{
+ "name": "vue3-antd-admin",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "serve": "vue-cli-service serve",
+ "build": "vue-cli-service build",
+ "lint": "vue-cli-service lint",
+ "deploy": "gh-pages -d dist",
+ "lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
+ "lint:lint-staged": "lint-staged",
+ "lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
+ "lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
+ "prepare": "husky install",
+ "test prod cors": "http-server dist --cors --gzip -P http://29135jo738.zicp.vip",
+ "test prod gzip": "http-server dist --cors --gzip -c-1"
+ },
+ "dependencies": {
+ "@vueuse/core": "^7.2.2",
+ "ant-design-vue": "3.0.0-alpha.14",
+ "axios": "^0.24.0",
+ "dayjs": "^1.10.7",
+ "lodash": "^4.17.21",
+ "mitt": "^3.0.0",
+ "nprogress": "^1.0.0-1",
+ "pinia": "2.0.6",
+ "qs": "^6.10.2",
+ "sortablejs": "^1.14.0",
+ "vue": "^3.2.24",
+ "vue-router": "^4.0.12"
+ },
+ "devDependencies": {
+ "@commitlint/cli": "^15.0.0",
+ "@commitlint/config-conventional": "^15.0.0",
+ "@types/lodash": "^4.14.178",
+ "@types/node": "^16.11.12",
+ "@types/webpack-env": "^1.16.3",
+ "@typescript-eslint/eslint-plugin": "^5.6.0",
+ "@typescript-eslint/parser": "^5.6.0",
+ "@vue/cli-plugin-babel": "^5.0.0-rc.1",
+ "@vue/cli-plugin-eslint": "^5.0.0-rc.1",
+ "@vue/cli-plugin-router": "^5.0.0-rc.1",
+ "@vue/cli-plugin-typescript": "^5.0.0-rc.1",
+ "@vue/cli-plugin-vuex": "^5.0.0-rc.1",
+ "@vue/cli-service": "^5.0.0-rc.1",
+ "@vue/compiler-sfc": "^3.2.24",
+ "@vue/eslint-config-typescript": "^9.1.0",
+ "babel-plugin-import": "^1.13.3",
+ "babel-plugin-lodash": "^3.3.4",
+ "commitizen": "^4.2.4",
+ "compression-webpack-plugin": "^9.1.1",
+ "core-js": "^3.19.3",
+ "eslint": "^8.4.1",
+ "eslint-config-prettier": "^8.3.0",
+ "eslint-plugin-prettier": "^4.0.0",
+ "eslint-plugin-vue": "^8.2.0",
+ "gh-pages": "^3.2.3",
+ "husky": "^7.0.4",
+ "less": "^4.1.2",
+ "less-loader": "10.2.0",
+ "lint-staged": "^12.1.2",
+ "lodash-webpack-plugin": "^0.11.6",
+ "mockjs": "^1.1.0",
+ "path-browserify": "^1.0.1",
+ "postcss-html": "^1.3.0",
+ "prettier": "^2.5.1",
+ "stylelint": "^14.1.0",
+ "stylelint-config-html": "^1.0.0",
+ "stylelint-config-prettier": "^9.0.3",
+ "stylelint-config-recommended": "^6.0.0",
+ "stylelint-config-standard": "^24.0.0",
+ "stylelint-order": "^5.0.0",
+ "svg-sprite-loader": "^6.0.11",
+ "typescript": "^4.5.3",
+ "vue-cli-plugin-windicss": "^1.1.2",
+ "vue-eslint-parser": "^8.0.1"
+ },
+ "__npminstall_done": false,
+ "homepage": "git@buqiyuan.github.io/vue3-antd-admin",
+ "keywords": [
+ "vue",
+ "ant-design-vue",
+ "vue3",
+ "ts",
+ "tsx",
+ "admin",
+ "typescript"
+ ],
+ "license": "MIT",
+ "lint-staged": {
+ "*.{js,jsx,ts,tsx}": [
+ "eslint --fix",
+ "prettier --write"
+ ],
+ "{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [
+ "prettier --write--parser json"
+ ],
+ "package.json": [
+ "prettier --write"
+ ],
+ "*.vue": [
+ "eslint --fix",
+ "prettier --write",
+ "stylelint --fix"
+ ],
+ "*.{scss,less,styl,html}": [
+ "stylelint --fix",
+ "prettier --write"
+ ],
+ "*.md": [
+ "prettier --write"
+ ]
+ },
+ "target": "web"
+}
diff --git a/prettier.config.js b/prettier.config.js
new file mode 100644
index 000000000..51f8d01be
--- /dev/null
+++ b/prettier.config.js
@@ -0,0 +1,10 @@
+module.exports = {
+ printWidth: 100,
+ semi: true,
+ vueIndentScriptAndStyle: true,
+ singleQuote: true,
+ trailingComma: 'all',
+ proseWrap: 'never',
+ htmlWhitespaceSensitivity: 'strict',
+ endOfLine: 'auto',
+};
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2
GIT binary patch
literal 4286
zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj
zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56
zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy
zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei
z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX
zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm
zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp=
zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8
zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO
z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3
z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD
zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6
z={Xwx{T%b6i9IjI)Ls)S{-*mq<@~R{?$}ZKjf;^k75i_}(2MXt}^SEBVg7AI@28
zo_uPg2V)_e-`2Ois=PYoe%9u*n9({PFR)OnHJPi{dNx>KxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S
literal 0
HcmV?d00001
diff --git a/public/iconfont.js b/public/iconfont.js
new file mode 100644
index 000000000..98bd2762f
--- /dev/null
+++ b/public/iconfont.js
@@ -0,0 +1 @@
+!function(a){var h,l,v,o,i,m='',z=(z=document.getElementsByTagName("script"))[z.length-1].getAttribute("data-injectcss"),t=function(a,h){h.parentNode.insertBefore(a,h)};if(z&&!a.__iconfont__svg__cssinject__){a.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}function n(){i||(i=!0,v())}function s(){try{o.documentElement.doScroll("left")}catch(a){return void setTimeout(s,50)}n()}h=function(){var a,h;(h=document.createElement("div")).innerHTML=m,m=null,(a=h.getElementsByTagName("svg")[0])&&(a.setAttribute("aria-hidden","true"),a.style.position="absolute",a.style.width=0,a.style.height=0,a.style.overflow="hidden",h=a,(a=document.body).firstChild?t(h,a.firstChild):a.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(h,0):(l=function(){document.removeEventListener("DOMContentLoaded",l,!1),h()},document.addEventListener("DOMContentLoaded",l,!1)):document.attachEvent&&(v=h,o=a.document,i=!1,s(),o.onreadystatechange=function(){"complete"==o.readyState&&(o.onreadystatechange=null,n())})}(window);
\ No newline at end of file
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 000000000..d0a8aaadc
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+ <%= htmlWebpackPlugin.options.title %>
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/App.vue b/src/App.vue
new file mode 100644
index 000000000..012944216
--- /dev/null
+++ b/src/App.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/api/account/index.ts b/src/api/account/index.ts
new file mode 100644
index 000000000..be985572a
--- /dev/null
+++ b/src/api/account/index.ts
@@ -0,0 +1,38 @@
+import { request, BaseResponse } from '@/utils/request';
+
+export function updateAccountInfo(data: any) {
+ return request>({
+ url: 'account/update',
+ method: 'post',
+ data,
+ });
+}
+
+export function updatePassword(data: any) {
+ return request({
+ url: 'account/password',
+ method: 'post',
+ data,
+ });
+}
+
+export function getInfo() {
+ return request({
+ url: 'account/info',
+ method: 'get',
+ });
+}
+
+export function permmenu() {
+ return request({
+ url: 'account/permmenu',
+ method: 'get',
+ });
+}
+
+export function logout() {
+ return request({
+ url: 'account/logout',
+ method: 'post',
+ });
+}
diff --git a/src/api/account/model.d.ts b/src/api/account/model.d.ts
new file mode 100644
index 000000000..439cac29a
--- /dev/null
+++ b/src/api/account/model.d.ts
@@ -0,0 +1,41 @@
+declare namespace API {
+ type Menu = {
+ createTime: Date;
+ updateTime: Date;
+ id: number;
+ parentId: number;
+ name: string;
+ router: string;
+ perms: string;
+ type: number;
+ icon: string;
+ orderNum: number;
+ viewPath: string;
+ keepalive: boolean;
+ isShow: boolean;
+ };
+
+ type PermMenu = {
+ menus: Menu[];
+ perms: string[];
+ };
+
+ type AdminUserInfo = {
+ createTime: Date;
+ updateTime: Date;
+ id: number;
+ departmentId: number;
+ name: string;
+ username: string;
+ password: string;
+ psalt: string;
+ nickName: string;
+ headImg: string;
+ email: string;
+ phone: string;
+ remark: string;
+ status: number;
+ roles: number[];
+ departmentName: string;
+ };
+}
diff --git a/src/api/login/index.ts b/src/api/login/index.ts
new file mode 100644
index 000000000..c86e0efbb
--- /dev/null
+++ b/src/api/login/index.ts
@@ -0,0 +1,45 @@
+import { request, BaseResponse } from '@/utils/request';
+
+/**
+ * @description 登录
+ * @param {LoginParams} data
+ * @returns
+ */
+export function login(data: API.LoginParams) {
+ return request>(
+ {
+ url: 'login',
+ method: 'post',
+ data,
+ },
+ {
+ isGetDataDirectly: false,
+ },
+ );
+}
+/**
+ * @description 获取验证码
+ */
+export function getImageCaptcha(params?: API.CaptchaParams) {
+ return request({
+ url: 'captcha/img',
+ method: 'get',
+ params,
+ });
+}
+
+/**
+ * @description 登出
+ */
+export function logout(data: { token: string }) {
+ return request(
+ {
+ url: 'account/logout',
+ method: 'post',
+ data,
+ },
+ {
+ isGetDataDirectly: false,
+ },
+ );
+}
diff --git a/src/api/login/model.d.ts b/src/api/login/model.d.ts
new file mode 100644
index 000000000..aad874481
--- /dev/null
+++ b/src/api/login/model.d.ts
@@ -0,0 +1,26 @@
+declare namespace API {
+ /** 登录参数 */
+ type LoginParams = {
+ captchaId: string;
+ password: string;
+ username: string;
+ verifyCode: string;
+ };
+
+ /** 登录成功结果 */
+ type LoginResult = {
+ token: string;
+ };
+
+ /** 获取验证码参数 */
+ type CaptchaParams = {
+ width?: number;
+ height?: number;
+ };
+
+ /** 获取验证码结果 */
+ type CaptchaResult = {
+ img: string;
+ id: string;
+ };
+}
diff --git a/src/api/system/dept/index.ts b/src/api/system/dept/index.ts
new file mode 100644
index 000000000..10c43202b
--- /dev/null
+++ b/src/api/system/dept/index.ts
@@ -0,0 +1,96 @@
+import { request } from '@/utils/request';
+// import type { BaseResponse } from '@/utils/request';
+import Api from '@/core/permission/modules/sys/dept';
+
+/**
+ * @description 获取部门列表
+ * @returns
+ */
+export function getDeptList() {
+ return request({
+ url: Api.list,
+ method: 'get',
+ });
+}
+
+/**
+ * @description 部门移动排序
+ * @param {API.MovedDeptsParams} data
+ * @returns
+ */
+export function moveDeptList(data: API.MovedDeptsParams) {
+ return request({
+ url: Api.move,
+ method: 'post',
+ data,
+ });
+}
+
+/**
+ * @description 删除部门
+ * @param {API.DelDeptParams} data
+ * @returns
+ */
+export function deleteDept(data: API.DelDeptParams) {
+ return request(
+ {
+ url: 'sys/dept/delete',
+ method: 'post',
+ data,
+ },
+ {
+ successMsg: '删除成功',
+ },
+ );
+}
+
+/**
+ * @description 更新某个部门
+ * @param {API.UpdateDeptParams} data 参数
+ * @returns
+ */
+export function updateDept(data: API.UpdateDeptParams) {
+ return request({
+ url: Api.update,
+ method: 'post',
+ data,
+ });
+}
+
+/**
+ * @description 创建部门
+ * @param {API.CreateDeptParams} data 参数
+ * @returns
+ */
+export function createDept(data: API.CreateDeptParams) {
+ return request({
+ url: Api.add,
+ method: 'post',
+ data,
+ });
+}
+/**
+ * @description 查询单个部门信息
+ * @param query
+ * @returns
+ */
+export function getDeptInfo(query: { departmentId: string | number }) {
+ return request({
+ url: Api.info,
+ method: 'get',
+ params: query,
+ });
+}
+
+/**
+ * @description 管理员部门转移
+ * @param data
+ * @returns
+ */
+export function transferDept(data: API.TransferDeptParams) {
+ return request({
+ url: Api.transfer,
+ method: 'post',
+ data,
+ });
+}
diff --git a/src/api/system/dept/model.d.ts b/src/api/system/dept/model.d.ts
new file mode 100644
index 000000000..89440c595
--- /dev/null
+++ b/src/api/system/dept/model.d.ts
@@ -0,0 +1,67 @@
+declare namespace API {
+ /** 获取系统部门返回结果 */
+ type SysDeptListResult = {
+ createTime: string;
+ updateTime: string;
+ id: number;
+ parentId: number;
+ name: string;
+ orderNum: number;
+ };
+ /** 部门 */
+ type MovedDeptItem = {
+ id: number;
+ parentId: number;
+ };
+
+ /** 要排序的部门 */
+ type MovedDeptsParams = {
+ depts: MovedDeptItem[];
+ };
+
+ /** 删除部门的参数 */
+ type DelDeptParams = {
+ departmentId: number | string;
+ };
+
+ /** 更新某个部门需要传的参数 */
+ type UpdateDeptParams = {
+ name: string;
+ parentId: number | string;
+ orderNum: number;
+ id: number | string;
+ };
+
+ /** 创建部门参数 */
+ type CreateDeptParams = {
+ name: string;
+ parentId: number;
+ orderNum: number;
+ };
+
+ /** 管理员部门转移 */
+ type TransferDeptParams = {
+ userIds: number[];
+ departmentId: number;
+ };
+
+ /** 部门详情 */
+ type GetDeptInfoResult = {
+ department: {
+ createTime: string;
+ updateTime: string;
+ id: number;
+ parentId: number;
+ name: 'string';
+ orderNum: number;
+ };
+ parentDepartment: {
+ createTime: string;
+ updateTime: string;
+ id: number;
+ parentId: number;
+ name: 'string';
+ orderNum: number;
+ };
+ };
+}
diff --git a/src/api/system/log/index.ts b/src/api/system/log/index.ts
new file mode 100644
index 000000000..fe28f2ea4
--- /dev/null
+++ b/src/api/system/log/index.ts
@@ -0,0 +1,32 @@
+import { request, BaseResponse } from '@/utils/request';
+import LogApi from '@/core/permission/modules/sys/log';
+
+export function getReqLogList(query: API.PageParams) {
+ return request>(
+ {
+ url: LogApi.req,
+ method: 'get',
+ params: query,
+ },
+ {
+ isMock: true,
+ isGetDataDirectly: false,
+ },
+ );
+}
+
+export function getLoginLogList(query: API.PageParams) {
+ return request>({
+ url: LogApi.login,
+ method: 'get',
+ params: query,
+ });
+}
+
+export function getTaskLogList(query: API.PageParams) {
+ return request>({
+ url: LogApi.task,
+ method: 'get',
+ params: query,
+ });
+}
diff --git a/src/api/system/log/model.d.ts b/src/api/system/log/model.d.ts
new file mode 100644
index 000000000..addcee94d
--- /dev/null
+++ b/src/api/system/log/model.d.ts
@@ -0,0 +1,42 @@
+declare namespace API {
+ /** 登录日志项结果 */
+ type LoginLogListItemResult = {
+ id: number;
+ ip: string;
+ os: string;
+ browser: string;
+ time: string;
+ username: string;
+ };
+ /** 登录日志结果 */
+ type LoginLogListResult = LoginLogListItemResult[];
+
+ /** 请求日志项结果 */
+ type ReqLogListItemResult = {
+ createTime: string;
+ updateTime: string;
+ id: number;
+ ip: string;
+ userId: number;
+ params: string;
+ action: string;
+ method: string;
+ status: number;
+ consumeTime: number;
+ };
+ /** 请求日志结果 */
+ type ReqLogListResult = ReqLogListItemResult[];
+
+ /** 任务日志项结果 */
+ type TaskLogListItemResult = {
+ id: number;
+ taskId: number;
+ name: string;
+ createTime: string;
+ consumeTime: number;
+ detail: string;
+ status: number;
+ };
+ /** 任务日志结果 */
+ type TaskLogListResult = TaskLogListItemResult[];
+}
diff --git a/src/api/system/menu/index.ts b/src/api/system/menu/index.ts
new file mode 100644
index 000000000..04b047524
--- /dev/null
+++ b/src/api/system/menu/index.ts
@@ -0,0 +1,56 @@
+import { request } from '@/utils/request';
+import Api from '@/core/permission/modules/sys/menu';
+
+export function getMenuList() {
+ return request({
+ url: Api.list,
+ method: 'get',
+ });
+}
+
+export function getMenuInfo(query: { menuId: number }) {
+ return request({
+ url: Api.info,
+ method: 'get',
+ params: query,
+ });
+}
+
+export function createMenu(data: API.MenuAddParams) {
+ return request(
+ {
+ url: Api.add,
+ method: 'post',
+ data,
+ },
+ {
+ successMsg: '创建成功',
+ },
+ );
+}
+
+export function updateMenu(data: API.MenuUpdateParams) {
+ return request(
+ {
+ url: Api.update,
+ method: 'post',
+ data,
+ },
+ {
+ successMsg: '更新成功',
+ },
+ );
+}
+
+export function deleteMenu(data: { menuId: number }) {
+ return request(
+ {
+ url: Api.delete,
+ method: 'post',
+ data,
+ },
+ {
+ successMsg: '删除成功',
+ },
+ );
+}
diff --git a/src/api/system/menu/model.d.ts b/src/api/system/menu/model.d.ts
new file mode 100644
index 000000000..41e022ac8
--- /dev/null
+++ b/src/api/system/menu/model.d.ts
@@ -0,0 +1,73 @@
+declare namespace API {
+ type MenuListResultItem = {
+ createTime: string;
+ updateTime: string;
+ id: number;
+ parentId: number;
+ name: string;
+ router: string;
+ perms: string;
+ type: number;
+ icon: string;
+ orderNum: number;
+ viewPath: string;
+ keepalive: boolean;
+ isShow: boolean;
+ };
+
+ /** 获取菜单列表参数 */
+ type MenuListResult = MenuListResultItem[];
+
+ /** 新增菜单参数 */
+ type MenuAddParams = {
+ type: number;
+ parentId: number;
+ name: string;
+ orderNum: number;
+ router: string;
+ isShow: boolean;
+ keepalive: boolean;
+ icon: string;
+ perms: string;
+ viewPath: string;
+ };
+
+ /** 更新某项菜单参数 */
+ type MenuUpdateParams = MenuAddParams & {
+ menuId: number;
+ };
+
+ /** 获取菜单详情结果 */
+ type MenuInfoResult = {
+ menu: {
+ createTime: string;
+ updateTime: string;
+ id: number;
+ parentId: number;
+ name: string;
+ router: string;
+ perms: string;
+ type: number;
+ icon: string;
+ orderNum: number;
+ viewPath: string;
+ keepalive: boolean;
+ isShow: boolean;
+ };
+ parentMenu: {
+ createTime: string;
+ updateTime: string;
+ id: number;
+ parentId: number;
+ name: string;
+ router: string;
+ perms: string;
+ type: number;
+ icon: string;
+ orderNum: number;
+ viewPath: string;
+ keepalive: boolean;
+ isShow: boolean;
+ };
+ };
+}
diff --git a/src/api/system/online/index.ts b/src/api/system/online/index.ts
new file mode 100644
index 000000000..7ac38481c
--- /dev/null
+++ b/src/api/system/online/index.ts
@@ -0,0 +1,17 @@
+import { request } from '@/utils/request';
+import OnlineApi from '@/core/permission/modules/sys/online';
+
+export function getOnlineList() {
+ return request({
+ url: OnlineApi.list,
+ method: 'get',
+ });
+}
+
+export function kickUser(data: { id: number }) {
+ return request({
+ url: OnlineApi.kick,
+ method: 'post',
+ data,
+ });
+}
diff --git a/src/api/system/online/model.d.ts b/src/api/system/online/model.d.ts
new file mode 100644
index 000000000..0e3239790
--- /dev/null
+++ b/src/api/system/online/model.d.ts
@@ -0,0 +1,15 @@
+declare namespace API {
+ /** 在线用户列表项 */
+ type OnlineUserListItem = {
+ id: number;
+ ip: string;
+ username: string;
+ isCurrent: true;
+ time: string;
+ os: string;
+ browser: string;
+ disable: boolean;
+ };
+ /** 在线用户列表 */
+ type OnlineUserListResult = OnlineUserListItem[];
+}
diff --git a/src/api/system/role/index.ts b/src/api/system/role/index.ts
new file mode 100644
index 000000000..1c714cbbf
--- /dev/null
+++ b/src/api/system/role/index.ts
@@ -0,0 +1,66 @@
+import { request } from '@/utils/request';
+// import type { BaseResponse } from '@/utils/request';
+import Api from '@/core/permission/modules/sys/role';
+
+export function getRoleInfo(query: { roleId: number }) {
+ return request({
+ url: Api.info,
+ method: 'get',
+ params: query,
+ });
+}
+
+export function getRoleList(data?: API.PageParams) {
+ return request({
+ url: Api.list,
+ method: 'get',
+ data,
+ });
+}
+
+export function getRoleListByPage(query: API.PageParams) {
+ return request({
+ url: Api.page,
+ method: 'get',
+ params: query,
+ });
+}
+
+export function createRole(data: API.CreateRoleParams) {
+ return request(
+ {
+ url: Api.add,
+ method: 'post',
+ data,
+ },
+ {
+ successMsg: '创建角色成功',
+ },
+ );
+}
+
+export function updateRole(data: API.UpdateRoleParams) {
+ return request(
+ {
+ url: Api.update,
+ method: 'post',
+ data,
+ },
+ {
+ successMsg: '更新角色成功',
+ },
+ );
+}
+
+export function deleteRole(data: { roleIds: number[] }) {
+ return request(
+ {
+ url: Api.delete,
+ method: 'post',
+ data,
+ },
+ {
+ successMsg: '删除角色成功',
+ },
+ );
+}
diff --git a/src/api/system/role/model.d.ts b/src/api/system/role/model.d.ts
new file mode 100644
index 000000000..b7e794c96
--- /dev/null
+++ b/src/api/system/role/model.d.ts
@@ -0,0 +1,55 @@
+declare namespace API {
+ /** 新增角色 */
+ type CreateRoleParams = {
+ name: string;
+ label: string;
+ remark: string;
+ menus: Key[];
+ depts: number[];
+ };
+ /** 更新角色 */
+ type UpdateRoleParams = CreateRoleParams & {
+ roleId: number;
+ };
+
+ /** 角色列表项 */
+ type RoleListResultItem = {
+ createTime: string;
+ updateTime: string;
+ id: number;
+ userId: string;
+ name: string;
+ label: string;
+ remark: string;
+ };
+
+ /** 角色列表 */
+ type RoleListResult = RoleListResultItem[];
+
+ /** 角色详情 */
+ type RoleInfoResult = {
+ roleInfo: {
+ createTime: string;
+ updateTime: string;
+ id: number;
+ userId: string;
+ name: string;
+ label: string;
+ remark: string;
+ };
+ menus: {
+ createTime: string;
+ updateTime: string;
+ id: number;
+ roleId: number;
+ menuId: number;
+ }[];
+ depts: {
+ createTime: string;
+ updateTime: string;
+ id: number;
+ roleId: number;
+ departmentId: number;
+ }[];
+ };
+}
diff --git a/src/api/system/user/index.ts b/src/api/system/user/index.ts
new file mode 100644
index 000000000..de0e0544d
--- /dev/null
+++ b/src/api/system/user/index.ts
@@ -0,0 +1,83 @@
+import { request } from '@/utils/request';
+import Api from '@/core/permission/modules/sys/user';
+import { generatePermCode } from '@/core/permission';
+
+export function getUserListPage(data: API.PageParams<{ departmentIds: number[] }>) {
+ return request>(
+ {
+ url: Api.page,
+ method: 'post',
+ data,
+ },
+ {
+ permCode: generatePermCode(Api.page),
+ },
+ );
+}
+
+export function createUser(data: API.CreateUserParams) {
+ return request(
+ {
+ url: Api.add,
+ method: 'post',
+ data,
+ },
+ {
+ permCode: generatePermCode(Api.add),
+ successMsg: '创建用户成功',
+ },
+ );
+}
+
+export function getUserInfo(query: { userId: number }) {
+ return request(
+ {
+ url: Api.info,
+ method: 'get',
+ params: query,
+ },
+ {
+ permCode: generatePermCode(Api.info),
+ },
+ );
+}
+
+export function updateUser(data: API.UpdateAdminInfoParams) {
+ return request(
+ {
+ url: Api.update,
+ method: 'post',
+ data,
+ },
+ {
+ permCode: generatePermCode(Api.update),
+ successMsg: '修改用户成功',
+ },
+ );
+}
+
+export function updateUserPassword(data: API.UpdateAdminUserPassword) {
+ return request(
+ {
+ url: Api.password,
+ method: 'post',
+ data,
+ },
+ {
+ permCode: generatePermCode(Api.password),
+ },
+ );
+}
+
+export function deleteUsers(data: { userIds: number[] }) {
+ return request(
+ {
+ url: Api.delete,
+ method: 'post',
+ data,
+ },
+ {
+ permCode: generatePermCode(Api.delete),
+ },
+ );
+}
diff --git a/src/api/system/user/model.d.ts b/src/api/system/user/model.d.ts
new file mode 100644
index 000000000..0c17847c2
--- /dev/null
+++ b/src/api/system/user/model.d.ts
@@ -0,0 +1,74 @@
+declare namespace API {
+ type UserListPageResultItem = {
+ createTime: string;
+ departmentId: number;
+ email: string;
+ headImg: string;
+ id: number;
+ name: string;
+ nickName: string;
+ phone: string;
+ remark: string;
+ status: number;
+ updateTime: string;
+ username: string;
+ departmentName: string;
+ roleNames: string[];
+ };
+
+ /** 获取用户列表结果 */
+ type UserListPageResult = UserListPageResultItem[];
+
+ /** 创建用户参数 */
+ type CreateUserParams = {
+ departmentId: number;
+ name: string;
+ username: string;
+ roles: number[];
+ nickName: string;
+ email: string;
+ phone: string;
+ remark: string;
+ status: number;
+ };
+
+ /** 管理员用户详情 */
+ type AdminUserInfo = {
+ createTime: string;
+ updateTime: string;
+ id: number;
+ departmentId: number;
+ name: string;
+ username: string;
+ password: string;
+ psalt: string;
+ nickName: string;
+ headImg: string;
+ email: string;
+ phone: string;
+ remark: string;
+ status: number;
+ roles: string[];
+ departmentName: string;
+ };
+
+ /** 更新管理员用户参数 */
+ type UpdateAdminInfoParams = {
+ departmentId: number;
+ name: string;
+ username: string;
+ roles: number[];
+ nickName: string;
+ email: string;
+ phone: string;
+ remark: string;
+ status: number;
+ id: number;
+ };
+
+ /** 更新管理员密码 */
+ type UpdateAdminUserPassword = {
+ userId: number;
+ password: string;
+ };
+}
diff --git a/src/api/typings.d.ts b/src/api/typings.d.ts
new file mode 100644
index 000000000..39e2abe49
--- /dev/null
+++ b/src/api/typings.d.ts
@@ -0,0 +1,104 @@
+// @ts-ignore
+/* eslint-disable */
+
+declare namespace API {
+ type CurrentUser = {
+ name?: string
+ avatar?: string
+ userid?: string
+ email?: string
+ signature?: string
+ title?: string
+ group?: string
+ tags?: { key?: string; label?: string }[]
+ notifyCount?: number
+ unreadCount?: number
+ country?: string
+ access?: string
+ geographic?: {
+ province?: { label?: string; key?: string }
+ city?: { label?: string; key?: string }
+ }
+ address?: string
+ phone?: string
+ }
+
+ /** 全局通过表格查询返回结果 */
+ type TableListResult = {
+ list: T
+ pagination: PaginationResult
+ }
+
+ /** 全局通用表格分页返回数据结构 */
+ type PaginationResult = {
+ page: number
+ size: number
+ total: number
+ }
+
+ /** 全局通用表格分页请求参数 */
+ type PageParams = {
+ limit?: number
+ page?: number
+ } & {
+ [P in keyof T]?: T[P]
+ }
+
+ type RuleListItem = {
+ key?: number
+ disabled?: boolean
+ href?: string
+ avatar?: string
+ name?: string
+ owner?: string
+ desc?: string
+ callNo?: number
+ status?: number
+ updatedAt?: string
+ createdAt?: string
+ progress?: number
+ }
+
+ type RuleList = {
+ data?: RuleListItem[]
+ /** 列表的内容总数 */
+ total?: number
+ success?: boolean
+ }
+
+ type FakeCaptcha = {
+ code?: number
+ status?: string
+ }
+
+ type ErrorResponse = {
+ /** 业务约定的错误码 */
+ errorCode: string
+ /** 业务上的错误信息 */
+ errorMessage?: string
+ /** 业务上的请求是否成功 */
+ success?: boolean
+ }
+
+ type NoticeIconList = {
+ data?: NoticeIconItem[]
+ /** 列表的内容总数 */
+ total?: number
+ success?: boolean
+ }
+
+ type NoticeIconItemType = 'notification' | 'message' | 'event'
+
+ type NoticeIconItem = {
+ id?: string
+ extra?: string
+ key?: string
+ read?: boolean
+ avatar?: string
+ title?: string
+ status?: string
+ datetime?: string
+ description?: string
+ type?: NoticeIconItemType
+ }
+}
diff --git a/src/assets/404.gif b/src/assets/404.gif
new file mode 100644
index 0000000000000000000000000000000000000000..cd6e0d9433421b3f29d0ec0c40f755e354728000
GIT binary patch
literal 164227
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