forked from opentiny/tiny-vue
feat(statistic): statistic component (#1491)
* fix: add new component statistic * fix: add statistic renderless * feat: add statistic theme * feat: add statistic component * fix: update review * fix: update review * fix: update review
This commit is contained in:
parent
772ef20270
commit
ecba505e95
|
@ -0,0 +1,144 @@
|
||||||
|
export default {
|
||||||
|
mode: ['pc'],
|
||||||
|
apis: [
|
||||||
|
{
|
||||||
|
name: 'statistic',
|
||||||
|
type: 'component',
|
||||||
|
props: [
|
||||||
|
{
|
||||||
|
name: 'value',
|
||||||
|
type: 'number',
|
||||||
|
defaultValue: '0',
|
||||||
|
desc: {
|
||||||
|
'zh-CN': '数字显示内容',
|
||||||
|
'en-US': 'Digital display content'
|
||||||
|
},
|
||||||
|
mode: ['pc'],
|
||||||
|
pcDemo: 'basic-usage',
|
||||||
|
mfDemo: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'precision',
|
||||||
|
type: 'number',
|
||||||
|
defaultValue: '0',
|
||||||
|
desc: {
|
||||||
|
'zh-CN': '精度值',
|
||||||
|
'en-US': 'Take precision value'
|
||||||
|
},
|
||||||
|
mode: ['pc'],
|
||||||
|
pcDemo: 'basic-usage',
|
||||||
|
mfDemo: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'title',
|
||||||
|
type: 'string | array',
|
||||||
|
defaultValue: '',
|
||||||
|
desc: {
|
||||||
|
'zh-CN': '设置数字内容标题',
|
||||||
|
'en-US': 'Set digital content titles'
|
||||||
|
},
|
||||||
|
mode: ['pc'],
|
||||||
|
pcDemo: 'basic-usage',
|
||||||
|
mfDemo: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'group-separator',
|
||||||
|
type: 'string',
|
||||||
|
defaultValue: ',',
|
||||||
|
desc: {
|
||||||
|
'zh-CN': '设置千分位标志符',
|
||||||
|
'en-US': 'Set Millennial Flag'
|
||||||
|
},
|
||||||
|
mode: ['pc'],
|
||||||
|
pcDemo: 'basic-usage',
|
||||||
|
mfDemo: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'prefix',
|
||||||
|
type: 'string',
|
||||||
|
defaultValue: '',
|
||||||
|
desc: {
|
||||||
|
'zh-CN': '设置数字内容前缀',
|
||||||
|
'en-US': 'Set numerical content prefix'
|
||||||
|
},
|
||||||
|
mode: ['pc'],
|
||||||
|
pcDemo: 'basic-usage',
|
||||||
|
mfDemo: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'suffix',
|
||||||
|
type: 'string',
|
||||||
|
defaultValue: '',
|
||||||
|
desc: {
|
||||||
|
'zh-CN': '设置数字内容后缀',
|
||||||
|
'en-US': 'Set numeric content suffix'
|
||||||
|
},
|
||||||
|
mode: ['pc'],
|
||||||
|
pcDemo: 'basic-usage',
|
||||||
|
mfDemo: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'formatter',
|
||||||
|
type: '(value) => {}',
|
||||||
|
defaultValue: '',
|
||||||
|
desc: {
|
||||||
|
'zh-CN': '设置自定义数字格式化',
|
||||||
|
'en-US': 'Set custom number formatting'
|
||||||
|
},
|
||||||
|
mode: ['pc'],
|
||||||
|
pcDemo: 'basic-usage',
|
||||||
|
mfDemo: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'value-style',
|
||||||
|
type: 'string | object | array',
|
||||||
|
defaultValue: '',
|
||||||
|
desc: {
|
||||||
|
'zh-CN': '设置数字样式',
|
||||||
|
'en-US': 'Set Number Style'
|
||||||
|
},
|
||||||
|
mode: ['pc'],
|
||||||
|
pcDemo: 'basic-usage',
|
||||||
|
mfDemo: ''
|
||||||
|
}
|
||||||
|
],
|
||||||
|
events: [],
|
||||||
|
methods: [],
|
||||||
|
slots: [
|
||||||
|
{
|
||||||
|
name: 'prefix',
|
||||||
|
type: '',
|
||||||
|
defaultValue: '',
|
||||||
|
desc: {
|
||||||
|
'zh-CN': '数字内容前置插槽',
|
||||||
|
'en-US': 'Digital content front slot'
|
||||||
|
},
|
||||||
|
mode: ['pc'],
|
||||||
|
mfDemo: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'suffix',
|
||||||
|
type: '',
|
||||||
|
defaultValue: '',
|
||||||
|
desc: {
|
||||||
|
'zh-CN': '数字内容后置插槽',
|
||||||
|
'en-US': 'Digital content rear slot'
|
||||||
|
},
|
||||||
|
mode: ['pc'],
|
||||||
|
mfDemo: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'title',
|
||||||
|
type: '',
|
||||||
|
defaultValue: '',
|
||||||
|
desc: {
|
||||||
|
'zh-CN': '数字内容标题插槽',
|
||||||
|
'en-US': 'Digital content title slot'
|
||||||
|
},
|
||||||
|
mode: ['pc'],
|
||||||
|
mfDemo: ''
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<tiny-layout>
|
||||||
|
<tiny-row :flex="true" class="row-bg">
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="num" :precision="0" title="用户活跃度"></tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="num" :precision="2" title="消费额度"></tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="num" :precision="0" title="来访数量" prefix="view:"></tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="123" :precision="0" title="男女占比例" suffix="/100"></tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
</tiny-row>
|
||||||
|
</tiny-layout>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="jsx">
|
||||||
|
import { Statistic as TinyStatistic, Layout as TinyLayout, Row as TinyRow, Col as TinyCol } from '@opentiny/vue'
|
||||||
|
|
||||||
|
const num = 306526.23
|
||||||
|
</script>
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { test, expect } from '@playwright/test'
|
||||||
|
|
||||||
|
test('基本用法', async ({ page }) => {
|
||||||
|
page.on('pageerror', (exception) => expect(exception).toBeNull())
|
||||||
|
await page.goto('statistic#basic-usage')
|
||||||
|
await page
|
||||||
|
.locator('div')
|
||||||
|
.filter({ hasText: /123\/100$/ })
|
||||||
|
.first()
|
||||||
|
.click()
|
||||||
|
await page
|
||||||
|
.locator('div')
|
||||||
|
.filter({ hasText: /^基本用法$/ })
|
||||||
|
.first()
|
||||||
|
.click()
|
||||||
|
await page
|
||||||
|
.locator('div')
|
||||||
|
.filter({ hasText: /^306,526\.23$/ })
|
||||||
|
.click()
|
||||||
|
})
|
|
@ -0,0 +1,38 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<tiny-layout>
|
||||||
|
<tiny-row :flex="true" class="row-bg">
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="num" :precision="0" title="用户活跃度"></tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="num" :precision="2" title="消费额度"></tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="num" :precision="0" title="来访数量" prefix="view:"></tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="123" :precision="0" title="男女占比例" suffix="/100"></tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
</tiny-row>
|
||||||
|
</tiny-layout>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Statistic, Layout, Row, Col } from '@opentiny/vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
TinyStatistic: Statistic,
|
||||||
|
TinyLayout: Layout,
|
||||||
|
TinyRow: Row,
|
||||||
|
TinyCol: Col
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
num: 306526.23
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<tiny-layout>
|
||||||
|
<tiny-row :flex="true" class="row-bg">
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="10010258" :precision="0">
|
||||||
|
<template #title> 活跃度 </template>
|
||||||
|
</tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="num" :precision="2" :title="msg"> </tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="num" :precision="2" :title="money">
|
||||||
|
<template #title:data="{ scoped }">{{ scoped }}</template>
|
||||||
|
</tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="num" :precision="0" title="点赞数量">
|
||||||
|
<template #prefix> Like:</template>
|
||||||
|
</tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="600" :precision="0" title="队伍比分">
|
||||||
|
<template #suffix>/220</template>
|
||||||
|
</tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
</tiny-row>
|
||||||
|
</tiny-layout>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="jsx">
|
||||||
|
import { Statistic as TinyStatistic, Layout as TinyLayout, Row as TinyRow, Col as TinyCol } from '@opentiny/vue'
|
||||||
|
|
||||||
|
const num = 306526.23
|
||||||
|
const msg = { value: '额度' }
|
||||||
|
const money = { value: '存款' }
|
||||||
|
</script>
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { test, expect } from '@playwright/test'
|
||||||
|
|
||||||
|
test('插槽用法', async ({ page }) => {
|
||||||
|
page.on('pageerror', (exception) => expect(exception).toBeNull())
|
||||||
|
await page.goto('statistic#statistic-slot')
|
||||||
|
await page.locator('div').filter({ hasText: /^10,010,258$/ })
|
||||||
|
await page
|
||||||
|
.locator('div')
|
||||||
|
.filter({ hasText: /^306,526\.23$/ })
|
||||||
|
.first()
|
||||||
|
await page.getByText('Like:306,526').click()
|
||||||
|
await page.getByText('600/').click()
|
||||||
|
})
|
|
@ -0,0 +1,51 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<tiny-layout>
|
||||||
|
<tiny-row :flex="true" class="row-bg">
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="10010258" :precision="0">
|
||||||
|
<template #title> 活跃度 </template>
|
||||||
|
</tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="num" :precision="2" :title="msg"> </tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="num" :precision="2" :title="money">
|
||||||
|
<template #title:data="{ scoped }">{{ scoped }}</template>
|
||||||
|
</tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="num" :precision="0" title="点赞数量">
|
||||||
|
<template #prefix> Like:</template>
|
||||||
|
</tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="3">
|
||||||
|
<tiny-statistic :value="600" :precision="0" title="队伍比分">
|
||||||
|
<template #suffix>/220</template>
|
||||||
|
</tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
</tiny-row>
|
||||||
|
</tiny-layout>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Statistic, Layout, Row, Col } from '@opentiny/vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
TinyStatistic: Statistic,
|
||||||
|
TinyLayout: Layout,
|
||||||
|
TinyRow: Row,
|
||||||
|
TinyCol: Col
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
num: 306526.23,
|
||||||
|
msg: { value: '额度' },
|
||||||
|
money: { value: '存款' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,29 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<tiny-layout>
|
||||||
|
<tiny-row :flex="true" class="row-bg">
|
||||||
|
<tiny-col :span="6">
|
||||||
|
<tiny-statistic :value="num" :value-style="{ color: '#b12220' }" :precision="0" title="点赞数量">
|
||||||
|
<template #prefix> Like:</template>
|
||||||
|
</tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="6">
|
||||||
|
<tiny-statistic :value="num" :value-style="{ 'color': '#3ac295' }" :precision="0" title="点赞数量">
|
||||||
|
<template #prefix> Like:</template>
|
||||||
|
</tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="6">
|
||||||
|
<tiny-statistic :value="num" :value-style="[{ 'color': '#e37d29' }]" :precision="0" title="点赞数量">
|
||||||
|
<template #prefix> Like:</template>
|
||||||
|
</tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
</tiny-row>
|
||||||
|
</tiny-layout>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="jsx">
|
||||||
|
import { Statistic as TinyStatistic, Layout as TinyLayout, Row as TinyRow, Col as TinyCol } from '@opentiny/vue'
|
||||||
|
|
||||||
|
const num = 306526.23
|
||||||
|
</script>
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { test, expect } from '@playwright/test'
|
||||||
|
|
||||||
|
test('样式用法', async ({ page }) => {
|
||||||
|
page.on('pageerror', (exception) => expect(exception).toBeNull())
|
||||||
|
await page.goto('statistic#statistic-style')
|
||||||
|
await expect(page.getByText('Like:306,526').first()).toHaveClass(/tiny-statistic__slots/)
|
||||||
|
})
|
|
@ -0,0 +1,41 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<tiny-layout>
|
||||||
|
<tiny-row :flex="true" class="row-bg">
|
||||||
|
<tiny-col :span="6">
|
||||||
|
<tiny-statistic :value="num" :value-style="{ color: '#b12220' }" :precision="0" title="点赞数量">
|
||||||
|
<template #prefix> Like:</template>
|
||||||
|
</tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="6">
|
||||||
|
<tiny-statistic :value="num" :value-style="{ 'color': '#3ac295' }" :precision="0" title="点赞数量">
|
||||||
|
<template #prefix> Like:</template>
|
||||||
|
</tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
<tiny-col :span="6">
|
||||||
|
<tiny-statistic :value="num" :value-style="[{ 'color': '#e37d29' }]" :precision="0" title="点赞数量">
|
||||||
|
<template #prefix> Like:</template>
|
||||||
|
</tiny-statistic>
|
||||||
|
</tiny-col>
|
||||||
|
</tiny-row>
|
||||||
|
</tiny-layout>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Statistic, Layout, Row, Col } from '@opentiny/vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
TinyStatistic: Statistic,
|
||||||
|
TinyLayout: Layout,
|
||||||
|
TinyRow: Row,
|
||||||
|
TinyCol: Col
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
num: 306526.23
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
title: Statistic 统计组件
|
||||||
|
---
|
||||||
|
|
||||||
|
# Statistic 统计组件
|
||||||
|
|
||||||
|
显示统计。
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
title: Statistics component
|
||||||
|
---
|
||||||
|
|
||||||
|
# Statistics component
|
||||||
|
|
||||||
|
Display statistical data.
|
|
@ -0,0 +1,46 @@
|
||||||
|
export default {
|
||||||
|
column: '2',
|
||||||
|
owner: '',
|
||||||
|
demos: [
|
||||||
|
{
|
||||||
|
demoId: 'basic-usage',
|
||||||
|
name: {
|
||||||
|
'zh-CN': '基本用法',
|
||||||
|
'en-US': 'Basic Usage'
|
||||||
|
},
|
||||||
|
desc: {
|
||||||
|
'zh-CN':
|
||||||
|
'通过<code>value</code>设置数字内容,<code>precision</code>设置数字精度值,<code>title</code>设置数字内容标题,<code>prefix</code>设置数字内容前置插槽,<code>suffix</code>设置数字内容后置插槽。',
|
||||||
|
'en-US':
|
||||||
|
'Set digital content through<code>value</code>,<code>precision</code>set digital precision value,<code>title</code>set digital content title,<code>prefix</code>set digital content front slot, and<code>suffix</code>set digital content rear slot.'
|
||||||
|
},
|
||||||
|
codeFiles: ['basic-usage.vue']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
demoId: 'statistic-slot',
|
||||||
|
name: {
|
||||||
|
'zh-CN': '插槽用法',
|
||||||
|
'en-US': 'Slot Usage'
|
||||||
|
},
|
||||||
|
desc: {
|
||||||
|
'zh-CN':
|
||||||
|
'通过<code>title</code>设置标题插槽,<code>prefix</code>设置数字前缀插槽,<code>suffix</code>设置数字后缀插槽。',
|
||||||
|
'en-US':
|
||||||
|
'Set the title slot through<code>title</code>, set the number prefix slot through<code>prefix</code>, and set the number suffix slot through<code>suffix</code>.'
|
||||||
|
},
|
||||||
|
codeFiles: ['statistic-slot.vue']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
demoId: 'statistic-style',
|
||||||
|
name: {
|
||||||
|
'zh-CN': '样式用法',
|
||||||
|
'en-US': 'Style Usage'
|
||||||
|
},
|
||||||
|
desc: {
|
||||||
|
'zh-CN': '通过<code>value-style</code>设置数字样式。',
|
||||||
|
'en-US': 'Set the number style through<code>value style</code>.'
|
||||||
|
},
|
||||||
|
codeFiles: ['statistic-style.vue']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -211,7 +211,8 @@ export const cmpMenus = [
|
||||||
{ 'nameCn': '树形控件', 'name': 'Tree', 'key': 'tree' },
|
{ 'nameCn': '树形控件', 'name': 'Tree', 'key': 'tree' },
|
||||||
{ 'nameCn': '穿梭框', 'name': 'Transfer', 'key': 'transfer' },
|
{ 'nameCn': '穿梭框', 'name': 'Transfer', 'key': 'transfer' },
|
||||||
{ 'nameCn': '无限滚动', 'name': 'InfiniteScroll', 'key': 'infinite-scroll' },
|
{ 'nameCn': '无限滚动', 'name': 'InfiniteScroll', 'key': 'infinite-scroll' },
|
||||||
{ 'nameCn': '骨架屏', 'name': 'Skeleton', 'key': 'skeleton' }
|
{ 'nameCn': '骨架屏', 'name': 'Skeleton', 'key': 'skeleton' },
|
||||||
|
{ 'nameCn': '统计', 'name': 'Statistic', 'key': 'statistic' }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,7 +26,8 @@ const noSaasComponents = [
|
||||||
'TopBox',
|
'TopBox',
|
||||||
'Watermark',
|
'Watermark',
|
||||||
'Wheel',
|
'Wheel',
|
||||||
'Skeleton'
|
'Skeleton',
|
||||||
|
'Statistic'
|
||||||
]
|
]
|
||||||
|
|
||||||
// mobile-first上所有分类,pc上都有,因此可以用pc端menu分类进行合并
|
// mobile-first上所有分类,pc上都有,因此可以用pc端menu分类进行合并
|
||||||
|
|
|
@ -2583,6 +2583,19 @@
|
||||||
"type": "template",
|
"type": "template",
|
||||||
"exclude": false
|
"exclude": false
|
||||||
},
|
},
|
||||||
|
"Statistic": {
|
||||||
|
"path": "vue/src/statistic/index.ts",
|
||||||
|
"type": "component",
|
||||||
|
"exclude": false,
|
||||||
|
"mode": [
|
||||||
|
"pc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"StatisticPc": {
|
||||||
|
"path": "vue/src/statistic/src/pc.vue",
|
||||||
|
"type": "template",
|
||||||
|
"exclude": false
|
||||||
|
},
|
||||||
"SlideBar": {
|
"SlideBar": {
|
||||||
"path": "vue/src/slide-bar/index.ts",
|
"path": "vue/src/slide-bar/index.ts",
|
||||||
"type": "component",
|
"type": "component",
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { isFunction } from '../common/type'
|
||||||
|
|
||||||
|
export const isNumber =
|
||||||
|
({ props }) =>
|
||||||
|
() => {
|
||||||
|
return typeof props.value === 'number'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getIntegerAndDecimal =
|
||||||
|
({ props }) =>
|
||||||
|
() => {
|
||||||
|
if (isFunction(props.formatter)) {
|
||||||
|
return props.formatter(props.value)
|
||||||
|
}
|
||||||
|
if (!isNumber(props.value)) {
|
||||||
|
return props.value
|
||||||
|
}
|
||||||
|
let displayValue = props.value ? String(props.value).split('.') : ''
|
||||||
|
let integer = displayValue[0]?.replace(/\B(?=(\d{3})+(?!\d))/g, props.groupSeparator)
|
||||||
|
let decimal = displayValue[1]?.padEnd(props.precision, '0').slice(0, props.precision > 0 ? props.precision : 0)
|
||||||
|
return [integer, decimal].join(decimal ? '.' : '')
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { getIntegerAndDecimal } from './index'
|
||||||
|
import type { IStatisticApi, IStatisticState } from '@/types'
|
||||||
|
|
||||||
|
export const api = ['state', 'getIntegerAndDecimal']
|
||||||
|
|
||||||
|
export const renderless = (props, hooks): IStatisticApi => {
|
||||||
|
const api: IStatisticApi = {
|
||||||
|
getIntegerAndDecimal: getIntegerAndDecimal({ props })
|
||||||
|
}
|
||||||
|
const { reactive, computed } = hooks
|
||||||
|
|
||||||
|
const state: IStatisticState = reactive({
|
||||||
|
value: computed(() => api.getIntegerAndDecimal(props))
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.assign(api, {
|
||||||
|
state
|
||||||
|
})
|
||||||
|
|
||||||
|
return api
|
||||||
|
}
|
|
@ -157,6 +157,7 @@ export * from './selected-box.type'
|
||||||
export * from './shared.type'
|
export * from './shared.type'
|
||||||
export * from './skeleton.type'
|
export * from './skeleton.type'
|
||||||
export * from './skeleton-item.type'
|
export * from './skeleton-item.type'
|
||||||
|
export * from './statistic.type'
|
||||||
export * from './slide-bar.type'
|
export * from './slide-bar.type'
|
||||||
export * from './slider.type'
|
export * from './slider.type'
|
||||||
export * from './slider-button.type'
|
export * from './slider-button.type'
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import type { ExtractPropTypes } from 'vue'
|
||||||
|
import type { statisticProps, $constants } from '@/statistic/src'
|
||||||
|
import type { ISharedRenderlessFunctionParams } from './shared.type'
|
||||||
|
|
||||||
|
export type IStatisticProps = ExtractPropTypes<typeof statisticProps>
|
||||||
|
|
||||||
|
export type IStatisticConstants = typeof $constants
|
||||||
|
|
||||||
|
export interface IStatisticState {
|
||||||
|
getIntegerAndDecimal: number | string
|
||||||
|
}
|
||||||
|
export interface IStatisticApi {
|
||||||
|
getIntegerAndDecimal: (value: string | number) => string | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IStatisticPcRenderlessParams = ISharedRenderlessFunctionParams<never> & {
|
||||||
|
state: IStatisticState
|
||||||
|
props: IStatisticProps
|
||||||
|
api: IStatisticApi
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
@import '../custom.less';
|
||||||
|
@import './vars.less';
|
||||||
|
|
||||||
|
@statistic-item-prefix-cls: ~'@{css-prefix}statistic';
|
||||||
|
|
||||||
|
.@{statistic-item-prefix-cls} {
|
||||||
|
.component-css-vars-statistic();
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
font-size: var(--ti-statistic-font-size);
|
||||||
|
color: var(--ti-statistic-font-color);
|
||||||
|
font-weight: var(--ti-statistic-title-font-weight);
|
||||||
|
line-height: var(--ti-statistic-title-line-height);
|
||||||
|
margin-bottom: var(--ti-statistic-title-margin-bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__footer-title {
|
||||||
|
margin-top: var(--ti-statistic-title-margin-bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__slots {
|
||||||
|
font-weight: var(--ti-statistic-font-weight);
|
||||||
|
font-size: var(--ti-statistic-font-size);
|
||||||
|
color: var(--ti-statistic-font-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__prefix {
|
||||||
|
margin-right: var(--ti-statistic-prefix-margin-right);
|
||||||
|
font-weight: var(--ti-statistic-prefix-font-weight);
|
||||||
|
display: inline-block;
|
||||||
|
font-size: var(--ti-statistic-prefix-font-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__description {
|
||||||
|
font-size: var(--ti-statistic-description-font-size);
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__suffix {
|
||||||
|
font-size: var(--ti-statistic-suffix-font-size);
|
||||||
|
margin-left: var(--ti-statistic-suffix-margin-left);
|
||||||
|
font-weight: var(--ti-statistic-suffix-font-weight);
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
export const tinyStatisticSmbTheme = {
|
||||||
|
'ti-statistic-font-size': '24px',
|
||||||
|
'ti-statistic-prefix-font-size': '24px',
|
||||||
|
'ti-statistic-font-color': '#191919',
|
||||||
|
'ti-statistic-suffix-font-size': 'var(--ti-common-font-size-4)'
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
.component-css-vars-statistic() {
|
||||||
|
// 标题字体大小
|
||||||
|
--ti-statistic-font-size: var(--ti-common-font-size-base);
|
||||||
|
// 标题字体颜色
|
||||||
|
--ti-statistic-font-color: var(--ti-common-color-text-weaken);
|
||||||
|
// 标题字体粗细
|
||||||
|
--ti-statistic-title-font-weight: var(--ti-common-font-weight-5);
|
||||||
|
// 标题下间距
|
||||||
|
--ti-statistic-title-margin-bottom: var(--ti-common-space-base);
|
||||||
|
// 标题行高
|
||||||
|
--ti-statistic-title-line-height: var(ti-common-line-height-4);
|
||||||
|
// 前缀插槽字体粗细
|
||||||
|
--ti-statistic-font-weight: var(--ti-common-font-weight-5);
|
||||||
|
// 前缀缀插槽间距值
|
||||||
|
--ti-statistic-prefix-margin-right: var(--ti-common-space-6);
|
||||||
|
// 前缀字体大小
|
||||||
|
--ti-statistic-prefix-font-size: var(--ti-common-font-size-4);
|
||||||
|
// 前缀字体粗细
|
||||||
|
--ti-statistic-prefix-font-weight: var(--ti-common-font-weight-5);
|
||||||
|
// 后缀插槽间距值
|
||||||
|
--ti-statistic-suffix-margin-left: var(--ti-common-space-6);
|
||||||
|
// 后缀字体大小
|
||||||
|
--ti-statistic-suffix-font-size: var(--ti-common-font-size-4);
|
||||||
|
// 后缀字体粗细
|
||||||
|
--ti-statistic-suffix-font-weight: var(--ti-common-font-weight-5);
|
||||||
|
// 数字内容字体
|
||||||
|
--ti-statistic-description-font-size: var(--ti-common-font-size-4);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
import { describe } from 'vitest'
|
||||||
|
|
||||||
|
describe('PC Mode', () => {})
|
|
@ -0,0 +1,35 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2022 - present TinyVue Authors.
|
||||||
|
* Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license.
|
||||||
|
*
|
||||||
|
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
|
||||||
|
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
import Statistic from './src/index'
|
||||||
|
import '@opentiny/vue-theme/statistic/index.less'
|
||||||
|
import { version } from './package.json'
|
||||||
|
|
||||||
|
Statistic.model = {
|
||||||
|
prop: 'modelValue',
|
||||||
|
event: 'update:modelValue'
|
||||||
|
}
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
|
Statistic.install = function (Vue) {
|
||||||
|
Vue.component(Statistic.name, Statistic)
|
||||||
|
}
|
||||||
|
|
||||||
|
Statistic.version = version
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
|
if (process.env.BUILD_TARGET === 'runtime') {
|
||||||
|
if (typeof window !== 'undefined' && window.Vue) {
|
||||||
|
Statistic.install(window.Vue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Statistic
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"name": "@opentiny/vue-statistic",
|
||||||
|
"version": "3.7.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"module": "index.ts",
|
||||||
|
"sideEffects": false,
|
||||||
|
"type": "module",
|
||||||
|
"devDependencies": {
|
||||||
|
"@opentiny-internal/vue-test-utils": "workspace:*",
|
||||||
|
"vitest": "^0.31.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "pnpm -w build:ui $npm_package_name",
|
||||||
|
"//postversion": "pnpm build"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@opentiny/vue-renderless": "workspace:~",
|
||||||
|
"@opentiny/vue-common": "workspace:~",
|
||||||
|
"@opentiny/vue-layout": "workspace:~",
|
||||||
|
"@opentiny/vue-row": "workspace:~",
|
||||||
|
"@opentiny/vue-col": "workspace:~",
|
||||||
|
"@opentiny/vue-theme": "workspace:~"
|
||||||
|
},
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
import type { PropType } from '@opentiny/vue-common'
|
||||||
|
import { $props, $prefix, $setup, defineComponent } from '@opentiny/vue-common'
|
||||||
|
import template from 'virtual-template?pc'
|
||||||
|
|
||||||
|
export const $constants = {
|
||||||
|
PREFIX: 'tiny-statistic'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const definePropType = <T>(val: any): PropType<T> => val
|
||||||
|
|
||||||
|
export const statisticProps = {
|
||||||
|
...$props,
|
||||||
|
_constants: {
|
||||||
|
type: Object,
|
||||||
|
default: () => $constants
|
||||||
|
},
|
||||||
|
precision: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
formatter: Function,
|
||||||
|
value: {
|
||||||
|
type: definePropType<number | object>([Number, Object]),
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
prefix: String,
|
||||||
|
suffix: String,
|
||||||
|
title: [String, Object],
|
||||||
|
valueStyle: {
|
||||||
|
type: [String, Object, Array]
|
||||||
|
},
|
||||||
|
groupSeparator: {
|
||||||
|
type: String,
|
||||||
|
default: ','
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: $prefix + 'Statistic',
|
||||||
|
props: statisticProps,
|
||||||
|
setup(props, context) {
|
||||||
|
return $setup({ props, context, template })
|
||||||
|
}
|
||||||
|
})
|
|
@ -0,0 +1,51 @@
|
||||||
|
<template>
|
||||||
|
<div class="tiny-statistic">
|
||||||
|
<div class="tiny-statistic__title">
|
||||||
|
<div v-if="title && typeof title === 'string'">
|
||||||
|
{{ title }}
|
||||||
|
</div>
|
||||||
|
<div v-else-if="$slots.title">
|
||||||
|
<slot name="title" :data="title">
|
||||||
|
{{ title }}
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tiny-statistic__slots">
|
||||||
|
<div v-if="$slots.prefix || prefix" class="tiny-statistic__prefix">
|
||||||
|
<slot name="prefix">
|
||||||
|
<span>{{ prefix }}</span>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
<span class="tiny-statistic__description" :style="valueStyle">
|
||||||
|
{{ state.value }}
|
||||||
|
</span>
|
||||||
|
<div v-if="$slots.suffix || suffix" class="tiny-statistic__suffix">
|
||||||
|
<slot name="suffix">
|
||||||
|
<span>{{ suffix }}</span>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="title && title instanceof Object" :class="['tiny-statistic__footer-title', 'tiny-statistic__title']">
|
||||||
|
<div v-if="$slots.title">
|
||||||
|
<slot name="title" :data="title"> </slot>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<span>{{ title.value }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { renderless, api } from '@opentiny/vue-renderless/statistic/vue'
|
||||||
|
import { props, setup, defineComponent } from '@opentiny/vue-common'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {},
|
||||||
|
emits: [],
|
||||||
|
props: [...props, 'formatter', 'precision', 'prefix', 'suffix', 'title', 'value', 'valueStyle', 'groupSeparator'],
|
||||||
|
setup(props, context) {
|
||||||
|
return setup({ props, context, renderless, api })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
Loading…
Reference in New Issue