diff --git a/Readme.md b/Readme.md index 6e32594..6563594 100644 --- a/Readme.md +++ b/Readme.md @@ -16,7 +16,7 @@ - @bd/core 针对`web components`的核心封装库, 以数据驱动, 可以更方便的开发 wc 组件 -### 开发进度 && 计划 (37/55) +### 开发进度 && 计划 (39/55) - [x] `wc-card` 卡片组件 - [x] `wc-space` 间隔组件 @@ -55,7 +55,7 @@ - [x] `wc-silder` 滑块组件 - [x] `wc-swipe` 轮播图组件 - [x] `wc-breadcrumb` 面包屑组件 -- [ ] `wc-progress` 进度条组件 +- [x] `wc-progress` 进度条组件 - [ ] `wc-tree` 树形菜单组件 - [ ] `wc-uploader` 上传组件 - [x] `wc-notify` 通知组件 @@ -70,7 +70,7 @@ - [ ] `wc-chatbubble` 聊天气泡组件 - [x] `wc-divider` 分割线组件 - [ ] `wc-table` 表格组件 -- [ ] `wc-result` 结果反馈组件 +- [x] `wc-result` 结果反馈组件 - [ ] `wc-empty` 空状态组件 - [x] `wc-sandbox` 代码沙盒组件 diff --git a/src/form/input.js b/src/form/input.js index cb9265d..bc194ea 100644 --- a/src/form/input.js +++ b/src/form/input.js @@ -140,6 +140,7 @@ class Input extends Component { .list { width: 100%; + background: #fff; } &.hide { display: none; diff --git a/src/index.js b/src/index.js index e860cdc..a6a7688 100644 --- a/src/index.js +++ b/src/index.js @@ -21,3 +21,5 @@ import './steps/index.js' import './swipe/index.js' import './tabs/index.js' import './timeline/index.js' +import './result/index.js' +import './progress/index.js' diff --git a/src/progress/index.js b/src/progress/index.js new file mode 100644 index 0000000..82cf453 --- /dev/null +++ b/src/progress/index.js @@ -0,0 +1,310 @@ +/** + * {进度条} + * @author chensbox + * @date 2023/04/28 16:14:10 + */ + +import { css, html, Component, styleMap, svg } from '@bd/core' + +class Progress extends Component { + static props = { + value: { + type: Number, + default: 0, + attribute: false, + observer(val) { + this.value = this.clamp(val) + } + }, + type: { + type: String, + default: 'line' // line/circle/dashboard + }, + 'stroke-width': { + type: Number, + default: 6, + attribute: false + }, + 'text-inside': { + type: Boolean, + default: false, + attribute: true + }, + status: { + type: String, + default: '', // success/exception/warning + attribute: false + }, + color: { + type: String, + default: '', + attribute: false, + observer(val) { + if (val.includes(',')) { + this.#colors = val.split(',') + } else { + this.#colors = val + } + } + }, + width: { + type: Number, + default: 126, + attribute: false + }, + 'show-text': { + type: Boolean, + default: false, + attribute: true + }, + + format: { + type: Function, + default: null, + attribute: false + }, + 'back-color': { + type: String, + default: '#ebeef5', + attribute: false + }, + 'text-color': { + type: String, + default: '#606266', + attribute: false + }, + 'stroke-linecap': { + type: String, + default: 'round', //butt/round/square + attribute: false + } + } + + static styles = [ + css` + :host { + position: relative; + display: inline-block; + } + :host([type='line']) { + width: 100%; + .progress-text { + width: auto; + margin-left: 5px; + display: inline-block; + } + } + .progress-bar { + display: inline-block; + vertical-align: middle; + } + .bar-outer, + .bar-inner { + height: 100%; + border-radius: 999rem; + } + .bar-inner { + transition: 0.6s ease; + transition-property: width, background-color; + .bar-innerText { + margin: 0 5px; + height: 100%; + line-height: 6px; + font-size: 12px; + line-height: 100%; + vertical-align: middle; + text-align: right; + } + } + .progress-text { + display: block; + position: absolute; + width: 100%; + top: 50%; + transform: translateY(-50%); + text-align: center; + } + ` + ] + + #colors + + get relativeStrokeWidth() { + return ((this['stroke-width'] / this.width) * 100).toFixed(1) + } + get radius() { + if (this.type === 'circle' || this.type === 'dashboard') { + return parseInt(50 - parseFloat(this.relativeStrokeWidth) / 2, 10) + } else { + return 0 + } + } + get trackPath() { + const radius = this.radius + const isDashboard = this.type === 'dashboard' + return ` + M 50 50 + m 0 ${isDashboard ? '' : '-'}${radius} + a ${radius} ${radius} 0 1 1 0 ${isDashboard ? '-' : ''}${radius * 2} + a ${radius} ${radius} 0 1 1 0 ${isDashboard ? '' : '-'}${radius * 2} + ` + } + get trailPathStyle() { + return styleMap({ + strokeDasharray: `${this.perimeter * this.rate}px, ${this.perimeter}px`, + strokeDashoffset: this.strokeDashoffset + }) + } + get strokeDashoffset() { + const offset = (-1 * this.perimeter * (1 - this.rate)) / 2 + return `${offset}px` + } + get perimeter() { + return 2 * Math.PI * this.radius + } + get rate() { + return this.type === 'dashboard' ? 0.75 : 1 + } + get stroke() { + let ret + if (this.color) { + ret = this.getCurrentColor(this.value) + } else { + switch (this.status) { + case 'success': + ret = '#13ce66' + break + case 'exception': + ret = '#ff4949' + break + case 'warning': + ret = '#e6a23c' + break + default: + ret = '#20a0ff' + } + } + return ret + } + get circlePathStyle() { + return styleMap({ + strokeDasharray: `${this.perimeter * this.rate * (this.value / 100)}px, ${ + this.perimeter + }px`, + strokeDashoffset: this.strokeDashoffset, + transition: 'stroke-dasharray 0.6s ease 0s, stroke 0.6s ease' + }) + } + get barStyle() { + return styleMap({ + width: this.value + '%', + 'background-color': this.stroke //this.getCurrentColor(this.value) + }) + } + get progressTextSize() { + let size = + this.type === 'line' + ? 12 + this['stroke-width'] * 0.4 + : this.width * 0.111111 + 2 + return size + 'px' + } + + clamp(val) { + return Math.max(0, Math.min(val, 100)) + } + getCurrentColor(value) { + if (!Array.isArray(this.#colors)) { + return this.#colors + } + let length = this.#colors.length + let step = 100 / length + let index = Math.floor(value / step) + + return this.#colors[index >= length ? length - 1 : index] + } + + renderCircle() { + return html` +
+ + + + +
+ ` + } + renderLine() { + let $barInnerText = '' + if (this['text-inside'] && this['show-text']) { + $barInnerText = html` +
+ ${this.value + '%'} +
+ ` + } + + return html` +
+
+
${$barInnerText}
+
+
+ ` + } + render() { + let $outSideText = '' + if (this['show-text'] && !this['text-inside']) { + $outSideText = html` +
+ ${this.value + '%'} +
+ ` + } + + return html` + ${this.type === 'line' ? this.renderLine() : this.renderCircle()} + ${$outSideText} + ` + } +} + +Progress.reg('progress') diff --git a/src/result/index.js b/src/result/index.js new file mode 100644 index 0000000..ffb11e7 --- /dev/null +++ b/src/result/index.js @@ -0,0 +1,135 @@ +/** + * {结果} + * @author chensbox + * @date 2023/04/28 16:14:10 + */ + +import { css, html, Component, styleMap } from '@bd/core' +import '../icon/index.js' + +class Result extends Component { + static props = { + title: { + type: String, + default: '', + attribute: false + }, + 'sub-title': { type: String, default: '' }, + type: { + type: String, + default: 'success' + }, + icon: { + type: String, + default: '' + } + } + + static styles = [ + css` + :host { + position: relative; + display: inline-block; + text-align: center; + } + :host([type='warning']) .icon { + background: #e6a23c; + wc-icon { + transform: translateY(-2px); + } + } + :host([type='error']) .icon { + --size: 24px; + background: #f56c6c; + } + :host([type='info']) .icon { + background: #909399; + } + .result { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + text-align: center; + box-sizing: border-box; + padding: 40px 30px; + } + .icon-wrapper { + display: flex; + align-items: center; + justify-content: center; + } + .icon { + display: flex; + justify-content: center; + align-items: center; + width: 53px; + height: 53px; + border-radius: 50%; + color: #fff; + background: #67c23a; + } + .title { + margin-top: 20px; + } + .sub-title { + margin-top: 10px; + } + .extra { + margin-top: 30px; + } + span { + font-size: 14px; + color: #5e6d82; + line-height: 1.5em; + } + ` + ] + get iconName() { + if (this.icon) { + return this.icon + } + if (this.type === 'success') { + return 'get' + } + if (this.type === 'error') { + return 'close' + } + return this.type + } + mounted() { + console.log(this.subTitle) + } + + render() { + return html` +
+
+ +
+ +
+
+
+ +
+ + ${this.title} + +
+ +
+ + ${this['sub-title']} + +
+ +
+ +
+
+ ` + } +} + +Result.reg('result')