From 23cec8f081746a414acaeca892f697c03d24d29d Mon Sep 17 00:00:00 2001 From: ktianc <2445667550@qq.com> Date: Fri, 16 Sep 2022 12:32:51 +0800 Subject: [PATCH] frist --- .gitattributes | 4 + .gitignore | 22 + README.en.md | 37 - README.md | 122 +- kinit-admin/.env.base | 11 + kinit-admin/.env.dev | 23 + kinit-admin/.env.gitee | 23 + kinit-admin/.env.pro | 23 + kinit-admin/.env.test | 23 + kinit-admin/.eslintignore | 8 + kinit-admin/.eslintrc.js | 69 + kinit-admin/.github/workflows/auto-merge.yml | 130 ++ .../workflows/reademe-contributors.yml | 25 + kinit-admin/.github/workflows/release.yml | 18 + kinit-admin/.gitignore | 8 + kinit-admin/.husky/commit-msg | 4 + kinit-admin/.husky/lintstagedrc.js | 9 + kinit-admin/.husky/pre-commit | 8 + kinit-admin/.prettierignore | 10 + kinit-admin/.stylelintignore | 6 + kinit-admin/.vscode/extensions.json | 3 + kinit-admin/.vscode/settings.json | 19 + kinit-admin/CHANGELOG.md | 643 ++++++++++ kinit-admin/LICENSE | 21 + kinit-admin/README.md | 240 ++++ kinit-admin/README.zh-CN.md | 240 ++++ kinit-admin/commitlint.config.js | 28 + kinit-admin/index.html | 142 +++ kinit-admin/mock/_createProductionServer.ts | 18 + kinit-admin/mock/analysis/index.ts | 89 ++ kinit-admin/mock/dict/index.ts | 63 + kinit-admin/mock/role/index.ts | 534 ++++++++ kinit-admin/mock/table/index.ts | 137 ++ kinit-admin/mock/user/index.ts | 93 ++ kinit-admin/mock/workplace/index.ts | 172 +++ kinit-admin/package.json | 119 ++ kinit-admin/plop/component/component.hbs | 11 + kinit-admin/plop/component/index.hbs | 3 + kinit-admin/plop/component/prompt.js | 38 + kinit-admin/plop/view/prompt.js | 37 + kinit-admin/plop/view/view.hbs | 7 + kinit-admin/plopfile.js | 7 + kinit-admin/postcss.config.js | 5 + kinit-admin/prettier.config.js | 19 + kinit-admin/public/favicon.ico | Bin 0 -> 4286 bytes kinit-admin/public/logo.png | Bin 0 -> 9193 bytes kinit-admin/src/App.vue | 63 + kinit-admin/src/api/common/index.ts | 11 + .../src/api/dashboard/analysis/index.ts | 23 + .../src/api/dashboard/analysis/types.ts | 22 + .../src/api/dashboard/workplace/index.ts | 22 + .../src/api/dashboard/workplace/types.ts | 30 + kinit-admin/src/api/login/index.ts | 31 + kinit-admin/src/api/login/types.ts | 12 + kinit-admin/src/api/table/index.ts | 18 + kinit-admin/src/api/table/types.ts | 9 + kinit-admin/src/assets/imgs/avatar.jpg | Bin 0 -> 6264 bytes kinit-admin/src/assets/imgs/logo.png | Bin 0 -> 9193 bytes kinit-admin/src/assets/svgs/403.svg | 1 + kinit-admin/src/assets/svgs/404.svg | 1 + kinit-admin/src/assets/svgs/500.svg | 1 + kinit-admin/src/assets/svgs/icon.svg | 1 + kinit-admin/src/assets/svgs/login-bg.svg | 1 + kinit-admin/src/assets/svgs/login-box-bg.svg | 1 + kinit-admin/src/assets/svgs/message.svg | 1 + kinit-admin/src/assets/svgs/money.svg | 1 + kinit-admin/src/assets/svgs/peoples.svg | 1 + kinit-admin/src/assets/svgs/shopping.svg | 1 + kinit-admin/src/components/Backtop/index.ts | 3 + .../src/components/Backtop/src/Backtop.vue | 15 + .../src/components/Breadcrumb/index.ts | 3 + .../components/Breadcrumb/src/Breadcrumb.vue | 127 ++ .../src/components/Breadcrumb/src/helper.ts | 31 + kinit-admin/src/components/Collapse/index.ts | 3 + .../src/components/Collapse/src/Collapse.vue | 35 + .../src/components/ConfigGlobal/index.ts | 3 + .../ConfigGlobal/src/ConfigGlobal.vue | 62 + .../src/components/ContentDetailWrap/index.ts | 3 + .../src/ContentDetailWrap.vue | 59 + .../src/components/ContentWrap/index.ts | 3 + .../ContentWrap/src/ContentWrap.vue | 33 + .../src/components/ContextMenu/index.ts | 10 + .../ContextMenu/src/ContextMenu.vue | 72 ++ kinit-admin/src/components/CountTo/index.ts | 3 + .../src/components/CountTo/src/CountTo.vue | 180 +++ .../src/components/Descriptions/index.ts | 3 + .../Descriptions/src/Descriptions.vue | 139 ++ kinit-admin/src/components/Dialog/index.ts | 3 + .../src/components/Dialog/src/Dialog.vue | 118 ++ kinit-admin/src/components/Echart/index.ts | 3 + .../src/components/Echart/src/Echart.vue | 113 ++ kinit-admin/src/components/Editor/index.ts | 8 + .../src/components/Editor/src/Editor.vue | 138 ++ kinit-admin/src/components/Error/index.ts | 3 + .../src/components/Error/src/Error.vue | 58 + kinit-admin/src/components/Footer/index.ts | 3 + .../src/components/Footer/src/Footer.vue | 22 + kinit-admin/src/components/Form/index.ts | 14 + kinit-admin/src/components/Form/src/Form.vue | 299 +++++ .../src/components/Form/src/componentMap.ts | 48 + .../Form/src/components/useRenderCheckbox.tsx | 20 + .../Form/src/components/useRenderRadio.tsx | 20 + .../Form/src/components/useRenderSelect.tsx | 48 + kinit-admin/src/components/Form/src/helper.ts | 148 +++ kinit-admin/src/components/Form/src/types.ts | 15 + kinit-admin/src/components/Highlight/index.ts | 3 + .../components/Highlight/src/Highlight.vue | 65 + kinit-admin/src/components/Icon/index.ts | 3 + kinit-admin/src/components/Icon/src/Icon.vue | 78 ++ .../src/components/ImageViewer/index.ts | 33 + .../ImageViewer/src/ImageViewer.vue | 34 + .../src/components/ImageViewer/src/types.ts | 9 + kinit-admin/src/components/Infotip/index.ts | 3 + .../src/components/Infotip/src/Infotip.vue | 52 + .../src/components/InputPassword/index.ts | 3 + .../InputPassword/src/InputPassword.vue | 152 +++ .../src/components/LocaleDropdown/index.ts | 3 + .../LocaleDropdown/src/LocaleDropdown.vue | 52 + kinit-admin/src/components/Logo/index.ts | 3 + kinit-admin/src/components/Logo/src/Logo.vue | 85 ++ kinit-admin/src/components/Menu/index.ts | 3 + kinit-admin/src/components/Menu/src/Menu.vue | 299 +++++ .../Menu/src/components/useRenderMenuItem.tsx | 59 + .../src/components/useRenderMenuTitle.tsx | 23 + kinit-admin/src/components/Menu/src/helper.ts | 55 + kinit-admin/src/components/Qrcode/index.ts | 3 + .../src/components/Qrcode/src/Qrcode.vue | 251 ++++ .../src/components/Screenfull/index.ts | 3 + .../components/Screenfull/src/Screenfull.vue | 30 + kinit-admin/src/components/Search/index.ts | 3 + .../src/components/Search/src/Search.vue | 139 ++ kinit-admin/src/components/Setting/index.ts | 3 + .../src/components/Setting/src/Setting.vue | 301 +++++ .../src/components/ColorRadioPicker.vue | 65 + .../src/components/InterfaceDisplay.vue | 202 +++ .../src/components/LayoutRadioPicker.vue | 171 +++ .../src/components/SizeDropdown/index.ts | 3 + .../SizeDropdown/src/SizeDropdown.vue | 39 + kinit-admin/src/components/Sticky/index.ts | 3 + .../src/components/Sticky/src/Sticky.vue | 141 +++ kinit-admin/src/components/TabMenu/index.ts | 3 + .../src/components/TabMenu/src/TabMenu.vue | 226 ++++ .../src/components/TabMenu/src/helper.ts | 52 + kinit-admin/src/components/Table/index.ts | 11 + .../src/components/Table/src/Table.vue | 297 +++++ .../src/components/Table/src/helper.ts | 8 + kinit-admin/src/components/Table/src/types.ts | 24 + kinit-admin/src/components/TagsView/index.ts | 3 + .../src/components/TagsView/src/TagsView.vue | 579 +++++++++ .../src/components/TagsView/src/helper.ts | 21 + .../src/components/ThemeSwitch/index.ts | 3 + .../ThemeSwitch/src/ThemeSwitch.vue | 41 + kinit-admin/src/components/UserInfo/index.ts | 3 + .../src/components/UserInfo/src/UserInfo.vue | 67 + kinit-admin/src/components/index.ts | 6 + kinit-admin/src/config/app.ts | 106 ++ kinit-admin/src/config/axios/config.ts | 46 + kinit-admin/src/config/axios/index.ts | 33 + kinit-admin/src/config/axios/service.ts | 70 + kinit-admin/src/config/locale.ts | 32 + kinit-admin/src/directives/index.ts | 10 + .../src/directives/permission/hasPermi.ts | 47 + kinit-admin/src/hooks/event/useScrollTo.ts | 62 + kinit-admin/src/hooks/web/useCache.ts | 17 + kinit-admin/src/hooks/web/useConfigGlobal.ts | 9 + kinit-admin/src/hooks/web/useCrudSchemas.ts | 251 ++++ kinit-admin/src/hooks/web/useDesign.ts | 18 + kinit-admin/src/hooks/web/useEmitt.ts | 23 + kinit-admin/src/hooks/web/useForm.ts | 91 ++ kinit-admin/src/hooks/web/useI18n.ts | 52 + kinit-admin/src/hooks/web/useIcon.ts | 7 + kinit-admin/src/hooks/web/useIntro.ts | 47 + kinit-admin/src/hooks/web/useLocale.ts | 35 + kinit-admin/src/hooks/web/useNProgress.ts | 34 + kinit-admin/src/hooks/web/usePageLoading.ts | 18 + kinit-admin/src/hooks/web/useTable.ts | 191 +++ kinit-admin/src/hooks/web/useTimeAgo.ts | 48 + kinit-admin/src/hooks/web/useTitle.ts | 25 + kinit-admin/src/hooks/web/useValidator.ts | 64 + kinit-admin/src/hooks/web/useWatermark.ts | 55 + kinit-admin/src/layout/Layout.vue | 78 ++ kinit-admin/src/layout/components/AppView.vue | 52 + .../src/layout/components/ToolHeader.vue | 83 ++ .../src/layout/components/useRenderLayout.tsx | 263 ++++ kinit-admin/src/locales/en.ts | 441 +++++++ kinit-admin/src/locales/zh-CN.ts | 437 +++++++ kinit-admin/src/main.ts | 55 + kinit-admin/src/permission.ts | 82 ++ kinit-admin/src/plugins/animate.css/index.ts | 1 + kinit-admin/src/plugins/echarts/index.ts | 41 + kinit-admin/src/plugins/elementPlus/index.ts | 18 + kinit-admin/src/plugins/svgIcon/index.ts | 3 + kinit-admin/src/plugins/vueI18n/helper.ts | 3 + kinit-admin/src/plugins/vueI18n/index.ts | 42 + kinit-admin/src/plugins/windi.css/index.ts | 3 + kinit-admin/src/router/index.ts | 569 +++++++++ kinit-admin/src/store/index.ts | 13 + kinit-admin/src/store/modules/app.ts | 184 +++ kinit-admin/src/store/modules/dict.ts | 38 + kinit-admin/src/store/modules/locale.ts | 35 + kinit-admin/src/store/modules/permission.ts | 84 ++ kinit-admin/src/store/modules/tagsView.ts | 141 +++ kinit-admin/src/styles/index.less | 2 + kinit-admin/src/styles/theme.less | 6 + kinit-admin/src/styles/var.css | 67 + kinit-admin/src/styles/variables.module.less | 10 + kinit-admin/src/utils/color.ts | 153 +++ kinit-admin/src/utils/domUtils.ts | 289 +++++ kinit-admin/src/utils/index.ts | 110 ++ kinit-admin/src/utils/is.ts | 105 ++ kinit-admin/src/utils/propTypes.ts | 29 + kinit-admin/src/utils/routerHelper.ts | 194 +++ kinit-admin/src/utils/tree.ts | 207 +++ kinit-admin/src/utils/tsxHelper.ts | 16 + kinit-admin/src/views/Authorization/Role.vue | 88 ++ kinit-admin/src/views/Authorization/User.vue | 88 ++ kinit-admin/src/views/Components/CountTo.vue | 100 ++ .../src/views/Components/Descriptions.vue | 142 +++ kinit-admin/src/views/Components/Dialog.vue | 147 +++ kinit-admin/src/views/Components/Echart.vue | 36 + .../src/views/Components/Editor/Editor.vue | 32 + .../src/views/Components/Form/DefaultForm.vue | 1127 +++++++++++++++++ .../src/views/Components/Form/RefForm.vue | 269 ++++ .../src/views/Components/Form/UseFormDemo.vue | 279 ++++ .../src/views/Components/Highlight.vue | 20 + kinit-admin/src/views/Components/Icon.vue | 62 + .../src/views/Components/ImageViewer.vue | 30 + kinit-admin/src/views/Components/Infotip.vue | 33 + .../src/views/Components/InputPassword.vue | 21 + kinit-admin/src/views/Components/Qrcode.vue | 108 ++ kinit-admin/src/views/Components/Search.vue | 226 ++++ kinit-admin/src/views/Components/Sticky.vue | 62 + .../views/Components/Table/DefaultTable.vue | 100 ++ .../src/views/Components/Table/RefTable.vue | 181 +++ .../views/Components/Table/UseTableDemo.vue | 180 +++ kinit-admin/src/views/Dashboard/Analysis.vue | 127 ++ kinit-admin/src/views/Dashboard/Workplace.vue | 291 +++++ .../views/Dashboard/components/PanelGroup.vue | 200 +++ .../src/views/Dashboard/echarts-data.ts | 310 +++++ kinit-admin/src/views/Error/403.vue | 17 + kinit-admin/src/views/Error/404.vue | 17 + kinit-admin/src/views/Error/500.vue | 17 + .../views/Example/Dialog/ExampleDialog.vue | 273 ++++ .../Example/Dialog/components/Detail.vue | 40 + .../views/Example/Dialog/components/Write.vue | 55 + .../src/views/Example/Page/ExampleAdd.vue | 52 + .../src/views/Example/Page/ExampleDetail.vue | 32 + .../src/views/Example/Page/ExampleEdit.vue | 64 + .../src/views/Example/Page/ExamplePage.vue | 164 +++ .../views/Example/Page/components/Detail.vue | 65 + .../views/Example/Page/components/Write.vue | 146 +++ kinit-admin/src/views/Guide/Guide.vue | 20 + kinit-admin/src/views/Level/Menu111.vue | 20 + kinit-admin/src/views/Level/Menu12.vue | 20 + kinit-admin/src/views/Level/Menu2.vue | 20 + kinit-admin/src/views/Login/Login.vue | 109 ++ .../src/views/Login/components/LoginForm.vue | 257 ++++ .../views/Login/components/RegisterForm.vue | 144 +++ .../src/views/Login/components/index.ts | 4 + kinit-admin/src/views/Redirect/Redirect.vue | 30 + .../src/views/hooks/useCrudSchemas.vue | 222 ++++ kinit-admin/src/views/hooks/useWatermark.vue | 32 + kinit-admin/stylelint.config.js | 231 ++++ kinit-admin/tsconfig.json | 39 + .../types/componentType/configGlobal.d.ts | 3 + .../types/componentType/contextMenu.d.ts | 7 + .../types/componentType/descriptions.d.ts | 11 + kinit-admin/types/componentType/form.d.ts | 97 ++ kinit-admin/types/componentType/icon.d.ts | 5 + kinit-admin/types/componentType/infotip.d.ts | 4 + .../types/componentType/localeDropdown.d.ts | 10 + kinit-admin/types/componentType/qrcode.d.ts | 9 + kinit-admin/types/componentType/table.d.ts | 36 + kinit-admin/types/components.d.ts | 7 + kinit-admin/types/custom-types.d.ts | 27 + kinit-admin/types/env.d.ts | 24 + kinit-admin/types/global.d.ts | 40 + kinit-admin/types/router.d.ts | 74 ++ kinit-admin/vite.config.ts | 152 +++ kinit-admin/windi.config.ts | 76 ++ kinit-api/.gitignore | 31 + kinit-api/README.md | 107 ++ kinit-api/alembic.ini | 100 ++ kinit-api/alembic/README | 1 + kinit-api/alembic/env.py | 96 ++ kinit-api/alembic/script.py.mako | 24 + .../alembic/versions/03e55ed3e858_update.py | 30 + .../alembic/versions/0cd7a858c5a5_update.py | 66 + .../alembic/versions/5e629ba5c3c8_update.py | 88 ++ .../alembic/versions/65797098992b_update.py | 111 ++ .../versions/a95a845d335f_生成迁移文件.py | 24 + .../versions/bc1417d96581_更新迁移文件.py | 46 + .../alembic/versions/d4898760c577_update.py | 28 + .../alembic/versions/ecb50546debd_update.py | 28 + .../alembic/versions/f2390b45da1d_update.py | 28 + kinit-api/application/__init__.py | 0 kinit-api/application/settings.py | 86 ++ kinit-api/application/urls.py | 16 + kinit-api/apps/__init__.py | 13 + kinit-api/apps/vadmin/__init__.py | 0 kinit-api/apps/vadmin/auth/__init__.py | 0 kinit-api/apps/vadmin/auth/crud.py | 144 +++ kinit-api/apps/vadmin/auth/models/__init__.py | 13 + kinit-api/apps/vadmin/auth/models/m2m.py | 28 + kinit-api/apps/vadmin/auth/models/menu.py | 38 + kinit-api/apps/vadmin/auth/models/role.py | 27 + kinit-api/apps/vadmin/auth/models/user.py | 67 + .../apps/vadmin/auth/schemas/__init__.py | 3 + kinit-api/apps/vadmin/auth/schemas/menu.py | 82 ++ kinit-api/apps/vadmin/auth/schemas/role.py | 54 + kinit-api/apps/vadmin/auth/schemas/user.py | 63 + kinit-api/apps/vadmin/auth/utils/__init__.py | 7 + kinit-api/apps/vadmin/auth/utils/auth_util.py | 64 + kinit-api/apps/vadmin/auth/utils/current.py | 108 ++ kinit-api/apps/vadmin/auth/utils/login.py | 97 ++ kinit-api/apps/vadmin/auth/views.py | 126 ++ kinit-api/apps/vadmin/record/__init__.py | 0 kinit-api/apps/vadmin/record/crud.py | 24 + .../apps/vadmin/record/models/__init__.py | 12 + kinit-api/apps/vadmin/record/models/login.py | 43 + .../apps/vadmin/record/models/operation.py | 47 + kinit-api/apps/vadmin/record/models/sms.py | 23 + .../apps/vadmin/record/schemas/__init__.py | 2 + kinit-api/apps/vadmin/record/schemas/login.py | 33 + kinit-api/apps/vadmin/record/schemas/sms.py | 30 + kinit-api/apps/vadmin/record/views.py | 38 + kinit-api/apps/vadmin/system/__init__.py | 0 kinit-api/apps/vadmin/system/crud.py | 42 + .../apps/vadmin/system/models/__init__.py | 1 + kinit-api/apps/vadmin/system/models/dict.py | 36 + .../apps/vadmin/system/schemas/__init__.py | 1 + kinit-api/apps/vadmin/system/schemas/dict.py | 60 + kinit-api/apps/vadmin/system/views.py | 104 ++ kinit-api/core/__init__.py | 0 kinit-api/core/crud.py | 216 ++++ kinit-api/core/database.py | 89 ++ kinit-api/core/dependencies.py | 30 + kinit-api/core/exception.py | 107 ++ kinit-api/core/logger.py | 28 + kinit-api/core/middleware.py | 43 + kinit-api/core/validator.py | 42 + kinit-api/db/__init__.py | 0 kinit-api/db/db_base.py | 23 + kinit-api/logs/.gitkeep | 0 kinit-api/main.py | 80 ++ kinit-api/requirements.txt | 47 + kinit-api/static/.gitkeep | 0 kinit-api/temp/.gitkeep | 0 kinit-api/utils/__init__.py | 0 kinit-api/utils/crawle.py | 27 + kinit-api/utils/response.py | 36 + kinit-api/utils/save_file.py | 22 + kinit-api/utils/status.py | 11 + 353 files changed, 24351 insertions(+), 74 deletions(-) create mode 100644 .gitattributes create mode 100644 .gitignore delete mode 100644 README.en.md create mode 100644 kinit-admin/.env.base create mode 100644 kinit-admin/.env.dev create mode 100644 kinit-admin/.env.gitee create mode 100644 kinit-admin/.env.pro create mode 100644 kinit-admin/.env.test create mode 100644 kinit-admin/.eslintignore create mode 100644 kinit-admin/.eslintrc.js create mode 100644 kinit-admin/.github/workflows/auto-merge.yml create mode 100644 kinit-admin/.github/workflows/reademe-contributors.yml create mode 100644 kinit-admin/.github/workflows/release.yml create mode 100644 kinit-admin/.gitignore create mode 100644 kinit-admin/.husky/commit-msg create mode 100644 kinit-admin/.husky/lintstagedrc.js create mode 100644 kinit-admin/.husky/pre-commit create mode 100644 kinit-admin/.prettierignore create mode 100644 kinit-admin/.stylelintignore create mode 100644 kinit-admin/.vscode/extensions.json create mode 100644 kinit-admin/.vscode/settings.json create mode 100644 kinit-admin/CHANGELOG.md create mode 100644 kinit-admin/LICENSE create mode 100644 kinit-admin/README.md create mode 100644 kinit-admin/README.zh-CN.md create mode 100644 kinit-admin/commitlint.config.js create mode 100644 kinit-admin/index.html create mode 100644 kinit-admin/mock/_createProductionServer.ts create mode 100644 kinit-admin/mock/analysis/index.ts create mode 100644 kinit-admin/mock/dict/index.ts create mode 100644 kinit-admin/mock/role/index.ts create mode 100644 kinit-admin/mock/table/index.ts create mode 100644 kinit-admin/mock/user/index.ts create mode 100644 kinit-admin/mock/workplace/index.ts create mode 100644 kinit-admin/package.json create mode 100644 kinit-admin/plop/component/component.hbs create mode 100644 kinit-admin/plop/component/index.hbs create mode 100644 kinit-admin/plop/component/prompt.js create mode 100644 kinit-admin/plop/view/prompt.js create mode 100644 kinit-admin/plop/view/view.hbs create mode 100644 kinit-admin/plopfile.js create mode 100644 kinit-admin/postcss.config.js create mode 100644 kinit-admin/prettier.config.js create mode 100644 kinit-admin/public/favicon.ico create mode 100644 kinit-admin/public/logo.png create mode 100644 kinit-admin/src/App.vue create mode 100644 kinit-admin/src/api/common/index.ts create mode 100644 kinit-admin/src/api/dashboard/analysis/index.ts create mode 100644 kinit-admin/src/api/dashboard/analysis/types.ts create mode 100644 kinit-admin/src/api/dashboard/workplace/index.ts create mode 100644 kinit-admin/src/api/dashboard/workplace/types.ts create mode 100644 kinit-admin/src/api/login/index.ts create mode 100644 kinit-admin/src/api/login/types.ts create mode 100644 kinit-admin/src/api/table/index.ts create mode 100644 kinit-admin/src/api/table/types.ts create mode 100644 kinit-admin/src/assets/imgs/avatar.jpg create mode 100644 kinit-admin/src/assets/imgs/logo.png create mode 100644 kinit-admin/src/assets/svgs/403.svg create mode 100644 kinit-admin/src/assets/svgs/404.svg create mode 100644 kinit-admin/src/assets/svgs/500.svg create mode 100644 kinit-admin/src/assets/svgs/icon.svg create mode 100644 kinit-admin/src/assets/svgs/login-bg.svg create mode 100644 kinit-admin/src/assets/svgs/login-box-bg.svg create mode 100644 kinit-admin/src/assets/svgs/message.svg create mode 100644 kinit-admin/src/assets/svgs/money.svg create mode 100644 kinit-admin/src/assets/svgs/peoples.svg create mode 100644 kinit-admin/src/assets/svgs/shopping.svg create mode 100644 kinit-admin/src/components/Backtop/index.ts create mode 100644 kinit-admin/src/components/Backtop/src/Backtop.vue create mode 100644 kinit-admin/src/components/Breadcrumb/index.ts create mode 100644 kinit-admin/src/components/Breadcrumb/src/Breadcrumb.vue create mode 100644 kinit-admin/src/components/Breadcrumb/src/helper.ts create mode 100644 kinit-admin/src/components/Collapse/index.ts create mode 100644 kinit-admin/src/components/Collapse/src/Collapse.vue create mode 100644 kinit-admin/src/components/ConfigGlobal/index.ts create mode 100644 kinit-admin/src/components/ConfigGlobal/src/ConfigGlobal.vue create mode 100644 kinit-admin/src/components/ContentDetailWrap/index.ts create mode 100644 kinit-admin/src/components/ContentDetailWrap/src/ContentDetailWrap.vue create mode 100644 kinit-admin/src/components/ContentWrap/index.ts create mode 100644 kinit-admin/src/components/ContentWrap/src/ContentWrap.vue create mode 100644 kinit-admin/src/components/ContextMenu/index.ts create mode 100644 kinit-admin/src/components/ContextMenu/src/ContextMenu.vue create mode 100644 kinit-admin/src/components/CountTo/index.ts create mode 100644 kinit-admin/src/components/CountTo/src/CountTo.vue create mode 100644 kinit-admin/src/components/Descriptions/index.ts create mode 100644 kinit-admin/src/components/Descriptions/src/Descriptions.vue create mode 100644 kinit-admin/src/components/Dialog/index.ts create mode 100644 kinit-admin/src/components/Dialog/src/Dialog.vue create mode 100644 kinit-admin/src/components/Echart/index.ts create mode 100644 kinit-admin/src/components/Echart/src/Echart.vue create mode 100644 kinit-admin/src/components/Editor/index.ts create mode 100644 kinit-admin/src/components/Editor/src/Editor.vue create mode 100644 kinit-admin/src/components/Error/index.ts create mode 100644 kinit-admin/src/components/Error/src/Error.vue create mode 100644 kinit-admin/src/components/Footer/index.ts create mode 100644 kinit-admin/src/components/Footer/src/Footer.vue create mode 100644 kinit-admin/src/components/Form/index.ts create mode 100644 kinit-admin/src/components/Form/src/Form.vue create mode 100644 kinit-admin/src/components/Form/src/componentMap.ts create mode 100644 kinit-admin/src/components/Form/src/components/useRenderCheckbox.tsx create mode 100644 kinit-admin/src/components/Form/src/components/useRenderRadio.tsx create mode 100644 kinit-admin/src/components/Form/src/components/useRenderSelect.tsx create mode 100644 kinit-admin/src/components/Form/src/helper.ts create mode 100644 kinit-admin/src/components/Form/src/types.ts create mode 100644 kinit-admin/src/components/Highlight/index.ts create mode 100644 kinit-admin/src/components/Highlight/src/Highlight.vue create mode 100644 kinit-admin/src/components/Icon/index.ts create mode 100644 kinit-admin/src/components/Icon/src/Icon.vue create mode 100644 kinit-admin/src/components/ImageViewer/index.ts create mode 100644 kinit-admin/src/components/ImageViewer/src/ImageViewer.vue create mode 100644 kinit-admin/src/components/ImageViewer/src/types.ts create mode 100644 kinit-admin/src/components/Infotip/index.ts create mode 100644 kinit-admin/src/components/Infotip/src/Infotip.vue create mode 100644 kinit-admin/src/components/InputPassword/index.ts create mode 100644 kinit-admin/src/components/InputPassword/src/InputPassword.vue create mode 100644 kinit-admin/src/components/LocaleDropdown/index.ts create mode 100644 kinit-admin/src/components/LocaleDropdown/src/LocaleDropdown.vue create mode 100644 kinit-admin/src/components/Logo/index.ts create mode 100644 kinit-admin/src/components/Logo/src/Logo.vue create mode 100644 kinit-admin/src/components/Menu/index.ts create mode 100644 kinit-admin/src/components/Menu/src/Menu.vue create mode 100644 kinit-admin/src/components/Menu/src/components/useRenderMenuItem.tsx create mode 100644 kinit-admin/src/components/Menu/src/components/useRenderMenuTitle.tsx create mode 100644 kinit-admin/src/components/Menu/src/helper.ts create mode 100644 kinit-admin/src/components/Qrcode/index.ts create mode 100644 kinit-admin/src/components/Qrcode/src/Qrcode.vue create mode 100644 kinit-admin/src/components/Screenfull/index.ts create mode 100644 kinit-admin/src/components/Screenfull/src/Screenfull.vue create mode 100644 kinit-admin/src/components/Search/index.ts create mode 100644 kinit-admin/src/components/Search/src/Search.vue create mode 100644 kinit-admin/src/components/Setting/index.ts create mode 100644 kinit-admin/src/components/Setting/src/Setting.vue create mode 100644 kinit-admin/src/components/Setting/src/components/ColorRadioPicker.vue create mode 100644 kinit-admin/src/components/Setting/src/components/InterfaceDisplay.vue create mode 100644 kinit-admin/src/components/Setting/src/components/LayoutRadioPicker.vue create mode 100644 kinit-admin/src/components/SizeDropdown/index.ts create mode 100644 kinit-admin/src/components/SizeDropdown/src/SizeDropdown.vue create mode 100644 kinit-admin/src/components/Sticky/index.ts create mode 100644 kinit-admin/src/components/Sticky/src/Sticky.vue create mode 100644 kinit-admin/src/components/TabMenu/index.ts create mode 100644 kinit-admin/src/components/TabMenu/src/TabMenu.vue create mode 100644 kinit-admin/src/components/TabMenu/src/helper.ts create mode 100644 kinit-admin/src/components/Table/index.ts create mode 100644 kinit-admin/src/components/Table/src/Table.vue create mode 100644 kinit-admin/src/components/Table/src/helper.ts create mode 100644 kinit-admin/src/components/Table/src/types.ts create mode 100644 kinit-admin/src/components/TagsView/index.ts create mode 100644 kinit-admin/src/components/TagsView/src/TagsView.vue create mode 100644 kinit-admin/src/components/TagsView/src/helper.ts create mode 100644 kinit-admin/src/components/ThemeSwitch/index.ts create mode 100644 kinit-admin/src/components/ThemeSwitch/src/ThemeSwitch.vue create mode 100644 kinit-admin/src/components/UserInfo/index.ts create mode 100644 kinit-admin/src/components/UserInfo/src/UserInfo.vue create mode 100644 kinit-admin/src/components/index.ts create mode 100644 kinit-admin/src/config/app.ts create mode 100644 kinit-admin/src/config/axios/config.ts create mode 100644 kinit-admin/src/config/axios/index.ts create mode 100644 kinit-admin/src/config/axios/service.ts create mode 100644 kinit-admin/src/config/locale.ts create mode 100644 kinit-admin/src/directives/index.ts create mode 100644 kinit-admin/src/directives/permission/hasPermi.ts create mode 100644 kinit-admin/src/hooks/event/useScrollTo.ts create mode 100644 kinit-admin/src/hooks/web/useCache.ts create mode 100644 kinit-admin/src/hooks/web/useConfigGlobal.ts create mode 100644 kinit-admin/src/hooks/web/useCrudSchemas.ts create mode 100644 kinit-admin/src/hooks/web/useDesign.ts create mode 100644 kinit-admin/src/hooks/web/useEmitt.ts create mode 100644 kinit-admin/src/hooks/web/useForm.ts create mode 100644 kinit-admin/src/hooks/web/useI18n.ts create mode 100644 kinit-admin/src/hooks/web/useIcon.ts create mode 100644 kinit-admin/src/hooks/web/useIntro.ts create mode 100644 kinit-admin/src/hooks/web/useLocale.ts create mode 100644 kinit-admin/src/hooks/web/useNProgress.ts create mode 100644 kinit-admin/src/hooks/web/usePageLoading.ts create mode 100644 kinit-admin/src/hooks/web/useTable.ts create mode 100644 kinit-admin/src/hooks/web/useTimeAgo.ts create mode 100644 kinit-admin/src/hooks/web/useTitle.ts create mode 100644 kinit-admin/src/hooks/web/useValidator.ts create mode 100644 kinit-admin/src/hooks/web/useWatermark.ts create mode 100644 kinit-admin/src/layout/Layout.vue create mode 100644 kinit-admin/src/layout/components/AppView.vue create mode 100644 kinit-admin/src/layout/components/ToolHeader.vue create mode 100644 kinit-admin/src/layout/components/useRenderLayout.tsx create mode 100644 kinit-admin/src/locales/en.ts create mode 100644 kinit-admin/src/locales/zh-CN.ts create mode 100644 kinit-admin/src/main.ts create mode 100644 kinit-admin/src/permission.ts create mode 100644 kinit-admin/src/plugins/animate.css/index.ts create mode 100644 kinit-admin/src/plugins/echarts/index.ts create mode 100644 kinit-admin/src/plugins/elementPlus/index.ts create mode 100644 kinit-admin/src/plugins/svgIcon/index.ts create mode 100644 kinit-admin/src/plugins/vueI18n/helper.ts create mode 100644 kinit-admin/src/plugins/vueI18n/index.ts create mode 100644 kinit-admin/src/plugins/windi.css/index.ts create mode 100644 kinit-admin/src/router/index.ts create mode 100644 kinit-admin/src/store/index.ts create mode 100644 kinit-admin/src/store/modules/app.ts create mode 100644 kinit-admin/src/store/modules/dict.ts create mode 100644 kinit-admin/src/store/modules/locale.ts create mode 100644 kinit-admin/src/store/modules/permission.ts create mode 100644 kinit-admin/src/store/modules/tagsView.ts create mode 100644 kinit-admin/src/styles/index.less create mode 100644 kinit-admin/src/styles/theme.less create mode 100644 kinit-admin/src/styles/var.css create mode 100644 kinit-admin/src/styles/variables.module.less create mode 100644 kinit-admin/src/utils/color.ts create mode 100644 kinit-admin/src/utils/domUtils.ts create mode 100644 kinit-admin/src/utils/index.ts create mode 100644 kinit-admin/src/utils/is.ts create mode 100644 kinit-admin/src/utils/propTypes.ts create mode 100644 kinit-admin/src/utils/routerHelper.ts create mode 100644 kinit-admin/src/utils/tree.ts create mode 100644 kinit-admin/src/utils/tsxHelper.ts create mode 100644 kinit-admin/src/views/Authorization/Role.vue create mode 100644 kinit-admin/src/views/Authorization/User.vue create mode 100644 kinit-admin/src/views/Components/CountTo.vue create mode 100644 kinit-admin/src/views/Components/Descriptions.vue create mode 100644 kinit-admin/src/views/Components/Dialog.vue create mode 100644 kinit-admin/src/views/Components/Echart.vue create mode 100644 kinit-admin/src/views/Components/Editor/Editor.vue create mode 100644 kinit-admin/src/views/Components/Form/DefaultForm.vue create mode 100644 kinit-admin/src/views/Components/Form/RefForm.vue create mode 100644 kinit-admin/src/views/Components/Form/UseFormDemo.vue create mode 100644 kinit-admin/src/views/Components/Highlight.vue create mode 100644 kinit-admin/src/views/Components/Icon.vue create mode 100644 kinit-admin/src/views/Components/ImageViewer.vue create mode 100644 kinit-admin/src/views/Components/Infotip.vue create mode 100644 kinit-admin/src/views/Components/InputPassword.vue create mode 100644 kinit-admin/src/views/Components/Qrcode.vue create mode 100644 kinit-admin/src/views/Components/Search.vue create mode 100644 kinit-admin/src/views/Components/Sticky.vue create mode 100644 kinit-admin/src/views/Components/Table/DefaultTable.vue create mode 100644 kinit-admin/src/views/Components/Table/RefTable.vue create mode 100644 kinit-admin/src/views/Components/Table/UseTableDemo.vue create mode 100644 kinit-admin/src/views/Dashboard/Analysis.vue create mode 100644 kinit-admin/src/views/Dashboard/Workplace.vue create mode 100644 kinit-admin/src/views/Dashboard/components/PanelGroup.vue create mode 100644 kinit-admin/src/views/Dashboard/echarts-data.ts create mode 100644 kinit-admin/src/views/Error/403.vue create mode 100644 kinit-admin/src/views/Error/404.vue create mode 100644 kinit-admin/src/views/Error/500.vue create mode 100644 kinit-admin/src/views/Example/Dialog/ExampleDialog.vue create mode 100644 kinit-admin/src/views/Example/Dialog/components/Detail.vue create mode 100644 kinit-admin/src/views/Example/Dialog/components/Write.vue create mode 100644 kinit-admin/src/views/Example/Page/ExampleAdd.vue create mode 100644 kinit-admin/src/views/Example/Page/ExampleDetail.vue create mode 100644 kinit-admin/src/views/Example/Page/ExampleEdit.vue create mode 100644 kinit-admin/src/views/Example/Page/ExamplePage.vue create mode 100644 kinit-admin/src/views/Example/Page/components/Detail.vue create mode 100644 kinit-admin/src/views/Example/Page/components/Write.vue create mode 100644 kinit-admin/src/views/Guide/Guide.vue create mode 100644 kinit-admin/src/views/Level/Menu111.vue create mode 100644 kinit-admin/src/views/Level/Menu12.vue create mode 100644 kinit-admin/src/views/Level/Menu2.vue create mode 100644 kinit-admin/src/views/Login/Login.vue create mode 100644 kinit-admin/src/views/Login/components/LoginForm.vue create mode 100644 kinit-admin/src/views/Login/components/RegisterForm.vue create mode 100644 kinit-admin/src/views/Login/components/index.ts create mode 100644 kinit-admin/src/views/Redirect/Redirect.vue create mode 100644 kinit-admin/src/views/hooks/useCrudSchemas.vue create mode 100644 kinit-admin/src/views/hooks/useWatermark.vue create mode 100644 kinit-admin/stylelint.config.js create mode 100644 kinit-admin/tsconfig.json create mode 100644 kinit-admin/types/componentType/configGlobal.d.ts create mode 100644 kinit-admin/types/componentType/contextMenu.d.ts create mode 100644 kinit-admin/types/componentType/descriptions.d.ts create mode 100644 kinit-admin/types/componentType/form.d.ts create mode 100644 kinit-admin/types/componentType/icon.d.ts create mode 100644 kinit-admin/types/componentType/infotip.d.ts create mode 100644 kinit-admin/types/componentType/localeDropdown.d.ts create mode 100644 kinit-admin/types/componentType/qrcode.d.ts create mode 100644 kinit-admin/types/componentType/table.d.ts create mode 100644 kinit-admin/types/components.d.ts create mode 100644 kinit-admin/types/custom-types.d.ts create mode 100644 kinit-admin/types/env.d.ts create mode 100644 kinit-admin/types/global.d.ts create mode 100644 kinit-admin/types/router.d.ts create mode 100644 kinit-admin/vite.config.ts create mode 100644 kinit-admin/windi.config.ts create mode 100644 kinit-api/.gitignore create mode 100644 kinit-api/README.md create mode 100644 kinit-api/alembic.ini create mode 100644 kinit-api/alembic/README create mode 100644 kinit-api/alembic/env.py create mode 100644 kinit-api/alembic/script.py.mako create mode 100644 kinit-api/alembic/versions/03e55ed3e858_update.py create mode 100644 kinit-api/alembic/versions/0cd7a858c5a5_update.py create mode 100644 kinit-api/alembic/versions/5e629ba5c3c8_update.py create mode 100644 kinit-api/alembic/versions/65797098992b_update.py create mode 100644 kinit-api/alembic/versions/a95a845d335f_生成迁移文件.py create mode 100644 kinit-api/alembic/versions/bc1417d96581_更新迁移文件.py create mode 100644 kinit-api/alembic/versions/d4898760c577_update.py create mode 100644 kinit-api/alembic/versions/ecb50546debd_update.py create mode 100644 kinit-api/alembic/versions/f2390b45da1d_update.py create mode 100644 kinit-api/application/__init__.py create mode 100644 kinit-api/application/settings.py create mode 100644 kinit-api/application/urls.py create mode 100644 kinit-api/apps/__init__.py create mode 100644 kinit-api/apps/vadmin/__init__.py create mode 100644 kinit-api/apps/vadmin/auth/__init__.py create mode 100644 kinit-api/apps/vadmin/auth/crud.py create mode 100644 kinit-api/apps/vadmin/auth/models/__init__.py create mode 100644 kinit-api/apps/vadmin/auth/models/m2m.py create mode 100644 kinit-api/apps/vadmin/auth/models/menu.py create mode 100644 kinit-api/apps/vadmin/auth/models/role.py create mode 100644 kinit-api/apps/vadmin/auth/models/user.py create mode 100644 kinit-api/apps/vadmin/auth/schemas/__init__.py create mode 100644 kinit-api/apps/vadmin/auth/schemas/menu.py create mode 100644 kinit-api/apps/vadmin/auth/schemas/role.py create mode 100644 kinit-api/apps/vadmin/auth/schemas/user.py create mode 100644 kinit-api/apps/vadmin/auth/utils/__init__.py create mode 100644 kinit-api/apps/vadmin/auth/utils/auth_util.py create mode 100644 kinit-api/apps/vadmin/auth/utils/current.py create mode 100644 kinit-api/apps/vadmin/auth/utils/login.py create mode 100644 kinit-api/apps/vadmin/auth/views.py create mode 100644 kinit-api/apps/vadmin/record/__init__.py create mode 100644 kinit-api/apps/vadmin/record/crud.py create mode 100644 kinit-api/apps/vadmin/record/models/__init__.py create mode 100644 kinit-api/apps/vadmin/record/models/login.py create mode 100644 kinit-api/apps/vadmin/record/models/operation.py create mode 100644 kinit-api/apps/vadmin/record/models/sms.py create mode 100644 kinit-api/apps/vadmin/record/schemas/__init__.py create mode 100644 kinit-api/apps/vadmin/record/schemas/login.py create mode 100644 kinit-api/apps/vadmin/record/schemas/sms.py create mode 100644 kinit-api/apps/vadmin/record/views.py create mode 100644 kinit-api/apps/vadmin/system/__init__.py create mode 100644 kinit-api/apps/vadmin/system/crud.py create mode 100644 kinit-api/apps/vadmin/system/models/__init__.py create mode 100644 kinit-api/apps/vadmin/system/models/dict.py create mode 100644 kinit-api/apps/vadmin/system/schemas/__init__.py create mode 100644 kinit-api/apps/vadmin/system/schemas/dict.py create mode 100644 kinit-api/apps/vadmin/system/views.py create mode 100644 kinit-api/core/__init__.py create mode 100644 kinit-api/core/crud.py create mode 100644 kinit-api/core/database.py create mode 100644 kinit-api/core/dependencies.py create mode 100644 kinit-api/core/exception.py create mode 100644 kinit-api/core/logger.py create mode 100644 kinit-api/core/middleware.py create mode 100644 kinit-api/core/validator.py create mode 100644 kinit-api/db/__init__.py create mode 100644 kinit-api/db/db_base.py create mode 100644 kinit-api/logs/.gitkeep create mode 100644 kinit-api/main.py create mode 100644 kinit-api/requirements.txt create mode 100644 kinit-api/static/.gitkeep create mode 100644 kinit-api/temp/.gitkeep create mode 100644 kinit-api/utils/__init__.py create mode 100644 kinit-api/utils/crawle.py create mode 100644 kinit-api/utils/response.py create mode 100644 kinit-api/utils/save_file.py create mode 100644 kinit-api/utils/status.py diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..71c0ecd --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +*.css linguist-language=Python +*.less linguist-language=Python +*.js linguist-language=Python +*.html linguist-language=Python diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4bf1f92 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# Build and Release Folders +bin-debug/ +bin-release/ +[Oo]bj/ +[Bb]in/ + +# Other files and folders +.settings/ + +# Executables +*.swf +*.air +*.ipa +*.apk + +# Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties` +# should NOT be excluded as they contain compiler settings and other important +# information for Eclipse / Flash Builder. +docker_env/mysql/data/ +docker_env/redis/data/ +*/.idea +dvadmin-doc/docs/.vuepress/dist \ No newline at end of file diff --git a/README.en.md b/README.en.md deleted file mode 100644 index 64dc395..0000000 --- a/README.en.md +++ /dev/null @@ -1,37 +0,0 @@ -# kinit - -#### Description -基于fastapi与vue3+typescript-vite3-element-plus的基础项目 -前端基于vue-element-plus-admin框架开发 - -#### Software Architecture -Software architecture description - -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README.md b/README.md index 07bb71e..e46fca7 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,86 @@ -# kinit - -#### 介绍 +# kinit + +一天出租屋的下午,脑子里浮现出了多个画面,但是总是停留在了想,未行动,在娱乐。 + +这样的日子很不快乐,总想做点什么,但是总觉得做什么都很困难,不管了,我先做了再说。 + +因为热爱,所以拥抱未来! + + + +## 介绍 基于fastapi与vue3+typescript-vite3-element-plus的基础项目 -前端基于vue-element-plus-admin框架开发 - -#### 软件架构 -软件架构说明 - - -#### 安装教程 - -1. xxxx -2. xxxx -3. xxxx - -#### 使用说明 - -1. xxxx -2. xxxx -3. xxxx - -#### 参与贡献 - -1. Fork 本仓库 -2. 新建 Feat_xxx 分支 -3. 提交代码 -4. 新建 Pull Request - - -#### 特技 - -1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md -2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) -3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 -4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 -5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) -6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) + +前端基于vue-element-plus-admin框架开发 + + + +这个项目主要包括项目的基础功能,用户权限管理,登录功能,简单的几个页面。 + +之后的项目将由在该项目的基础上开发。 + + + +开源项目参考: + +vue-element-plus-admin:https://gitee.com/kailong110120130/vue-element-plus-admin + +项目地址:https://gitee.com/ktianc/kinit + +## 软件架构 + +### 项目结构 + +| 项目名称 | 开发框架 | 标识 | 访问地址 | +| ------------ | --------------- | ----------- | -------- | +| 项目接口 | Fastapi 0.79 | kinit-api | | +| 后台管理系统 | Vue3 | kinit-admin | | +| 微信小程序 | Uni-app(Vue3) | kinit-wx | | + +### 项目分支 + +Git 仓库: + +| 分支 | 描述 | +| ------- | ---------------- | +| master | 主分支,开发分支 | +| release | 版本分支 | + +### 项目技术 + +| 分类 | 技术 | +| ---------------- | ---------------------------------------- | +| 数据库 | Mysql 8.0,Redis | +| 接口开发 | Fastapi 0.79 | +| 管理系统前端开发 | Vue3 + Vite3 + Typescript + Element Plus | +| 微信小程序开发 | Uni-app(Vue3)+ Uview 2.0 | + + +## 安装教程 + +1. xxxx +2. xxxx +3. xxxx + +## 使用说明 + +1. xxxx +2. xxxx +3. xxxx + +## 参与贡献 + +1. Fork 本仓库 +2. 新建 Feat_xxx 分支 +3. 提交代码 +4. 新建 Pull Request + + +## 特技 + +1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md +2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) +3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 +4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 +5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) +6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/kinit-admin/.env.base b/kinit-admin/.env.base new file mode 100644 index 0000000..8a8d91c --- /dev/null +++ b/kinit-admin/.env.base @@ -0,0 +1,11 @@ +# 环境 +NODE_ENV=development + +# 接口前缀 +VITE_API_BASEPATH=base + +# 打包路径 +VITE_BASE_PATH=/ + +# 标题 +VITE_APP_TITLE=ElementAdmin diff --git a/kinit-admin/.env.dev b/kinit-admin/.env.dev new file mode 100644 index 0000000..6a641a3 --- /dev/null +++ b/kinit-admin/.env.dev @@ -0,0 +1,23 @@ +# 环境 +NODE_ENV=production + +# 接口前缀 +VITE_API_BASEPATH=dev + +# 打包路径 +VITE_BASE_PATH=/dist-dev/ + +# 是否删除debugger +VITE_DROP_DEBUGGER=false + +# 是否删除console.log +VITE_DROP_CONSOLE=false + +# 是否sourcemap +VITE_SOURCEMAP=true + +# 输出路径 +VITE_OUT_DIR=dist-dev + +# 标题 +VITE_APP_TITLE=ElementAdmin diff --git a/kinit-admin/.env.gitee b/kinit-admin/.env.gitee new file mode 100644 index 0000000..c55b595 --- /dev/null +++ b/kinit-admin/.env.gitee @@ -0,0 +1,23 @@ +# 环境 +NODE_ENV=production + +# 接口前缀 +VITE_API_BASEPATH=pro + +# 打包路径 +VITE_BASE_PATH=/vue-element-plus-admin/ + +# 是否删除debugger +VITE_DROP_DEBUGGER=true + +# 是否删除console.log +VITE_DROP_CONSOLE=true + +# 是否sourcemap +VITE_SOURCEMAP=false + +# 输出路径 +VITE_OUT_DIR=dist-pro + +# 标题 +VITE_APP_TITLE=ElementAdmin diff --git a/kinit-admin/.env.pro b/kinit-admin/.env.pro new file mode 100644 index 0000000..99a9480 --- /dev/null +++ b/kinit-admin/.env.pro @@ -0,0 +1,23 @@ +# 环境 +NODE_ENV=production + +# 接口前缀 +VITE_API_BASEPATH=pro + +# 打包路径 +VITE_BASE_PATH=/ + +# 是否删除debugger +VITE_DROP_DEBUGGER=true + +# 是否删除console.log +VITE_DROP_CONSOLE=true + +# 是否sourcemap +VITE_SOURCEMAP=false + +# 输出路径 +VITE_OUT_DIR=dist-pro + +# 标题 +VITE_APP_TITLE=ElementAdmin diff --git a/kinit-admin/.env.test b/kinit-admin/.env.test new file mode 100644 index 0000000..3f6ebe1 --- /dev/null +++ b/kinit-admin/.env.test @@ -0,0 +1,23 @@ +# 环境 +NODE_ENV=production + +# 接口前缀 +VITE_API_BASEPATH=test + +# 打包路径 +VITE_BASE_PATH=/dist-test/ + +# 是否删除debugger +VITE_DROP_DEBUGGER=false + +# 是否删除console.log +VITE_DROP_CONSOLE=false + +# 是否sourcemap +VITE_SOURCEMAP=true + +# 输出路径 +VITE_OUT_DIR=dist-test + +# 标题 +VITE_APP_TITLE=ElementAdmin diff --git a/kinit-admin/.eslintignore b/kinit-admin/.eslintignore new file mode 100644 index 0000000..1e85c0f --- /dev/null +++ b/kinit-admin/.eslintignore @@ -0,0 +1,8 @@ +/build/ +/config/ +/dist/ +/*.js +/test/unit/coverage/ +/node_modules/* +/dist* +/src/main.ts diff --git a/kinit-admin/.eslintrc.js b/kinit-admin/.eslintrc.js new file mode 100644 index 0000000..2aec88b --- /dev/null +++ b/kinit-admin/.eslintrc.js @@ -0,0 +1,69 @@ +// @ts-check +const { defineConfig } = require('eslint-define-config') +module.exports = defineConfig({ + root: true, + env: { + browser: true, + node: true, + es6: true + }, + parser: 'vue-eslint-parser', + parserOptions: { + parser: '@typescript-eslint/parser', + ecmaVersion: 2020, + sourceType: 'module', + jsxPragma: 'React', + ecmaFeatures: { + jsx: true + } + }, + extends: [ + 'plugin:vue/vue3-recommended', + 'plugin:@typescript-eslint/recommended', + 'prettier', + 'plugin:prettier/recommended' + ], + rules: { + 'vue/script-setup-uses-vars': 'error', + 'vue/no-reserved-component-names': 'off', + '@typescript-eslint/ban-ts-ignore': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-empty-function': 'off', + 'vue/custom-event-name-casing': 'off', + 'no-use-before-define': 'off', + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-unused-vars': 'off', + 'no-unused-vars': 'off', + 'space-before-function-paren': 'off', + + 'vue/attributes-order': 'off', + 'vue/one-component-per-file': 'off', + 'vue/html-closing-bracket-newline': 'off', + 'vue/max-attributes-per-line': 'off', + 'vue/multiline-html-element-content-newline': 'off', + 'vue/singleline-html-element-content-newline': 'off', + 'vue/attribute-hyphenation': 'off', + 'vue/require-default-prop': 'off', + 'vue/require-explicit-emits': 'off', + 'vue/html-self-closing': [ + 'error', + { + html: { + void: 'always', + normal: 'never', + component: 'always' + }, + svg: 'always', + math: 'always' + } + ], + 'vue/multi-word-component-names': 'off', + 'vue/no-v-html': 'off' + } +}) diff --git a/kinit-admin/.github/workflows/auto-merge.yml b/kinit-admin/.github/workflows/auto-merge.yml new file mode 100644 index 0000000..33b6e00 --- /dev/null +++ b/kinit-admin/.github/workflows/auto-merge.yml @@ -0,0 +1,130 @@ +name: Automerge + +on: + pull_request: + types: + - labeled + - unlabeled + - synchronize + - opened + - edited + - ready_for_review + - reopened + - unlocked + pull_request_review: + types: + - submitted + status: {} + +jobs: + # 合并发布版本的 pr 到 master + auto-merge: + runs-on: ubuntu-latest + steps: + - name: Automerge + uses: 'pascalgn/automerge-action@v0.14.3' + env: + GITHUB_TOKEN: '${{ secrets.TOKEN }}' + MERGE_LABELS: '' + MERGE_FILTER_AUTHOR: 'kailong321200875' + + push-to-gh-pages: + needs: [auto-merge] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup Pnpm + uses: pnpm/action-setup@v2 + with: + version: latest + + - name: use Node.js 16 + uses: actions/setup-node@v2.1.2 + with: + node-version: '16.x' + + - name: Set SSH Environment + env: + DOCS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEPLOY_KEY }} + run: | + mkdir -p ~/.ssh/ + echo "$ACTIONS_DEPLOY_KEY" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan github.com > ~/.ssh/known_hosts + chmod 700 ~/.ssh && chmod 600 ~/.ssh/* + git config --local user.email "321200875@qq.com" + git config --local user.name "kailong321200875" + + # 发布到 github + - name: Build Github + run: | + pnpm install --no-frozen-lockfile + pnpm run build:pro + + - name: Deploy Github + uses: peaceiris/actions-gh-pages@v3 + with: + deploy_key: ${{secrets.ACTIONS_DEPLOY_KEY}} + publish_branch: gh-pages + publish_dir: ./dist-pro + force_orphan: true + cname: element-plus-admin.cn + + push-to-gh-pages-gitee: + needs: [auto-merge] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup Pnpm + uses: pnpm/action-setup@v2 + with: + version: latest + + - name: use Node.js 16 + uses: actions/setup-node@v2.1.2 + with: + node-version: '16.x' + + - name: Set SSH Environment + env: + DOCS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEPLOY_KEY }} + run: | + mkdir -p ~/.ssh/ + echo "$ACTIONS_DEPLOY_KEY" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan github.com > ~/.ssh/known_hosts + chmod 700 ~/.ssh && chmod 600 ~/.ssh/* + git config --local user.email "321200875@qq.com" + git config --local user.name "kailong321200875" + + - name: Build Gitee + run: | + pnpm install --no-frozen-lockfile + pnpm run build:gitee + + # 发布到 gitee + - name: Deploy Gitee + uses: peaceiris/actions-gh-pages@v3 + with: + deploy_key: ${{secrets.ACTIONS_DEPLOY_KEY}} + publish_branch: gh-pages-gitee + publish_dir: ./dist-pro + force_orphan: true + + - name: Sync Github Repos To Gitee # 名字随便起 + uses: Yikun/hub-mirror-action@v1.1 # 使用Yikun/hub-mirror-action + with: + src: github/kailong321200875 # 源端账户名(github) + dst: gitee/kailong110120130 # 目的端账户名(gitee) + dst_key: ${{ secrets.ACTIONS_DEPLOY_KEY }} # SSH密钥对中的私钥 + dst_token: ${{ secrets.GITEE_TOKEN }} # Gitee账户的私人令牌 + account_type: user # 账户类型 + clone_style: 'https' # 使用https方式进行clone,也可以使用ssh + debug: true # 启用后会显示所有执行命令 + force_update: true # 启用后,强制同步,即强制覆盖目的端仓库 + static_list: 'vue-element-plus-admin' # 静态同步列表,在此填写需要同步的仓库名称,可填写多个 + timeout: '600s' # git超时设置,超时后会自动重试git操作 diff --git a/kinit-admin/.github/workflows/reademe-contributors.yml b/kinit-admin/.github/workflows/reademe-contributors.yml new file mode 100644 index 0000000..8cdb00f --- /dev/null +++ b/kinit-admin/.github/workflows/reademe-contributors.yml @@ -0,0 +1,25 @@ +on: + push: + branches: + - master + +jobs: + contrib-readme-en-job: + runs-on: ubuntu-latest + name: A job to automate contrib in readme + steps: + - name: Contribute List + uses: akhilmhdh/contributors-readme-action@v2.3.4 + env: + GITHUB_TOKEN: ${{ secrets.CONTRIBUTORS_TOKEN }} + + contrib-readme-job: + runs-on: ubuntu-latest + name: A job to automate contrib in readme.zh-CN + steps: + - name: Contribute List + uses: akhilmhdh/contributors-readme-action@v2.3.4 + with: + readme_path: README.zh-CN.md + env: + GITHUB_TOKEN: ${{ secrets.CONTRIBUTORS_TOKEN }} diff --git a/kinit-admin/.github/workflows/release.yml b/kinit-admin/.github/workflows/release.yml new file mode 100644 index 0000000..609f607 --- /dev/null +++ b/kinit-admin/.github/workflows/release.yml @@ -0,0 +1,18 @@ +on: + push: + branches: + - master + +name: Release + +jobs: + release-please: + runs-on: ubuntu-latest + steps: + - uses: GoogleCloudPlatform/release-please-action@v3 + id: release + with: + token: ${{ secrets.TOKEN }} + release-type: node + package-name: standard-version + changelog-types: '[{"type": "types", "section":"Types", "hidden": false},{"type": "revert", "section":"Reverts", "hidden": false},{"type": "feat", "section": "Features", "hidden": false},{"type": "fix", "section": "Bug Fixes", "hidden": false},{"type": "improvement", "section": "Feature Improvements", "hidden": false},{"type": "docs", "section":"Docs", "hidden": false},{"type": "style", "section":"Styling", "hidden": false},{"type": "refactor", "section":"Code Refactoring", "hidden": false},{"type": "perf", "section":"Performance Improvements", "hidden": false},{"type": "test", "section":"Tests", "hidden": false},{"type": "build", "section":"Build System", "hidden": false},{"type": "ci", "section":"CI", "hidden":false}]' diff --git a/kinit-admin/.gitignore b/kinit-admin/.gitignore new file mode 100644 index 0000000..0b05e6a --- /dev/null +++ b/kinit-admin/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local +/dist* +*-lock.* +pnpm-debug diff --git a/kinit-admin/.husky/commit-msg b/kinit-admin/.husky/commit-msg new file mode 100644 index 0000000..10cb551 --- /dev/null +++ b/kinit-admin/.husky/commit-msg @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +pnpm commitlint --edit "$1" diff --git a/kinit-admin/.husky/lintstagedrc.js b/kinit-admin/.husky/lintstagedrc.js new file mode 100644 index 0000000..02afbb2 --- /dev/null +++ b/kinit-admin/.husky/lintstagedrc.js @@ -0,0 +1,9 @@ +module.exports = { + '*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write'], + '{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': ['prettier --write--parser json'], + 'package.json': ['prettier --write'], + '*.vue': ['prettier --write', 'stylelint --fix'], + '*.{scss,less,styl,css,html}': ['stylelint --fix', 'prettier --write'], + '*.md': ['prettier --write'], + '*.hbs': ['prettier --write'] +} diff --git a/kinit-admin/.husky/pre-commit b/kinit-admin/.husky/pre-commit new file mode 100644 index 0000000..a6a2318 --- /dev/null +++ b/kinit-admin/.husky/pre-commit @@ -0,0 +1,8 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +[ -n "$CI" ] && exit 0 + +# Format and submit code according to lintstagedrc.js configuration +npm run ts:check +npm run lint:lint-staged diff --git a/kinit-admin/.prettierignore b/kinit-admin/.prettierignore new file mode 100644 index 0000000..15cf071 --- /dev/null +++ b/kinit-admin/.prettierignore @@ -0,0 +1,10 @@ +/node_modules/** +/dist/ +/dist* +/public/* +/docs/* +/vite.config.ts +/src/types/env.d.ts +/docs/**/* +/plop/**/* +CHANGELOG diff --git a/kinit-admin/.stylelintignore b/kinit-admin/.stylelintignore new file mode 100644 index 0000000..aa605b4 --- /dev/null +++ b/kinit-admin/.stylelintignore @@ -0,0 +1,6 @@ +/dist/* +/public/* +public/* +/dist* +/src/types/env.d.ts +/docs/**/* diff --git a/kinit-admin/.vscode/extensions.json b/kinit-admin/.vscode/extensions.json new file mode 100644 index 0000000..62a1b22 --- /dev/null +++ b/kinit-admin/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["vue.volar", "lokalise.i18n-ally"] +} diff --git a/kinit-admin/.vscode/settings.json b/kinit-admin/.vscode/settings.json new file mode 100644 index 0000000..8bafd70 --- /dev/null +++ b/kinit-admin/.vscode/settings.json @@ -0,0 +1,19 @@ +{ + "typescript.tsdk": "node_modules/typescript/lib", + "prettier.enable": false, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + }, + "[vue]": { + "editor.defaultFormatter": "rvest.vs-code-prettier-eslint" + }, + "i18n-ally.localesPaths": ["src/locales"], + "i18n-ally.keystyle": "nested", + "i18n-ally.sortKeys": true, + "i18n-ally.namespace": false, + "i18n-ally.enabledParsers": ["ts"], + "i18n-ally.sourceLanguage": "en", + "i18n-ally.displayLanguage": "zh-CN", + "i18n-ally.enabledFrameworks": ["vue", "react"], + "god.tsconfig": "./tsconfig.json" +} diff --git a/kinit-admin/CHANGELOG.md b/kinit-admin/CHANGELOG.md new file mode 100644 index 0000000..e41e0c3 --- /dev/null +++ b/kinit-admin/CHANGELOG.md @@ -0,0 +1,643 @@ +# Changelog + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + +## [1.6.3](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.6.2...v1.6.3) (2022-08-20) + + +### Bug Fixes + +* 修复重定向错误 ([89d03fd](https://github.com/kailong321200875/vue-element-plus-admin/commit/89d03fd067e7aca565ceb84ea9276f340bbfcb60)) + + +### Styling + +* 调整样式 ([d29e151](https://github.com/kailong321200875/vue-element-plus-admin/commit/d29e151f8a660031a685f6ef9f789532b1b7b58b)) + +## [1.6.2](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.6.1...v1.6.2) (2022-08-13) + + +### Styling + +* Misspelling ([c43e833](https://github.com/kailong321200875/vue-element-plus-admin/commit/c43e833582e4f14ac78b0683f1eb3bdeb9fb4821)) +* perfect tableDemo ([c589edd](https://github.com/kailong321200875/vue-element-plus-admin/commit/c589edd960b23ad0c8b56d2c7880b61014114d45)) + + +### Code Refactoring + +* refactor axios ([0980640](https://github.com/kailong321200875/vue-element-plus-admin/commit/0980640f65fc80e3e58ba49e98db10b7b1b80077)) + +## [1.6.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.6.0...v1.6.1) (2022-07-30) + + +### Bug Fixes + +* fix menu active bug ([ff59fc7](https://github.com/kailong321200875/vue-element-plus-admin/commit/ff59fc7e133202945360a7e210f9cdf3a4a89dd7)) +* Pie chart data not updated ([55d4ce7](https://github.com/kailong321200875/vue-element-plus-admin/commit/55d4ce7e35ff9a0c5590bc3589160cfd304d3ae5)) + + +### Performance Improvements + +* add static router ([55522b0](https://github.com/kailong321200875/vue-element-plus-admin/commit/55522b0661a8df3ad3c8afafcc9f8fcb162c5a00)) + + +### Styling + +* tagviews styles update ([bff7d93](https://github.com/kailong321200875/vue-element-plus-admin/commit/bff7d9370db7a9c171828721bb99643dac2f235d)) + +## [1.6.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.5.4...v1.6.0) (2022-07-18) + + +### Features + +* 添加按钮权限 ([7bef662](https://github.com/kailong321200875/vue-element-plus-admin/commit/7bef662db1e91aa8164e9f7a92de3fe4480a3c3b)) + + +### Performance Improvements + +* 移除md5依赖 ([a123097](https://github.com/kailong321200875/vue-element-plus-admin/commit/a123097f1f38eac45e945c7d3fdccafc16ea9b69)) + + +### Styling + +* 压缩图片尺寸 ([ae3c565](https://github.com/kailong321200875/vue-element-plus-admin/commit/ae3c5657b604ffbdae5ce3ce3603626ad4acc5e5)) + + +### Docs + +* vite2 to vite3 ([b3918b9](https://github.com/kailong321200875/vue-element-plus-admin/commit/b3918b9c3c5de4b48811ec95967851cfb3c231e1)) +* vite2 to vite3 ([aaf07de](https://github.com/kailong321200875/vue-element-plus-admin/commit/aaf07de77aa600332880a894faa35757f787c012)) + +## [1.6.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.5.4...v1.6.0) (2022-07-18) + + +### Features + +* 添加按钮权限 ([7bef662](https://github.com/kailong321200875/vue-element-plus-admin/commit/7bef662db1e91aa8164e9f7a92de3fe4480a3c3b)) + + +### Performance Improvements + +* 移除md5依赖 ([a123097](https://github.com/kailong321200875/vue-element-plus-admin/commit/a123097f1f38eac45e945c7d3fdccafc16ea9b69)) + + +### Styling + +* 压缩图片尺寸 ([ae3c565](https://github.com/kailong321200875/vue-element-plus-admin/commit/ae3c5657b604ffbdae5ce3ce3603626ad4acc5e5)) + + +### Docs + +* vite2 to vite3 ([b3918b9](https://github.com/kailong321200875/vue-element-plus-admin/commit/b3918b9c3c5de4b48811ec95967851cfb3c231e1)) +* vite2 to vite3 ([aaf07de](https://github.com/kailong321200875/vue-element-plus-admin/commit/aaf07de77aa600332880a894faa35757f787c012)) + +## [1.5.4](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.5.3...v1.5.4) (2022-07-16) + + +### Bug Fixes + +* fix build:test error ([14530cf](https://github.com/kailong321200875/vue-element-plus-admin/commit/14530cf790bfbbe37c72fa831f0376bbb4209e9d)) + +## [1.5.3](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.5.2...v1.5.3) (2022-07-01) + + +### Bug Fixes + +* fix useCrudSchemas not work ([0a855b9](https://github.com/kailong321200875/vue-element-plus-admin/commit/0a855b93e282dfe7863b3fce31dde5d7e0d3e2b6)) + +## [1.5.2](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.5.1...v1.5.2) (2022-07-01) + + +### Performance Improvements + +* add useCrudSchemas demo ([ca3ce54](https://github.com/kailong321200875/vue-element-plus-admin/commit/ca3ce54630b723d87415b14c642440d6734876ff)) + +## [1.5.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.5.0...v1.5.1) (2022-07-01) + + +### Bug Fixes + +* change showMainRoute to canTo ([5e292f8](https://github.com/kailong321200875/vue-element-plus-admin/commit/5e292f8a2b2ded7297a2a76893e113ac81517d23)) + + +### Performance Improvements + +* dialog combine with form ([34aefb6](https://github.com/kailong321200875/vue-element-plus-admin/commit/34aefb64ab9237521a1225925264818eebff9ad3)) +* dynamic options demo ([1acb4d7](https://github.com/kailong321200875/vue-element-plus-admin/commit/1acb4d7e8f449ba342699f1b4387ac2404a4c1fb)) +* dynamic options demo ([9a3b617](https://github.com/kailong321200875/vue-element-plus-admin/commit/9a3b6177aa0fbc99c86c5073a1c6c696e1eaf890)) +* useCrudSchemas cutom label ([7864d83](https://github.com/kailong321200875/vue-element-plus-admin/commit/7864d830e2134d814609e722b7bad1754ea9460e)) + +## [1.5.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.4.5...v1.5.0) (2022-06-25) + + +### Features + +* refactoring API ([37b7583](https://github.com/kailong321200875/vue-element-plus-admin/commit/37b75839a591648b145065432efb1dc8c7a3b917)) + + +### Bug Fixes + +* 修复axios已知问题 ([537af57](https://github.com/kailong321200875/vue-element-plus-admin/commit/537af57a0aaa24c88ebe75acf52dc0403a58b04b)) + + +### Performance Improvements + +* perf axios config ([39edd84](https://github.com/kailong321200875/vue-element-plus-admin/commit/39edd84023109a84683c21ea33e41bd024756520)) + +## [1.4.5](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.4.4...v1.4.5) (2022-06-09) + + +### Bug Fixes + +* fix tagsview not work ([d88e051](https://github.com/kailong321200875/vue-element-plus-admin/commit/d88e0514349e877f1c5280a48f9b1bd2bfd622bf)) +* fix tagsview not work ([1bf2d4c](https://github.com/kailong321200875/vue-element-plus-admin/commit/1bf2d4c77287fdca7ed1cb8c9998a53f1375dc6f)) + + +### Types + +* fix types error ([586486a](https://github.com/kailong321200875/vue-element-plus-admin/commit/586486a68d4bf2a024e50a79945b4007324f642d)) + +## [1.4.4](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.4.3...v1.4.4) (2022-06-06) + + +### Types + +* fix type error ([d66f12e](https://github.com/kailong321200875/vue-element-plus-admin/commit/d66f12e0e77f6acf485bae06509d9ea4abcd1eaa)) + +### [1.4.3](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.4.2...v1.4.3) (2022-06-01) + + +### Bug Fixes + +* multiple requests when pageSize change and currentPage isn't 1 ([f71a250](https://github.com/kailong321200875/vue-element-plus-admin/commit/f71a2503bc521c01e7102feecf4ec39a5224a6bb)) + +### [1.4.2](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.4.1...v1.4.2) (2022-05-15) + + +### Styling + +* fix dark mode bug ([2f9fd5d](https://github.com/kailong321200875/vue-element-plus-admin/commit/2f9fd5d21550d771ec12ae3540b975e2eebcd25b)) + +### [1.4.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.4.0...v1.4.1) (2022-05-12) + + +### Bug Fixes + +* the warning of VSCode extensions ([a368c21](https://github.com/kailong321200875/vue-element-plus-admin/commit/a368c21fb9c41f98f31f51586a2023076a8a9132)) + +## [1.4.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.3.2...v1.4.0) (2022-05-10) + + +### Features + +* add dark mode ([0758a6a](https://github.com/kailong321200875/vue-element-plus-admin/commit/0758a6a9d83170e53d45d39c3313e52ff5885746)) + +### [1.3.2](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.3.1...v1.3.2) (2022-05-07) + + +### Bug Fixes + +* fix the problem that the page is stuck in top mode ([8d01f48](https://github.com/kailong321200875/vue-element-plus-admin/commit/8d01f48d5098195b10c03b3cb3a0f485ebc9e018)) + +### [1.3.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.3.0...v1.3.1) (2022-05-06) + + +### Bug Fixes + +* spelling 'useRenderChcekbox' ([ee92f03](https://github.com/kailong321200875/vue-element-plus-admin/commit/ee92f039bea4307ccfb819728d3e2ed04fa00e03)) + +## [1.3.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.13...v1.3.0) (2022-04-26) + + +### Features + +* add useCrudSchemas hook ([00d947e](https://github.com/kailong321200875/vue-element-plus-admin/commit/00d947e2f81105194b0622d33768f999e37ad28a)) + + +### Bug Fixes + +* fix Table slot warning ([0eac05d](https://github.com/kailong321200875/vue-element-plus-admin/commit/0eac05d4f973ff7b15e00973f6e96595a3cd6d43)) + + +### Code Refactoring + +* refactor useAxios ([185f1e6](https://github.com/kailong321200875/vue-element-plus-admin/commit/185f1e6e210ecaac28ebfdee4198b7ca2eaa0933)) + + +### Build System + +* add url ([ab0f59a](https://github.com/kailong321200875/vue-element-plus-admin/commit/ab0f59ac91a077cf060923fa76e6d57e05d0b21b)) +* update plugins ([c475a61](https://github.com/kailong321200875/vue-element-plus-admin/commit/c475a610c19094034306f2dc665e240c7c117f87)) +* update plugins ([dfedbc7](https://github.com/kailong321200875/vue-element-plus-admin/commit/dfedbc74fdb2c819a96b6263849bdaab59b9e337)) + +### [1.2.13](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.12...v1.2.13) (2022-04-18) + + +### Performance Improvements + +* Editor component support v-model ([d77f8e3](https://github.com/kailong321200875/vue-element-plus-admin/commit/d77f8e334d77ee43c9ee0f411733f7397b278bc0)) + +### [1.2.12](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.11...v1.2.12) (2022-04-17) + + +### Bug Fixes + +* fixed spelling 'ElememtPlusSzie' ([5dbbc60](https://github.com/kailong321200875/vue-element-plus-admin/commit/5dbbc608640d93fe68fec6f58fdb30a43e02aada)) + +### [1.2.11](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.10...v1.2.11) (2022-04-14) + + +### Bug Fixes + +* fix the error reported by the Editor component ([7dc6d8a](https://github.com/kailong321200875/vue-element-plus-admin/commit/7dc6d8a9d7289bfaf27f972e9ca1773c0a1ddd7d)) +* fix the error reported by the Editor component ([90ef985](https://github.com/kailong321200875/vue-element-plus-admin/commit/90ef9856a0885fa812339cb7047ecc98b86c7b73)) + + +### Performance Improvements + +* add tagsViewIcon setting ([d395f03](https://github.com/kailong321200875/vue-element-plus-admin/commit/d395f03a57a9265f1d39b3220fc7c9b983efee30)) +* add uniqueopened setting ([b060319](https://github.com/kailong321200875/vue-element-plus-admin/commit/b0603199a5ae0ee923483dad449f49220d36f444)) + + +### Build System + +* update plugins ([2ee4954](https://github.com/kailong321200875/vue-element-plus-admin/commit/2ee49549e7b601af26ef5204f7648d271f3348f2)) + + +### Styling + +* add layout background color ([9b614fe](https://github.com/kailong321200875/vue-element-plus-admin/commit/9b614fe89288538197c50f164586aeed7836b7a8)) + +### [1.2.10](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.9...v1.2.10) (2022-04-12) + + +### Bug Fixes + +* fix bug ([327522f](https://github.com/kailong321200875/vue-element-plus-admin/commit/327522f2b73ae0e11f8ebbc39394b06029ce0b65)) + + +### Styling + +* modify the commitlint package manager ([ba7e722](https://github.com/kailong321200875/vue-element-plus-admin/commit/ba7e7224ab58612548519415f5429c32827a61de)) + +### [1.2.9](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.8...v1.2.9) (2022-04-12) + + +### Docs + +* update changlog ([e37273d](https://github.com/kailong321200875/vue-element-plus-admin/commit/e37273d95d29a3bb752604658d550264aacdc979)) + +### [1.2.8](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.7...v1.2.8) (2022-04-11) + +### Build System + +- update plugins ([00a573a](https://github.com/kailong321200875/vue-element-plus-admin/commit/00a573af3f455395b4ee2ab99a03f3103d466e9c)) + +### Docs + +- update changlog ([62fc183](https://github.com/kailong321200875/vue-element-plus-admin/commit/62fc1839fdff3a4d06a7db4cf3f8ce2cb9aee681)) + +### [1.2.7](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.6...v1.2.7) (2022-04-10) + +### Build System + +- update plugins ([f13a91d](https://github.com/kailong321200875/vue-element-plus-admin/commit/f13a91dd460b1dcdbd17aef723ab3ca2b01c34f0)) + +### Styling + +- .bhs code formatting ([57b2707](https://github.com/kailong321200875/vue-element-plus-admin/commit/57b27071e9a33423c46542a5d0e5d5c2e9a3b718)) + +### [1.2.6](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.5...v1.2.6) (2022-04-08) + +### Build System + +- update plugins ([d645892](https://github.com/kailong321200875/vue-element-plus-admin/commit/d645892cde2f7f43215a2ba1776ee94a322437bf)) + +### [1.2.5](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.4...v1.2.5) (2022-04-08) + +### Performance Improvements + +- add plop ([fa54a17](https://github.com/kailong321200875/vue-element-plus-admin/commit/fa54a1704ffd93f7b42dbeb1229bc4868d2d3a6a)) + +### Build System + +- update plugins ([18c6bd8](https://github.com/kailong321200875/vue-element-plus-admin/commit/18c6bd868622d954b51ea34e37516361ad4eb540)) + +### Styling + +- fix padding and background color ([f8c9d54](https://github.com/kailong321200875/vue-element-plus-admin/commit/f8c9d54687edafd92f5b61bf5288bb1188c73f01)) + +### [1.2.4](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.3...v1.2.4) (2022-04-06) + +### Bug Fixes + +- add Sticky props comment ([46133b3](https://github.com/kailong321200875/vue-element-plus-admin/commit/46133b3ff39d48d11cbcaa1f20a271118f48eb29)) +- fix bug ([179ca06](https://github.com/kailong321200875/vue-element-plus-admin/commit/179ca064ba8adbb3b063d9798ec1930ccc68e459)) +- fix remove unnecessary variables ([ca01cbf](https://github.com/kailong321200875/vue-element-plus-admin/commit/ca01cbfd98b63a0d76190fe8d43097fdc9df74e6)) +- fix style ([17c8fea](https://github.com/kailong321200875/vue-element-plus-admin/commit/17c8fea93811d9d9b708808484f5c907d761fcf1)) +- remove ContentDetailWrap style ([4ceaa9d](https://github.com/kailong321200875/vue-element-plus-admin/commit/4ceaa9d7816369d0dcaf3e18e4cdbbd6165cef88)) + +### [1.2.3](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.2...v1.2.3) (2022-03-31) + +### Bug Fixes + +- fix refresh with query ([e94020f](https://github.com/kailong321200875/vue-element-plus-admin/commit/e94020ff541a061599486c0003258f1dbf13aba8)) + +### [1.2.2](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.1...v1.2.2) (2022-03-30) + +### Bug Fixes + +- fix avatar height bug ([cd4ab76](https://github.com/kailong321200875/vue-element-plus-admin/commit/cd4ab767018941777174d7837045f5259d1cc403)) +- fix parmas to params ([2c7211c](https://github.com/kailong321200875/vue-element-plus-admin/commit/2c7211c89d7299ffc0a36bef8999b3c201dbaf4a)) + +### [1.2.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.0...v1.2.1) (2022-03-29) + +### Bug Fixes + +- fix invalid paging ([ad184ee](https://github.com/kailong321200875/vue-element-plus-admin/commit/ad184ee9c0619da36f1ca3f26e67f18f88488523)) + +### Build System + +- update plugins ([0c7276f](https://github.com/kailong321200875/vue-element-plus-admin/commit/0c7276feadaedef83e6a4ad9d457e26d408698a8)) + +## [1.2.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.14...v1.2.0) (2022-03-27) + +### Features + +- add hooks demo ([c43f39e](https://github.com/kailong321200875/vue-element-plus-admin/commit/c43f39efef296266c64cc24690717d07fa0bcb85)) +- add inputPassword demo ([8f8b126](https://github.com/kailong321200875/vue-element-plus-admin/commit/8f8b1260e75df6998ebea617f62d4ab6be81d721)) + +### Docs + +- update LICENSE ([69d3dcc](https://github.com/kailong321200875/vue-element-plus-admin/commit/69d3dcc7edf69e9b4e3042ddb11faa85ec7d39e2)) + +### Styling + +- modify the function name to make it more semantic ([046ae51](https://github.com/kailong321200875/vue-element-plus-admin/commit/046ae512f02df2d3f08134949b9376a061c1eef3)) +- update Footer component presentation ([d4a9ba3](https://github.com/kailong321200875/vue-element-plus-admin/commit/d4a9ba3aa6758b8aac18b30e1a6b9501baff826c)) +- update Icon demo ([8597122](https://github.com/kailong321200875/vue-element-plus-admin/commit/85971227cd3055ea280cf493c7c42b250c1515da)) + +### Tests + +- test push first commit ([a67bb48](https://github.com/kailong321200875/vue-element-plus-admin/commit/a67bb48f269651a2dcd01b9e33d10f20c42d76ee)) + +### Build System + +- update plugins ([9c13d92](https://github.com/kailong321200875/vue-element-plus-admin/commit/9c13d92b36a2a7c95b9edb7821367fc8f0ac6658)) +- update server port ([d2be8c1](https://github.com/kailong321200875/vue-element-plus-admin/commit/d2be8c1a307a3c5daf363bd7f1d21e574598de5c)) + +### [1.1.14](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.13...v1.1.14) (2022-03-22) + +### Bug Fixes + +- fix the bug that the form search function is invalid of the example-dialog page ([9ec30e7](https://github.com/kailong321200875/vue-element-plus-admin/commit/9ec30e719f89865497dbb1321be1df906f59f14e)) + +### [1.1.13](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.12...v1.1.13) (2022-03-17) + +### Build System + +- update plugins ([a2d0313](https://github.com/kailong321200875/vue-element-plus-admin/commit/a2d03137899f9b16fc1d4a09a23576cd74e7950e)) + +### [1.1.12](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.11...v1.1.12) (2022-03-15) + +### Build System + +- update plugins ([fee2252](https://github.com/kailong321200875/vue-element-plus-admin/commit/fee2252930b05b709d0c012e809568c4ed32bd89)) + +### [1.1.11](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.10...v1.1.11) (2022-03-15) + +### Bug Fixes + +- fix the problem of blank bar when toggle the TagsView component ([b1d9771](https://github.com/kailong321200875/vue-element-plus-admin/commit/b1d9771c750709fe45061d13299a85dbbd6ead25)) +- fix the problem that no reaction when copy setting config in http page ([61e0e33](https://github.com/kailong321200875/vue-element-plus-admin/commit/61e0e33c64d6a889fe6ed80d27a10cf8b201d21a)) + +### [1.1.10](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.9...v1.1.10) (2022-03-13) + +### Build System + +- update plugins ([0b525c8](https://github.com/kailong321200875/vue-element-plus-admin/commit/0b525c875075a28288e92243b205b337f85ab550)) + +### [1.1.9](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.8...v1.1.9) (2022-03-07) + +### Build System + +- update plugins ([1456fd4](https://github.com/kailong321200875/vue-element-plus-admin/commit/1456fd49ec9abbfe1f25aeadfe5fed54fec07394)) + +### [1.1.8](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.7...v1.1.8) (2022-03-07) + +### Docs + +- update changelog ([bf09441](https://github.com/kailong321200875/vue-element-plus-admin/commit/bf09441852e59b0d07d4949a33de75958696817f)) + +### [1.1.7](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.6...v1.1.7) (2022-03-06) + +### Styling + +- add labelMessage attribute to Form component ([8c42790](https://github.com/kailong321200875/vue-element-plus-admin/commit/8c427907843ccb2dfd882d27c1e8a894c5616487)) + +### [1.1.6](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.5...v1.1.6) (2022-03-04) + +### Bug Fixes + +- fix the problem that the tree data of Table component cannot be displayed ([bf83d3e](https://github.com/kailong321200875/vue-element-plus-admin/commit/bf83d3efbad9097f245c32cc07d1178580cec4e3)) + +### [1.1.5](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.4...v1.1.5) (2022-03-02) + +### Bug Fixes + +- fix the problem of tagsview error when loginout ([835d76a](https://github.com/kailong321200875/vue-element-plus-admin/commit/835d76ae87b950106f957976ebc8f6f2e8842ddf)) + +### Build System + +- update plugins ([de34bb1](https://github.com/kailong321200875/vue-element-plus-admin/commit/de34bb193d6c844dbc1cec38db5f61b3f95e19f2)) + +### Styling + +- fix tabMenu z-index bug ([8b3be02](https://github.com/kailong321200875/vue-element-plus-admin/commit/8b3be02368a1bddb7dc78f18adbea7f4ebfe75d6)) +- fix tags-view style bug ([ebff817](https://github.com/kailong321200875/vue-element-plus-admin/commit/ebff81777b9c0b839256b83e321ecbdbff25fc73)) + +### [1.1.4](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.3...v1.1.4) (2022-03-01) + +### CI + +- update workflow ([0490d18](https://github.com/kailong321200875/vue-element-plus-admin/commit/0490d18145cb0d9c4b066ab01a2c10cb527e38ba)) +- update workflow ([51f7bca](https://github.com/kailong321200875/vue-element-plus-admin/commit/51f7bca6034902b251d081ee383b0d796782d434)) + +### [1.1.3](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.2...v1.1.3) (2022-03-01) + +### CI + +- update workflow ([91cc5c5](https://github.com/kailong321200875/vue-element-plus-admin/commit/91cc5c595cadc5695d8f54bdc4922d8f04439f24)) + +### [1.1.2](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.1...v1.1.2) (2022-03-01) + +### Workflows + +- update workflow ([d9708aa](https://github.com/kailong321200875/vue-element-plus-admin/commit/d9708aae5bc0cb795bb0fbf8d17df753cc88ba1d)) + +### [1.1.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.0...v1.1.1) (2022-03-01) + +### Workflows + +- update workflow ([085328a](https://github.com/kailong321200875/vue-element-plus-admin/commit/085328aba8c4f356bf7915a6bbdc1ec4f46ceeda)) + +## [1.1.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.0.3...v1.1.0) (2022-03-01) + +### Features + +- 🎸 layout 三种布局重构完成 ([429e428](https://github.com/kailong321200875/vue-element-plus-admin/commit/429e42809cef33a33662e41ad50297217d128b8c)) +- 🎸 layout 布局重构 �[bd24b92](https://github.com/kailong321200875/vue-element-plus-admin/commit/bd24b92acb279343dbaf83b74f1ed2a3f57f1003)) +- 🎸 Table 组件重构完成并给出相应示 �[35879f8](https://github.com/kailong321200875/vue-element-plus-admin/commit/35879f8ecc0ffa76122a336e2eaa93ecfb408c1d)) +- 🎸 v0.0.4 发布 ([a58dc1b](https://github.com/kailong321200875/vue-element-plus-admin/commit/a58dc1b1c2774974782ef6d116b8805975b82b1c)) +- 🎸 初始化项 �[26d4c7c](https://github.com/kailong321200875/vue-element-plus-admin/commit/26d4c7c56894cf2031b3a7cce08d53c37f4a49e3)) +- 🎸 初版完成 ([5bfe4d2](https://github.com/kailong321200875/vue-element-plus-admin/commit/5bfe4d236fd9c2841da100f34c980b4572b67b20)) +- 🎸 新增 Detail 详情组件并给出相应示 �[e77a931](https://github.com/kailong321200875/vue-element-plus-admin/commit/e77a931ef2d2967a9717e27b187d68512c01284f)) +- 🎸 新增二维码组 �[85555ee](https://github.com/kailong321200875/vue-element-plus-admin/commit/85555eef7dc7d72cb701bdd81044ba8fb8e72acc)) +- 🎸 新增全局配置 ([f8405a6](https://github.com/kailong321200875/vue-element-plus-admin/commit/f8405a63c9b1288fbe95bae235b65a08e8fae8d2)) +- 🎸 新增固定 � 级菜单配 �[4c4903e](https://github.com/kailong321200875/vue-element-plus-admin/commit/4c4903e806c8818e320108cc3e5279d728061c29)) +- 🎸 新增权限管理及相关示例文 �[32b6583](https://github.com/kailong321200875/vue-element-plus-admin/commit/32b6583099646b2ee622ac7b35388468769b91b8)) +- 🎸 显示更多组建 � 发中 ([fa9f24d](https://github.com/kailong321200875/vue-element-plus-admin/commit/fa9f24d5da8d2e40d7c3661eabacb8f0474a7bf2)) +- 🎸 权限管理 � 发中 ([38f5211](https://github.com/kailong321200875/vue-element-plus-admin/commit/38f521174ba9eba750fee4516141d7a267f1c4ce)) +- 🎸 权限管理 � 发中 ([6d7ea66](https://github.com/kailong321200875/vue-element-plus-admin/commit/6d7ea6694d8299332018a6689bcd82502a9a552c)) +- 🎸 综合实例重构 �[5142e6e](https://github.com/kailong321200875/vue-element-plus-admin/commit/5142e6e323cb20c89a97398bf41d32c93ce42cad)) +- 🎸 重构 layout ([7ede021](https://github.com/kailong321200875/vue-element-plus-admin/commit/7ede02141e258ab4c88e9b4daad966513d4dbe68)) +- 🎸 重构 layout-classic 布局 ([29d9c98](https://github.com/kailong321200875/vue-element-plus-admin/commit/29d9c988605b822195900268da6bc3f3b0b9c770)) +- 🎸 重构 sider 组件 �[51313d7](https://github.com/kailong321200875/vue-element-plus-admin/commit/51313d7116c7ab2ded7e3a65514ea9ac413edecd)) +- Add analysis api ([83327ea](https://github.com/kailong321200875/vue-element-plus-admin/commit/83327ea763ebb233bb540513276ffa288fbcb4a1)) +- Add analysis demo ([cd06934](https://github.com/kailong321200875/vue-element-plus-admin/commit/cd069340fc5157535fdc82e792c6b6dce7d7a97e)) +- Add count-to demo ([d3fbd3a](https://github.com/kailong321200875/vue-element-plus-admin/commit/d3fbd3a06c3b802fc863b4dc8013122c14bd16f2)) +- Add Descriptions component and add Descriptions demo ([7ad46f8](https://github.com/kailong321200875/vue-element-plus-admin/commit/7ad46f828d626a87699cd4d3a959a5634577d580)) +- Add Dialog component and add dailog demo ([a18ad8f](https://github.com/kailong321200875/vue-element-plus-admin/commit/a18ad8f4a89b78c73e57d8d2543494243f656d05)) +- add doucment link ([53201ae](https://github.com/kailong321200875/vue-element-plus-admin/commit/53201ae97a425714871d99e8847a3672ba0d389f)) +- Add dynamic route ([9d926b2](https://github.com/kailong321200875/vue-element-plus-admin/commit/9d926b2760b75e1d8e71a68dc7ff6c5026223a43)) +- Add Editor component and add editor demo ([3fb3e8d](https://github.com/kailong321200875/vue-element-plus-admin/commit/3fb3e8da39d816bcf4aedb65d40c7052bdb6d8bf)) +- Add Error component ([7411dbc](https://github.com/kailong321200875/vue-element-plus-admin/commit/7411dbc9fd8f122187c86a11523b49c88cc71a8c)) +- Add example-dialog demo ([262f421](https://github.com/kailong321200875/vue-element-plus-admin/commit/262f4211cf53aef30a32f4b88e88fb1b9246ffcb)) +- Add example-page demo ([1492f91](https://github.com/kailong321200875/vue-element-plus-admin/commit/1492f9119aa2960cc05956218e6d151c8b316875)) +- Add form demo ([472f574](https://github.com/kailong321200875/vue-element-plus-admin/commit/472f574f42f8f31c4e6047043ac755ba5fb35b7b)) +- Add form demo ([e6f9580](https://github.com/kailong321200875/vue-element-plus-admin/commit/e6f95803316bb5df2d1060285c1d591a79340721)) +- Add form demo ([543156f](https://github.com/kailong321200875/vue-element-plus-admin/commit/543156f328350bd12e71a41c872e547e41cda7fe)) +- Add form demo ([7795d2a](https://github.com/kailong321200875/vue-element-plus-admin/commit/7795d2a4fe3dbc9849ddc7c1d3e2d9215dc66f56)) +- Add guide demo ([0832194](https://github.com/kailong321200875/vue-element-plus-admin/commit/0832194e6131051416edff7c2eac6b0a016ffd80)) +- Add highlight demo ([eb206b0](https://github.com/kailong321200875/vue-element-plus-admin/commit/eb206b0cc31ac7da3dfd8b3d4b874061c5c91d53)) +- Add Icon demo ([e4b7a76](https://github.com/kailong321200875/vue-element-plus-admin/commit/e4b7a769126d6f0fca424007c294ff229eefcb35)) +- Add ImageViewer component and add ImageViewer demo ([af9fc0a](https://github.com/kailong321200875/vue-element-plus-admin/commit/af9fc0a4aded3ec08746ddeaeabac4c3cfa9463d)) +- Add Infotip component ([e4b7a76](https://github.com/kailong321200875/vue-element-plus-admin/commit/e4b7a769126d6f0fca424007c294ff229eefcb35)) +- Add infotip demo ([dbf3b0f](https://github.com/kailong321200875/vue-element-plus-admin/commit/dbf3b0f5a333ccef524bbac825035b0c6dc78ec9)) +- Add Qrcode component and add qrcode demo ([535a31b](https://github.com/kailong321200875/vue-element-plus-admin/commit/535a31b35eb6a76589f602fd96dcf91f46f349b0)) +- Add Search component and add search demo ([33eca8a](https://github.com/kailong321200875/vue-element-plus-admin/commit/33eca8a97d59f5cc453e1a60ee81b1519527d0f1)) +- Add Table component and add useTable hook ([17e8e7c](https://github.com/kailong321200875/vue-element-plus-admin/commit/17e8e7cda9a009818f11cfa0429ce0f9adc00be5)) +- Add useScrollTo hook ([7d7fd9e](https://github.com/kailong321200875/vue-element-plus-admin/commit/7d7fd9ed646d2b68cec0547ad8e65b0404bb95bb)) +- Add useWatermark hook and add useWatermark demo ([d3fbd3a](https://github.com/kailong321200875/vue-element-plus-admin/commit/d3fbd3a06c3b802fc863b4dc8013122c14bd16f2)) +- Add workplace api ([cb558f8](https://github.com/kailong321200875/vue-element-plus-admin/commit/cb558f8af9dfef2ba2879f021db395ee79e8c8d4)) +- **Animate:** Add animate.css ([1436543](https://github.com/kailong321200875/vue-element-plus-admin/commit/1436543a5c599f651ed7805165ea83b9ebcddef5)) +- **Breadcrumbe:** Add Breadcrumb component ([4612e55](https://github.com/kailong321200875/vue-element-plus-admin/commit/4612e5544bcd626d686972e5cb874d0aa4af08b3)) +- **component:** Add CountTo component and Echart component ([e20fa76](https://github.com/kailong321200875/vue-element-plus-admin/commit/e20fa76cad0894a69fd04c81c2108faabf392684)) +- **component:** Add Footer component ([dad7330](https://github.com/kailong321200875/vue-element-plus-admin/commit/dad733063413c79eca61c6cb5ff671b35933a85f)) +- **component:** Add Footer component ([f81e996](https://github.com/kailong321200875/vue-element-plus-admin/commit/f81e996a426538aeaa2aa37a540395dcf360a09c)) +- **Component:** Add Highlight component ([c53fa56](https://github.com/kailong321200875/vue-element-plus-admin/commit/c53fa562e540447df082e35c7f26e56f2426e430)) +- **component:** Add namespace of class ([d847ccb](https://github.com/kailong321200875/vue-element-plus-admin/commit/d847ccb098edc72fe55c1f8459bf149453a3b73d)) +- **Component:** Setting component add copy button ([e496096](https://github.com/kailong321200875/vue-element-plus-admin/commit/e496096539e6a56b0761a625c9d59210facc5432)) +- **ContextMenu:** Add ContextMenu component ([349ac9d](https://github.com/kailong321200875/vue-element-plus-admin/commit/349ac9d3989d77e5246cecf0006dd8d83c489990)) +- Detail 组件重构完成 ([7f5ef99](https://github.com/kailong321200875/vue-element-plus-admin/commit/7f5ef99ccc32b03f7be21f70c333bb8e679c7d93)) +- Highlight 组件重构 ([34221f3](https://github.com/kailong321200875/vue-element-plus-admin/commit/34221f387f5e15a08cdc21edd76ce8d8c5c20fbc)) +- **hooks:** Add useIntro hook ([0832194](https://github.com/kailong321200875/vue-element-plus-admin/commit/0832194e6131051416edff7c2eac6b0a016ffd80)) +- **hooks:** Add useTimeAgo hook ([c53fa56](https://github.com/kailong321200875/vue-element-plus-admin/commit/c53fa562e540447df082e35c7f26e56f2426e430)) +- **I18n:** Add Ii8n ([3810b8c](https://github.com/kailong321200875/vue-element-plus-admin/commit/3810b8c3b26f86c27aa7db479dfb7b0d283d970f)) +- **Layout:** Add classic layout ([839b601](https://github.com/kailong321200875/vue-element-plus-admin/commit/839b6015b8e31bf70e6f0bf0608fa729b028729b)) +- **Layout:** Add cutMenu layout ([ff4dd3a](https://github.com/kailong321200875/vue-element-plus-admin/commit/ff4dd3afbf5c0c7a439c71b0c494b81e0f2c70d4)) +- **Layout:** Add topLeft layout ([71b1c5e](https://github.com/kailong321200875/vue-element-plus-admin/commit/71b1c5e10cade8d1c018d0c5f63c98ba9357bab8)) +- **LocaleDropdown:** Add LocaleDropdown Component ([3810b8c](https://github.com/kailong321200875/vue-element-plus-admin/commit/3810b8c3b26f86c27aa7db479dfb7b0d283d970f)) +- **Logo:** Add Logo component ([958edef](https://github.com/kailong321200875/vue-element-plus-admin/commit/958edefe7bc2bf3ae77520a5d885a9d47e8a37b9)) +- **mock:** Add mock ([3fc7d4d](https://github.com/kailong321200875/vue-element-plus-admin/commit/3fc7d4d39a72056fcf419fe19a9d41d90f945bad)) +- **router:** Add dynamic routing ([b218ccc](https://github.com/kailong321200875/vue-element-plus-admin/commit/b218ccc9cce2ce1363c4a21d22b4d69c43c7b2dc)) +- Search component add expand attribute and expandField attribute ([9b4b317](https://github.com/kailong321200875/vue-element-plus-admin/commit/9b4b31781765d31dec50acc40e2eed91401502d4)) +- **store:** Add localeStore ([3810b8c](https://github.com/kailong321200875/vue-element-plus-admin/commit/3810b8c3b26f86c27aa7db479dfb7b0d283d970f)) +- **store:** Add tagsView store ([349ac9d](https://github.com/kailong321200875/vue-element-plus-admin/commit/349ac9d3989d77e5246cecf0006dd8d83c489990)) +- Table 组件重构 ([07adefb](https://github.com/kailong321200875/vue-element-plus-admin/commit/07adefb89b7555280e6217e09cf81ba7aa5b93c2)) +- **TagsView:** Add TagsView component ([349ac9d](https://github.com/kailong321200875/vue-element-plus-admin/commit/349ac9d3989d77e5246cecf0006dd8d83c489990)) +- **useForm:** Add useForm ([357fc44](https://github.com/kailong321200875/vue-element-plus-admin/commit/357fc44e519c5829567c17f611fcaadee3f9f933)) +- **useNProgress:** Add useNProgress ([c5ab359](https://github.com/kailong321200875/vue-element-plus-admin/commit/c5ab3599c8ea001ff7831b72fefc9e274163fbbb)) +- **useTitle:** Add useTitle ([c5ab359](https://github.com/kailong321200875/vue-element-plus-admin/commit/c5ab3599c8ea001ff7831b72fefc9e274163fbbb)) +- **utils:** Add color utils ([71dfba2](https://github.com/kailong321200875/vue-element-plus-admin/commit/71dfba21c5bc0276689b5aecf0d75e53efdda09f)) +- **VForm:** Add VForm component ([448ac52](https://github.com/kailong321200875/vue-element-plus-admin/commit/448ac5293e48a03840df2bb0b399a8f02aae666e)) +- **VInputPassword:** Add VInputPassword Component ([a1bf7e9](https://github.com/kailong321200875/vue-element-plus-admin/commit/a1bf7e9b552f75d3b87c64904ac9e7c99fc936a5)) +- **Workplace:** Add wrokplace demo ([c53fa56](https://github.com/kailong321200875/vue-element-plus-admin/commit/c53fa562e540447df082e35c7f26e56f2426e430)) +- 综合实例、权限管理重 �[a4bd206](https://github.com/kailong321200875/vue-element-plus-admin/commit/a4bd2068a5d40d146b5b45cb3727ced990147b68)) +- 部分组件重构完成 ([3d96229](https://github.com/kailong321200875/vue-element-plus-admin/commit/3d9622978dc234ef12dbce63e18caf3440563aa0)) + +### Bug Fixes + +- 🐛 删除 Editor 双向绑定,改 �props 传参 ([c395e27](https://github.com/kailong321200875/vue-element-plus-admin/commit/c395e27f67af9f60b151a5484ab5a3c90c4c1d1e)) +- fix Form component setProps not work bug ([48ffc52](https://github.com/kailong321200875/vue-element-plus-admin/commit/48ffc52ca8fa26d8e6a5fa4b8b3001701a1f0732)) +- fix useScrollTo not work bug ([53201ae](https://github.com/kailong321200875/vue-element-plus-admin/commit/53201ae97a425714871d99e8847a3672ba0d389f)) +- 修复 tagsView 无动画效 �[0e3eb4b](https://github.com/kailong321200875/vue-element-plus-admin/commit/0e3eb4ba8b1503e1d221dfda59a3a0001dbdcb56)) + +### Performance Improvements + +- update useForm hook ([8a958cd](https://github.com/kailong321200875/vue-element-plus-admin/commit/8a958cd71d9afbd32b243aac0814bfa3281477cd)) + +### Code Refactoring + +- 💡 综合实例查看详情重构 ([9c26edd](https://github.com/kailong321200875/vue-element-plus-admin/commit/9c26edd5d599b5fb5a832fb547e3d95b6bfa9a98)) + +### Build System + +- Add conventional-changelog-cli plugin ([384485f](https://github.com/kailong321200875/vue-element-plus-admin/commit/384485f6994c6ac33abee506508ab9d35fe658a9)) +- Add conventional-github-releaser plugin ([3cd5c71](https://github.com/kailong321200875/vue-element-plus-admin/commit/3cd5c71899dde3ac3910aef0180d8b39fad51f1b)) +- Add standard-version plugin ([110ce25](https://github.com/kailong321200875/vue-element-plus-admin/commit/110ce257841648e29b247a0338624a188694b6e9)) +- Add vite-plugin-html plugin ([d5b6e2a](https://github.com/kailong321200875/vue-element-plus-admin/commit/d5b6e2a7770eb59aa32839f69da5be37397e3538)) +- delete useless plugin ([c756761](https://github.com/kailong321200875/vue-element-plus-admin/commit/c756761dfc3200156acb228474d3539197ef413b)) +- **pinia:** Add pinia ([2040500](https://github.com/kailong321200875/vue-element-plus-admin/commit/2040500af14d277a79f01eba5eca2a440203cecf)) +- **types:** Add vue-types ([2c41826](https://github.com/kailong321200875/vue-element-plus-admin/commit/2c41826c572268b74a663a6966c548628ac7e280)) +- **unplugin-auto-import:** Delete unplugin-auto-import ([2040500](https://github.com/kailong321200875/vue-element-plus-admin/commit/2040500af14d277a79f01eba5eca2a440203cecf)) +- **unplugin-vue-components:** Delete unplugin-vue-components ([2040500](https://github.com/kailong321200875/vue-element-plus-admin/commit/2040500af14d277a79f01eba5eca2a440203cecf)) +- update plugin ([8d08bc6](https://github.com/kailong321200875/vue-element-plus-admin/commit/8d08bc6fc92258674abdd12834eaa4530ec276dd)) +- update plugins ([3c58042](https://github.com/kailong321200875/vue-element-plus-admin/commit/3c580420a20121845f02c0dd3caca5a74f06a89d)) +- **vite-plugin-style-import:** Add vite-plugin-style-import ([2040500](https://github.com/kailong321200875/vue-element-plus-admin/commit/2040500af14d277a79f01eba5eca2a440203cecf)) +- **vite-plugin-vue-setup-extend:** Delete vite-plugin-vue-setup-extend ([2040500](https://github.com/kailong321200875/vue-element-plus-admin/commit/2040500af14d277a79f01eba5eca2a440203cecf)) +- 修改 vite 配置 ([9991fb4](https://github.com/kailong321200875/vue-element-plus-admin/commit/9991fb4e5c46b9e4016beaade7232e28dc272797)) +- 设置多语 �([45e879e](https://github.com/kailong321200875/vue-element-plus-admin/commit/45e879edeef677b6aa1d2cfe4dd8dc5b76c83c59)) +- 配置代码格式 �[ffdb556](https://github.com/kailong321200875/vue-element-plus-admin/commit/ffdb556a096db247306eae8eecc1b85718314cdd)) +- 集成基础配置 ([ced99de](https://github.com/kailong321200875/vue-element-plus-admin/commit/ced99de9b113a01d9d0b190f6d2c6adc983a3102)) +- 集成基础配置 ([5dbcf23](https://github.com/kailong321200875/vue-element-plus-admin/commit/5dbcf2397ccdec80c695c113f49e8aa9bb6d012c)) + +### Styling + +- 💄 优化 layout 样式 ([37ec378](https://github.com/kailong321200875/vue-element-plus-admin/commit/37ec378f0b2bf83d73ddf0e472aada6aab248f09)) +- 💄 微调样式 ([612b486](https://github.com/kailong321200875/vue-element-plus-admin/commit/612b48673c3389779ccfdd161e2ca80b21d265b2)) +- Add elNamespace ([d847ccb](https://github.com/kailong321200875/vue-element-plus-admin/commit/d847ccb098edc72fe55c1f8459bf149453a3b73d)) +- **appStore:** code style ([641ed68](https://github.com/kailong321200875/vue-element-plus-admin/commit/641ed684fefeb52e2f91e8baab7b610fc74c8d88)) +- **Breadcrumb:** fix Breadcrumb style bug ([8755c86](https://github.com/kailong321200875/vue-element-plus-admin/commit/8755c862b837d90a25b27c01fabe64abf81fc4a2)) +- **breadcrumb:** update disabled text color ([1522e92](https://github.com/kailong321200875/vue-element-plus-admin/commit/1522e925bae37cb9df4de2252d81f717788f4537)) +- change function to arrow function ([4612e55](https://github.com/kailong321200875/vue-element-plus-admin/commit/4612e5544bcd626d686972e5cb874d0aa4af08b3)) +- delete console.log ([49a6bfe](https://github.com/kailong321200875/vue-element-plus-admin/commit/49a6bfe9d81a40e2f5f15b68d7289e1787e89b54)) +- **Icon:** delete default color ([95a2bd8](https://github.com/kailong321200875/vue-element-plus-admin/commit/95a2bd884dd9846a56cda7c4c3ee4a41ce631b7c)) +- level demo style beautification ([dbf3b0f](https://github.com/kailong321200875/vue-element-plus-admin/commit/dbf3b0f5a333ccef524bbac825035b0c6dc78ec9)) +- lint code style ([b292419](https://github.com/kailong321200875/vue-element-plus-admin/commit/b2924190b8996e8208f951e3fadbcb09baddb8df)) +- **Login:** update login styles ([eb68f1d](https://github.com/kailong321200875/vue-element-plus-admin/commit/eb68f1d919e13c07b7d200e9aec53804b2a6dc7b)) +- modify menu z-index attribute ([0d7a778](https://github.com/kailong321200875/vue-element-plus-admin/commit/0d7a7781ce0b5e39f01355d3acdb3f364cabf76d)) +- **TagView:** Vertical center tag ([41281c4](https://github.com/kailong321200875/vue-element-plus-admin/commit/41281c4d541a2744e5df5dff2764cc85465b6a4c)) + +### Types + +- add ImportMetaEnv ([38e0257](https://github.com/kailong321200875/vue-element-plus-admin/commit/38e0257487e4138a74ad1bb4ee4ba004abcfaa12)) +- Adding BfFrom Component types ([8e036f5](https://github.com/kailong321200875/vue-element-plus-admin/commit/8e036f54b56ce8521eb8ec4b7ca21aa9c24f43f2)) +- **BfForm:** Adding BfForm types ([bc9195b](https://github.com/kailong321200875/vue-element-plus-admin/commit/bc9195b21eeb79629a82a04d90e2ac5aa6592928)) +- **BfForm:** Adding BfForm types ([184b468](https://github.com/kailong321200875/vue-element-plus-admin/commit/184b468cd41dcd1cdae11477b9ee2d6e17de1481)) +- **BfForm:** Adding BfForm types ([58cb24d](https://github.com/kailong321200875/vue-element-plus-admin/commit/58cb24d9f8a50be80b5ea793387d582a77a59137)) +- delete useless types ([3fc79c0](https://github.com/kailong321200875/vue-element-plus-admin/commit/3fc79c0ae7acd0929f47e33f96c8d45a90d8f762)) +- **VForm:** Adding VForm types ([7528fe6](https://github.com/kailong321200875/vue-element-plus-admin/commit/7528fe6da60368213d28d9f1b6310d02d3d53282)) + +### Docs + +- ✏️ 修改 readme ([8edb2a3](https://github.com/kailong321200875/vue-element-plus-admin/commit/8edb2a3493dca975036859b5d2c52afaa91f5dbb)) +- ✏️ 更新 readme ([62eeb55](https://github.com/kailong321200875/vue-element-plus-admin/commit/62eeb55330dd4af2a46801c7a19f38a3ef312bbf)) +- Add README.md ([21dcf88](https://github.com/kailong321200875/vue-element-plus-admin/commit/21dcf88ba31957bbdb50c6207d010650daab70fc)) +- Error modifying readme name ([25d5c84](https://github.com/kailong321200875/vue-element-plus-admin/commit/25d5c84e92e68aa72362a14f55aacd946fa5b1b2)) +- update description ([be6ff98](https://github.com/kailong321200875/vue-element-plus-admin/commit/be6ff9899b25cc00519210950d27ee56ac5112e6)) +- update description ([c15aa87](https://github.com/kailong321200875/vue-element-plus-admin/commit/c15aa8755c9c937512c7380a6d03c4d877ef4d87)) +- update README ([27979dc](https://github.com/kailong321200875/vue-element-plus-admin/commit/27979dc6def7d9d8cea62a08d49a6c828be2258b)) +- update README.md ([53201ae](https://github.com/kailong321200875/vue-element-plus-admin/commit/53201ae97a425714871d99e8847a3672ba0d389f)) +- update README.md ([c11823a](https://github.com/kailong321200875/vue-element-plus-admin/commit/c11823abd8a033e14b4c20d17ac941195d39bcfe)) +- 修改 README ([b79a567](https://github.com/kailong321200875/vue-element-plus-admin/commit/b79a56753df55976e749c4494266df052d315416)) diff --git a/kinit-admin/LICENSE b/kinit-admin/LICENSE new file mode 100644 index 0000000..9861118 --- /dev/null +++ b/kinit-admin/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021-present Archer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/kinit-admin/README.md b/kinit-admin/README.md new file mode 100644 index 0000000..731173f --- /dev/null +++ b/kinit-admin/README.md @@ -0,0 +1,240 @@ +
+
+ + 福州-大雨 + + |
+
+
+ + 葉家男孩 + + |
+
+
+ + Z6w6j6 + + |
+
+
+ + Archer + + |
+
+ + Archer + + |
+
+
+ + Kailong502431556 + + |
+
+
+ + Xingyu4j + + |
+
+
+ + Snoword + + |
+
+
+ + Huanghong + + |
+
+
+ + Yangyu + + |
+
+ + WuYihui + + |
+
+
+ + Xiterjia + + |
+
+
+ + Z6w6j6 + + |
+
+ + 福州-大雨 + + |
+
+
+ + 葉家男孩 + + |
+
+
+ + Z6w6j6 + + |
+
+
+ + Archer + + |
+
+ + Archer + + |
+
+
+ + Kailong502431556 + + |
+
+
+ + Xingyu4j + + |
+
+
+ + Snoword + + |
+
+
+ + Huanghong + + |
+
+
+ + Yangyu + + |
+
+ + WuYihui + + |
+
+
+ + Xiterjia + + |
+
+
+ + Z6w6j6 + + |
I am testing data, I am testing data.
1I1>71e{dFL_8$L8>!SV6_|+{nL|xI|rrLlSfjLJ4vr?#bx-ADLXnY zgilc@@O6GI!CNlI4s3moX%|TAUTsLKDDDg-)F{@VF+QmbF@Gg0^hGGjNuP~Jbxdt+ zd__@chTr1@HQmc4p09 MYbO zez$-+ME&*W8Y&h_W&^6eP b80sWE(HDAh^ zi4~Lruc+lyf@zd+`#r0mg>i9E1YaGvm^(YcAKZ}u!yy2)i(^i{M ->%1R<$YCVFrlXzF W1YXmrAb z)KGK^FX!mv^4#>o<|N&HW%_2uUyNKAuMMnSznr=&F${X=!u$>Fe=V55CBE}-!H_!> zMv2A14qNysIh$cP4!ekQ+J6kBzZGs_q2k1)JRjdyJZfZsyvu>XDZ}BE5g+WSz)jH! z{;YURbaD4rY^gw4mRqpF4Skk_XHWHujU|&Mcx!hSuHl)9T@*@G0!lNbZELl9Eukai zbh-8=6Z2KyBTXZ1-}`fraU%Ux)$%yF+9gRskBo9GIqpgGF<5AS>jg8XM;hx+BK&r! z E;rJg*Y;rabcZV?9Sw-Hcu8E@-LpjYEWy&GXL~VkR^a(MJgtdG {ojJ?4>5}t-j+P^+(<;A4L=tRZB~w^*Ys`;%i8B)xY+a}hH{7crjc+B=^6+Oo zH*Y&-{z2Uk)}URh-CaU3r=g>zo-K#=y=+}n#QG_*Ta{ap?J75@#D9$knHK|BvqUI^ z_46Fh)wAfUx!fAAsP2QLMmc}Qr)mFM_MdRY_n8)#DArG~RSr>3R@QnToH%m3_+J|q BLq7lj literal 0 HcmV?d00001 diff --git a/kinit-admin/src/assets/imgs/logo.png b/kinit-admin/src/assets/imgs/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b76c71b6ba9a0f73203fbf745fe93d240a3c7802 GIT binary patch literal 9193 zcmX9^2Ut@}(*{vMApwHYi XtvS)pOc)|-<~rT N`R?%w*ibFMc6?%(G~SRCdlq@OxuY$Fj>+gNgU7NpA{UkLOQhYancbKN2Oxx)dD zJoe;Ot`9Q|KS}$V9h(Yu^dpB%O}ljSN6eLYP~SdR)I2YGf-Q67RymG6eW{Nnr;{O# ze&Gl-e?$+++!6gOAcvrtBl?*`00UqSG +XwgVGxY2;{M={g286`Wwa?J8&-jD%$6%ZhOJZy%0r(kPNf&y< zjLmyYO?ym@d#5@BObvTX^?N6Xex}+z@}pknZ`(}Yb|E#pN7_9Q% V9mjADb{Z) z*0E;o;1p`vGPk$no7pn9H{jnk;5BUNTkL6@>kq5f9%9&2ajWuGtMZlX$r~I=8!K{^ z9Es~3iEEq*YirVVoQd-s32V!;UpV8}IO111<5rg*eCCW>;f!5bl=;LNv%DZv&K14P z6}2=kUB(r;$n{}yPO5}EVu3q+e&&ABqF5Do*c{LMxoKD-Z|E!!AR#kTlKH&vrY9sm z^1hwo4F+WLcF+WG(B!yS&h5a7+X3UFqM3ZCF@FCsKL1fZzY%`lVFBb2KXRBKIW)mv z%I`DOc0HkuHi2!r-w_B`LvLdP6N+opbPUWKTu>ni8AT->BP&}+H*aKcXm~ (uay?<|=3TV0mzK#0Db)~!?))=Ccb%=dj5WW>H6!imxA>d>qiVN( z2}Mt!SJCbjcC-*x*ivXhqzbM1m1%xKLFq>j o^n_mRh9`&~a_aCc Zc2v;XfKuU)Rbj(0fd zytDtt%ifF1V$ocCVq$W_Y|<>=>F21EVZ4x5+`5o%pRO*cNDjkjqq2d+Z8+f^ot&cn zOV3Hy;^A!TjxFZpW8hWnKbX8QiSBQ!Cwx}ao<^-FE4|KH2&c7sf#0kdwgVFul9^P5#1c_#ls%nE2OHg zZ#1uHvSedcHg+>!^U*#`q0Ew);5FV{_<}lSWFYbh&1d3X?UHVgS%zI3D6O)FYqfXT zuGgcZDIUN6Wpm7!J0EE|pXu?+og+H(q69ulZ$ otFE7V9SIoI+Tj10Uy1H-$~r zYj4D(q%6}b2bMTqc^Hk>n2&8r41vKDDk*U$zTvjMV>u?i2E-~SmTfocqEYs}K`|Lb z#jfx601Zu%`4m{5<78evWFAGtDt2I7EXrdv8D4p4su$<`<`)bPQ^5UNuIzhDHYO5z zR(e{JHOz5$jKK<7BlPdf;FL5Dm&~>8OygKD_Xxtmjo;HA!_-#v&eQ_K!e^=alHB-f z`T7>VE4y^m7Q1*YJyOGZR?0dro?c+- %BLA7lQr%>)hIifwtG}`xB!pAc28r+t-tkdk4oO5@i*Rsdqd2Z=_$oeSeQDW-WT{dV 8fPMPnXj0Fo=H#vmVK@vw* zM)xic|4NR^>qoTp^@U8cFhLHwd^Fm}R{c>jYK*(<3*6HkJYUdV{DgnJU0q*CV4+h> z#OQtKb9bQ`Yz%cQk#B`~t0mh<(bd1Xa9oe83qva>yklD2cID-k=WsSI-68s*0YOwO zI=EHl)#vg#7*!=&P<-_VmZh@9KXy1bb=CrK<15NrCwo}a#nWR7p}-ay-N_h8GoBSi ze#h)OGH>aFTbRQ;YOq2(f)Fnp%Rja($xYE3Bpt)fR_BE6o5J?$>(mDIr@eH?pL~vc zR>SbaGfvdhOMUA4fV5PjNwbmGLGeYy`iENg8~maa%ChOqEIPgKV#4OvxCDzFbHz z?I3}Cdy*4&-;vQ?F5GC__TJ5cWpqaL{aVzQ%cG9eK5DXzZmk#LTA%7ed`*dZIqHJb zVSuV6Nq46DJVS=JJ3LK3#Gl4c-Q%v2vU2UelKh+wy3ewCN$Z#oc|WLhzO;>*r>MwJ zfka#Rj!oT@;!&JT^VAWkHDTv$kwI-S(f0jGGuT<5_Iw4?vuI4nKs#<7(|EH%yCK(A z;t|-I;( @|dMmQPZn0{ZRF6Pk3y_ z^h+H;(G>;LHr7{$-UU&xnxE$4Xuj=VS<57@9Im8Fkx{xgHOa3s6K6~w)LAJ!GSTA^ zH}-{k$BDkYs?>X) x}U>i8xd_F6Ew!6ipJr zBi|I95Q>&**Z(PdZ1%L?$<^=|)U~`))^m@0ChU4Rn$T{jj(E_U@{1tSRHzRpN%#nD ze>~|D=0@%hsS-tIg(J^rtZD1zQfpOs?g+(^B5VQJZl!ZauN|K?)!Dikjze8Lai$q| z%dFc5U(k4R>own+o(19RMkl2gM!pDC`oHiVcV_ChuPS-wj246{$5#UXI`yz_OsGdu zH;zWhN2nF%PdPWTc7`-_E)dOQ-WGTHI#Z){AukV;f15Oiy}bKMKepF(K#bc+sV)n_ z=hCfrI-b4R<$SNcBxP2S6piuI5K4MFk^(Y%f@Ie^mxOx8`Qyc?7_x+p+2+&dEe|l) zcqami=<4f}Ft%Ina G%-J&D3sCX*E^jH+hn;5P6W4E_=T=^8Hfa&~ zeIBgKl>NBQ%IxU+uj;Pv@Gr!*oZiECw62&ohDWgmovAfrX#%`u@LcY-T&*3|kbNa~ zDY^z(^;m oq!Pzd zwn(Fw zEia`W{?|Q#_fE;F5*n4(BvB$|n+)2@YgU`W^P@j}9i3wSVTw!~{_mK9*RX#cI>zp`G~oKihga92dB|#qUOt+>10 nv?-(f)P!Gt)Vq-)!CJASZQCT4K+&f7oCWBlGkEPF)yNvoXziXXn9R+7@+66a1_u zl169t&$4<9(L3pP?{c9&SSLBmKYR0jP%L@SI -0GD*v6eUKUA%Xqbi0viV}HNCg0v3Vl&I9G81zGPrv3Z;^2w!)P%Vw1 zzLNM42O-!kYr7kfQnR;3;kOQ+Jpa= `EYQ>fJLjs9cYIc72={##-ozb)d8 z)yM?yzE+9Tao9kb+n!7@`r8e_NT-5=_`TDmPF*e@|NBIGS=v4Wv5U``Ai}BaX?>yV z25jT=u6mu)56~AUfAinUYyFUKEfTnW55zhBtN^naZ EI;t eO5k{n!G4DP!u8OQvY|bvaWQn#JnSj{8 zp*mB#+_c|ws=&&oyFG|#6)qq|Tj^&6S&=WUF;E_{zj); G!=P&+kLI?Ym~D1 zi#2I2nr*KxbM#l(?~3R#o;cUtzU!m76bys4!ZAIoTYxwObmO0s*!6x2vHOI#ZJMj8 zH5XmZ0lDAbye!9p`mcWaqq`;}
&ztJA$EjYa#3lv$^32iv+r0}-3un|5caA_Svp*N|a;xlZXIaZGk1wSgqto+M zn_J?G$X^E11FX6hZo#yU0=A=4s9i!U@zPqTsZS|!m$N-fE zx&i^YIc}7ma(5FdY)~pAn+-+#u)3=DGd*cw`O(es1&SCK%7AI|7wZQo#H`i~^W7>O zGwaOle7AemIq8LVPc}hJX9a|(t#0ImloQCkDw^3u=Q!N^J$=U%eN|wW-)(N`W7gtH zUB(<(AU&5YZMxW9hq%9i%%rN5h-)o;S6;ilwg~dN!<#AtaeoITzj;4@{edu2_Ya5E zuf|F#y2gWA8qtjA!lx%>`2neAh)G{IUoYpIuUYIR+_DaHgtx7QSTEgsq&xrGZC4v+ zGr2N`RRcUL$h;vu?Ic_IgRDoCUXwq=%|Dt)h}4u+t6s>bA!@_xXxQFZO)!mfPSkZ* zb&ucv{P-hQreCoBtpBJyw3fz7_PD;{(lXUaE+1Mvl+#6BS9LKIx1-7K%8(|BbQ9Tv z9BFy%ps%|y3VEV;pI|N?&xlVgboR00q7=nn1fCH_DB^YWJ}L$P^q$&@xuZ7S2gVwT zwqY`NtnK(;Fo>;`K4%O9JLa&wjP0K9jAUiiR}|lQ)l`6f#nyQy{h&T)J@&&Qb?bAi zSV{L{eqOhOPlsh8gc)V!?rr+u ={)>xuus zHD{>&e<_H+@YiY9yzAi{8~L4j%kj`B#bzROzQV*eI9+#UKWvEGU<^{FWbOM7G~!V5 zdL}}7CWr1!>Y%;?6iqp-({XkvQ~!27lj9Ny94&E|7r6?rx4|i_WgX1U2wij~z8`Mc z^ND4VoWce>sE_iC{MSx7rKAY^FeT_N^4d2VzuBf&q{fJDhiJpgEbhAYO(>6+@ YHqFlb@1CZGIjYnUw~C1o3i$~Y ze^Wcjtq9~Qk7qI++SbrK#g`0eqnGs+IeyH-@j3dqECv62$3jHpt@48r=`)hRgd>G!GW@p4lkjSMa^msYG{sJ0<9*rq7cbb)$U)V0KeN;H1!{$EPN$D8t$xO z9*$&LMJR3>U{s$oq-4YF?`flOgF-SkBM?JRXz~4{>(b#Ns0w?Jf)%HZY(v!lbh^49 zt$~M~Z_M||JR-F8taKM!5%QGuaVh(+?X)o+9ZIb0AYz##sleOG93^fOtP~yF_b)HA zpsrp>W8{LZRZ6z?#JV#BJ|KSVq`m^FI>P2q>du@01)G~vZ9W3o82HADSX3s7!x5e% zP;eeR8Pw%8z2$H;K18lm5{vD7pu<^kcuerp@<1#9=i%_89)7!wkWgFkVwr?7GFo8* z`>vD>%Zb5TD$Xp@l*dX|JuIYT?%1qc{th@lCM=fJV*P+l>5w{KjzgEm!q5JjE{2GR zrT#_km{;iC?w8Yu!22u{JSV!_{#Fxw?ok7876W~g9@M9Ire{ Y%J3l;Y!KjG%S|7_4iL?oKqi~)(S>URO oX9n86)G<%DvaBc1qEe>N^B&Sa4}!j%i^I3JrG~g~7fbY@ z5KStNjqSD%TJfdNC3E@=BzCUMss}vhO&u?XX(8UUF0#i^#}84jHsTLQR&e6F#(hx2 zkI=A9gGP-p+)&9EY<)}IUI{h++Nthyp!6vH$>tzz!s{Y=<{}*^A$T#(u>>|Z^+QDV z4TSwSmL#|2M`bF*w&)=AdzEi!G5@UF;d4hC1`=zBy329FX(lXvwZ<26SO(;OMF#Q} z8m8k$-WCyO$q4{h5&YeS*j?p1Z-tS=#evh`ZE8XP@k_JqI+Ub-n-&vt*%jP0xd2ky zvH+WR$(Ig`nv#!L-p&o2twPO7EzOaLQeBd_n8JQk2<(31V;kg6X|`iPbsQHkL$zUQ zGopr))6vDN`tF0ef`FLVVQszK7`r?$PG;btoXY8in9u~SM`cj2w&4#k+uYj&4r+u| z%mZVfhZ!IPE7u0l@U}MWEJ;!P6H4Q;g&n_1?gwf*dtfda51gmT7St72pe&F6Rwn8} zJKyuboDJ|vrcg1JDH)fd1<9F#(17cOohu&$L0oI>+wKsWTC@K2F;9BfwvNI(q9A9~ z;vm+q)X%Ah=j>c<894Z%PT}7nyxb~l9HLo(C)6_wq{QxVz |Lt;J4Ic=IWd$>;3#!GvvglmJ z6rcXhtIp5?9u0oklY)0vfARYMbh#GWch@No&J_=#Y=sCJWjdqHpFI =UB-X}T#CVpj&4N6 zk4*_Xbm*R!B+rD{WSwvT;+%r=MTQR7{_q`g(04U!r2n)BS9; @h{+eB-GC(0vsk=taz YHtM@+ZZx4%g zQPZ%3st!Io!%D23Inuu@_{7RhC(AM%768pr@#11B8(0CFr!&TVmG&Eoh&(O^HWALE zYG_RizVOpvh4Qi&oj6?ocb(V%E4D)gb&(XnVIRN4sKfe-tyY?BDEZ?(5_OPqurkf+ zGa4R60igWO9d?Q`*ruI }gtx_tUL$uhTWRaIasNm^H!ct9&TrgRKQ* nz@SXd)2qOZ{ISBOILu?MRB8ppvWhu44^j}k2IR=a z%oduXWoL1ZNB!K!QGEtyZdV4y-6fSCVy%%BzoB3*pB-kmO1aeRs7sP0AGyB5Wn!5J zy!F^8qFRj@r*=X9Cutn#lINwnF3t91*v9V6nR=Ky(r3D7bG!P jTv?wA9GqhNIhOxMz^I_b zu?<|eo>%$>g1gjFpw)c;j2fqp9Z99|w0s++zlg&d?>!Fn7b5@!zGj}tEu8IkX>N~X zAB<0{Q>R&Q8*DBTBu#5HqDjv#;<0DmCdCh8Ijj46IHaKd_=(*fcNcx*s_P!^p53&F z&bl =O``E(cKoOFnGgxJFxZ1Ok!TG40{tT#C@q(HR^e`vqTTaxNX{k}=# z^(QAI7DM#6{_nyLiMI4D?4llLS7%lMwps& T ze&4)eu{EKw~nVMvLCE|-??Gti7f2`^{MLVv29jNgsxWal98hM`c|pm#)_ z+#Gg_6>>SYplZVf1qw3m7;uiKP&2?7eLf)*POMLpfHAFrtNI3R-yJpa9fAZ!d@z9h zK%-;Y_NWPi*mo}P$*&4^H2hkMhpk?rOYnnOwaqu{poh{{cE`5who}h{si-qJcq*p{ z@^#&l#y&NB*_+XxTDSSWA2l`Uz}e 2n#jzRL#qX-in-K>YqYk#d-)j-_4beeq} z8HL&bhd1&?130&Tz|2;h!M?!(eDRrD((g}@rL`S4xgOVDfCWFj^sA2+Fz09d*5S2G zw0&@2*KNCNII|qGyCLd<@1K?m&(&_iui2kt&Z3g#fI_KCLeTF?ZbwE0 $wRYgq5IOX!@=;xzwsY7%6q(CM3~%9` zbts{5U%U)(Y>$nHXb -PQomkm 7M^3Ycmc#7yY$6J9137e2gRODlT2e`21=St* zRLLJ(ynq2dM~LRFyD$(rWdk+k;AHwBrj1|B!funhE1D5So_#X>I+JbGbY-(aRO!}? zgOm63?k=VPsC6EZu?e4)7tJ !`sE->&_h7-pO(| zjvU_mUxYqI>WnB}%FyTMb= h~d3_~~49SwXa%iTO%2MF4WTET$K> z_Tn2f=4`gQ&mdVEEh}A&>A2TQ#$!yx=Iz6KA>Ho-s`?DRjm7fa)xBV_L6LE`< bQpiFQV!gopI%fH*w5GCM6noHPRsd&bq?8aJf5 z{`pCih{*8jz~%7AOvk_XV4Qyz2e?1Ufz^#DviazrQLEjSl+?_SelIQl%goYknO92d zV{fPmEgEz>a1^!PtdSz?!DTt(Id~q@9njS9Gtngpt9-)sQt9hf*)EC8b0(W7DZ6?` ze kZH#d8B(4me{omw9=`42=WiidW_O8>LmGb>}Xt^&?T?vL1WHfAYNsP7lV%X49Rd zE#9{Ue5 pSY{(T37w9kW9TClkT-J3(W5>*w8~-xiMMou2P7qsd>5 zPy+ly!ti-Sxxw$
-$YKTOmB@ea#b~fo%C=F z4kh+sALcSOQgUg4uUpwo1x$E)hmsdf b}0I)amP0dho&LG4gDACl8=;loj#MLdNA^jFF!?g5XBTGXb-r z97_?=wD*`%-WNq$3j>?iEB$ctK zoLuMa9bhapwu&-)H9%71zY2GGi;-fhifd7wW{+a%1N7NrN>i1RvMDVP_NZ&U195Mz z6D}lpm1yV?p2 Vq*-ax@-hAMx~tcOMGFscM-2jb94Y z2!;%+O|us={Jj>Jf_N{<|D>6%aP|&74tSCa%xnu)ThdmquT=vS&7<~0@j-vWb|qG* X5_)J=A58xJn+`(LK;w&=?YsX2HuGA3 literal 0 HcmV?d00001 diff --git a/kinit-admin/src/assets/svgs/403.svg b/kinit-admin/src/assets/svgs/403.svg new file mode 100644 index 0000000..4500596 --- /dev/null +++ b/kinit-admin/src/assets/svgs/403.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/kinit-admin/src/assets/svgs/404.svg b/kinit-admin/src/assets/svgs/404.svg new file mode 100644 index 0000000..5244d8d --- /dev/null +++ b/kinit-admin/src/assets/svgs/404.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/kinit-admin/src/assets/svgs/500.svg b/kinit-admin/src/assets/svgs/500.svg new file mode 100644 index 0000000..9c02092 --- /dev/null +++ b/kinit-admin/src/assets/svgs/500.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/kinit-admin/src/assets/svgs/icon.svg b/kinit-admin/src/assets/svgs/icon.svg new file mode 100644 index 0000000..7024bec --- /dev/null +++ b/kinit-admin/src/assets/svgs/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/kinit-admin/src/assets/svgs/login-bg.svg b/kinit-admin/src/assets/svgs/login-bg.svg new file mode 100644 index 0000000..bbe06c1 --- /dev/null +++ b/kinit-admin/src/assets/svgs/login-bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/kinit-admin/src/assets/svgs/login-box-bg.svg b/kinit-admin/src/assets/svgs/login-box-bg.svg new file mode 100644 index 0000000..ab10040 --- /dev/null +++ b/kinit-admin/src/assets/svgs/login-box-bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/kinit-admin/src/assets/svgs/message.svg b/kinit-admin/src/assets/svgs/message.svg new file mode 100644 index 0000000..14ca817 --- /dev/null +++ b/kinit-admin/src/assets/svgs/message.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/kinit-admin/src/assets/svgs/money.svg b/kinit-admin/src/assets/svgs/money.svg new file mode 100644 index 0000000..c1580de --- /dev/null +++ b/kinit-admin/src/assets/svgs/money.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/kinit-admin/src/assets/svgs/peoples.svg b/kinit-admin/src/assets/svgs/peoples.svg new file mode 100644 index 0000000..aab852e --- /dev/null +++ b/kinit-admin/src/assets/svgs/peoples.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/kinit-admin/src/assets/svgs/shopping.svg b/kinit-admin/src/assets/svgs/shopping.svg new file mode 100644 index 0000000..f395bc7 --- /dev/null +++ b/kinit-admin/src/assets/svgs/shopping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/kinit-admin/src/components/Backtop/index.ts b/kinit-admin/src/components/Backtop/index.ts new file mode 100644 index 0000000..96de88d --- /dev/null +++ b/kinit-admin/src/components/Backtop/index.ts @@ -0,0 +1,3 @@ +import Backtop from './src/Backtop.vue' + +export { Backtop } diff --git a/kinit-admin/src/components/Backtop/src/Backtop.vue b/kinit-admin/src/components/Backtop/src/Backtop.vue new file mode 100644 index 0000000..f5c2fc4 --- /dev/null +++ b/kinit-admin/src/components/Backtop/src/Backtop.vue @@ -0,0 +1,15 @@ + + + + + diff --git a/kinit-admin/src/components/Breadcrumb/index.ts b/kinit-admin/src/components/Breadcrumb/index.ts new file mode 100644 index 0000000..93ffe70 --- /dev/null +++ b/kinit-admin/src/components/Breadcrumb/index.ts @@ -0,0 +1,3 @@ +import Breadcrumb from './src/Breadcrumb.vue' + +export { Breadcrumb } diff --git a/kinit-admin/src/components/Breadcrumb/src/Breadcrumb.vue b/kinit-admin/src/components/Breadcrumb/src/Breadcrumb.vue new file mode 100644 index 0000000..bbbbc19 --- /dev/null +++ b/kinit-admin/src/components/Breadcrumb/src/Breadcrumb.vue @@ -0,0 +1,127 @@ + + + diff --git a/kinit-admin/src/components/Breadcrumb/src/helper.ts b/kinit-admin/src/components/Breadcrumb/src/helper.ts new file mode 100644 index 0000000..fb3ec19 --- /dev/null +++ b/kinit-admin/src/components/Breadcrumb/src/helper.ts @@ -0,0 +1,31 @@ +import { pathResolve } from '@/utils/routerHelper' +import type { RouteMeta } from 'vue-router' + +export const filterBreadcrumb = ( + routes: AppRouteRecordRaw[], + parentPath = '' +): AppRouteRecordRaw[] => { + const res: AppRouteRecordRaw[] = [] + + for (const route of routes) { + const meta = route?.meta as RouteMeta + if (meta.hidden && !meta.canTo) { + continue + } + + const data: AppRouteRecordRaw = + !meta.alwaysShow && route.children?.length === 1 + ? { ...route.children[0], path: pathResolve(route.path, route.children[0].path) } + : { ...route } + + data.path = pathResolve(parentPath, data.path) + + if (data.children) { + data.children = filterBreadcrumb(data.children, data.path) + } + if (data) { + res.push(data) + } + } + return res +} diff --git a/kinit-admin/src/components/Collapse/index.ts b/kinit-admin/src/components/Collapse/index.ts new file mode 100644 index 0000000..73f65a3 --- /dev/null +++ b/kinit-admin/src/components/Collapse/index.ts @@ -0,0 +1,3 @@ +import Collapse from './src/Collapse.vue' + +export { Collapse } diff --git a/kinit-admin/src/components/Collapse/src/Collapse.vue b/kinit-admin/src/components/Collapse/src/Collapse.vue new file mode 100644 index 0000000..f397af5 --- /dev/null +++ b/kinit-admin/src/components/Collapse/src/Collapse.vue @@ -0,0 +1,35 @@ + + + + ++ diff --git a/kinit-admin/src/components/ConfigGlobal/index.ts b/kinit-admin/src/components/ConfigGlobal/index.ts new file mode 100644 index 0000000..dda2462 --- /dev/null +++ b/kinit-admin/src/components/ConfigGlobal/index.ts @@ -0,0 +1,3 @@ +import ConfigGlobal from './src/ConfigGlobal.vue' + +export { ConfigGlobal } diff --git a/kinit-admin/src/components/ConfigGlobal/src/ConfigGlobal.vue b/kinit-admin/src/components/ConfigGlobal/src/ConfigGlobal.vue new file mode 100644 index 0000000..985d5df --- /dev/null +++ b/kinit-admin/src/components/ConfigGlobal/src/ConfigGlobal.vue @@ -0,0 +1,62 @@ + + + ++ + + diff --git a/kinit-admin/src/components/ContentDetailWrap/index.ts b/kinit-admin/src/components/ContentDetailWrap/index.ts new file mode 100644 index 0000000..1871cac --- /dev/null +++ b/kinit-admin/src/components/ContentDetailWrap/index.ts @@ -0,0 +1,3 @@ +import ContentDetailWrap from './src/ContentDetailWrap.vue' + +export { ContentDetailWrap } diff --git a/kinit-admin/src/components/ContentDetailWrap/src/ContentDetailWrap.vue b/kinit-admin/src/components/ContentDetailWrap/src/ContentDetailWrap.vue new file mode 100644 index 0000000..22aeb83 --- /dev/null +++ b/kinit-admin/src/components/ContentDetailWrap/src/ContentDetailWrap.vue @@ -0,0 +1,59 @@ + + + ++ ++ diff --git a/kinit-admin/src/components/ContentWrap/index.ts b/kinit-admin/src/components/ContentWrap/index.ts new file mode 100644 index 0000000..8c22cc8 --- /dev/null +++ b/kinit-admin/src/components/ContentWrap/index.ts @@ -0,0 +1,3 @@ +import ContentWrap from './src/ContentWrap.vue' + +export { ContentWrap } diff --git a/kinit-admin/src/components/ContentWrap/src/ContentWrap.vue b/kinit-admin/src/components/ContentWrap/src/ContentWrap.vue new file mode 100644 index 0000000..4538fc0 --- /dev/null +++ b/kinit-admin/src/components/ContentWrap/src/ContentWrap.vue @@ -0,0 +1,33 @@ + + + ++ ++++++ ++ {{ t('common.back') }} + +++ + ++++ +++ ++++ + + + diff --git a/kinit-admin/src/components/ContextMenu/index.ts b/kinit-admin/src/components/ContextMenu/index.ts new file mode 100644 index 0000000..2a7c1f0 --- /dev/null +++ b/kinit-admin/src/components/ContextMenu/index.ts @@ -0,0 +1,10 @@ +import ContextMenu from './src/ContextMenu.vue' +import { ElDropdown } from 'element-plus' +import type { RouteLocationNormalizedLoaded } from 'vue-router' + +export interface ContextMenuExpose { + elDropdownMenuRef: ComponentRef+ {{ title }} ++ ++ + +{{ message }}+ ++ +++ + tagItem: RouteLocationNormalizedLoaded +} + +export { ContextMenu } diff --git a/kinit-admin/src/components/ContextMenu/src/ContextMenu.vue b/kinit-admin/src/components/ContextMenu/src/ContextMenu.vue new file mode 100644 index 0000000..5007121 --- /dev/null +++ b/kinit-admin/src/components/ContextMenu/src/ContextMenu.vue @@ -0,0 +1,72 @@ + + + + + + diff --git a/kinit-admin/src/components/CountTo/index.ts b/kinit-admin/src/components/CountTo/index.ts new file mode 100644 index 0000000..2119f02 --- /dev/null +++ b/kinit-admin/src/components/CountTo/index.ts @@ -0,0 +1,3 @@ +import CountTo from './src/CountTo.vue' + +export { CountTo } diff --git a/kinit-admin/src/components/CountTo/src/CountTo.vue b/kinit-admin/src/components/CountTo/src/CountTo.vue new file mode 100644 index 0000000..cab8ea9 --- /dev/null +++ b/kinit-admin/src/components/CountTo/src/CountTo.vue @@ -0,0 +1,180 @@ + + + + + {{ displayValue }} + + diff --git a/kinit-admin/src/components/Descriptions/index.ts b/kinit-admin/src/components/Descriptions/index.ts new file mode 100644 index 0000000..91b0eb4 --- /dev/null +++ b/kinit-admin/src/components/Descriptions/index.ts @@ -0,0 +1,3 @@ +import Descriptions from './src/Descriptions.vue' + +export { Descriptions } diff --git a/kinit-admin/src/components/Descriptions/src/Descriptions.vue b/kinit-admin/src/components/Descriptions/src/Descriptions.vue new file mode 100644 index 0000000..c59d74a --- /dev/null +++ b/kinit-admin/src/components/Descriptions/src/Descriptions.vue @@ -0,0 +1,139 @@ + + + ++ + + + ++ +{{ t(item.label) }} + ++ + + diff --git a/kinit-admin/src/components/Dialog/index.ts b/kinit-admin/src/components/Dialog/index.ts new file mode 100644 index 0000000..1655dad --- /dev/null +++ b/kinit-admin/src/components/Dialog/index.ts @@ -0,0 +1,3 @@ +import Dialog from './src/Dialog.vue' + +export { Dialog } diff --git a/kinit-admin/src/components/Dialog/src/Dialog.vue b/kinit-admin/src/components/Dialog/src/Dialog.vue new file mode 100644 index 0000000..4e030ad --- /dev/null +++ b/kinit-admin/src/components/Dialog/src/Dialog.vue @@ -0,0 +1,118 @@ + + + +++ ++++ {{ title }} +++ ++ + + ++++ ++ + +{{ item.label }} + + + +{{ data[item.field] }} + ++ + + + + diff --git a/kinit-admin/src/components/Echart/index.ts b/kinit-admin/src/components/Echart/index.ts new file mode 100644 index 0000000..4822092 --- /dev/null +++ b/kinit-admin/src/components/Echart/index.ts @@ -0,0 +1,3 @@ +import Echart from './src/Echart.vue' + +export { Echart } diff --git a/kinit-admin/src/components/Echart/src/Echart.vue b/kinit-admin/src/components/Echart/src/Echart.vue new file mode 100644 index 0000000..84f23da --- /dev/null +++ b/kinit-admin/src/components/Echart/src/Echart.vue @@ -0,0 +1,113 @@ + + + + + diff --git a/kinit-admin/src/components/Editor/index.ts b/kinit-admin/src/components/Editor/index.ts new file mode 100644 index 0000000..3fbf0a9 --- /dev/null +++ b/kinit-admin/src/components/Editor/index.ts @@ -0,0 +1,8 @@ +import Editor from './src/Editor.vue' +import { IDomEditor } from '@wangeditor/editor' + +export interface EditorExpose { + getEditorRef: () => Promise++ + ++ {{ title }} + ++ + + + ++ + + +} + +export { Editor } diff --git a/kinit-admin/src/components/Editor/src/Editor.vue b/kinit-admin/src/components/Editor/src/Editor.vue new file mode 100644 index 0000000..9254803 --- /dev/null +++ b/kinit-admin/src/components/Editor/src/Editor.vue @@ -0,0 +1,138 @@ + + + + + + + diff --git a/kinit-admin/src/components/Error/index.ts b/kinit-admin/src/components/Error/index.ts new file mode 100644 index 0000000..a52c6f9 --- /dev/null +++ b/kinit-admin/src/components/Error/index.ts @@ -0,0 +1,3 @@ +import Error from './src/Error.vue' + +export { Error } diff --git a/kinit-admin/src/components/Error/src/Error.vue b/kinit-admin/src/components/Error/src/Error.vue new file mode 100644 index 0000000..8676a81 --- /dev/null +++ b/kinit-admin/src/components/Error/src/Error.vue @@ -0,0 +1,58 @@ + + + +++ diff --git a/kinit-admin/src/components/Footer/index.ts b/kinit-admin/src/components/Footer/index.ts new file mode 100644 index 0000000..bd052e0 --- /dev/null +++ b/kinit-admin/src/components/Footer/index.ts @@ -0,0 +1,3 @@ +import Footer from './src/Footer.vue' + +export { Footer } diff --git a/kinit-admin/src/components/Footer/src/Footer.vue b/kinit-admin/src/components/Footer/src/Footer.vue new file mode 100644 index 0000000..e7a778d --- /dev/null +++ b/kinit-admin/src/components/Footer/src/Footer.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/kinit-admin/src/components/Form/index.ts b/kinit-admin/src/components/Form/index.ts new file mode 100644 index 0000000..a9c5efc --- /dev/null +++ b/kinit-admin/src/components/Form/index.ts @@ -0,0 +1,14 @@ +import Form from './src/Form.vue' +import { ElForm } from 'element-plus' + +export interface FormExpose { + setValues: (data: Recordable) => void + setProps: (props: Recordable) => void + delSchema: (field: string) => void + addSchema: (formSchema: FormSchema, index?: number) => void + setSchema: (schemaProps: FormSetPropsType[]) => void + formModel: Recordable + getElFormRef: () => ComponentRef+++
{{ errorMap[type].message }}+++{{ errorMap[type].buttonText }} ++} + +export { Form } diff --git a/kinit-admin/src/components/Form/src/Form.vue b/kinit-admin/src/components/Form/src/Form.vue new file mode 100644 index 0000000..fee05df --- /dev/null +++ b/kinit-admin/src/components/Form/src/Form.vue @@ -0,0 +1,299 @@ + + + diff --git a/kinit-admin/src/components/Form/src/componentMap.ts b/kinit-admin/src/components/Form/src/componentMap.ts new file mode 100644 index 0000000..822f64d --- /dev/null +++ b/kinit-admin/src/components/Form/src/componentMap.ts @@ -0,0 +1,48 @@ +import type { Component } from 'vue' +import { + ElCascader, + ElCheckboxGroup, + ElColorPicker, + ElDatePicker, + ElInput, + ElInputNumber, + ElRadioGroup, + ElRate, + ElSelect, + ElSelectV2, + ElSlider, + ElSwitch, + ElTimePicker, + ElTimeSelect, + ElTransfer, + ElAutocomplete, + ElDivider +} from 'element-plus' +import { InputPassword } from '@/components/InputPassword' +import { Editor } from '@/components/Editor' + +const componentMap: Recordable = { + Radio: ElRadioGroup, + Checkbox: ElCheckboxGroup, + CheckboxButton: ElCheckboxGroup, + Input: ElInput, + Autocomplete: ElAutocomplete, + InputNumber: ElInputNumber, + Select: ElSelect, + Cascader: ElCascader, + Switch: ElSwitch, + Slider: ElSlider, + TimePicker: ElTimePicker, + DatePicker: ElDatePicker, + Rate: ElRate, + ColorPicker: ElColorPicker, + Transfer: ElTransfer, + Divider: ElDivider, + TimeSelect: ElTimeSelect, + SelectV2: ElSelectV2, + RadioButton: ElRadioGroup, + InputPassword: InputPassword, + Editor: Editor +} + +export { componentMap } diff --git a/kinit-admin/src/components/Form/src/components/useRenderCheckbox.tsx b/kinit-admin/src/components/Form/src/components/useRenderCheckbox.tsx new file mode 100644 index 0000000..26ac32e --- /dev/null +++ b/kinit-admin/src/components/Form/src/components/useRenderCheckbox.tsx @@ -0,0 +1,20 @@ +import { ElCheckbox, ElCheckboxButton } from 'element-plus' +import { defineComponent } from 'vue' + +export const useRenderCheckbox = () => { + const renderChcekboxOptions = (item: FormSchema) => { + // 如果有别名,就取别名 + const labelAlias = item?.componentProps?.optionsAlias?.labelField + const valueAlias = item?.componentProps?.optionsAlias?.valueField + const Com = (item.component === 'Checkbox' ? ElCheckbox : ElCheckboxButton) as ReturnType< + typeof defineComponent + > + return item?.componentProps?.options?.map((option) => { + return {option[valueAlias || 'label']} + }) + } + + return { + renderChcekboxOptions + } +} diff --git a/kinit-admin/src/components/Form/src/components/useRenderRadio.tsx b/kinit-admin/src/components/Form/src/components/useRenderRadio.tsx new file mode 100644 index 0000000..98a4778 --- /dev/null +++ b/kinit-admin/src/components/Form/src/components/useRenderRadio.tsx @@ -0,0 +1,20 @@ +import { ElRadio, ElRadioButton } from 'element-plus' +import { defineComponent } from 'vue' + +export const useRenderRadio = () => { + const renderRadioOptions = (item: FormSchema) => { + // 如果有别名,就取别名 + const labelAlias = item?.componentProps?.optionsAlias?.labelField + const valueAlias = item?.componentProps?.optionsAlias?.valueField + const Com = (item.component === 'Radio' ? ElRadio : ElRadioButton) as ReturnType< + typeof defineComponent + > + return item?.componentProps?.options?.map((option) => { + return{option[valueAlias || 'label']} + }) + } + + return { + renderRadioOptions + } +} diff --git a/kinit-admin/src/components/Form/src/components/useRenderSelect.tsx b/kinit-admin/src/components/Form/src/components/useRenderSelect.tsx new file mode 100644 index 0000000..13793f5 --- /dev/null +++ b/kinit-admin/src/components/Form/src/components/useRenderSelect.tsx @@ -0,0 +1,48 @@ +import { ElOption, ElOptionGroup } from 'element-plus' +import { getSlot } from '@/utils/tsxHelper' +import { Slots } from 'vue' + +export const useRenderSelect = (slots: Slots) => { + // 渲染 select options + const renderSelectOptions = (item: FormSchema) => { + // 如果有别名,就取别名 + const labelAlias = item?.componentProps?.optionsAlias?.labelField + return item?.componentProps?.options?.map((option) => { + if (option?.options?.length) { + return ( ++ {() => { + return option?.options?.map((v) => { + return renderSelectOptionItem(item, v) + }) + }} + + ) + } else { + return renderSelectOptionItem(item, option) + } + }) + } + + // 渲染 select option item + const renderSelectOptionItem = (item: FormSchema, option: ComponentOptions) => { + // 如果有别名,就取别名 + const labelAlias = item?.componentProps?.optionsAlias?.labelField + const valueAlias = item?.componentProps?.optionsAlias?.valueField + return ( ++ {{ + default: () => + // option 插槽名规则,{field}-option + item?.componentProps?.optionsSlot + ? getSlot(slots, `${item.field}-option`, { item: option }) + : undefined + }} + + ) + } + + return { + renderSelectOptions + } +} diff --git a/kinit-admin/src/components/Form/src/helper.ts b/kinit-admin/src/components/Form/src/helper.ts new file mode 100644 index 0000000..fbd7959 --- /dev/null +++ b/kinit-admin/src/components/Form/src/helper.ts @@ -0,0 +1,148 @@ +import { useI18n } from '@/hooks/web/useI18n' +import type { Slots } from 'vue' +import { getSlot } from '@/utils/tsxHelper' +import { PlaceholderMoel } from './types' + +const { t } = useI18n() + +/** + * + * @param schema 对应组件数据 + * @returns 返回提示信息对象 + * @description 用于自动设置placeholder + */ +export const setTextPlaceholder = (schema: FormSchema): PlaceholderMoel => { + const textMap = ['Input', 'Autocomplete', 'InputNumber', 'InputPassword'] + const selectMap = ['Select', 'TimePicker', 'DatePicker', 'TimeSelect', 'TimeSelect'] + if (textMap.includes(schema?.component as string)) { + return { + placeholder: t('common.inputText') + } + } + if (selectMap.includes(schema?.component as string)) { + // 一些范围选择器 + const twoTextMap = ['datetimerange', 'daterange', 'monthrange', 'datetimerange', 'daterange'] + if ( + twoTextMap.includes( + (schema?.componentProps?.type || schema?.componentProps?.isRange) as string + ) + ) { + return { + startPlaceholder: t('common.startTimeText'), + endPlaceholder: t('common.endTimeText'), + rangeSeparator: '-' + } + } else { + return { + placeholder: t('common.selectText') + } + } + } + return {} +} + +/** + * + * @param col 内置栅格 + * @returns 返回栅格属性 + * @description 合并传入进来的栅格属性 + */ +export const setGridProp = (col: ColProps = {}): ColProps => { + const colProps: ColProps = { + // 如果有span,代表用户优先级更高,所以不需要默认栅格 + ...(col.span + ? {} + : { + xs: 24, + sm: 12, + md: 12, + lg: 12, + xl: 12 + }), + ...col + } + return colProps +} + +/** + * + * @param item 传入的组件属性 + * @returns 默认添加 clearable 属性 + */ +export const setComponentProps = (item: FormSchema): Recordable => { + const notNeedClearable = ['ColorPicker'] + const componentProps: Recordable = notNeedClearable.includes(item.component as string) + ? { ...item.componentProps } + : { + clearable: true, + ...item.componentProps + } + // 需要删除额外的属性 + delete componentProps?.slots + return componentProps +} + +/** + * + * @param slots 插槽 + * @param slotsProps 插槽属性 + * @param field 字段名 + */ +export const setItemComponentSlots = ( + slots: Slots, + slotsProps: Recordable = {}, + field: string +): Recordable => { + const slotObj: Recordable = {} + for (const key in slotsProps) { + if (slotsProps[key]) { + // 由于组件有可能重复,需要有一个唯一的前缀 + slotObj[key] = (data: Recordable) => { + return getSlot(slots, `${field}-${key}`, data) + } + } + } + return slotObj +} + +/** + * + * @param schema Form表单结构化数组 + * @param formModel FormMoel + * @returns FormMoel + * @description 生成对应的formModel + */ +export const initModel = (schema: FormSchema[], formModel: Recordable) => { + const model: Recordable = { ...formModel } + schema.map((v) => { + // 如果是hidden,就删除对应的值 + if (v.hidden) { + delete model[v.field] + } else if (v.component && v.component !== 'Divider') { + const hasField = Reflect.has(model, v.field) + // 如果先前已经有值存在,则不进行重新赋值,而是采用现有的值 + model[v.field] = hasField ? model[v.field] : v.value !== void 0 ? v.value : '' + } + }) + return model +} + +/** + * @param slots 插槽 + * @param field 字段名 + * @returns 返回FormIiem插槽 + */ +export const setFormItemSlots = (slots: Slots, field: string): Recordable => { + const slotObj: Recordable = {} + if (slots[`${field}-error`]) { + slotObj['error'] = (data: Recordable) => { + return getSlot(slots, `${field}-error`, data) + } + } + if (slots[`${field}-label`]) { + slotObj['label'] = (data: Recordable) => { + return getSlot(slots, `${field}-label`, data) + } + } + return slotObj +} diff --git a/kinit-admin/src/components/Form/src/types.ts b/kinit-admin/src/components/Form/src/types.ts new file mode 100644 index 0000000..fb650ba --- /dev/null +++ b/kinit-admin/src/components/Form/src/types.ts @@ -0,0 +1,15 @@ +export interface PlaceholderMoel { + placeholder?: string + startPlaceholder?: string + endPlaceholder?: string + rangeSeparator?: string +} + +export type FormProps = { + schema?: FormSchema[] + isCol?: boolean + model?: Recordable + autoSetPlaceholder?: boolean + isCustom?: boolean + labelWidth?: string | number +} & Recordable diff --git a/kinit-admin/src/components/Highlight/index.ts b/kinit-admin/src/components/Highlight/index.ts new file mode 100644 index 0000000..3e2d9ed --- /dev/null +++ b/kinit-admin/src/components/Highlight/index.ts @@ -0,0 +1,3 @@ +import Highlight from './src/Highlight.vue' + +export { Highlight } diff --git a/kinit-admin/src/components/Highlight/src/Highlight.vue b/kinit-admin/src/components/Highlight/src/Highlight.vue new file mode 100644 index 0000000..ef923a9 --- /dev/null +++ b/kinit-admin/src/components/Highlight/src/Highlight.vue @@ -0,0 +1,65 @@ + diff --git a/kinit-admin/src/components/Icon/index.ts b/kinit-admin/src/components/Icon/index.ts new file mode 100644 index 0000000..cf92784 --- /dev/null +++ b/kinit-admin/src/components/Icon/index.ts @@ -0,0 +1,3 @@ +import Icon from './src/Icon.vue' + +export { Icon } diff --git a/kinit-admin/src/components/Icon/src/Icon.vue b/kinit-admin/src/components/Icon/src/Icon.vue new file mode 100644 index 0000000..8c5dded --- /dev/null +++ b/kinit-admin/src/components/Icon/src/Icon.vue @@ -0,0 +1,78 @@ + + + ++ + + + + + + diff --git a/kinit-admin/src/components/ImageViewer/index.ts b/kinit-admin/src/components/ImageViewer/index.ts new file mode 100644 index 0000000..3868135 --- /dev/null +++ b/kinit-admin/src/components/ImageViewer/index.ts @@ -0,0 +1,33 @@ +import ImageViewer from './src/ImageViewer.vue' +import { isClient } from '@/utils/is' +import { createVNode, render, VNode } from 'vue' +import { ImageViewerProps } from './src/types' + +let instance: Nullable= null + +export function createImageViewer(options: ImageViewerProps) { + if (!isClient) return + const { + urlList, + initialIndex = 0, + infinite = true, + hideOnClickModal = false, + appendToBody = false, + zIndex = 2000, + show = true + } = options + + const propsData: Partial = {} + const container = document.createElement('div') + propsData.urlList = urlList + propsData.initialIndex = initialIndex + propsData.infinite = infinite + propsData.hideOnClickModal = hideOnClickModal + propsData.appendToBody = appendToBody + propsData.zIndex = zIndex + propsData.show = show + + document.body.appendChild(container) + instance = createVNode(ImageViewer, propsData) + render(instance, container) +} diff --git a/kinit-admin/src/components/ImageViewer/src/ImageViewer.vue b/kinit-admin/src/components/ImageViewer/src/ImageViewer.vue new file mode 100644 index 0000000..02fdb00 --- /dev/null +++ b/kinit-admin/src/components/ImageViewer/src/ImageViewer.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/kinit-admin/src/components/ImageViewer/src/types.ts b/kinit-admin/src/components/ImageViewer/src/types.ts new file mode 100644 index 0000000..1932d74 --- /dev/null +++ b/kinit-admin/src/components/ImageViewer/src/types.ts @@ -0,0 +1,9 @@ +export interface ImageViewerProps { + urlList?: string[] + zIndex?: number + initialIndex?: number + infinite?: boolean + hideOnClickModal?: boolean + appendToBody?: boolean + show?: boolean +} diff --git a/kinit-admin/src/components/Infotip/index.ts b/kinit-admin/src/components/Infotip/index.ts new file mode 100644 index 0000000..413fa5f --- /dev/null +++ b/kinit-admin/src/components/Infotip/index.ts @@ -0,0 +1,3 @@ +import Infotip from './src/Infotip.vue' + +export { Infotip } diff --git a/kinit-admin/src/components/Infotip/src/Infotip.vue b/kinit-admin/src/components/Infotip/src/Infotip.vue new file mode 100644 index 0000000..776341d --- /dev/null +++ b/kinit-admin/src/components/Infotip/src/Infotip.vue @@ -0,0 +1,52 @@ + + + + ++ diff --git a/kinit-admin/src/components/InputPassword/index.ts b/kinit-admin/src/components/InputPassword/index.ts new file mode 100644 index 0000000..1dcc38e --- /dev/null +++ b/kinit-admin/src/components/InputPassword/index.ts @@ -0,0 +1,3 @@ +import InputPassword from './src/InputPassword.vue' + +export { InputPassword } diff --git a/kinit-admin/src/components/InputPassword/src/InputPassword.vue b/kinit-admin/src/components/InputPassword/src/InputPassword.vue new file mode 100644 index 0000000..137ff41 --- /dev/null +++ b/kinit-admin/src/components/InputPassword/src/InputPassword.vue @@ -0,0 +1,152 @@ + + + ++++ {{ title }} + +++
++ {{ showIndex ? `${$index + 1}、` : '' }}{{ typeof item === 'string' ? item : item.label }} + +++ + + diff --git a/kinit-admin/src/components/LocaleDropdown/index.ts b/kinit-admin/src/components/LocaleDropdown/index.ts new file mode 100644 index 0000000..d02e640 --- /dev/null +++ b/kinit-admin/src/components/LocaleDropdown/index.ts @@ -0,0 +1,3 @@ +import LocaleDropdown from './src/LocaleDropdown.vue' + +export { LocaleDropdown } diff --git a/kinit-admin/src/components/LocaleDropdown/src/LocaleDropdown.vue b/kinit-admin/src/components/LocaleDropdown/src/LocaleDropdown.vue new file mode 100644 index 0000000..9040908 --- /dev/null +++ b/kinit-admin/src/components/LocaleDropdown/src/LocaleDropdown.vue @@ -0,0 +1,52 @@ + + + ++ + ++ + + +++ + diff --git a/kinit-admin/src/components/Logo/index.ts b/kinit-admin/src/components/Logo/index.ts new file mode 100644 index 0000000..1c4224c --- /dev/null +++ b/kinit-admin/src/components/Logo/index.ts @@ -0,0 +1,3 @@ +import Logo from './src/Logo.vue' + +export { Logo } diff --git a/kinit-admin/src/components/Logo/src/Logo.vue b/kinit-admin/src/components/Logo/src/Logo.vue new file mode 100644 index 0000000..f7dffe2 --- /dev/null +++ b/kinit-admin/src/components/Logo/src/Logo.vue @@ -0,0 +1,85 @@ + + + ++ + + + ++ {{ item.name }} + ++ + diff --git a/kinit-admin/src/components/Menu/index.ts b/kinit-admin/src/components/Menu/index.ts new file mode 100644 index 0000000..a6ec696 --- /dev/null +++ b/kinit-admin/src/components/Menu/index.ts @@ -0,0 +1,3 @@ +import Menu from './src/Menu.vue' + +export { Menu } diff --git a/kinit-admin/src/components/Menu/src/Menu.vue b/kinit-admin/src/components/Menu/src/Menu.vue new file mode 100644 index 0000000..9fc7996 --- /dev/null +++ b/kinit-admin/src/components/Menu/src/Menu.vue @@ -0,0 +1,299 @@ + + + + + diff --git a/kinit-admin/src/components/Menu/src/components/useRenderMenuItem.tsx b/kinit-admin/src/components/Menu/src/components/useRenderMenuItem.tsx new file mode 100644 index 0000000..17a520a --- /dev/null +++ b/kinit-admin/src/components/Menu/src/components/useRenderMenuItem.tsx @@ -0,0 +1,59 @@ +import { ElSubMenu, ElMenuItem } from 'element-plus' +import type { RouteMeta } from 'vue-router' +import { hasOneShowingChild } from '../helper' +import { isUrl } from '@/utils/is' +import { useRenderMenuTitle } from './useRenderMenuTitle' +import { useDesign } from '@/hooks/web/useDesign' +import { pathResolve } from '@/utils/routerHelper' + +export const useRenderMenuItem = ( + // allRouters: AppRouteRecordRaw[] = [], + menuMode: 'vertical' | 'horizontal' +) => { + const renderMenuItem = (routers: AppRouteRecordRaw[], parentPath = '/') => { + return routers.map((v) => { + const meta = (v.meta ?? {}) as RouteMeta + if (!meta.hidden) { + const { oneShowingChild, onlyOneChild } = hasOneShowingChild(v.children, v) + const fullPath = isUrl(v.path) ? v.path : pathResolve(parentPath, v.path) // getAllParentPath+
+ {{ title }} ++(allRouters, v.path).join('/') + + const { renderMenuTitle } = useRenderMenuTitle() + + if ( + oneShowingChild && + (!onlyOneChild?.children || onlyOneChild?.noShowingChildren) && + !meta?.alwaysShow + ) { + return ( + + {{ + default: () => renderMenuTitle(onlyOneChild ? onlyOneChild?.meta : meta) + }} + + ) + } else { + const { getPrefixCls } = useDesign() + + const preFixCls = getPrefixCls('menu-popper') + return ( ++ {{ + title: () => renderMenuTitle(meta), + default: () => renderMenuItem(v.children!, fullPath) + }} + + ) + } + } + }) + } + + return { + renderMenuItem + } +} diff --git a/kinit-admin/src/components/Menu/src/components/useRenderMenuTitle.tsx b/kinit-admin/src/components/Menu/src/components/useRenderMenuTitle.tsx new file mode 100644 index 0000000..6f7caff --- /dev/null +++ b/kinit-admin/src/components/Menu/src/components/useRenderMenuTitle.tsx @@ -0,0 +1,23 @@ +import type { RouteMeta } from 'vue-router' +import { Icon } from '@/components/Icon' +import { useI18n } from '@/hooks/web/useI18n' + +export const useRenderMenuTitle = () => { + const renderMenuTitle = (meta: RouteMeta) => { + const { t } = useI18n() + const { title = 'Please set title', icon } = meta + + return icon ? ( + <> ++ + > + ) : ( + + ) + } + + return { + renderMenuTitle + } +} diff --git a/kinit-admin/src/components/Menu/src/helper.ts b/kinit-admin/src/components/Menu/src/helper.ts new file mode 100644 index 0000000..b483881 --- /dev/null +++ b/kinit-admin/src/components/Menu/src/helper.ts @@ -0,0 +1,55 @@ +import type { RouteMeta } from 'vue-router' +import { ref, unref } from 'vue' +import { findPath } from '@/utils/tree' + +type OnlyOneChildType = AppRouteRecordRaw & { noShowingChildren?: boolean } + +interface HasOneShowingChild { + oneShowingChild?: boolean + onlyOneChild?: OnlyOneChildType +} + +export const getAllParentPath = (treeData: T[], path: string) => { + const menuList = findPath(treeData, (n) => n.path === path) as AppRouteRecordRaw[] + return (menuList || []).map((item) => item.path) +} + +export const hasOneShowingChild = ( + children: AppRouteRecordRaw[] = [], + parent: AppRouteRecordRaw +): HasOneShowingChild => { + const onlyOneChild = ref () + + const showingChildren = children.filter((v) => { + const meta = (v.meta ?? {}) as RouteMeta + if (meta.hidden) { + return false + } else { + // Temp set(will be used if only has one showing child) + onlyOneChild.value = v + return true + } + }) + + // When there is only one child router, the child router is displayed by default + if (showingChildren.length === 1) { + return { + oneShowingChild: true, + onlyOneChild: unref(onlyOneChild) + } + } + + // Show parent if there are no child router to display + if (!showingChildren.length) { + onlyOneChild.value = { ...parent, path: '', noShowingChildren: true } + return { + oneShowingChild: true, + onlyOneChild: unref(onlyOneChild) + } + } + + return { + oneShowingChild: false, + onlyOneChild: unref(onlyOneChild) + } +} diff --git a/kinit-admin/src/components/Qrcode/index.ts b/kinit-admin/src/components/Qrcode/index.ts new file mode 100644 index 0000000..ce46161 --- /dev/null +++ b/kinit-admin/src/components/Qrcode/index.ts @@ -0,0 +1,3 @@ +import Qrcode from './src/Qrcode.vue' + +export { Qrcode } diff --git a/kinit-admin/src/components/Qrcode/src/Qrcode.vue b/kinit-admin/src/components/Qrcode/src/Qrcode.vue new file mode 100644 index 0000000..7a6ebf8 --- /dev/null +++ b/kinit-admin/src/components/Qrcode/src/Qrcode.vue @@ -0,0 +1,251 @@ + + + + ++ + + diff --git a/kinit-admin/src/components/Screenfull/index.ts b/kinit-admin/src/components/Screenfull/index.ts new file mode 100644 index 0000000..faec2d8 --- /dev/null +++ b/kinit-admin/src/components/Screenfull/index.ts @@ -0,0 +1,3 @@ +import Screenfull from './src/Screenfull.vue' + +export { Screenfull } diff --git a/kinit-admin/src/components/Screenfull/src/Screenfull.vue b/kinit-admin/src/components/Screenfull/src/Screenfull.vue new file mode 100644 index 0000000..32a12e7 --- /dev/null +++ b/kinit-admin/src/components/Screenfull/src/Screenfull.vue @@ -0,0 +1,30 @@ + + + ++ +++++ {{ disabledText }}+++ diff --git a/kinit-admin/src/components/Search/index.ts b/kinit-admin/src/components/Search/index.ts new file mode 100644 index 0000000..fcc6f16 --- /dev/null +++ b/kinit-admin/src/components/Search/index.ts @@ -0,0 +1,3 @@ +import Search from './src/Search.vue' + +export { Search } diff --git a/kinit-admin/src/components/Search/src/Search.vue b/kinit-admin/src/components/Search/src/Search.vue new file mode 100644 index 0000000..c548c53 --- /dev/null +++ b/kinit-admin/src/components/Search/src/Search.vue @@ -0,0 +1,139 @@ + + + + + + ++ ++ + diff --git a/kinit-admin/src/components/Setting/index.ts b/kinit-admin/src/components/Setting/index.ts new file mode 100644 index 0000000..b64c9ad --- /dev/null +++ b/kinit-admin/src/components/Setting/index.ts @@ -0,0 +1,3 @@ +import Setting from './src/Setting.vue' + +export { Setting } diff --git a/kinit-admin/src/components/Setting/src/Setting.vue b/kinit-admin/src/components/Setting/src/Setting.vue new file mode 100644 index 0000000..fd239f2 --- /dev/null +++ b/kinit-admin/src/components/Setting/src/Setting.vue @@ -0,0 +1,301 @@ + + + ++ ++ {{ t('common.query') }} + + ++ {{ t('common.reset') }} + + {{ t(visible ? 'common.shrink' : 'common.expand') }} + ++ ++ ++ + + {{ t('setting.projectSetting') }} + + + + + + diff --git a/kinit-admin/src/components/Setting/src/components/ColorRadioPicker.vue b/kinit-admin/src/components/Setting/src/components/ColorRadioPicker.vue new file mode 100644 index 0000000..bc40e10 --- /dev/null +++ b/kinit-admin/src/components/Setting/src/components/ColorRadioPicker.vue @@ -0,0 +1,65 @@ + + + ++ ++ + +{{ t('setting.theme') }} ++ + + {{ t('setting.layout') }} ++ + + {{ t('setting.systemTheme') }} ++ + + {{ t('setting.headerTheme') }} ++ + + + {{ t('setting.menuTheme') }} ++ + {{ t('setting.interfaceDisplay') }} ++ + + ++{{ t('setting.copy') }} ++++ {{ t('setting.clearAndReset') }} + ++ ++ + + diff --git a/kinit-admin/src/components/Setting/src/components/InterfaceDisplay.vue b/kinit-admin/src/components/Setting/src/components/InterfaceDisplay.vue new file mode 100644 index 0000000..8050939 --- /dev/null +++ b/kinit-admin/src/components/Setting/src/components/InterfaceDisplay.vue @@ -0,0 +1,202 @@ + + + ++ + ++ diff --git a/kinit-admin/src/components/Setting/src/components/LayoutRadioPicker.vue b/kinit-admin/src/components/Setting/src/components/LayoutRadioPicker.vue new file mode 100644 index 0000000..96b1dbe --- /dev/null +++ b/kinit-admin/src/components/Setting/src/components/LayoutRadioPicker.vue @@ -0,0 +1,171 @@ + + + ++ {{ t('setting.breadcrumb') }} ++ ++ + {{ t('setting.breadcrumbIcon') }} ++ ++ + {{ t('setting.hamburgerIcon') }} ++ ++ + {{ t('setting.screenfullIcon') }} ++ ++ + {{ t('setting.sizeIcon') }} ++ ++ + {{ t('setting.localeIcon') }} ++ ++ + {{ t('setting.tagsView') }} ++ ++ + {{ t('setting.tagsViewIcon') }} ++ ++ + {{ t('setting.logo') }} ++ ++ + {{ t('setting.uniqueOpened') }} ++ ++ + {{ t('setting.fixedHeader') }} ++ ++ + {{ t('setting.footer') }} ++ ++ + {{ t('setting.greyMode') }} ++ ++ + {{ t('setting.dynamicRouter') }} +++ + + + ++ + + diff --git a/kinit-admin/src/components/SizeDropdown/index.ts b/kinit-admin/src/components/SizeDropdown/index.ts new file mode 100644 index 0000000..516488d --- /dev/null +++ b/kinit-admin/src/components/SizeDropdown/index.ts @@ -0,0 +1,3 @@ +import SizeDropdown from './src/SizeDropdown.vue' + +export { SizeDropdown } diff --git a/kinit-admin/src/components/SizeDropdown/src/SizeDropdown.vue b/kinit-admin/src/components/SizeDropdown/src/SizeDropdown.vue new file mode 100644 index 0000000..773ad62 --- /dev/null +++ b/kinit-admin/src/components/SizeDropdown/src/SizeDropdown.vue @@ -0,0 +1,39 @@ + + + ++ +++ + diff --git a/kinit-admin/src/components/Sticky/index.ts b/kinit-admin/src/components/Sticky/index.ts new file mode 100644 index 0000000..5e1de45 --- /dev/null +++ b/kinit-admin/src/components/Sticky/index.ts @@ -0,0 +1,3 @@ +import Sticky from './src/Sticky.vue' + +export { Sticky } diff --git a/kinit-admin/src/components/Sticky/src/Sticky.vue b/kinit-admin/src/components/Sticky/src/Sticky.vue new file mode 100644 index 0000000..6906fbc --- /dev/null +++ b/kinit-admin/src/components/Sticky/src/Sticky.vue @@ -0,0 +1,141 @@ + + ++ + + + ++ {{ t(`size.${item}`) }} + +++ diff --git a/kinit-admin/src/components/TabMenu/index.ts b/kinit-admin/src/components/TabMenu/index.ts new file mode 100644 index 0000000..b5fd71c --- /dev/null +++ b/kinit-admin/src/components/TabMenu/index.ts @@ -0,0 +1,3 @@ +import TabMenu from './src/TabMenu.vue' + +export { TabMenu } diff --git a/kinit-admin/src/components/TabMenu/src/TabMenu.vue b/kinit-admin/src/components/TabMenu/src/TabMenu.vue new file mode 100644 index 0000000..061421b --- /dev/null +++ b/kinit-admin/src/components/TabMenu/src/TabMenu.vue @@ -0,0 +1,226 @@ + + + diff --git a/kinit-admin/src/components/TabMenu/src/helper.ts b/kinit-admin/src/components/TabMenu/src/helper.ts new file mode 100644 index 0000000..793f132 --- /dev/null +++ b/kinit-admin/src/components/TabMenu/src/helper.ts @@ -0,0 +1,52 @@ +import { getAllParentPath } from '@/components/Menu/src/helper' +import type { RouteMeta } from 'vue-router' +import { isUrl } from '@/utils/is' +import { cloneDeep } from 'lodash-es' +import { reactive } from 'vue' + +export type TabMapTypes = { + [key: string]: string[] +} + +export const tabPathMap = reactive+++ +sticky+({}) + +export const initTabMap = (routes: AppRouteRecordRaw[]) => { + for (const v of routes) { + const meta = (v.meta ?? {}) as RouteMeta + if (!meta?.hidden) { + tabPathMap[v.path] = [] + } + } +} + +export const filterMenusPath = ( + routes: AppRouteRecordRaw[], + allRoutes: AppRouteRecordRaw[] +): AppRouteRecordRaw[] => { + const res: AppRouteRecordRaw[] = [] + for (const v of routes) { + let data: Nullable = null + const meta = (v.meta ?? {}) as RouteMeta + if (!meta.hidden || meta.canTo) { + const allParentPaht = getAllParentPath (allRoutes, v.path) + + const fullPath = isUrl(v.path) ? v.path : allParentPaht.join('/') + + data = cloneDeep(v) + data.path = fullPath + if (v.children && data) { + data.children = filterMenusPath(v.children, allRoutes) + } + + if (data) { + res.push(data) + } + + if (allParentPaht.length && Reflect.has(tabPathMap, allParentPaht[0])) { + tabPathMap[allParentPaht[0]].push(fullPath) + } + } + } + + return res +} diff --git a/kinit-admin/src/components/Table/index.ts b/kinit-admin/src/components/Table/index.ts new file mode 100644 index 0000000..d734e21 --- /dev/null +++ b/kinit-admin/src/components/Table/index.ts @@ -0,0 +1,11 @@ +import Table from './src/Table.vue' +import { ElTable } from 'element-plus' + +export interface TableExpose { + setProps: (props: Recordable) => void + setColumn: (columnProps: TableSetPropsType[]) => void + selections: Recordable[] + elTableRef: ComponentRef +} + +export { Table } diff --git a/kinit-admin/src/components/Table/src/Table.vue b/kinit-admin/src/components/Table/src/Table.vue new file mode 100644 index 0000000..35905cb --- /dev/null +++ b/kinit-admin/src/components/Table/src/Table.vue @@ -0,0 +1,297 @@ + diff --git a/kinit-admin/src/components/Table/src/helper.ts b/kinit-admin/src/components/Table/src/helper.ts new file mode 100644 index 0000000..d8b34a8 --- /dev/null +++ b/kinit-admin/src/components/Table/src/helper.ts @@ -0,0 +1,8 @@ +export const setIndex = (reserveIndex: boolean, index: number, size: number, current: number) => { + const newIndex = index + 1 + if (reserveIndex) { + return size * (current - 1) + newIndex + } else { + return newIndex + } +} diff --git a/kinit-admin/src/components/Table/src/types.ts b/kinit-admin/src/components/Table/src/types.ts new file mode 100644 index 0000000..58ecd83 --- /dev/null +++ b/kinit-admin/src/components/Table/src/types.ts @@ -0,0 +1,24 @@ +export type TableProps = { + pageSize?: number + currentPage?: number + // 是否多选 + selection?: boolean + // 是否所有的超出隐藏,优先级低于schema中的showOverflowTooltip, + showOverflowTooltip?: boolean + // 表头 + columns?: TableColumn[] + // 是否展示分页 + pagination?: Pagination | undefined + // 仅对 type=selection 的列有效,类型为 Boolean,为 true 则会在数据更新之后保留之前选中的数据(需指定 row-key) + reserveSelection?: boolean + // 加载状态 + loading?: boolean + // 是否叠加索引 + reserveIndex?: boolean + // 对齐方式 + align?: 'left' | 'center' | 'right' + // 表头对齐方式 + headerAlign?: 'left' | 'center' | 'right' + data?: Recordable + expand?: boolean +} & Recordable diff --git a/kinit-admin/src/components/TagsView/index.ts b/kinit-admin/src/components/TagsView/index.ts new file mode 100644 index 0000000..30e604a --- /dev/null +++ b/kinit-admin/src/components/TagsView/index.ts @@ -0,0 +1,3 @@ +import TagsView from './src/TagsView.vue' + +export { TagsView } diff --git a/kinit-admin/src/components/TagsView/src/TagsView.vue b/kinit-admin/src/components/TagsView/src/TagsView.vue new file mode 100644 index 0000000..94afb8a --- /dev/null +++ b/kinit-admin/src/components/TagsView/src/TagsView.vue @@ -0,0 +1,579 @@ + + + + ++ + + diff --git a/kinit-admin/src/components/TagsView/src/helper.ts b/kinit-admin/src/components/TagsView/src/helper.ts new file mode 100644 index 0000000..22f6a50 --- /dev/null +++ b/kinit-admin/src/components/TagsView/src/helper.ts @@ -0,0 +1,21 @@ +import type { RouteMeta, RouteLocationNormalizedLoaded } from 'vue-router' +import { pathResolve } from '@/utils/routerHelper' + +export const filterAffixTags = (routes: AppRouteRecordRaw[], parentPath = '') => { + let tags: RouteLocationNormalizedLoaded[] = [] + routes.forEach((route) => { + const meta = route.meta as RouteMeta + const tagPath = pathResolve(parentPath, route.path) + if (meta?.affix) { + tags.push({ ...route, path: tagPath, fullPath: tagPath } as RouteLocationNormalizedLoaded) + } + if (route.children) { + const tempTags: RouteLocationNormalizedLoaded[] = filterAffixTags(route.children, tagPath) + if (tempTags.length >= 1) { + tags = [...tags, ...tempTags] + } + } + }) + + return tags +} diff --git a/kinit-admin/src/components/ThemeSwitch/index.ts b/kinit-admin/src/components/ThemeSwitch/index.ts new file mode 100644 index 0000000..823a276 --- /dev/null +++ b/kinit-admin/src/components/ThemeSwitch/index.ts @@ -0,0 +1,3 @@ +import ThemeSwitch from './src/ThemeSwitch.vue' + +export { ThemeSwitch } diff --git a/kinit-admin/src/components/ThemeSwitch/src/ThemeSwitch.vue b/kinit-admin/src/components/ThemeSwitch/src/ThemeSwitch.vue new file mode 100644 index 0000000..25221d1 --- /dev/null +++ b/kinit-admin/src/components/ThemeSwitch/src/ThemeSwitch.vue @@ -0,0 +1,41 @@ + + + + +++ + ++ ++++ ++++ ++++ {{ t(item?.meta?.title as string) }} + + + + ++ diff --git a/kinit-admin/src/components/UserInfo/index.ts b/kinit-admin/src/components/UserInfo/index.ts new file mode 100644 index 0000000..c3a34ab --- /dev/null +++ b/kinit-admin/src/components/UserInfo/index.ts @@ -0,0 +1,3 @@ +import UserInfo from './src/UserInfo.vue' + +export { UserInfo } diff --git a/kinit-admin/src/components/UserInfo/src/UserInfo.vue b/kinit-admin/src/components/UserInfo/src/UserInfo.vue new file mode 100644 index 0000000..641fe01 --- /dev/null +++ b/kinit-admin/src/components/UserInfo/src/UserInfo.vue @@ -0,0 +1,67 @@ + + + + + + diff --git a/kinit-admin/src/components/index.ts b/kinit-admin/src/components/index.ts new file mode 100644 index 0000000..4d030c3 --- /dev/null +++ b/kinit-admin/src/components/index.ts @@ -0,0 +1,6 @@ +import type { App } from 'vue' +import { Icon } from './Icon' + +export const setupGlobCom = (app: App++ ++ Archer +
+ + ++ +{{ t('common.document') }}++ +{{ t('common.loginOut') }}+): void => { + app.component('Icon', Icon) +} diff --git a/kinit-admin/src/config/app.ts b/kinit-admin/src/config/app.ts new file mode 100644 index 0000000..2c51654 --- /dev/null +++ b/kinit-admin/src/config/app.ts @@ -0,0 +1,106 @@ +import { useCache } from '@/hooks/web/useCache' + +const { wsCache } = useCache() + +export type LayoutType = 'classic' | 'topLeft' | 'top' | 'cutMenu' + +export type ThemeTypes = { + elColorPrimary?: string + leftMenuBorderColor?: string + leftMenuBgColor?: string + leftMenuBgLightColor?: string + leftMenuBgActiveColor?: string + leftMenuCollapseBgActiveColor?: string + leftMenuTextColor?: string + leftMenuTextActiveColor?: string + logoTitleTextColor?: string + logoBorderColor?: string + topHeaderBgColor?: string + topHeaderTextColor?: string + topHeaderHoverColor?: string + topToolBorderColor?: string +} +export interface AppState { + breadcrumb: boolean + breadcrumbIcon: boolean + collapse: boolean + uniqueOpened: boolean + hamburger: boolean + screenfull: boolean + size: boolean + locale: boolean + tagsView: boolean + tagsViewIcon: boolean + logo: boolean + fixedHeader: boolean + greyMode: boolean + dynamicRouter: boolean + pageLoading: boolean + layout: LayoutType + title: string + userInfo: string + isDark: boolean + currentSize: ElememtPlusSize + sizeMap: ElememtPlusSize[] + mobile: boolean + footer: boolean + theme: ThemeTypes +} + +export const appModules: AppState = { + userInfo: 'userInfo', // 登录信息存储字段-建议每个项目换一个字段,避免与其他项目冲突 + sizeMap: ['default', 'large', 'small'], + mobile: false, // 是否是移动端 + title: import.meta.env.VITE_APP_TITLE, // 标题 + pageLoading: false, // 路由跳转loading + + breadcrumb: true, // 面包屑 + breadcrumbIcon: true, // 面包屑图标 + collapse: false, // 折叠菜单 + uniqueOpened: false, // 是否只保持一个子菜单的展开 + hamburger: true, // 折叠图标 + screenfull: true, // 全屏图标 + size: true, // 尺寸图标 + locale: true, // 多语言图标 + tagsView: true, // 标签页 + tagsViewIcon: true, // 是否显示标签图标 + logo: true, // logo + fixedHeader: true, // 固定toolheader + footer: true, // 显示页脚 + greyMode: false, // 是否开始灰色模式,用于特殊悼念日 + dynamicRouter: wsCache.get('dynamicRouter') || false, // 是否动态路由 + + layout: wsCache.get('layout') || 'classic', // layout布局 + isDark: wsCache.get('isDark') || false, // 是否是暗黑模式 + currentSize: wsCache.get('default') || 'default', // 组件尺寸 + theme: wsCache.get('theme') || { + // 主题色 + elColorPrimary: '#409eff', + // 左侧菜单边框颜色 + leftMenuBorderColor: 'inherit', + // 左侧菜单背景颜色 + leftMenuBgColor: '#001529', + // 左侧菜单浅色背景颜色 + leftMenuBgLightColor: '#0f2438', + // 左侧菜单选中背景颜色 + leftMenuBgActiveColor: 'var(--el-color-primary)', + // 左侧菜单收起选中背景颜色 + leftMenuCollapseBgActiveColor: 'var(--el-color-primary)', + // 左侧菜单字体颜色 + leftMenuTextColor: '#bfcbd9', + // 左侧菜单选中字体颜色 + leftMenuTextActiveColor: '#fff', + // logo字体颜色 + logoTitleTextColor: '#fff', + // logo边框颜色 + logoBorderColor: 'inherit', + // 头部背景颜色 + topHeaderBgColor: '#fff', + // 头部字体颜色 + topHeaderTextColor: 'inherit', + // 头部悬停颜色 + topHeaderHoverColor: '#f6f6f6', + // 头部边框颜色 + topToolBorderColor: '#eee' + } +} diff --git a/kinit-admin/src/config/axios/config.ts b/kinit-admin/src/config/axios/config.ts new file mode 100644 index 0000000..69c2fc0 --- /dev/null +++ b/kinit-admin/src/config/axios/config.ts @@ -0,0 +1,46 @@ +const config: { + base_url: { + base: string + dev: string + pro: string + test: string + } + result_code: number | string + default_headers: AxiosHeaders + request_timeout: number +} = { + /** + * api请求基础路径 + */ + base_url: { + // 开发环境接口前缀 + base: '', + + // 打包开发环境接口前缀 + dev: '', + + // 打包生产环境接口前缀 + pro: '', + + // 打包测试环境接口前缀 + test: '' + }, + + /** + * 接口成功返回状态码 + */ + result_code: '0000', + + /** + * 接口请求超时时间 + */ + request_timeout: 60000, + + /** + * 默认接口请求类型 + * 可选值:application/x-www-form-urlencoded multipart/form-data + */ + default_headers: 'application/json' +} + +export { config } diff --git a/kinit-admin/src/config/axios/index.ts b/kinit-admin/src/config/axios/index.ts new file mode 100644 index 0000000..ab71a45 --- /dev/null +++ b/kinit-admin/src/config/axios/index.ts @@ -0,0 +1,33 @@ +import { service } from './service' + +import { config } from './config' + +const { default_headers } = config + +const request = (option: any) => { + const { url, method, params, data, headersType, responseType } = option + return service({ + url: url, + method, + params, + data, + responseType: responseType, + headers: { + 'Content-Type': headersType || default_headers + } + }) +} +export default { + get: (option: any) => { + return request({ method: 'get', ...option }) as unknown as T + }, + post: (option: any) => { + return request({ method: 'post', ...option }) as unknown as T + }, + delete: (option: any) => { + return request({ method: 'delete', ...option }) as unknown as T + }, + put: (option: any) => { + return request({ method: 'put', ...option }) as unknown as T + } +} diff --git a/kinit-admin/src/config/axios/service.ts b/kinit-admin/src/config/axios/service.ts new file mode 100644 index 0000000..a3cacd9 --- /dev/null +++ b/kinit-admin/src/config/axios/service.ts @@ -0,0 +1,70 @@ +import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios' + +import qs from 'qs' + +import { config } from './config' + +import { ElMessage } from 'element-plus' + +const { result_code, base_url } = config + +export const PATH_URL = base_url[import.meta.env.VITE_API_BASEPATH] + +// 创建axios实例 +const service: AxiosInstance = axios.create({ + baseURL: PATH_URL, // api 的 base_url + timeout: config.request_timeout // 请求超时时间 +}) + +// request拦截器 +service.interceptors.request.use( + (config: AxiosRequestConfig) => { + if ( + config.method === 'post' && + (config.headers as any)['Content-Type'] === 'application/x-www-form-urlencoded' + ) { + config.data = qs.stringify(config.data) + } + // get参数编码 + if (config.method === 'get' && config.params) { + let url = config.url as string + url += '?' + const keys = Object.keys(config.params) + for (const key of keys) { + if (config.params[key] !== void 0 && config.params[key] !== null) { + url += `${key}=${encodeURIComponent(config.params[key])}&` + } + } + url = url.substring(0, url.length - 1) + config.params = {} + config.url = url + } + return config + }, + (error: AxiosError) => { + // Do something with request error + console.log(error) // for debug + Promise.reject(error) + } +) + +// response 拦截器 +service.interceptors.response.use( + (response: AxiosResponse ) => { + if (response.config.responseType === 'blob') { + // 如果是文件流,直接过 + return response + } else if (response.data.code === result_code) { + return response.data + } else { + ElMessage.error(response.data.message) + } + }, + (error: AxiosError) => { + console.log('err' + error) // for debug + ElMessage.error(error.message) + return Promise.reject(error) + } +) + +export { service } diff --git a/kinit-admin/src/config/locale.ts b/kinit-admin/src/config/locale.ts new file mode 100644 index 0000000..c20a3d9 --- /dev/null +++ b/kinit-admin/src/config/locale.ts @@ -0,0 +1,32 @@ +import { useCache } from '@/hooks/web/useCache' +import zhCn from 'element-plus/es/locale/lang/zh-cn' +import en from 'element-plus/es/locale/lang/en' + +const { wsCache } = useCache() + +export const elLocaleMap = { + 'zh-CN': zhCn, + en: en +} +export interface LocaleState { + currentLocale: LocaleDropdownType + localeMap: LocaleDropdownType[] +} + +export const localeModules: LocaleState = { + currentLocale: { + lang: wsCache.get('lang') || 'zh-CN', + elLocale: elLocaleMap[wsCache.get('lang') || 'zh-CN'] + }, + // 多语言 + localeMap: [ + { + lang: 'zh-CN', + name: '简体中文' + }, + { + lang: 'en', + name: 'English' + } + ] +} diff --git a/kinit-admin/src/directives/index.ts b/kinit-admin/src/directives/index.ts new file mode 100644 index 0000000..11b1da8 --- /dev/null +++ b/kinit-admin/src/directives/index.ts @@ -0,0 +1,10 @@ +import type { App } from 'vue' +import { setupPermissionDirective } from './permission/hasPermi' + +/** + * 导出指令:v-xxx + * @methods hasPermi 按钮权限,用法: v-hasPermi + */ +export const setupPermission = (app: App ) => { + setupPermissionDirective(app) +} diff --git a/kinit-admin/src/directives/permission/hasPermi.ts b/kinit-admin/src/directives/permission/hasPermi.ts new file mode 100644 index 0000000..0814c99 --- /dev/null +++ b/kinit-admin/src/directives/permission/hasPermi.ts @@ -0,0 +1,47 @@ +import type { App, Directive, DirectiveBinding } from 'vue' +import { useI18n } from '@/hooks/web/useI18n' +import { useCache } from '@/hooks/web/useCache' +import { intersection } from 'lodash-es' +import { isArray } from '@/utils/is' +import { useAppStoreWithOut } from '@/store/modules/app' + +const { t } = useI18n() +const { wsCache } = useCache() +const appStore = useAppStoreWithOut() + +// 全部权限 +const all_permission = ['*.*.*'] +const hasPermission = (value: string | string[]): boolean => { + const permissions = wsCache.get(appStore.getUserInfo).permissions as string[] + if (!value) { + throw new Error(t('permission.hasPermission')) + } + if (!isArray(value)) { + return permissions?.includes(value as string) + } + if (all_permission[0] === permissions[0]) { + return true + } + return (intersection(value, permissions) as string[]).length > 0 +} +function hasPermi(el: Element, binding: DirectiveBinding) { + const value = binding.value + + const flag = hasPermission(value) + if (!flag) { + el.parentNode?.removeChild(el) + } +} +const mounted = (el: Element, binding: DirectiveBinding ) => { + hasPermi(el, binding) +} + +const permiDirective: Directive = { + mounted +} + +export const setupPermissionDirective = (app: App ) => { + app.directive('hasPermi', permiDirective) +} + +export default permiDirective diff --git a/kinit-admin/src/hooks/event/useScrollTo.ts b/kinit-admin/src/hooks/event/useScrollTo.ts new file mode 100644 index 0000000..74fd673 --- /dev/null +++ b/kinit-admin/src/hooks/event/useScrollTo.ts @@ -0,0 +1,62 @@ +import { ref, unref } from 'vue' + +export interface ScrollToParams { + el: HTMLElement + to: number + position: string + duration?: number + callback?: () => void +} + +const easeInOutQuad = (t: number, b: number, c: number, d: number) => { + t /= d / 2 + if (t < 1) { + return (c / 2) * t * t + b + } + t-- + return (-c / 2) * (t * (t - 2) - 1) + b +} +const move = (el: HTMLElement, position: string, amount: number) => { + el[position] = amount +} + +export function useScrollTo({ + el, + position = 'scrollLeft', + to, + duration = 500, + callback +}: ScrollToParams) { + const isActiveRef = ref(false) + const start = el[position] + const change = to - start + const increment = 20 + let currentTime = 0 + + function animateScroll() { + if (!unref(isActiveRef)) { + return + } + currentTime += increment + const val = easeInOutQuad(currentTime, start, change, duration) + move(el, position, val) + if (currentTime < duration && unref(isActiveRef)) { + requestAnimationFrame(animateScroll) + } else { + if (callback) { + callback() + } + } + } + + function run() { + isActiveRef.value = true + animateScroll() + } + + function stop() { + isActiveRef.value = false + } + + return { start: run, stop } +} diff --git a/kinit-admin/src/hooks/web/useCache.ts b/kinit-admin/src/hooks/web/useCache.ts new file mode 100644 index 0000000..b405ef3 --- /dev/null +++ b/kinit-admin/src/hooks/web/useCache.ts @@ -0,0 +1,17 @@ +/** + * 配置浏览器本地存储的方式,可直接存储对象数组。 + */ + +import WebStorageCache from 'web-storage-cache' + +type CacheType = 'sessionStorage' | 'localStorage' + +export const useCache = (type: CacheType = 'sessionStorage') => { + const wsCache: WebStorageCache = new WebStorageCache({ + storage: type + }) + + return { + wsCache + } +} diff --git a/kinit-admin/src/hooks/web/useConfigGlobal.ts b/kinit-admin/src/hooks/web/useConfigGlobal.ts new file mode 100644 index 0000000..59007d3 --- /dev/null +++ b/kinit-admin/src/hooks/web/useConfigGlobal.ts @@ -0,0 +1,9 @@ +import { inject } from 'vue' + +export const useConfigGlobal = () => { + const configGlobal = inject('configGlobal', {}) as ConfigGlobalTypes + + return { + configGlobal + } +} diff --git a/kinit-admin/src/hooks/web/useCrudSchemas.ts b/kinit-admin/src/hooks/web/useCrudSchemas.ts new file mode 100644 index 0000000..c15dd9c --- /dev/null +++ b/kinit-admin/src/hooks/web/useCrudSchemas.ts @@ -0,0 +1,251 @@ +import { reactive } from 'vue' +import { eachTree, treeMap, filter } from '@/utils/tree' +import { findIndex } from '@/utils' +import { useDictStoreWithOut } from '@/store/modules/dict' +import { useI18n } from '@/hooks/web/useI18n' +import type { AxiosPromise } from 'axios' + +export type CrudSchema = Omit & { + search?: CrudSearchParams + table?: CrudTableParams + form?: CrudFormParams + detail?: CrudDescriptionsParams + children?: CrudSchema[] +} + +type CrudSearchParams = { + // 是否显示在查询项 + show?: boolean + // 字典名称,会去取全局的字典 + dictName?: string + // 接口 + api?: () => Promise +} & Omit + +type CrudTableParams = { + // 是否显示表头 + show?: boolean +} & Omit + +type CrudFormParams = { + // 字典名称,会去取全局的字典 + dictName?: string + // 接口 + api?: () => Promise + // 是否显示表单项 + show?: boolean +} & Omit + +type CrudDescriptionsParams = { + // 是否显示表单项 + show?: boolean +} & Omit + +const dictStore = useDictStoreWithOut() + +const { t } = useI18n() + +interface AllSchemas { + searchSchema: FormSchema[] + tableColumns: TableColumn[] + formSchema: FormSchema[] + detailSchema: DescriptionsSchema[] +} + +// 过滤所有结构 +export const useCrudSchemas = ( + crudSchema: CrudSchema[] +): { + allSchemas: AllSchemas +} => { + // 所有结构数据 + const allSchemas = reactive ({ + searchSchema: [], + tableColumns: [], + formSchema: [], + detailSchema: [] + }) + + const searchSchema = filterSearchSchema(crudSchema, allSchemas) + allSchemas.searchSchema = searchSchema || [] + + const tableColumns = filterTableSchema(crudSchema) + allSchemas.tableColumns = tableColumns || [] + + const formSchema = filterFormSchema(crudSchema, allSchemas) + allSchemas.formSchema = formSchema + + const detailSchema = filterDescriptionsSchema(crudSchema) + allSchemas.detailSchema = detailSchema + + return { + allSchemas + } +} + +// 过滤 Search 结构 +const filterSearchSchema = (crudSchema: CrudSchema[], allSchemas: AllSchemas): FormSchema[] => { + const searchSchema: FormSchema[] = [] + + // 获取字典列表队列 + const searchRequestTask: Array<() => Promise > = [] + + eachTree(crudSchema, (schemaItem: CrudSchema) => { + // 判断是否显示 + if (schemaItem?.search?.show) { + const searchSchemaItem = { + // 默认为 input + component: schemaItem.search.component || 'Input', + componentProps: {}, + ...schemaItem.search, + field: schemaItem.field, + label: schemaItem.search?.label || schemaItem.label + } + + if (searchSchemaItem.dictName) { + // 如果有 dictName 则证明是从字典中获取数据 + const dictArr = dictStore.getDictObj[searchSchemaItem.dictName] + searchSchemaItem.componentProps!.options = filterOptions(dictArr) + } else if (searchSchemaItem.api) { + searchRequestTask.push(async () => { + const res = await (searchSchemaItem.api as () => AxiosPromise)() + if (res) { + const index = findIndex(allSchemas.searchSchema, (v: FormSchema) => { + return v.field === searchSchemaItem.field + }) + if (index !== -1) { + allSchemas.searchSchema[index]!.componentProps!.options = filterOptions( + res, + searchSchemaItem.componentProps.optionsAlias?.labelField + ) + } + } + }) + } + + // 删除不必要的字段 + delete searchSchemaItem.show + delete searchSchemaItem.dictName + + searchSchema.push(searchSchemaItem) + } + }) + + for (const task of searchRequestTask) { + task() + } + + return searchSchema +} + +// 过滤 table 结构 +const filterTableSchema = (crudSchema: CrudSchema[]): TableColumn[] => { + const tableColumns = treeMap (crudSchema, { + conversion: (schema: CrudSchema) => { + if (schema?.table?.show !== false) { + return { + ...schema.table, + ...schema + } + } + } + }) + + // 第一次过滤会有 undefined 所以需要二次过滤 + return filter (tableColumns as TableColumn[], (data) => { + if (data.children === void 0) { + delete data.children + } + return !!data.field + }) +} + +// 过滤 form 结构 +const filterFormSchema = (crudSchema: CrudSchema[], allSchemas: AllSchemas): FormSchema[] => { + const formSchema: FormSchema[] = [] + + // 获取字典列表队列 + const formRequestTask: Array<() => Promise > = [] + + eachTree(crudSchema, (schemaItem: CrudSchema) => { + // 判断是否显示 + if (schemaItem?.form?.show !== false) { + const formSchemaItem = { + // 默认为 input + component: schemaItem?.form?.component || 'Input', + componentProps: {}, + ...schemaItem.form, + field: schemaItem.field, + label: schemaItem.search?.label || schemaItem.label + } + + if (formSchemaItem.dictName) { + // 如果有 dictName 则证明是从字典中获取数据 + const dictArr = dictStore.getDictObj[formSchemaItem.dictName] + formSchemaItem.componentProps!.options = filterOptions(dictArr) + } else if (formSchemaItem.api) { + formRequestTask.push(async () => { + const res = await (formSchemaItem.api as () => AxiosPromise)() + if (res) { + const index = findIndex(allSchemas.formSchema, (v: FormSchema) => { + return v.field === formSchemaItem.field + }) + if (index !== -1) { + allSchemas.formSchema[index]!.componentProps!.options = filterOptions( + res, + formSchemaItem.componentProps.optionsAlias?.labelField + ) + } + } + }) + } + + // 删除不必要的字段 + delete formSchemaItem.show + delete formSchemaItem.dictName + + formSchema.push(formSchemaItem) + } + }) + + for (const task of formRequestTask) { + task() + } + console.log(formSchema) + return formSchema +} + +// 过滤 descriptions 结构 +const filterDescriptionsSchema = (crudSchema: CrudSchema[]): DescriptionsSchema[] => { + const descriptionsSchema: FormSchema[] = [] + + eachTree(crudSchema, (schemaItem: CrudSchema) => { + // 判断是否显示 + if (schemaItem?.detail?.show !== false) { + const descriptionsSchemaItem = { + ...schemaItem.detail, + field: schemaItem.field, + label: schemaItem.detail?.label || schemaItem.label + } + + // 删除不必要的字段 + delete descriptionsSchemaItem.show + + descriptionsSchema.push(descriptionsSchemaItem) + } + }) + + return descriptionsSchema +} + +// 给options添加国际化 +const filterOptions = (options: Recordable, labelField?: string) => { + return options.map((v: Recordable) => { + if (labelField) { + v['labelField'] = t(v.labelField) + } else { + v['label'] = t(v.label) + } + return v + }) +} diff --git a/kinit-admin/src/hooks/web/useDesign.ts b/kinit-admin/src/hooks/web/useDesign.ts new file mode 100644 index 0000000..1ec349f --- /dev/null +++ b/kinit-admin/src/hooks/web/useDesign.ts @@ -0,0 +1,18 @@ +import variables from '@/styles/variables.module.less' + +export const useDesign = () => { + const lessVariables = variables + + /** + * @param scope 类名 + * @returns 返回空间名-类名 + */ + const getPrefixCls = (scope: string) => { + return `${lessVariables.namespace}-${scope}` + } + + return { + variables: lessVariables, + getPrefixCls + } +} diff --git a/kinit-admin/src/hooks/web/useEmitt.ts b/kinit-admin/src/hooks/web/useEmitt.ts new file mode 100644 index 0000000..26b5d62 --- /dev/null +++ b/kinit-admin/src/hooks/web/useEmitt.ts @@ -0,0 +1,23 @@ +import mitt from 'mitt' +import { onBeforeUnmount } from 'vue' + +interface Option { + name: string // 事件名称 + callback: Fn // 回调 +} + +const emitter = mitt() + +export const useEmitt = (option?: Option) => { + if (option) { + emitter.on(option.name, option.callback) + + onBeforeUnmount(() => { + emitter.off(option.name) + }) + } + + return { + emitter + } +} diff --git a/kinit-admin/src/hooks/web/useForm.ts b/kinit-admin/src/hooks/web/useForm.ts new file mode 100644 index 0000000..21d2186 --- /dev/null +++ b/kinit-admin/src/hooks/web/useForm.ts @@ -0,0 +1,91 @@ +import type { Form, FormExpose } from '@/components/Form' +import type { ElForm } from 'element-plus' +import { ref, unref, nextTick } from 'vue' +import type { FormProps } from '@/components/Form/src/types' + +export const useForm = (props?: FormProps) => { + // From实例 + const formRef = ref () + + // ElForm实例 + const elFormRef = ref >() + + /** + * @param ref Form实例 + * @param elRef ElForm实例 + */ + const register = (ref: typeof Form & FormExpose, elRef: ComponentRef ) => { + formRef.value = ref + elFormRef.value = elRef + } + + const getForm = async () => { + await nextTick() + const form = unref(formRef) + if (!form) { + console.error('The form is not registered. Please use the register method to register') + } + return form + } + + // 一些内置的方法 + const methods: { + setProps: (props: Recordable) => void + setValues: (data: Recordable) => void + getFormData: () => Promise + setSchema: (schemaProps: FormSetPropsType[]) => void + addSchema: (formSchema: FormSchema, index?: number) => void + delSchema: (field: string) => void + } = { + setProps: async (props: FormProps = {}) => { + const form = await getForm() + form?.setProps(props) + }, + + setValues: async (data: Recordable) => { + const form = await getForm() + form?.setValues(data) + }, + + /** + * @param schemaProps 需要设置的schemaProps + */ + setSchema: async (schemaProps: FormSetPropsType[]) => { + const form = await getForm() + form?.setSchema(schemaProps) + }, + + /** + * @param formSchema 需要新增数据 + * @param index 在哪里新增 + */ + addSchema: async (formSchema: FormSchema, index?: number) => { + const form = await getForm() + form?.addSchema(formSchema, index) + }, + + /** + * @param field 删除哪个数据 + */ + delSchema: async (field: string) => { + const form = await getForm() + form?.delSchema(field) + }, + + /** + * @returns form data + */ + getFormData: async (): Promise => { + const form = await getForm() + return form?.formModel as T + } + } + + props && methods.setProps(props) + + return { + register, + elFormRef, + methods + } +} diff --git a/kinit-admin/src/hooks/web/useI18n.ts b/kinit-admin/src/hooks/web/useI18n.ts new file mode 100644 index 0000000..f1e0e7b --- /dev/null +++ b/kinit-admin/src/hooks/web/useI18n.ts @@ -0,0 +1,52 @@ +import { i18n } from '@/plugins/vueI18n' + +type I18nGlobalTranslation = { + (key: string): string + (key: string, locale: string): string + (key: string, locale: string, list: unknown[]): string + (key: string, locale: string, named: Record ): string + (key: string, list: unknown[]): string + (key: string, named: Record ): string +} + +type I18nTranslationRestParameters = [string, any] + +const getKey = (namespace: string | undefined, key: string) => { + if (!namespace) { + return key + } + if (key.startsWith(namespace)) { + return key + } + return `${namespace}.${key}` +} + +export const useI18n = ( + namespace?: string +): { + t: I18nGlobalTranslation +} => { + const normalFn = { + t: (key: string) => { + return getKey(namespace, key) + } + } + + if (!i18n) { + return normalFn + } + + const { t, ...methods } = i18n.global + + const tFn: I18nGlobalTranslation = (key: string, ...arg: any[]) => { + if (!key) return '' + if (!key.includes('.') && !namespace) return key + return (t as any)(getKey(namespace, key), ...(arg as I18nTranslationRestParameters)) + } + return { + ...methods, + t: tFn + } +} + +export const t = (key: string) => key diff --git a/kinit-admin/src/hooks/web/useIcon.ts b/kinit-admin/src/hooks/web/useIcon.ts new file mode 100644 index 0000000..b9a5ccb --- /dev/null +++ b/kinit-admin/src/hooks/web/useIcon.ts @@ -0,0 +1,7 @@ +import { h } from 'vue' +import type { VNode } from 'vue' +import { Icon } from '@/components/Icon' + +export const useIcon = (props: IconTypes): VNode => { + return h(Icon, props) +} diff --git a/kinit-admin/src/hooks/web/useIntro.ts b/kinit-admin/src/hooks/web/useIntro.ts new file mode 100644 index 0000000..85604df --- /dev/null +++ b/kinit-admin/src/hooks/web/useIntro.ts @@ -0,0 +1,47 @@ +import introJs from 'intro.js' +import { IntroJs, Step, Options } from 'intro.js' +import 'intro.js/introjs.css' +import { useI18n } from '@/hooks/web/useI18n' +import { useDesign } from '@/hooks/web/useDesign' + +export const useIntro = (setps?: Step[], options?: Options) => { + const { t } = useI18n() + + const { variables } = useDesign() + + const defaultSetps: Step[] = setps || [ + { + element: `#${variables.namespace}-menu`, + title: t('common.menu'), + intro: t('common.menuDes'), + position: 'right' + }, + { + element: `#${variables.namespace}-tool-header`, + title: t('common.tool'), + intro: t('common.toolDes'), + position: 'left' + }, + { + element: `#${variables.namespace}-tags-view`, + title: t('common.tagsView'), + intro: t('common.tagsViewDes'), + position: 'bottom' + } + ] + + const defaultOptions: Options = options || { + prevLabel: t('common.prevLabel'), + nextLabel: t('common.nextLabel'), + skipLabel: t('common.skipLabel'), + doneLabel: t('common.doneLabel') + } + + const introRef: IntroJs = introJs() + + introRef.addSteps(defaultSetps).setOptions(defaultOptions) + + return { + introRef + } +} diff --git a/kinit-admin/src/hooks/web/useLocale.ts b/kinit-admin/src/hooks/web/useLocale.ts new file mode 100644 index 0000000..c65070e --- /dev/null +++ b/kinit-admin/src/hooks/web/useLocale.ts @@ -0,0 +1,35 @@ +import { i18n } from '@/plugins/vueI18n' +import { useLocaleStoreWithOut } from '@/store/modules/locale' +import { setHtmlPageLang } from '@/plugins/vueI18n/helper' + +const setI18nLanguage = (locale: LocaleType) => { + const localeStore = useLocaleStoreWithOut() + + if (i18n.mode === 'legacy') { + i18n.global.locale = locale + } else { + ;(i18n.global.locale as any).value = locale + } + localeStore.setCurrentLocale({ + lang: locale + }) + setHtmlPageLang(locale) +} + +export const useLocale = () => { + // Switching the language will change the locale of useI18n + // And submit to configuration modification + const changeLocale = async (locale: LocaleType) => { + const globalI18n = i18n.global + + const langModule = await import(`../../locales/${locale}.ts`) + + globalI18n.setLocaleMessage(locale, langModule.default) + + setI18nLanguage(locale) + } + + return { + changeLocale + } +} diff --git a/kinit-admin/src/hooks/web/useNProgress.ts b/kinit-admin/src/hooks/web/useNProgress.ts new file mode 100644 index 0000000..28990e7 --- /dev/null +++ b/kinit-admin/src/hooks/web/useNProgress.ts @@ -0,0 +1,34 @@ +import { nextTick, unref } from 'vue' +import type { NProgressOptions } from 'nprogress' +import NProgress from 'nprogress' +import 'nprogress/nprogress.css' +import { useCssVar } from '@vueuse/core' + +const primaryColor = useCssVar('--el-color-primary', document.documentElement) + +export const useNProgress = () => { + NProgress.configure({ showSpinner: false } as NProgressOptions) + + const initColor = async () => { + await nextTick() + const bar = document.getElementById('nprogress')?.getElementsByClassName('bar')[0] as ElRef + if (bar) { + bar.style.background = unref(primaryColor.value) + } + } + + initColor() + + const start = () => { + NProgress.start() + } + + const done = () => { + NProgress.done() + } + + return { + start, + done + } +} diff --git a/kinit-admin/src/hooks/web/usePageLoading.ts b/kinit-admin/src/hooks/web/usePageLoading.ts new file mode 100644 index 0000000..bb89457 --- /dev/null +++ b/kinit-admin/src/hooks/web/usePageLoading.ts @@ -0,0 +1,18 @@ +import { useAppStoreWithOut } from '@/store/modules/app' + +const appStore = useAppStoreWithOut() + +export const usePageLoading = () => { + const loadStart = () => { + appStore.setPageLoading(true) + } + + const loadDone = () => { + appStore.setPageLoading(false) + } + + return { + loadStart, + loadDone + } +} diff --git a/kinit-admin/src/hooks/web/useTable.ts b/kinit-admin/src/hooks/web/useTable.ts new file mode 100644 index 0000000..9a4c1b4 --- /dev/null +++ b/kinit-admin/src/hooks/web/useTable.ts @@ -0,0 +1,191 @@ +import { Table, TableExpose } from '@/components/Table' +import { ElTable, ElMessageBox, ElMessage } from 'element-plus' +import { ref, reactive, watch, computed, unref, nextTick } from 'vue' +import { get } from 'lodash-es' +import type { TableProps } from '@/components/Table/src/types' +import { useI18n } from '@/hooks/web/useI18n' + +const { t } = useI18n() + +interface TableResponse { + total: number + list: T[] + pageNumber: number + pageSize: number +} + +interface UseTableConfig { + getListApi: (option: any) => Promise >> + delListApi?: (option: any) => Promise + // 返回数据格式配置 + response: { + list: string + total?: string + } + props?: TableProps +} + +interface TableObject { + pageSize: number + currentPage: number + total: number + tableList: T[] + params: any + loading: boolean + currentRow: Nullable +} + +export const useTable = (config?: UseTableConfig ) => { + const tableObject = reactive >({ + // 页数 + pageSize: 10, + // 当前页 + currentPage: 1, + // 总条数 + total: 10, + // 表格数据 + tableList: [], + // AxiosConfig 配置 + params: {}, + // 加载中 + loading: true, + // 当前行的数据 + currentRow: null + }) + + const paramsObj = computed(() => { + return { + ...tableObject.params, + pageSize: tableObject.pageSize, + pageIndex: tableObject.currentPage + } + }) + + watch( + () => tableObject.currentPage, + () => { + methods.getList() + } + ) + + watch( + () => tableObject.pageSize, + () => { + // 当前页不为1时,修改页数后会导致多次调用getList方法 + if (tableObject.currentPage === 1) { + methods.getList() + } else { + tableObject.currentPage = 1 + methods.getList() + } + } + ) + + // Table实例 + const tableRef = ref () + + // ElTable实例 + const elTableRef = ref >() + + const register = (ref: typeof Table & TableExpose, elRef: ComponentRef ) => { + tableRef.value = ref + elTableRef.value = unref(elRef) + } + + const getTable = async () => { + await nextTick() + const table = unref(tableRef) + if (!table) { + console.error('The table is not registered. Please use the register method to register') + } + return table + } + + const delData = async (ids: string[] | number[]) => { + const res = await (config?.delListApi && config?.delListApi(ids)) + if (res) { + ElMessage.success(t('common.delSuccess')) + + // 计算出临界点 + const currentPage = + tableObject.total % tableObject.pageSize === ids.length || tableObject.pageSize === 1 + ? tableObject.currentPage > 1 + ? tableObject.currentPage - 1 + : tableObject.currentPage + : tableObject.currentPage + + tableObject.currentPage = currentPage + methods.getList() + } + } + + const methods = { + getList: async () => { + tableObject.loading = true + const res = await config?.getListApi(unref(paramsObj)).finally(() => { + tableObject.loading = false + }) + if (res) { + tableObject.tableList = get(res.data || {}, config?.response.list as string) + tableObject.total = get(res.data || {}, config?.response?.total as string) || 0 + } + }, + setProps: async (props: TableProps = {}) => { + const table = await getTable() + table?.setProps(props) + }, + setColumn: async (columnProps: TableSetPropsType[]) => { + const table = await getTable() + table?.setColumn(columnProps) + }, + getSelections: async () => { + const table = await getTable() + return (table?.selections || []) as T[] + }, + // 与Search组件结合 + setSearchParams: (data: Recordable) => { + tableObject.currentPage = 1 + tableObject.params = Object.assign(tableObject.params, { + pageSize: tableObject.pageSize, + pageIndex: tableObject.currentPage, + ...data + }) + methods.getList() + }, + // 删除数据 + delList: async (ids: string[] | number[], multiple: boolean, message = true) => { + const tableRef = await getTable() + if (multiple) { + if (!tableRef?.selections.length) { + ElMessage.warning(t('common.delNoData')) + return + } + } else { + if (!tableObject.currentRow) { + ElMessage.warning(t('common.delNoData')) + return + } + } + if (message) { + ElMessageBox.confirm(t('common.delMessage'), t('common.delWarning'), { + confirmButtonText: t('common.delOk'), + cancelButtonText: t('common.delCancel'), + type: 'warning' + }).then(async () => { + await delData(ids) + }) + } else { + await delData(ids) + } + } + } + + config?.props && methods.setProps(config.props) + + return { + register, + elTableRef, + tableObject, + methods + } +} diff --git a/kinit-admin/src/hooks/web/useTimeAgo.ts b/kinit-admin/src/hooks/web/useTimeAgo.ts new file mode 100644 index 0000000..6dc7123 --- /dev/null +++ b/kinit-admin/src/hooks/web/useTimeAgo.ts @@ -0,0 +1,48 @@ +import { useTimeAgo as useTimeAgoCore, UseTimeAgoMessages } from '@vueuse/core' +import { computed, unref } from 'vue' +import { useLocaleStoreWithOut } from '@/store/modules/locale' + +const TIME_AGO_MESSAGE_MAP: { + 'zh-CN': UseTimeAgoMessages + en: UseTimeAgoMessages +} = { + 'zh-CN': { + justNow: '刚刚', + past: (n) => (n.match(/\d/) ? `${n}前` : n), + future: (n) => (n.match(/\d/) ? `${n}后` : n), + month: (n, past) => (n === 1 ? (past ? '上个月' : '下个月') : `${n} 个月`), + year: (n, past) => (n === 1 ? (past ? '去年' : '明年') : `${n} 年`), + day: (n, past) => (n === 1 ? (past ? '昨天' : '明天') : `${n} 天`), + week: (n, past) => (n === 1 ? (past ? '上周' : '下周') : `${n} 周`), + hour: (n) => `${n} 小时`, + minute: (n) => `${n} 分钟`, + second: (n) => `${n} 秒` + }, + en: { + justNow: '刚刚', + past: (n) => (n.match(/\d/) ? `${n} ago` : n), + future: (n) => (n.match(/\d/) ? `in ${n}` : n), + month: (n, past) => + n === 1 ? (past ? 'last month' : 'next month') : `${n} month${n > 1 ? 's' : ''}`, + year: (n, past) => + n === 1 ? (past ? 'last year' : 'next year') : `${n} year${n > 1 ? 's' : ''}`, + day: (n, past) => (n === 1 ? (past ? 'yesterday' : 'tomorrow') : `${n} day${n > 1 ? 's' : ''}`), + week: (n, past) => + n === 1 ? (past ? 'last week' : 'next week') : `${n} week${n > 1 ? 's' : ''}`, + hour: (n) => `${n} hour${n > 1 ? 's' : ''}`, + minute: (n) => `${n} minute${n > 1 ? 's' : ''}`, + second: (n) => `${n} second${n > 1 ? 's' : ''}` + } +} + +export const useTimeAgo = (time: Date | number | string) => { + const localeStore = useLocaleStoreWithOut() + + const currentLocale = computed(() => localeStore.getCurrentLocale) + + const timeAgo = useTimeAgoCore(time, { + messages: TIME_AGO_MESSAGE_MAP[unref(currentLocale).lang] + }) + + return timeAgo +} diff --git a/kinit-admin/src/hooks/web/useTitle.ts b/kinit-admin/src/hooks/web/useTitle.ts new file mode 100644 index 0000000..d0eb188 --- /dev/null +++ b/kinit-admin/src/hooks/web/useTitle.ts @@ -0,0 +1,25 @@ +import { watch, ref } from 'vue' +import { isString } from '@/utils/is' +import { useAppStoreWithOut } from '@/store/modules/app' +import { useI18n } from '@/hooks/web/useI18n' + +const appStore = useAppStoreWithOut() + +export const useTitle = (newTitle?: string) => { + const { t } = useI18n() + const title = ref( + newTitle ? `${appStore.getTitle} - ${t(newTitle as string)}` : appStore.getTitle + ) + + watch( + title, + (n, o) => { + if (isString(n) && n !== o && document) { + document.title = n + } + }, + { immediate: true } + ) + + return title +} diff --git a/kinit-admin/src/hooks/web/useValidator.ts b/kinit-admin/src/hooks/web/useValidator.ts new file mode 100644 index 0000000..a0d36c3 --- /dev/null +++ b/kinit-admin/src/hooks/web/useValidator.ts @@ -0,0 +1,64 @@ +import { useI18n } from '@/hooks/web/useI18n' + +const { t } = useI18n() + +type Callback = (error?: string | Error | undefined) => void + +interface LengthRange { + min: number + max: number + message: string +} + +export const useValidator = () => { + const required = (message?: string) => { + return { + required: true, + message: message || t('common.required') + } + } + + const lengthRange = (val: any, callback: Callback, options: LengthRange) => { + const { min, max, message } = options + if (val.length < min || val.length > max) { + callback(new Error(message)) + } else { + callback() + } + } + + const notSpace = (val: any, callback: Callback, message: string) => { + // 用户名不能有空格 + if (val.indexOf(' ') !== -1) { + callback(new Error(message)) + } else { + callback() + } + } + + const notSpecialCharacters = (val: any, callback: Callback, message: string) => { + // 密码不能是特殊字符 + if (/[`~!@#$%^&*()_+<>?:"{},.\/;'[\]]/gi.test(val)) { + callback(new Error(message)) + } else { + callback() + } + } + + // 两个字符串是否想等 + const isEqual = (val1: string, val2: string, callback: Callback, message: string) => { + if (val1 === val2) { + callback() + } else { + callback(new Error(message)) + } + } + + return { + required, + lengthRange, + notSpace, + notSpecialCharacters, + isEqual + } +} diff --git a/kinit-admin/src/hooks/web/useWatermark.ts b/kinit-admin/src/hooks/web/useWatermark.ts new file mode 100644 index 0000000..4a31359 --- /dev/null +++ b/kinit-admin/src/hooks/web/useWatermark.ts @@ -0,0 +1,55 @@ +const domSymbol = Symbol('watermark-dom') + +export function useWatermark(appendEl: HTMLElement | null = document.body) { + let func: Fn = () => {} + const id = domSymbol.toString() + const clear = () => { + const domId = document.getElementById(id) + if (domId) { + const el = appendEl + el && el.removeChild(domId) + } + window.removeEventListener('resize', func) + } + const createWatermark = (str: string) => { + clear() + + const can = document.createElement('canvas') + can.width = 300 + can.height = 240 + + const cans = can.getContext('2d') + if (cans) { + cans.rotate((-20 * Math.PI) / 120) + cans.font = '15px Vedana' + cans.fillStyle = 'rgba(0, 0, 0, 0.15)' + cans.textAlign = 'left' + cans.textBaseline = 'middle' + cans.fillText(str, can.width / 20, can.height) + } + + const div = document.createElement('div') + div.id = id + div.style.pointerEvents = 'none' + div.style.top = '0px' + div.style.left = '0px' + div.style.position = 'absolute' + div.style.zIndex = '100000000' + div.style.width = document.documentElement.clientWidth + 'px' + div.style.height = document.documentElement.clientHeight + 'px' + div.style.background = 'url(' + can.toDataURL('image/png') + ') left top repeat' + const el = appendEl + el && el.appendChild(div) + return id + } + + function setWatermark(str: string) { + createWatermark(str) + func = () => { + createWatermark(str) + } + window.addEventListener('resize', func) + } + + return { setWatermark, clear } +} diff --git a/kinit-admin/src/layout/Layout.vue b/kinit-admin/src/layout/Layout.vue new file mode 100644 index 0000000..324da7e --- /dev/null +++ b/kinit-admin/src/layout/Layout.vue @@ -0,0 +1,78 @@ + + + diff --git a/kinit-admin/src/layout/components/AppView.vue b/kinit-admin/src/layout/components/AppView.vue new file mode 100644 index 0000000..ace76b6 --- /dev/null +++ b/kinit-admin/src/layout/components/AppView.vue @@ -0,0 +1,52 @@ + + + + + + + diff --git a/kinit-admin/src/layout/components/ToolHeader.vue b/kinit-admin/src/layout/components/ToolHeader.vue new file mode 100644 index 0000000..091a25a --- /dev/null +++ b/kinit-admin/src/layout/components/ToolHeader.vue @@ -0,0 +1,83 @@ + + + diff --git a/kinit-admin/src/layout/components/useRenderLayout.tsx b/kinit-admin/src/layout/components/useRenderLayout.tsx new file mode 100644 index 0000000..9e5f744 --- /dev/null +++ b/kinit-admin/src/layout/components/useRenderLayout.tsx @@ -0,0 +1,263 @@ +import { computed } from 'vue' +import { useAppStore } from '@/store/modules/app' +import { Menu } from '@/components/Menu' +import { TabMenu } from '@/components/TabMenu' +import { TagsView } from '@/components/TagsView' +import { Logo } from '@/components/Logo' +import AppView from './AppView.vue' +import ToolHeader from './ToolHeader.vue' +import { ElScrollbar } from 'element-plus' +import { useDesign } from '@/hooks/web/useDesign' + +const { getPrefixCls } = useDesign() + +const prefixCls = getPrefixCls('layout') + +const appStore = useAppStore() + +const pageLoading = computed(() => appStore.getPageLoading) + +// 标签页 +const tagsView = computed(() => appStore.getTagsView) + +// 菜单折叠 +const collapse = computed(() => appStore.getCollapse) + +// logo +const logo = computed(() => appStore.logo) + +// 固定头部 +const fixedHeader = computed(() => appStore.getFixedHeader) + +// 是否是移动端 +const mobile = computed(() => appStore.getMobile) + +export const useRenderLayout = () => { + const renderClassic = () => { + return ( + <> ++ + ++ + ++ + {logo.value ? ( +++ ) : undefined} + + ++ > + ) + } + + const renderTopLeft = () => { + return ( + <> ++ +++ ++ + {tagsView.value ? ( + + ) : undefined} + + + {logo.value ?+: undefined} + + + + ++ > + ) + } + + const renderTop = () => { + return ( + <> ++++ {tagsView.value ? ( + ++ ) : undefined} + + + + {logo.value ?+: undefined} + + + ++ > + ) + } + + const renderCutMenu = () => { + return ( + <> ++ {tagsView.value ? ( + ++ ) : undefined} + + + + {logo.value ?+: undefined} + + + ++ > + ) + } + + return { + renderClassic, + renderTopLeft, + renderTop, + renderCutMenu + } +} diff --git a/kinit-admin/src/locales/en.ts b/kinit-admin/src/locales/en.ts new file mode 100644 index 0000000..6f6ec58 --- /dev/null +++ b/kinit-admin/src/locales/en.ts @@ -0,0 +1,441 @@ +export default { + common: { + inputText: 'Please input', + selectText: 'Please select', + startTimeText: 'Start time', + endTimeText: 'End time', + login: 'Login', + required: 'This is required', + loginOut: 'Login out', + document: 'Document', + reminder: 'Reminder', + loginOutMessage: 'Exit the system?', + back: 'Back', + ok: 'OK', + cancel: 'Cancel', + reload: 'Reload current', + closeTab: 'Close current', + closeTheLeftTab: 'Close left', + closeTheRightTab: 'Close right', + closeOther: 'Close other', + closeAll: 'Close all', + prevLabel: 'Prev', + nextLabel: 'Next', + skipLabel: 'Jump', + doneLabel: 'End', + menu: 'Menu', + menuDes: 'Menu bar rendered in routed structure', + collapse: 'Collapse', + collapseDes: 'Expand and zoom the menu bar', + tagsView: 'Tags view', + tagsViewDes: 'Used to record routing history', + tool: 'Tool', + toolDes: 'Used to set up custom systems', + query: 'Query', + reset: 'Reset', + shrink: 'Put away', + expand: 'Expand', + delMessage: 'Delete the selected data?', + delWarning: 'Warning', + delOk: 'OK', + delCancel: 'Cancel', + delNoData: 'Please select the data to delete', + delSuccess: 'Deleted successfully' + }, + error: { + noPermission: `Sorry, you don't have permission to access this page.`, + pageError: 'Sorry, the page you visited does not exist.', + networkError: 'Sorry, the server reported an error.', + returnToHome: 'Return to home' + }, + setting: { + projectSetting: 'Project setting', + theme: 'Theme', + layout: 'Layout', + systemTheme: 'System theme', + menuTheme: 'Menu theme', + interfaceDisplay: 'Interface display', + breadcrumb: 'Breadcrumb', + breadcrumbIcon: 'Breadcrumb icon', + collapseMenu: 'Collapse menu', + hamburgerIcon: 'Hamburger icon', + screenfullIcon: 'Screenfull icon', + sizeIcon: 'Size icon', + localeIcon: 'Locale icon', + tagsView: 'Tags view', + logo: 'Logo', + greyMode: 'Grey mode', + fixedHeader: 'Fixed header', + headerTheme: 'Header theme', + cutMenu: 'Cut Menu', + copy: 'Copy', + clearAndReset: 'Clear cache and reset', + copySuccess: 'Copy success', + copyFailed: 'Copy failed', + footer: 'Footer', + uniqueOpened: 'Unique opened', + tagsViewIcon: 'Tags view icon', + dynamicRouter: 'Dynamic router', + reExperienced: 'Please exit the login experience again' + }, + size: { + default: 'Default', + large: 'Large', + small: 'Small' + }, + login: { + welcome: 'Welcome to the system', + message: 'Backstage management system', + username: 'Username', + password: 'Password', + register: 'Register', + checkPassword: 'Confirm password', + login: 'Sign in', + otherLogin: 'Sign in with', + remember: 'Remember me', + hasUser: 'Existing account? Go to login', + forgetPassword: 'Forget password', + usernamePlaceholder: 'Please input username', + passwordPlaceholder: 'Please input password', + code: 'Verification code', + codePlaceholder: 'Please input verification code' + }, + router: { + login: 'Login', + level: 'Multi level menu', + menu: 'Menu', + menu1: 'Menu1', + menu11: 'Menu1-1', + menu111: 'Menu1-1-1', + menu12: 'Menu1-2', + menu2: 'Menu2', + dashboard: 'Dashboard', + analysis: 'Analysis', + workplace: 'Workplace', + guide: 'Guide', + component: 'Component', + icon: 'Icon', + echart: 'Echart', + countTo: 'Count to', + watermark: 'Watermark', + qrcode: 'Qrcode', + highlight: 'Highlight', + infotip: 'Infotip', + form: 'Form', + defaultForm: 'All examples', + search: 'Search', + table: 'Table', + defaultTable: 'Basic example', + editor: 'Editor', + richText: 'Rich text', + dialog: 'Dialog', + imageViewer: 'Image viewer', + descriptions: 'Descriptions', + example: 'Example', + exampleDialog: 'Example dialog', + examplePage: 'Example page', + exampleAdd: 'Example page - add', + exampleEdit: 'Example page - edit', + exampleDetail: 'Example page - detail', + errorPage: 'Error page', + authorization: 'Authorization', + user: 'User management', + role: 'Role management', + document: 'Document', + inputPassword: 'InputPassword', + sticky: 'Sticky' + }, + permission: { + hasPermission: 'Please set the operation permission value' + }, + analysis: { + newUser: 'New user', + unreadInformation: 'Unread information', + transactionAmount: 'Transaction amount', + totalShopping: 'Total Shopping', + monthlySales: 'Monthly sales', + userAccessSource: 'User access source', + january: 'January', + february: 'February', + march: 'March', + april: 'April', + may: 'May', + june: 'June', + july: 'July', + august: 'August', + september: 'September', + october: 'October', + november: 'November', + december: 'December', + estimate: 'Estimate', + actual: 'Actual', + directAccess: 'Airect access', + mailMarketing: 'Mail marketing', + allianceAdvertising: 'Alliance advertising', + videoAdvertising: 'Video advertising', + searchEngines: 'Search engines', + weeklyUserActivity: 'Weekly user activity', + activeQuantity: 'Active quantity', + monday: 'Monday', + tuesday: 'Tuesday', + wednesday: 'Wednesday', + thursday: 'Thursday', + friday: 'Friday', + saturday: 'Saturday', + sunday: 'Sunday' + }, + workplace: { + goodMorning: 'Good morning', + happyDay: 'Wish you happy every day!', + toady: `It's sunny today`, + project: 'Project', + access: 'Project access', + toDo: 'To do', + introduction: 'A serious introduction', + more: 'More', + shortcutOperation: 'Shortcut operation', + operation: 'Operation', + index: 'Index', + personal: 'Personal', + team: 'Team', + quote: 'Quote', + contribution: 'Contribution', + hot: 'Hot', + yield: 'Yield', + dynamic: 'Dynamic', + push: 'push', + pushCode: 'Archer push code to Github', + follow: 'Follow' + }, + formDemo: { + input: 'Input', + inputNumber: 'InputNumber', + default: 'Default', + icon: 'Icon', + mixed: 'Mixed', + textarea: 'Textarea', + slot: 'Slot', + position: 'Position', + autocomplete: 'Autocomplete', + select: 'Select', + selectGroup: 'Select Group', + selectV2: 'SelectV2', + cascader: 'Cascader', + switch: 'Switch', + rate: 'Rate', + colorPicker: 'Color Picker', + transfer: 'Transfer', + render: 'Render', + radio: 'Radio', + button: 'Button', + checkbox: 'Checkbox', + slider: 'Slider', + datePicker: 'Date Picker', + shortcuts: 'Shortcuts', + today: 'Today', + yesterday: 'Yesterday', + aWeekAgo: 'A week ago', + week: 'Week', + year: 'Year', + month: 'Month', + dates: 'Dates', + daterange: 'Date Range', + monthrange: 'Month Range', + dateTimePicker: 'DateTimePicker', + dateTimerange: 'Datetime Range', + timePicker: 'Time Picker', + timeSelect: 'Time Select', + inputPassword: 'input Password', + passwordStrength: 'Password Strength', + defaultForm: 'All examples', + formDes: + 'The secondary encapsulation of form components based on ElementPlus realizes data-driven and supports all Form parameters', + example: 'example', + operate: 'operate', + change: 'Change', + restore: 'Restore', + disabled: 'Disabled', + disablement: 'Disablement', + delete: 'Delete', + add: 'Add', + setValue: 'Set value', + resetValue: 'Reset value', + set: 'Set', + subitem: 'Subitem', + formValidation: 'Form validation', + verifyReset: 'Verify reset' + }, + guideDemo: { + guide: 'Guide', + start: 'Start', + message: + 'The guide page is very useful for some people who enter the project for the first time. You can briefly introduce the functions of the project. The boot page is based on intro js' + }, + iconDemo: { + icon: 'Icon', + localIcon: 'Local Icon', + iconify: 'Iconify component', + recommendedUse: 'Recommended use', + recommendeDes: + 'Iconify component basically contains all icons. You can query any icon you want. And packaging will only package the icons used.', + accessAddress: 'Access address' + }, + echartDemo: { + echart: 'Echart', + echartDes: + 'Based on the secondary packaging components of eckarts, the width is adaptive. The corresponding chart can be displayed by passing in the options and height attributes.' + }, + countToDemo: { + countTo: 'CountTo', + countToDes: + 'The transformation is based on vue-count-to and supports all vue-count-to parameters.', + suffix: 'Suffix', + prefix: 'Prefix', + separator: 'Separator', + duration: 'Duration', + endVal: 'End val', + startVal: 'Start val', + start: 'Start', + pause: 'Pause', + resume: 'Resume' + }, + watermarkDemo: { + watermark: 'Watermark', + createdWatermark: 'Created watermark', + clearWatermark: 'Clear watermark', + resetWatermark: 'Reset watermark' + }, + qrcodeDemo: { + qrcode: 'Qrcode', + qrcodeDes: 'Secondary packaging based on qrcode', + basicUsage: 'Basic usage', + imgTag: 'Img tag', + style: 'Style config', + click: 'Click event', + asynchronousContent: 'Asynchronous content', + invalid: 'Invalid', + logoConfig: 'Logo config', + logoStyle: 'Logo style', + size: 'size config' + }, + highlightDemo: { + highlight: 'Highlight', + message: 'The best time to plant a tree is ten years ago, followed by now.', + keys1: 'ten years ago', + keys2: 'now' + }, + infotipDemo: { + infotip: 'Infotip', + infotipDes: 'Secondary packaging of components based on Highlight', + title: 'matters needing attention' + }, + levelDemo: { + menu: 'Multi level menu cache' + }, + searchDemo: { + search: 'Search', + searchDes: + 'Based on the secondary encapsulation of form components, the functions of query and reset are realized', + operate: 'operate', + change: 'Change', + grid: 'grid', + button: 'Button', + restore: 'Restore', + inline: 'inline', + bottom: 'Bottom', + position: 'position', + left: 'left', + center: 'center', + right: 'right', + dynamicOptions: 'Dynamic options' + }, + stickyDemo: { + sticky: 'Sticky' + }, + tableDemo: { + table: 'Table', + tableDes: 'Secondary packaging of Table components based on ElementPlus', + index: 'Index', + title: 'Title', + author: 'Author', + displayTime: 'Display time', + importance: 'Importance', + pageviews: 'Pageviews', + action: 'Action', + important: 'Important', + good: 'Good', + commonly: 'Commonly', + operate: 'operate', + example: 'example', + show: 'Show', + hidden: 'Hidden', + pagination: 'pagination', + reserveIndex: 'Reserve index', + restoreIndex: 'Restore index', + showSelections: 'Show selections', + hiddenSelections: 'Restore selections', + showExpandedRows: 'Show expanded rows', + hiddenExpandedRows: 'Hidden expanded rows', + changeTitle: 'Change title', + header: 'Header', + selectAllNone: 'Select all / none' + }, + richText: { + richText: 'Rich text', + richTextDes: 'Secondary packaging based on wangeditor' + }, + dialogDemo: { + dialog: 'Dialog', + dialogDes: 'Secondary packaging of Dialog components based on ElementPlus', + open: 'Open', + close: 'Close', + combineWithForm: 'Combine with form', + submit: 'Submit' + }, + imageViewerDemo: { + open: 'Open', + imageViewer: 'Image viewer', + imageViewerDes: 'Secondary packaging of ImageViewer components based on ElementPlus' + }, + descriptionsDemo: { + descriptions: 'Descriptions', + descriptionsDes: 'Secondary packaging of Descriptions components based on ElementPlus', + username: 'Username', + nickName: 'NickName', + phone: 'Phone', + email: 'Email', + addr: 'Address', + form: 'Combined with Form component' + }, + exampleDemo: { + title: 'Title', + add: 'Add', + del: 'Delete', + edit: 'Edit', + author: 'Author', + displayTime: 'Display time', + importance: 'Importance', + pageviews: 'Pageviews', + important: 'Important', + content: 'Content', + save: 'Save', + detail: 'Detail' + }, + userDemo: { + title: 'User management', + message: + 'Because it is simulated data, only two accounts with different permissions are provided, which can be modified and combined by developers according to the actual situation.', + index: 'Index', + action: 'Action', + username: 'Username', + password: 'Password', + role: 'Role', + remark: 'Remark', + remarkMessage1: 'Back end control routing permission', + remarkMessage2: 'Front end control routing permission' + }, + inputPasswordDemo: { + title: 'InputPassword', + inputPasswordDes: 'Secondary packaging of Input components based on ElementPlus' + } +} diff --git a/kinit-admin/src/locales/zh-CN.ts b/kinit-admin/src/locales/zh-CN.ts new file mode 100644 index 0000000..7600880 --- /dev/null +++ b/kinit-admin/src/locales/zh-CN.ts @@ -0,0 +1,437 @@ +export default { + common: { + inputText: '请输入', + selectText: '请选择', + startTimeText: '开始时间', + endTimeText: '结束时间', + login: '登录', + required: '该项为必填项', + loginOut: '退出系统', + document: '项目文档', + reminder: '温馨提示', + loginOutMessage: '是否退出本系统?', + back: '返回', + ok: '确定', + cancel: '取消', + reload: '重新加载', + closeTab: '关闭标签页', + closeTheLeftTab: '关闭左侧标签页', + closeTheRightTab: '关闭右侧标签页', + closeOther: '关闭其他标签页', + closeAll: '关闭全部标签页', + prevLabel: '上一步', + nextLabel: '下一步', + skipLabel: '跳过', + doneLabel: '结束', + menu: '菜单', + menuDes: '以路由的结构渲染的菜单栏', + collapse: '展开缩收', + collapseDes: '展开和缩放菜单栏', + tagsView: '标签页', + tagsViewDes: '用于记录路由历史记录', + tool: '工具', + toolDes: '用于设置定制系统', + query: '查询', + reset: '重置', + shrink: '收起', + expand: '展开', + delMessage: '是否删除所选中数据?', + delWarning: '提示', + delOk: '确定', + delCancel: '取消', + delNoData: '请选择需要删除的数据', + delSuccess: '删除成功' + }, + error: { + noPermission: `抱歉,您无权访问此页面。`, + pageError: '抱歉,您访问的页面不存在。', + networkError: '抱歉,服务器报告错误。', + returnToHome: '返回首页' + }, + setting: { + projectSetting: '项目配置', + theme: '主题', + layout: '布局', + systemTheme: '系统主题', + menuTheme: '菜单主题', + interfaceDisplay: '界面显示', + breadcrumb: '面包屑', + breadcrumbIcon: '面包屑图标', + collapseMenu: '折叠菜单', + hamburgerIcon: '折叠图标', + screenfullIcon: '全屏图标', + sizeIcon: '尺寸图标', + localeIcon: '多语言图标', + tagsView: '标签页', + logo: '标志', + greyMode: '灰色模式', + fixedHeader: '固定头部', + headerTheme: '头部主题', + cutMenu: '切割菜单', + copy: '拷贝', + clearAndReset: '清除缓存并且重置', + copySuccess: '拷贝成功', + copyFailed: '拷贝失败', + footer: '页脚', + uniqueOpened: '菜单手风琴', + tagsViewIcon: '标签页图标', + dynamicRouter: '动态路由', + reExperienced: '请重新退出登录体验' + }, + size: { + default: '默认', + large: '大', + small: '小' + }, + login: { + welcome: '欢迎使用本系统', + message: '开箱即用的中后台管理系统', + username: '用户名', + password: '密码', + register: '注册', + checkPassword: '确认密码', + login: '登录', + otherLogin: '其他登录方式', + remember: '记住我', + hasUser: '已有账号?去登录', + forgetPassword: '忘记密码', + usernamePlaceholder: '请输入用户名', + passwordPlaceholder: '请输入密码', + code: '验证码', + codePlaceholder: '请输入验证码' + }, + router: { + login: '登录', + level: '多级菜单', + menu: '菜单', + menu1: '菜单1', + menu11: '菜单1-1', + menu111: '菜单1-1-1', + menu12: '菜单1-2', + menu2: '菜单2', + dashboard: '首页', + analysis: '分析页', + workplace: '工作台', + guide: '引导', + component: '组件', + icon: '图标', + echart: '图表', + countTo: '数字动画', + watermark: '水印', + qrcode: '二维码', + highlight: '高亮', + infotip: '信息提示', + form: '表单', + defaultForm: '全部示例', + search: '查询', + table: '表格', + defaultTable: '基础示例', + editor: '编辑器', + richText: '富文本', + dialog: '弹窗', + imageViewer: '图片预览', + descriptions: '描述', + example: '综合示例', + exampleDialog: '综合示例 - 弹窗', + examplePage: '综合示例 - 页面', + exampleAdd: '综合示例 - 新增', + exampleEdit: '综合示例 - 编辑', + exampleDetail: '综合示例 - 详情', + errorPage: '错误页面', + authorization: '权限管理', + user: '用户管理', + role: '角色管理', + document: '文档', + inputPassword: '密码输入框', + sticky: '黏性' + }, + permission: { + hasPermission: '请设置操作权限值' + }, + analysis: { + newUser: '新增用户', + unreadInformation: '未读消息', + transactionAmount: '成交金额', + totalShopping: '购物总量', + monthlySales: '每月销售额', + userAccessSource: '用户访问来源', + january: '一月', + february: '二月', + march: '三月', + april: '四月', + may: '五月', + june: '六月', + july: '七月', + august: '八月', + september: '九月', + october: '十月', + november: '十一月', + december: '十二月', + estimate: '预计', + actual: '实际', + directAccess: '直接访问', + mailMarketing: '邮件营销', + allianceAdvertising: '联盟广告', + videoAdvertising: '视频广告', + searchEngines: '搜索引擎', + weeklyUserActivity: '每周用户活跃量', + activeQuantity: '活跃量', + monday: '周一', + tuesday: '周二', + wednesday: '周三', + thursday: '周四', + friday: '周五', + saturday: '周六', + sunday: '周日' + }, + workplace: { + goodMorning: '早安', + happyDay: '祝你开心每一天!', + toady: '今日晴', + project: '项目数', + access: '项目访问', + toDo: '待办', + introduction: '一个正经的简介', + more: '更多', + shortcutOperation: '快捷操作', + operation: '操作', + index: '指数', + personal: '个人', + team: '团队', + quote: '引用', + contribution: '贡献', + hot: '热度', + yield: '产量', + dynamic: '动态', + push: '推送', + pushCode: 'Archer 推送 代码到 Github', + follow: '关注' + }, + formDemo: { + input: '输入框', + inputNumber: '数字输入框', + default: '默认', + icon: '图标', + mixed: '复合型', + textarea: '多行文本', + slot: '插槽', + position: '位置', + autocomplete: '自动补全', + select: '选择器', + selectGroup: '选项分组', + selectV2: '虚拟列表选择器', + cascader: '级联选择器', + switch: '开关', + rate: '评分', + colorPicker: '颜色选择器', + transfer: '穿梭框', + render: '渲染器', + radio: '单选框', + button: '按钮', + checkbox: '多选框', + slider: '滑块', + datePicker: '日期选择器', + shortcuts: '快捷选项', + today: '今天', + yesterday: '昨天', + aWeekAgo: '一周前', + week: '周', + year: '年', + month: '月', + dates: '日期', + daterange: '日期范围', + monthrange: '月份范围', + dateTimePicker: '日期时间选择器', + dateTimerange: '日期时间范围', + timePicker: '时间选择器', + timeSelect: '时间选择', + inputPassword: '密码输入框', + passwordStrength: '密码强度', + defaultForm: '全部示例', + formDes: '基于 ElementPlus 的 Form 组件二次封装,实现数据驱动,支持所有 Form 参数', + example: '示例', + operate: '操作', + change: '更改', + restore: '还原', + disabled: '禁用', + disablement: '解除禁用', + delete: '删除', + add: '添加', + setValue: '设置值', + resetValue: '重置值', + set: '设置', + subitem: '子项', + formValidation: '表单验证', + verifyReset: '验证重置' + }, + guideDemo: { + guide: '引导页', + start: '开始', + message: + '引导页对于一些第一次进入项目的人很有用,你可以简单介绍下项目的功能。引导页基于 intro.js' + }, + iconDemo: { + icon: '图标', + localIcon: '本地图标', + iconify: 'Iconify组件', + recommendedUse: '推荐使用', + recommendeDes: + 'Iconify组件基本包含所有的图标,你可以查询到你想要的任何图标。并且打包只会打包所用到的图标。', + accessAddress: '访问地址' + }, + echartDemo: { + echart: '图表', + echartDes: + '基于 echarts 二次封装组件,自适应宽度,只需传入 options 与 height 属性即可展示对应的图表。' + }, + countToDemo: { + countTo: '数字动画', + countToDes: '基于 vue-count-to 进行改造,支持所有 vue-count-to 参数。', + suffix: '后缀', + prefix: '前缀', + separator: '分割符号', + duration: '持续时间', + endVal: '结束值', + startVal: '开始值', + start: '开始', + pause: '暂停', + resume: '继续' + }, + watermarkDemo: { + watermark: '水印', + createdWatermark: '创建水印', + clearWatermark: '清除水印', + resetWatermark: '重置水印' + }, + qrcodeDemo: { + qrcode: '二维码', + qrcodeDes: '基于 qrcode 二次封装', + basicUsage: '基础用法', + imgTag: 'img标签', + style: '样式配置', + click: '点击事件', + asynchronousContent: '异步内容', + invalid: '失效', + logoConfig: 'logo配置', + logoStyle: 'logo样式', + size: '大小配置' + }, + highlightDemo: { + highlight: '高亮', + message: '种一棵树最好的时间是十年前,其次就是现在。', + keys1: '十年前', + keys2: '现在' + }, + infotipDemo: { + infotip: '信息提示', + infotipDes: '基于 Highlight 组件二次封装', + title: '注意事项' + }, + levelDemo: { + menu: '多级菜单缓存' + }, + searchDemo: { + search: '查询', + searchDes: '基于 Form 组件二次封装,实现查询、重置功能', + operate: '操作', + change: '更改', + grid: '栅格', + button: '按钮', + restore: '还原', + inline: '内联', + bottom: '底部', + position: '位置', + left: '左', + center: '中', + right: '右', + dynamicOptions: '动态选项' + }, + stickyDemo: { + sticky: '黏性' + }, + tableDemo: { + table: '表格', + tableDes: '基于 ElementPlus 的 Table 组件二次封装', + index: '序号', + title: '标题', + author: '作者', + displayTime: '创建时间', + importance: '重要性', + pageviews: '阅读数', + action: '操作', + important: '重要', + good: '良好', + commonly: '一般', + operate: '操作', + example: '示例', + show: '显示', + hidden: '隐藏', + pagination: '分页', + reserveIndex: '叠加序号', + restoreIndex: '还原序号', + showSelections: '显示多选', + hiddenSelections: '隐藏多选', + showExpandedRows: '显示展开行', + hiddenExpandedRows: '隐藏展开行', + changeTitle: '修改标题', + header: '头部', + selectAllNone: '全选/全不选' + }, + richText: { + richText: '富文本', + richTextDes: '基于 wangeditor 二次封装' + }, + dialogDemo: { + dialog: '弹窗', + dialogDes: '基于 ElementPlus 的 Dialog 组件二次封装', + open: '打开', + close: '关闭', + combineWithForm: '与表单结合', + submit: '提交' + }, + imageViewerDemo: { + open: '打开', + imageViewer: '图片预览', + imageViewerDes: '基于 ElementPlus 的 ImageViewer 组件二次封装' + }, + descriptionsDemo: { + descriptions: '描述', + descriptionsDes: '基于 ElementPlus 的 Descriptions 组件二次封装', + username: '用户名', + nickName: '昵称', + phone: '联系电话', + email: '邮箱', + addr: '地址', + form: '与 Form 组件组合' + }, + exampleDemo: { + title: '标题', + add: '新增', + del: '删除', + edit: '编辑', + author: '作者', + displayTime: '创建时间', + importance: '重要性', + pageviews: '阅读数', + important: '重要', + content: '内容', + save: '保存', + detail: '详情' + }, + userDemo: { + title: '用户管理', + message: '由于是模拟数据,所以只提供了两种不同权限的帐号,开发者可根据实际情况自行改造结合。', + index: '序号', + action: '操作', + username: '用户名', + password: '密码', + role: '角色', + remark: '备注', + remarkMessage1: '后端控制路由权限', + remarkMessage2: '前端控制路由权限' + }, + inputPasswordDemo: { + title: '密码输入框', + inputPasswordDes: '基于 ElementPlus 的 Input 组件二次封装' + } +} diff --git a/kinit-admin/src/main.ts b/kinit-admin/src/main.ts new file mode 100644 index 0000000..f6bfd39 --- /dev/null +++ b/kinit-admin/src/main.ts @@ -0,0 +1,55 @@ +// 引入windi css +import '@/plugins/windi.css' + +// 导入全局的svg图标 +import '@/plugins/svgIcon' + +// 初始化多语言 +import { setupI18n } from '@/plugins/vueI18n' + +// 引入状态管理 +import { setupStore } from '@/store' + +// 全局组件 +import { setupGlobCom } from '@/components' + +// 引入element-plus +import { setupElementPlus } from '@/plugins/elementPlus' + +// 引入全局样式 +import '@/styles/index.less' + +// 引入动画 +import '@/plugins/animate.css' + +// 路由 +import { setupRouter } from './router' + +// 权限 +import { setupPermission } from './directives' + +import { createApp } from 'vue' + +import App from './App.vue' + +import './permission' +// 创建实例 +const setupAll = async () => { + const app = createApp(App) + + await setupI18n(app) + + setupStore(app) + + setupGlobCom(app) + + setupElementPlus(app) + + setupRouter(app) + + setupPermission(app) + + app.mount('#app') +} + +setupAll() diff --git a/kinit-admin/src/permission.ts b/kinit-admin/src/permission.ts new file mode 100644 index 0000000..7c7dc28 --- /dev/null +++ b/kinit-admin/src/permission.ts @@ -0,0 +1,82 @@ +import router from './router' +import { useAppStoreWithOut } from '@/store/modules/app' +import { useCache } from '@/hooks/web/useCache' +import type { RouteRecordRaw } from 'vue-router' +import { useTitle } from '@/hooks/web/useTitle' +import { useNProgress } from '@/hooks/web/useNProgress' +import { usePermissionStoreWithOut } from '@/store/modules/permission' +import { useDictStoreWithOut } from '@/store/modules/dict' +import { usePageLoading } from '@/hooks/web/usePageLoading' +import { getDictApi } from '@/api/common' + +const permissionStore = usePermissionStoreWithOut() + +const appStore = useAppStoreWithOut() + +const dictStore = useDictStoreWithOut() + +const { wsCache } = useCache() + +const { start, done } = useNProgress() + +const { loadStart, loadDone } = usePageLoading() + +const whiteList = ['/login'] // 不重定向白名单 + +router.beforeEach(async (to, from, next) => { + start() + loadStart() + if (wsCache.get(appStore.getUserInfo)) { + if (to.path === '/login') { + next({ path: '/' }) + } else { + if (permissionStore.getIsAddRouters) { + next() + return + } + + if (!dictStore.getIsSetDict) { + // 获取所有字典 + const res = await getDictApi() + if (res) { + dictStore.setDictObj(res.data) + dictStore.setIsSetDict(true) + } + } + + // 开发者可根据实际情况进行修改 + const roleRouters = wsCache.get('roleRouters') || [] + const userInfo = wsCache.get(appStore.getUserInfo) + + // 是否使用动态路由 + if (appStore.getDynamicRouter) { + userInfo.role === 'admin' + ? await permissionStore.generateRoutes('admin', roleRouters as AppCustomRouteRecordRaw[]) + : await permissionStore.generateRoutes('test', roleRouters as string[]) + } else { + await permissionStore.generateRoutes('none') + } + + permissionStore.getAddRouters.forEach((route) => { + router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表 + }) + const redirectPath = from.query.redirect || to.path + const redirect = decodeURIComponent(redirectPath as string) + const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect } + permissionStore.setIsAddRouters(true) + next(nextData) + } + } else { + if (whiteList.indexOf(to.path) !== -1) { + next() + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } + } +}) + +router.afterEach((to) => { + useTitle(to?.meta?.title as string) + done() // 结束Progress + loadDone() +}) diff --git a/kinit-admin/src/plugins/animate.css/index.ts b/kinit-admin/src/plugins/animate.css/index.ts new file mode 100644 index 0000000..3e93451 --- /dev/null +++ b/kinit-admin/src/plugins/animate.css/index.ts @@ -0,0 +1 @@ +import 'animate.css' diff --git a/kinit-admin/src/plugins/echarts/index.ts b/kinit-admin/src/plugins/echarts/index.ts new file mode 100644 index 0000000..34f756f --- /dev/null +++ b/kinit-admin/src/plugins/echarts/index.ts @@ -0,0 +1,41 @@ +import * as echarts from 'echarts/core' + +import { + BarChart, + LineChart, + PieChart, + MapChart, + PictorialBarChart, + RadarChart +} from 'echarts/charts' + +import { + TitleComponent, + TooltipComponent, + GridComponent, + PolarComponent, + AriaComponent, + ParallelComponent, + LegendComponent +} from 'echarts/components' + +import { CanvasRenderer } from 'echarts/renderers' + +echarts.use([ + LegendComponent, + TitleComponent, + TooltipComponent, + GridComponent, + PolarComponent, + AriaComponent, + ParallelComponent, + BarChart, + LineChart, + PieChart, + MapChart, + CanvasRenderer, + PictorialBarChart, + RadarChart +]) + +export default echarts diff --git a/kinit-admin/src/plugins/elementPlus/index.ts b/kinit-admin/src/plugins/elementPlus/index.ts new file mode 100644 index 0000000..a5362a1 --- /dev/null +++ b/kinit-admin/src/plugins/elementPlus/index.ts @@ -0,0 +1,18 @@ +import type { App } from 'vue' + +// 需要全局引入一些组件,如ElScrollbar,不然一些下拉项样式有问题 +import { ElLoading, ElScrollbar } from 'element-plus' + +const plugins = [ElLoading] + +const components = [ElScrollbar] + +export const setupElementPlus = (app: App+ +++ {tagsView.value ? ( + ++ ) : undefined} + + + ) => { + plugins.forEach((plugin) => { + app.use(plugin) + }) + + components.forEach((component) => { + app.component(component.name, component) + }) +} diff --git a/kinit-admin/src/plugins/svgIcon/index.ts b/kinit-admin/src/plugins/svgIcon/index.ts new file mode 100644 index 0000000..b5b7f70 --- /dev/null +++ b/kinit-admin/src/plugins/svgIcon/index.ts @@ -0,0 +1,3 @@ +import 'virtual:svg-icons-register' + +import '@purge-icons/generated' diff --git a/kinit-admin/src/plugins/vueI18n/helper.ts b/kinit-admin/src/plugins/vueI18n/helper.ts new file mode 100644 index 0000000..da6bc8c --- /dev/null +++ b/kinit-admin/src/plugins/vueI18n/helper.ts @@ -0,0 +1,3 @@ +export const setHtmlPageLang = (locale: LocaleType) => { + document.querySelector('html')?.setAttribute('lang', locale) +} diff --git a/kinit-admin/src/plugins/vueI18n/index.ts b/kinit-admin/src/plugins/vueI18n/index.ts new file mode 100644 index 0000000..f845b13 --- /dev/null +++ b/kinit-admin/src/plugins/vueI18n/index.ts @@ -0,0 +1,42 @@ +import type { App } from 'vue' +import { createI18n } from 'vue-i18n' +import { useLocaleStoreWithOut } from '@/store/modules/locale' +import type { I18n, I18nOptions } from 'vue-i18n' +import { setHtmlPageLang } from './helper' + +export let i18n: ReturnType + +const createI18nOptions = async (): Promise => { + const localeStore = useLocaleStoreWithOut() + const locale = localeStore.getCurrentLocale + const localeMap = localeStore.getLocaleMap + const defaultLocal = await import(`../../locales/${locale.lang}.ts`) + const message = defaultLocal.default ?? {} + + setHtmlPageLang(locale.lang) + + localeStore.setCurrentLocale({ + lang: locale.lang + // elLocale: elLocal + }) + + return { + legacy: false, + locale: locale.lang, + fallbackLocale: locale.lang, + messages: { + [locale.lang]: message + }, + availableLocales: localeMap.map((v) => v.lang), + sync: true, + silentTranslationWarn: true, + missingWarn: false, + silentFallbackWarn: true + } +} + +export const setupI18n = async (app: App ) => { + const options = await createI18nOptions() + i18n = createI18n(options) as I18n + app.use(i18n) +} diff --git a/kinit-admin/src/plugins/windi.css/index.ts b/kinit-admin/src/plugins/windi.css/index.ts new file mode 100644 index 0000000..dbdfbbf --- /dev/null +++ b/kinit-admin/src/plugins/windi.css/index.ts @@ -0,0 +1,3 @@ +import 'virtual:windi.css' + +import 'virtual:windi-devtools' diff --git a/kinit-admin/src/router/index.ts b/kinit-admin/src/router/index.ts new file mode 100644 index 0000000..edb4b68 --- /dev/null +++ b/kinit-admin/src/router/index.ts @@ -0,0 +1,569 @@ +import { createRouter, createWebHashHistory } from 'vue-router' +import type { RouteRecordRaw } from 'vue-router' +import type { App } from 'vue' +import { Layout, getParentLayout } from '@/utils/routerHelper' +import { useI18n } from '@/hooks/web/useI18n' + +const { t } = useI18n() + +export const constantRouterMap: AppRouteRecordRaw[] = [ + { + path: '/', + component: Layout, + redirect: '/dashboard/analysis', + name: 'Root', + meta: { + hidden: true + } + }, + { + path: '/redirect', + component: Layout, + name: 'Redirect', + children: [ + { + path: '/redirect/:path(.*)', + name: 'Redirect', + component: () => import('@/views/Redirect/Redirect.vue'), + meta: {} + } + ], + meta: { + hidden: true, + noTagsView: true + } + }, + { + path: '/login', + component: () => import('@/views/Login/Login.vue'), + name: 'Login', + meta: { + hidden: true, + title: t('router.login'), + noTagsView: true + } + }, + { + path: '/404', + component: () => import('@/views/Error/404.vue'), + name: 'NoFind', + meta: { + hidden: true, + title: '404', + noTagsView: true + } + } +] + +export const asyncRouterMap: AppRouteRecordRaw[] = [ + { + path: '/dashboard', + component: Layout, + redirect: '/dashboard/analysis', + name: 'Dashboard', + meta: { + title: t('router.dashboard'), + icon: 'ant-design:dashboard-filled', + alwaysShow: true + }, + children: [ + { + path: 'analysis', + component: () => import('@/views/Dashboard/Analysis.vue'), + name: 'Analysis', + meta: { + title: t('router.analysis'), + noCache: true, + affix: true + } + }, + { + path: 'workplace', + component: () => import('@/views/Dashboard/Workplace.vue'), + name: 'Workplace', + meta: { + title: t('router.workplace'), + noCache: true + } + } + ] + }, + { + path: '/external-link', + component: Layout, + meta: {}, + name: 'ExternalLink', + children: [ + { + path: 'https://element-plus-admin-doc.cn/', + name: 'DocumentLink', + meta: { + title: t('router.document'), + icon: 'clarity:document-solid' + } + } + ] + }, + { + path: '/guide', + component: Layout, + name: 'Guide', + meta: {}, + children: [ + { + path: 'index', + component: () => import('@/views/Guide/Guide.vue'), + name: 'GuideDemo', + meta: { + title: t('router.guide'), + icon: 'cib:telegram-plane' + } + } + ] + }, + { + path: '/components', + component: Layout, + name: 'ComponentsDemo', + meta: { + title: t('router.component'), + icon: 'bx:bxs-component', + alwaysShow: true + }, + children: [ + { + path: 'form', + component: getParentLayout(), + redirect: '/components/form/default-form', + name: 'Form', + meta: { + title: t('router.form'), + alwaysShow: true + }, + children: [ + { + path: 'default-form', + component: () => import('@/views/Components/Form/DefaultForm.vue'), + name: 'DefaultForm', + meta: { + title: t('router.defaultForm') + } + }, + { + path: 'use-form', + component: () => import('@/views/Components/Form/UseFormDemo.vue'), + name: 'UseForm', + meta: { + title: 'UseForm' + } + }, + { + path: 'ref-form', + component: () => import('@/views/Components/Form/RefForm.vue'), + name: 'RefForm', + meta: { + title: 'RefForm' + } + } + ] + }, + { + path: 'table', + component: getParentLayout(), + redirect: '/components/table/default-table', + name: 'TableDemo', + meta: { + title: t('router.table'), + alwaysShow: true + }, + children: [ + { + path: 'default-table', + component: () => import('@/views/Components/Table/DefaultTable.vue'), + name: 'DefaultTable', + meta: { + title: t('router.defaultTable') + } + }, + { + path: 'use-table', + component: () => import('@/views/Components/Table/UseTableDemo.vue'), + name: 'UseTable', + meta: { + title: 'UseTable' + } + }, + { + path: 'ref-table', + component: () => import('@/views/Components/Table/RefTable.vue'), + name: 'RefTable', + meta: { + title: 'RefTable' + } + } + ] + }, + { + path: 'editor-demo', + component: getParentLayout(), + redirect: '/components/editor-demo/editor', + name: 'EditorDemo', + meta: { + title: t('router.editor'), + alwaysShow: true + }, + children: [ + { + path: 'editor', + component: () => import('@/views/Components/Editor/Editor.vue'), + name: 'Editor', + meta: { + title: t('router.richText') + } + } + ] + }, + { + path: 'search', + component: () => import('@/views/Components/Search.vue'), + name: 'Search', + meta: { + title: t('router.search') + } + }, + { + path: 'descriptions', + component: () => import('@/views/Components/Descriptions.vue'), + name: 'Descriptions', + meta: { + title: t('router.descriptions') + } + }, + { + path: 'image-viewer', + component: () => import('@/views/Components/ImageViewer.vue'), + name: 'ImageViewer', + meta: { + title: t('router.imageViewer') + } + }, + { + path: 'dialog', + component: () => import('@/views/Components/Dialog.vue'), + name: 'Dialog', + meta: { + title: t('router.dialog') + } + }, + { + path: 'icon', + component: () => import('@/views/Components/Icon.vue'), + name: 'Icon', + meta: { + title: t('router.icon') + } + }, + { + path: 'echart', + component: () => import('@/views/Components/Echart.vue'), + name: 'Echart', + meta: { + title: t('router.echart') + } + }, + { + path: 'count-to', + component: () => import('@/views/Components/CountTo.vue'), + name: 'CountTo', + meta: { + title: t('router.countTo') + } + }, + { + path: 'qrcode', + component: () => import('@/views/Components/Qrcode.vue'), + name: 'Qrcode', + meta: { + title: t('router.qrcode') + } + }, + { + path: 'highlight', + component: () => import('@/views/Components/Highlight.vue'), + name: 'Highlight', + meta: { + title: t('router.highlight') + } + }, + { + path: 'infotip', + component: () => import('@/views/Components/Infotip.vue'), + name: 'Infotip', + meta: { + title: t('router.infotip') + } + }, + { + path: 'input-password', + component: () => import('@/views/Components/InputPassword.vue'), + name: 'InputPassword', + meta: { + title: t('router.inputPassword') + } + }, + { + path: 'sticky', + component: () => import('@/views/Components/Sticky.vue'), + name: 'Sticky', + meta: { + title: t('router.sticky') + } + } + ] + }, + { + path: '/hooks', + component: Layout, + redirect: '/hooks/useWatermark', + name: 'Hooks', + meta: { + title: 'hooks', + icon: 'ic:outline-webhook', + alwaysShow: true + }, + children: [ + { + path: 'useWatermark', + component: () => import('@/views/hooks/useWatermark.vue'), + name: 'UseWatermark', + meta: { + title: 'useWatermark' + } + }, + { + path: 'useCrudSchemas', + component: () => import('@/views/hooks/useCrudSchemas.vue'), + name: 'UseCrudSchemas', + meta: { + title: 'useCrudSchemas' + } + } + ] + }, + { + path: '/level', + component: Layout, + redirect: '/level/menu1/menu1-1/menu1-1-1', + name: 'Level', + meta: { + title: t('router.level'), + icon: 'carbon:skill-level-advanced' + }, + children: [ + { + path: 'menu1', + name: 'Menu1', + component: getParentLayout(), + redirect: '/level/menu1/menu1-1/menu1-1-1', + meta: { + title: t('router.menu1') + }, + children: [ + { + path: 'menu1-1', + name: 'Menu11', + component: getParentLayout(), + redirect: '/level/menu1/menu1-1/menu1-1-1', + meta: { + title: t('router.menu11'), + alwaysShow: true + }, + children: [ + { + path: 'menu1-1-1', + name: 'Menu111', + component: () => import('@/views/Level/Menu111.vue'), + meta: { + title: t('router.menu111') + } + } + ] + }, + { + path: 'menu1-2', + name: 'Menu12', + component: () => import('@/views/Level/Menu12.vue'), + meta: { + title: t('router.menu12') + } + } + ] + }, + { + path: 'menu2', + name: 'Menu2', + component: () => import('@/views/Level/Menu2.vue'), + meta: { + title: t('router.menu2') + } + } + ] + }, + { + path: '/example', + component: Layout, + redirect: '/example/example-dialog', + name: 'Example', + meta: { + title: t('router.example'), + icon: 'ep:management', + alwaysShow: true + }, + children: [ + { + path: 'example-dialog', + component: () => import('@/views/Example/Dialog/ExampleDialog.vue'), + name: 'ExampleDialog', + meta: { + title: t('router.exampleDialog') + } + }, + { + path: 'example-page', + component: () => import('@/views/Example/Page/ExamplePage.vue'), + name: 'ExamplePage', + meta: { + title: t('router.examplePage') + } + }, + { + path: 'example-add', + component: () => import('@/views/Example/Page/ExampleAdd.vue'), + name: 'ExampleAdd', + meta: { + title: t('router.exampleAdd'), + noTagsView: true, + noCache: true, + hidden: true, + canTo: true, + activeMenu: '/example/example-page' + } + }, + { + path: 'example-edit', + component: () => import('@/views/Example/Page/ExampleEdit.vue'), + name: 'ExampleEdit', + meta: { + title: t('router.exampleEdit'), + noTagsView: true, + noCache: true, + hidden: true, + canTo: true, + activeMenu: '/example/example-page' + } + }, + { + path: 'example-detail', + component: () => import('@/views/Example/Page/ExampleDetail.vue'), + name: 'ExampleDetail', + meta: { + title: t('router.exampleDetail'), + noTagsView: true, + noCache: true, + hidden: true, + canTo: true, + activeMenu: '/example/example-page' + } + } + ] + }, + { + path: '/error', + component: Layout, + redirect: '/error/404', + name: 'Error', + meta: { + title: t('router.errorPage'), + icon: 'ci:error', + alwaysShow: true + }, + children: [ + { + path: '404-demo', + component: () => import('@/views/Error/404.vue'), + name: '404Demo', + meta: { + title: '404' + } + }, + { + path: '403-demo', + component: () => import('@/views/Error/403.vue'), + name: '403Demo', + meta: { + title: '403' + } + }, + { + path: '500-demo', + component: () => import('@/views/Error/500.vue'), + name: '500Demo', + meta: { + title: '500' + } + } + ] + } + // { + // path: '/authorization', + // component: Layout, + // redirect: '/authorization/user', + // name: 'Authorization', + // meta: { + // title: t('router.authorization'), + // icon: 'eos-icons:role-binding', + // alwaysShow: true + // }, + // children: [ + // { + // path: 'user', + // component: () => import('@/views/Authorization/User.vue'), + // name: 'User', + // meta: { + // title: t('router.user') + // } + // }, + // { + // path: 'role', + // component: () => import('@/views/Authorization/Role.vue'), + // name: 'Role', + // meta: { + // title: t('router.role') + // } + // } + // ] + // } +] + +const router = createRouter({ + history: createWebHashHistory(), + strict: true, + routes: constantRouterMap as RouteRecordRaw[], + scrollBehavior: () => ({ left: 0, top: 0 }) +}) + +export const resetRouter = (): void => { + const resetWhiteNameList = ['Redirect', 'Login', 'NoFind', 'Root'] + router.getRoutes().forEach((route) => { + const { name } = route + if (name && !resetWhiteNameList.includes(name as string)) { + router.hasRoute(name) && router.removeRoute(name) + } + }) +} + +export const setupRouter = (app: App ) => { + app.use(router) +} + +export default router diff --git a/kinit-admin/src/store/index.ts b/kinit-admin/src/store/index.ts new file mode 100644 index 0000000..4038068 --- /dev/null +++ b/kinit-admin/src/store/index.ts @@ -0,0 +1,13 @@ +import type { App } from 'vue' +import { createPinia } from 'pinia' +import piniaPluginPersist from 'pinia-plugin-persist' + +const store = createPinia() + +store.use(piniaPluginPersist) + +export const setupStore = (app: App ) => { + app.use(store) +} + +export { store } diff --git a/kinit-admin/src/store/modules/app.ts b/kinit-admin/src/store/modules/app.ts new file mode 100644 index 0000000..beb6884 --- /dev/null +++ b/kinit-admin/src/store/modules/app.ts @@ -0,0 +1,184 @@ +import { defineStore } from 'pinia' +import { store } from '../index' +import { useCache } from '@/hooks/web/useCache' +import { appModules } from '@/config/app' +import type { AppState, LayoutType, ThemeTypes } from '@/config/app' +import { setCssVar, humpToUnderline } from '@/utils' +import { ElMessage } from 'element-plus' + +const { wsCache } = useCache() + +export const useAppStore = defineStore({ + id: 'app', + state: (): AppState => appModules, + persist: { + enabled: true + }, + getters: { + getBreadcrumb(): boolean { + return this.breadcrumb + }, + getBreadcrumbIcon(): boolean { + return this.breadcrumbIcon + }, + getCollapse(): boolean { + return this.collapse + }, + getUniqueOpened(): boolean { + return this.uniqueOpened + }, + getHamburger(): boolean { + return this.hamburger + }, + getScreenfull(): boolean { + return this.screenfull + }, + getSize(): boolean { + return this.size + }, + getLocale(): boolean { + return this.locale + }, + getTagsView(): boolean { + return this.tagsView + }, + getTagsViewIcon(): boolean { + return this.tagsViewIcon + }, + getLogo(): boolean { + return this.logo + }, + getFixedHeader(): boolean { + return this.fixedHeader + }, + getGreyMode(): boolean { + return this.greyMode + }, + getDynamicRouter(): boolean { + return this.dynamicRouter + }, + getPageLoading(): boolean { + return this.pageLoading + }, + getLayout(): LayoutType { + return this.layout + }, + getTitle(): string { + return this.title + }, + getUserInfo(): string { + return this.userInfo + }, + getIsDark(): boolean { + return this.isDark + }, + getCurrentSize(): ElememtPlusSize { + return this.currentSize + }, + getSizeMap(): ElememtPlusSize[] { + return this.sizeMap + }, + getMobile(): boolean { + return this.mobile + }, + getTheme(): ThemeTypes { + return this.theme + }, + getFooter(): boolean { + return this.footer + } + }, + actions: { + setBreadcrumb(breadcrumb: boolean) { + this.breadcrumb = breadcrumb + }, + setBreadcrumbIcon(breadcrumbIcon: boolean) { + this.breadcrumbIcon = breadcrumbIcon + }, + setCollapse(collapse: boolean) { + this.collapse = collapse + }, + setUniqueOpened(uniqueOpened: boolean) { + this.uniqueOpened = uniqueOpened + }, + setHamburger(hamburger: boolean) { + this.hamburger = hamburger + }, + setScreenfull(screenfull: boolean) { + this.screenfull = screenfull + }, + setSize(size: boolean) { + this.size = size + }, + setLocale(locale: boolean) { + this.locale = locale + }, + setTagsView(tagsView: boolean) { + this.tagsView = tagsView + }, + setTagsViewIcon(tagsViewIcon: boolean) { + this.tagsViewIcon = tagsViewIcon + }, + setLogo(logo: boolean) { + this.logo = logo + }, + setFixedHeader(fixedHeader: boolean) { + this.fixedHeader = fixedHeader + }, + setGreyMode(greyMode: boolean) { + this.greyMode = greyMode + }, + setDynamicRouter(dynamicRouter: boolean) { + wsCache.set('dynamicRouter', dynamicRouter) + this.dynamicRouter = dynamicRouter + }, + setPageLoading(pageLoading: boolean) { + this.pageLoading = pageLoading + }, + setLayout(layout: LayoutType) { + if (this.mobile && layout !== 'classic') { + ElMessage.warning('移动端模式下不支持切换其他布局') + return + } + this.layout = layout + wsCache.set('layout', this.layout) + }, + setTitle(title: string) { + this.title = title + }, + setIsDark(isDark: boolean) { + this.isDark = isDark + if (this.isDark) { + document.documentElement.classList.add('dark') + document.documentElement.classList.remove('light') + } else { + document.documentElement.classList.add('light') + document.documentElement.classList.remove('dark') + } + wsCache.set('isDark', this.isDark) + }, + setCurrentSize(currentSize: ElememtPlusSize) { + this.currentSize = currentSize + wsCache.set('currentSize', this.currentSize) + }, + setMobile(mobile: boolean) { + this.mobile = mobile + }, + setTheme(theme: ThemeTypes) { + this.theme = Object.assign(this.theme, theme) + wsCache.set('theme', this.theme) + }, + setCssVarTheme() { + for (const key in this.theme) { + setCssVar(`--${humpToUnderline(key)}`, this.theme[key]) + } + }, + setFooter(footer: boolean) { + this.footer = footer + } + } +}) + +export const useAppStoreWithOut = () => { + return useAppStore(store) +} diff --git a/kinit-admin/src/store/modules/dict.ts b/kinit-admin/src/store/modules/dict.ts new file mode 100644 index 0000000..446b925 --- /dev/null +++ b/kinit-admin/src/store/modules/dict.ts @@ -0,0 +1,38 @@ +import { defineStore } from 'pinia' +import { store } from '../index' + +export interface DictState { + isSetDict: boolean + dictObj: Recordable +} + +export const useDictStore = defineStore({ + id: 'dict', + state: (): DictState => ({ + isSetDict: false, + dictObj: {} + }), + persist: { + enabled: true + }, + getters: { + getDictObj(): Recordable { + return this.dictObj + }, + getIsSetDict(): boolean { + return this.isSetDict + } + }, + actions: { + setDictObj(dictObj: Recordable) { + this.dictObj = dictObj + }, + setIsSetDict(isSetDict: boolean) { + this.isSetDict = isSetDict + } + } +}) + +export const useDictStoreWithOut = () => { + return useDictStore(store) +} diff --git a/kinit-admin/src/store/modules/locale.ts b/kinit-admin/src/store/modules/locale.ts new file mode 100644 index 0000000..4b7d064 --- /dev/null +++ b/kinit-admin/src/store/modules/locale.ts @@ -0,0 +1,35 @@ +import { defineStore } from 'pinia' +import { store } from '../index' +import { useCache } from '@/hooks/web/useCache' +import { localeModules, elLocaleMap } from '@/config/locale' +import type { LocaleState } from '@/config/locale' + +const { wsCache } = useCache() + +export const useLocaleStore = defineStore({ + id: 'locales', + state: (): LocaleState => localeModules, + persist: { + enabled: true + }, + getters: { + getCurrentLocale(): LocaleDropdownType { + return this.currentLocale + }, + getLocaleMap(): LocaleDropdownType[] { + return this.localeMap + } + }, + actions: { + setCurrentLocale(localeMap: LocaleDropdownType) { + // this.locale = Object.assign(this.locale, localeMap) + this.currentLocale.lang = localeMap?.lang + this.currentLocale.elLocale = elLocaleMap[localeMap?.lang] + wsCache.set('lang', localeMap?.lang) + } + } +}) + +export const useLocaleStoreWithOut = () => { + return useLocaleStore(store) +} diff --git a/kinit-admin/src/store/modules/permission.ts b/kinit-admin/src/store/modules/permission.ts new file mode 100644 index 0000000..22ca1a5 --- /dev/null +++ b/kinit-admin/src/store/modules/permission.ts @@ -0,0 +1,84 @@ +import { defineStore } from 'pinia' +import { asyncRouterMap, constantRouterMap } from '@/router' +import { generateRoutesFn1, generateRoutesFn2, flatMultiLevelRoutes } from '@/utils/routerHelper' +import { store } from '../index' +import { cloneDeep } from 'lodash-es' + +export interface PermissionState { + routers: AppRouteRecordRaw[] + addRouters: AppRouteRecordRaw[] + isAddRouters: boolean + menuTabRouters: AppRouteRecordRaw[] +} + +export const usePermissionStore = defineStore({ + id: 'permission', + state: (): PermissionState => ({ + routers: [], + addRouters: [], + isAddRouters: false, + menuTabRouters: [] + }), + persist: { + enabled: true + }, + getters: { + getRouters(): AppRouteRecordRaw[] { + return this.routers + }, + getAddRouters(): AppRouteRecordRaw[] { + return flatMultiLevelRoutes(cloneDeep(this.addRouters)) + }, + getIsAddRouters(): boolean { + return this.isAddRouters + }, + getMenuTabRouters(): AppRouteRecordRaw[] { + return this.menuTabRouters + } + }, + actions: { + generateRoutes( + type: 'admin' | 'test' | 'none', + routers?: AppCustomRouteRecordRaw[] | string[] + ): Promise { + return new Promise ((resolve) => { + let routerMap: AppRouteRecordRaw[] = [] + if (type === 'admin') { + // 模拟后端过滤菜单 + routerMap = generateRoutesFn2(routers as AppCustomRouteRecordRaw[]) + } else if (type === 'test') { + // 模拟前端过滤菜单 + routerMap = generateRoutesFn1(cloneDeep(asyncRouterMap), routers as string[]) + } else { + // 直接读取静态路由表 + routerMap = cloneDeep(asyncRouterMap) + } + // 动态路由,404一定要放到最后面 + this.addRouters = routerMap.concat([ + { + path: '/:path(.*)*', + redirect: '/404', + name: '404Page', + meta: { + hidden: true, + breadcrumb: false + } + } + ]) + // 渲染菜单的所有路由 + this.routers = cloneDeep(constantRouterMap).concat(routerMap) + resolve() + }) + }, + setIsAddRouters(state: boolean): void { + this.isAddRouters = state + }, + setMenuTabRouters(routers: AppRouteRecordRaw[]): void { + this.menuTabRouters = routers + } + } +}) + +export const usePermissionStoreWithOut = () => { + return usePermissionStore(store) +} diff --git a/kinit-admin/src/store/modules/tagsView.ts b/kinit-admin/src/store/modules/tagsView.ts new file mode 100644 index 0000000..33da805 --- /dev/null +++ b/kinit-admin/src/store/modules/tagsView.ts @@ -0,0 +1,141 @@ +import router from '@/router' +import type { RouteLocationNormalizedLoaded } from 'vue-router' +import { getRawRoute } from '@/utils/routerHelper' +import { defineStore } from 'pinia' +import { store } from '../index' +import { findIndex } from '@/utils' + +export interface TagsViewState { + visitedViews: RouteLocationNormalizedLoaded[] + cachedViews: Set +} + +export const useTagsViewStore = defineStore({ + id: 'tagsView', + state: (): TagsViewState => ({ + visitedViews: [], + cachedViews: new Set() + }), + getters: { + getVisitedViews(): RouteLocationNormalizedLoaded[] { + return this.visitedViews + }, + getCachedViews(): string[] { + return Array.from(this.cachedViews) + } + }, + actions: { + // 新增缓存和tag + addView(view: RouteLocationNormalizedLoaded): void { + this.addVisitedView(view) + this.addCachedView() + }, + // 新增tag + addVisitedView(view: RouteLocationNormalizedLoaded) { + if (this.visitedViews.some((v) => v.path === view.path)) return + if (view.meta?.noTagsView) return + this.visitedViews.push( + Object.assign({}, view, { + title: view.meta?.title || 'no-name' + }) + ) + }, + // 新增缓存 + addCachedView() { + const cacheMap: Set = new Set() + for (const v of this.visitedViews) { + const item = getRawRoute(v) + const needCache = !item.meta?.noCache + if (!needCache) { + continue + } + const name = item.name as string + cacheMap.add(name) + } + if (Array.from(this.cachedViews).sort().toString() === Array.from(cacheMap).sort().toString()) + return + this.cachedViews = cacheMap + }, + // 删除某个 + delView(view: RouteLocationNormalizedLoaded) { + this.delVisitedView(view) + this.addCachedView() + }, + // 删除tag + delVisitedView(view: RouteLocationNormalizedLoaded) { + for (const [i, v] of this.visitedViews.entries()) { + if (v.path === view.path) { + this.visitedViews.splice(i, 1) + break + } + } + }, + // 删除缓存 + delCachedView() { + const route = router.currentRoute.value + const index = findIndex (this.getCachedViews, (v) => v === route.name) + if (index > -1) { + this.cachedViews.delete(this.getCachedViews[index]) + } + }, + // 删除所有缓存和tag + delAllViews() { + this.delAllVisitedViews() + this.addCachedView() + }, + // 删除所有tag + delAllVisitedViews() { + // const affixTags = this.visitedViews.filter((tag) => tag.meta.affix) + this.visitedViews = [] + }, + // 删除其他 + delOthersViews(view: RouteLocationNormalizedLoaded) { + this.delOthersVisitedViews(view) + this.addCachedView() + }, + // 删除其他tag + delOthersVisitedViews(view: RouteLocationNormalizedLoaded) { + this.visitedViews = this.visitedViews.filter((v) => { + return v?.meta?.affix || v.path === view.path + }) + }, + // 删除左侧 + delLeftViews(view: RouteLocationNormalizedLoaded) { + const index = findIndex ( + this.visitedViews, + (v) => v.path === view.path + ) + if (index > -1) { + this.visitedViews = this.visitedViews.filter((v, i) => { + return v?.meta?.affix || v.path === view.path || i > index + }) + this.addCachedView() + } + }, + // 删除右侧 + delRightViews(view: RouteLocationNormalizedLoaded) { + const index = findIndex ( + this.visitedViews, + (v) => v.path === view.path + ) + if (index > -1) { + this.visitedViews = this.visitedViews.filter((v, i) => { + return v?.meta?.affix || v.path === view.path || i < index + }) + this.addCachedView() + } + }, + updateVisitedView(view: RouteLocationNormalizedLoaded) { + for (let v of this.visitedViews) { + if (v.path === view.path) { + v = Object.assign(v, view) + break + } + } + } + } +}) + +export const useTagsViewStoreWithOut = () => { + return useTagsViewStore(store) +} diff --git a/kinit-admin/src/styles/index.less b/kinit-admin/src/styles/index.less new file mode 100644 index 0000000..c023316 --- /dev/null +++ b/kinit-admin/src/styles/index.less @@ -0,0 +1,2 @@ +@import './var.css'; +@import 'element-plus/theme-chalk/dark/css-vars.css'; diff --git a/kinit-admin/src/styles/theme.less b/kinit-admin/src/styles/theme.less new file mode 100644 index 0000000..39b03b3 --- /dev/null +++ b/kinit-admin/src/styles/theme.less @@ -0,0 +1,6 @@ +// .text-color { +// color: var(--el-text-color-regular); +// } +// .dark .dark\:text-color { +// color: rgba(255, 255, 255, var(--dark-text-color)); +// } diff --git a/kinit-admin/src/styles/var.css b/kinit-admin/src/styles/var.css new file mode 100644 index 0000000..0d7d0df --- /dev/null +++ b/kinit-admin/src/styles/var.css @@ -0,0 +1,67 @@ +:root { + --dark-bg-color: #293146; + + /* left menu start */ + --left-menu-border-color: '#eee'; + + --left-menu-max-width: 200px; + + --left-menu-min-width: 64px; + + --left-menu-bg-color: #001529; + + --left-menu-bg-light-color: #0f2438; + + --left-menu-bg-active-color: var(--el-color-primary); + + --left-menu-text-color: #bfcbd9; + + --left-menu-text-active-color: #fff; + + --left-menu-collapse-bg-active-color: var(--el-color-primary); + /* left menu end */ + + /* logo start */ + --logo-height: 50px; + + --logo-title-text-color: #fff; + + --logo-border-color: 'inherit'; + /* logo end */ + + /* header start */ + --top-header-bg-color: '#fff'; + + --top-header-text-color: 'inherit'; + + --top-header-hover-color: #f6f6f6; + + --top-tool-height: var(--logo-height); + + --top-tool-p-x: 0; + + --top-tool-border-color: #eee; + + --tags-view-height: 35px; + + --tags-view-border-color: #eee; + /* header start */ + + /* tab menu start */ + --tab-menu-max-width: 80px; + + --tab-menu-min-width: 30px; + + --tab-menu-collapse-height: 36px; + + --tab-menu-border-color: #eee; + /* tab menu end */ + + --app-content-padding: 20px; + + --app-content-bg-color: #f5f7f9; + + --app-footer-height: 50px; + + --transition-time-02: 0.2s; +} diff --git a/kinit-admin/src/styles/variables.module.less b/kinit-admin/src/styles/variables.module.less new file mode 100644 index 0000000..e97028d --- /dev/null +++ b/kinit-admin/src/styles/variables.module.less @@ -0,0 +1,10 @@ +// 命名空间 +@namespace: v; +// el命名空间 +@elNamespace: el; + +// 导出变量 +:export { + namespace: @namespace; + elNamespace: @elNamespace; +} diff --git a/kinit-admin/src/utils/color.ts b/kinit-admin/src/utils/color.ts new file mode 100644 index 0000000..6888583 --- /dev/null +++ b/kinit-admin/src/utils/color.ts @@ -0,0 +1,153 @@ +/** + * 判断是否 十六进制颜色值. + * 输入形式可为 #fff000 #f00 + * + * @param String color 十六进制颜色值 + * @return Boolean + */ +export const isHexColor = (color: string) => { + const reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-f]{6})$/ + return reg.test(color) +} + +/** + * RGB 颜色值转换为 十六进制颜色值. + * r, g, 和 b 需要在 [0, 255] 范围内 + * + * @return String 类似#ff00ff + * @param r + * @param g + * @param b + */ +export const rgbToHex = (r: number, g: number, b: number) => { + // tslint:disable-next-line:no-bitwise + const hex = ((r << 16) | (g << 8) | b).toString(16) + return '#' + new Array(Math.abs(hex.length - 7)).join('0') + hex +} + +/** + * Transform a HEX color to its RGB representation + * @param {string} hex The color to transform + * @returns The RGB representation of the passed color + */ +export const hexToRGB = (hex: string, opacity?: number) => { + let sHex = hex.toLowerCase() + if (isHexColor(hex)) { + if (sHex.length === 4) { + let sColorNew = '#' + for (let i = 1; i < 4; i += 1) { + sColorNew += sHex.slice(i, i + 1).concat(sHex.slice(i, i + 1)) + } + sHex = sColorNew + } + const sColorChange: number[] = [] + for (let i = 1; i < 7; i += 2) { + sColorChange.push(parseInt('0x' + sHex.slice(i, i + 2))) + } + return opacity + ? 'RGBA(' + sColorChange.join(',') + ',' + opacity + ')' + : 'RGB(' + sColorChange.join(',') + ')' + } + return sHex +} + +export const colorIsDark = (color: string) => { + if (!isHexColor(color)) return + const [r, g, b] = hexToRGB(color) + .replace(/(?:\(|\)|rgb|RGB)*/g, '') + .split(',') + .map((item) => Number(item)) + return r * 0.299 + g * 0.578 + b * 0.114 < 192 +} + +/** + * Darkens a HEX color given the passed percentage + * @param {string} color The color to process + * @param {number} amount The amount to change the color by + * @returns {string} The HEX representation of the processed color + */ +export const darken = (color: string, amount: number) => { + color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color + amount = Math.trunc((255 * amount) / 100) + return `#${subtractLight(color.substring(0, 2), amount)}${subtractLight( + color.substring(2, 4), + amount + )}${subtractLight(color.substring(4, 6), amount)}` +} + +/** + * Lightens a 6 char HEX color according to the passed percentage + * @param {string} color The color to change + * @param {number} amount The amount to change the color by + * @returns {string} The processed color represented as HEX + */ +export const lighten = (color: string, amount: number) => { + color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color + amount = Math.trunc((255 * amount) / 100) + return `#${addLight(color.substring(0, 2), amount)}${addLight( + color.substring(2, 4), + amount + )}${addLight(color.substring(4, 6), amount)}` +} + +/* Suma el porcentaje indicado a un color (RR, GG o BB) hexadecimal para aclararlo */ +/** + * Sums the passed percentage to the R, G or B of a HEX color + * @param {string} color The color to change + * @param {number} amount The amount to change the color by + * @returns {string} The processed part of the color + */ +const addLight = (color: string, amount: number) => { + const cc = parseInt(color, 16) + amount + const c = cc > 255 ? 255 : cc + return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}` +} + +/** + * Calculates luminance of an rgb color + * @param {number} r red + * @param {number} g green + * @param {number} b blue + */ +const luminanace = (r: number, g: number, b: number) => { + const a = [r, g, b].map((v) => { + v /= 255 + return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4) + }) + return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722 +} + +/** + * Calculates contrast between two rgb colors + * @param {string} rgb1 rgb color 1 + * @param {string} rgb2 rgb color 2 + */ +const contrast = (rgb1: string[], rgb2: number[]) => { + return ( + (luminanace(~~rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) / + (luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05) + ) +} + +/** + * Determines what the best text color is (black or white) based con the contrast with the background + * @param hexColor - Last selected color by the user + */ +export const calculateBestTextColor = (hexColor: string) => { + const rgbColor = hexToRGB(hexColor.substring(1)) + const contrastWithBlack = contrast(rgbColor.split(','), [0, 0, 0]) + + return contrastWithBlack >= 12 ? '#000000' : '#FFFFFF' +} + +/** + * Subtracts the indicated percentage to the R, G or B of a HEX color + * @param {string} color The color to change + * @param {number} amount The amount to change the color by + * @returns {string} The processed part of the color + */ +const subtractLight = (color: string, amount: number) => { + const cc = parseInt(color, 16) - amount + const c = cc < 0 ? 0 : cc + return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}` +} diff --git a/kinit-admin/src/utils/domUtils.ts b/kinit-admin/src/utils/domUtils.ts new file mode 100644 index 0000000..dbc1989 --- /dev/null +++ b/kinit-admin/src/utils/domUtils.ts @@ -0,0 +1,289 @@ +import { isServer } from './is' +const ieVersion = isServer ? 0 : Number((document as any).documentMode) +const SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g +const MOZ_HACK_REGEXP = /^moz([A-Z])/ + +export interface ViewportOffsetResult { + left: number + top: number + right: number + bottom: number + rightIncludeBody: number + bottomIncludeBody: number +} + +/* istanbul ignore next */ +const trim = function (string: string) { + return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '') +} + +/* istanbul ignore next */ +const camelCase = function (name: string) { + return name + .replace(SPECIAL_CHARS_REGEXP, function (_, __, letter, offset) { + return offset ? letter.toUpperCase() : letter + }) + .replace(MOZ_HACK_REGEXP, 'Moz$1') +} + +/* istanbul ignore next */ +export function hasClass(el: Element, cls: string) { + if (!el || !cls) return false + if (cls.indexOf(' ') !== -1) { + throw new Error('className should not contain space.') + } + if (el.classList) { + return el.classList.contains(cls) + } else { + return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1 + } +} + +/* istanbul ignore next */ +export function addClass(el: Element, cls: string) { + if (!el) return + let curClass = el.className + const classes = (cls || '').split(' ') + + for (let i = 0, j = classes.length; i < j; i++) { + const clsName = classes[i] + if (!clsName) continue + + if (el.classList) { + el.classList.add(clsName) + } else if (!hasClass(el, clsName)) { + curClass += ' ' + clsName + } + } + if (!el.classList) { + el.className = curClass + } +} + +/* istanbul ignore next */ +export function removeClass(el: Element, cls: string) { + if (!el || !cls) return + const classes = cls.split(' ') + let curClass = ' ' + el.className + ' ' + + for (let i = 0, j = classes.length; i < j; i++) { + const clsName = classes[i] + if (!clsName) continue + + if (el.classList) { + el.classList.remove(clsName) + } else if (hasClass(el, clsName)) { + curClass = curClass.replace(' ' + clsName + ' ', ' ') + } + } + if (!el.classList) { + el.className = trim(curClass) + } +} + +export function getBoundingClientRect(element: Element): DOMRect | number { + if (!element || !element.getBoundingClientRect) { + return 0 + } + return element.getBoundingClientRect() +} + +/** + * 获取当前元素的left、top偏移 + * left:元素最左侧距离文档左侧的距离 + * top:元素最顶端距离文档顶端的距离 + * right:元素最右侧距离文档右侧的距离 + * bottom:元素最底端距离文档底端的距离 + * rightIncludeBody:元素最左侧距离文档右侧的距离 + * bottomIncludeBody:元素最底端距离文档最底部的距离 + * + * @description: + */ +export function getViewportOffset(element: Element): ViewportOffsetResult { + const doc = document.documentElement + + const docScrollLeft = doc.scrollLeft + const docScrollTop = doc.scrollTop + const docClientLeft = doc.clientLeft + const docClientTop = doc.clientTop + + const pageXOffset = window.pageXOffset + const pageYOffset = window.pageYOffset + + const box = getBoundingClientRect(element) + + const { left: retLeft, top: rectTop, width: rectWidth, height: rectHeight } = box as DOMRect + + const scrollLeft = (pageXOffset || docScrollLeft) - (docClientLeft || 0) + const scrollTop = (pageYOffset || docScrollTop) - (docClientTop || 0) + const offsetLeft = retLeft + pageXOffset + const offsetTop = rectTop + pageYOffset + + const left = offsetLeft - scrollLeft + const top = offsetTop - scrollTop + + const clientWidth = window.document.documentElement.clientWidth + const clientHeight = window.document.documentElement.clientHeight + return { + left: left, + top: top, + right: clientWidth - rectWidth - left, + bottom: clientHeight - rectHeight - top, + rightIncludeBody: clientWidth - left, + bottomIncludeBody: clientHeight - top + } +} + +/* istanbul ignore next */ +export const on = function ( + element: HTMLElement | Document | Window, + event: string, + handler: EventListenerOrEventListenerObject +): void { + if (element && event && handler) { + element.addEventListener(event, handler, false) + } +} + +/* istanbul ignore next */ +export const off = function ( + element: HTMLElement | Document | Window, + event: string, + handler: any +): void { + if (element && event && handler) { + element.removeEventListener(event, handler, false) + } +} + +/* istanbul ignore next */ +export const once = function (el: HTMLElement, event: string, fn: EventListener): void { + const listener = function (this: any, ...args: unknown[]) { + if (fn) { + // @ts-ignore + fn.apply(this, args) + } + off(el, event, listener) + } + on(el, event, listener) +} + +/* istanbul ignore next */ +export const getStyle = + ieVersion < 9 + ? function (element: Element | any, styleName: string) { + if (isServer) return + if (!element || !styleName) return null + styleName = camelCase(styleName) + if (styleName === 'float') { + styleName = 'styleFloat' + } + try { + switch (styleName) { + case 'opacity': + try { + return element.filters.item('alpha').opacity / 100 + } catch (e) { + return 1.0 + } + default: + return element.style[styleName] || element.currentStyle + ? element.currentStyle[styleName] + : null + } + } catch (e) { + return element.style[styleName] + } + } + : function (element: Element | any, styleName: string) { + if (isServer) return + if (!element || !styleName) return null + styleName = camelCase(styleName) + if (styleName === 'float') { + styleName = 'cssFloat' + } + try { + const computed = (document as any).defaultView.getComputedStyle(element, '') + return element.style[styleName] || computed ? computed[styleName] : null + } catch (e) { + return element.style[styleName] + } + } + +/* istanbul ignore next */ +export function setStyle(element: Element | any, styleName: any, value: any) { + if (!element || !styleName) return + + if (typeof styleName === 'object') { + for (const prop in styleName) { + if (Object.prototype.hasOwnProperty.call(styleName, prop)) { + setStyle(element, prop, styleName[prop]) + } + } + } else { + styleName = camelCase(styleName) + if (styleName === 'opacity' && ieVersion < 9) { + element.style.filter = isNaN(value) ? '' : 'alpha(opacity=' + value * 100 + ')' + } else { + element.style[styleName] = value + } + } +} + +/* istanbul ignore next */ +export const isScroll = (el: Element, vertical: any) => { + if (isServer) return + + const determinedDirection = vertical !== null || vertical !== undefined + const overflow = determinedDirection + ? vertical + ? getStyle(el, 'overflow-y') + : getStyle(el, 'overflow-x') + : getStyle(el, 'overflow') + + return overflow.match(/(scroll|auto)/) +} + +/* istanbul ignore next */ +export const getScrollContainer = (el: Element, vertical?: any) => { + if (isServer) return + + let parent: any = el + while (parent) { + if ([window, document, document.documentElement].includes(parent)) { + return window + } + if (isScroll(parent, vertical)) { + return parent + } + parent = parent.parentNode + } + + return parent +} + +/* istanbul ignore next */ +export const isInContainer = (el: Element, container: any) => { + if (isServer || !el || !container) return false + + const elRect = el.getBoundingClientRect() + let containerRect + + if ([window, document, document.documentElement, null, undefined].includes(container)) { + containerRect = { + top: 0, + right: window.innerWidth, + bottom: window.innerHeight, + left: 0 + } + } else { + containerRect = container.getBoundingClientRect() + } + + return ( + elRect.top < containerRect.bottom && + elRect.bottom > containerRect.top && + elRect.right > containerRect.left && + elRect.left < containerRect.right + ) +} diff --git a/kinit-admin/src/utils/index.ts b/kinit-admin/src/utils/index.ts new file mode 100644 index 0000000..246de69 --- /dev/null +++ b/kinit-admin/src/utils/index.ts @@ -0,0 +1,110 @@ +// import type { Plugin } from 'vue' + +/** + * + * @param component 需要注册的组件 + * @param alias 组件别名 + * @returns any + */ +export const withInstall = (component: T, alias?: string) => { + const comp = component as any + comp.install = (app: any) => { + app.component(comp.name || comp.displayName, component) + if (alias) { + app.config.globalProperties[alias] = component + } + } + return component as T & Plugin +} + +/** + * @param str 需要转下划线的驼峰字符串 + * @returns 字符串下划线 + */ +export const humpToUnderline = (str: string): string => { + return str.replace(/([A-Z])/g, '-$1').toLowerCase() +} + +/** + * @param str 需要转驼峰的下划线字符串 + * @returns 字符串驼峰 + */ +export const underlineToHump = (str: string): string => { + if (!str) return '' + return str.replace(/\-(\w)/g, (_, letter: string) => { + return letter.toUpperCase() + }) +} + +export const setCssVar = (prop: string, val: any, dom = document.documentElement) => { + dom.style.setProperty(prop, val) +} + +/** + * 查找数组对象的某个下标 + * @param {Array} ary 查找的数组 + * @param {Functon} fn 判断的方法 + */ +// eslint-disable-next-line +export const findIndex = (ary: Array , fn: Fn): number => { + if (ary.findIndex) { + return ary.findIndex(fn) + } + let index = -1 + ary.some((item: T, i: number, ary: Array ) => { + const ret: T = fn(item, i, ary) + if (ret) { + index = i + return ret + } + }) + return index +} + +export const trim = (str: string) => { + return str.replace(/(^\s*)|(\s*$)/g, '') +} + +/** + * @param {Date | number | string} time 需要转换的时间 + * @param {String} fmt 需要转换的格式 如 yyyy-MM-dd、yyyy-MM-dd HH:mm:ss + */ +export function formatTime(time: Date | number | string, fmt: string) { + if (!time) return '' + else { + const date = new Date(time) + const o = { + 'M+': date.getMonth() + 1, + 'd+': date.getDate(), + 'H+': date.getHours(), + 'm+': date.getMinutes(), + 's+': date.getSeconds(), + 'q+': Math.floor((date.getMonth() + 3) / 3), + S: date.getMilliseconds() + } + if (/(y+)/.test(fmt)) { + fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)) + } + for (const k in o) { + if (new RegExp('(' + k + ')').test(fmt)) { + fmt = fmt.replace( + RegExp.$1, + RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length) + ) + } + } + return fmt + } +} + +/** + * 生成随机字符串 + */ +export function toAnyString() { + const str: string = 'xxxxx-xxxxx-4xxxx-yxxxx-xxxxx'.replace(/[xy]/g, (c: string) => { + const r: number = (Math.random() * 16) | 0 + const v: number = c === 'x' ? r : (r & 0x3) | 0x8 + return v.toString() + }) + return str +} diff --git a/kinit-admin/src/utils/is.ts b/kinit-admin/src/utils/is.ts new file mode 100644 index 0000000..3752985 --- /dev/null +++ b/kinit-admin/src/utils/is.ts @@ -0,0 +1,105 @@ +// copy to vben-admin + +const toString = Object.prototype.toString + +export const is = (val: unknown, type: string) => { + return toString.call(val) === `[object ${type}]` +} + +export const isDef = (val?: T): val is T => { + return typeof val !== 'undefined' +} + +export const isUnDef = (val?: T): val is T => { + return !isDef(val) +} + +export const isObject = (val: any): val is Record => { + return val !== null && is(val, 'Object') +} + +export const isEmpty = (val: T): val is T => { + if (isArray(val) || isString(val)) { + return val.length === 0 + } + + if (val instanceof Map || val instanceof Set) { + return val.size === 0 + } + + if (isObject(val)) { + return Object.keys(val).length === 0 + } + + return false +} + +export const isDate = (val: unknown): val is Date => { + return is(val, 'Date') +} + +export const isNull = (val: unknown): val is null => { + return val === null +} + +export const isNullAndUnDef = (val: unknown): val is null | undefined => { + return isUnDef(val) && isNull(val) +} + +export const isNullOrUnDef = (val: unknown): val is null | undefined => { + return isUnDef(val) || isNull(val) +} + +export const isNumber = (val: unknown): val is number => { + return is(val, 'Number') +} + +export const isPromise = (val: unknown): val is Promise => { + return is(val, 'Promise') && isObject(val) && isFunction(val.then) && isFunction(val.catch) +} + +export const isString = (val: unknown): val is string => { + return is(val, 'String') +} + +export const isFunction = (val: unknown): val is Function => { + return typeof val === 'function' +} + +export const isBoolean = (val: unknown): val is boolean => { + return is(val, 'Boolean') +} + +export const isRegExp = (val: unknown): val is RegExp => { + return is(val, 'RegExp') +} + +export const isArray = (val: any): val is Array => { + return val && Array.isArray(val) +} + +export const isWindow = (val: any): val is Window => { + return typeof window !== 'undefined' && is(val, 'Window') +} + +export const isElement = (val: unknown): val is Element => { + return isObject(val) && !!val.tagName +} + +export const isMap = (val: unknown): val is Map => { + return is(val, 'Map') +} + +export const isServer = typeof window === 'undefined' + +export const isClient = !isServer + +export const isUrl = (path: string): boolean => { + const reg = + /(((^https?:(?:\/\/)?)(?:[-:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&%@.\w_]*)#?(?:[\w]*))?)$/ + return reg.test(path) +} + +export const isDark = (): boolean => { + return window.matchMedia('(prefers-color-scheme: dark)').matches +} diff --git a/kinit-admin/src/utils/propTypes.ts b/kinit-admin/src/utils/propTypes.ts new file mode 100644 index 0000000..5d685f3 --- /dev/null +++ b/kinit-admin/src/utils/propTypes.ts @@ -0,0 +1,29 @@ +import { createTypes, VueTypesInterface, VueTypeValidableDef } from 'vue-types' +import { CSSProperties } from 'vue' + +// 自定义扩展vue-types +type PropTypes = VueTypesInterface & { + readonly style: VueTypeValidableDef