From e11b5a4538104c07d4e9bfd588a277efb6472cee Mon Sep 17 00:00:00 2001 From: devin974 <1123303669@qq.com> Date: Tue, 10 Aug 2021 12:59:30 +0800 Subject: [PATCH 1/2] fix: progress error --- devui/progress/__tests__/progress.spec.ts | 53 +++++++ devui/progress/demo/progress-demo.tsx | 12 -- devui/progress/demo/progress.route.ts | 15 -- devui/progress/index.ts | 10 ++ devui/progress/progress.scss | 43 ++++++ devui/progress/progress.tsx | 178 +++++++++++++++++++++- devui/vue-devui.ts | 5 +- sites/.vitepress/config/sidebar.ts | 1 + sites/components/progress/index.md | 142 +++++++++++++++++ 9 files changed, 425 insertions(+), 34 deletions(-) create mode 100644 devui/progress/__tests__/progress.spec.ts delete mode 100644 devui/progress/demo/progress-demo.tsx delete mode 100644 devui/progress/demo/progress.route.ts create mode 100644 devui/progress/index.ts create mode 100644 devui/progress/progress.scss create mode 100644 sites/components/progress/index.md diff --git a/devui/progress/__tests__/progress.spec.ts b/devui/progress/__tests__/progress.spec.ts new file mode 100644 index 00000000..2ade6e88 --- /dev/null +++ b/devui/progress/__tests__/progress.spec.ts @@ -0,0 +1,53 @@ +import { mount } from '@vue/test-utils'; +import Progress from '../progress'; + +describe('d-progress', () => { + it('height', () => { + const wrapper = mount(Progress, { + props: { height: '20px' }, + }); + expect(wrapper.props().height).toBe('20px'); + }); + + it('percentage', () => { + const wrapper = mount(Progress, { + props: { percentage: 20 }, + }); + expect(wrapper.props().percentage).toBe(20); + }); + + it('percentageText', () => { + const wrapper = mount(Progress, { + props: { percentageText: '30%' }, + }); + expect(wrapper.props().percentageText).toBe('30%'); + }); + + it('barbgcolor', () => { + const wrapper = mount(Progress, { + props: { barbgcolor: '#5170ff' }, + }); + expect(wrapper.props().barbgcolor).toBe('#5170ff'); + }); + + it('isCircle', () => { + const wrapper = mount(Progress, { + props: { isCircle: false }, + }); + expect(wrapper.props().isCircle).toBe(false); + }); + + it('strokeWidth', () => { + const wrapper = mount(Progress, { + props: { strokeWidth: 6 }, + }); + expect(wrapper.props().strokeWidth).toBe(6); + }); + + it('showContent', () => { + const wrapper = mount(Progress, { + props: { showContent: true }, + }); + expect(wrapper.props().showContent).toBe(true); + }); +}); diff --git a/devui/progress/demo/progress-demo.tsx b/devui/progress/demo/progress-demo.tsx deleted file mode 100644 index 5fd16814..00000000 --- a/devui/progress/demo/progress-demo.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { defineComponent } from 'vue' - -export default defineComponent({ - name: 'd-progress-demo', - props: { - }, - setup(props, ctx) { - return () => { - return
devui-progress-demo
- } - } -}) \ No newline at end of file diff --git a/devui/progress/demo/progress.route.ts b/devui/progress/demo/progress.route.ts deleted file mode 100644 index 4acd43fe..00000000 --- a/devui/progress/demo/progress.route.ts +++ /dev/null @@ -1,15 +0,0 @@ -import ProgressDemoComponent from './progress-demo' -import DevUIApiComponent from '../../shared/devui-api/devui-api' - -import ApiCn from '../doc/api-cn.md' -import ApiEn from '../doc/api-en.md' -const routes = [ - { path: '', redirectTo: 'demo' }, - { path: 'demo', component: ProgressDemoComponent}, - { path: 'api', component: DevUIApiComponent, meta: { - 'zh-cn': ApiCn, - 'en-us': ApiEn - }} -] - -export default routes diff --git a/devui/progress/index.ts b/devui/progress/index.ts new file mode 100644 index 00000000..e654ac18 --- /dev/null +++ b/devui/progress/index.ts @@ -0,0 +1,10 @@ +import { App } from 'vue' +import Progress from './progress' + +Progress.install = function(Vue: App) { + Vue.component(Progress.name, Progress) +}; + +Progress.version = '0.0.1' + +export default Progress diff --git a/devui/progress/progress.scss b/devui/progress/progress.scss new file mode 100644 index 00000000..0cd85d7b --- /dev/null +++ b/devui/progress/progress.scss @@ -0,0 +1,43 @@ +.devui-progress--line { + position: relative; + background: #dfe1e6; + + .devui-progress-bar { + width: 0; + height: 100%; + transition: width 0.6s ease; + background-color: #5e7ce0; + } + + > span { + display: block; + white-space: nowrap; + color: #ffffff; + text-align: center; + position: absolute; + left: 0; + top: 0; + height: 100%; + width: 100%; + font-size: 12px; + line-height: 1.5; + } +} + +.devui-progress-circle { + position: relative; + + .devui-progress-circle-text { + position: absolute; + top: 50%; + left: 50%; + width: 100%; + margin: 0; + padding: 0; + color: #252b3a; + line-height: 1; + white-space: normal; + text-align: center; + transform: translate(-50%, -50%); + } +} diff --git a/devui/progress/progress.tsx b/devui/progress/progress.tsx index 1604e378..207af980 100644 --- a/devui/progress/progress.tsx +++ b/devui/progress/progress.tsx @@ -1,12 +1,180 @@ -import { defineComponent } from 'vue' +import { + defineComponent, + reactive, + toRefs, + watch, +} from 'vue' + +import './progress.scss' + +interface data { + pathString: string + trailPath: any + strokePath: any +} export default defineComponent({ - name: 'd-progress', + name: 'DProgress', props: { + height: { + type: String, + default: '20px', + }, + percentage: { + type: Number, + default: 0, + }, + percentageText: { + type: String, + default: '', + }, + barbgcolor: { + type: String, + default: '#5170ff', + }, + isCircle: { + type: Boolean, + default: false, + }, + strokeWidth: { + type: Number, + default: 6, + }, + showContent: { + type: Boolean, + default: true, + } }, - setup(props, ctx) { - return () => { - return
devui-progress
+ setup(props) { + const { + height, + percentage, + percentageText, + barbgcolor, + isCircle, + strokeWidth, + showContent, + } = toRefs(props); + + const data: data = reactive({ + pathString: '', + trailPath: null, + strokePath: null, + }); + + const setCircleProgress = () => { + if (!isCircle) { + return; + } + + const radius = 50 - strokeWidth.value / 2; + const beginPositionY = -radius; + const endPositionY = radius * -2; + + data.pathString = `M 50,50 m 0,${beginPositionY} + a ${radius},${radius} 0 1 1 0,${-endPositionY} + a ${radius},${radius} 0 1 1 0,${endPositionY}`; + + const len = Math.PI * 2 * radius; + + data.trailPath = { + stroke: '#dfe1e6', + strokeDasharray: `${len}px ${len}px`, + strokeDashoffset: `0`, + transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s' + }; + + data.strokePath = { + stroke: barbgcolor || null, + strokeDasharray: `${(percentage.value / 100) * len }px ${len}px`, + strokeDashoffset: `0`, + transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s' + }; } + + setCircleProgress(); + + watch([height, percentage, percentageText, barbgcolor, isCircle, strokeWidth, showContent], () => { + setCircleProgress(); + }) + + return { + data, + }; + }, + render() { + const { + height, + percentage, + percentageText, + barbgcolor, + isCircle, + strokeWidth, + showContent, + data, + $slots, + } = this; + + const progressLine = ( +
+
+ + {percentageText} + +
+ ); + + const textElement = ( + {percentage}% + ); + + const progressCircle = ( +
+ + + + + {showContent && $slots.default?.()} + {showContent && !$slots.default && textElement} +
+ ); + + return ( +
+ {!isCircle ? progressLine : progressCircle} +
+ ); } }) \ No newline at end of file diff --git a/devui/vue-devui.ts b/devui/vue-devui.ts index 2a0a2d82..572fa95b 100644 --- a/devui/vue-devui.ts +++ b/devui/vue-devui.ts @@ -22,9 +22,10 @@ import TextInput from './text-input'; // 数据展示 import Avatar from './avatar'; import Carousel from './carousel'; +import Progress from './progress'; function install(app: App): void { - const packages = [ Button, Icon, Panel, Tabs, Alert, DLoading, Checkbox, Radio, Switch, TagsInput, TextInput, Avatar, Carousel ]; + const packages = [ Button, Icon, Panel, Tabs, Alert, DLoading, Checkbox, Radio, Switch, TagsInput, TextInput, Avatar, Carousel, Progress ]; packages.forEach((item: any) => { if (item.install) { app.use(item); @@ -34,5 +35,5 @@ function install(app: App): void { }); } -export { Button, Icon, Panel, Tabs, Alert, LoadingService, Loading, Checkbox, Radio, Switch, TagsInput, TextInput, Avatar, Carousel }; +export { Button, Icon, Panel, Tabs, Alert, LoadingService, Loading, Checkbox, Radio, Switch, TagsInput, TextInput, Avatar, Carousel, Progress }; export default { install, version: '0.0.1' }; diff --git a/sites/.vitepress/config/sidebar.ts b/sites/.vitepress/config/sidebar.ts index c49dde11..2662548f 100644 --- a/sites/.vitepress/config/sidebar.ts +++ b/sites/.vitepress/config/sidebar.ts @@ -37,6 +37,7 @@ const sidebar = { children: [ { text: 'Avatar 头像', link: '/components/avatar/' }, { text: 'Carousel 走马灯', link: '/components/carousel/' }, + { text: 'Progress 进度条', link: '/components/progress/' }, ] }, ], diff --git a/sites/components/progress/index.md b/sites/components/progress/index.md new file mode 100644 index 00000000..e6c4a5ef --- /dev/null +++ b/sites/components/progress/index.md @@ -0,0 +1,142 @@ +# Progress 进度条 + +进度条。 + +### 何时使用 +1. 当操作需要较长的时间时,向用户展示操作进度。 +2. 当操作需要打断现有界面或后台运行,需要较长时间时。 +3. 当需要显示一个操作完成的百分比或已完成的步骤/总步骤时。 + +### 基本用法 +基本的进度和文字配置。 + +
+
+ +
+
+ +
+
+ + +```html +
+ +
+
+ +
+``` + +```css +.progress-container { + margin-bottom: 20px; +} +``` + +### 圆环用法 +基本的进度和文字配置。 + +
+
+ +
+
+ + +
+
+ + + +
+
+ + +```html +
+ +
+
+ +
+
+ + + +
+``` + +```css +.progress-container-circle { + height: 130px; + width: 130px; + font-size: 20px; + display: inline-block; + margin-right: 10px; +} + +.icon-position { + position: absolute; + top: 50%; + left: 50%; + width: 100%; + margin: 0; + padding: 0; + line-height: 1; + white-space: normal; + text-align: center; + transform: translate(-50%, -50%); + color: #50d4ab; + font-size: 24px; +} +``` + +### API +#### d-progress 参数 +| 参数 | 类型 | 默认值 | 描述 | 跳转Demo | +| :---: | :---: | :---: | :---: | :---: | +| percentage | `number` | 0 | 可选,进度条的值最大为 100 | [基本用法](#基本用法) | +| percentageText | `string` | -- | 可选,进度条当前值的文字说明比如:'30%' \| '4/5' | [基本用法](#基本用法) | +| barbgcolor | `string` | #5170ff | 可选,进度条的颜色显示,默认为天蓝色 | [基本用法](#基本用法) | +| height | `string` | 20px | 可选,进度条的高度值,默认值为 20px | [基本用法](#基本用法) | +| isCircle | `boolean` | false | 可选, 显示进度条是否为圈形 | [圆环用法](#圆环用法) | +| strokeWidth | `number` | 6 | 可选,设置圈形进度条宽度,单位是进度条与画布宽度的百分比 | [圆环用法](#圆环用法) | +| showContent | `boolean` | true | 可选,设置圈形进度条内是否展示内容 | [圆环用法](#圆环用法) | + + + -- Gitee From bed9875c317d943546ffdf42dd3323b4a707417e Mon Sep 17 00:00:00 2001 From: devin974 <1123303669@qq.com> Date: Wed, 11 Aug 2021 12:02:44 +0800 Subject: [PATCH 2/2] fix: progress api --- devui/progress/progress.tsx | 14 +++++------ devui/vue-devui.ts | 39 ------------------------------ sites/components/progress/index.md | 2 +- 3 files changed, 8 insertions(+), 47 deletions(-) delete mode 100644 devui/vue-devui.ts diff --git a/devui/progress/progress.tsx b/devui/progress/progress.tsx index 207af980..0f9c88be 100644 --- a/devui/progress/progress.tsx +++ b/devui/progress/progress.tsx @@ -28,7 +28,7 @@ export default defineComponent({ type: String, default: '', }, - barbgcolor: { + barBgColor: { type: String, default: '#5170ff', }, @@ -50,7 +50,7 @@ export default defineComponent({ height, percentage, percentageText, - barbgcolor, + barBgColor, isCircle, strokeWidth, showContent, @@ -85,7 +85,7 @@ export default defineComponent({ }; data.strokePath = { - stroke: barbgcolor || null, + stroke: barBgColor || null, strokeDasharray: `${(percentage.value / 100) * len }px ${len}px`, strokeDashoffset: `0`, transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s' @@ -94,7 +94,7 @@ export default defineComponent({ setCircleProgress(); - watch([height, percentage, percentageText, barbgcolor, isCircle, strokeWidth, showContent], () => { + watch([height, percentage, percentageText, barBgColor, isCircle, strokeWidth, showContent], () => { setCircleProgress(); }) @@ -107,7 +107,7 @@ export default defineComponent({ height, percentage, percentageText, - barbgcolor, + barBgColor, isCircle, strokeWidth, showContent, @@ -129,7 +129,7 @@ export default defineComponent({ height: height, borderRadius: height, width: `${percentage}%`, - backgroundColor: barbgcolor, + backgroundColor: barBgColor, }} /> diff --git a/devui/vue-devui.ts b/devui/vue-devui.ts deleted file mode 100644 index 572fa95b..00000000 --- a/devui/vue-devui.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { App } from 'vue'; - -// 通用 -import Button from './button'; -import Icon from './icon'; -import Panel from './panel'; - -// 导航 -import Tabs from './tabs'; - -// 反馈 -import Alert from './alert/alert'; -import DLoading, { LoadingService, Loading } from './loading'; - -// 数据录入 -import Checkbox from './checkbox'; -import Radio from './radio'; -import Switch from './switch'; -import TagsInput from './tags-input'; -import TextInput from './text-input'; - -// 数据展示 -import Avatar from './avatar'; -import Carousel from './carousel'; -import Progress from './progress'; - -function install(app: App): void { - const packages = [ Button, Icon, Panel, Tabs, Alert, DLoading, Checkbox, Radio, Switch, TagsInput, TextInput, Avatar, Carousel, Progress ]; - packages.forEach((item: any) => { - if (item.install) { - app.use(item); - } else if (item.name) { - app.component(item.name, item); - } - }); -} - -export { Button, Icon, Panel, Tabs, Alert, LoadingService, Loading, Checkbox, Radio, Switch, TagsInput, TextInput, Avatar, Carousel, Progress }; -export default { install, version: '0.0.1' }; diff --git a/sites/components/progress/index.md b/sites/components/progress/index.md index e6c4a5ef..d42495df 100644 --- a/sites/components/progress/index.md +++ b/sites/components/progress/index.md @@ -103,7 +103,7 @@ | :---: | :---: | :---: | :---: | :---: | | percentage | `number` | 0 | 可选,进度条的值最大为 100 | [基本用法](#基本用法) | | percentageText | `string` | -- | 可选,进度条当前值的文字说明比如:'30%' \| '4/5' | [基本用法](#基本用法) | -| barbgcolor | `string` | #5170ff | 可选,进度条的颜色显示,默认为天蓝色 | [基本用法](#基本用法) | +| barBgColor | `string` | #5170ff | 可选,进度条的颜色显示,默认为天蓝色 | [基本用法](#基本用法) | | height | `string` | 20px | 可选,进度条的高度值,默认值为 20px | [基本用法](#基本用法) | | isCircle | `boolean` | false | 可选, 显示进度条是否为圈形 | [圆环用法](#圆环用法) | | strokeWidth | `number` | 6 | 可选,设置圈形进度条宽度,单位是进度条与画布宽度的百分比 | [圆环用法](#圆环用法) | -- Gitee