From 3556c1c7c6ea6ae352b614744b5a1b00e8d6af6a Mon Sep 17 00:00:00 2001
From: devin974 <1123303669@qq.com>
Date: Wed, 11 Aug 2021 12:17:01 +0800
Subject: [PATCH] feat: progress
---
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 +++++++++++++++++++++-
sites/components/progress/index.md | 142 +++++++++++++++++
7 files changed, 421 insertions(+), 32 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..0f9c88be 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 00000000..d42495df
--- /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