From b1781d9aef17395e165d1bf8f0fdb0dfbca0e280 Mon Sep 17 00:00:00 2001 From: Lishundong <577732344@qq.com> Date: Fri, 24 Oct 2025 09:40:46 +0800 Subject: [PATCH] init --- .editorconfig | 16 + .eslintignore | 8 + .eslintrc.js | 7 + .github/FUNDING.yml | 12 + .github/ISSUE_TEMPLATE/bug_report.md | 48 ++ .github/ISSUE_TEMPLATE/feature_request.md | 28 + .github/ISSUE_TEMPLATE/question.md | 34 + .github/workflows/ci.yml | 30 + .github/workflows/codeql.yml | 41 ++ .github/workflows/coverage.yml | 27 + .github/workflows/emoji-helper.yml | 14 + .github/workflows/issue-labeled.yml | 37 ++ .github/workflows/issue-open-check.yml | 34 + .github/workflows/pnpm.yml | 33 + .github/workflows/preview-build.yml | 41 ++ .github/workflows/preview-deploy.yml | 100 +++ .github/workflows/preview-start.yml | 24 + .gitignore | 44 ++ .hintrc | 13 + .husky/commit-msg | 7 + .husky/pre-commit | 4 + .prettierignore | 22 + .prettierrc.js | 21 + .vs/VSWorkspaceState.json | 6 + .vs/qingdao-admin/v17/.suo | Bin 0 -> 12800 bytes .vs/slnx.sqlite | Bin 0 -> 135168 bytes CODE_OF_CONDUCT.md | 46 ++ LICENSE | 21 + README.md | 138 ++++ config/config.ts | 159 +++++ config/defaultSettings.ts | 28 + config/oneapi.json | 593 ++++++++++++++++++ config/proxy.ts | 49 ++ config/routes.ts | 120 ++++ jest.config.ts | 23 + jsconfig.json | 11 + mock/listTableList.ts | 176 ++++++ mock/notices.ts | 115 ++++ mock/requestRecord.mock.js | 324 ++++++++++ mock/route.ts | 5 + mock/user.ts | 203 ++++++ package.json | 147 +++++ public/CNAME | 1 + public/favicon.ico | Bin 0 -> 4286 bytes public/icons/icon-128x128.png | Bin 0 -> 1329 bytes public/icons/icon-192x192.png | Bin 0 -> 1856 bytes public/icons/icon-512x512.png | Bin 0 -> 5082 bytes public/pro_icon.svg | 5 + public/scripts/loading.js | 202 ++++++ src/access.ts | 55 ++ src/app.tsx | 271 ++++++++ src/assets/logo.svg | 1 + src/components/DictTag/index.tsx | 115 ++++ src/components/Footer/index.tsx | 29 + src/components/HeaderDropdown/index.tsx | 27 + src/components/IconSelector/Category.tsx | 63 ++ src/components/IconSelector/CopyableIcon.tsx | 47 ++ .../IconSelector/IconPicSearcher.tsx | 233 +++++++ src/components/IconSelector/fields.ts | 223 +++++++ src/components/IconSelector/index.tsx | 142 +++++ src/components/IconSelector/style.less | 137 ++++ src/components/IconSelector/themeIcons.tsx | 41 ++ src/components/ProFromMap/index.less | 24 + src/components/ProFromMap/index.tsx | 226 +++++++ src/components/ProFromMap/point.png | Bin 0 -> 3554 bytes .../RightContent/AvatarDropdown.tsx | 143 +++++ src/components/RightContent/index.tsx | 31 + src/components/index.ts | 12 + src/enums/httpEnum.ts | 31 + src/enums/pagesEnums.ts | 4 + src/global.less | 73 +++ src/global.tsx | 91 +++ src/hooks/net/dict.ts | 7 + src/locales/en-US.ts | 27 + src/locales/en-US/app.ts | 26 + src/locales/en-US/component.ts | 5 + src/locales/en-US/globalHeader.ts | 17 + src/locales/en-US/menu.ts | 52 ++ src/locales/en-US/pages.ts | 71 +++ src/locales/en-US/pwa.ts | 6 + src/locales/en-US/settingDrawer.ts | 31 + src/locales/en-US/settings.ts | 60 ++ src/locales/zh-CN.ts | 57 ++ src/locales/zh-CN/app.ts | 23 + src/locales/zh-CN/component.ts | 5 + src/locales/zh-CN/globalHeader.ts | 17 + src/locales/zh-CN/menu.ts | 52 ++ src/locales/zh-CN/monitor/job-log.ts | 18 + src/locales/zh-CN/monitor/job.ts | 25 + src/locales/zh-CN/monitor/logininfor.ts | 13 + src/locales/zh-CN/monitor/onlineUser.ts | 20 + src/locales/zh-CN/monitor/operlog.ts | 19 + src/locales/zh-CN/monitor/server.ts | 27 + src/locales/zh-CN/pages.ts | 71 +++ src/locales/zh-CN/pwa.ts | 6 + src/locales/zh-CN/settingDrawer.ts | 31 + src/locales/zh-CN/settings.ts | 55 ++ src/locales/zh-CN/system/config.ts | 14 + src/locales/zh-CN/system/dept.ts | 18 + src/locales/zh-CN/system/dict-data.ts | 17 + src/locales/zh-CN/system/dict.ts | 12 + src/locales/zh-CN/system/menu.ts | 22 + src/locales/zh-CN/system/notice.ts | 13 + src/locales/zh-CN/system/post.ts | 13 + src/locales/zh-CN/system/role.ts | 21 + src/locales/zh-CN/system/user.ts | 31 + src/locales/zh-TW.ts | 20 + src/locales/zh-TW/component.ts | 5 + src/locales/zh-TW/globalHeader.ts | 17 + src/locales/zh-TW/menu.ts | 52 ++ src/locales/zh-TW/pages.ts | 68 ++ src/locales/zh-TW/pwa.ts | 6 + src/locales/zh-TW/settingDrawer.ts | 31 + src/locales/zh-TW/settings.ts | 55 ++ src/manifest.json | 22 + src/models/testModel.ts | 11 + src/pages/404.tsx | 18 + .../Industrytrend/components/chartcards.tsx | 215 +++++++ .../Industrytrend/components/chartconfigs.tsx | 456 ++++++++++++++ src/pages/Analysis/Industrytrend/index.tsx | 570 +++++++++++++++++ src/pages/Analysis/Industrytrend/utils.ts | 232 +++++++ src/pages/Analysis/User/index.tsx | 1 + .../Application/ModelManagement/index.tsx | 303 +++++++++ .../ModelManagement/modelStyle.less | 19 + src/pages/Application/Preproducts/edit.tsx | 143 +++++ src/pages/Application/Preproducts/index.tsx | 233 +++++++ src/pages/Area/Business/detail.tsx | 0 src/pages/Area/Business/edit.tsx | 173 +++++ src/pages/Area/Business/index.tsx | 204 ++++++ src/pages/Area/Subway/UpLine/edit.tsx | 184 ++++++ src/pages/Area/Subway/UpLine/index.tsx | 179 ++++++ src/pages/Area/Subway/edit.tsx | 90 +++ src/pages/Area/Subway/index.tsx | 176 ++++++ src/pages/Classify/Industry/edit.tsx | 190 ++++++ src/pages/Classify/Industry/index.tsx | 256 ++++++++ src/pages/Classify/Jobs/edit.tsx | 159 +++++ src/pages/Classify/Jobs/index.tsx | 211 +++++++ src/pages/Company/List/edit.tsx | 154 +++++ src/pages/Company/List/index.tsx | 279 ++++++++ src/pages/Jobfair/List/edit.tsx | 247 ++++++++ src/pages/Jobfair/List/index.tsx | 227 +++++++ src/pages/Logs/Logininfor/edit.tsx | 216 +++++++ src/pages/Logs/Logininfor/index.tsx | 335 ++++++++++ src/pages/Logs/MobileLogininfor/edit.tsx | 216 +++++++ src/pages/Logs/MobileLogininfor/index.tsx | 335 ++++++++++ src/pages/Logs/Mobilelog/detail.tsx | 113 ++++ src/pages/Logs/Mobilelog/index.tsx | 330 ++++++++++ src/pages/Logs/Operlog/detail.tsx | 113 ++++ src/pages/Logs/Operlog/index.tsx | 366 +++++++++++ .../Management/List/SeeMatching/detail.tsx | 74 +++ .../Management/List/SeeMatching/index.tsx | 235 +++++++ src/pages/Management/List/edit.tsx | 207 ++++++ src/pages/Management/List/index.tsx | 337 ++++++++++ src/pages/Mobileusers/List/index.tsx | 177 ++++++ src/pages/Monitor/Cache/List.tsx | 240 +++++++ src/pages/Monitor/Cache/List/index.less | 10 + src/pages/Monitor/Cache/index.less | 33 + src/pages/Monitor/Cache/index.tsx | 201 ++++++ src/pages/Monitor/Druid/index.tsx | 31 + src/pages/Monitor/Job/detail.tsx | 131 ++++ src/pages/Monitor/Job/edit.tsx | 232 +++++++ src/pages/Monitor/Job/index.tsx | 460 ++++++++++++++ src/pages/Monitor/JobLog/detail.tsx | 105 ++++ src/pages/Monitor/JobLog/index.tsx | 343 ++++++++++ src/pages/Monitor/Online/index.tsx | 162 +++++ src/pages/Monitor/Server/index.tsx | 267 ++++++++ src/pages/Monitor/Server/style.less | 11 + src/pages/System/AdminDict/edit.tsx | 152 +++++ src/pages/System/AdminDict/index.tsx | 394 ++++++++++++ src/pages/System/AdminDictData/edit.tsx | 252 ++++++++ src/pages/System/AdminDictData/index.tsx | 439 +++++++++++++ src/pages/System/Config/edit.tsx | 172 +++++ src/pages/System/Config/index.tsx | 398 ++++++++++++ src/pages/System/Dept/edit.tsx | 212 +++++++ src/pages/System/Dept/index.tsx | 346 ++++++++++ src/pages/System/Dict/edit.tsx | 152 +++++ src/pages/System/Dict/index.tsx | 394 ++++++++++++ src/pages/System/DictData/edit.tsx | 252 ++++++++ src/pages/System/DictData/index.tsx | 454 ++++++++++++++ src/pages/System/Menu/edit.tsx | 392 ++++++++++++ src/pages/System/Menu/index.tsx | 342 ++++++++++ src/pages/System/Notice/edit.tsx | 174 +++++ src/pages/System/Notice/index.tsx | 366 +++++++++++ src/pages/System/Post/edit.tsx | 166 +++++ src/pages/System/Post/index.tsx | 366 +++++++++++ src/pages/System/Role/authUser.tsx | 274 ++++++++ .../System/Role/components/DataScope.tsx | 233 +++++++ .../Role/components/UserSelectorModal.tsx | 125 ++++ src/pages/System/Role/edit.tsx | 199 ++++++ src/pages/System/Role/index.tsx | 513 +++++++++++++++ src/pages/System/User/components/AuthRole.tsx | 81 +++ src/pages/System/User/components/DeptTree.tsx | 69 ++ src/pages/System/User/components/ResetPwd.tsx | 95 +++ src/pages/System/User/edit.tsx | 279 ++++++++ src/pages/System/User/index.tsx | 561 +++++++++++++++++ src/pages/Tool/Gen/components/BaseInfo.tsx | 124 ++++ src/pages/Tool/Gen/components/ColumnInfo.tsx | 304 +++++++++ src/pages/Tool/Gen/components/GenInfo.tsx | 330 ++++++++++ src/pages/Tool/Gen/components/PreviewCode.tsx | 50 ++ src/pages/Tool/Gen/data.d.ts | 106 ++++ src/pages/Tool/Gen/edit.tsx | 183 ++++++ src/pages/Tool/Gen/import.tsx | 107 ++++ src/pages/Tool/Gen/index.tsx | 360 +++++++++++ src/pages/Tool/Gen/locales/zh-CN.ts | 8 + src/pages/Tool/Gen/service.ts | 106 ++++ src/pages/Tool/Gen/style.less | 4 + src/pages/Tool/Swagger/index.tsx | 31 + src/pages/User/Center/Center.less | 61 ++ .../components/AvatarCropper/cropper.css | 309 +++++++++ .../components/AvatarCropper/images/bg.png | Bin 0 -> 168 bytes .../components/AvatarCropper/index.less | 10 + .../Center/components/AvatarCropper/index.tsx | 144 +++++ .../User/Center/components/BaseInfo/index.tsx | 119 ++++ .../Center/components/ResetPassword/index.tsx | 84 +++ src/pages/User/Center/index.tsx | 200 ++++++ src/pages/User/Login/index.tsx | 439 +++++++++++++ src/pages/User/Settings/index.tsx | 20 + src/pages/Welcome.tsx | 164 +++++ src/requestErrorConfig.ts | 109 ++++ src/service-worker.js | 65 ++ src/services/Management/list.ts | 48 ++ src/services/analysis/industry.ts | 52 ++ src/services/ant-design-pro/api.ts | 11 + src/services/ant-design-pro/index.ts | 12 + src/services/ant-design-pro/login.ts | 38 ++ src/services/ant-design-pro/rule.ts | 42 ++ src/services/ant-design-pro/typings.d.ts | 108 ++++ src/services/application/preproducts.ts | 28 + src/services/area/business.ts | 33 + src/services/area/subway.ts | 39 ++ src/services/area/upline.ts | 33 + src/services/classify/industry.ts | 43 ++ src/services/classify/jobs.ts | 17 + src/services/company/list.ts | 33 + src/services/jobfair/list.ts | 45 ++ src/services/logs/logininfor.ts | 68 ++ src/services/logs/mobilelog.ts | 45 ++ src/services/logs/mobilelogininfor.ts | 68 ++ src/services/logs/operlog.ts | 60 ++ src/services/mobileusers/list.ts | 23 + src/services/monitor/cache.ts | 17 + src/services/monitor/cachelist.ts | 51 ++ src/services/monitor/job.ts | 73 +++ src/services/monitor/jobLog.ts | 40 ++ src/services/monitor/online.ts | 23 + src/services/monitor/server.ts | 16 + src/services/session.ts | 159 +++++ src/services/swagger/index.ts | 12 + src/services/swagger/pet.ts | 153 +++++ src/services/swagger/store.ts | 48 ++ src/services/swagger/typings.d.ts | 112 ++++ src/services/swagger/user.ts | 100 +++ src/services/system/admindicdata.ts | 65 ++ src/services/system/admindict.ts | 120 ++++ src/services/system/auth.ts | 39 ++ src/services/system/config.ts | 62 ++ src/services/system/dept.ts | 56 ++ src/services/system/dict.ts | 144 +++++ src/services/system/dictdata.ts | 72 +++ src/services/system/index.ts | 14 + src/services/system/menu.ts | 61 ++ src/services/system/notice.ts | 49 ++ src/services/system/post.ts | 54 ++ src/services/system/role.ts | 128 ++++ src/services/system/user.ts | 152 +++++ src/services/typings.d.ts | 191 ++++++ src/types/Management/list.d.ts | 72 +++ src/types/analysis/industry.d.ts | 103 +++ src/types/application/preproducts.d.ts | 26 + src/types/area/business.d.ts | 39 ++ src/types/area/subway.d.ts | 44 ++ src/types/area/upline.d.ts | 44 ++ src/types/classify/industry.d.ts | 43 ++ src/types/classify/jobs.d.ts | 33 + src/types/company/list.d.ts | 29 + src/types/jobfair/list.d.ts | 39 ++ src/types/logs/logininfor.d.ts | 43 ++ src/types/logs/mobilelog.d.ts | 57 ++ src/types/logs/mobilelogoninfor.ts | 43 ++ src/types/logs/operlog.d.ts | 57 ++ src/types/mobileusers/list.d.ts | 38 ++ src/types/monitor/cache.d.ts | 153 +++++ src/types/monitor/cacheList.d.ts | 36 ++ src/types/monitor/job.d.ts | 58 ++ src/types/monitor/jobLog.d.ts | 47 ++ src/types/monitor/online.d.ts | 55 ++ src/types/monitor/server.d.ts | 84 +++ src/types/system/config.d.ts | 45 ++ src/types/system/dept.d.ts | 53 ++ src/types/system/dict-data.d.ts | 53 ++ src/types/system/dict.d.ts | 48 ++ src/types/system/menu.d.ts | 66 ++ src/types/system/notice.d.ts | 45 ++ src/types/system/post.d.ts | 45 ++ src/types/system/role.d.ts | 65 ++ src/types/system/user.d.ts | 71 +++ src/types/typings.d.ts | 0 src/typings.d.ts | 32 + src/utils/IconUtil.ts | 20 + src/utils/downloadfile.ts | 63 ++ src/utils/options.ts | 12 + src/utils/permission.ts | 64 ++ src/utils/similarity_Job.js | 401 ++++++++++++ src/utils/tools.ts | 20 + src/utils/tree.ts | 93 +++ tests/setupTests.jsx | 64 ++ tsconfig.json | 23 + types/cache/cache.json | 1 + types/cache/login.cache.json | 386 ++++++++++++ types/cache/mock/login.mock.cache.js | 324 ++++++++++ types/cache/mock/mock.cache.js | 0 types/index.d.ts | 120 ++++ types/route.d.ts | 18 + 313 files changed, 33845 insertions(+) create mode 100644 .editorconfig create mode 100644 .eslintignore create mode 100644 .eslintrc.js create mode 100644 .github/FUNDING.yml create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/question.md create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/coverage.yml create mode 100644 .github/workflows/emoji-helper.yml create mode 100644 .github/workflows/issue-labeled.yml create mode 100644 .github/workflows/issue-open-check.yml create mode 100644 .github/workflows/pnpm.yml create mode 100644 .github/workflows/preview-build.yml create mode 100644 .github/workflows/preview-deploy.yml create mode 100644 .github/workflows/preview-start.yml create mode 100644 .gitignore create mode 100644 .hintrc create mode 100644 .husky/commit-msg create mode 100644 .husky/pre-commit create mode 100644 .prettierignore create mode 100644 .prettierrc.js create mode 100644 .vs/VSWorkspaceState.json create mode 100644 .vs/qingdao-admin/v17/.suo create mode 100644 .vs/slnx.sqlite create mode 100644 CODE_OF_CONDUCT.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 config/config.ts create mode 100644 config/defaultSettings.ts create mode 100644 config/oneapi.json create mode 100644 config/proxy.ts create mode 100644 config/routes.ts create mode 100644 jest.config.ts create mode 100644 jsconfig.json create mode 100644 mock/listTableList.ts create mode 100644 mock/notices.ts create mode 100644 mock/requestRecord.mock.js create mode 100644 mock/route.ts create mode 100644 mock/user.ts create mode 100644 package.json create mode 100644 public/CNAME create mode 100644 public/favicon.ico create mode 100644 public/icons/icon-128x128.png create mode 100644 public/icons/icon-192x192.png create mode 100644 public/icons/icon-512x512.png create mode 100644 public/pro_icon.svg create mode 100644 public/scripts/loading.js create mode 100644 src/access.ts create mode 100644 src/app.tsx create mode 100644 src/assets/logo.svg create mode 100644 src/components/DictTag/index.tsx create mode 100644 src/components/Footer/index.tsx create mode 100644 src/components/HeaderDropdown/index.tsx create mode 100644 src/components/IconSelector/Category.tsx create mode 100644 src/components/IconSelector/CopyableIcon.tsx create mode 100644 src/components/IconSelector/IconPicSearcher.tsx create mode 100644 src/components/IconSelector/fields.ts create mode 100644 src/components/IconSelector/index.tsx create mode 100644 src/components/IconSelector/style.less create mode 100644 src/components/IconSelector/themeIcons.tsx create mode 100644 src/components/ProFromMap/index.less create mode 100644 src/components/ProFromMap/index.tsx create mode 100644 src/components/ProFromMap/point.png create mode 100644 src/components/RightContent/AvatarDropdown.tsx create mode 100644 src/components/RightContent/index.tsx create mode 100644 src/components/index.ts create mode 100644 src/enums/httpEnum.ts create mode 100644 src/enums/pagesEnums.ts create mode 100644 src/global.less create mode 100644 src/global.tsx create mode 100644 src/hooks/net/dict.ts create mode 100644 src/locales/en-US.ts create mode 100644 src/locales/en-US/app.ts create mode 100644 src/locales/en-US/component.ts create mode 100644 src/locales/en-US/globalHeader.ts create mode 100644 src/locales/en-US/menu.ts create mode 100644 src/locales/en-US/pages.ts create mode 100644 src/locales/en-US/pwa.ts create mode 100644 src/locales/en-US/settingDrawer.ts create mode 100644 src/locales/en-US/settings.ts create mode 100644 src/locales/zh-CN.ts create mode 100644 src/locales/zh-CN/app.ts create mode 100644 src/locales/zh-CN/component.ts create mode 100644 src/locales/zh-CN/globalHeader.ts create mode 100644 src/locales/zh-CN/menu.ts create mode 100644 src/locales/zh-CN/monitor/job-log.ts create mode 100644 src/locales/zh-CN/monitor/job.ts create mode 100644 src/locales/zh-CN/monitor/logininfor.ts create mode 100644 src/locales/zh-CN/monitor/onlineUser.ts create mode 100644 src/locales/zh-CN/monitor/operlog.ts create mode 100644 src/locales/zh-CN/monitor/server.ts create mode 100644 src/locales/zh-CN/pages.ts create mode 100644 src/locales/zh-CN/pwa.ts create mode 100644 src/locales/zh-CN/settingDrawer.ts create mode 100644 src/locales/zh-CN/settings.ts create mode 100644 src/locales/zh-CN/system/config.ts create mode 100644 src/locales/zh-CN/system/dept.ts create mode 100644 src/locales/zh-CN/system/dict-data.ts create mode 100644 src/locales/zh-CN/system/dict.ts create mode 100644 src/locales/zh-CN/system/menu.ts create mode 100644 src/locales/zh-CN/system/notice.ts create mode 100644 src/locales/zh-CN/system/post.ts create mode 100644 src/locales/zh-CN/system/role.ts create mode 100644 src/locales/zh-CN/system/user.ts create mode 100644 src/locales/zh-TW.ts create mode 100644 src/locales/zh-TW/component.ts create mode 100644 src/locales/zh-TW/globalHeader.ts create mode 100644 src/locales/zh-TW/menu.ts create mode 100644 src/locales/zh-TW/pages.ts create mode 100644 src/locales/zh-TW/pwa.ts create mode 100644 src/locales/zh-TW/settingDrawer.ts create mode 100644 src/locales/zh-TW/settings.ts create mode 100644 src/manifest.json create mode 100644 src/models/testModel.ts create mode 100644 src/pages/404.tsx create mode 100644 src/pages/Analysis/Industrytrend/components/chartcards.tsx create mode 100644 src/pages/Analysis/Industrytrend/components/chartconfigs.tsx create mode 100644 src/pages/Analysis/Industrytrend/index.tsx create mode 100644 src/pages/Analysis/Industrytrend/utils.ts create mode 100644 src/pages/Analysis/User/index.tsx create mode 100644 src/pages/Application/ModelManagement/index.tsx create mode 100644 src/pages/Application/ModelManagement/modelStyle.less create mode 100644 src/pages/Application/Preproducts/edit.tsx create mode 100644 src/pages/Application/Preproducts/index.tsx create mode 100644 src/pages/Area/Business/detail.tsx create mode 100644 src/pages/Area/Business/edit.tsx create mode 100644 src/pages/Area/Business/index.tsx create mode 100644 src/pages/Area/Subway/UpLine/edit.tsx create mode 100644 src/pages/Area/Subway/UpLine/index.tsx create mode 100644 src/pages/Area/Subway/edit.tsx create mode 100644 src/pages/Area/Subway/index.tsx create mode 100644 src/pages/Classify/Industry/edit.tsx create mode 100644 src/pages/Classify/Industry/index.tsx create mode 100644 src/pages/Classify/Jobs/edit.tsx create mode 100644 src/pages/Classify/Jobs/index.tsx create mode 100644 src/pages/Company/List/edit.tsx create mode 100644 src/pages/Company/List/index.tsx create mode 100644 src/pages/Jobfair/List/edit.tsx create mode 100644 src/pages/Jobfair/List/index.tsx create mode 100644 src/pages/Logs/Logininfor/edit.tsx create mode 100644 src/pages/Logs/Logininfor/index.tsx create mode 100644 src/pages/Logs/MobileLogininfor/edit.tsx create mode 100644 src/pages/Logs/MobileLogininfor/index.tsx create mode 100644 src/pages/Logs/Mobilelog/detail.tsx create mode 100644 src/pages/Logs/Mobilelog/index.tsx create mode 100644 src/pages/Logs/Operlog/detail.tsx create mode 100644 src/pages/Logs/Operlog/index.tsx create mode 100644 src/pages/Management/List/SeeMatching/detail.tsx create mode 100644 src/pages/Management/List/SeeMatching/index.tsx create mode 100644 src/pages/Management/List/edit.tsx create mode 100644 src/pages/Management/List/index.tsx create mode 100644 src/pages/Mobileusers/List/index.tsx create mode 100644 src/pages/Monitor/Cache/List.tsx create mode 100644 src/pages/Monitor/Cache/List/index.less create mode 100644 src/pages/Monitor/Cache/index.less create mode 100644 src/pages/Monitor/Cache/index.tsx create mode 100644 src/pages/Monitor/Druid/index.tsx create mode 100644 src/pages/Monitor/Job/detail.tsx create mode 100644 src/pages/Monitor/Job/edit.tsx create mode 100644 src/pages/Monitor/Job/index.tsx create mode 100644 src/pages/Monitor/JobLog/detail.tsx create mode 100644 src/pages/Monitor/JobLog/index.tsx create mode 100644 src/pages/Monitor/Online/index.tsx create mode 100644 src/pages/Monitor/Server/index.tsx create mode 100644 src/pages/Monitor/Server/style.less create mode 100644 src/pages/System/AdminDict/edit.tsx create mode 100644 src/pages/System/AdminDict/index.tsx create mode 100644 src/pages/System/AdminDictData/edit.tsx create mode 100644 src/pages/System/AdminDictData/index.tsx create mode 100644 src/pages/System/Config/edit.tsx create mode 100644 src/pages/System/Config/index.tsx create mode 100644 src/pages/System/Dept/edit.tsx create mode 100644 src/pages/System/Dept/index.tsx create mode 100644 src/pages/System/Dict/edit.tsx create mode 100644 src/pages/System/Dict/index.tsx create mode 100644 src/pages/System/DictData/edit.tsx create mode 100644 src/pages/System/DictData/index.tsx create mode 100644 src/pages/System/Menu/edit.tsx create mode 100644 src/pages/System/Menu/index.tsx create mode 100644 src/pages/System/Notice/edit.tsx create mode 100644 src/pages/System/Notice/index.tsx create mode 100644 src/pages/System/Post/edit.tsx create mode 100644 src/pages/System/Post/index.tsx create mode 100644 src/pages/System/Role/authUser.tsx create mode 100644 src/pages/System/Role/components/DataScope.tsx create mode 100644 src/pages/System/Role/components/UserSelectorModal.tsx create mode 100644 src/pages/System/Role/edit.tsx create mode 100644 src/pages/System/Role/index.tsx create mode 100644 src/pages/System/User/components/AuthRole.tsx create mode 100644 src/pages/System/User/components/DeptTree.tsx create mode 100644 src/pages/System/User/components/ResetPwd.tsx create mode 100644 src/pages/System/User/edit.tsx create mode 100644 src/pages/System/User/index.tsx create mode 100644 src/pages/Tool/Gen/components/BaseInfo.tsx create mode 100644 src/pages/Tool/Gen/components/ColumnInfo.tsx create mode 100644 src/pages/Tool/Gen/components/GenInfo.tsx create mode 100644 src/pages/Tool/Gen/components/PreviewCode.tsx create mode 100644 src/pages/Tool/Gen/data.d.ts create mode 100644 src/pages/Tool/Gen/edit.tsx create mode 100644 src/pages/Tool/Gen/import.tsx create mode 100644 src/pages/Tool/Gen/index.tsx create mode 100644 src/pages/Tool/Gen/locales/zh-CN.ts create mode 100644 src/pages/Tool/Gen/service.ts create mode 100644 src/pages/Tool/Gen/style.less create mode 100644 src/pages/Tool/Swagger/index.tsx create mode 100644 src/pages/User/Center/Center.less create mode 100644 src/pages/User/Center/components/AvatarCropper/cropper.css create mode 100644 src/pages/User/Center/components/AvatarCropper/images/bg.png create mode 100644 src/pages/User/Center/components/AvatarCropper/index.less create mode 100644 src/pages/User/Center/components/AvatarCropper/index.tsx create mode 100644 src/pages/User/Center/components/BaseInfo/index.tsx create mode 100644 src/pages/User/Center/components/ResetPassword/index.tsx create mode 100644 src/pages/User/Center/index.tsx create mode 100644 src/pages/User/Login/index.tsx create mode 100644 src/pages/User/Settings/index.tsx create mode 100644 src/pages/Welcome.tsx create mode 100644 src/requestErrorConfig.ts create mode 100644 src/service-worker.js create mode 100644 src/services/Management/list.ts create mode 100644 src/services/analysis/industry.ts create mode 100644 src/services/ant-design-pro/api.ts create mode 100644 src/services/ant-design-pro/index.ts create mode 100644 src/services/ant-design-pro/login.ts create mode 100644 src/services/ant-design-pro/rule.ts create mode 100644 src/services/ant-design-pro/typings.d.ts create mode 100644 src/services/application/preproducts.ts create mode 100644 src/services/area/business.ts create mode 100644 src/services/area/subway.ts create mode 100644 src/services/area/upline.ts create mode 100644 src/services/classify/industry.ts create mode 100644 src/services/classify/jobs.ts create mode 100644 src/services/company/list.ts create mode 100644 src/services/jobfair/list.ts create mode 100644 src/services/logs/logininfor.ts create mode 100644 src/services/logs/mobilelog.ts create mode 100644 src/services/logs/mobilelogininfor.ts create mode 100644 src/services/logs/operlog.ts create mode 100644 src/services/mobileusers/list.ts create mode 100644 src/services/monitor/cache.ts create mode 100644 src/services/monitor/cachelist.ts create mode 100644 src/services/monitor/job.ts create mode 100644 src/services/monitor/jobLog.ts create mode 100644 src/services/monitor/online.ts create mode 100644 src/services/monitor/server.ts create mode 100644 src/services/session.ts create mode 100644 src/services/swagger/index.ts create mode 100644 src/services/swagger/pet.ts create mode 100644 src/services/swagger/store.ts create mode 100644 src/services/swagger/typings.d.ts create mode 100644 src/services/swagger/user.ts create mode 100644 src/services/system/admindicdata.ts create mode 100644 src/services/system/admindict.ts create mode 100644 src/services/system/auth.ts create mode 100644 src/services/system/config.ts create mode 100644 src/services/system/dept.ts create mode 100644 src/services/system/dict.ts create mode 100644 src/services/system/dictdata.ts create mode 100644 src/services/system/index.ts create mode 100644 src/services/system/menu.ts create mode 100644 src/services/system/notice.ts create mode 100644 src/services/system/post.ts create mode 100644 src/services/system/role.ts create mode 100644 src/services/system/user.ts create mode 100644 src/services/typings.d.ts create mode 100644 src/types/Management/list.d.ts create mode 100644 src/types/analysis/industry.d.ts create mode 100644 src/types/application/preproducts.d.ts create mode 100644 src/types/area/business.d.ts create mode 100644 src/types/area/subway.d.ts create mode 100644 src/types/area/upline.d.ts create mode 100644 src/types/classify/industry.d.ts create mode 100644 src/types/classify/jobs.d.ts create mode 100644 src/types/company/list.d.ts create mode 100644 src/types/jobfair/list.d.ts create mode 100644 src/types/logs/logininfor.d.ts create mode 100644 src/types/logs/mobilelog.d.ts create mode 100644 src/types/logs/mobilelogoninfor.ts create mode 100644 src/types/logs/operlog.d.ts create mode 100644 src/types/mobileusers/list.d.ts create mode 100644 src/types/monitor/cache.d.ts create mode 100644 src/types/monitor/cacheList.d.ts create mode 100644 src/types/monitor/job.d.ts create mode 100644 src/types/monitor/jobLog.d.ts create mode 100644 src/types/monitor/online.d.ts create mode 100644 src/types/monitor/server.d.ts create mode 100644 src/types/system/config.d.ts create mode 100644 src/types/system/dept.d.ts create mode 100644 src/types/system/dict-data.d.ts create mode 100644 src/types/system/dict.d.ts create mode 100644 src/types/system/menu.d.ts create mode 100644 src/types/system/notice.d.ts create mode 100644 src/types/system/post.d.ts create mode 100644 src/types/system/role.d.ts create mode 100644 src/types/system/user.d.ts create mode 100644 src/types/typings.d.ts create mode 100644 src/typings.d.ts create mode 100644 src/utils/IconUtil.ts create mode 100644 src/utils/downloadfile.ts create mode 100644 src/utils/options.ts create mode 100644 src/utils/permission.ts create mode 100644 src/utils/similarity_Job.js create mode 100644 src/utils/tools.ts create mode 100644 src/utils/tree.ts create mode 100644 tests/setupTests.jsx create mode 100644 tsconfig.json create mode 100644 types/cache/cache.json create mode 100644 types/cache/login.cache.json create mode 100644 types/cache/mock/login.mock.cache.js create mode 100644 types/cache/mock/mock.cache.js create mode 100644 types/index.d.ts create mode 100644 types/route.d.ts diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7e3649a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +# http://editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false + +[Makefile] +indent_style = tab diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..8336e93 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,8 @@ +/lambda/ +/scripts +/config +.history +public +dist +.umi +mock \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..3ac39ef --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: [require.resolve('@umijs/lint/dist/config/eslint')], + globals: { + page: true, + REACT_APP_ENV: true, + }, +}; diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..26b00e2 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: ant-design +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..5cb2692 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,48 @@ +--- +name: '报告 Bug | Report bug 🐛' +about: 报告 Ant Design Pro 的 bug +title: '🐛 [BUG]' +labels: '🐛 bug' +assignees: '' +--- + +### 🐛 bug 描述 + + + +### 📷 复现步骤 | Recurrence steps + + + +### 🏞 期望结果 | Expected results + + + +### 💻 复现代码 | Recurrence code + + + +### © 版本信息 + +- Ant Design Pro 版本: [e.g. 4.0.0] +- umi 版本 +- 浏览器环境 +- 开发环境 [e.g. mac OS] + +### 🚑 其他信息 + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..b2b866a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,28 @@ +--- +name: '功能需求 | Feature Requirements ✨' +about: 对 Ant Design Pro 的需求或建议 +title: '👑 [需求 | Feature]' +labels: '👑 Feature Request' +assignees: '' +--- + +### 🥰 需求描述 | Requirements description + + + +### 🧐 解决方案 | Solution + + + +### 🚑 其他信息 | Other information + + diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md new file mode 100644 index 0000000..f0fbe7d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.md @@ -0,0 +1,34 @@ +--- +name: '疑问或需要帮助 | Questions or need help ❓' +about: 对 Ant Design Pro 使用的疑问或需要帮助 +title: '🧐[问题 | question]' +labels: '🧐 question' +assignees: '' +--- + +### 🧐 问题描述 | Problem description + + + +### 💻 示例代码 | Sample code + + + +### 🚑 其他信息 | Other information + + + +OS: + +Node: + +浏览器 | browser: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d6f5693 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,30 @@ +name: Node CI + +on: [push, pull_request] + +permissions: + contents: read + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + node_version: [16.x, 14.x] + os: [ubuntu-latest, windows-latest, macOS-latest] + steps: + - uses: actions/checkout@v1 + - name: Use Node.js ${{ matrix.node_version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node_version }} + - run: echo ${{github.ref}} + - run: npm install + - run: yarn run lint + - run: yarn run tsc + - run: yarn run build + env: + CI: true + PROGRESS: none + NODE_ENV: test + NODE_OPTIONS: --max_old_space_size=4096 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..705b30e --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,41 @@ +name: "CodeQL" + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + schedule: + - cron: "48 12 * * 2" + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ javascript ] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + queries: +security-and-quality + + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 0000000..d145753 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,27 @@ +name: coverage CI + +on: [push, pull_request] + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Use Node.js 16.x + uses: actions/setup-node@v1 + with: + node-version: 16.x + - run: echo ${{github.ref}} + - run: curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm@7 + - run: pnpm config set store-dir ~/.pnpm-store + - run: pnpm install --strict-peer-dependencies=false + - run: yarn run test:coverage + env: + CI: true + PROGRESS: none + NODE_ENV: test + NODE_OPTIONS: --max_old_space_size=4096 + - run: bash <(curl -s https://codecov.io/bash) diff --git a/.github/workflows/emoji-helper.yml b/.github/workflows/emoji-helper.yml new file mode 100644 index 0000000..8965a1a --- /dev/null +++ b/.github/workflows/emoji-helper.yml @@ -0,0 +1,14 @@ +name: Emoji Helper + +on: + release: + types: [published] + +jobs: + emoji: + runs-on: ubuntu-latest + steps: + - uses: actions-cool/emoji-helper@v1.0.0 + with: + type: 'release' + emoji: '+1, laugh, heart, hooray, rocket, eyes' diff --git a/.github/workflows/issue-labeled.yml b/.github/workflows/issue-labeled.yml new file mode 100644 index 0000000..a3e8b5f --- /dev/null +++ b/.github/workflows/issue-labeled.yml @@ -0,0 +1,37 @@ +name: Issue labeled + +on: + issues: + types: [labeled] + +jobs: + reply-helper: + runs-on: ubuntu-latest + steps: + - name: help wanted + if: github.event.label.name == '❤️ help wanted' || github.event.label.name == '🤝Welcome PR' + uses: actions-cool/issues-helper@v1.11 + with: + actions: 'create-comment' + token: ${{ secrets.GITHUB_TOKEN }} + issue-number: ${{ github.event.issue.number }} + body: | + Hello @${{ github.event.issue.user.login }}. We totally like your proposal/feedback, welcome to [send us a Pull Request](https://help.github.com/en/articles/creating-a-pull-request) for it. Please provide changelog/TypeScript/documentation/test cases if needed and make sure CI passed, we will review it soon. We appreciate your effort in advance and looking forward to your contribution! + + 你好 @${{ github.event.issue.user.login }},我们完全同意你的提议/反馈,欢迎直接在此仓库 [创建一个 Pull Request](https://help.github.com/en/articles/creating-a-pull-request) 来解决这个问题。请务必提供改动所需相应的 changelog、TypeScript 定义、测试用例、文档等,并确保 CI 通过,我们会尽快进行 Review,提前感谢和期待您的贡献。 + + ![giphy](https://user-images.githubusercontent.com/507615/62342668-4735dc00-b51a-11e9-92a7-d46fbb1cc0c7.gif) + + - name: Need Reproduce + if: github.event.label.name == '🤔 Need Reproduce' + uses: actions-cool/issues-helper@v1.11 + with: + actions: 'create-comment' + token: ${{ secrets.GITHUB_TOKEN }} + issue-number: ${{ github.event.issue.number }} + body: | + Hello @${{ github.event.issue.user.login }}. Please provide a online reproduction by forking this link https://codesandbox.io/ or a minimal GitHub repository. + + 你好 @${{ github.event.issue.user.login }}, 我们需要你提供一个在线的重现实例以便于我们帮你排查问题。你可以通过点击 [此处](https://codesandbox.io/) 创建一个 codesandbox 或者提供一个最小化的 GitHub 仓库。 + + ![](https://gw.alipayobjects.com/zos/antfincdn/y9kwg7DVCd/reproduce.gif) diff --git a/.github/workflows/issue-open-check.yml b/.github/workflows/issue-open-check.yml new file mode 100644 index 0000000..3644213 --- /dev/null +++ b/.github/workflows/issue-open-check.yml @@ -0,0 +1,34 @@ +name: Issue Open Check + +on: + issues: + types: [opened, edited] + +jobs: + check-issue: + runs-on: ubuntu-latest + steps: + - uses: actions-cool/issues-helper@v2.2.0 + id: check + with: + actions: 'check-issue' + issue-number: ${{ github.event.issue.number }} + title-excludes: '🐛 [BUG], 👑 [需求 | Feature], 🧐[问题 | question]' + + - if: steps.check.outputs.check-result == 'false' && github.event.issue.state == 'open' + uses: actions-cool/issues-helper@v2.2.0 + with: + actions: 'create-comment, close-issue' + issue-number: ${{ github.event.issue.number }} + body: | + 当前 Issue 未检测到标题,请规范填写,谢谢! + + The title of the current issue is not detected, please fill in according to the specifications, thank you! + + - if: steps.check.outputs.check-result == 'true' + uses: actions-cool/issues-similarity-analysis@v1 + with: + filter-threshold: 0.8 + title-excludes: '🐛[BUG], 👑 [需求 | Feature], 🧐[问题 | question]' + comment-title: '### 以下的 Issues 可能会帮助到你 / The following issues may help you' + show-footer: false diff --git a/.github/workflows/pnpm.yml b/.github/workflows/pnpm.yml new file mode 100644 index 0000000..63bb2e4 --- /dev/null +++ b/.github/workflows/pnpm.yml @@ -0,0 +1,33 @@ +name: Node pnpm CI + +on: [push, pull_request] + +permissions: + contents: read + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + node_version: [16.x] + os: [ubuntu-latest, windows-latest, macOS-latest] + steps: + - uses: actions/checkout@v1 + - name: Use Node.js ${{ matrix.node_version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node_version }} + - run: echo ${{github.ref}} + - run: curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm@7 + - run: pnpm config set store-dir ~/.pnpm-store + - run: pnpm install --strict-peer-dependencies=false + - run: pnpm run lint + - run: pnpm run tsc + - run: pnpm run build + - run: pnpm run test + env: + CI: true + PROGRESS: none + NODE_ENV: test + NODE_OPTIONS: --max_old_space_size=4096 diff --git a/.github/workflows/preview-build.yml b/.github/workflows/preview-build.yml new file mode 100644 index 0000000..d8667a5 --- /dev/null +++ b/.github/workflows/preview-build.yml @@ -0,0 +1,41 @@ +name: Preview Build + +on: + pull_request: + types: [opened, synchronize, reopened] + +permissions: + contents: read + +jobs: + build-preview: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: build + run: | + yarn + yarn add umi-plugin-pro --save + yarn build + + - name: upload dist artifact + uses: actions/upload-artifact@v2 + with: + name: dist + path: dist/ + retention-days: 5 + + - name: Save PR number + if: ${{ always() }} + run: echo ${{ github.event.number }} > ./pr-id.txt + + - name: Upload PR number + if: ${{ always() }} + uses: actions/upload-artifact@v2 + with: + name: pr + path: ./pr-id.txt diff --git a/.github/workflows/preview-deploy.yml b/.github/workflows/preview-deploy.yml new file mode 100644 index 0000000..e9a699f --- /dev/null +++ b/.github/workflows/preview-deploy.yml @@ -0,0 +1,100 @@ +name: Preview Deploy + +on: + workflow_run: + workflows: ['Preview Build'] + types: + - completed + +permissions: + contents: read + +jobs: + success: + permissions: + actions: read # for dawidd6/action-download-artifact to query and download artifacts + issues: write # for actions-cool/maintain-one-comment to modify or create issue comments + pull-requests: write # for actions-cool/maintain-one-comment to modify or create PR comments + runs-on: ubuntu-latest + if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' + steps: + - name: download pr artifact + uses: dawidd6/action-download-artifact@v2 + with: + workflow: ${{ github.event.workflow_run.workflow_id }} + name: pr + + - name: save PR id + id: pr + run: echo "::set-output name=id::$( + + + body-include: '' + number: ${{ steps.pr.outputs.id }} + + - name: The job failed + if: ${{ failure() }} + uses: actions-cool/maintain-one-comment@v1.2.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + body: | + 😭 Deploy PR Preview failed. + + + + + body-include: '' + number: ${{ steps.pr.outputs.id }} + + failed: + permissions: + actions: read # for dawidd6/action-download-artifact to query and download artifacts + issues: write # for actions-cool/maintain-one-comment to modify or create issue comments + pull-requests: write # for actions-cool/maintain-one-comment to modify or create PR comments + runs-on: ubuntu-latest + if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'failure' + steps: + - name: download pr artifact + uses: dawidd6/action-download-artifact@v2 + with: + workflow: ${{ github.event.workflow_run.workflow_id }} + name: pr + + - name: save PR id + id: pr + run: echo "::set-output name=id::$( + + + body-include: '' + number: ${{ steps.pr.outputs.id }} diff --git a/.github/workflows/preview-start.yml b/.github/workflows/preview-start.yml new file mode 100644 index 0000000..39f561d --- /dev/null +++ b/.github/workflows/preview-start.yml @@ -0,0 +1,24 @@ +name: Preview Start + +on: pull_request_target + +permissions: + contents: read + +jobs: + preview: + permissions: + issues: write # for actions-cool/maintain-one-comment to modify or create issue comments + pull-requests: write # for actions-cool/maintain-one-comment to modify or create PR comments + runs-on: ubuntu-latest + steps: + - name: create + uses: actions-cool/maintain-one-comment@v1.2.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + body: | + ⚡️ Deploying PR Preview... + + + + body-include: '' diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c352f48 --- /dev/null +++ b/.gitignore @@ -0,0 +1,44 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +**/node_modules +# roadhog-api-doc ignore +/src/utils/request-temp.js +_roadhog-api-doc + +# production +/dist +/qingdao + +# misc +.DS_Store +npm-debug.log* +yarn-error.log + +/coverage +.idea +yarn.lock +package-lock.json +*bak +.vscode + + +# visual studio code +.history +*.log +functions/* +.temp/** + +# umi +.umi +.umi-production +.umi-test + +# screenshot +screenshot +.firebase +.eslintcache + +build + +pnpm-lock.yaml diff --git a/.hintrc b/.hintrc new file mode 100644 index 0000000..1a5323d --- /dev/null +++ b/.hintrc @@ -0,0 +1,13 @@ +{ + "extends": [ + "development" + ], + "hints": { + "no-inline-styles": "off" + }, + "browserslist": [ + "defaults", + "not ie 11", + "not ie <= 11" + ] +} \ No newline at end of file diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 0000000..b04aa8f --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,7 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +# Export Git hook params +export GIT_PARAMS=$* + +# npx --no-install fabric verify-commit diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..6149072 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +# npx --no-install lint-staged diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..7999ccd --- /dev/null +++ b/.prettierignore @@ -0,0 +1,22 @@ +**/*.svg +.umi +.umi-production +/dist +.dockerignore +.DS_Store +.eslintignore +*.png +*.toml +docker +.editorconfig +Dockerfile* +.gitignore +.prettierignore +LICENSE +.eslintcache +*.lock +yarn-error.log +.history +CNAME +/build +/public diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..3447a1a --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,21 @@ +module.exports = { + singleQuote: true, + trailingComma: 'all', + printWidth: 100, + proseWrap: 'never', + endOfLine: 'lf', + overrides: [ + { + files: '.prettierrc', + options: { + parser: 'json', + }, + }, + { + files: 'document.ejs', + options: { + parser: 'html', + }, + }, + ], +}; diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json new file mode 100644 index 0000000..6b61141 --- /dev/null +++ b/.vs/VSWorkspaceState.json @@ -0,0 +1,6 @@ +{ + "ExpandedNodes": [ + "" + ], + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/.vs/qingdao-admin/v17/.suo b/.vs/qingdao-admin/v17/.suo new file mode 100644 index 0000000000000000000000000000000000000000..e24f0d6e651a55adced7ea8ec114fd97dd3d7b53 GIT binary patch literal 12800 zcmeHN%X1qw9F|iGly`XqCj};}>hEEu1)V zW`;=n~w!e3Q{#aU6r(-xmo zl*VaT?61ju|1MuG9{K&3f3DvOJ&b-|KI(K{1Y${C7ViT+i_%$fZI@AYz8)4sHGHyt z=Ue~UB$}bVGAVrGmPH;ju!V)31TRv^mfJ7rF)D^ay10Y->Fuwh@}t|ZAhv*#7dg<+ zysjb7qs7)g^eGenKC}-Zo6;XeUuD-%qWrH;0Lo9hW3l-ulpl2KkKjqMJ%;=^GI{tc zGVPzT=kpmn48#`Z=(FFab$vC;b8a0Bv>{W!f|C zn04AepMLiL5Z>WcLwX>fy`kfvVNW?gxdvq=cgmP+wx9eN19A=FI>B{={-658b>TVW z=aCN~zkqxg`9vT|~9VA+UvlBgyd6eNF zDSv7LTlF*rd}4Fmia&wxl>A%4=Q>q|$L6YB#H=?k&TJd_F?^@w zpOo5e%h9N1M7W5y3^Hl_5Hcr6xHeX5UK#_qX$JT_4`8fkO26*^n#q3=s73r);QBd9 zbzSciKJ>q3{*!hk|7Q5hlJcrtqtZ3n`NbMIvmvz*{0}j#y%S`M%Zp-fjJ92c5{U)9?MwD<~)Mei@HYyN6GJ;ae+KLQ7JQzCxPTq+e4HBRt(Z)_ne*zqG$5CyE4gO z=HyZZ&rH{8@Q!{>OhGrgEqN~rcfAFP!f2{n+UrHhAhM!9JNy%J9q$!Z4)!wx-jQ?p z9@6C8S#5%{GPJ_cwr<*};+E1jMyC0mQ*{MWqO@#a<=}J3#bOV+NIV-}jSL1pCHX5Xm7C9JnZ|I`-Q4KE)8@T@SEW+^y)Bv74 z&`*SM0>siLr1k|gf*xcYHSWf?@BaZIje#{K0FyS`4?0 z3I}8!37*>+D64=@!)}+{5#QsUME{G_YRyafH!OEE@$5SRc{nE%Nyv>WN);_-_f+9B zdc1@Grs1yd?FML`!!d>(O=qp>czPxsiN<27NPIFr8A)fOsfcC0WsRqz)6)~v=nIyS zYxVTeO`d$WpZxAmR2$DISSCV0-T!dTgJi~m!TJBaeg2=oY2PIgZaD7@Yd0ayyh}Uh z|8We+eRsE#uIb$xvz2lB8Q**V;D7%S%#C9>|K$IIajhU9f_v8A97XX{x9Y{`eH_o8 zxu*!e_0q>`{r~S?#pj$alOMiw1I=@XHF-bSY(BhyQUCv7O8+QugYfJ3Z@g{cKHHM> z4Emw{sTj-@pLez2@zMmzOMe~T`2J7cKOM$crubZ+CAbg%;Qo(08SZr%`&**d_kUjb l_o4mQ?p{pw?|)|hp-$}oUcdig9K!XB9;u!Cr+&Xb`VR`l3I+fG literal 0 HcmV?d00001 diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..31e0c5093f2574a5b6c7254eb24facbdb7132159 GIT binary patch literal 135168 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

m(`5Rs{Q0PO(dS@^W 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 Design Pro + +

+ +An out-of-box UI solution for enterprise applications as a React boilerplate. + +[![Build Status](https://dev.azure.com/ant-design/ant-design-pro/_apis/build/status/ant-design.ant-design-pro?branchName=master)](https://dev.azure.com/ant-design/ant-design-pro/_build/latest?definitionId=1?branchName=master) ![Github Action](https://github.com/ant-design/ant-design-pro/workflows/Node%20CI/badge.svg) ![Deploy](https://github.com/ant-design/ant-design-pro/workflows/Deploy%20CI/badge.svg) + +[![Gitter](https://img.shields.io/gitter/room/ant-design/pro-english.svg?style=flat-square&logoWidth=20&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjEyMzUiIGhlaWdodD0iNjUwIiB2aWV3Qm94PSIwIDAgNzQxMCAzOTAwIj4NCjxyZWN0IHdpZHRoPSI3NDEwIiBoZWlnaHQ9IjM5MDAiIGZpbGw9IiNiMjIyMzQiLz4NCjxwYXRoIGQ9Ik0wLDQ1MEg3NDEwbTAsNjAwSDBtMCw2MDBINzQxMG0wLDYwMEgwbTAsNjAwSDc0MTBtMCw2MDBIMCIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjMwMCIvPg0KPHJlY3Qgd2lkdGg9IjI5NjQiIGhlaWdodD0iMjEwMCIgZmlsbD0iIzNjM2I2ZSIvPg0KPGcgZmlsbD0iI2ZmZiI%2BDQo8ZyBpZD0iczE4Ij4NCjxnIGlkPSJzOSI%2BDQo8ZyBpZD0iczUiPg0KPGcgaWQ9InM0Ij4NCjxwYXRoIGlkPSJzIiBkPSJNMjQ3LDkwIDMxNy41MzQyMzAsMzA3LjA4MjAzOSAxMzIuODczMjE4LDE3Mi45MTc5NjFIMzYxLjEyNjc4MkwxNzYuNDY1NzcwLDMwNy4wODIwMzl6Ii8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB5PSI0MjAiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHk9Ijg0MCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTI2MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjcyIgeT0iMTY4MCIvPg0KPC9nPg0KPHVzZSB4bGluazpocmVmPSIjczQiIHg9IjI0NyIgeT0iMjEwIi8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzOSIgeD0iNDk0Ii8%2BDQo8L2c%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzMTgiIHg9Ijk4OCIvPg0KPHVzZSB4bGluazpocmVmPSIjczkiIHg9IjE5NzYiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3M1IiB4PSIyNDcwIi8%2BDQo8L2c%2BDQo8L3N2Zz4%3D)](https://gitter.im/ant-design/pro-english?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Join the chat at https://gitter.im/ant-design/ant-design-pro](https://img.shields.io/gitter/room/ant-design/ant-design-pro.svg?style=flat-square&logoWidth=20&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjkwMCIgaGVpZ2h0PSI2MDAiIHZpZXdCb3g9IjAgMCAzMCAyMCI%2BDQo8ZGVmcz4NCjxwYXRoIGlkPSJzIiBkPSJNMCwtMSAwLjU4Nzc4NSwwLjgwOTAxNyAtMC45NTEwNTcsLTAuMzA5MDE3SDAuOTUxMDU3TC0wLjU4Nzc4NSwwLjgwOTAxN3oiIGZpbGw9IiNmZmRlMDAiLz4NCjwvZGVmcz4NCjxyZWN0IHdpZHRoPSIzMCIgaGVpZ2h0PSIyMCIgZmlsbD0iI2RlMjkxMCIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNSw1KSBzY2FsZSgzKSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsMikgcm90YXRlKDIzLjAzNjI0MykiLz4NCjx1c2UgeGxpbms6aHJlZj0iI3MiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyLDQpIHJvdGF0ZSg0NS44Njk4OTgpIi8%2BDQo8dXNlIHhsaW5rOmhyZWY9IiNzIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMiw3KSByb3RhdGUoNjkuOTQ1Mzk2KSIvPg0KPHVzZSB4bGluazpocmVmPSIjcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAsOSkgcm90YXRlKDIwLjY1OTgwOCkiLz4NCjwvc3ZnPg%3D%3D)](https://gitter.im/ant-design/ant-design-pro?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Build With Umi](https://img.shields.io/badge/build%20with-umi-028fe4.svg?style=flat-square)](http://umijs.org/) ![](https://badgen.net/badge/icon/Ant%20Design?icon=https://gw.alipayobjects.com/zos/antfincdn/Pp4WPgVDB3/KDpgvguMpGfqaHPjicRK.svg&label) + +![](https://user-images.githubusercontent.com/8186664/44953195-581e3d80-aec4-11e8-8dcb-54b9db38ec11.png) + +
+ +- Preview: http://preview.pro.ant.design +- Home Page: http://pro.ant.design +- Documentation: http://pro.ant.design/docs/getting-started +- ChangeLog: http://pro.ant.design/docs/changelog +- FAQ: http://pro.ant.design/docs/faq +- Mirror Site in China: http://ant-design-pro.gitee.io + +## 5.0 is out! 🎉🎉🎉 + +[Ant Design Pro 5.0.0](https://github.com/ant-design/ant-design-pro/issues/8656) + +## Translation Recruitment :loudspeaker: + +We need your help: https://github.com/ant-design/ant-design-pro/issues/120 + +## Features + +- :bulb: **TypeScript**: A language for application-scale JavaScript +- :scroll: **Blocks**: Build page with block template +- :gem: **Neat Design**: Follow [Ant Design specification](http://ant.design/) +- :triangular_ruler: **Common Templates**: Typical templates for enterprise applications +- :rocket: **State of The Art Development**: Newest development stack of React/umi/dva/antd +- :iphone: **Responsive**: Designed for variable screen sizes +- :art: **Theming**: Customizable theme with simple config +- :globe_with_meridians: **International**: Built-in i18n solution +- :gear: **Best Practices**: Solid workflow to make your code healthy +- :1234: **Mock development**: Easy to use mock development solution +- :white_check_mark: **UI Test**: Fly safely with unit and e2e tests + +## Templates + +``` +- Dashboard + - Analytic + - Monitor + - Workspace +- Form + - Basic Form + - Step Form + - Advanced From +- List + - Standard Table + - Standard List + - Card List + - Search List (Project/Applications/Article) +- Profile + - Simple Profile + - Advanced Profile +- Account + - Account Center + - Account Settings +- Result + - Success + - Failed +- Exception + - 403 + - 404 + - 500 +- User + - Login + - Register + - Register Result +``` + +## Usage + +### Use bash + +We provide pro-cli to quickly initialize scaffolding. + +```bash +# use npm +npm i @ant-design/pro-cli -g +pro create myapp +``` + +select umi version + +```shell +🐂 Use umi@4 or umi@3 ? (Use arrow keys) +❯ umi@4 + umi@3 +``` + +> If the umi@4 version is selected, full blocks are not yet supported. + +If you choose umi@3, you can also choose the pro template. Pro is the basic template, which only provides the basic content of the framework operation. Complete contains all blocks, which is not suitable for secondary development as a basic template. + +```shell +? 🚀 Full or a simple scaffold? (Use arrow keys) +❯ simple + complete +``` + +Install dependencies: + +```shell +$ cd myapp && tyarn +// or +$ cd myapp && npm install +``` + +## Browsers support + +Modern browsers. + +| [Edge](http://godban.github.io/browsers-support-badges/)
Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [Opera](http://godban.github.io/browsers-support-badges/)
Opera | +| --- | --- | --- | --- | --- | +| Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions | + +## Contributing + +Any type of contribution is welcome, here are some examples of how you may contribute to this project: + +- Use Ant Design Pro in your daily work. +- Submit [issues](http://github.com/ant-design/ant-design-pro/issues) to report bugs or ask questions. +- Propose [pull requests](http://github.com/ant-design/ant-design-pro/pulls) to improve our code. +======= +# qingdao-admin + +>>>>>>> 997802589330c49d3abc4f122ed00ce04a3c9601 diff --git a/config/config.ts b/config/config.ts new file mode 100644 index 0000000..7c27b33 --- /dev/null +++ b/config/config.ts @@ -0,0 +1,159 @@ +// https://umijs.org/config/ +import { defineConfig } from '@umijs/max'; +import { join } from 'path'; +import defaultSettings from './defaultSettings'; +import proxy from './proxy'; +import routes from './routes'; + +const { REACT_APP_ENV = 'dev' } = process.env; + +export default defineConfig({ + /** + * @name 开启 hash 模式 + * @description 让 build 之后的产物包含 hash 后缀。通常用于增量发布和避免浏览器加载缓存。 + * @doc https://umijs.org/docs/api/config#hash + */ + hash: true, + + /** + * @name 兼容性设置 + * @description 设置 ie11 不一定完美兼容,需要检查自己使用的所有依赖 + * @doc https://umijs.org/docs/api/config#targets + */ + // targets: { + // ie: 11, + // }, + /** + * @name 路由的配置,不在路由中引入的文件不会编译 + * @description 只支持 path,component,routes,redirect,wrappers,title 的配置 + * @doc https://umijs.org/docs/guides/routes + */ + // umi routes: https://umijs.org/docs/routing + routes, + /** + * @name 主题的配置 + * @description 虽然叫主题,但是其实只是 less 的变量设置 + * @doc antd的主题设置 https://ant.design/docs/react/customize-theme-cn + * @doc umi 的theme 配置 https://umijs.org/docs/api/config#theme + */ + theme: { + // 如果不想要 configProvide 动态设置主题需要把这个设置为 default + // 只有设置为 variable, 才能使用 configProvide 动态设置主色调 + 'root-entry-name': 'variable', + }, + /** + * @name moment 的国际化配置 + * @description 如果对国际化没有要求,打开之后能减少js的包大小 + * @doc https://umijs.org/docs/api/config#ignoremomentlocale + */ + ignoreMomentLocale: true, + /** + * @name 代理配置 + * @description 可以让你的本地服务器代理到你的服务器上,这样你就可以访问服务器的数据了 + * @see 要注意以下 代理只能在本地开发时使用,build 之后就无法使用了。 + * @doc 代理介绍 https://umijs.org/docs/guides/proxy + * @doc 代理配置 https://umijs.org/docs/api/config#proxy + */ + proxy: proxy[REACT_APP_ENV as keyof typeof proxy], + /** + * @name 快速热更新配置 + * @description 一个不错的热更新组件,更新时可以保留 state + */ + fastRefresh: true, + //============== 以下都是max的插件配置 =============== + /** + * @name 数据流插件 + * @@doc https://umijs.org/docs/max/data-flow + */ + model: {}, + /** + * 一个全局的初始数据流,可以用它在插件之间共享数据 + * @description 可以用来存放一些全局的数据,比如用户信息,或者一些全局的状态,全局初始状态在整个 Umi 项目的最开始创建。 + * @doc https://umijs.org/docs/max/data-flow#%E5%85%A8%E5%B1%80%E5%88%9D%E5%A7%8B%E7%8A%B6%E6%80%81 + */ + initialState: {}, + /** + * @name layout 插件 + * @doc https://umijs.org/docs/max/layout-menu + */ + title: '青岛智慧就业服务系统', + layout: { + locale: false, + ...defaultSettings, + }, + /** + * @name moment2dayjs 插件 + * @description 将项目中的 moment 替换为 dayjs + * @doc https://umijs.org/docs/max/moment2dayjs + */ + moment2dayjs: { + preset: 'antd', + plugins: ['duration'], + }, + /** + * @name 国际化插件 + * @doc https://umijs.org/docs/max/i18n + */ + locale: { + // default zh-CN + default: 'zh-CN', + antd: false, + // default true, when it is true, will use `navigator.language` overwrite default + baseNavigator: false, + }, + /** + * @name antd 插件 + * @description 内置了 babel import 插件 + * @doc https://umijs.org/docs/max/antd#antd + */ + antd: {}, + /** + * @name 网络请求配置 + * @description 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。 + * @doc https://umijs.org/docs/max/request + */ + request: {}, + /** + * @name 权限插件 + * @description 基于 initialState 的权限插件,必须先打开 initialState + * @doc https://umijs.org/docs/max/access + */ + access: {}, + /** + * @name 中额外的 script + * @description 配置 中额外的 script + */ + headScripts: [ + // 解决首次加载时白屏的问题 + { src: '/qingdao/scripts/loading.js', async: true }, + ], + //================ pro 插件配置 ================= + presets: ['umi-presets-pro'], + /** + * @name openAPI 插件的配置 + * @description 基于 openapi 的规范生成serve 和mock,能减少很多样板代码 + * @doc https://pro.ant.design/zh-cn/docs/openapi/ + */ + openAPI: [ + { + requestLibPath: "import { request } from '@umijs/max'", + // 或者使用在线的版本 + // schemaPath: "https://gw.alipayobjects.com/os/antfincdn/M%24jrzTTYJN/oneapi.json" + schemaPath: join(__dirname, 'oneapi.json'), + mock: false, + }, + { + requestLibPath: "import { request } from '@umijs/max'", + schemaPath: 'https://gw.alipayobjects.com/os/antfincdn/CA1dOm%2631B/openapi.json', + projectName: 'swagger', + }, + ], + mfsu: { + strategy: 'normal', + }, + outputPath: 'qingdao', + base: '/qingdao/', + publicPath: '/qingdao/', + esbuildMinifyIIFE: true, + requestRecord: {}, +}); diff --git a/config/defaultSettings.ts b/config/defaultSettings.ts new file mode 100644 index 0000000..f4c8439 --- /dev/null +++ b/config/defaultSettings.ts @@ -0,0 +1,28 @@ +import { ProLayoutProps } from '@ant-design/pro-components'; + +/** + * @name + */ +const Settings: ProLayoutProps & { + pwa?: boolean; + logo?: string; +} = { + navTheme: 'light', + // 拂晓蓝 + colorPrimary: '#1890ff', + layout: 'mix', + contentWidth: 'Fluid', + fixedHeader: false, + fixSiderbar: true, + colorWeak: false, + title: '青岛智慧就业服务系统', + pwa: true, + logo: 'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg', + iconfontUrl: '', + token: { + // 参见ts声明,demo 见文档,通过token 修改样式 + //https://procomponents.ant.design/components/layout#%E9%80%9A%E8%BF%87-token-%E4%BF%AE%E6%94%B9%E6%A0%B7%E5%BC%8F + }, +}; + +export default Settings; diff --git a/config/oneapi.json b/config/oneapi.json new file mode 100644 index 0000000..c77d988 --- /dev/null +++ b/config/oneapi.json @@ -0,0 +1,593 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "Ant Design Pro", + "version": "1.0.0" + }, + "servers": [ + { + "url": "http://localhost:8000/" + }, + { + "url": "https://localhost:8000/" + } + ], + "paths": { + "/api/currentUser": { + "get": { + "tags": ["api"], + "description": "获取当前的用户", + "operationId": "currentUser", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CurrentUser" + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "x-swagger-router-controller": "api" + }, + "/api/login/captcha": { + "post": { + "description": "发送验证码", + "operationId": "getFakeCaptcha", + "tags": ["login"], + "parameters": [ + { + "name": "phone", + "in": "query", + "description": "手机号", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FakeCaptcha" + } + } + } + } + } + } + }, + "/api/login/outLogin": { + "post": { + "description": "登录接口", + "operationId": "outLogin", + "tags": ["login"], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "x-swagger-router-controller": "api" + }, + "/api/login/account": { + "post": { + "tags": ["login"], + "description": "登录接口", + "operationId": "login", + "requestBody": { + "description": "登录系统", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LoginParams" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LoginResult" + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "x-codegen-request-body-name": "body" + }, + "x-swagger-router-controller": "api" + }, + "/api/notices": { + "summary": "getNotices", + "description": "NoticeIconItem", + "get": { + "tags": ["api"], + "operationId": "getNotices", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NoticeIconList" + } + } + } + } + } + } + }, + "/api/rule": { + "get": { + "tags": ["rule"], + "description": "获取规则列表", + "operationId": "rule", + "parameters": [ + { + "name": "current", + "in": "query", + "description": "当前的页码", + "schema": { + "type": "number" + } + }, + { + "name": "pageSize", + "in": "query", + "description": "页面的容量", + "schema": { + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RuleList" + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "post": { + "tags": ["rule"], + "description": "新建规则", + "operationId": "addRule", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RuleListItem" + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "put": { + "tags": ["rule"], + "description": "新建规则", + "operationId": "updateRule", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RuleListItem" + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "delete": { + "tags": ["rule"], + "description": "删除规则", + "operationId": "removeRule", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "x-swagger-router-controller": "api" + }, + "/swagger": { + "x-swagger-pipe": "swagger_raw" + } + }, + "components": { + "schemas": { + "CurrentUser": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "avatar": { + "type": "string" + }, + "userid": { + "type": "string" + }, + "email": { + "type": "string" + }, + "signature": { + "type": "string" + }, + "title": { + "type": "string" + }, + "group": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "label": { + "type": "string" + } + } + } + }, + "notifyCount": { + "type": "integer", + "format": "int32" + }, + "unreadCount": { + "type": "integer", + "format": "int32" + }, + "country": { + "type": "string" + }, + "access": { + "type": "string" + }, + "geographic": { + "type": "object", + "properties": { + "province": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "key": { + "type": "string" + } + } + }, + "city": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "key": { + "type": "string" + } + } + } + } + }, + "address": { + "type": "string" + }, + "phone": { + "type": "string" + } + } + }, + "LoginResult": { + "type": "object", + "properties": { + "status": { + "type": "string" + }, + "type": { + "type": "string" + }, + "currentAuthority": { + "type": "string" + } + } + }, + "PageParams": { + "type": "object", + "properties": { + "current": { + "type": "number" + }, + "pageSize": { + "type": "number" + } + } + }, + "RuleListItem": { + "type": "object", + "properties": { + "key": { + "type": "integer", + "format": "int32" + }, + "disabled": { + "type": "boolean" + }, + "href": { + "type": "string" + }, + "avatar": { + "type": "string" + }, + "name": { + "type": "string" + }, + "owner": { + "type": "string" + }, + "desc": { + "type": "string" + }, + "callNo": { + "type": "integer", + "format": "int32" + }, + "status": { + "type": "integer", + "format": "int32" + }, + "updatedAt": { + "type": "string", + "format": "datetime" + }, + "createdAt": { + "type": "string", + "format": "datetime" + }, + "progress": { + "type": "integer", + "format": "int32" + } + } + }, + "RuleList": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RuleListItem" + } + }, + "total": { + "type": "integer", + "description": "列表的内容总数", + "format": "int32" + }, + "success": { + "type": "boolean" + } + } + }, + "FakeCaptcha": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "status": { + "type": "string" + } + } + }, + "LoginParams": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "password": { + "type": "string" + }, + "autoLogin": { + "type": "boolean" + }, + "type": { + "type": "string" + } + } + }, + "ErrorResponse": { + "required": ["errorCode"], + "type": "object", + "properties": { + "errorCode": { + "type": "string", + "description": "业务约定的错误码" + }, + "errorMessage": { + "type": "string", + "description": "业务上的错误信息" + }, + "success": { + "type": "boolean", + "description": "业务上的请求是否成功" + } + } + }, + "NoticeIconList": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/NoticeIconItem" + } + }, + "total": { + "type": "integer", + "description": "列表的内容总数", + "format": "int32" + }, + "success": { + "type": "boolean" + } + } + }, + "NoticeIconItemType": { + "title": "NoticeIconItemType", + "description": "已读未读列表的枚举", + "type": "string", + "properties": {}, + "enum": ["notification", "message", "event"] + }, + "NoticeIconItem": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "extra": { + "type": "string", + "format": "any" + }, + "key": { "type": "string" }, + "read": { + "type": "boolean" + }, + "avatar": { + "type": "string" + }, + "title": { + "type": "string" + }, + "status": { + "type": "string" + }, + "datetime": { + "type": "string", + "format": "date" + }, + "description": { + "type": "string" + }, + "type": { + "extensions": { + "x-is-enum": true + }, + "$ref": "#/components/schemas/NoticeIconItemType" + } + } + } + } + } +} diff --git a/config/proxy.ts b/config/proxy.ts new file mode 100644 index 0000000..4f40f64 --- /dev/null +++ b/config/proxy.ts @@ -0,0 +1,49 @@ +/** + * @name 代理的配置 + * @see 在生产环境 代理是无法生效的,所以这里没有生产环境的配置 + * ------------------------------- + * The agent cannot take effect in the production environment + * so there is no configuration of the production environment + * For details, please see + * https://pro.ant.design/docs/deploy + * + * @doc https://umijs.org/docs/guides/proxy + */ +export default { + // 如果需要自定义本地开发服务器 请取消注释按需调整 + dev: { + // localhost:8000/api/** -> https://preview.pro.ant.design/api/** + '/api/': { + // 要代理的地址 + target: 'https://qd.zhaopinzao8dian.com/api', + // 配置了这个可以从 http 代理到 https + // 依赖 origin 的功能可能需要这个,比如 cookie + changeOrigin: true, + pathRewrite: { '^/api': '' }, + }, + '/profile/avatar/': { + target: 'https://qd.zhaopinzao8dian.com/api', + changeOrigin: true, + } + }, + + /** + * @name 详细的代理配置 + * @doc https://github.com/chimurai/http-proxy-middleware + */ + test: { + // localhost:8000/api/** -> https://preview.pro.ant.design/api/** + '/api/': { + target: 'https://proapi.azurewebsites.net', + changeOrigin: true, + pathRewrite: { '^': '' }, + }, + }, + pre: { + '/api/': { + target: 'your pre url', + changeOrigin: true, + pathRewrite: { '^': '' }, + }, + }, +}; diff --git a/config/routes.ts b/config/routes.ts new file mode 100644 index 0000000..e62c649 --- /dev/null +++ b/config/routes.ts @@ -0,0 +1,120 @@ +/** + * @name umi 的路由配置 + * @description 只支持 path,component,routes,redirect,wrappers,name,icon 的配置 + * @param path path 只支持两种占位符配置,第一种是动态参数 :id 的形式,第二种是 * 通配符,通配符只能出现路由字符串的最后。 + * @param component 配置 location 和 path 匹配后用于渲染的 React 组件路径。可以是绝对路径,也可以是相对路径,如果是相对路径,会从 src/pages 开始找起。 + * @param routes 配置子路由,通常在需要为多个路径增加 layout 组件时使用。 + * @param redirect 配置路由跳转 + * @param wrappers 配置路由组件的包装组件,通过包装组件可以为当前的路由组件组合进更多的功能。 比如,可以用于路由级别的权限校验 + * @param name 配置路由的标题,默认读取国际化文件 menu.ts 中 menu.xxxx 的值,如配置 name 为 login,则读取 menu.ts 中 menu.login 的取值作为标题 + * @param icon 配置路由的图标,取值参考 https://ant.design/components/icon-cn, 注意去除风格后缀和大小写,如想要配置图标为 则取值应为 stepBackward 或 StepBackward,如想要配置图标为 则取值应为 user 或者 User + * @doc https://umijs.org/docs/guides/routes + */ +export default [ + { + path: '/', + redirect: '/account/center', + }, + { + path: '*', + layout: false, + component: './404', + }, + { + path: '/user', + layout: false, + routes: [ + { + name: 'login', + path: '/user/login', + component: './User/Login', + }, + ], + }, + { + path: '/account', + routes: [ + { + name: 'acenter', + path: '/account/center', + component: './User/Center', + }, + { + name: 'asettings', + path: '/account/settings', + component: './User/Settings', + }, + ], + }, + { + name: 'area', + path: '/area', + routes: [ + { + name: '字典数据', + path: '/area/updata-router/index/:id', + component: './Area/Subway/UpLine', + }, + ], + }, + { + name: 'management', + path: '/management', + routes: [ + { + name: '字典数据', + path: '/management/see-matching/index/:id', + component: './Management/List/SeeMatching', + }, + ], + }, + { + name: 'system', + path: '/system', + routes: [ + { + name: '字典数据', + path: '/system/dict-data/index/:id', + component: './System/DictData', + }, + { + name: '字典数据', + path: '/system/admin-dict-data/index/:id', + component: './System/AdminDictData', + }, + { + name: '分配用户', + path: '/system/role-auth/user/:id', + component: './System/Role/authUser', + }, + ], + }, + { + name: 'monitor', + path: '/monitor', + routes: [ + { + name: '任务日志', + path: '/monitor/job-log/index/:id', + component: './Monitor/JobLog', + }, + ], + }, + { + name: 'tool', + path: '/tool', + routes: [ + { + name: '导入表', + path: '/tool/gen/import', + component: './Tool/Gen/import', + }, + { + name: '编辑表', + path: '/tool/gen/edit.tsx', + component: './Tool/Gen/edit.tsx', + }, + ], + }, + +]; diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 0000000..1de2a1a --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,23 @@ +import { configUmiAlias, createConfig } from '@umijs/max/test'; + +export default async () => { + const config = await configUmiAlias({ + ...createConfig({ + target: 'browser', + }), + }); + + console.log(); + return { + ...config, + testEnvironmentOptions: { + ...(config?.testEnvironmentOptions || {}), + url: 'http://localhost:8000', + }, + setupFiles: [...(config.setupFiles || []), './tests/setupTests.jsx'], + globals: { + ...config.globals, + localStorage: null, + }, + }; +}; diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..197bee5 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/mock/listTableList.ts b/mock/listTableList.ts new file mode 100644 index 0000000..35ec3ce --- /dev/null +++ b/mock/listTableList.ts @@ -0,0 +1,176 @@ +import { Request, Response } from 'express'; +import moment from 'moment'; +import { parse } from 'url'; + +// mock tableListDataSource +const genList = (current: number, pageSize: number) => { + const tableListDataSource: API.RuleListItem[] = []; + + for (let i = 0; i < pageSize; i += 1) { + const index = (current - 1) * 10 + i; + tableListDataSource.push({ + key: index, + disabled: i % 6 === 0, + href: 'https://ant.design', + avatar: [ + 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + ][i % 2], + name: `TradeCode ${index}`, + owner: '曲丽丽', + desc: '这是一段描述', + callNo: Math.floor(Math.random() * 1000), + status: Math.floor(Math.random() * 10) % 4, + updatedAt: moment().format('YYYY-MM-DD'), + createdAt: moment().format('YYYY-MM-DD'), + progress: Math.ceil(Math.random() * 100), + }); + } + tableListDataSource.reverse(); + return tableListDataSource; +}; + +let tableListDataSource = genList(1, 100); + +function getRule(req: Request, res: Response, u: string) { + let realUrl = u; + if (!realUrl || Object.prototype.toString.call(realUrl) !== '[object String]') { + realUrl = req.url; + } + const { current = 1, pageSize = 10 } = req.query; + const params = parse(realUrl, true).query as unknown as API.PageParams & + API.RuleListItem & { + sorter: any; + filter: any; + }; + + let dataSource = [...tableListDataSource].slice( + ((current as number) - 1) * (pageSize as number), + (current as number) * (pageSize as number), + ); + if (params.sorter) { + const sorter = JSON.parse(params.sorter); + dataSource = dataSource.sort((prev, next) => { + let sortNumber = 0; + (Object.keys(sorter) as Array).forEach((key) => { + let nextSort = next?.[key] as number; + let preSort = prev?.[key] as number; + if (sorter[key] === 'descend') { + if (preSort - nextSort > 0) { + sortNumber += -1; + } else { + sortNumber += 1; + } + return; + } + if (preSort - nextSort > 0) { + sortNumber += 1; + } else { + sortNumber += -1; + } + }); + return sortNumber; + }); + } + if (params.filter) { + const filter = JSON.parse(params.filter as any) as { + [key: string]: string[]; + }; + if (Object.keys(filter).length > 0) { + dataSource = dataSource.filter((item) => { + return (Object.keys(filter) as Array).some((key) => { + if (!filter[key]) { + return true; + } + if (filter[key].includes(`${item[key]}`)) { + return true; + } + return false; + }); + }); + } + } + + if (params.name) { + dataSource = dataSource.filter((data) => data?.name?.includes(params.name || '')); + } + const result = { + data: dataSource, + total: tableListDataSource.length, + success: true, + pageSize, + current: parseInt(`${params.current}`, 10) || 1, + }; + + return res.json(result); +} + +function postRule(req: Request, res: Response, u: string, b: Request) { + let realUrl = u; + if (!realUrl || Object.prototype.toString.call(realUrl) !== '[object String]') { + realUrl = req.url; + } + + const body = (b && b.body) || req.body; + const { method, name, desc, key } = body; + + switch (method) { + /* eslint no-case-declarations:0 */ + case 'delete': + tableListDataSource = tableListDataSource.filter((item) => key.indexOf(item.key) === -1); + break; + case 'post': + (() => { + const i = Math.ceil(Math.random() * 10000); + const newRule: API.RuleListItem = { + key: tableListDataSource.length, + href: 'https://ant.design', + avatar: [ + 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + ][i % 2], + name, + owner: '曲丽丽', + desc, + callNo: Math.floor(Math.random() * 1000), + status: Math.floor(Math.random() * 10) % 2, + updatedAt: moment().format('YYYY-MM-DD'), + createdAt: moment().format('YYYY-MM-DD'), + progress: Math.ceil(Math.random() * 100), + }; + tableListDataSource.unshift(newRule); + return res.json(newRule); + })(); + return; + + case 'update': + (() => { + let newRule = {}; + tableListDataSource = tableListDataSource.map((item) => { + if (item.key === key) { + newRule = { ...item, desc, name }; + return { ...item, desc, name }; + } + return item; + }); + return res.json(newRule); + })(); + return; + default: + break; + } + + const result = { + list: tableListDataSource, + pagination: { + total: tableListDataSource.length, + }, + }; + + res.json(result); +} + +export default { + 'GET /api/rule': getRule, + 'POST /api/rule': postRule, +}; diff --git a/mock/notices.ts b/mock/notices.ts new file mode 100644 index 0000000..616c921 --- /dev/null +++ b/mock/notices.ts @@ -0,0 +1,115 @@ +import { Request, Response } from 'express'; + +const getNotices = (req: Request, res: Response) => { + res.json({ + data: [ + { + id: '000000001', + avatar: + 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/MSbDR4FR2MUAAAAAAAAAAAAAFl94AQBr', + title: '你收到了 14 份新周报', + datetime: '2017-08-09', + type: 'notification', + }, + { + id: '000000002', + avatar: + 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/hX-PTavYIq4AAAAAAAAAAAAAFl94AQBr', + title: '你推荐的 曲妮妮 已通过第三轮面试', + datetime: '2017-08-08', + type: 'notification', + }, + { + id: '000000003', + avatar: + 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/jHX5R5l3QjQAAAAAAAAAAAAAFl94AQBr', + title: '这种模板可以区分多种通知类型', + datetime: '2017-08-07', + read: true, + type: 'notification', + }, + { + id: '000000004', + avatar: + 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/Wr4mQqx6jfwAAAAAAAAAAAAAFl94AQBr', + title: '左侧图标用于区分不同的类型', + datetime: '2017-08-07', + type: 'notification', + }, + { + id: '000000005', + avatar: + 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/Mzj_TbcWUj4AAAAAAAAAAAAAFl94AQBr', + title: '内容不要超过两行字,超出时自动截断', + datetime: '2017-08-07', + type: 'notification', + }, + { + id: '000000006', + avatar: + 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/eXLzRbPqQE4AAAAAAAAAAAAAFl94AQBr', + title: '曲丽丽 评论了你', + description: '描述信息描述信息描述信息', + datetime: '2017-08-07', + type: 'message', + clickClose: true, + }, + { + id: '000000007', + avatar: + 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/w5mRQY2AmEEAAAAAAAAAAAAAFl94AQBr', + title: '朱偏右 回复了你', + description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像', + datetime: '2017-08-07', + type: 'message', + clickClose: true, + }, + { + id: '000000008', + avatar: + 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/wPadR5M9918AAAAAAAAAAAAAFl94AQBr', + title: '标题', + description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像', + datetime: '2017-08-07', + type: 'message', + clickClose: true, + }, + { + id: '000000009', + title: '任务名称', + description: '任务需要在 2017-01-12 20:00 前启动', + extra: '未开始', + status: 'todo', + type: 'event', + }, + { + id: '000000010', + title: '第三方紧急代码变更', + description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务', + extra: '马上到期', + status: 'urgent', + type: 'event', + }, + { + id: '000000011', + title: '信息安全考试', + description: '指派竹尔于 2017-01-09 前完成更新并发布', + extra: '已耗时 8 天', + status: 'doing', + type: 'event', + }, + { + id: '000000012', + title: 'ABCD 版本发布', + description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务', + extra: '进行中', + status: 'processing', + type: 'event', + }, + ], + }); +}; + +export default { + 'GET /api/notices': getNotices, +}; diff --git a/mock/requestRecord.mock.js b/mock/requestRecord.mock.js new file mode 100644 index 0000000..6c59e19 --- /dev/null +++ b/mock/requestRecord.mock.js @@ -0,0 +1,324 @@ +module.exports = { + 'GET /api/currentUser': { + data: { + name: 'Serati Ma', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png', + userid: '00000001', + email: 'antdesign@alipay.com', + signature: '海纳百川,有容乃大', + title: '交互专家', + group: '蚂蚁金服-某某某事业群-某某平台部-某某技术部-UED', + tags: [ + { key: '0', label: '很有想法的' }, + { key: '1', label: '专注设计' }, + { key: '2', label: '辣~' }, + { key: '3', label: '大长腿' }, + { key: '4', label: '川妹子' }, + { key: '5', label: '海纳百川' }, + ], + notifyCount: 12, + unreadCount: 11, + country: 'China', + geographic: { + province: { label: '浙江省', key: '330000' }, + city: { label: '杭州市', key: '330100' }, + }, + address: '西湖区工专路 77 号', + phone: '0752-268888888', + }, + }, + 'GET /api/rule': { + data: [ + { + key: 99, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + name: 'TradeCode 99', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 503, + status: '0', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 81, + }, + { + key: 98, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + name: 'TradeCode 98', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 164, + status: '0', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 12, + }, + { + key: 97, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + name: 'TradeCode 97', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 174, + status: '1', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 81, + }, + { + key: 96, + disabled: true, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + name: 'TradeCode 96', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 914, + status: '0', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 7, + }, + { + key: 95, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + name: 'TradeCode 95', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 698, + status: '2', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 82, + }, + { + key: 94, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + name: 'TradeCode 94', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 488, + status: '1', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 14, + }, + { + key: 93, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + name: 'TradeCode 93', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 580, + status: '2', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 77, + }, + { + key: 92, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + name: 'TradeCode 92', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 244, + status: '3', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 58, + }, + { + key: 91, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + name: 'TradeCode 91', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 959, + status: '0', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 66, + }, + { + key: 90, + disabled: true, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + name: 'TradeCode 90', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 958, + status: '0', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 72, + }, + { + key: 89, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + name: 'TradeCode 89', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 301, + status: '2', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 2, + }, + { + key: 88, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + name: 'TradeCode 88', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 277, + status: '1', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 12, + }, + { + key: 87, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + name: 'TradeCode 87', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 810, + status: '1', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 82, + }, + { + key: 86, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + name: 'TradeCode 86', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 780, + status: '3', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 22, + }, + { + key: 85, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + name: 'TradeCode 85', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 705, + status: '3', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 12, + }, + { + key: 84, + disabled: true, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + name: 'TradeCode 84', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 203, + status: '0', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 79, + }, + { + key: 83, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + name: 'TradeCode 83', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 491, + status: '2', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 59, + }, + { + key: 82, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + name: 'TradeCode 82', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 73, + status: '0', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 100, + }, + { + key: 81, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', + name: 'TradeCode 81', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 406, + status: '3', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 61, + }, + { + key: 80, + disabled: false, + href: 'https://ant.design', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', + name: 'TradeCode 80', + owner: '曲丽丽', + desc: '这是一段描述', + callNo: 112, + status: '2', + updatedAt: '2022-12-06T05:00:57.040Z', + createdAt: '2022-12-06T05:00:57.040Z', + progress: 20, + }, + ], + total: 100, + success: true, + pageSize: 20, + current: 1, + }, + 'POST /api/login/outLogin': { data: {}, success: true }, + 'POST /api/login/account': { + status: 'ok', + type: 'account', + currentAuthority: 'admin', + }, +}; diff --git a/mock/route.ts b/mock/route.ts new file mode 100644 index 0000000..418d10f --- /dev/null +++ b/mock/route.ts @@ -0,0 +1,5 @@ +export default { + '/api/auth_routes': { + '/form/advanced-form': { authority: ['admin', 'user'] }, + }, +}; diff --git a/mock/user.ts b/mock/user.ts new file mode 100644 index 0000000..75edd34 --- /dev/null +++ b/mock/user.ts @@ -0,0 +1,203 @@ +import { Request, Response } from 'express'; + +const waitTime = (time: number = 100) => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(true); + }, time); + }); +}; + +async function getFakeCaptcha(req: Request, res: Response) { + await waitTime(2000); + return res.json('captcha-xxx'); +} + +const { ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION } = process.env; + +/** + * 当前用户的权限,如果为空代表没登录 + * current user access, if is '', user need login + * 如果是 pro 的预览,默认是有权限的 + */ +let access = ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site' ? 'admin' : ''; + +const getAccess = () => { + return access; +}; + +// 代码中会兼容本地 service mock 以及部署站点的静态数据 +export default { + // 支持值为 Object 和 Array + 'GET /api/currentUser': (req: Request, res: Response) => { + if (!getAccess()) { + res.status(401).send({ + data: { + isLogin: false, + }, + errorCode: '401', + errorMessage: '请先登录!', + success: true, + }); + return; + } + res.send({ + success: true, + data: { + name: 'Serati Ma', + avatar: 'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png', + userid: '00000001', + email: 'antdesign@alipay.com', + signature: '海纳百川,有容乃大', + title: '交互专家', + group: '蚂蚁金服-某某某事业群-某某平台部-某某技术部-UED', + tags: [ + { + key: '0', + label: '很有想法的', + }, + { + key: '1', + label: '专注设计', + }, + { + key: '2', + label: '辣~', + }, + { + key: '3', + label: '大长腿', + }, + { + key: '4', + label: '川妹子', + }, + { + key: '5', + label: '海纳百川', + }, + ], + notifyCount: 12, + unreadCount: 11, + country: 'China', + access: getAccess(), + geographic: { + province: { + label: '浙江省', + key: '330000', + }, + city: { + label: '杭州市', + key: '330100', + }, + }, + address: '西湖区工专路 77 号', + phone: '0752-268888888', + }, + }); + }, + // GET POST 可省略 + 'GET /api/users': [ + { + key: '1', + name: 'John Brown', + age: 32, + address: 'New York No. 1 Lake Park', + }, + { + key: '2', + name: 'Jim Green', + age: 42, + address: 'London No. 1 Lake Park', + }, + { + key: '3', + name: 'Joe Black', + age: 32, + address: 'Sidney No. 1 Lake Park', + }, + ], + 'POST /api/login/account': async (req: Request, res: Response) => { + const { password, username, type } = req.body; + await waitTime(2000); + if (password === 'ant.design' && username === 'admin') { + res.send({ + status: 'ok', + type, + currentAuthority: 'admin', + }); + access = 'admin'; + return; + } + if (password === 'ant.design' && username === 'user') { + res.send({ + status: 'ok', + type, + currentAuthority: 'user', + }); + access = 'user'; + return; + } + if (type === 'mobile') { + res.send({ + status: 'ok', + type, + currentAuthority: 'admin', + }); + access = 'admin'; + return; + } + + res.send({ + status: 'error', + type, + currentAuthority: 'guest', + }); + access = 'guest'; + }, + 'POST /api/login/outLogin': (req: Request, res: Response) => { + access = ''; + res.send({ data: {}, success: true }); + }, + 'POST /api/register': (req: Request, res: Response) => { + res.send({ status: 'ok', currentAuthority: 'user', success: true }); + }, + 'GET /api/500': (req: Request, res: Response) => { + res.status(500).send({ + timestamp: 1513932555104, + status: 500, + error: 'error', + message: 'error', + path: '/base/category/list', + }); + }, + 'GET /api/404': (req: Request, res: Response) => { + res.status(404).send({ + timestamp: 1513932643431, + status: 404, + error: 'Not Found', + message: 'No message available', + path: '/base/category/list/2121212', + }); + }, + 'GET /api/403': (req: Request, res: Response) => { + res.status(403).send({ + timestamp: 1513932555104, + status: 403, + error: 'Forbidden', + message: 'Forbidden', + path: '/base/category/list', + }); + }, + 'GET /api/401': (req: Request, res: Response) => { + res.status(401).send({ + timestamp: 1513932555104, + status: 401, + error: 'Unauthorized', + message: 'Unauthorized', + path: '/base/category/list', + }); + }, + + 'GET /api/login/captcha': getFakeCaptcha, +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..c18c76b --- /dev/null +++ b/package.json @@ -0,0 +1,147 @@ +{ + "name": "ant-design-pro", + "version": "6.0.0", + "private": true, + "description": "An out-of-box UI solution for enterprise applications", + "scripts": { + "dev": "npm run start:dev", + "build": "max build", + "deploy": "npm run build && npm run gh-pages", + "preview": "npm run build && max preview --port 8000", + "serve": "umi-serve", + "start": "cross-env UMI_ENV=dev max dev", + "start:dev": "cross-env REACT_APP_ENV=dev MOCK=none UMI_ENV=dev max dev", + "start:no-mock": "cross-env MOCK=none UMI_ENV=dev max dev", + "start:pre": "cross-env REACT_APP_ENV=pre UMI_ENV=dev max dev", + "start:test": "cross-env REACT_APP_ENV=test MOCK=none UMI_ENV=dev max dev", + "test": "jest", + "test:coverage": "npm run jest -- --coverage", + "test:update": "npm run jest -- -u", + "docker-hub:build": "docker build -f Dockerfile.hub -t ant-design-pro ./", + "docker-prod:build": "docker-compose -f ./docker/docker-compose.yml build", + "docker-prod:dev": "docker-compose -f ./docker/docker-compose.yml up", + "docker:build": "docker-compose -f ./docker/docker-compose.dev.yml build", + "docker:dev": "docker-compose -f ./docker/docker-compose.dev.yml up", + "docker:push": "npm run docker-hub:build && npm run docker:tag && docker push antdesign/ant-design-pro", + "docker:tag": "docker tag ant-design-pro antdesign/ant-design-pro", + "analyze": "cross-env ANALYZE=1 max build", + "gh-pages": "gh-pages -d dist", + "i18n-remove": "pro i18n-remove --locale=zh-CN --write", + "postinstall": "max setup", + "jest": "jest", + "lint": "npm run lint:js && npm run lint:prettier && npm run tsc", + "lint-staged": "lint-staged", + "lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ", + "lint:fix": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src ", + "lint:js": "eslint --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src", + "lint:prettier": "prettier -c --write \"**/**.{js,jsx,tsx,ts,less,md,json}\" --end-of-line auto", + "openapi": "max openapi", + "prepare": "cd .. && husky install", + "prettier": "prettier -c --write \"**/**.{js,jsx,tsx,ts,less,md,json}\"", + "tsc": "tsc --noEmit", + "record": "cross-env NODE_ENV=development REACT_APP_ENV=test max record --scene=login" + }, + "lint-staged": { + "**/*.{js,jsx,ts,tsx}": "npm run lint-staged:js", + "**/*.{js,jsx,tsx,ts,less,md,json}": [ + "prettier --write" + ] + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not ie <= 10" + ], + "dependencies": { + "@amap/amap-jsapi-loader": "^1.0.1", + "@ant-design/charts": "^2.3.0", + "@ant-design/icons": "^5.5.0", + "@ant-design/maps": "^1.0.0", + "@ant-design/plots": "^2.3.2", + "@ant-design/pro-components": "^2.8.7", + "@ant-design/use-emotion-css": "1.0.4", + "@testing-library/dom": "^10.4.0", + "@umijs/route-utils": "^4.0.1", + "ant-design-pro": "file:", + "antd": "^5.21.1", + "antd-style": "^3.6.2", + "classnames": "^2.5.1", + "dayjs": "^1.11.13", + "echarts": "^5.6.0", + "fabric": "^6.4.0", + "highlight.js": "^11.10.0", + "lodash": "^4.17.21", + "moment": "^2.30.1", + "omit.js": "^2.0.2", + "query-string": "^9.1.0", + "rc-menu": "^9.15.0", + "rc-util": "^5.43.0", + "react": "^18.3.0", + "react-cropper": "^2.3.3", + "react-dev-inspector": "^2.0.1", + "react-dom": "^18.3.0", + "react-helmet-async": "^2.0.0", + "react-highlight": "^0.15.0" + }, + "devDependencies": { + "@ant-design/pro-cli": "^3.3.0", + "@testing-library/react": "^16.0.1", + "@types/classnames": "^2.3.1", + "@types/express": "^4.17.21", + "@types/history": "^4.7.11", + "@types/jest": "^29.5.12", + "@types/lodash": "^4.17.4", + "@types/react": "^18.3.0", + "@types/react-dom": "^18.3.0", + "@types/react-helmet": "^6.1.11", + "@umijs/fabric": "^2.14.1", + "@umijs/lint": "^4.2.9", + "@umijs/max": "^4.2.9", + "cross-env": "^7.0.3", + "eslint": "^9.11.0", + "express": "^4.21.0", + "gh-pages": "^6.1.0", + "husky": "^9.1.3", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": "^15.2.0", + "mockjs": "^1.1.0", + "prettier": "^3.3.0", + "swagger-ui-dist": "^5.17.14", + "ts-node": "^10.9.1", + "typescript": "^5.6.2", + "umi-presets-pro": "^2.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "create-umi": { + "ignoreScript": [ + "docker*", + "functions*", + "site", + "generateMock" + ], + "ignoreDependencies": [ + "netlify*", + "serverless" + ], + "ignore": [ + ".dockerignore", + ".git", + ".github", + ".gitpod.yml", + "CODE_OF_CONDUCT.md", + "Dockerfile", + "Dockerfile.*", + "lambda", + "LICENSE", + "netlify.toml", + "README.*.md", + "azure-pipelines.yml", + "docker", + "CNAME", + "create-umi" + ] + } +} diff --git a/public/CNAME b/public/CNAME new file mode 100644 index 0000000..30c2d4d --- /dev/null +++ b/public/CNAME @@ -0,0 +1 @@ +preview.pro.ant.design \ No newline at end of file diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..e2e93252988b5bed120ddeb168eb577bf0caa881 GIT binary patch literal 4286 zcmeHLO(?8k6#ga#Gs=ufvobTd=q@y~nOLdYlqL%nQY4WqC`)z}3y~cqOAAF4VkQd~ z^3$wrC}~D1l%!eMp!|gA&U5sN?~b{2>)yNg-s#Lc-+9k_p7Y<=XqqYcDJs(Vt%dBG z=F~Lpdy*pd!Y zozZT}udJ-#| zqiAVq0sT@kAMMobbULxOw+F6{j*egO8CQ?TgTuo^+}_@zrlv;l$*-)e#PRVl?(Xgo zi9`?zg>ZFsh0DuJ)Ya9!von7LPN@OfP9IfH_4tet&&I~a#O{TK1<3*LO-xJ( zZ*Fc5%v&m4#Z&mZySs8{XJ-fV^Yh@{p`ju8d_J)w6+U%`!(qAC+uJK~qg_o+O|QC` zTVg0Y{jSHqzP^^&G0t4^cwF+$`egj?@9$AtTMLuPB>7!lUKY8&zP?xd=H_PM(U;HS ztNi!(_oJes0<5X6tu4{BxVR{FO)_x3UauFkv$I%RTSHe@7dAIHF+4mhc?|>t(!XbCXVQZk z8yje7Xh2R*&WCwdw&?N4$H!4$Uyq)i9_;V$3;y)^-LKhmkv{Z#(CP^-7Wn# zI5-H>z`y`nTU%u=f7Tbh-mg5fPT0G8`Wx6^vD1(>-r0;AFlyjWYC!!D@UQlt)%}4^ literal 0 HcmV?d00001 diff --git a/public/icons/icon-128x128.png b/public/icons/icon-128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..48d0e2339a60a637b94319c65e8654289b4f4b6c GIT binary patch literal 1329 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

*C7T$?5!b= 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 + + + + \ No newline at end of file diff --git a/public/scripts/loading.js b/public/scripts/loading.js new file mode 100644 index 0000000..c1ced54 --- /dev/null +++ b/public/scripts/loading.js @@ -0,0 +1,202 @@ +/** + * loading 占位 + * 解决首次加载时白屏的问题 + */ + (function () { + const _root = document.querySelector('#root'); + if (_root && _root.innerHTML === '') { + _root.innerHTML = ` + + +

+
+
+ + + + + + +
+
+
+ 正在加载资源 +
+
+ 初次加载资源可能需要较多时间 请耐心等待 +
+
+ `; + } +})(); diff --git a/src/access.ts b/src/access.ts new file mode 100644 index 0000000..e1f2065 --- /dev/null +++ b/src/access.ts @@ -0,0 +1,55 @@ +import { checkRole, matchPermission } from './utils/permission'; +/** + * @see https://umijs.org/zh-CN/plugins/plugin-access + * */ +export default function access(initialState: { currentUser?: API.CurrentUser } | undefined) { + const { currentUser } = initialState ?? {}; + const hasPerms = (perm: string) => { + return matchPermission(initialState?.currentUser?.permissions, perm); + }; + const roleFiler = (route: { authority: string[] }) => { + return checkRole(initialState?.currentUser?.roles, route.authority); + }; + return { + canAdmin: currentUser && currentUser.access === 'admin', + hasPerms, + roleFiler, + }; +} + +export function setSessionToken( + access_token: string | undefined, + refresh_token: string | undefined, + expireTime: number, +): void{ + if (access_token) { + localStorage.setItem('access_token', access_token); + } else { + localStorage.removeItem('access_token'); + } + if (refresh_token) { + localStorage.setItem('refresh_token', refresh_token); + } else { + localStorage.removeItem('refresh_token'); + } + localStorage.setItem('expireTime', `${expireTime}`); +} + +export function getAccessToken() { + return localStorage.getItem('access_token'); +} + +export function getRefreshToken() { + return localStorage.getItem('refresh_token'); +} + +export function getTokenExpireTime() { + return localStorage.getItem('expireTime'); +} + +export function clearSessionToken() { + sessionStorage.removeItem('user'); + localStorage.removeItem('access_token'); + localStorage.removeItem('refresh_token'); + localStorage.removeItem('expireTime'); +} diff --git a/src/app.tsx b/src/app.tsx new file mode 100644 index 0000000..584436f --- /dev/null +++ b/src/app.tsx @@ -0,0 +1,271 @@ +import { AvatarDropdown, AvatarName, Footer, SelectLang } from '@/components'; +import type { Settings as LayoutSettings } from '@ant-design/pro-components'; +import { SettingDrawer } from '@ant-design/pro-components'; +import type { RunTimeLayoutConfig } from '@umijs/max'; +import { history } from '@umijs/max'; +import defaultSettings from '../config/defaultSettings'; +import { errorConfig } from './requestErrorConfig'; +import { clearSessionToken, getAccessToken, getRefreshToken, getTokenExpireTime } from './access'; +import { + getRemoteMenu, + getRoutersInfo, + getUserInfo, + patchRouteWithRemoteMenus, + setRemoteMenu, +} from './services/session'; +import { PageEnum } from './enums/pagesEnums'; +import { stringify } from 'querystring'; +import { message } from 'antd'; + +const isDev = process.env.NODE_ENV === 'development'; +const loginOut = async () => { + clearSessionToken(); + setRemoteMenu(null); + const { search, pathname } = window.location; + const urlParams = new URL(window.location.href).searchParams; + /** 此方法会跳转到 redirect 参数所在的位置 */ + const redirect = urlParams.get('redirect'); + // Note: There may be security issues, please note + console.log('redirect', window.location.pathname, redirect); + if (window.location.pathname !== '/qingdao/user/login' && !redirect) { + history.replace({ + pathname: '/user/login', + search: stringify({ + redirect: pathname.replace('/qingdao', '') + search, + }), + }); + } +}; + +/** + * @see https://umijs.org/zh-CN/plugins/plugin-initial-state + * */ +export async function getInitialState(): Promise<{ + settings?: Partial; + currentUser?: API.CurrentUser; + loading?: boolean; + fetchUserInfo?: () => Promise; +}> { + const fetchUserInfo = async () => { + try { + const response = await getUserInfo({ + skipErrorHandler: true, + }); + if (response.user.avatar === '') { + response.user.avatar = + 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png'; + } + return { + ...response.user, + permissions: response.permissions, + roles: response.roles, + } as API.CurrentUser; + } catch (error) { + console.log(error); + history.push(PageEnum.LOGIN); + } + return undefined; + }; + // 如果不是登录页面,执行 + const { location } = history; + if (location.pathname !== PageEnum.LOGIN) { + const currentUser = await fetchUserInfo(); + return { + fetchUserInfo, + currentUser, + settings: defaultSettings as Partial, + }; + } + return { + fetchUserInfo, + settings: defaultSettings as Partial, + }; +} + +// ProLayout 支持的api https://procomponents.ant.design/components/layout +export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => { + return { + // actionsRender: () => [, ], + actionsRender: () => [], + avatarProps: { + src: initialState?.currentUser?.avatar, + title: , + render: (_, avatarChildren) => { + return {avatarChildren}; + }, + }, + waterMarkProps: { + // content: initialState?.currentUser?.nickName, + }, + // actionRef: layoutActionRef, + menu: { + locale: false, + // // 每当 initialState?.currentUser?.userid 发生修改时重新执行 request + params: { + userId: initialState?.currentUser?.userId, + }, + request: async () => { + if (!initialState?.currentUser?.userId) { + return []; + } + return getRemoteMenu(); + }, + }, + footerRender: () =>