Skip to content

Commit d3fbd3a

Browse files
feat: Add count-to demo
feat: Add useWatermark hook and add useWatermark demo
1 parent e4b7a76 commit d3fbd3a

File tree

10 files changed

+432
-7
lines changed

10 files changed

+432
-7
lines changed

src/hooks/web/usePageLoading.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ export const usePageLoading = () => {
88
}
99

1010
const loadDone = () => {
11-
setTimeout(() => {
12-
appStore.setPageLoading(false)
13-
}, 1000)
11+
appStore.setPageLoading(false)
1412
}
1513

1614
return {

src/hooks/web/useWatermark.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
const domSymbol = Symbol('watermark-dom')
2+
3+
export function useWatermark(appendEl: HTMLElement | null = document.body) {
4+
let func: Fn = () => {}
5+
const id = domSymbol.toString()
6+
const clear = () => {
7+
const domId = document.getElementById(id)
8+
if (domId) {
9+
const el = appendEl
10+
el && el.removeChild(domId)
11+
}
12+
window.removeEventListener('resize', func)
13+
}
14+
const createWatermark = (str: string) => {
15+
clear()
16+
17+
const can = document.createElement('canvas')
18+
can.width = 300
19+
can.height = 240
20+
21+
const cans = can.getContext('2d')
22+
if (cans) {
23+
cans.rotate((-20 * Math.PI) / 120)
24+
cans.font = '15px Vedana'
25+
cans.fillStyle = 'rgba(0, 0, 0, 0.15)'
26+
cans.textAlign = 'left'
27+
cans.textBaseline = 'middle'
28+
cans.fillText(str, can.width / 20, can.height)
29+
}
30+
31+
const div = document.createElement('div')
32+
div.id = id
33+
div.style.pointerEvents = 'none'
34+
div.style.top = '0px'
35+
div.style.left = '0px'
36+
div.style.position = 'absolute'
37+
div.style.zIndex = '100000000'
38+
div.style.width = document.documentElement.clientWidth + 'px'
39+
div.style.height = document.documentElement.clientHeight + 'px'
40+
div.style.background = 'url(' + can.toDataURL('image/png') + ') left top repeat'
41+
const el = appendEl
42+
el && el.appendChild(div)
43+
return id
44+
}
45+
46+
function setWatermark(str: string) {
47+
createWatermark(str)
48+
func = () => {
49+
createWatermark(str)
50+
}
51+
window.addEventListener('resize', func)
52+
}
53+
54+
return { setWatermark, clear }
55+
}

src/locales/en.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,10 @@ export default {
8787
workplace: 'Workplace',
8888
guide: 'Guide',
8989
component: 'Component',
90-
icon: 'Icon'
90+
icon: 'Icon',
91+
echart: 'Echart',
92+
countTo: 'Count to',
93+
watermark: 'Watermark'
9194
},
9295
analysis: {
9396
newUser: 'New user',
@@ -203,5 +206,30 @@ export default {
203206
recommendeDes:
204207
'Iconify component basically contains all icons. You can query any icon you want. And packaging will only package the icons used.',
205208
accessAddress: 'Access address'
209+
},
210+
echartDemo: {
211+
echart: 'Echart',
212+
echartDes:
213+
'Based on the secondary packaging components of eckarts, the width is adaptive. The corresponding chart can be displayed by passing in the options and height attributes.'
214+
},
215+
countToDemo: {
216+
countTo: 'CountTo',
217+
countToDes:
218+
'The transformation is based on vue-count-to and supports all vue-count-to parameters.',
219+
suffix: 'Suffix',
220+
prefix: 'Prefix',
221+
separator: 'Separator',
222+
duration: 'Duration',
223+
endVal: 'End val',
224+
startVal: 'Start val',
225+
start: 'Start',
226+
pause: 'Pause',
227+
resume: 'Resume'
228+
},
229+
watermarkDemo: {
230+
watermark: 'Watermark',
231+
createdWatermark: 'Created watermark',
232+
clearWatermark: 'Clear watermark',
233+
resetWatermark: 'Reset watermark'
206234
}
207235
}

src/locales/zh-CN.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,10 @@ export default {
8787
workplace: '工作台',
8888
guide: '引导',
8989
component: '组件',
90-
icon: '图标'
90+
icon: '图标',
91+
echart: '图表',
92+
countTo: '数字动画',
93+
watermark: '水印'
9194
},
9295
analysis: {
9396
newUser: '新增用户',
@@ -203,5 +206,29 @@ export default {
203206
recommendeDes:
204207
'Iconify组件基本包含所有的图标,你可以查询到你想要的任何图标。并且打包只会打包所用到的图标。',
205208
accessAddress: '访问地址'
209+
},
210+
echartDemo: {
211+
echart: '图表',
212+
echartDes:
213+
'基于 echarts 二次封装组件,自适应宽度,只需传入 options 与 height 属性即可展示对应的图表。'
214+
},
215+
countToDemo: {
216+
countTo: '数字动画',
217+
countToDes: '基于 vue-count-to 进行改造,支持所有 vue-count-to 参数。',
218+
suffix: '后缀',
219+
prefix: '前缀',
220+
separator: '分割符号',
221+
duration: '持续时间',
222+
endVal: '结束值',
223+
startVal: '开始值',
224+
start: '开始',
225+
pause: '暂停',
226+
resume: '继续'
227+
},
228+
watermarkDemo: {
229+
watermark: '水印',
230+
createdWatermark: '创建水印',
231+
clearWatermark: '清除水印',
232+
resetWatermark: '重置水印'
206233
}
207234
}

src/router/index.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,30 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
103103
meta: {
104104
title: t('router.icon')
105105
}
106+
},
107+
{
108+
path: 'echart',
109+
component: () => import('@/views/Components/Echart.vue'),
110+
name: 'Echart',
111+
meta: {
112+
title: t('router.echart')
113+
}
114+
},
115+
{
116+
path: 'count-to',
117+
component: () => import('@/views/Components/CountTo.vue'),
118+
name: 'CountTo',
119+
meta: {
120+
title: t('router.countTo')
121+
}
122+
},
123+
{
124+
path: 'watermark',
125+
component: () => import('@/views/Components/Watermark.vue'),
126+
name: 'Watermark',
127+
meta: {
128+
title: t('router.watermark')
129+
}
106130
}
107131
]
108132
},

src/views/Components/CountTo.vue

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<script setup lang="ts">
2+
import { ContentWrap } from '@/components/ContentWrap'
3+
import { useI18n } from '@/hooks/web/useI18n'
4+
import { CountTo } from '@/components/CountTo'
5+
import { ElRow, ElCol, ElInputNumber, ElInput, ElButton } from 'element-plus'
6+
import { ref, unref } from 'vue'
7+
8+
const { t } = useI18n()
9+
10+
const countRef = ref<ComponentRef<typeof CountTo>>()
11+
12+
const startVal = ref(0)
13+
14+
const endVal = ref(1314512)
15+
16+
const duration = ref(3000)
17+
18+
const decimals = ref(0)
19+
20+
const separator = ref(',')
21+
22+
const prefix = ref('¥ ')
23+
24+
const suffix = ref(' rmb')
25+
26+
const autoplay = ref(false)
27+
28+
const start = () => {
29+
unref(countRef)?.start()
30+
}
31+
32+
const pauseResume = () => {
33+
unref(countRef)?.pauseResume()
34+
}
35+
</script>
36+
37+
<template>
38+
<ContentWrap :title="t('countToDemo.countTo')" :message="t('countToDemo.countToDes')">
39+
<div class="text-center mb-40px">
40+
<CountTo
41+
ref="countRef"
42+
:start-val="startVal"
43+
:end-val="endVal"
44+
:duration="duration"
45+
:decimals="decimals"
46+
:separator="separator"
47+
:prefix="prefix"
48+
:suffix="suffix"
49+
:autoplay="autoplay"
50+
class="text-30px font-bold text-[var(--el-color-primary)]"
51+
/>
52+
</div>
53+
<ElRow :gutter="20" justify="space-between">
54+
<ElCol :xl="8" :lg="8" :md="12" :sm="24" :xs="24">
55+
<div class="flex mb-20px items-center">
56+
<span class="min-w-90px text-right">{{ t('countToDemo.startVal') }}:</span>
57+
<ElInputNumber v-model="startVal" :min="0" />
58+
</div>
59+
</ElCol>
60+
<ElCol :xl="8" :lg="8" :md="12" :sm="24" :xs="24">
61+
<div class="flex mb-20px items-center">
62+
<span class="min-w-90px text-right">{{ t('countToDemo.endVal') }}:</span>
63+
<ElInputNumber v-model="endVal" :min="1" />
64+
</div>
65+
</ElCol>
66+
<ElCol :xl="8" :lg="8" :md="12" :sm="24" :xs="24">
67+
<div class="flex mb-20px items-center">
68+
<span class="min-w-90px text-right">{{ t('countToDemo.duration') }}:</span>
69+
<ElInputNumber v-model="duration" :min="1000" />
70+
</div>
71+
</ElCol>
72+
<ElCol :xl="8" :lg="8" :md="12" :sm="24" :xs="24">
73+
<div class="flex mb-20px items-center">
74+
<span class="min-w-90px text-right">{{ t('countToDemo.separator') }}:</span>
75+
<ElInput v-model="separator" />
76+
</div>
77+
</ElCol>
78+
<ElCol :xl="8" :lg="8" :md="12" :sm="24" :xs="24">
79+
<div class="flex mb-20px items-center">
80+
<span class="min-w-90px text-right">{{ t('countToDemo.prefix') }}:</span>
81+
<ElInput v-model="prefix" />
82+
</div>
83+
</ElCol>
84+
<ElCol :xl="8" :lg="8" :md="12" :sm="24" :xs="24">
85+
<div class="flex mb-20px items-center">
86+
<span class="min-w-90px text-right">{{ t('countToDemo.suffix') }}:</span>
87+
<ElInput v-model="suffix" />
88+
</div>
89+
</ElCol>
90+
<ElCol :span="24">
91+
<div class="text-center">
92+
<ElButton type="primary" @click="start">{{ t('countToDemo.start') }}</ElButton>
93+
<ElButton @click="pauseResume">
94+
{{ t('countToDemo.pause') }}/{{ t('countToDemo.resume') }}
95+
</ElButton>
96+
</div>
97+
</ElCol>
98+
</ElRow>
99+
</ContentWrap>
100+
</template>

src/views/Components/Echart.vue

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<script setup lang="ts">
2+
import { ContentWrap } from '@/components/ContentWrap'
3+
import { useI18n } from '@/hooks/web/useI18n'
4+
import { pieOptions, barOptions, lineOptions, wordOptions } from '@/views/Dashboard/echarts-data'
5+
import { Echart } from '@/components/Echart'
6+
import { ElRow, ElCol, ElCard } from 'element-plus'
7+
8+
const { t } = useI18n()
9+
</script>
10+
11+
<template>
12+
<ContentWrap :title="t('echartDemo.echart')" :message="t('echartDemo.echartDes')">
13+
<ElRow :gutter="20" justify="space-between">
14+
<ElCol :xl="10" :lg="10" :md="24" :sm="24" :xs="24">
15+
<ElCard shadow="hover" class="mb-20px">
16+
<Echart :options="pieOptions" :height="300" />
17+
</ElCard>
18+
</ElCol>
19+
<ElCol :xl="14" :lg="14" :md="24" :sm="24" :xs="24">
20+
<ElCard shadow="hover" class="mb-20px">
21+
<Echart :options="barOptions" :height="300" />
22+
</ElCard>
23+
</ElCol>
24+
<ElCol :span="24">
25+
<ElCard shadow="hover" class="mb-20px">
26+
<Echart :options="lineOptions" :height="350" />
27+
</ElCard>
28+
</ElCol>
29+
<ElCol :span="24">
30+
<ElCard shadow="hover" class="mb-20px">
31+
<Echart :options="wordOptions" :height="300" />
32+
</ElCard>
33+
</ElCol>
34+
</ElRow>
35+
</ContentWrap>
36+
</template>

src/views/Components/Watermark.vue

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<script setup lang="ts">
2+
import { ContentWrap } from '@/components/ContentWrap'
3+
import { useI18n } from '@/hooks/web/useI18n'
4+
import { ElButton } from 'element-plus'
5+
import { useWatermark } from '@/hooks/web/useWatermark'
6+
import { computed, onBeforeUnmount } from 'vue'
7+
import { useAppStore } from '@/store/modules/app'
8+
9+
const appStore = useAppStore()
10+
11+
const title = computed(() => appStore.getTitle)
12+
13+
const { setWatermark, clear } = useWatermark()
14+
15+
const { t } = useI18n()
16+
17+
onBeforeUnmount(() => {
18+
clear()
19+
})
20+
</script>
21+
22+
<template>
23+
<ContentWrap :title="t('watermarkDemo.watermark')">
24+
<ElButton type="primary" @click="setWatermark(title)">
25+
{{ t('watermarkDemo.createdWatermark') }}
26+
</ElButton>
27+
<ElButton type="danger" @click="clear">{{ t('watermarkDemo.clearWatermark') }}</ElButton>
28+
<ElButton type="warning" @click="setWatermark(`${title}-new`)">
29+
{{ t('watermarkDemo.resetWatermark') }}
30+
</ElButton>
31+
</ContentWrap>
32+
</template>

src/views/Dashboard/Analysis.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const { t } = useI18n()
1717
1818
const loading = ref(true)
1919
20-
const pieOptionsData = reactive<EChartsOption>(pieOptions)
20+
const pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption
2121
2222
// 用户来源
2323
const getUserAccessSource = async () => {
@@ -100,7 +100,7 @@ getAllApi()
100100
<ElCol :xl="10" :lg="10" :md="24" :sm="24" :xs="24">
101101
<ElCard shadow="hover" class="mb-20px">
102102
<ElSkeleton :loading="loading" animated>
103-
<Echart :options="pieOptions" :height="300" />
103+
<Echart :options="pieOptionsData" :height="300" />
104104
</ElSkeleton>
105105
</ElCard>
106106
</ElCol>

0 commit comments

Comments
 (0)