Commit a89eeef6f3a0b9863d28cf516b126a938eed7361

Authored by Vben
1 parent fab7a6c5

feat(time): added time compoennt close #285

.env.development
@@ -7,7 +7,8 @@ VITE_USE_MOCK = true @@ -7,7 +7,8 @@ VITE_USE_MOCK = true
7 VITE_PUBLIC_PATH = / 7 VITE_PUBLIC_PATH = /
8 8
9 # Cross-domain proxy, you can configure multiple 9 # Cross-domain proxy, you can configure multiple
10 -VITE_PROXY=[["/basic-api","http://localhost:3000"],["/upload","http://localhost:3001/upload"]] 10 +# Please note that no line breaks
  11 +VITE_PROXY = [["/basic-api","http://localhost:3000"],["/upload","http://localhost:3001/upload"]]
11 # VITE_PROXY=[["/api","https://vvbin.cn/test"]] 12 # VITE_PROXY=[["/api","https://vvbin.cn/test"]]
12 13
13 # Delete console 14 # Delete console
.vscode/settings.json
@@ -6,18 +6,18 @@ @@ -6,18 +6,18 @@
6 //============= Editor ====================== 6 //============= Editor ======================
7 //=========================================== 7 //===========================================
8 "explorer.openEditors.visible": 0, 8 "explorer.openEditors.visible": 0,
  9 + "editor.tabSize": 2,
  10 + "editor.renderControlCharacters": true,
  11 + "window.zoomLevel": -1,
9 "editor.minimap.renderCharacters": false, 12 "editor.minimap.renderCharacters": false,
10 "editor.minimap.maxColumn": 300, 13 "editor.minimap.maxColumn": 300,
11 "editor.minimap.showSlider": "always", 14 "editor.minimap.showSlider": "always",
12 - "editor.smoothScrolling": true,  
13 "editor.cursorBlinking": "phase", 15 "editor.cursorBlinking": "phase",
14 "editor.cursorSmoothCaretAnimation": true, 16 "editor.cursorSmoothCaretAnimation": true,
15 "editor.detectIndentation": false, 17 "editor.detectIndentation": false,
16 "editor.defaultFormatter": "esbenp.prettier-vscode", 18 "editor.defaultFormatter": "esbenp.prettier-vscode",
17 "diffEditor.ignoreTrimWhitespace": false, 19 "diffEditor.ignoreTrimWhitespace": false,
18 "javascript.format.insertSpaceBeforeFunctionParenthesis": true, 20 "javascript.format.insertSpaceBeforeFunctionParenthesis": true,
19 - "editor.formatOnPaste": true,  
20 - "editor.formatOnSave": true,  
21 "editor.suggestSelection": "first", 21 "editor.suggestSelection": "first",
22 "editor.trimAutoWhitespace": true, 22 "editor.trimAutoWhitespace": true,
23 "editor.quickSuggestions": { 23 "editor.quickSuggestions": {
@@ -39,7 +39,6 @@ @@ -39,7 +39,6 @@
39 "emmet.syntaxProfiles": { 39 "emmet.syntaxProfiles": {
40 "vue-html": "html", 40 "vue-html": "html",
41 "vue": "html", 41 "vue": "html",
42 - "javascript": "javascriptreact",  
43 "xml": { 42 "xml": {
44 "attr_quotes": "single" 43 "attr_quotes": "single"
45 } 44 }
@@ -80,7 +79,6 @@ @@ -80,7 +79,6 @@
80 "files.exclude": { 79 "files.exclude": {
81 "**/bower_components": true, 80 "**/bower_components": true,
82 "**/.idea": true, 81 "**/.idea": true,
83 - "**/yarn.lock": true,  
84 "**/tmp": true, 82 "**/tmp": true,
85 "**/.git": true, 83 "**/.git": true,
86 "**/.svn": true, 84 "**/.svn": true,
@@ -89,7 +87,6 @@ @@ -89,7 +87,6 @@
89 "**/.DS_Store": true 87 "**/.DS_Store": true
90 }, 88 },
91 "files.watcherExclude": { 89 "files.watcherExclude": {
92 - // 文件监视排除  
93 "**/.git/objects/**": true, 90 "**/.git/objects/**": true,
94 "**/.git/subtree-cache/**": true, 91 "**/.git/subtree-cache/**": true,
95 "**/.vscode/**": true, 92 "**/.vscode/**": true,
@@ -99,10 +96,6 @@ @@ -99,10 +96,6 @@
99 "**/dist/**": true, 96 "**/dist/**": true,
100 "**/yarn.lock": true 97 "**/yarn.lock": true
101 }, 98 },
102 - "files.associations": {  
103 - "*.vue": "vue",  
104 - "*.wxss": "css"  
105 - },  
106 "stylelint.enable": true, 99 "stylelint.enable": true,
107 "stylelint.packageManager": "yarn", 100 "stylelint.packageManager": "yarn",
108 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 101 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
CHANGELOG.zh_CN.md
@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
3 ### ✨ Features 3 ### ✨ Features
4 4
5 - 图标选择器新增 svg 模式 5 - 图标选择器新增 svg 模式
  6 +- 新增时间组件
6 7
7 ### ✨ Refactor 8 ### ✨ Refactor
8 9
build/vite/optimizer.ts
1 // TODO 1 // TODO
2 -import type { GetManualChunk, GetManualChunkApi } from 'rollup'; 2 +import type { GetManualChunk } from 'rollup';
3 3
4 // 4 //
5 const vendorLibs: { match: string[]; output: string }[] = [ 5 const vendorLibs: { match: string[]; output: string }[] = [
@@ -10,8 +10,7 @@ const vendorLibs: { match: string[]; output: string }[] = [ @@ -10,8 +10,7 @@ const vendorLibs: { match: string[]; output: string }[] = [
10 ]; 10 ];
11 11
12 // @ts-ignore 12 // @ts-ignore
13 -export const configManualChunk: GetManualChunk = (id: string, api: GetManualChunkApi) => {  
14 - console.log(api); 13 +export const configManualChunk: GetManualChunk = (id: string) => {
15 if (/[\\/]node_modules[\\/]/.test(id)) { 14 if (/[\\/]node_modules[\\/]/.test(id)) {
16 const matchItem = vendorLibs.find((item) => { 15 const matchItem = vendorLibs.find((item) => {
17 const reg = new RegExp(`[\\/]node_modules[\\/]_?(${item.match.join('|')})(.*)`, 'ig'); 16 const reg = new RegExp(`[\\/]node_modules[\\/]_?(${item.match.join('|')})(.*)`, 'ig');
package.json
@@ -49,7 +49,7 @@ @@ -49,7 +49,7 @@
49 "vditor": "^3.8.2", 49 "vditor": "^3.8.2",
50 "vue": "^3.0.7", 50 "vue": "^3.0.7",
51 "vue-i18n": "^9.0.0", 51 "vue-i18n": "^9.0.0",
52 - "vue-router": "^4.0.4", 52 + "vue-router": "^4.0.5",
53 "vue-types": "^3.0.2", 53 "vue-types": "^3.0.2",
54 "vuex": "^4.0.0", 54 "vuex": "^4.0.0",
55 "vuex-module-decorators": "^1.0.1", 55 "vuex-module-decorators": "^1.0.1",
@@ -118,7 +118,7 @@ @@ -118,7 +118,7 @@
118 "vite-plugin-style-import": "^0.8.1", 118 "vite-plugin-style-import": "^0.8.1",
119 "vite-plugin-svg-icons": "^0.3.4", 119 "vite-plugin-svg-icons": "^0.3.4",
120 "vite-plugin-theme": "^0.4.8", 120 "vite-plugin-theme": "^0.4.8",
121 - "vite-plugin-windicss": "0.7.2", 121 + "vite-plugin-windicss": "0.8.2",
122 "vue-eslint-parser": "^7.6.0", 122 "vue-eslint-parser": "^7.6.0",
123 "yargs": "^16.2.0" 123 "yargs": "^16.2.0"
124 }, 124 },
src/components/Time/index.ts 0 → 100644
  1 +export { default as Time } from './src/index.vue';
src/components/Time/src/index.vue 0 → 100644
  1 +<template>
  2 + <span>{{ date }}</span>
  3 +</template>
  4 +<script lang="ts">
  5 + import { defineComponent, ref, watch } from 'vue';
  6 +
  7 + import { useI18n } from '/@/hooks/web/useI18n';
  8 + import { useIntervalFn } from '@vueuse/core';
  9 +
  10 + import { formatToDateTime, formatToDate, dateUtil } from '/@/utils/dateUtil';
  11 + import { isNumber, isObject, isString } from '/@/utils/is';
  12 + import { propTypes } from '/@/utils/propTypes';
  13 +
  14 + const ONE_SECONDS = 1000;
  15 + const ONE_MINUTES = ONE_SECONDS * 60;
  16 + const ONE_HOUR = ONE_MINUTES * 60;
  17 + const ONE_DAY = ONE_HOUR * 24;
  18 + export default defineComponent({
  19 + name: 'Time',
  20 + props: {
  21 + value: propTypes.oneOfType([propTypes.number, propTypes.instanceOf(Date), propTypes.string])
  22 + .isRequired,
  23 + step: propTypes.number.def(60),
  24 + mode: propTypes.oneOf(['date', 'datetime', 'relative']).def('relative'),
  25 + },
  26 + setup(props) {
  27 + const date = ref('');
  28 +
  29 + const { t } = useI18n();
  30 +
  31 + useIntervalFn(setTime, props.step * ONE_SECONDS);
  32 +
  33 + watch(
  34 + () => props.value,
  35 + () => {
  36 + setTime();
  37 + },
  38 + { immediate: true }
  39 + );
  40 +
  41 + function getTime() {
  42 + const { value } = props;
  43 + let time: number = 0;
  44 + if (isNumber(value)) {
  45 + const timestamp = value.toString().length > 10 ? value : value * 1000;
  46 + time = new Date(timestamp).getTime();
  47 + } else if (isString(value)) {
  48 + time = new Date(value).getTime();
  49 + } else if (isObject(value)) {
  50 + time = value.getTime();
  51 + }
  52 + return time;
  53 + }
  54 +
  55 + function setTime() {
  56 + const { mode, value } = props;
  57 + const time = getTime();
  58 + if (mode === 'relative') {
  59 + date.value = getRelativeTime(time);
  60 + } else {
  61 + if (mode === 'datetime') {
  62 + date.value = formatToDateTime(value);
  63 + } else if (mode === 'date') {
  64 + date.value = formatToDate(value);
  65 + }
  66 + }
  67 + }
  68 +
  69 + function getRelativeTime(timeStamp: number) {
  70 + const currentTime = new Date().getTime();
  71 +
  72 + // Determine whether the incoming timestamp is earlier than the current timestamp
  73 + const isBefore = dateUtil(timeStamp).isBefore(currentTime);
  74 +
  75 + let diff = currentTime - timeStamp;
  76 + if (!isBefore) {
  77 + diff = -diff;
  78 + }
  79 +
  80 + let resStr = '';
  81 + let dirStr = isBefore ? t('component.time.before') : t('component.time.after');
  82 +
  83 + if (diff < ONE_SECONDS) {
  84 + resStr = t('component.time.just');
  85 + // Less than or equal to 59 seconds
  86 + } else if (diff < ONE_MINUTES) {
  87 + resStr = parseInt(diff / ONE_SECONDS) + t('component.time.seconds') + dirStr;
  88 + // More than 59 seconds, less than or equal to 59 minutes and 59 seconds
  89 + } else if (diff >= ONE_MINUTES && diff < ONE_HOUR) {
  90 + resStr = Math.floor(diff / ONE_MINUTES) + t('component.time.minutes') + dirStr;
  91 + // More than 59 minutes and 59 seconds, less than or equal to 23 hours, 59 minutes and 59 seconds
  92 + } else if (diff >= ONE_HOUR && diff < ONE_DAY) {
  93 + resStr = Math.floor(diff / ONE_HOUR) + t('component.time.hours') + dirStr;
  94 + // More than 23 hours, 59 minutes and 59 seconds, less than or equal to 29 days, 59 minutes and 59 seconds
  95 + } else if (diff >= ONE_DAY && diff < 2623860000) {
  96 + resStr = Math.floor(diff / ONE_DAY) + t('component.time.days') + dirStr;
  97 + // More than 29 days, 59 minutes, 59 seconds, less than 364 days, 23 hours, 59 minutes, 59 seconds, and the incoming timestamp is earlier than the current
  98 + } else if (diff >= 2623860000 && diff <= 31567860000 && isBefore) {
  99 + resStr = dateUtil(timeStamp).format('MM-DD-HH-mm');
  100 + } else {
  101 + resStr = dateUtil(timeStamp).format('YYYY');
  102 + }
  103 + return resStr;
  104 + }
  105 +
  106 + return { date };
  107 + },
  108 + });
  109 +</script>
src/hooks/core/useContext.ts
@@ -4,7 +4,7 @@ import { @@ -4,7 +4,7 @@ import {
4 inject, 4 inject,
5 reactive, 5 reactive,
6 readonly as defineReadonly, 6 readonly as defineReadonly,
7 - defineComponent, 7 + // defineComponent,
8 UnwrapRef, 8 UnwrapRef,
9 } from 'vue'; 9 } from 'vue';
10 10
@@ -29,18 +29,21 @@ export function createContext&lt;T&gt;( @@ -29,18 +29,21 @@ export function createContext&lt;T&gt;(
29 const provideData = readonly ? defineReadonly(state) : state; 29 const provideData = readonly ? defineReadonly(state) : state;
30 !createProvider && provide(key, native ? context : provideData); 30 !createProvider && provide(key, native ? context : provideData);
31 31
32 - const Provider = createProvider  
33 - ? defineComponent({  
34 - name: 'Provider',  
35 - inheritAttrs: false,  
36 - setup(_, { slots }) {  
37 - provide(key, provideData);  
38 - return () => slots.default?.();  
39 - },  
40 - })  
41 - : null;  
42 -  
43 - return { Provider, state }; 32 + // const Provider = createProvider
  33 + // ? defineComponent({
  34 + // name: 'Provider',
  35 + // inheritAttrs: false,
  36 + // setup(_, { slots }) {
  37 + // provide(key, provideData);
  38 + // return () => slots.default?.();
  39 + // },
  40 + // })
  41 + // : null;
  42 +
  43 + return {
  44 + // Provider,
  45 + state,
  46 + };
44 } 47 }
45 48
46 export function useContext<T>(key: InjectionKey<T>, native?: boolean): T; 49 export function useContext<T>(key: InjectionKey<T>, native?: boolean): T;
src/layouts/default/content/index.vue
1 <template> 1 <template>
2 - <div :class="[prefixCls, getLayoutContentMode]">  
3 - <transition name="fade">  
4 - <Loading  
5 - v-if="getOpenPageLoading"  
6 - :loading="getPageLoading"  
7 - background="rgba(240, 242, 245, 0.6)"  
8 - absolute  
9 - :class="`${prefixCls}-loading`"  
10 - />  
11 - </transition> 2 + <div :class="[prefixCls, getLayoutContentMode]" v-loading="getOpenPageLoading && getPageLoading">
12 <PageLayout /> 3 <PageLayout />
13 </div> 4 </div>
14 </template> 5 </template>
15 <script lang="ts"> 6 <script lang="ts">
16 import { defineComponent } from 'vue'; 7 import { defineComponent } from 'vue';
17 8
  9 + import PageLayout from '/@/layouts/page/index.vue';
  10 +
18 import { useDesign } from '/@/hooks/web/useDesign'; 11 import { useDesign } from '/@/hooks/web/useDesign';
19 import { useRootSetting } from '/@/hooks/setting/useRootSetting'; 12 import { useRootSetting } from '/@/hooks/setting/useRootSetting';
20 import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting'; 13 import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
21 - import PageLayout from '/@/layouts/page/index.vue';  
22 import { useContentViewHeight } from './useContentViewHeight'; 14 import { useContentViewHeight } from './useContentViewHeight';
23 - import { Loading } from '/@/components/Loading';  
24 15
25 export default defineComponent({ 16 export default defineComponent({
26 name: 'LayoutContent', 17 name: 'LayoutContent',
27 - components: { PageLayout, Loading }, 18 + components: { PageLayout },
28 setup() { 19 setup() {
29 const { prefixCls } = useDesign('layout-content'); 20 const { prefixCls } = useDesign('layout-content');
30 const { getOpenPageLoading } = useTransitionSetting(); 21 const { getOpenPageLoading } = useTransitionSetting();
src/layouts/default/footer/index.vue
@@ -2,7 +2,9 @@ @@ -2,7 +2,9 @@
2 <Footer :class="prefixCls" v-if="getShowLayoutFooter"> 2 <Footer :class="prefixCls" v-if="getShowLayoutFooter">
3 <div :class="`${prefixCls}__links`"> 3 <div :class="`${prefixCls}__links`">
4 <a @click="openWindow(SITE_URL)">{{ t('layout.footer.onlinePreview') }}</a> 4 <a @click="openWindow(SITE_URL)">{{ t('layout.footer.onlinePreview') }}</a>
  5 +
5 <GithubFilled @click="openWindow(GITHUB_URL)" :class="`${prefixCls}__github`" /> 6 <GithubFilled @click="openWindow(GITHUB_URL)" :class="`${prefixCls}__github`" />
  7 +
6 <a @click="openWindow(DOC_URL)">{{ t('layout.footer.onlineDocument') }}</a> 8 <a @click="openWindow(DOC_URL)">{{ t('layout.footer.onlineDocument') }}</a>
7 </div> 9 </div>
8 <div>Copyright &copy;2020 Vben Admin</div> 10 <div>Copyright &copy;2020 Vben Admin</div>
src/layouts/default/index.vue
@@ -2,13 +2,9 @@ @@ -2,13 +2,9 @@
2 <Layout :class="prefixCls"> 2 <Layout :class="prefixCls">
3 <LayoutFeatures /> 3 <LayoutFeatures />
4 <LayoutHeader fixed v-if="getShowFullHeaderRef" /> 4 <LayoutHeader fixed v-if="getShowFullHeaderRef" />
5 - <Layout  
6 - :class="{  
7 - 'ant-layout-has-sider': getIsMixSidebar,  
8 - }"  
9 - > 5 + <Layout :class="layoutClass">
10 <LayoutSideBar v-if="getShowSidebar || getIsMobile" /> 6 <LayoutSideBar v-if="getShowSidebar || getIsMobile" />
11 - <Layout :class="`${prefixCls}__main`"> 7 + <Layout :class="`${prefixCls}-main`">
12 <LayoutMultipleHeader /> 8 <LayoutMultipleHeader />
13 <LayoutContent /> 9 <LayoutContent />
14 <LayoutFooter /> 10 <LayoutFooter />
@@ -18,7 +14,7 @@ @@ -18,7 +14,7 @@
18 </template> 14 </template>
19 15
20 <script lang="ts"> 16 <script lang="ts">
21 - import { defineComponent } from 'vue'; 17 + import { defineComponent, computed, unref } from 'vue';
22 import { Layout } from 'ant-design-vue'; 18 import { Layout } from 'ant-design-vue';
23 import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; 19 import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
24 20
@@ -53,12 +49,15 @@ @@ -53,12 +49,15 @@
53 49
54 const { getShowSidebar, getIsMixSidebar } = useMenuSetting(); 50 const { getShowSidebar, getIsMixSidebar } = useMenuSetting();
55 51
  52 + const layoutClass = computed(() => ({ 'ant-layout-has-sider': unref(getIsMixSidebar) }));
  53 +
56 return { 54 return {
57 getShowFullHeaderRef, 55 getShowFullHeaderRef,
58 getShowSidebar, 56 getShowSidebar,
59 prefixCls, 57 prefixCls,
60 getIsMobile, 58 getIsMobile,
61 getIsMixSidebar, 59 getIsMixSidebar,
  60 + layoutClass,
62 }; 61 };
63 }, 62 },
64 }); 63 });
@@ -77,7 +76,7 @@ @@ -77,7 +76,7 @@
77 min-height: 100%; 76 min-height: 100%;
78 } 77 }
79 78
80 - &__main { 79 + &-main {
81 margin-left: 1px; 80 margin-left: 1px;
82 } 81 }
83 } 82 }
src/layouts/default/trigger/HeaderTrigger.vue
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 import { propTypes } from '/@/utils/propTypes'; 11 import { propTypes } from '/@/utils/propTypes';
12 12
13 export default defineComponent({ 13 export default defineComponent({
14 - name: 'SiderTrigger', 14 + name: 'HeaderTrigger',
15 components: { MenuUnfoldOutlined, MenuFoldOutlined }, 15 components: { MenuUnfoldOutlined, MenuFoldOutlined },
16 props: { 16 props: {
17 theme: propTypes.oneOf(['light', 'dark']), 17 theme: propTypes.oneOf(['light', 'dark']),
src/locales/lang/en/component/time.ts 0 → 100644
  1 +export default {
  2 + before: ' ago',
  3 + after: ' after',
  4 + just: 'just now',
  5 + seconds: ' seconds',
  6 + minutes: ' minutes',
  7 + hours: ' hours',
  8 + days: ' days',
  9 +};
src/locales/lang/en/routes/demo/comp.ts
@@ -32,4 +32,6 @@ export default { @@ -32,4 +32,6 @@ export default {
32 upload: 'Upload', 32 upload: 'Upload',
33 33
34 loading: 'Loading', 34 loading: 'Loading',
  35 +
  36 + time: 'Time',
35 }; 37 };
src/locales/lang/zh_CN/component/time.ts 0 → 100644
  1 +export default {
  2 + before: '前',
  3 + after: '后',
  4 + just: '刚刚',
  5 + seconds: '秒',
  6 + minutes: '分钟',
  7 + hours: '小时',
  8 + days: '天',
  9 +};
src/locales/lang/zh_CN/routes/demo/comp.ts
@@ -31,4 +31,6 @@ export default { @@ -31,4 +31,6 @@ export default {
31 upload: '上传组件', 31 upload: '上传组件',
32 32
33 loading: 'Loading', 33 loading: 'Loading',
  34 +
  35 + time: '时间组件',
34 }; 36 };
src/router/index.ts
@@ -2,7 +2,6 @@ import type { RouteRecordRaw } from &#39;vue-router&#39;; @@ -2,7 +2,6 @@ import type { RouteRecordRaw } from &#39;vue-router&#39;;
2 import type { App } from 'vue'; 2 import type { App } from 'vue';
3 3
4 import { createRouter, createWebHashHistory } from 'vue-router'; 4 import { createRouter, createWebHashHistory } from 'vue-router';
5 -  
6 import { basicRoutes, LoginRoute } from './routes'; 5 import { basicRoutes, LoginRoute } from './routes';
7 import { REDIRECT_NAME } from './constant'; 6 import { REDIRECT_NAME } from './constant';
8 7
src/router/menus/modules/demo/comp.ts
@@ -122,6 +122,13 @@ const menu: MenuModule = { @@ -122,6 +122,13 @@ const menu: MenuModule = {
122 name: t('routes.demo.comp.countTo'), 122 name: t('routes.demo.comp.countTo'),
123 }, 123 },
124 { 124 {
  125 + path: 'timestamp',
  126 + name: t('routes.demo.comp.time'),
  127 + tag: {
  128 + content: 'new',
  129 + },
  130 + },
  131 + {
125 path: 'transition', 132 path: 'transition',
126 name: t('routes.demo.comp.transition'), 133 name: t('routes.demo.comp.transition'),
127 }, 134 },
src/router/routes/modules/demo/comp.ts
@@ -233,6 +233,14 @@ const comp: AppRouteModule = { @@ -233,6 +233,14 @@ const comp: AppRouteModule = {
233 }, 233 },
234 }, 234 },
235 { 235 {
  236 + path: 'timestamp',
  237 + name: 'TimeDemo',
  238 + component: () => import('/@/views/demo/comp/time/index.vue'),
  239 + meta: {
  240 + title: t('routes.demo.comp.time'),
  241 + },
  242 + },
  243 + {
236 path: 'countTo', 244 path: 'countTo',
237 name: 'CountTo', 245 name: 'CountTo',
238 component: () => import('/@/views/demo/comp/count-to/index.vue'), 246 component: () => import('/@/views/demo/comp/count-to/index.vue'),
src/utils/dateUtil.ts
  1 +/**
  2 + * Independent time operation tool to facilitate subsequent switch to dayjs
  3 + */
1 import moment from 'moment'; 4 import moment from 'moment';
2 5
3 const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm'; 6 const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm';
src/views/demo/comp/time/index.vue 0 → 100644
  1 +<template>
  2 + <PageWrapper title="时间组件示例">
  3 + <CollapseContainer title="基础示例">
  4 + <Time :value="time1" />
  5 + <br />
  6 + <Time :value="time2" />
  7 + </CollapseContainer>
  8 +
  9 + <CollapseContainer title="定时更新" class="my-4">
  10 + <Time :value="now" :step="1" />
  11 + <br />
  12 + <Time :value="now" :step="5" />
  13 + </CollapseContainer>
  14 +
  15 + <CollapseContainer title="定时更新">
  16 + <Time :value="now" mode="date" />
  17 + <br />
  18 + <Time :value="now" mode="datetime" />
  19 + <br />
  20 + <Time :value="now" />
  21 + </CollapseContainer>
  22 + </PageWrapper>
  23 +</template>
  24 +<script lang="ts">
  25 + import { defineComponent, reactive, toRefs } from 'vue';
  26 + import { PageWrapper } from '/@/components/Page';
  27 + import { Time } from '/@/components/Time';
  28 + import { CollapseContainer } from '/@/components/Container/index';
  29 +
  30 + export default defineComponent({
  31 + components: { PageWrapper, Time, CollapseContainer },
  32 + setup() {
  33 + const now = new Date().getTime();
  34 + const state = reactive({
  35 + time1: now - 60 * 3 * 1000,
  36 + time2: now - 86400 * 3 * 1000,
  37 + });
  38 + return {
  39 + ...toRefs(state),
  40 + now,
  41 + };
  42 + },
  43 + });
  44 +</script>
yarn.lock
@@ -1790,16 +1790,15 @@ @@ -1790,16 +1790,15 @@
1790 dependencies: 1790 dependencies:
1791 vue-demi latest 1791 vue-demi latest
1792 1792
1793 -"@windicss/plugin-utils@0.7.2":  
1794 - version "0.7.2"  
1795 - resolved "https://registry.npmjs.org/@windicss/plugin-utils/-/plugin-utils-0.7.2.tgz#c43c89a2f51110eb6f49da565dc235fb2af30269"  
1796 - integrity sha512-4znRERKhhStIOFy1/eB0rJXnXs+NyumBREjh0GZVMoHVmUB9up08tNUpbbq3tlJC96t27VsD4vdfv00T+It/IA== 1793 +"@windicss/plugin-utils@0.8.2":
  1794 + version "0.8.2"
  1795 + resolved "https://registry.npmjs.org/@windicss/plugin-utils/-/plugin-utils-0.8.2.tgz#032b21a79ff5af5031bf29bc3faeb0efcce73afb"
  1796 + integrity sha512-jBv9w3VrUF5BjkP/WjY5Brf6CzJYeFMwcZFfOYiSPGuK+4+a/UmYX8B0/bISp5GnY9plVYr5aibTY9PTbt597Q==
1797 dependencies: 1797 dependencies:
1798 - esbuild "^0.8.57"  
1799 - esbuild-register "^2.2.0"  
1800 fast-glob "^3.2.5" 1798 fast-glob "^3.2.5"
1801 micromatch "^4.0.2" 1799 micromatch "^4.0.2"
1802 - windicss "^2.3.0" 1800 + sucrase "^3.17.1"
  1801 + windicss "^2.4.0"
1803 1802
1804 "@zxcvbn-ts/core@^0.3.0": 1803 "@zxcvbn-ts/core@^0.3.0":
1805 version "0.3.0" 1804 version "0.3.0"
@@ -1944,6 +1943,11 @@ ant-design-vue@2.0.1: @@ -1944,6 +1943,11 @@ ant-design-vue@2.0.1:
1944 vue-types "^3.0.0" 1943 vue-types "^3.0.0"
1945 warning "^4.0.0" 1944 warning "^4.0.0"
1946 1945
  1946 +any-promise@^1.0.0:
  1947 + version "1.3.0"
  1948 + resolved "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
  1949 + integrity sha1-q8av7tzqUugJzcA3au0845Y10X8=
  1950 +
1947 anymatch@~3.1.1: 1951 anymatch@~3.1.1:
1948 version "3.1.1" 1952 version "3.1.1"
1949 resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" 1953 resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142"
@@ -2745,7 +2749,7 @@ commander@^2.16.0, commander@^2.20.0, commander@^2.20.3, commander@^2.8.1: @@ -2745,7 +2749,7 @@ commander@^2.16.0, commander@^2.20.0, commander@^2.20.3, commander@^2.8.1:
2745 resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 2749 resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
2746 integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 2750 integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
2747 2751
2748 -commander@^4.1.1: 2752 +commander@^4.0.0, commander@^4.1.1:
2749 version "4.1.1" 2753 version "4.1.1"
2750 resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" 2754 resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
2751 integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== 2755 integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
@@ -4741,7 +4745,7 @@ glob@7.1.4: @@ -4741,7 +4745,7 @@ glob@7.1.4:
4741 once "^1.3.0" 4745 once "^1.3.0"
4742 path-is-absolute "^1.0.0" 4746 path-is-absolute "^1.0.0"
4743 4747
4744 -glob@^7.0.0, glob@^7.1.3, glob@^7.1.6: 4748 +glob@7.1.6, glob@^7.0.0, glob@^7.1.3, glob@^7.1.6:
4745 version "7.1.6" 4749 version "7.1.6"
4746 resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" 4750 resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
4747 integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== 4751 integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
@@ -6588,6 +6592,15 @@ mute-stream@0.0.8: @@ -6588,6 +6592,15 @@ mute-stream@0.0.8:
6588 resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" 6592 resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
6589 integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== 6593 integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
6590 6594
  6595 +mz@^2.7.0:
  6596 + version "2.7.0"
  6597 + resolved "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
  6598 + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==
  6599 + dependencies:
  6600 + any-promise "^1.0.0"
  6601 + object-assign "^4.0.1"
  6602 + thenify-all "^1.0.0"
  6603 +
6591 nanoid@^3.0.1, nanoid@^3.1.20: 6604 nanoid@^3.0.1, nanoid@^3.1.20:
6592 version "3.1.20" 6605 version "3.1.20"
6593 resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788" 6606 resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788"
@@ -6652,6 +6665,11 @@ node-fetch@2.6.1: @@ -6652,6 +6665,11 @@ node-fetch@2.6.1:
6652 resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" 6665 resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
6653 integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== 6666 integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
6654 6667
  6668 +node-modules-regexp@^1.0.0:
  6669 + version "1.0.0"
  6670 + resolved "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40"
  6671 + integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=
  6672 +
6655 node-releases@^1.1.69: 6673 node-releases@^1.1.69:
6656 version "1.1.70" 6674 version "1.1.70"
6657 resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.70.tgz#66e0ed0273aa65666d7fe78febe7634875426a08" 6675 resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.70.tgz#66e0ed0273aa65666d7fe78febe7634875426a08"
@@ -7267,6 +7285,13 @@ pinkie@^2.0.0: @@ -7267,6 +7285,13 @@ pinkie@^2.0.0:
7267 resolved "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" 7285 resolved "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
7268 integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= 7286 integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
7269 7287
  7288 +pirates@^4.0.1:
  7289 + version "4.0.1"
  7290 + resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87"
  7291 + integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==
  7292 + dependencies:
  7293 + node-modules-regexp "^1.0.0"
  7294 +
7270 please-upgrade-node@^3.2.0: 7295 please-upgrade-node@^3.2.0:
7271 version "3.2.0" 7296 version "3.2.0"
7272 resolved "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" 7297 resolved "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942"
@@ -8799,6 +8824,18 @@ stylus-lookup@^3.0.1: @@ -8799,6 +8824,18 @@ stylus-lookup@^3.0.1:
8799 commander "^2.8.1" 8824 commander "^2.8.1"
8800 debug "^4.1.0" 8825 debug "^4.1.0"
8801 8826
  8827 +sucrase@^3.17.1:
  8828 + version "3.17.1"
  8829 + resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.17.1.tgz#b5e35ca7d99db2cc82b3e942934c3746b41ff8e2"
  8830 + integrity sha512-04cNLFAhS4NBG2Z/MTkLY6HdoBsqErv3wCncymFlfFtnpMthurlWYML2RlID4M2BbiJSu1eZdQnE8Lcz4PCe2g==
  8831 + dependencies:
  8832 + commander "^4.0.0"
  8833 + glob "7.1.6"
  8834 + lines-and-columns "^1.1.6"
  8835 + mz "^2.7.0"
  8836 + pirates "^4.0.1"
  8837 + ts-interface-checker "^0.1.9"
  8838 +
8802 sugarss@^2.0.0: 8839 sugarss@^2.0.0:
8803 version "2.0.0" 8840 version "2.0.0"
8804 resolved "https://registry.npmjs.org/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d" 8841 resolved "https://registry.npmjs.org/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d"
@@ -9053,6 +9090,20 @@ text-table@^0.2.0: @@ -9053,6 +9090,20 @@ text-table@^0.2.0:
9053 resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" 9090 resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
9054 integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= 9091 integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
9055 9092
  9093 +thenify-all@^1.0.0:
  9094 + version "1.6.0"
  9095 + resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
  9096 + integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=
  9097 + dependencies:
  9098 + thenify ">= 3.1.0 < 4"
  9099 +
  9100 +"thenify@>= 3.1.0 < 4":
  9101 + version "3.3.1"
  9102 + resolved "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f"
  9103 + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==
  9104 + dependencies:
  9105 + any-promise "^1.0.0"
  9106 +
9056 through2@^2.0.0, through2@^2.0.2: 9107 through2@^2.0.0, through2@^2.0.2:
9057 version "2.0.5" 9108 version "2.0.5"
9058 resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" 9109 resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
@@ -9171,6 +9222,11 @@ trough@^1.0.0: @@ -9171,6 +9222,11 @@ trough@^1.0.0:
9171 resolved "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" 9222 resolved "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406"
9172 integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== 9223 integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==
9173 9224
  9225 +ts-interface-checker@^0.1.9:
  9226 + version "0.1.13"
  9227 + resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699"
  9228 + integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
  9229 +
9174 ts-node@^9.1.1: 9230 ts-node@^9.1.1:
9175 version "9.1.1" 9231 version "9.1.1"
9176 resolved "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d" 9232 resolved "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d"
@@ -9626,13 +9682,13 @@ vite-plugin-theme@^0.4.8: @@ -9626,13 +9682,13 @@ vite-plugin-theme@^0.4.8:
9626 es-module-lexer "^0.3.26" 9682 es-module-lexer "^0.3.26"
9627 tinycolor2 "^1.4.2" 9683 tinycolor2 "^1.4.2"
9628 9684
9629 -vite-plugin-windicss@0.7.2:  
9630 - version "0.7.2"  
9631 - resolved "https://registry.npmjs.org/vite-plugin-windicss/-/vite-plugin-windicss-0.7.2.tgz#1647ee3765edb0f993b81206f35310a63b25c1f9"  
9632 - integrity sha512-U6N8ljy7meqLkq8aENb3VXKr93Vzp1pU5zwhJr7HmGi+42Wv4i8r7+7BW6WRS4Ght4SAMzFuzIGq9RLPzoZ2Jg== 9685 +vite-plugin-windicss@0.8.2:
  9686 + version "0.8.2"
  9687 + resolved "https://registry.npmjs.org/vite-plugin-windicss/-/vite-plugin-windicss-0.8.2.tgz#cb7a4e03ed218007425be60e54cd4f21cca836d1"
  9688 + integrity sha512-eeHmCAbmeKg1k0r5moPEQrVPFebfsCCGkKUSb8MYWkglLfpcBZfCHyTTdpn/PONy/JcvWrdpbND2/tsy30it3g==
9633 dependencies: 9689 dependencies:
9634 - "@windicss/plugin-utils" "0.7.2"  
9635 - windicss "^2.3.0" 9690 + "@windicss/plugin-utils" "0.8.2"
  9691 + windicss "^2.4.0"
9636 9692
9637 vite@^2.0.5: 9693 vite@^2.0.5:
9638 version "2.0.5" 9694 version "2.0.5"
@@ -9672,10 +9728,10 @@ vue-i18n@^9.0.0: @@ -9672,10 +9728,10 @@ vue-i18n@^9.0.0:
9672 "@intlify/shared" "9.0.0" 9728 "@intlify/shared" "9.0.0"
9673 "@vue/devtools-api" "^6.0.0-beta.5" 9729 "@vue/devtools-api" "^6.0.0-beta.5"
9674 9730
9675 -vue-router@^4.0.4:  
9676 - version "4.0.4"  
9677 - resolved "https://registry.npmjs.org/vue-router/-/vue-router-4.0.4.tgz#ad9b4b7bbdad622407b4ff189b1646f48c1e9053"  
9678 - integrity sha512-uN6PDEaYdU9aRO7mU+Dkr1uaY49hV3fucEDG/Vre/Qj8ct3RoJS16vcPrvKVzn69zDDjBV5b9Xw7fZA9r6b/Iw== 9731 +vue-router@^4.0.5:
  9732 + version "4.0.5"
  9733 + resolved "https://registry.npmjs.org/vue-router/-/vue-router-4.0.5.tgz#dd0a4134bc950c37aef64b973e9ee1008428d8fa"
  9734 + integrity sha512-AQq+pllb6FCc7rS6vh4PPcce3XA1jgK3hKNkQ4hXHwoVN7jOeAOMKCnX7XAX3etV9rmN7iNW8iIwgPk95ckBjw==
9679 9735
9680 vue-types@^3.0.0: 9736 vue-types@^3.0.0:
9681 version "3.0.1" 9737 version "3.0.1"
@@ -9771,10 +9827,10 @@ which@^2.0.1: @@ -9771,10 +9827,10 @@ which@^2.0.1:
9771 dependencies: 9827 dependencies:
9772 isexe "^2.0.0" 9828 isexe "^2.0.0"
9773 9829
9774 -windicss@^2.3.0:  
9775 - version "2.3.0"  
9776 - resolved "https://registry.npmjs.org/windicss/-/windicss-2.3.0.tgz#76f10017169df195d95042b7101d2e2586e8ebd1"  
9777 - integrity sha512-OR/ULZmcVhtEJDIFnkz4S4v4efpZ8DuvDtzBwXNgbtiPQIxN0Zhpo59q0rfF0i3tfwjKw2KCQXNxL5E98bMuVA== 9830 +windicss@^2.4.0:
  9831 + version "2.4.0"
  9832 + resolved "https://registry.npmjs.org/windicss/-/windicss-2.4.0.tgz#9aa0108399d5d3925d5ad5860e76c80299de0cab"
  9833 + integrity sha512-EcGkGnZpuoH0r/hNuj4GLheb9Lg3P+s5KOHUZU63zkl6yoMQNAwTvNXai7OjylbXLFDEWii7SAJbwQIFxE56qQ==
9778 9834
9779 wmf@~1.0.1: 9835 wmf@~1.0.1:
9780 version "1.0.2" 9836 version "1.0.2"