diff --git a/devui/progress/__tests__/progress.spec.ts b/devui/progress/__tests__/progress.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..2ade6e88eff48569605ca7d1531e74b6c998718e --- /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 5fd16814548740f46825910e9cc2b55c361d50bd..0000000000000000000000000000000000000000 --- 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 4acd43fe89c64261ff9d7ca0a127b0dd6b60577f..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..e654ac18825e2c30212a263f54354f87a86ffc1d --- /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 0000000000000000000000000000000000000000..0cd85d7bc37f1ccb862fbf303919d7a76c2af6cd --- /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 1604e378a14d76b7ff3cf53b7c628f5199fae5fb..0f9c88beaa1b032246f7e7fdb3b2869f557e32ad 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/sites/components/progress/index.md b/sites/components/progress/index.md new file mode 100644 index 0000000000000000000000000000000000000000..d42495dfa2922f5f9c5864aa4bff673d7d40b1a2 --- /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 | 可选,设置圈形进度条内是否展示内容 | [圆环用法](#圆环用法) | + + +