From 5db3ce773793d06fa17336aca42470d2aae93fb8 Mon Sep 17 00:00:00 2001 From: vben <anncwb@126.com> Date: Tue, 1 Dec 2020 20:59:17 +0800 Subject: [PATCH] refactor: add loading component and demo --- CHANGELOG.en_US.md | 2 +- CHANGELOG.zh_CN.md | 12 +++++++++++- build/config/lessModifyVars.ts | 1 + index.html | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------- package.json | 2 +- public/resource/img/loading.svg | 49 ------------------------------------------------- src/assets/images/loading.svg | 67 ------------------------------------------------------------------- src/components/Application/src/AppLocalePicker.vue | 4 ++++ src/components/Application/src/AppLogo.vue | 4 ++++ src/components/Drawer/src/BasicDrawer.tsx | 8 +++----- src/components/Loading/BasicLoading.vue | 55 ------------------------------------------------------- src/components/Loading/FullLoading.vue | 50 -------------------------------------------------- src/components/Loading/index.ts | 10 ++++++++-- src/components/Loading/src/createLoading.ts | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/components/Loading/src/index.vue | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/components/Loading/src/indicator.tsx | 9 +++++++++ src/components/Loading/src/types.ts | 10 ++++++++++ src/components/Loading/src/useLoading.ts | 39 +++++++++++++++++++++++++++++++++++++++ src/components/Loading/type.ts | 8 -------- src/components/Preview/src/index.tsx | 17 ++++++++++------- src/design/public.less | 5 ----- src/hooks/web/useI18n.ts | 1 + src/layouts/default/content/index.less | 4 ---- src/layouts/default/content/index.tsx | 16 +++++----------- src/layouts/page/index.tsx | 1 + src/locales/lang/en/routes/demo/comp.ts | 2 ++ src/locales/lang/zh_CN/routes/demo/comp.ts | 2 ++ src/router/menus/modules/demo/comp.ts | 4 ++++ src/router/routes/modules/demo/comp.ts | 8 ++++++++ src/setup/ant-design-vue/index.ts | 2 -- src/setup/ant-design-vue/spin.tsx | 12 ------------ src/setup/directives/index.ts | 2 ++ src/setup/directives/loading.ts | 43 +++++++++++++++++++++++++++++++++++++++++++ src/setup/i18n/index.ts | 3 ++- src/views/demo/comp/loading/index.vue | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tsconfig.json | 2 +- vite.config.ts | 4 ++-- yarn.lock | 11 ++++++----- 38 files changed, 539 insertions(+), 342 deletions(-) delete mode 100644 public/resource/img/loading.svg delete mode 100644 src/assets/images/loading.svg delete mode 100644 src/components/Loading/BasicLoading.vue delete mode 100644 src/components/Loading/FullLoading.vue create mode 100644 src/components/Loading/src/createLoading.ts create mode 100644 src/components/Loading/src/index.vue create mode 100644 src/components/Loading/src/indicator.tsx create mode 100644 src/components/Loading/src/types.ts create mode 100644 src/components/Loading/src/useLoading.ts delete mode 100644 src/components/Loading/type.ts delete mode 100644 src/setup/ant-design-vue/spin.tsx create mode 100644 src/setup/directives/loading.ts create mode 100644 src/views/demo/comp/loading/index.vue diff --git a/CHANGELOG.en_US.md b/CHANGELOG.en_US.md index 3df3104..c85cc83 100644 --- a/CHANGELOG.en_US.md +++ b/CHANGELOG.en_US.md @@ -3,7 +3,7 @@ ## (破坏性更新) Breaking changes - The ClickOutSide component import method is changed from `import ClickOutSide from'/@/components/ClickOutSide/index.vue'` to `import {ClickOutSide} from'/@/components/ClickOutSide'` -- Button component import method changed from `import ClickOutSide from'/@/components/Button/index.vue'` to `import {Button} from'/@/components/Button'` +- Button component import method changed from `import Button from'/@/components/Button/index.vue'` to `import {Button} from'/@/components/Button'` - StrengthMeter component import method is changed from `import StrengthMeter from'/@/components/StrengthMeter'` to `import {StrengthMeter} from'/@/components/StrengthMeter'` - In addition to the examples, the global internationalization function is added, supporting Chinese and English diff --git a/CHANGELOG.zh_CN.md b/CHANGELOG.zh_CN.md index 622c3ca..ee693a9 100644 --- a/CHANGELOG.zh_CN.md +++ b/CHANGELOG.zh_CN.md @@ -1,9 +1,19 @@ +## Wip + +### ✨ Features + +- 还原 antdv 默认 loading,重构 `Loading` 组件,增加`useLoading`和`v-loading`指令。并增加示例 + +### 🎫 Chores + +- 首屏 loading 修改 + ## 2.0.0-rc.12 (2020-11-30) ## (破坏性更新) Breaking changes - ClickOutSide 组件引入方式由 `import ClickOutSide from '/@/components/ClickOutSide/index.vue'`变更为`import { ClickOutSide } from '/@/components/ClickOutSide'` -- Button 组件引入方式由 `import ClickOutSide from '/@/components/Button/index.vue'`变更为`import { Button } from '/@/components/Button'` +- Button 组件引入方式由 `import Button from '/@/components/Button/index.vue'`变更为`import { Button } from '/@/components/Button'` - StrengthMeter 组件引入方式由 `import StrengthMeter from '/@/components/StrengthMeter'`变更为`import { StrengthMeter } from '/@/components/StrengthMeter'` - 除示例外加入全局国际化功能,支持中文与英文 diff --git a/build/config/lessModifyVars.ts b/build/config/lessModifyVars.ts index 73cbc18..b51223b 100644 --- a/build/config/lessModifyVars.ts +++ b/build/config/lessModifyVars.ts @@ -2,6 +2,7 @@ * less global variable */ const primaryColor = '#018ffb'; +// const primaryColor = '#0065cc'; //{ const modifyVars = { 'primary-color': primaryColor, // Global dominant color diff --git a/index.html b/index.html index 9c9dbbd..10e33a1 100644 --- a/index.html +++ b/index.html @@ -13,68 +13,136 @@ <title></title> <link rel="icon" href="/favicon.ico" /> <%= viteHtmlPluginOptions.injectConfig %> + </head> + <body> + <div id="app"> + <style> + .app-loading { + display: flex; + width: 100%; + height: 100%; + justify-content: center; + align-items: center; + flex-direction: column; + } - <style> - @keyframes load { - 0% { - -webkit-transform: rotate(-360deg); - transform: rotate(-360deg); + .app-loading .app-loading-wrap { + position: absolute; + top: 50%; + left: 50%; + display: flex; + -webkit-transform: translate3d(-50%, -50%, 0); + transform: translate3d(-50%, -50%, 0); + justify-content: center; + align-items: center; + flex-direction: column; } - 100% { - -webkit-transform: rotate(0); - transform: rotate(0); + .app-loading .dots { + display: flex; + padding: 98px; + justify-content: center; + align-items: center; } - } - .app-loading { - width: 100%; - height: 100%; - background: #f0f2f5; - } + .app-loading .app-loading-title { + display: flex; + margin-top: 30px; + font-size: 30px; + color: rgba(0, 0, 0, 0.85); + justify-content: center; + align-items: center; + } - .app-loading .app-loading-wrap { - position: absolute; - top: 50%; - left: 50%; - -webkit-transform: translate3d(-50%, -50%, 0); - transform: translate3d(-50%, -50%, 0); - } + .app-loading .app-loading-logo { + display: block; + width: 90px; + margin: 0 auto; + margin-bottom: 20px; + } - .app-loading .g-loading { - display: block; - width: 48px; - margin: 30px auto; - -webkit-animation: load 1.2s linear infinite; - animation: load 1.2s linear infinite; - -webkit-transform-origin: center center; - transform-origin: center center; - } + .dot { + position: relative; + display: inline-block; + width: 48px; + height: 48px; + margin-top: 30px; + font-size: 32px; + transform: rotate(45deg); + box-sizing: border-box; + animation: antRotate 1.2s infinite linear; + } - .app-loading .app-loading-wrap img.logo { - display: block; - width: 90px; - margin: 0 auto; - margin-bottom: 20px; - } + .dot i { + position: absolute; + display: block; + width: 20px; + height: 20px; + background-color: #0065cc; + border-radius: 100%; + opacity: 0.3; + transform: scale(0.75); + animation: antSpinMove 1s infinite linear alternate; + transform-origin: 50% 50%; + } - .app-loading .app-loading-wrap .app-loading__tip { - display: block; - margin: 20px auto 0 0; - font-size: 30px; - color: rgba(0, 0, 0, 0.85); - } - </style> - </head> - <body> - <div id="app"> - <section class="app-loading"> - <section class="app-loading-wrap"> - <img src="./resource/img/logo.png" class="logo" alt="Logo" /> - <img src="./resource/img/loading.svg" alt="" class="g-loading" /> - <h1 class="app-loading__tip"><%= viteHtmlPluginOptions.title %></h1> - </section> - </section> + .dot i:nth-child(1) { + top: 0; + left: 0; + } + + .dot i:nth-child(2) { + top: 0; + right: 0; + -webkit-animation-delay: 0.4s; + animation-delay: 0.4s; + } + + .dot i:nth-child(3) { + right: 0; + bottom: 0; + -webkit-animation-delay: 0.8s; + animation-delay: 0.8s; + } + + .dot i:nth-child(4) { + bottom: 0; + left: 0; + -webkit-animation-delay: 1.2s; + animation-delay: 1.2s; + } + @keyframes antRotate { + to { + -webkit-transform: rotate(405deg); + transform: rotate(405deg); + } + } + @-webkit-keyframes antRotate { + to { + -webkit-transform: rotate(405deg); + transform: rotate(405deg); + } + } + @keyframes antSpinMove { + to { + opacity: 1; + } + } + @-webkit-keyframes antSpinMove { + to { + opacity: 1; + } + } + </style> + <div class="app-loading"> + <div class="app-loading-wrap"> + <img src="./resource/img/logo.png" class="app-loading-logo" alt="Logo" /> + <div class="app-loading-dots"> + <span class="dot dot-spin"><i></i><i></i><i></i><i></i></span> + </div> + <div class="app-loading-title"><%= viteHtmlPluginOptions.title %></div> + </div> + </div> </div> <script type="module" src="/src/main.ts"></script> </body> diff --git a/package.json b/package.json index e749fa1..4fa309b 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ }, "dependencies": { "@iconify/iconify": "^2.0.0-rc.2", - "ant-design-vue": "2.0.0-rc.2", + "ant-design-vue": "^2.0.0-rc.2", "apexcharts": "3.22.0", "axios": "^0.21.0", "crypto-es": "^1.2.6", diff --git a/public/resource/img/loading.svg b/public/resource/img/loading.svg deleted file mode 100644 index 15395c6..0000000 --- a/public/resource/img/loading.svg +++ /dev/null @@ -1,49 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg viewBox="0 0 200 200" version="1.1" - xmlns="http://www.w3.org/2000/svg" - xmlns:xlink="http://www.w3.org/1999/xlink"> - <style type="text/css"> - .left-linear { - fill: url(#left-linear); - } - - .right-linear { - fill: url(#right-linear); - } - - .top { - fill: #64acff; - } - - .bottom { - fill: #9dbfe4; - } - svg { - display: block; - } - - .tip { - display: block; - min-width: 100px; - margin-top: 4px; - font-size: 13px; - color: rgba(0, 0, 0, 0.85);; - text-align: left; - } - </style> - <circle cx="97" cy="97" r="81" stroke-width="16" stroke="#327fd8" fill="none"></circle> - <g class="load"> - <linearGradient id="left-linear" gradientUnits="userSpaceOnUse" x1="50" y1="0" x2="100" y2="180"> - <stop offset="0" style="stop-color: #64acff;" /> - <stop offset="1" style="stop-color: #9DBFE4;" /> - </linearGradient> - <path class="left-linear" d="M20,100c0-44.1,35.9-80,80-80V0C44.8,0,0,44.8,0,100s44.8,100,100,100v-20C55.9,180,20,144.1,20,100z" /> - <circle class="bottom" cx="100" cy="190" r="10" /> - <linearGradient id="right-linear" gradientUnits="userSpaceOnUse" x1="100" y1="120" x2="100" y2="180"> - <stop offset="0" style="stop-color: transparent;" /> - <stop offset="1" style="stop-color: transparent;" /> - </linearGradient> - <path class="right-linear" d="M100,0v20c44.1,0,80,35.9,80,80c0,44.1-35.9,80-80,80v20c55.2,0,100-44.8,100-100S155.2,0,100,0z" /> - <circle class="top" cx="100" cy="10" r="10" /> - </g> -</svg> diff --git a/src/assets/images/loading.svg b/src/assets/images/loading.svg deleted file mode 100644 index b85b892..0000000 --- a/src/assets/images/loading.svg +++ /dev/null @@ -1,67 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg viewBox="0 0 200 200" version="1.1" - xmlns="http://www.w3.org/2000/svg" - xmlns:xlink="http://www.w3.org/1999/xlink"> - <style type="text/css"> - .left-linear { - fill: url(#left-linear); - } - - .right-linear { - fill: url(#right-linear); - } - - .top { - fill: #64acff; - } - - .bottom { - fill: #9dbfe4; - } - @keyframes load { - 0% { - transform: rotate(-360deg); - } - - 100% { - transform: rotate(0); - } - } - - .load { - animation: load 1.4s linear infinite; - transform-origin: center center; - } - - svg { - display: block; - } - - .tip { - display: block; - min-width: 100px; - margin-top: 4px; - font-size: 13px; - color: #303133; - text-align: left; - } - </style> - <circle cx="97" cy="97" r="81" stroke-width="16" stroke="#327fd8" fill="none"></circle> - <g class="load"> - <!--右半圆环--> - <linearGradient id="left-linear" gradientUnits="userSpaceOnUse" x1="50" y1="0" x2="100" y2="180"> - <stop offset="0" style="stop-color: #64acff;" /> - <stop offset="1" style="stop-color: #9DBFE4;" /> - </linearGradient> - <path class="left-linear" d="M20,100c0-44.1,35.9-80,80-80V0C44.8,0,0,44.8,0,100s44.8,100,100,100v-20C55.9,180,20,144.1,20,100z" /> - <!--左半圆环--> - <circle class="bottom" cx="100" cy="190" r="10" /> - <linearGradient id="right-linear" gradientUnits="userSpaceOnUse" x1="100" y1="120" x2="100" y2="180"> - <stop offset="0" style="stop-color: transparent;" /> - <stop offset="1" style="stop-color: transparent;" /> - </linearGradient> - <path class="right-linear" d="M100,0v20c44.1,0,80,35.9,80,80c0,44.1-35.9,80-80,80v20c55.2,0,100-44.8,100-100S155.2,0,100,0z" /> - <!--左半圆环--> - <circle class="top" cx="100" cy="10" r="10" /> - </g> -</svg> diff --git a/src/components/Application/src/AppLocalePicker.vue b/src/components/Application/src/AppLocalePicker.vue index 48ab5bd..5ef9e78 100644 --- a/src/components/Application/src/AppLocalePicker.vue +++ b/src/components/Application/src/AppLocalePicker.vue @@ -1,3 +1,7 @@ +<!-- + * @Author: Vben + * @Description: Multi-language switching component +--> <template> <Dropdown :trigger="['click']" diff --git a/src/components/Application/src/AppLogo.vue b/src/components/Application/src/AppLogo.vue index 6ce85ef..5763fe5 100644 --- a/src/components/Application/src/AppLogo.vue +++ b/src/components/Application/src/AppLogo.vue @@ -1,3 +1,7 @@ +<!-- + * @Author: Vben + * @Description: logo component +--> <template> <div class="app-logo anticon" diff --git a/src/components/Drawer/src/BasicDrawer.tsx b/src/components/Drawer/src/BasicDrawer.tsx index 3736bb7..84d0cff 100644 --- a/src/components/Drawer/src/BasicDrawer.tsx +++ b/src/components/Drawer/src/BasicDrawer.tsx @@ -7,7 +7,7 @@ import { defineComponent, ref, computed, watchEffect, watch, unref, nextTick, to import { Drawer, Row, Col, Button } from 'ant-design-vue'; import { BasicTitle } from '/@/components/Basic'; -import { FullLoading } from '/@/components/Loading/index'; +import { Loading } from '/@/components/Loading'; import { LeftOutlined } from '@ant-design/icons-vue'; import { useI18n } from '/@/hooks/web/useI18n'; @@ -97,9 +97,7 @@ export default defineComponent({ ); const getLoading = computed(() => { - return { - hidden: !unref(getProps).loading, - }; + return !!unref(getProps)?.loading; }); watchEffect(() => { @@ -230,7 +228,7 @@ export default defineComponent({ default: () => ( <> <div ref={scrollRef} style={unref(getScrollContentStyle)}> - <FullLoading absolute tip={t('loadingText')} class={unref(getLoading)} /> + <Loading absolute tip={t('loadingText')} loading={unref(getLoading)} /> {getSlot(slots)} </div> {renderFooter()} diff --git a/src/components/Loading/BasicLoading.vue b/src/components/Loading/BasicLoading.vue deleted file mode 100644 index f0afa90..0000000 --- a/src/components/Loading/BasicLoading.vue +++ /dev/null @@ -1,55 +0,0 @@ -<template> - <section class="basic-loading"> - <img - src="/@/assets/images/loading.svg" - alt="" - :height="getLoadingIconSize" - :width="getLoadingIconSize" - /> - <span class="mt-4" v-if="tip"> {{ tip }}</span> - </section> -</template> - -<script lang="ts"> - import type { PropType } from 'vue'; - // components - import { defineComponent, computed } from 'vue'; - - import { SizeEnum, sizeMap } from '/@/enums/sizeEnum'; - - import { BasicLoadingProps } from './type'; - - export default defineComponent({ - inheritAttrs: false, - name: 'BasicLoading', - props: { - tip: { - type: String as PropType<string>, - default: '', - }, - size: { - type: String as PropType<SizeEnum>, - default: SizeEnum.DEFAULT, - validator: (v: SizeEnum): boolean => { - return [SizeEnum.DEFAULT, SizeEnum.SMALL, SizeEnum.LARGE].includes(v); - }, - }, - }, - setup(props: BasicLoadingProps) { - const getLoadingIconSize = computed(() => { - const { size } = props; - return sizeMap.get(size); - }); - - return { getLoadingIconSize }; - }, - }); -</script> -<style lang="less" scoped> - .basic-loading { - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - } -</style> diff --git a/src/components/Loading/FullLoading.vue b/src/components/Loading/FullLoading.vue deleted file mode 100644 index ec738bd..0000000 --- a/src/components/Loading/FullLoading.vue +++ /dev/null @@ -1,50 +0,0 @@ -<template> - <section class="full-loading" :style="getStyle"> - <BasicLoading :tip="tip" :size="SizeEnum.DEFAULT" /> - </section> -</template> -<script lang="ts"> - import type { PropType } from 'vue'; - import { defineComponent, computed } from 'vue'; - import BasicLoading from './BasicLoading.vue'; - - import { SizeEnum } from '/@/enums/sizeEnum'; - - export default defineComponent({ - name: 'FullLoading', - components: { BasicLoading }, - props: { - tip: { - type: String as PropType<string>, - default: '', - }, - absolute: Boolean as PropType<boolean>, - }, - setup(props) { - const getStyle = computed((): any => { - return props.absolute - ? { - position: 'absolute', - left: 0, - top: 0, - 'z-index': 1, - } - : {}; - }); - - return { getStyle, SizeEnum }; - }, - }); -</script> -<style lang="less" scoped> - .full-loading { - display: flex; - width: 100%; - height: 100%; - // background: rgba(255, 255, 255, 0.3); - // background: #f0f2f5; - background: rgba(240, 242, 245, 0.5); - justify-content: center; - align-items: center; - } -</style> diff --git a/src/components/Loading/index.ts b/src/components/Loading/index.ts index 39bdd88..f8e5845 100644 --- a/src/components/Loading/index.ts +++ b/src/components/Loading/index.ts @@ -1,2 +1,8 @@ -export { default as BasicLoading } from './BasicLoading.vue'; -export { default as FullLoading } from './FullLoading.vue'; +import './src/indicator'; +import LoadingLib from './src/index.vue'; +import { withInstall } from '../util'; + +export { useLoading } from './src/useLoading'; +export { createLoading } from './src/createLoading'; + +export const Loading = withInstall(LoadingLib); diff --git a/src/components/Loading/src/createLoading.ts b/src/components/Loading/src/createLoading.ts new file mode 100644 index 0000000..bb7fd08 --- /dev/null +++ b/src/components/Loading/src/createLoading.ts @@ -0,0 +1,60 @@ +import { VNode, defineComponent } from 'vue'; +import type { LoadingProps } from './types'; + +import { createVNode, render, reactive, h } from 'vue'; +import Loading from './index.vue'; + +export function createLoading(props?: Partial<LoadingProps>, target?: HTMLElement) { + let vm: Nullable<VNode> = null; + const data = reactive({ + tip: '', + loading: true, + ...props, + }); + + const LoadingWrap = defineComponent({ + setup() { + return () => { + return h(Loading, { ...data }); + }; + }, + }); + + vm = createVNode(LoadingWrap); + + render(vm, document.createElement('div')); + + function close() { + if (vm?.el && vm.el.parentNode) { + vm.el.parentNode.removeChild(vm.el); + } + } + + function open(target: HTMLElement = document.body) { + if (!vm || !vm.el) { + return; + } + target.appendChild(vm.el as HTMLElement); + } + + if (target) { + open(target); + } + return { + vm, + close, + open, + setTip: (tip: string) => { + data.tip = tip; + }, + setLoading: (loading: boolean) => { + data.loading = loading; + }, + get loading() { + return data.loading; + }, + get $el() { + return vm?.el as HTMLElement; + }, + }; +} diff --git a/src/components/Loading/src/index.vue b/src/components/Loading/src/index.vue new file mode 100644 index 0000000..4d24a73 --- /dev/null +++ b/src/components/Loading/src/index.vue @@ -0,0 +1,82 @@ +<template> + <section class="full-loading" :class="{ absolute }" v-show="loading" :style="getStyle"> + <Spin v-bind="$attrs" :tip="tip" :size="size" :spinning="loading" /> + </section> +</template> +<script lang="ts"> + import { computed, CSSProperties, PropType } from 'vue'; + + import { defineComponent } from 'vue'; + import { Spin } from 'ant-design-vue'; + + import { SizeEnum } from '/@/enums/sizeEnum'; + import { ThemeEnum } from '/@/enums/appEnum'; + + export default defineComponent({ + name: 'Loading', + components: { Spin }, + props: { + tip: { + type: String as PropType<string>, + default: '', + }, + size: { + type: String as PropType<SizeEnum>, + default: SizeEnum.LARGE, + validator: (v: SizeEnum): boolean => { + return [SizeEnum.DEFAULT, SizeEnum.SMALL, SizeEnum.LARGE].includes(v); + }, + }, + absolute: { + type: Boolean as PropType<boolean>, + default: false, + }, + loading: { + type: Boolean as PropType<boolean>, + default: false, + }, + background: { + type: String as PropType<string>, + }, + theme: { + type: String as PropType<'dark' | 'light'>, + default: 'light', + }, + }, + setup(props) { + const getStyle = computed( + (): CSSProperties => { + const { background, theme } = props; + const bgColor = background + ? background + : theme === ThemeEnum.DARK + ? 'rgba(0, 0, 0, 0.2)' + : 'rgba(240, 242, 245, 0.4)'; + return { background: bgColor }; + } + ); + + return { getStyle }; + }, + }); +</script> +<style lang="less" scoped> + .full-loading { + position: fixed; + top: 0; + left: 0; + z-index: 200; + display: flex; + width: 100%; + height: 100%; + justify-content: center; + align-items: center; + + &.absolute { + position: absolute; + top: 0; + left: 0; + z-index: 1; + } + } +</style> diff --git a/src/components/Loading/src/indicator.tsx b/src/components/Loading/src/indicator.tsx new file mode 100644 index 0000000..f74bc0e --- /dev/null +++ b/src/components/Loading/src/indicator.tsx @@ -0,0 +1,9 @@ +// If you need to modify the default icon, you can open the comment and modify it here + +// import { Spin } from 'ant-design-vue'; +// import { LoadingOutlined } from '@ant-design/icons-vue'; +// Spin.setDefaultIndicator({ +// indicator: () => { +// return <LoadingOutlined spin />; +// }, +// }); diff --git a/src/components/Loading/src/types.ts b/src/components/Loading/src/types.ts new file mode 100644 index 0000000..9af60e6 --- /dev/null +++ b/src/components/Loading/src/types.ts @@ -0,0 +1,10 @@ +import { SizeEnum } from '/@/enums/sizeEnum'; + +export interface LoadingProps { + tip: string; + size: SizeEnum; + absolute: boolean; + loading: boolean; + background: string; + theme: 'dark' | 'light'; +} diff --git a/src/components/Loading/src/useLoading.ts b/src/components/Loading/src/useLoading.ts new file mode 100644 index 0000000..10f8e31 --- /dev/null +++ b/src/components/Loading/src/useLoading.ts @@ -0,0 +1,39 @@ +import { unref } from 'vue'; +import { createLoading } from './createLoading'; +import type { LoadingProps } from './types'; +import type { Ref } from 'vue'; + +export interface UseLoadingOptions { + target?: HTMLElement | Ref<ElRef>; + props?: Partial<LoadingProps>; +} + +export function useLoading(props: Partial<LoadingProps>): [Fn, Fn]; +export function useLoading(opt: Partial<UseLoadingOptions>): [Fn, Fn]; + +export function useLoading(opt: Partial<LoadingProps> | Partial<UseLoadingOptions>): [Fn, Fn] { + let props: Partial<LoadingProps>; + let target: HTMLElement | Ref<ElRef> = document.body; + + if (Reflect.has(opt, 'target') || Reflect.has(opt, 'props')) { + const options = opt as Partial<UseLoadingOptions>; + props = options.props || {}; + target = options.target || document.body; + } else { + props = opt as Partial<LoadingProps>; + } + + const instance = createLoading(props); + + const open = (): void => { + const t = unref(target); + if (!t) return; + instance.open(t); + }; + + const close = (): void => { + instance.close(); + }; + + return [open, close]; +} diff --git a/src/components/Loading/type.ts b/src/components/Loading/type.ts deleted file mode 100644 index 03a050f..0000000 --- a/src/components/Loading/type.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { SizeEnum } from '/@/enums/sizeEnum'; - -export interface BasicLoadingProps { - // 提示语 - tip: string; - - size: SizeEnum; -} diff --git a/src/components/Preview/src/index.tsx b/src/components/Preview/src/index.tsx index 334b8a4..8d91560 100644 --- a/src/components/Preview/src/index.tsx +++ b/src/components/Preview/src/index.tsx @@ -1,16 +1,17 @@ +import './index.less'; + import { defineComponent, ref, unref, computed, reactive, watchEffect } from 'vue'; import { basicProps } from './props'; import { Props } from './types'; -import './index.less'; -import { CloseOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons-vue'; +import { CloseOutlined, LeftOutlined, RightOutlined, LoadingOutlined } from '@ant-design/icons-vue'; +import { Spin } from 'ant-design-vue'; import resumeSvg from '/@/assets/svg/preview/resume.svg'; import rotateSvg from '/@/assets/svg/preview/p-rotate.svg'; import scaleSvg from '/@/assets/svg/preview/scale.svg'; import unScaleSvg from '/@/assets/svg/preview/unscale.svg'; -import loadingSvg from '/@/assets/images/loading.svg'; import unRotateSvg from '/@/assets/svg/preview/unrotate.svg'; enum StatueEnum { LOADING, @@ -271,12 +272,14 @@ export default defineComponent({ imgState.show && ( <div class={prefixCls} ref={wrapElRef} onMouseup={handleMouseUp}> <div class={`${prefixCls}-content`}> - <img - width="32" - src={loadingSvg} + <Spin + indicator={<LoadingOutlined style="font-size: 24px" spin />} + spinning={true} class={[ `${prefixCls}-image`, - imgState.status === StatueEnum.LOADING ? '' : 'hidden', + { + hidden: imgState.status !== StatueEnum.LOADING, + }, ]} /> <img diff --git a/src/design/public.less b/src/design/public.less index 905fc90..42089df 100644 --- a/src/design/public.less +++ b/src/design/public.less @@ -3,11 +3,6 @@ height: 100%; } -.app-svg-loading { - position: relative; - width: auto; -} - // ================================= // ==============scrollbar========== // ================================= diff --git a/src/hooks/web/useI18n.ts b/src/hooks/web/useI18n.ts index 2c50c71..1a852f8 100644 --- a/src/hooks/web/useI18n.ts +++ b/src/hooks/web/useI18n.ts @@ -26,6 +26,7 @@ export function useI18n(namespace?: string) { return { ...methods, t: (key: string, ...arg: Parameters<typeof t>) => { + if (!key) return ''; return t(getKey(key), ...arg); }, }; diff --git a/src/layouts/default/content/index.less b/src/layouts/default/content/index.less index 42bd51b..6912f98 100644 --- a/src/layouts/default/content/index.less +++ b/src/layouts/default/content/index.less @@ -14,10 +14,6 @@ position: absolute; z-index: @page-loading-z-index; - &.fill { - background: rgba(240, 242, 245) !important; - } - > .basic-loading { margin-bottom: 15%; } diff --git a/src/layouts/default/content/index.tsx b/src/layouts/default/content/index.tsx index 0354499..464e58f 100644 --- a/src/layouts/default/content/index.tsx +++ b/src/layouts/default/content/index.tsx @@ -1,31 +1,25 @@ import './index.less'; -import { defineComponent, unref, computed } from 'vue'; -import { FullLoading } from '/@/components/Loading/index'; +import { defineComponent, unref } from 'vue'; +import { Loading } from '/@/components/Loading'; import { RouterView } from 'vue-router'; import { useRootSetting } from '/@/hooks/setting/useRootSetting'; import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting'; -import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; export default defineComponent({ name: 'LayoutContent', setup() { const { getOpenPageLoading } = useTransitionSetting(); - const { getShowMultipleTab } = useMultipleTabSetting(); const { getLayoutContentMode, getPageLoading } = useRootSetting(); - const getLoadingClass = computed(() => { - return [ - `layout-content__loading`, - { fill: unref(getShowMultipleTab), hidden: !unref(getPageLoading) }, - ]; - }); return () => { return ( <div class={['layout-content', unref(getLayoutContentMode)]}> - {unref(getOpenPageLoading) && <FullLoading class={unref(getLoadingClass)} />} + {unref(getOpenPageLoading) && ( + <Loading loading={unref(getPageLoading)} absolute class="layout-content__loading" /> + )} <RouterView /> </div> ); diff --git a/src/layouts/page/index.tsx b/src/layouts/page/index.tsx index f94a02e..24e8551 100644 --- a/src/layouts/page/index.tsx +++ b/src/layouts/page/index.tsx @@ -22,6 +22,7 @@ export default defineComponent({ name: 'PageLayout', setup() { const { getShowMenu } = useMenuSetting(); + const { getOpenKeepAlive, getCanEmbedIFramePage } = useRootSetting(); const { getBasicTransition, getEnableTransition } = useTransitionSetting(); diff --git a/src/locales/lang/en/routes/demo/comp.ts b/src/locales/lang/en/routes/demo/comp.ts index 029d728..4099ef1 100644 --- a/src/locales/lang/en/routes/demo/comp.ts +++ b/src/locales/lang/en/routes/demo/comp.ts @@ -24,4 +24,6 @@ export default { qrcode: 'QR code', strength: 'Password strength', upload: 'Upload', + + loading: 'Loading', }; diff --git a/src/locales/lang/zh_CN/routes/demo/comp.ts b/src/locales/lang/zh_CN/routes/demo/comp.ts index 13d8345..cf49f6c 100644 --- a/src/locales/lang/zh_CN/routes/demo/comp.ts +++ b/src/locales/lang/zh_CN/routes/demo/comp.ts @@ -24,4 +24,6 @@ export default { qrcode: '二维码组件', strength: '密码强度组件', upload: '上传组件', + + loading: 'Loading', }; diff --git a/src/router/menus/modules/demo/comp.ts b/src/router/menus/modules/demo/comp.ts index 81858a4..6b46769 100644 --- a/src/router/menus/modules/demo/comp.ts +++ b/src/router/menus/modules/demo/comp.ts @@ -45,6 +45,10 @@ const menu: MenuModule = { name: 'routes.demo.comp.upload', }, { + path: 'loading', + name: 'routes.demo.comp.loading', + }, + { path: 'scroll', name: 'routes.demo.comp.scroll', children: [ diff --git a/src/router/routes/modules/demo/comp.ts b/src/router/routes/modules/demo/comp.ts index 8cc0e57..b5dc627 100644 --- a/src/router/routes/modules/demo/comp.ts +++ b/src/router/routes/modules/demo/comp.ts @@ -178,6 +178,14 @@ const comp: AppRouteModule = { title: 'routes.demo.comp.upload', }, }, + { + path: '/loading', + name: 'LoadingDemo', + component: () => import('/@/views/demo/comp/loading/index.vue'), + meta: { + title: 'routes.demo.comp.loading', + }, + }, ], }; diff --git a/src/setup/ant-design-vue/index.ts b/src/setup/ant-design-vue/index.ts index 15ee4a6..d16f7cc 100644 --- a/src/setup/ant-design-vue/index.ts +++ b/src/setup/ant-design-vue/index.ts @@ -12,8 +12,6 @@ import { } from 'ant-design-vue'; import 'ant-design-vue/dist/antd.css'; -import './spin'; - export function setupAntd(app: App<Element>) { // need // Here are the components required before registering and logging in diff --git a/src/setup/ant-design-vue/spin.tsx b/src/setup/ant-design-vue/spin.tsx deleted file mode 100644 index 5cfae8b..0000000 --- a/src/setup/ant-design-vue/spin.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Spin } from 'ant-design-vue'; -import svgImg from '/@/assets/images/loading.svg'; - -Spin.setDefaultIndicator({ - indicator: () => { - return ( - <div class="app-svg-loading"> - <img src={svgImg} alt="" height="32" width="32" /> - </div> - ); - }, -}); diff --git a/src/setup/directives/index.ts b/src/setup/directives/index.ts index 34c8655..0329eb6 100644 --- a/src/setup/directives/index.ts +++ b/src/setup/directives/index.ts @@ -3,7 +3,9 @@ */ import type { App } from 'vue'; import { setupPermissionDirective } from './permission'; +import { setupLoadingDirective } from './loading'; export function setupGlobDirectives(app: App) { setupPermissionDirective(app); + setupLoadingDirective(app); } diff --git a/src/setup/directives/loading.ts b/src/setup/directives/loading.ts new file mode 100644 index 0000000..20c6e44 --- /dev/null +++ b/src/setup/directives/loading.ts @@ -0,0 +1,43 @@ +import { createLoading } from '/@/components/Loading'; +import type { Directive, App } from 'vue'; + +const loadingDirective: Directive = { + mounted(el, binding) { + const tip = el.getAttribute('loading-tip'); + const background = el.getAttribute('loading-background'); + const theme = el.getAttribute('loading-theme'); + const size = el.getAttribute('loading-size'); + const fullscreen = !!binding.modifiers.fullscreen; + const instance = createLoading( + { + tip, + background, + theme, + size: size || 'large', + loading: !!binding.value, + absolute: !fullscreen, + }, + fullscreen ? document.body : el + ); + el.instance = instance; + }, + updated(el, binding) { + const instance = el.instance; + if (!instance) return; + instance.setTip(el.getAttribute('loading-tip')); + if (binding.oldValue !== binding.value) { + if (binding.oldValue !== binding.value) { + instance.setLoading?.(binding.value && !instance.loading); + } + } + }, + unmounted(el) { + el?.instance?.close(); + }, +}; + +export function setupLoadingDirective(app: App) { + app.directive('loading', loadingDirective); +} + +export default loadingDirective; diff --git a/src/setup/i18n/index.ts b/src/setup/i18n/index.ts index 90fb27f..8d704b1 100644 --- a/src/setup/i18n/index.ts +++ b/src/setup/i18n/index.ts @@ -15,7 +15,8 @@ const localeData: I18nOptions = { messages: localeMessages, availableLocales: availableLocales, sync: true, //If you don’t want to inherit locale from global scope, you need to set sync of i18n component option to false. - silentTranslationWarn: false, // true - warning off + silentTranslationWarn: true, // true - warning off + missingWarn: false, silentFallbackWarn: true, }; diff --git a/src/views/demo/comp/loading/index.vue b/src/views/demo/comp/loading/index.vue new file mode 100644 index 0000000..7524cef --- /dev/null +++ b/src/views/demo/comp/loading/index.vue @@ -0,0 +1,96 @@ +<template> + <div class="p-5" ref="wrapEl" v-loading="loadingRef" loading-tip="加载中..."> + <a-alert message="组件方式" /> + <a-button class="my-4 mr-4" type="primary" @click="openCompFullLoading">全屏 Loading</a-button> + <a-button class="my-4" type="primary" @click="openCompAbsolute">容器内 Loading</a-button> + <Loading :loading="loading" :absolute="absolute" :tip="tip" /> + + <a-alert message="函数方式" /> + + <a-button class="my-4 mr-4" type="primary" @click="openFnFullLoading">全屏 Loading</a-button> + <a-button class="my-4" type="primary" @click="openFnWrapLoading">容器内 Loading</a-button> + + <a-alert message="指令方式" /> + <a-button class="my-4 mr-4" type="primary" @click="openDirectiveLoading"> + 打开指令Loading + </a-button> + </div> +</template> +<script lang="ts"> + import { defineComponent, reactive, toRefs, ref } from 'vue'; + import { Loading, useLoading } from '/@/components/Loading'; + export default defineComponent({ + components: { Loading }, + setup() { + const wrapEl = ref<ElRef>(null); + + const loadingRef = ref(false); + const compState = reactive({ + absolute: false, + loading: false, + tip: '加载中...', + }); + const [openFullLoading, closeFullLoading] = useLoading({ + tip: '加载中...', + }); + + const [openWrapLoading, closeWrapLoading] = useLoading({ + target: wrapEl, + props: { + tip: '加载中...', + absolute: true, + }, + }); + + function openLoading(absolute: boolean) { + compState.absolute = absolute; + compState.loading = true; + setTimeout(() => { + compState.loading = false; + }, 2000); + } + + function openCompFullLoading() { + openLoading(false); + } + + function openCompAbsolute() { + openLoading(true); + } + + function openFnFullLoading() { + openFullLoading(); + + setTimeout(() => { + closeFullLoading(); + }, 2000); + } + + function openFnWrapLoading() { + openWrapLoading(); + + setTimeout(() => { + closeWrapLoading(); + }, 2000); + } + + function openDirectiveLoading() { + loadingRef.value = true; + setTimeout(() => { + loadingRef.value = false; + }, 2000); + } + + return { + openCompFullLoading, + openFnFullLoading, + openFnWrapLoading, + openCompAbsolute, + wrapEl, + loadingRef, + openDirectiveLoading, + ...toRefs(compState), + }; + }, + }); +</script> diff --git a/tsconfig.json b/tsconfig.json index 683297d..d095229 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "esnext", + "target": "es2016", "module": "esnext", "moduleResolution": "node", "strict": true, diff --git a/vite.config.ts b/vite.config.ts index 781ecc7..67d1ddc 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -8,7 +8,7 @@ import { createProxy } from './build/vite/proxy'; import globbyTransform from './build/vite/plugin/transform/globby'; import dynamicImportTransform from './build/vite/plugin/transform/dynamic-import'; -import { isDevFn, loadEnv } from './build/utils'; +import { loadEnv } from './build/utils'; import { createRollupPlugin, createVitePlugins } from './build/vite/plugin'; @@ -55,7 +55,7 @@ const viteConfig: UserConfig = { * Available options are 'terser' or 'esbuild'. * @default 'terser' */ - minify: isDevFn() ? false : 'terser', + minify: 'terser', /** * Base public path when served in production. * @default '/' diff --git a/yarn.lock b/yarn.lock index 05b4873..896fb40 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25,13 +25,14 @@ integrity sha512-Fi03PfuUqRs76aI3UWYpP864lkrfPo0hluwGqh7NJdLhvH4iRDc3jbJqZIvRDLHKbXrvAfPPV3+zjUccfFvWOQ== "@ant-design/icons-vue@^5.1.6": - version "5.1.6" - resolved "https://registry.npmjs.org/@ant-design/icons-vue/-/icons-vue-5.1.6.tgz#af15cbf2375d95199e90166adce4c9f6ad1c17f1" - integrity sha512-1KY04c/0iDM88ICdu6EW2/ZPOrH+FyL0uvR350XnVqvnDiLijdcrRaLzkZgCdBcy7cy5t5+onXKocymndCOdRA== + version "5.1.7" + resolved "https://registry.npmjs.org/@ant-design/icons-vue/-/icons-vue-5.1.7.tgz#5f8e26b547c3ecc16c0820152b935e8a44b5fad3" + integrity sha512-6UN/FydLs/bHC0WZxgSpdk0Ct8Ejzr7gdOx5sAIULpSprkxoHWiUbzTy8BMmUduImL42YY1L/qtZYJD6pIzmcQ== dependencies: "@ant-design/colors" "^5.0.0" "@ant-design/icons-svg" "^4.0.0" "@babel/runtime" "^7.10.4" + "@types/lodash" "^4.14.165" lodash "^4.17.15" "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3": @@ -1420,7 +1421,7 @@ dependencies: "@types/lodash" "*" -"@types/lodash@*": +"@types/lodash@*", "@types/lodash@^4.14.165": version "4.14.165" resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.165.tgz#74d55d947452e2de0742bad65270433b63a8c30f" integrity sha512-tjSSOTHhI5mCHTy/OOXYIhi2Wt1qcbHmuXD1Ha7q70CgI/I71afO4XtLb/cVexki1oVYchpul/TOuu3Arcdxrg== @@ -1959,7 +1960,7 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -ant-design-vue@2.0.0-rc.2: +ant-design-vue@^2.0.0-rc.2: version "2.0.0-rc.2" resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-2.0.0-rc.2.tgz#fd3b4a5a64fccbb53ed488a194317a040de2223e" integrity sha512-XA7X/7HHIveiTh41bZWGfoQ2Rys/rqWknK2zzdHwVnfw9ST3v+ciMKH0Uegyn7m14QL/EdUkC8zGsXpiSXqKNQ== -- libgit2 0.23.3