diff --git a/.eslintrc.js b/.eslintrc.js index 09aff820..d4c9c6cb 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -22,6 +22,7 @@ module.exports = defineConfig({ 'plugin:@typescript-eslint/recommended', 'prettier', 'plugin:prettier/recommended', + 'plugin:jest/recommended', ], rules: { '@typescript-eslint/ban-ts-ignore': 'off', diff --git a/.gitignore b/.gitignore index 600565c9..2f4e6611 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ test/server/static # local env files .env.local .env.*.local +.eslintcache # Log files npm-debug.log* diff --git a/.vscode/settings.json b/.vscode/settings.json index bbcf8694..86ae5732 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { - "cSpell.words": ["vben", "windi"], "typescript.tsdk": "./node_modules/typescript/lib", + "typescript.enablePromptUseWorkspaceTsdk": true, "volar.tsPlugin": true, "volar.tsPluginStatus": false, //=========================================== @@ -10,23 +10,14 @@ "editor.tabSize": 2, "editor.defaultFormatter": "esbenp.prettier-vscode", "diffEditor.ignoreTrimWhitespace": false, - "editor.trimAutoWhitespace": true, //=========================================== //============= Other ======================= //=========================================== "breadcrumbs.enabled": true, "open-in-browser.default": "chrome", //=========================================== - //============= emmet ======================= - //=========================================== - "emmet.triggerExpansionOnTab": true, - "emmet.showAbbreviationSuggestions": true, - //=========================================== //============= files ======================= //=========================================== - "files.trimTrailingWhitespace": true, - // "files.insertFinalNewline": true, - // "files.trimFinalNewlines": true, "files.eol": "\n", "search.exclude": { "**/node_modules": true, @@ -49,9 +40,14 @@ "CHANGELOG.md": true, "examples": true, "res": true, - "screenshots": true + "screenshots": true, + "yarn-error.log": true, + "**/.yarn": true }, "files.exclude": { + "**/.cache": true, + "**/.editorconfig": true, + "**/.eslintcache": true, "**/bower_components": true, "**/.idea": true, "**/tmp": true, @@ -73,17 +69,6 @@ }, "stylelint.enable": true, "stylelint.packageManager": "yarn", - // =========================================== - // ================ Vetur ==================== - // =========================================== - // "vetur.experimental.templateInterpolationService": true, - // "vetur.format.options.tabSize": 2, - // "vetur.languageFeatures.codeActions": false, - // "vetur.format.defaultFormatterOptions": { - // "js-beautify-html": { - // "wrap_attributes": "force-expand-multiline" - // } - // }, "liveServer.settings.donotShowInfoMsg": true, "telemetry.enableCrashReporter": false, "workbench.settings.enableNaturalLanguageSearch": false, @@ -132,5 +117,18 @@ "i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}", "i18n-ally.enabledParsers": ["ts"], "i18n-ally.sourceLanguage": "en", - "i18n-ally.enabledFrameworks": ["vue", "react"] + "i18n-ally.enabledFrameworks": ["vue", "react"], + "cSpell.words": [ + "vben", + "windi", + "browserslist", + "tailwindcss", + "esnext", + "antv", + "tinymce", + "qrcode", + "sider", + "pinia", + "sider" + ] } diff --git a/CHANGELOG.en_US.md b/CHANGELOG.en_US.md index 8cac9f0d..ae3619a8 100644 --- a/CHANGELOG.en_US.md +++ b/CHANGELOG.en_US.md @@ -1,3 +1,37 @@ +## 2.4.2(2021-06-10) + +### ✨ Refactor + +- `CountTo` component refactoring + +### ✨ Features + +- `radioButtonGroup` supports `boolean` value +- `useModalInner` added `redoModalHeight` to reset the height of `Modal` inside Modal +- `useECharts` added `getInstance` to obtain instances of `echart` +- `TableAction` added `stopButtonPropagation` to prevent the action button click event from bubbling +- `BasicTable` in the row edit mode, you can get or set the value of other editing components in the column +- The `ApiSelect` component will automatically re-fetch the data after the `params` is changed +- `TableImg` component improvement +- `BasicTable` added `columns-change` event to monitor the user to change the sorting, display, and fixed status of columns +- `Tinymce` supports dynamic modification readonly +- `BasicTable` added `updateTableDataRecord` method to update the specified row data +- `useModal` added `closeModal` method to close `Modal` + +### 🐛 Bug Fixes + +- Fix the problem that `redoModalHeight` cannot reduce the height +- Fix the problem that the schema data of `BasicForm` does not take effect +- Fix the problem that multiple tags may cause `KeepAlive` to fail +- Fix the problem that the default `axios` interceptor cannot handle custom code +- Fix the height issue of the lock screen pop-up window +- Fixed the problem that the half-selected state of the `Column Display` checkbox of `BaiscTable` was incorrectly displayed +- Fixed the problem that the preview list of the `BasicUpload` component could not be displayed in some cases +- Fix the problem that the `options` setting of ` RadioButtonGroup``disabled ` does not take effect +- Fix the problem that the button for uploading pictures in the read-only mode of the `Tinymce` component is still available +- Fix the stuttering problem of `BasicForm` under certain circumstances +- Fix the problem that "directory" routing does not work + ## 2.4.1(2021-06-01) ### ✨ Features diff --git a/CHANGELOG.md b/CHANGELOG.md index faa0ad89..cc1b6c5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,187 @@ +# [2.5.0](https://github.com/anncwb/vue-vben-admin/compare/v2.4.0...v2.5.0) (2021-06-20) + +### Bug Fixes + +- **api:** select api type error ([b387681](https://github.com/anncwb/vue-vben-admin/commit/b387681c00ac018f5bc6a9251009ddffe37acae6)) +- **api-select:** loss option data on event callback ([c5f2577](https://github.com/anncwb/vue-vben-admin/commit/c5f2577f515e7ae96b27b509e5dd4b3317fcb7b4)), closes [#733](https://github.com/anncwb/vue-vben-admin/issues/733) +- **ApiSelect demo:** add demo about ApiSelect's use ([#757](https://github.com/anncwb/vue-vben-admin/issues/757)) ([a03d3cc](https://github.com/anncwb/vue-vben-admin/commit/a03d3cc60c770eba644c1f3837850a2c1c015029)) +- **avatar:** mock data and Account center style ([2066f66](https://github.com/anncwb/vue-vben-admin/commit/2066f669715491f3e91ac6d0e905cd2b3e80b58d)) +- **axios:** make sure that the parameter is an object before processing, fix [#660](https://github.com/anncwb/vue-vben-admin/issues/660) ([834fa7e](https://github.com/anncwb/vue-vben-admin/commit/834fa7eb9c8aff252e083d38fdab4f6f53b4d43a)) +- **axios:** transformRequestHook logic error ([b69dcd7](https://github.com/anncwb/vue-vben-admin/commit/b69dcd79d742fd171302ce0f48c7750d60da217f)) +- **code-editor:** fix CodeEditor style problem, fix [#655](https://github.com/anncwb/vue-vben-admin/issues/655) ([5662804](https://github.com/anncwb/vue-vben-admin/commit/566280422de0537c4e31496eaaa95a9d51fe9458)) +- **codeeditor:** empty value set failed.fixed:[#659](https://github.com/anncwb/vue-vben-admin/issues/659) ([ba2bebb](https://github.com/anncwb/vue-vben-admin/commit/ba2bebb4069085817a90d065ed5877fdb50a8039)) +- **codeMirror:** fix the JsonEditor embedded in the bullet frame causing the style to be disordered ([#668](https://github.com/anncwb/vue-vben-admin/issues/668)) ([e1123a2](https://github.com/anncwb/vue-vben-admin/commit/e1123a2ccb5d5450a5072c19e5508a5dc0f14423)) +- **demo:** `breadcrumb` route invalid redirect ([84d9300](https://github.com/anncwb/vue-vben-admin/commit/84d9300e52fa73da575591aa4b71858a7e459c8c)) +- **demo:** account list page validate and save ([21f7a85](https://github.com/anncwb/vue-vben-admin/commit/21f7a854fe2455315287d04e895661ff739bce17)) +- **demo:** fix basic form page style ([8b6e07b](https://github.com/anncwb/vue-vben-admin/commit/8b6e07b768f110f13b4f2efa6c46e03266667a8c)) +- **demo:** make sure the map https resource is correct ([7b9cd09](https://github.com/anncwb/vue-vben-admin/commit/7b9cd09ad8a50c45b2e661e07953d786d82f367d)) +- **flow-chart:** fix drag and drop menu loss ([fa828fd](https://github.com/anncwb/vue-vben-admin/commit/fa828fd972efeea87f364be76a1139ae53ec20d8)) +- **form:** fix form update problem ([bcad95d](https://github.com/anncwb/vue-vben-admin/commit/bcad95d32a08a73f84ecbabab409cd64159f4077)), closes [#720](https://github.com/anncwb/vue-vben-admin/issues/720) +- **form:** loss args on component change event ([513823b](https://github.com/anncwb/vue-vben-admin/commit/513823bfbd3e8acc68098e0708c34bff2dd8dba6)) +- **form:** radioButtonGroup value support boolean ([9e2aa20](https://github.com/anncwb/vue-vben-admin/commit/9e2aa20daa08d2902cb5d56c1560306947e44939)) +- **form:** radioButtonGroup value support number ([bbddf30](https://github.com/anncwb/vue-vben-admin/commit/bbddf30e96feb1ab048323d93d3b8c1b18857acd)) +- **form:** schemas update problem ([808328d](https://github.com/anncwb/vue-vben-admin/commit/808328dc7e56b1cc07b678d501d9589290173443)), closes [#688](https://github.com/anncwb/vue-vben-admin/issues/688) +- **keep-alive:** tablist cache updating effect ([d62d0ca](https://github.com/anncwb/vue-vben-admin/commit/d62d0ca08cff442c23eb9265851b066a2f24afa8)), closes [#695](https://github.com/anncwb/vue-vben-admin/issues/695) +- **layout:** fix class loss ([d018363](https://github.com/anncwb/vue-vben-admin/commit/d018363ddcd68189a18829a2b2560f3b98da58a6)) +- **layout:** fix style compatibility issues ([905e5b7](https://github.com/anncwb/vue-vben-admin/commit/905e5b714b582548f32feca723012124343686a6)) +- **layout:** props warn ([#756](https://github.com/anncwb/vue-vben-admin/issues/756)) ([bbce002](https://github.com/anncwb/vue-vben-admin/commit/bbce002be170c52db984647c931db88d7724cb52)) +- **lock:** fix lock modal height ([40e3cb0](https://github.com/anncwb/vue-vben-admin/commit/40e3cb043c90a8343fa44a32acad2cb77de732da)), closes [#701](https://github.com/anncwb/vue-vben-admin/issues/701) +- **log:** fix Wrong version number ([#653](https://github.com/anncwb/vue-vben-admin/issues/653)) ([4f0d45f](https://github.com/anncwb/vue-vben-admin/commit/4f0d45f1df48755eadc0b09fa19762ee68f9abd1)) +- **login:** login page modal style fixed: [#662](https://github.com/anncwb/vue-vben-admin/issues/662) ([#666](https://github.com/anncwb/vue-vben-admin/issues/666)) ([b218f10](https://github.com/anncwb/vue-vben-admin/commit/b218f10e25a9364c399a5fe42eedb549f57c01ea)) +- **menu:** fix the jitter problem of menu folding animation,fix [#732](https://github.com/anncwb/vue-vben-admin/issues/732) ([4c89ea7](https://github.com/anncwb/vue-vben-admin/commit/4c89ea7474f4315870df1790f99f3e431f343b90)) +- **mock:** make sure ignore matches the file correctly, fix [#745](https://github.com/anncwb/vue-vben-admin/issues/745) ([a222ec8](https://github.com/anncwb/vue-vben-admin/commit/a222ec8553f9b4477a43a8f7d113b5646fbfc373)) +- **mock:** menu list api loss `type` field ([4185412](https://github.com/anncwb/vue-vben-admin/commit/41854121f3713dbde236afd3a416e9f27bd0c673)) +- **mock:** type error ([7c1ffa3](https://github.com/anncwb/vue-vben-admin/commit/7c1ffa3d23de508a8d1590985806cb7a484b24e5)) +- **modal:** add v-model support for visible ([de12bab](https://github.com/anncwb/vue-vben-admin/commit/de12babd314ac831d3cb645f42dbf8a476075623)) +- **modal:** ensure that the full screen height is calculated correctly ([1c1755c](https://github.com/anncwb/vue-vben-admin/commit/1c1755cf5b4ada7263c05ddf4105abb52a2abb2f)) +- **modal:** ensure that the shutdown event is not triggered multiple times ([655b743](https://github.com/anncwb/vue-vben-admin/commit/655b74323653147943cbde2352208cb765c82b8a)) +- **store:** fix type error after pinia version upgrade ([e8d6f88](https://github.com/anncwb/vue-vben-admin/commit/e8d6f8851efd7076946486864936f1797280d3ba)) +- **use-message:** `content` not support vNode ([154ebc3](https://github.com/anncwb/vue-vben-admin/commit/154ebc3d96f73bb3ceab99ea0229a3619d585aba)) +- build error ([5212ea7](https://github.com/anncwb/vue-vben-admin/commit/5212ea79b43c832a5136354b549de8f89b6e2156)) +- fix darkModeSwitch switch failure ([34a8054](https://github.com/anncwb/vue-vben-admin/commit/34a80542de670f0385dffaf5bf64bb9c3f6b90da)) +- fix if getDropdownList.length==0 show Dropdown component ([21c771b](https://github.com/anncwb/vue-vben-admin/commit/21c771b59cb45defbff37de21c5c1950370b8f92)) +- fix Login Page LocalePicker showLocale condition ([d683b0f](https://github.com/anncwb/vue-vben-admin/commit/d683b0f1e85b85b07090feba4ac7f741bd3bd482)) +- **modal:** redoModalHeight not work as expected ([5d554f1](https://github.com/anncwb/vue-vben-admin/commit/5d554f184f7b61774d1a1b2e61451677b38505de)) +- **page:** `basic form` action btns should be in line ([6c4f947](https://github.com/anncwb/vue-vben-admin/commit/6c4f947386c181f45253c94e4ef735d29a253053)) +- **radio-button:** fix RadioButton `disabled` support ([ee384b1](https://github.com/anncwb/vue-vben-admin/commit/ee384b1fa7e387b3680e9d54cbe4a1e2f15ec750)), closes [#710](https://github.com/anncwb/vue-vben-admin/issues/710) +- **route:** dynamically introduce components error ([c6b766d](https://github.com/anncwb/vue-vben-admin/commit/c6b766d8ea902294ab1f7e4a06781f2bcfdd1f0b)) +- **router:** loss `directory` route ([df8cd86](https://github.com/anncwb/vue-vben-admin/commit/df8cd860514f32f44847dcf724f0737ed4d8b9e0)), closes [#722](https://github.com/anncwb/vue-vben-admin/issues/722) +- **table:** wrong indeterminate state ([495b1da](https://github.com/anncwb/vue-vben-admin/commit/495b1da385e9b6428d2b994669d2065722445923)) +- **table:** make sure the table width is correct, fix [#593](https://github.com/anncwb/vue-vben-admin/issues/593) ([d73d43e](https://github.com/anncwb/vue-vben-admin/commit/d73d43ed91f30957cfd202c51552ca40a19cef08)) +- **table:** settings indeterminate state effect ([4fd2051](https://github.com/anncwb/vue-vben-admin/commit/4fd2051bc0403bfc5345ed6a5fc283a372ef7a92)) +- **table:** support change event ([9f4d171](https://github.com/anncwb/vue-vben-admin/commit/9f4d1719caa76de94e6362c16e4df3ac28df253c)), closes [#677](https://github.com/anncwb/vue-vben-admin/issues/677) +- **table:** try to get close to the form stuck ([d81481c](https://github.com/anncwb/vue-vben-admin/commit/d81481c52186145dac130aaa1594f0ba8db4d392)) +- **table:** useTable support onChange ([9f5085c](https://github.com/anncwb/vue-vben-admin/commit/9f5085c9f9f46b09391156b17091c1771bc13026)) +- **table-action:** fix the split line style is missing,fix [#674](https://github.com/anncwb/vue-vben-admin/issues/674) ([b1cb863](https://github.com/anncwb/vue-vben-admin/commit/b1cb86350253dc5be095466966d9469775f4395d)) +- **Tinymce:** Read only status upload button can also be used ([#718](https://github.com/anncwb/vue-vben-admin/issues/718)) ([966571b](https://github.com/anncwb/vue-vben-admin/commit/966571bdcb11c2729ab9ce212bd3e195f7bf3a59)) +- **tree:** support defaultExpandAll prop ([3ed2339](https://github.com/anncwb/vue-vben-admin/commit/3ed2339a6d75abbd6ccf723b6eaa762f9921409e)) +- **upload:** ensure preview items valid ([4376928](https://github.com/anncwb/vue-vben-admin/commit/437692869a232ee65c300c65ee473557ae0913c7)) +- **useViewHeight:** Fix the problem that useContentViewHeight does not calculate the footer ([#747](https://github.com/anncwb/vue-vben-admin/issues/747)) ([33cd8fe](https://github.com/anncwb/vue-vben-admin/commit/33cd8fe6533830176ab63ddfc4d74f75a384366c)) +- ensure that roleList is not empty ([aebad61](https://github.com/anncwb/vue-vben-admin/commit/aebad61b3d3e11aaf720b37e762e53e2e6999d3c)) +- fix node12 version data mock error ([644dbe3](https://github.com/anncwb/vue-vben-admin/commit/644dbe315bb03ea1641a682359873237208a5303)) +- Fix the problem that the `lang` attribute of `HTML` will not be set when it is first loaded ([#682](https://github.com/anncwb/vue-vben-admin/issues/682)) ([eca8907](https://github.com/anncwb/vue-vben-admin/commit/eca8907a11c28d816c3da5a0667f45a38a499012)) +- login failed ([035f55a](https://github.com/anncwb/vue-vben-admin/commit/035f55af9778819d72adc1700d9de56a6569b58f)) +- session timeout login logic error ([#678](https://github.com/anncwb/vue-vben-admin/issues/678)) ([132c7fb](https://github.com/anncwb/vue-vben-admin/commit/132c7fb944df255c4d76a25d6d924439f91f9c54)), closes [#673](https://github.com/anncwb/vue-vben-admin/issues/673) +- theme switching fails ([7e2ca79](https://github.com/anncwb/vue-vben-admin/commit/7e2ca79ece2f5209cb7ce4b0f5ee15012f9f51de)) + +### Features + +- optimize error message for api failure ([ea6834a](https://github.com/anncwb/vue-vben-admin/commit/ea6834aeec3ef56d411b2c10a474f75d3d7bfdfc)) +- **api-select:** auto refetch after params changed ([50207ad](https://github.com/anncwb/vue-vben-admin/commit/50207ad702ef3faca1e27c873c89132ab92fae8e)) +- **app-search:** auto focus on show ([1ae6362](https://github.com/anncwb/vue-vben-admin/commit/1ae636296df2cf99e8a777f053c539c50e6ad49a)) +- **axios:** added authenticationScheme configuration,fix [#774](https://github.com/anncwb/vue-vben-admin/issues/774) ([b6d5b07](https://github.com/anncwb/vue-vben-admin/commit/b6d5b0796de4d0b66c0f33c335ec991d44f64ef2)) +- **demo:** `switch` use in table ([46899aa](https://github.com/anncwb/vue-vben-admin/commit/46899aa3cd6b1616c42ac263a28af75be839f6a0)) +- **demo:** added guide page example ([d196340](https://github.com/anncwb/vue-vben-admin/commit/d196340d270d2becbf2cc81b7d4f09273381bd09)) +- **echarts:** add getInstance for useECharts ([fb6c76d](https://github.com/anncwb/vue-vben-admin/commit/fb6c76db535bd0c6305d03c0cff876a1f079100b)) +- **modal:** add closeModal for useModal ([6d5f9aa](https://github.com/anncwb/vue-vben-admin/commit/6d5f9aa699c5da8af6bf5841baddc4a8bd603917)) +- **modal:** add redoModalHeight for useModalInner ([f732b56](https://github.com/anncwb/vue-vben-admin/commit/f732b569042f7fe77c85cb295538ddd85561f7e9)) +- **preview:** added createImgPreview picture preview function ([305630e](https://github.com/anncwb/vue-vben-admin/commit/305630e3fd886b3f690f890a934a8a6ba224fba1)) +- **project-setting:** added sessionTimeoutProcessing project configuration item,fix [#772](https://github.com/anncwb/vue-vben-admin/issues/772) ([0d07084](https://github.com/anncwb/vue-vben-admin/commit/0d0708409c4adbe7a0c5e33abf5307031147eaeb)) +- **table:** add editable DatePicker & TimePicker ([#654](https://github.com/anncwb/vue-vben-admin/issues/654)) ([93006c7](https://github.com/anncwb/vue-vben-admin/commit/93006c7dc7b5243b26637f444c8057c95935e622)) +- **table:** add updateTableDataRecord method ([8e4f486](https://github.com/anncwb/vue-vben-admin/commit/8e4f486fcf835f0b6f2a95676dba268ffdd0566e)) +- **table:** editable component text align ([8eaf575](https://github.com/anncwb/vue-vben-admin/commit/8eaf57562610a833c8083ae9957f458319d1cc93)) +- **table:** support columns-change event ([125a7d1](https://github.com/anncwb/vue-vben-admin/commit/125a7d14831642c9cbb2e4b3e75953c3b2e2cdef)) +- **table:** support custom update on row editing ([fe2bcfc](https://github.com/anncwb/vue-vben-admin/commit/fe2bcfc6f74159c355f3be153a316869fdb8b644)), closes [#646](https://github.com/anncwb/vue-vben-admin/issues/646) +- **table:** updateTableDataRecord support functional rowKey ([448a4c2](https://github.com/anncwb/vue-vben-admin/commit/448a4c2809672480f8f635d7cc4661554112598a)) +- **table-action:** add stopButtonPropagation prop ([808012b](https://github.com/anncwb/vue-vben-admin/commit/808012b544b8c6f3cf467f42653c2783dbe8be6b)), closes [#699](https://github.com/anncwb/vue-vben-admin/issues/699) +- **table-img:** support simple show mode and more props ([19d8e01](https://github.com/anncwb/vue-vben-admin/commit/19d8e01e11644c66222f137abd05940cbdec0bb6)) +- **test:** add jest test suite ([f6fe1dd](https://github.com/anncwb/vue-vben-admin/commit/f6fe1dd62df231ccbd063db0d32359b48aa5c76b)) +- **use-drawer:** add closeDrawer function ([639520a](https://github.com/anncwb/vue-vben-admin/commit/639520ad5ddf829875ab517067abf2b45ebc04c2)) +- add CropperAvatar component ([8e410fc](https://github.com/anncwb/vue-vben-admin/commit/8e410fc6401847d8e5545468b5ce6fd7ce9fc5cc)) +- **tabs:** add setTabTitle method ([#680](https://github.com/anncwb/vue-vben-admin/issues/680)) ([5ddccf6](https://github.com/anncwb/vue-vben-admin/commit/5ddccf6ba28453b9a35355d53d0db65f1a8876bc)) +- **tinymce:** support dark theme and I18n ([83c9cd7](https://github.com/anncwb/vue-vben-admin/commit/83c9cd77421e9c0888a41e2d8dcbca816da67488)) +- **Tinymce:** add dynamics to the read-only state of the rich text editor ([#725](https://github.com/anncwb/vue-vben-admin/issues/725)) ([efce482](https://github.com/anncwb/vue-vben-admin/commit/efce482b3215ddf9ed588f63a218d5f76939e947)) +- **tree:** add defaultExpandLevel prop ([6edca1c](https://github.com/anncwb/vue-vben-admin/commit/6edca1c19c3b0772f9ab82a7b09251a74fff2173)), closes [#672](https://github.com/anncwb/vue-vben-admin/issues/672) + +### Performance Improvements + +- **component:** optimize tree and upload components ([3f6920f](https://github.com/anncwb/vue-vben-admin/commit/3f6920f7a9775fc06a34dead90b1724b23b7759c)) +- **cropper-avatar:** code optimization ([6dbbdba](https://github.com/anncwb/vue-vben-admin/commit/6dbbdbac76c2c3795e12dd346f6310d1b70f6a7d)) +- **i18n:** improve circular dependencies ([d677729](https://github.com/anncwb/vue-vben-admin/commit/d677729acbe2c024ab13cf490b205528507c4823)) +- **i18n:** improve warning prompt ([6ef62ba](https://github.com/anncwb/vue-vben-admin/commit/6ef62ba6ea7f5613a1fec982b30fe6b0f478bf59)) +- **locale:** reduce the number of multilingual files ([0acc4ab](https://github.com/anncwb/vue-vben-admin/commit/0acc4ab2dd70a239bd13929edede02b283feb7c2)) +- **PageWrapper:** fix the height calculation problem when footer and global footer are opened at the same time ([#760](https://github.com/anncwb/vue-vben-admin/issues/760)) ([ab2c7ef](https://github.com/anncwb/vue-vben-admin/commit/ab2c7efe6994dacfe0ff407783f2c3b246427bfc)) +- **utils:** mitt default export is changed from Class to Function ([d3d620f](https://github.com/anncwb/vue-vben-admin/commit/d3d620f4fc75dd69270e4d090a71d426701272ef)) +- add createImgPreview func ([#713](https://github.com/anncwb/vue-vben-admin/issues/713)) ([b7c7c46](https://github.com/anncwb/vue-vben-admin/commit/b7c7c46853d332641d116d818e657447884784f3)) +- optimize components and add comments ([55e9d9f](https://github.com/anncwb/vue-vben-admin/commit/55e9d9fc2953643cec95c74b6ed34b0e68641fb6)) + +## [2.4.2](https://github.com/anncwb/vue-vben-admin/compare/v2.4.0...v2.4.2) (2021-06-09) + +### Bug Fixes + +- fix darkModeSwitch switch failure ([34a8054](https://github.com/anncwb/vue-vben-admin/commit/34a80542de670f0385dffaf5bf64bb9c3f6b90da)) +- **api-select:** loss option data on event callback ([c5f2577](https://github.com/anncwb/vue-vben-admin/commit/c5f2577f515e7ae96b27b509e5dd4b3317fcb7b4)), closes [#733](https://github.com/anncwb/vue-vben-admin/issues/733) +- **avatar:** mock data and Account center style ([2066f66](https://github.com/anncwb/vue-vben-admin/commit/2066f669715491f3e91ac6d0e905cd2b3e80b58d)) +- **axios:** transformRequestHook logic error ([b69dcd7](https://github.com/anncwb/vue-vben-admin/commit/b69dcd79d742fd171302ce0f48c7750d60da217f)) +- **codeMirror:** fix the JsonEditor embedded in the bullet frame causing the style to be disordered ([#668](https://github.com/anncwb/vue-vben-admin/issues/668)) ([e1123a2](https://github.com/anncwb/vue-vben-admin/commit/e1123a2ccb5d5450a5072c19e5508a5dc0f14423)) +- **demo:** `breadcrumb` route invalid redirect ([84d9300](https://github.com/anncwb/vue-vben-admin/commit/84d9300e52fa73da575591aa4b71858a7e459c8c)) +- **demo:** account list page validate and save ([21f7a85](https://github.com/anncwb/vue-vben-admin/commit/21f7a854fe2455315287d04e895661ff739bce17)) +- **demo:** fix basic form page style ([8b6e07b](https://github.com/anncwb/vue-vben-admin/commit/8b6e07b768f110f13b4f2efa6c46e03266667a8c)) +- **demo:** make sure the map https resource is correct ([7b9cd09](https://github.com/anncwb/vue-vben-admin/commit/7b9cd09ad8a50c45b2e661e07953d786d82f367d)) +- **form:** fix form update problem ([bcad95d](https://github.com/anncwb/vue-vben-admin/commit/bcad95d32a08a73f84ecbabab409cd64159f4077)), closes [#720](https://github.com/anncwb/vue-vben-admin/issues/720) +- **form:** radioButtonGroup value support boolean ([9e2aa20](https://github.com/anncwb/vue-vben-admin/commit/9e2aa20daa08d2902cb5d56c1560306947e44939)) +- **form:** radioButtonGroup value support number ([bbddf30](https://github.com/anncwb/vue-vben-admin/commit/bbddf30e96feb1ab048323d93d3b8c1b18857acd)) +- **form:** schemas update problem ([808328d](https://github.com/anncwb/vue-vben-admin/commit/808328dc7e56b1cc07b678d501d9589290173443)), closes [#688](https://github.com/anncwb/vue-vben-admin/issues/688) +- **keep-alive:** tablist cache updating effect ([d62d0ca](https://github.com/anncwb/vue-vben-admin/commit/d62d0ca08cff442c23eb9265851b066a2f24afa8)), closes [#695](https://github.com/anncwb/vue-vben-admin/issues/695) +- **lock:** fix lock modal height ([40e3cb0](https://github.com/anncwb/vue-vben-admin/commit/40e3cb043c90a8343fa44a32acad2cb77de732da)), closes [#701](https://github.com/anncwb/vue-vben-admin/issues/701) +- **login:** login page modal style fixed: [#662](https://github.com/anncwb/vue-vben-admin/issues/662) ([#666](https://github.com/anncwb/vue-vben-admin/issues/666)) ([b218f10](https://github.com/anncwb/vue-vben-admin/commit/b218f10e25a9364c399a5fe42eedb549f57c01ea)) +- **mock:** menu list api loss `type` field ([4185412](https://github.com/anncwb/vue-vben-admin/commit/41854121f3713dbde236afd3a416e9f27bd0c673)) +- **mock:** type error ([7c1ffa3](https://github.com/anncwb/vue-vben-admin/commit/7c1ffa3d23de508a8d1590985806cb7a484b24e5)) +- **router:** loss `directory` route ([df8cd86](https://github.com/anncwb/vue-vben-admin/commit/df8cd860514f32f44847dcf724f0737ed4d8b9e0)), closes [#722](https://github.com/anncwb/vue-vben-admin/issues/722) +- build error ([5212ea7](https://github.com/anncwb/vue-vben-admin/commit/5212ea79b43c832a5136354b549de8f89b6e2156)) +- **axios:** make sure that the parameter is an object before processing, fix [#660](https://github.com/anncwb/vue-vben-admin/issues/660) ([834fa7e](https://github.com/anncwb/vue-vben-admin/commit/834fa7eb9c8aff252e083d38fdab4f6f53b4d43a)) +- **code-editor:** fix CodeEditor style problem, fix [#655](https://github.com/anncwb/vue-vben-admin/issues/655) ([5662804](https://github.com/anncwb/vue-vben-admin/commit/566280422de0537c4e31496eaaa95a9d51fe9458)) +- **codeeditor:** empty value set failed.fixed:[#659](https://github.com/anncwb/vue-vben-admin/issues/659) ([ba2bebb](https://github.com/anncwb/vue-vben-admin/commit/ba2bebb4069085817a90d065ed5877fdb50a8039)) +- **layout:** fix class loss ([d018363](https://github.com/anncwb/vue-vben-admin/commit/d018363ddcd68189a18829a2b2560f3b98da58a6)) +- **layout:** fix style compatibility issues ([905e5b7](https://github.com/anncwb/vue-vben-admin/commit/905e5b714b582548f32feca723012124343686a6)) +- **log:** fix Wrong version number ([#653](https://github.com/anncwb/vue-vben-admin/issues/653)) ([4f0d45f](https://github.com/anncwb/vue-vben-admin/commit/4f0d45f1df48755eadc0b09fa19762ee68f9abd1)) +- **modal:** redoModalHeight not work as expected ([5d554f1](https://github.com/anncwb/vue-vben-admin/commit/5d554f184f7b61774d1a1b2e61451677b38505de)) +- **page:** `basic form` action btns should be in line ([6c4f947](https://github.com/anncwb/vue-vben-admin/commit/6c4f947386c181f45253c94e4ef735d29a253053)) +- **radio-button:** fix RadioButton `disabled` support ([ee384b1](https://github.com/anncwb/vue-vben-admin/commit/ee384b1fa7e387b3680e9d54cbe4a1e2f15ec750)), closes [#710](https://github.com/anncwb/vue-vben-admin/issues/710) +- **table:** wrong indeterminate state ([495b1da](https://github.com/anncwb/vue-vben-admin/commit/495b1da385e9b6428d2b994669d2065722445923)) +- **table:** make sure the table width is correct, fix [#593](https://github.com/anncwb/vue-vben-admin/issues/593) ([d73d43e](https://github.com/anncwb/vue-vben-admin/commit/d73d43ed91f30957cfd202c51552ca40a19cef08)) +- **table:** settings indeterminate state effect ([4fd2051](https://github.com/anncwb/vue-vben-admin/commit/4fd2051bc0403bfc5345ed6a5fc283a372ef7a92)) +- **table:** support change event ([9f4d171](https://github.com/anncwb/vue-vben-admin/commit/9f4d1719caa76de94e6362c16e4df3ac28df253c)), closes [#677](https://github.com/anncwb/vue-vben-admin/issues/677) +- **table:** try to get close to the form stuck ([d81481c](https://github.com/anncwb/vue-vben-admin/commit/d81481c52186145dac130aaa1594f0ba8db4d392)) +- **Tinymce:** Read only status upload button can also be used ([#718](https://github.com/anncwb/vue-vben-admin/issues/718)) ([966571b](https://github.com/anncwb/vue-vben-admin/commit/966571bdcb11c2729ab9ce212bd3e195f7bf3a59)) +- **upload:** ensure preview items valid ([4376928](https://github.com/anncwb/vue-vben-admin/commit/437692869a232ee65c300c65ee473557ae0913c7)) +- ensure that roleList is not empty ([aebad61](https://github.com/anncwb/vue-vben-admin/commit/aebad61b3d3e11aaf720b37e762e53e2e6999d3c)) +- fix node12 version data mock error ([644dbe3](https://github.com/anncwb/vue-vben-admin/commit/644dbe315bb03ea1641a682359873237208a5303)) +- Fix the problem that the `lang` attribute of `HTML` will not be set when it is first loaded ([#682](https://github.com/anncwb/vue-vben-admin/issues/682)) ([eca8907](https://github.com/anncwb/vue-vben-admin/commit/eca8907a11c28d816c3da5a0667f45a38a499012)) +- **table:** useTable support onChange ([9f5085c](https://github.com/anncwb/vue-vben-admin/commit/9f5085c9f9f46b09391156b17091c1771bc13026)) +- **table-action:** fix the split line style is missing,fix [#674](https://github.com/anncwb/vue-vben-admin/issues/674) ([b1cb863](https://github.com/anncwb/vue-vben-admin/commit/b1cb86350253dc5be095466966d9469775f4395d)) +- login failed ([035f55a](https://github.com/anncwb/vue-vben-admin/commit/035f55af9778819d72adc1700d9de56a6569b58f)) +- session timeout login logic error ([#678](https://github.com/anncwb/vue-vben-admin/issues/678)) ([132c7fb](https://github.com/anncwb/vue-vben-admin/commit/132c7fb944df255c4d76a25d6d924439f91f9c54)), closes [#673](https://github.com/anncwb/vue-vben-admin/issues/673) +- **tree:** support defaultExpandAll prop ([3ed2339](https://github.com/anncwb/vue-vben-admin/commit/3ed2339a6d75abbd6ccf723b6eaa762f9921409e)) +- theme switching fails ([7e2ca79](https://github.com/anncwb/vue-vben-admin/commit/7e2ca79ece2f5209cb7ce4b0f5ee15012f9f51de)) + +### Features + +- **api-select:** auto refetch after params changed ([50207ad](https://github.com/anncwb/vue-vben-admin/commit/50207ad702ef3faca1e27c873c89132ab92fae8e)) +- **app-search:** auto focus on show ([1ae6362](https://github.com/anncwb/vue-vben-admin/commit/1ae636296df2cf99e8a777f053c539c50e6ad49a)) +- **demo:** `switch` use in table ([46899aa](https://github.com/anncwb/vue-vben-admin/commit/46899aa3cd6b1616c42ac263a28af75be839f6a0)) +- **echarts:** add getInstance for useECharts ([fb6c76d](https://github.com/anncwb/vue-vben-admin/commit/fb6c76db535bd0c6305d03c0cff876a1f079100b)) +- **modal:** add closeModal for useModal ([6d5f9aa](https://github.com/anncwb/vue-vben-admin/commit/6d5f9aa699c5da8af6bf5841baddc4a8bd603917)) +- **modal:** add redoModalHeight for useModalInner ([f732b56](https://github.com/anncwb/vue-vben-admin/commit/f732b569042f7fe77c85cb295538ddd85561f7e9)) +- **table:** add editable DatePicker & TimePicker ([#654](https://github.com/anncwb/vue-vben-admin/issues/654)) ([93006c7](https://github.com/anncwb/vue-vben-admin/commit/93006c7dc7b5243b26637f444c8057c95935e622)) +- **table:** add updateTableDataRecord method ([8e4f486](https://github.com/anncwb/vue-vben-admin/commit/8e4f486fcf835f0b6f2a95676dba268ffdd0566e)) +- **table:** editable component text align ([8eaf575](https://github.com/anncwb/vue-vben-admin/commit/8eaf57562610a833c8083ae9957f458319d1cc93)) +- **table:** support columns-change event ([125a7d1](https://github.com/anncwb/vue-vben-admin/commit/125a7d14831642c9cbb2e4b3e75953c3b2e2cdef)) +- **table:** support custom update on row editing ([fe2bcfc](https://github.com/anncwb/vue-vben-admin/commit/fe2bcfc6f74159c355f3be153a316869fdb8b644)), closes [#646](https://github.com/anncwb/vue-vben-admin/issues/646) +- **table:** updateTableDataRecord support functional rowKey ([448a4c2](https://github.com/anncwb/vue-vben-admin/commit/448a4c2809672480f8f635d7cc4661554112598a)) +- **table-action:** add stopButtonPropagation prop ([808012b](https://github.com/anncwb/vue-vben-admin/commit/808012b544b8c6f3cf467f42653c2783dbe8be6b)), closes [#699](https://github.com/anncwb/vue-vben-admin/issues/699) +- **table-img:** support simple show mode and more props ([19d8e01](https://github.com/anncwb/vue-vben-admin/commit/19d8e01e11644c66222f137abd05940cbdec0bb6)) +- **tabs:** add setTabTitle method ([#680](https://github.com/anncwb/vue-vben-admin/issues/680)) ([5ddccf6](https://github.com/anncwb/vue-vben-admin/commit/5ddccf6ba28453b9a35355d53d0db65f1a8876bc)) +- **tinymce:** support dark theme and I18n ([83c9cd7](https://github.com/anncwb/vue-vben-admin/commit/83c9cd77421e9c0888a41e2d8dcbca816da67488)) +- **Tinymce:** add dynamics to the read-only state of the rich text editor ([#725](https://github.com/anncwb/vue-vben-admin/issues/725)) ([efce482](https://github.com/anncwb/vue-vben-admin/commit/efce482b3215ddf9ed588f63a218d5f76939e947)) +- **tree:** add defaultExpandLevel prop ([6edca1c](https://github.com/anncwb/vue-vben-admin/commit/6edca1c19c3b0772f9ab82a7b09251a74fff2173)), closes [#672](https://github.com/anncwb/vue-vben-admin/issues/672) + +### Performance Improvements + +- optimize components and add comments ([55e9d9f](https://github.com/anncwb/vue-vben-admin/commit/55e9d9fc2953643cec95c74b6ed34b0e68641fb6)) +- **i18n:** improve circular dependencies ([d677729](https://github.com/anncwb/vue-vben-admin/commit/d677729acbe2c024ab13cf490b205528507c4823)) +- **i18n:** improve warning prompt ([6ef62ba](https://github.com/anncwb/vue-vben-admin/commit/6ef62ba6ea7f5613a1fec982b30fe6b0f478bf59)) + ## [2.4.1](https://github.com/anncwb/vue-vben-admin/compare/v2.4.0...v2.4.1) (2021-06-01) ### Bug Fixes diff --git a/CHANGELOG.zh_CN.md b/CHANGELOG.zh_CN.md index c39dc1e4..c25d4e3b 100644 --- a/CHANGELOG.zh_CN.md +++ b/CHANGELOG.zh_CN.md @@ -1,3 +1,78 @@ +## 2.5.0(2021-06-20) + +## (破坏性更新) Breaking changes + +- 将项目`windicss`改为`tailwindcss`,解决内存溢出问题 + - 目前项目不兼容地方有 + - `!xl:m-4` 之类的写法需要改为`xl:!m-4`,注意只有`!`这个不兼容,没用到则不用改 + - `windicss`自身新增的特性需要调整,比如`Attribute`模式不兼容 + +### ✨ Refactor + +- 移除`useExpose`,使用组件自身提供的`expose`代替 + +### ⚡ Performance Improvements + +- **Locale** 合并多语言文件,减少文件数量 +- **Utils** Mitt 默认导出由 `Class` 改为 `Function` +- **Axios** `isTransformRequestResult`更名为`isTransformResponse` + +### ✨ Features + +- **CropperImage** `Cropper` 头像裁剪新增圆形裁剪功能 +- **CropperAvatar** 新增头像上传组件 +- **Drawer** `useDrawer`新增`closeDrawer`函数 +- **Preview** 新增`createImgPreview`图片预览函数 +- **Setup** 新增引导页示例 +- **Tests** 添加 jest 测试套件,暂不支持 Vue 组件单测 +- **Axios** 新增`authenticationScheme`配置,用于指定认证方案 +- **Setting** 新增 `sessionTimeoutProcessing` 项目配置项,用于配置会话超时如何处理 + +### 🐛 Bug Fixes + +- **Modal** 修复全屏高度计算错误 +- **Modal** 修复关闭事件触发多次问题 +- **PageWrapper** 修复高度计算问题 +- **FlowChart** 修复拖放菜单丢失 +- 修复后台模式下,Iframe 路由错误 +- **PageWrapper** 修复 footer 与全局页脚同时开启时的高度计算问题 +- **Menu** 修复菜单折叠动画抖动问题 +- **Store**修复 pinia 版本升级之后类型错误 + +## 2.4.2(2021-06-10) + +### ✨ Refactor + +- `CountTo`组件重构 + +### ✨ Features + +- `radioButtonGroup` 支持`boolean`值 +- `useModalInner` 新增 `redoModalHeight`用于在 Modal 内部重设`Modal`高度 +- `useECharts` 新增`getInstance`用于获取`echart`实例 +- `TableAction` 新增 `stopButtonPropagation` 阻止操作按钮点击事件冒泡 +- `BasicTable` 在行编辑模式下,可以获取或设置其它处于列的编辑组件的值 +- `ApiSelect` 组件在`params`改变后会自动重新`fetch`数据 +- `TableImg` 组件改进 +- `BasicTable` 新增 `columns-change` 事件用于监听用户改变列排序、展示、固定状态 +- `Tinymce`支持动态修改 readonly +- `BasicTable`新增`updateTableDataRecord`方法用于更新指定行数据 +- `useModal`新增`closeModal`方法用于关闭`Modal` + +### 🐛 Bug Fixes + +- 修复`redoModalHeight`不能减小高度的问题 +- 修复 `BasicForm`设置 schemas 数据不生效的问题 +- 修复多标签可能导致`KeepAlive`失效的问题 +- 修复默认的`axios`拦截器不能处理自定义 code 的问题 +- 修复锁屏弹窗的高度问题 +- 修复`BaiscTable`的`列展示`复选框的半选状态显示不正确的问题 +- 修复`BasicUpload`组件的预览列表某些情况下不能显示的问题 +- 修复`RadioButtonGroup`的`options`设置`disabled`不生效的问题 +- 修复`Tinymce`组件在只读模式下上传图片的按钮仍然可用的问题 +- 修复`BasicForm`特定情况下的卡顿问题 +- 修复"目录"路由不起作用的问题 + ## 2.4.1(2021-06-01) ### ✨ Features diff --git a/build/vite/plugin/index.ts b/build/vite/plugin/index.ts index ce4e15fc..94ec6613 100644 --- a/build/vite/plugin/index.ts +++ b/build/vite/plugin/index.ts @@ -5,7 +5,6 @@ import vueJsx from '@vitejs/plugin-vue-jsx'; import legacy from '@vitejs/plugin-legacy'; import purgeIcons from 'vite-plugin-purge-icons'; -import windiCSS from 'vite-plugin-windicss'; import { configHtmlPlugin } from './html'; import { configPwaConfig } from './pwa'; @@ -46,9 +45,6 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { // vite-plugin-svg-icons vitePlugins.push(configSvgIconsPlugin(isBuild)); - // vite-plugin-windicss - vitePlugins.push(windiCSS()); - // vite-plugin-mock VITE_USE_MOCK && vitePlugins.push(configMockPlugin(isBuild)); diff --git a/jest.config.mjs b/jest.config.mjs new file mode 100644 index 00000000..162e72b3 --- /dev/null +++ b/jest.config.mjs @@ -0,0 +1,36 @@ +export default { + preset: 'ts-jest', + roots: ['/tests/'], + clearMocks: true, + moduleDirectories: ['node_modules', 'src'], + moduleFileExtensions: ['js', 'ts', 'vue', 'tsx', 'jsx', 'json', 'node'], + modulePaths: ['/src', '/node_modules'], + testMatch: [ + '**/tests/**/*.[jt]s?(x)', + '**/?(*.)+(spec|test).[tj]s?(x)', + '(/__tests__/.*|(\\.|/)(test|spec))\\.(js|ts)$', + ], + testPathIgnorePatterns: [ + '/tests/server/', + '/tests/__mocks__/', + '/node_modules/', + ], + transform: { + '^.+\\.tsx?$': 'ts-jest', + }, + transformIgnorePatterns: ['/tests/__mocks__/', '/node_modules/'], + // A map from regular expressions to module names that allow to stub out resources with a single module + moduleNameMapper: { + '\\.(vs|fs|vert|frag|glsl|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': + '/tests/__mocks__/fileMock.ts', + '\\.(sass|s?css|less)$': '/tests/__mocks__/styleMock.ts', + '\\?worker$': '/tests/__mocks__/workerMock.ts', + '^/@/(.*)$': '/src/$1', + }, + testEnvironment: 'jsdom', + verbose: true, + collectCoverage: false, + coverageDirectory: 'coverage', + collectCoverageFrom: ['src/**/*.{js,ts,vue}'], + coveragePathIgnorePatterns: ['^.+\\.d\\.ts$'], +}; diff --git a/mock/demo/select-demo.ts b/mock/demo/select-demo.ts index d962d27b..49692292 100644 --- a/mock/demo/select-demo.ts +++ b/mock/demo/select-demo.ts @@ -1,12 +1,15 @@ import { MockMethod } from 'vite-plugin-mock'; import { resultSuccess } from '../_util'; +const list: any[] = []; const demoList = (() => { - const result: any[] = []; + const result = { + list: list, + }; for (let index = 0; index < 20; index++) { - result.push({ - label: `选项${index}`, - value: `${index}`, + result.list.push({ + name: `选项${index}`, + id: `${index}`, }); } return result; @@ -15,8 +18,8 @@ const demoList = (() => { export default [ { url: '/basic-api/select/getDemoOptions', - timeout: 2000, - method: 'get', + timeout: 1000, + method: 'post', response: ({ query }) => { console.log(query); return resultSuccess(demoList); diff --git a/mock/sys/menu.ts b/mock/sys/menu.ts index c61e2164..bc7bfe02 100644 --- a/mock/sys/menu.ts +++ b/mock/sys/menu.ts @@ -168,6 +168,34 @@ const sysRoute = { ], }; +const linkRoute = { + path: '/link', + name: 'Link', + component: 'LAYOUT', + meta: { + icon: 'ion:tv-outline', + title: 'routes.demo.iframe.frame', + }, + children: [ + { + path: 'doc', + name: 'Doc', + meta: { + title: 'routes.demo.iframe.doc', + frameSrc: 'https://vvbin.cn/doc-next/', + }, + }, + { + path: 'https://vvbin.cn/doc-next/', + name: 'DocExternal', + component: 'LAYOUT', + meta: { + title: 'routes.demo.iframe.docExternal', + }, + }, + ], +}; + export default [ { url: '/basic-api/getMenuList', @@ -184,10 +212,10 @@ export default [ } const id = checkUser.userId; if (!id || id === '1') { - return resultSuccess([dashboardRoute, authRoute, levelRoute, sysRoute]); + return resultSuccess([dashboardRoute, authRoute, levelRoute, sysRoute, linkRoute]); } if (id === '2') { - return resultSuccess([dashboardRoute, authRoute, levelRoute]); + return resultSuccess([dashboardRoute, authRoute, levelRoute, linkRoute]); } }, }, diff --git a/package.json b/package.json index 97d89421..36757453 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vben-admin", - "version": "2.4.1", + "version": "2.5.0", "author": { "name": "vben", "email": "anncwb@126.com", @@ -62,11 +62,13 @@ "log": "conventional-changelog -p angular -i CHANGELOG.md -s", "clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite", "clean:lib": "rimraf node_modules", - "lint:eslint": "eslint \"{src,mock}/**/*.{vue,ts,tsx}\" --fix", + "lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix", "lint:prettier": "prettier --write --loglevel warn \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"", - "lint:stylelint": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/", + "lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/", "lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js", "lint:pretty": "pretty-quick --staged", + "test:unit": "jest", + "test:unit-coverage": "jest --coverage", "test:gzip": "http-server dist --cors --gzip -c-1", "test:br": "http-server dist --cors --brotli -c-1", "reinstall": "rimraf yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap", @@ -75,23 +77,24 @@ "postinstall": "npm run install:husky" }, "dependencies": { - "@iconify/iconify": "^2.0.1", - "@logicflow/core": "^0.4.11", - "@logicflow/extension": "^0.4.12", - "@vueuse/core": "^4.11.2", + "@iconify/iconify": "^2.0.2", + "@logicflow/core": "^0.5.0", + "@logicflow/extension": "^0.5.0", + "@vueuse/core": "^5.0.3", "@zxcvbn-ts/core": "^0.3.0", - "ant-design-vue": "2.1.2", + "ant-design-vue": "2.1.6", "axios": "^0.21.1", "codemirror": "^5.61.1", - "cropperjs": "^1.5.11", + "cropperjs": "^1.5.12", "crypto-js": "^4.0.0", - "echarts": "^5.1.1", "electron-is-dev": "^1.2.0", + "echarts": "^5.1.2", + "intro.js": "^4.1.0", "lodash-es": "^4.17.21", "mockjs": "^1.1.0", "nprogress": "^0.2.0", "path-to-regexp": "^6.2.0", - "pinia": "2.0.0-alpha.13", + "pinia": "2.0.0-beta.3", "print-js": "^1.6.0", "qrcode": "^1.4.4", "sortablejs": "^1.13.0", @@ -100,14 +103,14 @@ "vue": "3.0.11", "vue-i18n": "9.1.6", "vue-json-pretty": "^2.0.2", - "vue-router": "^4.0.8", + "vue-router": "^4.0.9", "vue-types": "^3.0.2", "xlsx": "^0.17.0" }, "devDependencies": { "@commitlint/cli": "^12.1.4", "@commitlint/config-conventional": "^12.1.4", - "@iconify/json": "^1.1.353", + "@iconify/json": "^1.1.358", "@purge-icons/generated": "^0.7.0", "@rollup/plugin-alias": "^3.1.1", "@rollup/plugin-commonjs": "^15.0.0", @@ -116,20 +119,23 @@ "@types/codemirror": "^5.60.0", "@types/crypto-js": "^4.0.1", "@types/fs-extra": "^9.0.11", - "@types/inquirer": "^7.3.1", + "@types/inquirer": "^7.3.2", + "@types/intro.js": "^3.0.1", + "@types/jest": "^26.0.23", "@types/lodash-es": "^4.17.4", "@types/mockjs": "^1.0.3", - "@types/node": "^15.12.1", + "@types/node": "^15.12.4", "@types/nprogress": "^0.2.0", "@types/qrcode": "^1.4.0", "@types/qs": "^6.9.6", "@types/sortablejs": "^1.10.6", - "@typescript-eslint/eslint-plugin": "^4.26.0", - "@typescript-eslint/parser": "^4.26.0", + "@typescript-eslint/eslint-plugin": "^4.27.0", + "@typescript-eslint/parser": "^4.27.0", "@vitejs/plugin-legacy": "^1.4.1", "@vitejs/plugin-vue": "^1.2.3", "@vitejs/plugin-vue-jsx": "^1.1.5", "@vue/compiler-sfc": "3.0.11", + "@vue/test-utils": "^2.0.0-rc.7", "autoprefixer": "^10.2.6", "commitizen": "^4.2.4", "conventional-changelog-cli": "^2.1.1", @@ -140,22 +146,25 @@ "electron-connect": "^0.6.3", "electron-contextmenu-middleware": "^1.0.3", "electron-input-menu": "^2.1.0", - "eslint": "^7.28.0", + "eslint": "^7.29.0", "eslint-config-prettier": "^8.3.0", "eslint-define-config": "^1.0.8", + "eslint-plugin-jest": "^24.3.6", "eslint-plugin-prettier": "^3.4.0", - "eslint-plugin-vue": "^7.10.0", - "esno": "^0.7.0", + "eslint-plugin-vue": "^7.11.1", + "esno": "^0.7.3", "fs-extra": "^10.0.0", "http-server": "^0.12.3", "husky": "^6.0.0", - "inquirer": "^8.1.0", + "inquirer": "^8.1.1", "is-ci": "^3.0.0", + "jest": "^27.0.4", "less": "^4.1.1", "lint-staged": "^11.0.0", - "postcss": "^8.3.0", + "npm-run-all": "^4.1.5", + "postcss": "^8.3.5", "prettier": "^2.3.1", - "pretty-quick": "^3.1.0", + "pretty-quick": "^3.1.1", "rimraf": "^3.0.2", "rollup-plugin-esbuild": "^3.0.2", "rollup-plugin-visualizer": "5.5.0", @@ -163,19 +172,20 @@ "stylelint-config-prettier": "^8.0.2", "stylelint-config-standard": "^22.0.0", "stylelint-order": "^4.1.0", + "tailwindcss": "^2.2.2", + "ts-jest": "^27.0.3", "ts-node": "^10.0.0", - "typescript": "4.3.2", - "vite": "2.3.6", + "typescript": "4.3.4", + "vite": "2.3.8", "vite-plugin-compression": "^0.2.5", "vite-plugin-html": "^2.0.7", "vite-plugin-imagemin": "^0.3.2", - "vite-plugin-mock": "^2.7.0", + "vite-plugin-mock": "^2.8.0", "vite-plugin-purge-icons": "^0.7.0", - "vite-plugin-pwa": "^0.7.3", - "vite-plugin-style-import": "^0.10.1", - "vite-plugin-svg-icons": "^0.7.0", + "vite-plugin-pwa": "^0.8.1", + "vite-plugin-style-import": "^1.0.0", + "vite-plugin-svg-icons": "^0.7.1", "vite-plugin-theme": "^0.8.1", - "vite-plugin-windicss": "^1.0.1", "vue-eslint-parser": "^7.6.0", "vue-tsc": "^0.1.7", "wait-on": "^5.2.1" @@ -183,7 +193,7 @@ "resolutions": { "//": "Used to install imagemin dependencies, because imagemin may not be installed in China. If it is abroad, you can delete it", "bin-wrapper": "npm:bin-wrapper-china", - "rollup": "^2.51.0" + "rollup": "^2.52.1" }, "repository": { "type": "git", diff --git a/postcss.config.js b/postcss.config.js index a47ef4f9..12a703d9 100755 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,5 +1,6 @@ module.exports = { plugins: { + tailwindcss: {}, autoprefixer: {}, }, }; diff --git a/src/api/demo/model/optionsModel.ts b/src/api/demo/model/optionsModel.ts index 0702aae4..c15ef8fd 100644 --- a/src/api/demo/model/optionsModel.ts +++ b/src/api/demo/model/optionsModel.ts @@ -5,7 +5,11 @@ export interface DemoOptionsItem { value: string; } +export interface selectParams { + id: number | string; +} + /** * @description: Request list return value */ -export type DemoOptionsGetResultModel = BasicFetchResult; +export type DemoOptionsGetResultModel = BasicFetchResult; diff --git a/src/api/demo/select.ts b/src/api/demo/select.ts index 30030aee..fd8c7968 100644 --- a/src/api/demo/select.ts +++ b/src/api/demo/select.ts @@ -1,6 +1,5 @@ import { defHttp } from '/@/utils/http/axios'; -import { DemoOptionsGetResultModel } from './model/optionsModel'; - +import { DemoOptionsItem, selectParams } from './model/optionsModel'; enum Api { OPTIONS_LIST = '/select/getDemoOptions', } @@ -8,5 +7,5 @@ enum Api { /** * @description: Get sample options value */ -export const optionsListApi = () => - defHttp.get({ url: Api.OPTIONS_LIST }); +export const optionsListApi = (params?: selectParams) => + defHttp.post({ url: Api.OPTIONS_LIST, params }); diff --git a/src/api/model/baseModel.ts b/src/api/model/baseModel.ts index fc040801..913f2ec8 100644 --- a/src/api/model/baseModel.ts +++ b/src/api/model/baseModel.ts @@ -4,6 +4,6 @@ export interface BasicPageParams { } export interface BasicFetchResult { - items: T; + items: T[]; total: number; } diff --git a/src/api/sys/model/menuModel.ts b/src/api/sys/model/menuModel.ts index 139c4f79..8d19eeab 100644 --- a/src/api/sys/model/menuModel.ts +++ b/src/api/sys/model/menuModel.ts @@ -1,4 +1,4 @@ -import { RouteMeta } from '/@/router/types'; +import type { RouteMeta } from 'vue-router'; export interface RouteItem { path: string; component: any; diff --git a/src/api/sys/upload.ts b/src/api/sys/upload.ts index c3a574a3..1f1b4389 100644 --- a/src/api/sys/upload.ts +++ b/src/api/sys/upload.ts @@ -1,6 +1,6 @@ import { UploadApiResult } from './model/uploadModel'; import { defHttp } from '/@/utils/http/axios'; -import { UploadFileParams } from '/@/utils/http/axios/types'; +import { UploadFileParams } from '/#/axios'; import { useGlobSetting } from '/@/hooks/setting'; const { uploadUrl = '' } = useGlobSetting(); diff --git a/src/api/sys/user.ts b/src/api/sys/user.ts index d60f2d8b..c5a08e26 100644 --- a/src/api/sys/user.ts +++ b/src/api/sys/user.ts @@ -1,7 +1,7 @@ import { defHttp } from '/@/utils/http/axios'; import { LoginParams, LoginResultModel, GetUserInfoModel } from './model/userModel'; -import { ErrorMessageMode } from '/@/utils/http/axios/types'; +import { ErrorMessageMode } from '/#/axios'; enum Api { Login = '/login', diff --git a/src/assets/svg/preview/p-rotate.svg b/src/assets/svg/preview/p-rotate.svg new file mode 100644 index 00000000..5153a816 --- /dev/null +++ b/src/assets/svg/preview/p-rotate.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg/preview/resume.svg b/src/assets/svg/preview/resume.svg new file mode 100644 index 00000000..0e86c5f6 --- /dev/null +++ b/src/assets/svg/preview/resume.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg/preview/scale.svg b/src/assets/svg/preview/scale.svg new file mode 100644 index 00000000..1f7adaee --- /dev/null +++ b/src/assets/svg/preview/scale.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg/preview/unrotate.svg b/src/assets/svg/preview/unrotate.svg new file mode 100644 index 00000000..e4708be1 --- /dev/null +++ b/src/assets/svg/preview/unrotate.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svg/preview/unscale.svg b/src/assets/svg/preview/unscale.svg new file mode 100644 index 00000000..1359b34c --- /dev/null +++ b/src/assets/svg/preview/unscale.svg @@ -0,0 +1 @@ + diff --git a/src/components/Application/index.ts b/src/components/Application/index.ts index c1b8fb8b..d7c51330 100644 --- a/src/components/Application/index.ts +++ b/src/components/Application/index.ts @@ -1,8 +1,15 @@ -import AppLogo from './src/AppLogo.vue'; -import AppProvider from './src/AppProvider.vue'; -import AppSearch from './src/search/AppSearch.vue'; -import AppLocalePicker from './src/AppLocalePicker.vue'; -import AppDarkModeToggle from './src/AppDarkModeToggle.vue'; +import { withInstall } from '/@/utils'; + +import appLogo from './src/AppLogo.vue'; +import appProvider from './src/AppProvider.vue'; +import appSearch from './src/search/AppSearch.vue'; +import appLocalePicker from './src/AppLocalePicker.vue'; +import appDarkModeToggle from './src/AppDarkModeToggle.vue'; export { useAppProviderContext } from './src/useAppContext'; -export { AppLogo, AppProvider, AppSearch, AppLocalePicker, AppDarkModeToggle }; + +export const AppLogo = withInstall(appLogo); +export const AppProvider = withInstall(appProvider); +export const AppSearch = withInstall(appSearch); +export const AppLocalePicker = withInstall(appLocalePicker); +export const AppDarkModeToggle = withInstall(appDarkModeToggle); diff --git a/src/components/Application/src/AppDarkModeToggle.vue b/src/components/Application/src/AppDarkModeToggle.vue index 9363c1ae..aac6408d 100644 --- a/src/components/Application/src/AppDarkModeToggle.vue +++ b/src/components/Application/src/AppDarkModeToggle.vue @@ -1,40 +1,35 @@ diff --git a/src/components/ContextMenu/src/createContextMenu.ts b/src/components/ContextMenu/src/createContextMenu.ts index 5fc3ed45..8f7a1c82 100644 --- a/src/components/ContextMenu/src/createContextMenu.ts +++ b/src/components/ContextMenu/src/createContextMenu.ts @@ -1,6 +1,6 @@ -import contextMenuVue from './ContextMenu'; +import contextMenuVue from './ContextMenu.vue'; import { isClient } from '/@/utils/is'; -import { CreateContextOptions, ContextMenuProps } from './types'; +import { CreateContextOptions, ContextMenuProps } from './typing'; import { createVNode, render } from 'vue'; const menuManager: { @@ -16,7 +16,9 @@ export const createContextMenu = function (options: CreateContextOptions) { event && event?.preventDefault(); - if (!isClient) return; + if (!isClient) { + return; + } return new Promise((resolve) => { const body = document.body; @@ -54,9 +56,9 @@ export const createContextMenu = function (options: CreateContextOptions) { body.removeEventListener('scroll', handleClick); }; - menuManager.resolve = function (...arg: any) { + menuManager.resolve = function (arg) { remove(); - resolve(arg[0]); + resolve(arg); }; remove(); body.appendChild(container); diff --git a/src/components/ContextMenu/src/index.less b/src/components/ContextMenu/src/index.less deleted file mode 100644 index 3d8dec03..00000000 --- a/src/components/ContextMenu/src/index.less +++ /dev/null @@ -1,65 +0,0 @@ -@default-height: 42px !important; - -@small-height: 36px !important; - -@large-height: 36px !important; - -.item-style() { - li { - display: inline-block; - width: 100%; - height: @default-height; - margin: 0 !important; - line-height: @default-height; - - span { - line-height: @default-height; - } - - > div { - margin: 0 !important; - } - - &:not(.ant-menu-item-disabled):hover { - color: @text-color-base; - background-color: @item-hover-bg; - } - } -} - -.context-menu { - position: fixed; - top: 0; - left: 0; - z-index: 200; - display: block; - width: 156px; - margin: 0; - list-style: none; - background-color: @component-background; - border: 1px solid rgba(0, 0, 0, 0.08); - border-radius: 0.25rem; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.1), - 0 1px 5px 0 rgba(0, 0, 0, 0.06); - background-clip: padding-box; - user-select: none; - - .item-style(); - - .ant-divider { - margin: 0 0; - } - - &__popup { - .ant-divider { - margin: 0 0; - } - - .item-style(); - } - - .ant-menu-submenu-title, - .ant-menu-item { - padding: 0 !important; - } -} diff --git a/src/components/ContextMenu/src/props.ts b/src/components/ContextMenu/src/props.ts deleted file mode 100644 index 509b424f..00000000 --- a/src/components/ContextMenu/src/props.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { PropType } from 'vue'; -import type { Axis, ContextMenuItem } from './types'; -import { propTypes } from '/@/utils/propTypes'; -export const contextMenuProps = { - width: propTypes.number.def(156), - customEvent: { - type: Object as PropType, - default: null, - }, - styles: propTypes.style, - showIcon: propTypes.bool.def(true), - axis: { - // The position of the right mouse button click - type: Object as PropType, - default() { - return { x: 0, y: 0 }; - }, - }, - items: { - // The most important list, if not, will not be displayed - type: Array as PropType, - default() { - return []; - }, - }, -}; diff --git a/src/components/ContextMenu/src/types.ts b/src/components/ContextMenu/src/typing.ts similarity index 100% rename from src/components/ContextMenu/src/types.ts rename to src/components/ContextMenu/src/typing.ts diff --git a/src/components/CountDown/index.ts b/src/components/CountDown/index.ts index fdcbccf0..98094169 100644 --- a/src/components/CountDown/index.ts +++ b/src/components/CountDown/index.ts @@ -1,4 +1,6 @@ -import CountButton from './src/CountButton.vue'; -import CountdownInput from './src/CountdownInput.vue'; +import { withInstall } from '/@/utils'; +import countButton from './src/CountButton.vue'; +import countdownInput from './src/CountdownInput.vue'; -export { CountdownInput, CountButton }; +export const CountdownInput = withInstall(countdownInput); +export const CountButton = withInstall(countButton); diff --git a/src/components/CountDown/src/CountButton.vue b/src/components/CountDown/src/CountButton.vue index 0f70edb0..1ef520ed 100644 --- a/src/components/CountDown/src/CountButton.vue +++ b/src/components/CountDown/src/CountButton.vue @@ -1,42 +1,44 @@ diff --git a/src/components/CountDown/src/CountdownInput.vue b/src/components/CountDown/src/CountdownInput.vue index 3f40713c..106f3cd3 100644 --- a/src/components/CountDown/src/CountdownInput.vue +++ b/src/components/CountDown/src/CountdownInput.vue @@ -1,37 +1,35 @@ diff --git a/src/components/CountTo/src/props.ts b/src/components/CountTo/src/props.ts deleted file mode 100644 index 33b35225..00000000 --- a/src/components/CountTo/src/props.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { PropType } from 'vue'; -import { propTypes } from '/@/utils/propTypes'; -export const countToProps = { - startVal: propTypes.number.def(0), - endVal: propTypes.number.def(2020), - duration: propTypes.number.def(1300), - autoplay: propTypes.bool.def(true), - decimals: { - type: Number as PropType, - required: false, - default: 0, - validator(value: number) { - return value >= 0; - }, - }, - color: { - type: String as PropType, - require: false, - }, - decimal: propTypes.string.def('.'), - separator: propTypes.string.def(','), - prefix: propTypes.string.def(''), - suffix: propTypes.string.def(''), - useEasing: propTypes.bool.def(true), - easingFn: { - type: Function as PropType<(t: number, b: number, c: number, d: number) => number>, - default(t: number, b: number, c: number, d: number) { - return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b; - }, - }, -}; diff --git a/src/components/Cropper/index.ts b/src/components/Cropper/index.ts index 31b97197..88d6d1d5 100644 --- a/src/components/Cropper/index.ts +++ b/src/components/Cropper/index.ts @@ -1,4 +1,7 @@ -import type Cropper from 'cropperjs'; +import { withInstall } from '/@/utils'; +import cropperImage from './src/Cropper.vue'; +import avatarCropper from './src/CropperAvatar.vue'; -export type { Cropper }; -export { default as CropperImage } from './src/Cropper.vue'; +export * from './src/typing'; +export const CropperImage = withInstall(cropperImage); +export const CropperAvatar = withInstall(avatarCropper); diff --git a/src/components/Cropper/src/AvatarCropper.vue b/src/components/Cropper/src/AvatarCropper.vue deleted file mode 100644 index d229fd86..00000000 --- a/src/components/Cropper/src/AvatarCropper.vue +++ /dev/null @@ -1,15 +0,0 @@ - - diff --git a/src/components/Cropper/src/CopperModal.vue b/src/components/Cropper/src/CopperModal.vue new file mode 100644 index 00000000..3883cd17 --- /dev/null +++ b/src/components/Cropper/src/CopperModal.vue @@ -0,0 +1,258 @@ + + + + diff --git a/src/components/Cropper/src/Cropper.vue b/src/components/Cropper/src/Cropper.vue index 8e16c3a6..f14737d3 100644 --- a/src/components/Cropper/src/Cropper.vue +++ b/src/components/Cropper/src/Cropper.vue @@ -1,5 +1,5 @@ + diff --git a/src/components/Preview/src/functional.ts b/src/components/Preview/src/functional.ts new file mode 100644 index 00000000..1f4ba671 --- /dev/null +++ b/src/components/Preview/src/functional.ts @@ -0,0 +1,20 @@ +import type { Options, Props } from './typing'; +import ImgPreview from './Functional.vue'; +import { isClient } from '/@/utils/is'; +import { createVNode, render } from 'vue'; + +let instance: ReturnType | null = null; +export function createImgPreview(options: Options) { + if (!isClient) return; + const { imageList, show = true, index = 0 } = options; + + const propsData: Partial = {}; + const container = document.createElement('div'); + propsData.imageList = imageList; + propsData.show = show; + propsData.index = index; + + instance = createVNode(ImgPreview, propsData); + render(instance, container); + document.body.appendChild(container); +} diff --git a/src/components/Preview/src/typing.ts b/src/components/Preview/src/typing.ts new file mode 100644 index 00000000..844b2541 --- /dev/null +++ b/src/components/Preview/src/typing.ts @@ -0,0 +1,30 @@ +export interface Options { + show?: boolean; + imageList: string[]; + index?: number; +} + +export interface Props { + show: boolean; + instance: Props; + imageList: string[]; + index: number; +} + +export interface ImageProps { + alt?: string; + fallback?: string; + src: string; + width: string | number; + height?: string | number; + placeholder?: string | boolean; + preview?: + | boolean + | { + visible?: boolean; + onVisibleChange?: (visible: boolean, prevVisible: boolean) => void; + getContainer: string | HTMLElement | (() => HTMLElement); + }; +} + +export type ImageItem = string | ImageProps; diff --git a/src/components/Qrcode/index.ts b/src/components/Qrcode/index.ts index 231b50f9..16a2f408 100644 --- a/src/components/Qrcode/index.ts +++ b/src/components/Qrcode/index.ts @@ -1,3 +1,5 @@ -export { default as QrCode } from './src/Qrcode.vue'; +import { withInstall } from '/@/utils'; +import qrCode from './src/Qrcode.vue'; -export * from './src/types'; +export const QrCode = withInstall(qrCode); +export * from './src/typing'; diff --git a/src/components/Qrcode/src/Qrcode.vue b/src/components/Qrcode/src/Qrcode.vue index f11260dd..beb80ad5 100644 --- a/src/components/Qrcode/src/Qrcode.vue +++ b/src/components/Qrcode/src/Qrcode.vue @@ -8,7 +8,7 @@ import { toCanvas, QRCodeRenderersOptions, LogoType } from './qrcodePlus'; import { toDataURL } from 'qrcode'; import { downloadByUrl } from '/@/utils/file/download'; - import { QrcodeDoneEventParams } from './types'; + import { QrcodeDoneEventParams } from './typing'; export default defineComponent({ name: 'QrCode', diff --git a/src/components/Qrcode/src/drawCanvas.ts b/src/components/Qrcode/src/drawCanvas.ts index 20a10b99..67fc4c87 100644 --- a/src/components/Qrcode/src/drawCanvas.ts +++ b/src/components/Qrcode/src/drawCanvas.ts @@ -1,6 +1,6 @@ import { toCanvas } from 'qrcode'; import type { QRCodeRenderersOptions } from 'qrcode'; -import { RenderQrCodeParams, ContentType } from './types'; +import { RenderQrCodeParams, ContentType } from './typing'; export const renderQrCode = ({ canvas, content, width = 0, options = {} }: RenderQrCodeParams) => { // 容错率,默认对内容少的二维码采用高容错率,内容多的二维码采用低容错率 options.errorCorrectionLevel = options.errorCorrectionLevel || getErrorCorrectionLevel(content); diff --git a/src/components/Qrcode/src/drawLogo.ts b/src/components/Qrcode/src/drawLogo.ts index d0c91423..85a160f2 100644 --- a/src/components/Qrcode/src/drawLogo.ts +++ b/src/components/Qrcode/src/drawLogo.ts @@ -1,12 +1,11 @@ import { isString } from '/@/utils/is'; -import { RenderQrCodeParams, LogoType } from './types'; +import { RenderQrCodeParams, LogoType } from './typing'; export const drawLogo = ({ canvas, logo }: RenderQrCodeParams) => { if (!logo) { return new Promise((resolve) => { resolve((canvas as HTMLCanvasElement).toDataURL()); }); } - const canvasWidth = (canvas as HTMLCanvasElement).width; const { logoSize = 0.15, diff --git a/src/components/Qrcode/src/qrcodePlus.ts b/src/components/Qrcode/src/qrcodePlus.ts index 00772bc7..64398617 100644 --- a/src/components/Qrcode/src/qrcodePlus.ts +++ b/src/components/Qrcode/src/qrcodePlus.ts @@ -1,5 +1,4 @@ // 参考 qr-code-with-logo 进行ts版本修改 import { toCanvas } from './toCanvas'; -export * from './types'; - +export * from './typing'; export { toCanvas }; diff --git a/src/components/Qrcode/src/toCanvas.ts b/src/components/Qrcode/src/toCanvas.ts index 30ef1570..f74d5968 100644 --- a/src/components/Qrcode/src/toCanvas.ts +++ b/src/components/Qrcode/src/toCanvas.ts @@ -1,6 +1,6 @@ import { renderQrCode } from './drawCanvas'; import { drawLogo } from './drawLogo'; -import { RenderQrCodeParams } from './types'; +import { RenderQrCodeParams } from './typing'; export const toCanvas = (options: RenderQrCodeParams) => { return renderQrCode(options) .then(() => { diff --git a/src/components/Qrcode/src/types.ts b/src/components/Qrcode/src/typing.ts similarity index 100% rename from src/components/Qrcode/src/types.ts rename to src/components/Qrcode/src/typing.ts diff --git a/src/components/SimpleMenu/src/components/Menu.vue b/src/components/SimpleMenu/src/components/Menu.vue index f7a3c2ae..e3f886ca 100644 --- a/src/components/SimpleMenu/src/components/Menu.vue +++ b/src/components/SimpleMenu/src/components/Menu.vue @@ -22,7 +22,7 @@ import { useDesign } from '/@/hooks/web/useDesign'; import { propTypes } from '/@/utils/propTypes'; import { createSimpleRootMenuContext } from './useSimpleMenuContext'; - import Mitt from '/@/utils/mitt'; + import mitt from '/@/utils/mitt'; export default defineComponent({ name: 'Menu', props: { @@ -44,7 +44,7 @@ }, emits: ['select', 'open-change'], setup(props, { emit }) { - const rootMenuEmitter = new Mitt(); + const rootMenuEmitter = mitt(); const instance = getCurrentInstance(); const currentActiveName = ref(''); diff --git a/src/components/SimpleMenu/src/components/MenuItem.vue b/src/components/SimpleMenu/src/components/MenuItem.vue index 15d5534e..222c7b62 100644 --- a/src/components/SimpleMenu/src/components/MenuItem.vue +++ b/src/components/SimpleMenu/src/components/MenuItem.vue @@ -39,9 +39,8 @@ const active = ref(false); - const { getItemStyle, getParentList, getParentMenu, getParentRootMenu } = useMenuItem( - instance - ); + const { getItemStyle, getParentList, getParentMenu, getParentRootMenu } = + useMenuItem(instance); const { prefixCls } = useDesign('menu'); diff --git a/src/components/SimpleMenu/src/components/SubMenuItem.vue b/src/components/SimpleMenu/src/components/SubMenuItem.vue index 0d24cbd7..0cc91229 100644 --- a/src/components/SimpleMenu/src/components/SubMenuItem.vue +++ b/src/components/SimpleMenu/src/components/SubMenuItem.vue @@ -77,7 +77,7 @@ import Icon from '/@/components/Icon'; import { Popover } from 'ant-design-vue'; import { isBoolean, isObject } from '/@/utils/is'; - import Mitt from '/@/utils/mitt'; + import mitt from '/@/utils/mitt'; const DELAY = 200; export default defineComponent({ @@ -109,13 +109,12 @@ isChild: false, }); - const { getParentSubMenu, getItemStyle, getParentMenu, getParentList } = useMenuItem( - instance - ); + const { getParentSubMenu, getItemStyle, getParentMenu, getParentList } = + useMenuItem(instance); const { prefixCls } = useDesign('menu'); - const subMenuEmitter = new Mitt(); + const subMenuEmitter = mitt(); const { rootMenuEmitter } = useSimpleRootMenuContext(); @@ -148,13 +147,11 @@ const getCollapse = computed(() => rootProps.collapse); const getTheme = computed(() => rootProps.theme); - const getOverlayStyle = computed( - (): CSSProperties => { - return { - minWidth: '200px', - }; - } - ); + const getOverlayStyle = computed((): CSSProperties => { + return { + minWidth: '200px', + }; + }); const getIsOpend = computed(() => { const name = props.name; @@ -276,8 +273,7 @@ state.opened = data; return; } - - if (isObject(data)) { + if (isObject(data) && rootProps.accordion) { const { opend, parent, uidList } = data as Recordable; if (parent === instance?.parent) { state.opened = opend; diff --git a/src/components/SimpleMenu/src/components/useMenu.ts b/src/components/SimpleMenu/src/components/useMenu.ts index beb4c840..8830559d 100644 --- a/src/components/SimpleMenu/src/components/useMenu.ts +++ b/src/components/SimpleMenu/src/components/useMenu.ts @@ -14,26 +14,24 @@ export function useMenuItem(instance: ComponentInternalInstance | null) { return findParentMenu(['SubMenu']); }); - const getItemStyle = computed( - (): CSSProperties => { - let parent = instance?.parent; - if (!parent) return {}; - const indentSize = (unref(getParentRootMenu)?.props.indentSize as number) ?? 20; - let padding = indentSize; + const getItemStyle = computed((): CSSProperties => { + let parent = instance?.parent; + if (!parent) return {}; + const indentSize = (unref(getParentRootMenu)?.props.indentSize as number) ?? 20; + let padding = indentSize; - if (unref(getParentRootMenu)?.props.collapse) { - padding = indentSize; - } else { - while (parent && parent.type.name !== 'Menu') { - if (parent.type.name === 'SubMenu') { - padding += indentSize; - } - parent = parent.parent; + if (unref(getParentRootMenu)?.props.collapse) { + padding = indentSize; + } else { + while (parent && parent.type.name !== 'Menu') { + if (parent.type.name === 'SubMenu') { + padding += indentSize; } + parent = parent.parent; } - return { paddingLeft: padding + 'px' }; } - ); + return { paddingLeft: padding + 'px' }; + }); function findParentMenu(name: string[]) { let parent = instance?.parent; diff --git a/src/components/SimpleMenu/src/components/useSimpleMenuContext.ts b/src/components/SimpleMenu/src/components/useSimpleMenuContext.ts index a79882f7..d6e21036 100644 --- a/src/components/SimpleMenu/src/components/useSimpleMenuContext.ts +++ b/src/components/SimpleMenu/src/components/useSimpleMenuContext.ts @@ -1,9 +1,9 @@ import type { InjectionKey, Ref } from 'vue'; import { createContext, useContext } from '/@/hooks/core/useContext'; -import Mitt from '/@/utils/mitt'; +import mitt from '/@/utils/mitt'; export interface SimpleRootMenuContextProps { - rootMenuEmitter: Mitt; + rootMenuEmitter: typeof mitt; activeName: Ref; } diff --git a/src/components/StrengthMeter/index.ts b/src/components/StrengthMeter/index.ts index e5030831..9763afab 100644 --- a/src/components/StrengthMeter/index.ts +++ b/src/components/StrengthMeter/index.ts @@ -1 +1,4 @@ -export { default as StrengthMeter } from './src/StrengthMeter.vue'; +import { withInstall } from '/@/utils'; +import strengthMeter from './src/StrengthMeter.vue'; + +export const StrengthMeter = withInstall(strengthMeter); diff --git a/src/components/StrengthMeter/src/StrengthMeter.vue b/src/components/StrengthMeter/src/StrengthMeter.vue index b900dbe2..9b56457e 100644 --- a/src/components/StrengthMeter/src/StrengthMeter.vue +++ b/src/components/StrengthMeter/src/StrengthMeter.vue @@ -20,10 +20,7 @@ diff --git a/src/components/Table/src/components/HeaderCell.vue b/src/components/Table/src/components/HeaderCell.vue index 47dbebb1..4c75682f 100644 --- a/src/components/Table/src/components/HeaderCell.vue +++ b/src/components/Table/src/components/HeaderCell.vue @@ -8,12 +8,11 @@ + diff --git a/src/components/Upload/src/UploadModal.vue b/src/components/Upload/src/UploadModal.vue index 5e1faba1..0e99f8e9 100644 --- a/src/components/Upload/src/UploadModal.vue +++ b/src/components/Upload/src/UploadModal.vue @@ -50,7 +50,7 @@ import { useUploadType } from './useUpload'; import { useMessage } from '/@/hooks/web/useMessage'; // types - import { FileItem, UploadResultStatus } from './types'; + import { FileItem, UploadResultStatus } from './typing'; import { basicProps } from './props'; import { createTableColumns, createActionColumn } from './data'; // utils @@ -58,9 +58,9 @@ import { buildUUID } from '/@/utils/uuid'; import { isFunction } from '/@/utils/is'; import { warn } from '/@/utils/log'; - import FileList from './FileList'; - + import FileList from './FileList.vue'; import { useI18n } from '/@/hooks/web/useI18n'; + export default defineComponent({ components: { BasicModal, Upload, Alert, FileList }, props: { @@ -70,20 +70,20 @@ default: () => [], }, }, - emits: ['change', 'register'], + emits: ['change', 'register', 'delete'], setup(props, { emit }) { - const { t } = useI18n(); - - // 是否正在上传 - const isUploadingRef = ref(false); - const fileListRef = ref([]); const state = reactive<{ fileList: FileItem[] }>({ fileList: [], }); + // 是否正在上传 + const isUploadingRef = ref(false); + const fileListRef = ref([]); + const { accept, helpText, maxNumber, maxSize } = toRefs(props); + + const { t } = useI18n(); const [register, { closeModal }] = useModalInner(); - const { accept, helpText, maxNumber, maxSize } = toRefs(props); const { getAccept, getStringAccept, getHelpText } = useUploadType({ acceptRef: accept, helpTextRef: helpText, @@ -162,10 +162,12 @@ } return false; } + // 删除 function handleRemove(record: FileItem) { const index = fileListRef.value.findIndex((item) => item.uuid === record.uuid); index !== -1 && fileListRef.value.splice(index, 1); + emit('delete', record); } // 预览 @@ -263,7 +265,7 @@ } // 点击关闭:则所有操作不保存,包括上传的 - function handleCloseFunc() { + async function handleCloseFunc() { if (!isUploadingRef.value) { fileListRef.value = []; return true; diff --git a/src/components/Upload/src/UploadPreviewModal.vue b/src/components/Upload/src/UploadPreviewModal.vue index 9929aff0..dca152ab 100644 --- a/src/components/Upload/src/UploadPreviewModal.vue +++ b/src/components/Upload/src/UploadPreviewModal.vue @@ -12,18 +12,15 @@ + diff --git a/src/components/Verify/src/ImgRotate.less b/src/components/Verify/src/ImgRotate.less deleted file mode 100644 index 10911b7c..00000000 --- a/src/components/Verify/src/ImgRotate.less +++ /dev/null @@ -1,51 +0,0 @@ -.ir-dv { - position: relative; - display: flex; - flex-direction: column; - align-items: center; - - &-img__wrap { - position: relative; - overflow: hidden; - border-radius: 50%; - - img { - width: 100%; - border-radius: 50%; - - &.to-origin { - transition: transform 0.3s; - } - } - } - - &-img__tip { - position: absolute; - bottom: 10px; - left: 0; - z-index: 1; - display: block; - width: 100%; - height: 30px; - font-size: 12px; - line-height: 30px; - color: @white; - text-align: center; - - &.success { - background-color: fade(@success-color, 60%); - } - - &.error { - background-color: fade(@error-color, 60%); - } - - &.normal { - background-color: rgba(0, 0, 0, 0.3); - } - } - - &-drag__bar { - margin-top: 20px; - } -} diff --git a/src/components/Verify/src/ImgRotate.tsx b/src/components/Verify/src/ImgRotate.tsx deleted file mode 100644 index fea4dda6..00000000 --- a/src/components/Verify/src/ImgRotate.tsx +++ /dev/null @@ -1,172 +0,0 @@ -import './ImgRotate.less'; - -import type { MoveData, DragVerifyActionType } from './types'; - -import { defineComponent, computed, unref, reactive, watch, ref, getCurrentInstance } from 'vue'; -import { useTimeoutFn } from '/@/hooks/core/useTimeout'; - -import BasicDragVerify from './DragVerify'; - -import { hackCss } from '/@/utils/domUtils'; - -import { rotateProps } from './props'; -import { useI18n } from '/@/hooks/web/useI18n'; - -export default defineComponent({ - name: 'ImgRotateDargVerify', - inheritAttrs: false, - props: rotateProps, - emits: ['success', 'change', 'update:value'], - setup(props, { emit, attrs }) { - const basicRef = ref>(null); - const state = reactive({ - showTip: false, - isPassing: false, - imgStyle: {}, - randomRotate: 0, - currentRotate: 0, - toOrigin: false, - startTime: 0, - endTime: 0, - draged: false, - }); - const { t } = useI18n(); - - watch( - () => state.isPassing, - (isPassing) => { - if (isPassing) { - const { startTime, endTime } = state; - const time = (endTime - startTime) / 1000; - emit('success', { isPassing, time: time.toFixed(1) }); - emit('change', isPassing); - emit('update:value', isPassing); - } - } - ); - - const getImgWrapStyleRef = computed(() => { - const { imgWrapStyle, imgWidth } = props; - return { - width: `${imgWidth}px`, - height: `${imgWidth}px`, - ...imgWrapStyle, - }; - }); - - const getFactorRef = computed(() => { - const { minDegree, maxDegree } = props; - if (minDegree === maxDegree) { - return Math.floor(1 + Math.random() * 1) / 10 + 1; - } - return 1; - }); - function handleStart() { - state.startTime = new Date().getTime(); - } - - function handleDragBarMove(data: MoveData) { - state.draged = true; - const { imgWidth, height, maxDegree } = props; - const { moveX } = data; - const currentRotate = Math.ceil( - (moveX / (imgWidth! - parseInt(height as string))) * maxDegree! * unref(getFactorRef) - ); - state.currentRotate = currentRotate; - state.imgStyle = hackCss('transform', `rotateZ(${state.randomRotate - currentRotate}deg)`); - } - - function handleImgOnLoad() { - const { minDegree, maxDegree } = props; - const ranRotate = Math.floor(minDegree! + Math.random() * (maxDegree! - minDegree!)); // 生成随机角度 - state.randomRotate = ranRotate; - state.imgStyle = hackCss('transform', `rotateZ(${ranRotate}deg)`); - } - - function handleDragEnd() { - const { randomRotate, currentRotate } = state; - const { diffDegree } = props; - - if (Math.abs(randomRotate - currentRotate) >= (diffDegree || 20)) { - state.imgStyle = hackCss('transform', `rotateZ(${randomRotate}deg)`); - state.toOrigin = true; - useTimeoutFn(() => { - state.toOrigin = false; - state.showTip = true; - // 时间与动画时间保持一致 - }, 300); - } else { - checkPass(); - } - state.showTip = true; - } - function checkPass() { - state.isPassing = true; - state.endTime = new Date().getTime(); - } - - function resume() { - state.showTip = false; - const basicEl = unref(basicRef); - if (!basicEl) { - return; - } - state.isPassing = false; - - basicEl.resume(); - handleImgOnLoad(); - } - - const instance = getCurrentInstance() as any; - if (instance) { - instance.resume = resume; - } - // handleImgOnLoad(); - return () => { - const { src } = props; - const { toOrigin, isPassing, startTime, endTime } = state; - const imgCls: string[] = []; - if (toOrigin) { - imgCls.push('to-origin'); - } - const time = (endTime - startTime) / 1000; - - return ( -
-
- { - resume(); - }} - /> - {state.showTip && ( - - {state.isPassing - ? t('component.verify.time', { time: time.toFixed(1) }) - : t('component.verify.error')} - - )} - {!state.showTip && !state.draged && ( - {t('component.verify.redoTip')} - )} -
- -
- ); - }; - }, -}); diff --git a/src/components/Verify/src/ImgRotate.vue b/src/components/Verify/src/ImgRotate.vue new file mode 100644 index 00000000..a40d5f0f --- /dev/null +++ b/src/components/Verify/src/ImgRotate.vue @@ -0,0 +1,221 @@ + + diff --git a/src/components/Verify/src/types.ts b/src/components/Verify/src/typing.ts similarity index 100% rename from src/components/Verify/src/types.ts rename to src/components/Verify/src/typing.ts diff --git a/src/components/VirtualScroll/index.ts b/src/components/VirtualScroll/index.ts index 84af1bca..a4c60897 100644 --- a/src/components/VirtualScroll/index.ts +++ b/src/components/VirtualScroll/index.ts @@ -1,3 +1,4 @@ -import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; +import { withInstall } from '/@/utils/index'; +import vScroll from './src/VirtualScroll.vue'; -export const VScroll = createAsyncComponent(() => import('./src/VirtualScroll')); +export const VScroll = withInstall(vScroll); diff --git a/src/components/VirtualScroll/src/VirtualScroll.tsx b/src/components/VirtualScroll/src/VirtualScroll.tsx deleted file mode 100644 index 3c78868f..00000000 --- a/src/components/VirtualScroll/src/VirtualScroll.tsx +++ /dev/null @@ -1,148 +0,0 @@ -import { - defineComponent, - computed, - ref, - unref, - reactive, - onMounted, - watch, - nextTick, - CSSProperties, -} from 'vue'; -import { useEventListener } from '/@/hooks/event/useEventListener'; - -import { props as basicProps } from './props'; -import { getSlot } from '/@/utils/helper/tsxHelper'; -import './index.less'; - -const prefixCls = 'virtual-scroll'; - -function convertToUnit(str: string | number | null | undefined, unit = 'px'): string | undefined { - if (str == null || str === '') { - return undefined; - } else if (isNaN(+str!)) { - return String(str); - } else { - return `${Number(str)}${unit}`; - } -} - -export default defineComponent({ - name: 'VirtualScroll', - props: basicProps, - setup(props, { slots }) { - const wrapElRef = ref(null); - const state = reactive({ - first: 0, - last: 0, - scrollTop: 0, - }); - - const getBenchRef = computed(() => { - return parseInt(props.bench as string, 10); - }); - - const getItemHeightRef = computed(() => { - return parseInt(props.itemHeight as string, 10); - }); - - const getFirstToRenderRef = computed(() => { - return Math.max(0, state.first - unref(getBenchRef)); - }); - - const getLastToRenderRef = computed(() => { - return Math.min((props.items || []).length, state.last + unref(getBenchRef)); - }); - - const getContainerStyleRef = computed((): CSSProperties => { - return { - height: convertToUnit((props.items || []).length * unref(getItemHeightRef)), - }; - }); - - const getWrapStyleRef = computed((): CSSProperties => { - const styles: Recordable = {}; - const height = convertToUnit(props.height); - const minHeight = convertToUnit(props.minHeight); - const minWidth = convertToUnit(props.minWidth); - const maxHeight = convertToUnit(props.maxHeight); - const maxWidth = convertToUnit(props.maxWidth); - const width = convertToUnit(props.width); - - if (height) styles.height = height; - if (minHeight) styles.minHeight = minHeight; - if (minWidth) styles.minWidth = minWidth; - if (maxHeight) styles.maxHeight = maxHeight; - if (maxWidth) styles.maxWidth = maxWidth; - if (width) styles.width = width; - return styles; - }); - - watch([() => props.itemHeight, () => props.height], () => { - onScroll(); - }); - - function getLast(first: number): number { - const wrapEl = unref(wrapElRef); - if (!wrapEl) { - return 0; - } - const height = parseInt(props.height || 0, 10) || wrapEl.clientHeight; - - return first + Math.ceil(height / unref(getItemHeightRef)); - } - - function getFirst(): number { - return Math.floor(state.scrollTop / unref(getItemHeightRef)); - } - - function onScroll() { - const wrapEl = unref(wrapElRef); - if (!wrapEl) { - return; - } - state.scrollTop = wrapEl.scrollTop; - state.first = getFirst(); - state.last = getLast(state.first); - } - - function renderChildren() { - const { items = [] } = props; - return items.slice(unref(getFirstToRenderRef), unref(getLastToRenderRef)).map(genChild); - } - - function genChild(item: any, index: number) { - index += unref(getFirstToRenderRef); - - const top = convertToUnit(index * unref(getItemHeightRef)); - return ( -
- {getSlot(slots, 'default', { index, item })} -
- ); - } - - onMounted(() => { - state.last = getLast(0); - nextTick(() => { - const wrapEl = unref(wrapElRef); - if (!wrapEl) { - return; - } - useEventListener({ - el: wrapEl, - name: 'scroll', - listener: onScroll, - wait: 0, - }); - }); - }); - return () => ( -
-
- {renderChildren()} -
-
- ); - }, -}); diff --git a/src/components/VirtualScroll/src/VirtualScroll.vue b/src/components/VirtualScroll/src/VirtualScroll.vue new file mode 100644 index 00000000..b37a0587 --- /dev/null +++ b/src/components/VirtualScroll/src/VirtualScroll.vue @@ -0,0 +1,190 @@ + + diff --git a/src/components/VirtualScroll/src/index.less b/src/components/VirtualScroll/src/index.less deleted file mode 100644 index 2483282a..00000000 --- a/src/components/VirtualScroll/src/index.less +++ /dev/null @@ -1,18 +0,0 @@ -.virtual-scroll { - position: relative; - display: block; - width: 100%; - max-width: 100%; - overflow: auto; - flex: 1 1 auto; - - &__container { - display: block; - } - - &__item { - position: absolute; - right: 0; - left: 0; - } -} diff --git a/src/components/VirtualScroll/src/props.ts b/src/components/VirtualScroll/src/props.ts deleted file mode 100644 index 4e33bd41..00000000 --- a/src/components/VirtualScroll/src/props.ts +++ /dev/null @@ -1,27 +0,0 @@ -// Helpers - -import type { PropType } from 'vue'; -// Types - -export type NumberOrNumberString = PropType; - -export const props = { - height: [Number, String] as NumberOrNumberString, - maxHeight: [Number, String] as NumberOrNumberString, - maxWidth: [Number, String] as NumberOrNumberString, - minHeight: [Number, String] as NumberOrNumberString, - minWidth: [Number, String] as NumberOrNumberString, - width: [Number, String] as NumberOrNumberString, - bench: { - type: [Number, String] as NumberOrNumberString, - default: 0, - }, - itemHeight: { - type: [Number, String] as NumberOrNumberString, - required: true, - }, - items: { - type: Array as PropType, - default: () => [], - }, -}; diff --git a/src/components/registerGlobComp.ts b/src/components/registerGlobComp.ts index 0e758ec9..c9511740 100644 --- a/src/components/registerGlobComp.ts +++ b/src/components/registerGlobComp.ts @@ -1,16 +1,18 @@ -import Icon from './Icon/index'; +import type { App } from 'vue'; +import { Icon } from './Icon'; import { Button } from './Button'; import { // Need Button as AntButton, + Input, } from 'ant-design-vue'; -import { App } from 'vue'; - -const compList = [Icon, Button, AntButton.Group]; +const compList = [Icon, AntButton.Group]; export function registerGlobComp(app: App) { - compList.forEach((comp: any) => { + compList.forEach((comp) => { app.component(comp.name || comp.displayName, comp); }); + + app.use(Input).use(Button); } diff --git a/src/design/tailwind.css b/src/design/tailwind.css new file mode 100644 index 00000000..254f058f --- /dev/null +++ b/src/design/tailwind.css @@ -0,0 +1,1742 @@ +/*! tailwindcss v2.2.0 | MIT License | https://tailwindcss.com */ + +/*! modern-normalize v1.1.0 | MIT License | https://github.com/sindresorhus/modern-normalize */ + +/* +Document +======== +*/ + +/** +Use a better box model (opinionated). +*/ + +*, +::before, +::after { + box-sizing: border-box; +} + +/** +Use a more readable tab size (opinionated). +*/ + +html { + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; +} + +/** +1. Correct the line height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +*/ + +html { + line-height: 1.15; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ +} + +/* +Sections +======== +*/ + +/** +Remove the margin in all browsers. +*/ + +body { + margin: 0; +} + +/** +Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) +*/ + +body { + font-family: system-ui, -apple-system, + /* Firefox supports this but not yet `system-ui` */ 'Segoe UI', Roboto, Helvetica, Arial, + sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'; +} + +/* +Grouping content +================ +*/ + +/** +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +*/ + +hr { + height: 0; + /* 1 */ + color: inherit; + /* 2 */ +} + +/* +Text-level semantics +==================== +*/ + +/** +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr[title] { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +/** +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/** +1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) +2. Correct the odd 'em' font sizing in all browsers. +*/ + +code, +kbd, +samp, +pre { + font-family: ui-monospace, SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace; + /* 1 */ + font-size: 1em; + /* 2 */ +} + +/** +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/** +Prevent 'sub' and 'sup' elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* +Tabular data +============ +*/ + +/** +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +*/ + +table { + text-indent: 0; + /* 1 */ + border-color: inherit; + /* 2 */ +} + +/* +Forms +===== +*/ + +/** +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + line-height: 1.15; + /* 1 */ + margin: 0; + /* 2 */ +} + +/** +Remove the inheritance of text transform in Edge and Firefox. +1. Remove the inheritance of text transform in Firefox. +*/ + +button, +select { + /* 1 */ + text-transform: none; +} + +/** +Correct the inability to style clickable types in iOS and Safari. +*/ + +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; +} + +/** +Remove the inner border and padding in Firefox. +*/ + +::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** +Restore the focus styles unset by the previous rule. +*/ + +:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** +Remove the additional ':invalid' styles in Firefox. +See: https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737 +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/** +Remove the padding so developers are not caught out when they zero out 'fieldset' elements in all browsers. +*/ + +legend { + padding: 0; +} + +/** +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/** +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/** +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} + +/** +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to 'inherit' in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ +} + +/* +Interactive +=========== +*/ + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; +} + +/** + * Manually forked from SUIT CSS Base: https://github.com/suitcss/base + * A thin layer on top of normalize.css that provides a starting point more + * suitable for web applications. + */ + +/** + * Removes the default spacing and border for appropriate elements. + */ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +button { + background-color: transparent; + background-image: none; +} + +/** + * Work around a Firefox/IE bug where the transparent `button` background + * results in a loss of the default `button` focus styles. + */ + +button:focus { + outline: 1px dotted; + outline: 5px auto -webkit-focus-ring-color; +} + +fieldset { + margin: 0; + padding: 0; +} + +ol, +ul { + list-style: none; + margin: 0; + padding: 0; +} + +/** + * Tailwind custom reset styles + */ + +/** + * 1. Use the user's configured `sans` font-family (with Tailwind's default + * sans-serif font stack as a fallback) as a sane default. + * 2. Use Tailwind's default "normal" line-height so the user isn't forced + * to override it to ensure consistency even when using the default theme. + */ + +html { + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, + 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', + 'Segoe UI Symbol', 'Noto Color Emoji'; + /* 1 */ + line-height: 1.5; + /* 2 */ +} + +/** + * Inherit font-family and line-height from `html` so users can set them as + * a class directly on the `html` element. + */ + +body { + font-family: inherit; + line-height: inherit; +} + +/** + * 1. Prevent padding and border from affecting element width. + * + * We used to set this in the html element and inherit from + * the parent element for everything else. This caused issues + * in shadow-dom-enhanced elements like
where the content + * is wrapped by a div with box-sizing set to `content-box`. + * + * https://github.com/mozdevs/cssremedy/issues/4 + * + * + * 2. Allow adding a border to an element by just adding a border-width. + * + * By default, the way the browser specifies that an element should have no + * border is by setting it's border-style to `none` in the user-agent + * stylesheet. + * + * In order to easily add borders to elements by just setting the `border-width` + * property, we change the default border-style for all elements to `solid`, and + * use border-width to hide them instead. This way our `border` utilities only + * need to set the `border-width` property instead of the entire `border` + * shorthand, making our border utilities much more straightforward to compose. + * + * https://github.com/tailwindcss/tailwindcss/pull/116 + */ + +*, +::before, +::after { + box-sizing: border-box; + /* 1 */ + border-width: 0; + /* 2 */ + border-style: solid; + /* 2 */ + border-color: currentColor; + /* 2 */ +} + +/* + * Ensure horizontal rules are visible by default + */ + +hr { + border-top-width: 1px; +} + +/** + * Undo the `border-style: none` reset that Normalize applies to images so that + * our `border-{width}` utilities have the expected effect. + * + * The Normalize reset is unnecessary for us since we default the border-width + * to 0 on all elements. + * + * https://github.com/tailwindcss/tailwindcss/issues/362 + */ + +img { + border-style: solid; +} + +textarea { + resize: vertical; +} + +input::-moz-placeholder, +textarea::-moz-placeholder { + opacity: 1; + color: #a1a1aa; +} + +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { + opacity: 1; + color: #a1a1aa; +} + +input::placeholder, +textarea::placeholder { + opacity: 1; + color: #a1a1aa; +} + +button, +[role='button'] { + cursor: pointer; +} + +table { + border-collapse: collapse; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/** + * Reset links to optimize for opt-in styling instead of + * opt-out. + */ + +a { + color: inherit; + text-decoration: inherit; +} + +/** + * Reset form element properties that are easy to forget to + * style explicitly so you don't inadvertently introduce + * styles that deviate from your design system. These styles + * supplement a partial reset that is already applied by + * normalize.css. + */ + +button, +input, +optgroup, +select, +textarea { + padding: 0; + line-height: inherit; + color: inherit; +} + +/** + * Use the configured 'mono' font family for elements that + * are expected to be rendered with a monospace font, falling + * back to the system monospace stack if there is no configured + * 'mono' font family. + */ + +pre, +code, +kbd, +samp { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', + 'Courier New', monospace; +} + +/** + * 1. Make replaced elements `display: block` by default as that's + * the behavior you want almost all of the time. Inspired by + * CSS Remedy, with `svg` added as well. + * + * https://github.com/mozdevs/cssremedy/issues/14 + * + * 2. Add `vertical-align: middle` to align replaced elements more + * sensibly by default when overriding `display` by adding a + * utility like `inline`. + * + * This can trigger a poorly considered linting error in some + * tools but is included by design. + * + * https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210 + */ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; + /* 1 */ + vertical-align: middle; + /* 2 */ +} + +/** + * Constrain images and videos to the parent width and preserve + * their intrinsic aspect ratio. + * + * https://github.com/mozdevs/cssremedy/issues/14 + */ + +img, +video { + max-width: 100%; + height: auto; +} + +*, +::before, +::after { + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-transform: translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) + rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) + scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + --tw-border-opacity: 1; + border-color: rgba(228, 228, 231, var(--tw-border-opacity)); + --tw-shadow: 0 0 #0000; + --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/); + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgba(59, 130, 246, 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-blur: var(--tw-empty, /*!*/ /*!*/); + --tw-brightness: var(--tw-empty, /*!*/ /*!*/); + --tw-contrast: var(--tw-empty, /*!*/ /*!*/); + --tw-grayscale: var(--tw-empty, /*!*/ /*!*/); + --tw-hue-rotate: var(--tw-empty, /*!*/ /*!*/); + --tw-invert: var(--tw-empty, /*!*/ /*!*/); + --tw-saturate: var(--tw-empty, /*!*/ /*!*/); + --tw-sepia: var(--tw-empty, /*!*/ /*!*/); + --tw-drop-shadow: var(--tw-empty, /*!*/ /*!*/); + --tw-filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) + var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); + --tw-backdrop-blur: var(--tw-empty, /*!*/ /*!*/); + --tw-backdrop-brightness: var(--tw-empty, /*!*/ /*!*/); + --tw-backdrop-contrast: var(--tw-empty, /*!*/ /*!*/); + --tw-backdrop-grayscale: var(--tw-empty, /*!*/ /*!*/); + --tw-backdrop-hue-rotate: var(--tw-empty, /*!*/ /*!*/); + --tw-backdrop-invert: var(--tw-empty, /*!*/ /*!*/); + --tw-backdrop-opacity: var(--tw-empty, /*!*/ /*!*/); + --tw-backdrop-saturate: var(--tw-empty, /*!*/ /*!*/); + --tw-backdrop-sepia: var(--tw-empty, /*!*/ /*!*/); + --tw-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) + var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) + var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) + var(--tw-backdrop-sepia); +} + +* > .enter-x:nth-child(1) { + transform: translateX(50px); +} + +* > .-enter-x:nth-child(1) { + transform: translateX(-50px); +} + +* > .enter-x:nth-child(1), +* > .-enter-x:nth-child(1) { + z-index: 9; + opacity: 0; + -webkit-animation: enter-x-animation 0.4s ease-in-out 0.3s; + animation: enter-x-animation 0.4s ease-in-out 0.3s; + -webkit-animation-fill-mode: forwards; + animation-fill-mode: forwards; + -webkit-animation-delay: 0.1s; + animation-delay: 0.1s; +} + +* > .enter-y:nth-child(1) { + transform: translateY(50px); +} + +* > .enter-y:nth-child(1), +* > .-enter-y:nth-child(1) { + z-index: 9; + opacity: 0; + -webkit-animation: enter-y-animation 0.4s ease-in-out 0.3s; + animation: enter-y-animation 0.4s ease-in-out 0.3s; + -webkit-animation-fill-mode: forwards; + animation-fill-mode: forwards; + -webkit-animation-delay: 0.1s; + animation-delay: 0.1s; +} + +* > .enter-x:nth-child(2) { + transform: translateX(50px); +} + +* > .-enter-x:nth-child(2) { + transform: translateX(-50px); +} + +* > .enter-x:nth-child(2), +* > .-enter-x:nth-child(2) { + z-index: 8; + opacity: 0; + -webkit-animation: enter-x-animation 0.4s ease-in-out 0.3s; + animation: enter-x-animation 0.4s ease-in-out 0.3s; + -webkit-animation-fill-mode: forwards; + animation-fill-mode: forwards; + -webkit-animation-delay: 0.2s; + animation-delay: 0.2s; +} + +* > .enter-y:nth-child(2) { + transform: translateY(50px); +} + +* > .enter-y:nth-child(2), +* > .-enter-y:nth-child(2) { + z-index: 8; + opacity: 0; + -webkit-animation: enter-y-animation 0.4s ease-in-out 0.3s; + animation: enter-y-animation 0.4s ease-in-out 0.3s; + -webkit-animation-fill-mode: forwards; + animation-fill-mode: forwards; + -webkit-animation-delay: 0.2s; + animation-delay: 0.2s; +} + +* > .enter-x:nth-child(3) { + transform: translateX(50px); +} + +* > .-enter-x:nth-child(3) { + transform: translateX(-50px); +} + +* > .enter-x:nth-child(3), +* > .-enter-x:nth-child(3) { + z-index: 7; + opacity: 0; + -webkit-animation: enter-x-animation 0.4s ease-in-out 0.3s; + animation: enter-x-animation 0.4s ease-in-out 0.3s; + -webkit-animation-fill-mode: forwards; + animation-fill-mode: forwards; + -webkit-animation-delay: 0.3s; + animation-delay: 0.3s; +} + +* > .enter-y:nth-child(3) { + transform: translateY(50px); +} + +* > .enter-y:nth-child(3), +* > .-enter-y:nth-child(3) { + z-index: 7; + opacity: 0; + -webkit-animation: enter-y-animation 0.4s ease-in-out 0.3s; + animation: enter-y-animation 0.4s ease-in-out 0.3s; + -webkit-animation-fill-mode: forwards; + animation-fill-mode: forwards; + -webkit-animation-delay: 0.3s; + animation-delay: 0.3s; +} + +* > .enter-x:nth-child(4) { + transform: translateX(50px); +} + +* > .-enter-x:nth-child(4) { + transform: translateX(-50px); +} + +* > .enter-x:nth-child(4), +* > .-enter-x:nth-child(4) { + z-index: 6; + opacity: 0; + -webkit-animation: enter-x-animation 0.4s ease-in-out 0.3s; + animation: enter-x-animation 0.4s ease-in-out 0.3s; + -webkit-animation-fill-mode: forwards; + animation-fill-mode: forwards; + -webkit-animation-delay: 0.4s; + animation-delay: 0.4s; +} + +* > .enter-y:nth-child(4) { + transform: translateY(50px); +} + +* > .enter-y:nth-child(4), +* > .-enter-y:nth-child(4) { + z-index: 6; + opacity: 0; + -webkit-animation: enter-y-animation 0.4s ease-in-out 0.3s; + animation: enter-y-animation 0.4s ease-in-out 0.3s; + -webkit-animation-fill-mode: forwards; + animation-fill-mode: forwards; + -webkit-animation-delay: 0.4s; + animation-delay: 0.4s; +} + +* > .enter-x:nth-child(5) { + transform: translateX(50px); +} + +* > .-enter-x:nth-child(5) { + transform: translateX(-50px); +} + +* > .enter-x:nth-child(5), +* > .-enter-x:nth-child(5) { + z-index: 5; + opacity: 0; + -webkit-animation: enter-x-animation 0.4s ease-in-out 0.3s; + animation: enter-x-animation 0.4s ease-in-out 0.3s; + -webkit-animation-fill-mode: forwards; + animation-fill-mode: forwards; + -webkit-animation-delay: 0.5s; + animation-delay: 0.5s; +} + +* > .enter-y:nth-child(5) { + transform: translateY(50px); +} + +* > .enter-y:nth-child(5), +* > .-enter-y:nth-child(5) { + z-index: 5; + opacity: 0; + -webkit-animation: enter-y-animation 0.4s ease-in-out 0.3s; + animation: enter-y-animation 0.4s ease-in-out 0.3s; + -webkit-animation-fill-mode: forwards; + animation-fill-mode: forwards; + -webkit-animation-delay: 0.5s; + animation-delay: 0.5s; +} + +@-webkit-keyframes enter-x-animation { + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes enter-x-animation { + to { + opacity: 1; + transform: translateX(0); + } +} + +@-webkit-keyframes enter-y-animation { + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes enter-y-animation { + to { + opacity: 1; + transform: translateY(0); + } +} + +.container { + width: 100%; +} + +@media (min-width: 576px) { + .container { + max-width: 576px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 768px; + } +} + +@media (min-width: 992px) { + .container { + max-width: 992px; + } +} + +@media (min-width: 1200px) { + .container { + max-width: 1200px; + } +} + +@media (min-width: 1600px) { + .container { + max-width: 1600px; + } +} + +.visible { + visibility: visible; +} + +.invisible { + visibility: hidden; +} + +.static { + position: static; +} + +.fixed { + position: fixed; +} + +.absolute { + position: absolute; +} + +.relative { + position: relative; +} + +.inset-0 { + top: 0px; + right: 0px; + bottom: 0px; + left: 0px; +} + +.top-0 { + top: 0px; +} + +.left-1\/2 { + left: 50%; +} + +.left-5 { + left: 1.25rem; +} + +.top-5 { + top: 1.25rem; +} + +.bottom-5 { + bottom: 1.25rem; +} + +.top-4 { + top: 1rem; +} + +.right-4 { + right: 1rem; +} + +.top-3 { + top: 0.75rem; +} + +.right-7 { + right: 1.75rem; +} + +.m-3 { + margin: 0.75rem; +} + +.m-10 { + margin: 2.5rem; +} + +.m-4 { + margin: 1rem; +} + +.m-5 { + margin: 1.25rem; +} + +.mx-auto { + margin-left: auto; + margin-right: auto; +} + +.\!my-4 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; +} + +.mx-4 { + margin-left: 1rem; + margin-right: 1rem; +} + +.my-4 { + margin-top: 1rem; + margin-bottom: 1rem; +} + +.my-auto { + margin-top: auto; + margin-bottom: auto; +} + +.\!my-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; +} + +.mx-1 { + margin-left: 0.25rem; + margin-right: 0.25rem; +} + +.my-3 { + margin-top: 0.75rem; + margin-bottom: 0.75rem; +} + +.\!mx-auto { + margin-left: auto !important; + margin-right: auto !important; +} + +.mx-12 { + margin-left: 3rem; + margin-right: 3rem; +} + +.my-2 { + margin-top: 0.5rem; + margin-bottom: 0.5rem; +} + +.my-5 { + margin-top: 1.25rem; + margin-bottom: 1.25rem; +} + +.mx-2 { + margin-left: 0.5rem; + margin-right: 0.5rem; +} + +.ml-1 { + margin-left: 0.25rem; +} + +.ml-2 { + margin-left: 0.5rem; +} + +.mr-2 { + margin-right: 0.5rem; +} + +.mr-1 { + margin-right: 0.25rem; +} + +.mt-1 { + margin-top: 0.25rem; +} + +.mt-2 { + margin-top: 0.5rem; +} + +.\!mt-4 { + margin-top: 1rem !important; +} + +.mb-1 { + margin-bottom: 0.25rem; +} + +.\!mr-4 { + margin-right: 1rem !important; +} + +.mt-4 { + margin-top: 1rem; +} + +.mb-4 { + margin-bottom: 1rem; +} + +.mt-5 { + margin-top: 1.25rem; +} + +.mt-10 { + margin-top: 2.5rem; +} + +.ml-4 { + margin-left: 1rem; +} + +.mr-5 { + margin-right: 1.25rem; +} + +.mr-4 { + margin-right: 1rem; +} + +.-mt-16 { + margin-top: -4rem; +} + +.mb-6 { + margin-bottom: 1.5rem; +} + +.mr-10 { + margin-right: 2.5rem; +} + +.mb-2 { + margin-bottom: 0.5rem; +} + +.mr-0 { + margin-right: 0px; +} + +.\!ml-4 { + margin-left: 1rem !important; +} + +.ml-5 { + margin-left: 1.25rem; +} + +.block { + display: block; +} + +.\!block { + display: block !important; +} + +.inline-block { + display: inline-block; +} + +.inline { + display: inline; +} + +.flex { + display: flex; +} + +.inline-flex { + display: inline-flex; +} + +.table { + display: table; +} + +.\!table { + display: table !important; +} + +.grid { + display: grid; +} + +.contents { + display: contents; +} + +.list-item { + display: list-item; +} + +.hidden { + display: none; +} + +.h-full { + height: 100%; +} + +.h-20 { + height: 5rem; +} + +.h-screen { + height: 100vh; +} + +.h-16 { + height: 4rem; +} + +.h-2\/5 { + height: 40%; +} + +.\!h-full { + height: 100% !important; +} + +.h-10 { + height: 2.5rem; +} + +.h-32 { + height: 8rem; +} + +.h-64 { + height: 16rem; +} + +.max-h-80 { + max-height: 20rem; +} + +.min-h-full { + min-height: 100%; +} + +.w-full { + width: 100%; +} + +.w-2\/3 { + width: 66.666667%; +} + +.w-1\/3 { + width: 33.333333%; +} + +.w-screen { + width: 100vw; +} + +.w-2\/5 { + width: 40%; +} + +.w-1\/2 { + width: 50%; +} + +.\!w-full { + width: 100% !important; +} + +.w-12 { + width: 3rem; +} + +.w-1\/4 { + width: 25%; +} + +.w-3\/4 { + width: 75%; +} + +.flex-1 { + flex: 1 1 0%; +} + +.flex-shrink { + flex-shrink: 1; +} + +.flex-grow-0 { + flex-grow: 0; +} + +.border-collapse { + border-collapse: collapse; +} + +.translate-x-1\/2 { + --tw-translate-x: 50%; + transform: var(--tw-transform); +} + +.cursor-pointer { + cursor: pointer; +} + +.cursor-not-allowed { + cursor: not-allowed; +} + +.resize { + resize: both; +} + +.flex-col { + flex-direction: column; +} + +.flex-wrap { + flex-wrap: wrap; +} + +.items-center { + align-items: center; +} + +.justify-end { + justify-content: flex-end; +} + +.justify-center { + justify-content: center; +} + +.justify-between { + justify-content: space-between; +} + +.justify-around { + justify-content: space-around; +} + +.justify-evenly { + justify-content: space-evenly; +} + +.overflow-auto { + overflow: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.rounded-md { + border-radius: 0.375rem; +} + +.border { + border-width: 1px; +} + +.\!border { + border-width: 1px !important; +} + +.border-t-0 { + border-top-width: 0px; +} + +.border-solid { + border-style: solid; +} + +.border-primary { + --tw-border-opacity: 1; + border-color: rgba(9, 96, 189, var(--tw-border-opacity)); +} + +.bg-black { + --tw-bg-opacity: 1; + background-color: rgba(0, 0, 0, var(--tw-bg-opacity)); +} + +.bg-gray-700 { + --tw-bg-opacity: 1; + background-color: rgba(63, 63, 70, var(--tw-bg-opacity)); +} + +.bg-white { + --tw-bg-opacity: 1; + background-color: rgba(255, 255, 255, var(--tw-bg-opacity)); +} + +.p-2 { + padding: 0.5rem; +} + +.p-5 { + padding: 1.25rem; +} + +.p-4 { + padding: 1rem; +} + +.p-1 { + padding: 0.25rem; +} + +.p-3 { + padding: 0.75rem; +} + +.p-10 { + padding: 2.5rem; +} + +.px-4 { + padding-left: 1rem; + padding-right: 1rem; +} + +.px-2 { + padding-left: 0.5rem; + padding-right: 0.5rem; +} + +.py-1 { + padding-top: 0.25rem; + padding-bottom: 0.25rem; +} + +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.py-1\.5 { + padding-top: 0.375rem; + padding-bottom: 0.375rem; +} + +.py-5 { + padding-top: 1.25rem; + padding-bottom: 1.25rem; +} + +.px-5 { + padding-left: 1.25rem; + padding-right: 1.25rem; +} + +.py-8 { + padding-top: 2rem; + padding-bottom: 2rem; +} + +.py-4 { + padding-top: 1rem; + padding-bottom: 1rem; +} + +.pl-2 { + padding-left: 0.5rem; +} + +.pt-5 { + padding-top: 1.25rem; +} + +.pl-4 { + padding-left: 1rem; +} + +.pt-4 { + padding-top: 1rem; +} + +.text-center { + text-align: center; +} + +.text-right { + text-align: right; +} + +.text-4xl { + font-size: 2.25rem; + line-height: 2.5rem; +} + +.text-5xl { + font-size: 3rem; + line-height: 1; +} + +.text-3xl { + font-size: 1.875rem; + line-height: 2.25rem; +} + +.text-2xl { + font-size: 1.5rem; + line-height: 2rem; +} + +.text-lg { + font-size: 1.125rem; + line-height: 1.75rem; +} + +.font-medium { + font-weight: 500; +} + +.font-normal { + font-weight: 400; +} + +.font-bold { + font-weight: 700; +} + +.uppercase { + text-transform: uppercase; +} + +.italic { + font-style: italic; +} + +.text-white { + --tw-text-opacity: 1; + color: rgba(255, 255, 255, var(--tw-text-opacity)); +} + +.text-gray-300 { + --tw-text-opacity: 1; + color: rgba(212, 212, 216, var(--tw-text-opacity)); +} + +.text-primary { + --tw-text-opacity: 1; + color: rgba(9, 96, 189, var(--tw-text-opacity)); +} + +.underline { + text-decoration: underline; +} + +.shadow { + --tw-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} + +.shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} + +.blur { + --tw-blur: blur(8px); + filter: var(--tw-filter); +} + +.transition { + transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow, + transform, filter, -webkit-backdrop-filter; + transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow, + transform, filter, backdrop-filter; + transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow, + transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.hover\:border-primary:hover { + --tw-border-opacity: 1; + border-color: rgba(9, 96, 189, var(--tw-border-opacity)); +} + +@media (min-width: 576px) { + .sm\:w-3\/4 { + width: 75%; + } + + .sm\:px-10 { + padding-left: 2.5rem; + padding-right: 2.5rem; + } + + .sm\:px-8 { + padding-left: 2rem; + padding-right: 2rem; + } +} + +@media (min-width: 768px) { + .md\:\!mx-4 { + margin-left: 1rem !important; + margin-right: 1rem !important; + } + + .md\:\!my-0 { + margin-top: 0px !important; + margin-bottom: 0px !important; + } + + .md\:mx-2 { + margin-left: 0.5rem; + margin-right: 0.5rem; + } + + .md\:mx-16 { + margin-left: 4rem; + margin-right: 4rem; + } + + .md\:mr-20 { + margin-right: 5rem; + } + + .md\:\!mt-0 { + margin-top: 0px !important; + } + + .md\:\!mr-4 { + margin-right: 1rem !important; + } + + .md\:ml-6 { + margin-left: 1.5rem; + } + + .md\:mt-0 { + margin-top: 0px; + } + + .md\:mr-10 { + margin-right: 2.5rem; + } + + .md\:block { + display: block; + } + + .md\:flex { + display: flex; + } + + .md\:h-4\/5 { + height: 80%; + } + + .md\:w-1\/3 { + width: 33.333333%; + } + + .md\:w-1\/4 { + width: 25%; + } + + .md\:\!w-1\/3 { + width: 33.333333% !important; + } + + .md\:text-lg { + font-size: 1.125rem; + line-height: 1.75rem; + } + + .md\:opacity-100 { + opacity: 1; + } +} + +@media (min-width: 992px) { + .lg\:flex { + display: flex; + } + + .lg\:w-2\/4 { + width: 50%; + } +} + +@media (min-width: 1200px) { + .xl\:my-0 { + margin-top: 0px; + margin-bottom: 0px; + } + + .xl\:ml-20 { + margin-left: 5rem; + } + + .xl\:flex { + display: flex; + } + + .xl\:hidden { + display: none; + } + + .xl\:h-auto { + height: auto; + } + + .xl\:w-6\/12 { + width: 50%; + } + + .xl\:w-auto { + width: auto; + } + + .xl\:w-1\/5 { + width: 20%; + } + + .xl\:w-4\/5 { + width: 80%; + } + + .xl\:flex-col { + flex-direction: column; + } + + .xl\:justify-start { + justify-content: flex-start; + } + + .xl\:p-4 { + padding: 1rem; + } + + .xl\:py-0 { + padding-top: 0px; + padding-bottom: 0px; + } + + .xl\:text-left { + text-align: left; + } + + .xl\:text-xl { + font-size: 1.25rem; + line-height: 1.75rem; + } + + .xl\:text-3xl { + font-size: 1.875rem; + line-height: 2.25rem; + } + + .xl\:text-gray-600 { + --tw-text-opacity: 1; + color: rgba(82, 82, 91, var(--tw-text-opacity)); + } + + .xl\:shadow-none { + --tw-shadow: 0 0 #0000; + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); + } +} + +@media (min-width: 1600px) { + .\32xl\:text-3xl { + font-size: 1.875rem; + line-height: 2.25rem; + } +} diff --git a/src/directives/clickOutside.ts b/src/directives/clickOutside.ts index 8c1b2dc4..f6f3051a 100644 --- a/src/directives/clickOutside.ts +++ b/src/directives/clickOutside.ts @@ -31,12 +31,14 @@ function createDocumentHandler(el: HTMLElement, binding: DirectiveBinding): Docu excludes = binding.arg; } else { // due to current implementation on binding type is wrong the type casting is necessary here - excludes.push((binding.arg as unknown) as HTMLElement); + excludes.push(binding.arg as unknown as HTMLElement); } return function (mouseup, mousedown) { - const popperRef = (binding.instance as ComponentPublicInstance<{ - popperRef: Nullable; - }>).popperRef; + const popperRef = ( + binding.instance as ComponentPublicInstance<{ + popperRef: Nullable; + }> + ).popperRef; const mouseUpTarget = mouseup.target as Node; const mouseDownTarget = mousedown.target as Node; const isBound = !binding || !binding.instance; diff --git a/src/enums/appEnum.ts b/src/enums/appEnum.ts index 025fa939..b2c9826e 100644 --- a/src/enums/appEnum.ts +++ b/src/enums/appEnum.ts @@ -20,6 +20,11 @@ export enum SettingButtonPositionEnum { FIXED = 'fixed', } +export enum SessionTimeoutProcessingEnum { + ROUTE_JUMP, + PAGE_COVERAGE, +} + /** * 权限模式 */ diff --git a/src/hooks/component/useFormItem.ts b/src/hooks/component/useFormItem.ts index 2f5a2a4c..140e3d0b 100644 --- a/src/hooks/component/useFormItem.ts +++ b/src/hooks/component/useFormItem.ts @@ -25,7 +25,7 @@ export function useRuleFormItem( innerState.value = props[key]; }); - const state = computed({ + const state: any = computed({ get() { return innerState.value; }, diff --git a/src/hooks/core/useExpose.ts b/src/hooks/core/useExpose.ts deleted file mode 100644 index 224b5aae..00000000 --- a/src/hooks/core/useExpose.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { getCurrentInstance } from 'vue'; - -// expose public api -export function useExpose(apis: T) { - const instance = getCurrentInstance(); - if (instance) { - Object.assign(instance.proxy, apis); - } -} diff --git a/src/hooks/web/useI18n.ts b/src/hooks/web/useI18n.ts index 40e11920..2a777b78 100644 --- a/src/hooks/web/useI18n.ts +++ b/src/hooks/web/useI18n.ts @@ -21,9 +21,7 @@ function getKey(namespace: string | undefined, key: string) { return `${namespace}.${key}`; } -export function useI18n( - namespace?: string -): { +export function useI18n(namespace?: string): { t: I18nGlobalTranslation; } { const normalFn = { diff --git a/src/hooks/web/useMessage.tsx b/src/hooks/web/useMessage.tsx index 56074e0e..97f5b2d0 100644 --- a/src/hooks/web/useMessage.tsx +++ b/src/hooks/web/useMessage.tsx @@ -5,6 +5,7 @@ import { InfoCircleFilled, CheckCircleFilled, CloseCircleFilled } from '@ant-des import { ArgsProps, ConfigProps } from 'ant-design-vue/lib/notification'; import { useI18n } from './useI18n'; +import { isString } from '/@/utils/is'; export interface NotifyApi { info(config: ArgsProps): void; @@ -46,7 +47,11 @@ function getIcon(iconType: string) { } function renderContent({ content }: Pick) { - return
${content as string}
`}>; + if (isString(content)) { + return
${content as string}
`}>; + } else { + return content; + } } /** @@ -59,8 +64,9 @@ function createConfirm(options: ModalOptionsEx): ConfirmOptions { centered: true, icon: getIcon(iconType), ...options, + content: renderContent(options), }; - return (Modal.confirm(opt) as unknown) as ConfirmOptions; + return Modal.confirm(opt) as unknown as ConfirmOptions; } const getBaseOptions = () => { diff --git a/src/layouts/default/content/index.vue b/src/layouts/default/content/index.vue index a94b0ee5..3f6d193b 100644 --- a/src/layouts/default/content/index.vue +++ b/src/layouts/default/content/index.vue @@ -5,9 +5,7 @@ diff --git a/src/layouts/default/header/MultipleHeader.vue b/src/layouts/default/header/MultipleHeader.vue index a71c442d..c852b7ee 100644 --- a/src/layouts/default/header/MultipleHeader.vue +++ b/src/layouts/default/header/MultipleHeader.vue @@ -17,7 +17,7 @@ import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; import { useAppInject } from '/@/hooks/web/useAppInject'; import { useDesign } from '/@/hooks/web/useDesign'; - import { headerHeightRef } from '../content/useContentViewHeight'; + import { useLayoutHeight } from '../content/useContentViewHeight'; const HEADER_HEIGHT = 48; @@ -26,6 +26,7 @@ name: 'LayoutMultipleHeader', components: { LayoutHeader, MultipleTabs }, setup() { + const { setHeaderHeight } = useLayoutHeight(); const { prefixCls } = useDesign('layout-multiple-header'); const { getCalcContentWidth, getSplit } = useMenuSetting(); @@ -77,7 +78,7 @@ if (unref(getShowMultipleTab) && !unref(getFullContent)) { height += TABS_HEIGHT; } - headerHeightRef.value = height; + setHeaderHeight(height); return { height: `${height}px`, }; diff --git a/src/layouts/default/header/components/Breadcrumb.vue b/src/layouts/default/header/components/Breadcrumb.vue index c135340a..6d5d2255 100644 --- a/src/layouts/default/header/components/Breadcrumb.vue +++ b/src/layouts/default/header/components/Breadcrumb.vue @@ -71,10 +71,10 @@ const breadcrumbList = filterItem(matched); if (currentRoute.value.meta?.currentActiveMenu) { - breadcrumbList.push(({ + breadcrumbList.push({ ...currentRoute.value, name: currentRoute.value.meta?.title || currentRoute.value.name, - } as unknown) as RouteLocationMatched); + } as unknown as RouteLocationMatched); } routes.value = breadcrumbList; }); diff --git a/src/layouts/default/header/components/lock/LockModal.vue b/src/layouts/default/header/components/lock/LockModal.vue index 2c1bf3b8..0a7ba613 100644 --- a/src/layouts/default/header/components/lock/LockModal.vue +++ b/src/layouts/default/header/components/lock/LockModal.vue @@ -95,7 +95,7 @@ &__entry { position: relative; //height: 240px; - padding: 130px 30px 60px 30px; + padding: 130px 30px 30px 30px; border-radius: 10px; } diff --git a/src/layouts/default/menu/index.vue b/src/layouts/default/menu/index.vue index 9e340906..9dcb2d51 100644 --- a/src/layouts/default/menu/index.vue +++ b/src/layouts/default/menu/index.vue @@ -76,13 +76,11 @@ ); }); - const getWrapperStyle = computed( - (): CSSProperties => { - return { - height: `calc(100% - ${unref(getIsShowLogo) ? '48px' : '0px'})`, - }; - } - ); + const getWrapperStyle = computed((): CSSProperties => { + return { + height: `calc(100% - ${unref(getIsShowLogo) ? '48px' : '0px'})`, + }; + }); const getLogoClass = computed(() => { return [ diff --git a/src/layouts/default/setting/SettingDrawer.tsx b/src/layouts/default/setting/SettingDrawer.tsx index beba91c9..c9828868 100644 --- a/src/layouts/default/setting/SettingDrawer.tsx +++ b/src/layouts/default/setting/SettingDrawer.tsx @@ -58,12 +58,8 @@ export default defineComponent({ getThemeColor, } = useRootSetting(); - const { - getOpenPageLoading, - getBasicTransition, - getEnableTransition, - getOpenNProgress, - } = useTransitionSetting(); + const { getOpenPageLoading, getBasicTransition, getEnableTransition, getOpenNProgress } = + useTransitionSetting(); const { getIsHorizontal, diff --git a/src/layouts/default/setting/index.vue b/src/layouts/default/setting/index.vue index fe0402d2..9c5bb87f 100644 --- a/src/layouts/default/setting/index.vue +++ b/src/layouts/default/setting/index.vue @@ -1,5 +1,5 @@