Commit 0633d9fecd9e36ec2ccca6cf1c35473065246485
0 parents
Exists in
master
初始化
Showing
15 changed files
with
964 additions
and
0 deletions
Show diff stats
| 1 | +++ a/components/amount/index.scss | ||
| @@ -0,0 +1,3 @@ | @@ -0,0 +1,3 @@ | ||
| 1 | +.zui-amount.numerical { | ||
| 2 | + font-family: DINPro-Medium, DIN Alternate, "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif; | ||
| 3 | +} | ||
| 0 | \ No newline at end of file | 4 | \ No newline at end of file |
| 1 | +++ a/components/amount/index.vue | ||
| @@ -0,0 +1,209 @@ | @@ -0,0 +1,209 @@ | ||
| 1 | +<template> | ||
| 2 | + <text class="zui-amount" :class="{ numerical: !isCapital }"> | ||
| 3 | + <slot v-if="$slots.prefix" name="prefix"></slot> | ||
| 4 | + <template v-else-if="prefix"> | ||
| 5 | + {{ prefix }} | ||
| 6 | + </template> | ||
| 7 | + <template v-if="!isCapital"> | ||
| 8 | + {{ Number(value || 0) | doPrecision(precision > 0 ? precision : 0, isRoundUp) | doFormat(hasSeparator, separator) }} | ||
| 9 | + </template> | ||
| 10 | + <template v-else> | ||
| 11 | + {{ Number(value || 0) | doPrecision(4, isRoundUp) | doCapital }} | ||
| 12 | + </template> | ||
| 13 | + </text> | ||
| 14 | +</template> | ||
| 15 | + | ||
| 16 | +<script> | ||
| 17 | +/* istanbul ignore file */ | ||
| 18 | +var formatValueByGapStep = function(step, value, gap, direction, range, isAdd, oldValue) { | ||
| 19 | + var gap = gap || ' '; | ||
| 20 | + var direction = direction || 'right'; | ||
| 21 | + var isAdd = isAdd || 1; | ||
| 22 | + var oldValue = oldValue || 0; | ||
| 23 | + if (value.length == 0) { | ||
| 24 | + return { value: value, range: range }; | ||
| 25 | + } | ||
| 26 | + var arr = value && value.split(''); | ||
| 27 | + var _range = range; | ||
| 28 | + var showValue = ''; | ||
| 29 | + if (direction == 'right') { | ||
| 30 | + for (var j = arr.length - 1, k = 0; j >= 0; j--, k++) { | ||
| 31 | + var m = arr[j]; | ||
| 32 | + showValue = k > 0 && k % step == 0 ? m + gap + showValue : m + '' + showValue; | ||
| 33 | + } | ||
| 34 | + if (isAdd == 1) { | ||
| 35 | + // 在添加的情况下,如果添加前字符串的长度减去新的字符串的长度为2,说明多了一个间隔符,需要调整range | ||
| 36 | + if (oldValue.length - showValue.length == -2) { | ||
| 37 | + _range = range + 1; | ||
| 38 | + } | ||
| 39 | + } else { | ||
| 40 | + // 在删除情况下,如果删除前字符串的长度减去新的字符串的长度为2,说明少了一个间隔符,需要调整range | ||
| 41 | + if (oldValue.length - showValue.length == 2) { | ||
| 42 | + _range = range - 1; | ||
| 43 | + } | ||
| 44 | + // 删除到最开始,range 保持 0 | ||
| 45 | + if (_range <= 0) { | ||
| 46 | + _range = 0; | ||
| 47 | + } | ||
| 48 | + } | ||
| 49 | + } else { | ||
| 50 | + arr.some(function(n, i) { | ||
| 51 | + showValue = i > 0 && i % step == 0 ? showValue + gap + n : showValue + '' + n; | ||
| 52 | + }); | ||
| 53 | + var adapt = range % (step + 1) == 0 ? 1 * isAdd : 0; | ||
| 54 | + _range = typeof range !== 'undefined' ? (range == 0 ? 0 : range + adapt) : showValue.length; | ||
| 55 | + } | ||
| 56 | + return { value: showValue, range: _range }; | ||
| 57 | +}; | ||
| 58 | +var numberCapital = function(number) { | ||
| 59 | + var cnNums = ['\u96f6', '\u58f9', '\u8d30', '\u53c1', '\u8086', '\u4f0d', '\u9646', '\u67d2', '\u634c', '\u7396']; | ||
| 60 | + // 拾 \u62fe 佰 \u4f70 仟 \u4edf | ||
| 61 | + var cnIntRadice = ['', '\u62fe', '\u4f70', '\u4edf']; | ||
| 62 | + // 万 \u4e07 亿 \u4ebf 兆 \u5146 | ||
| 63 | + var cnIntUnits = ['', '\u4e07', '\u4ebf', '兆']; | ||
| 64 | + // 角 \u89d2 分 \u5206 毫 \u6beb 厘 \u5398 | ||
| 65 | + var cnDecUnits = ['\u89d2', '\u5206', '\u6beb', '\u5398']; | ||
| 66 | + var cnInteger = '\u6574'; // 整 \u6574 | ||
| 67 | + var cnIntLast = '\u5143'; // 元 \u5143 | ||
| 68 | + var cnNegative = '\u8d1f'; // 负 | ||
| 69 | + // Maximum number | ||
| 70 | + var maxNum = 999999999999999.9999; | ||
| 71 | + var negative; | ||
| 72 | + // Integral part | ||
| 73 | + var integerNum; | ||
| 74 | + // Decimal part | ||
| 75 | + var decimalNum; | ||
| 76 | + // Capital number | ||
| 77 | + var capitalStr = ''; | ||
| 78 | + var parts; | ||
| 79 | + /* istanbul ignore if */ | ||
| 80 | + if (number == '') { | ||
| 81 | + return ''; | ||
| 82 | + } | ||
| 83 | + number = parseFloat(number); | ||
| 84 | + if (number < 0) { | ||
| 85 | + negative = true; | ||
| 86 | + number = Math.abs(number); | ||
| 87 | + } | ||
| 88 | + /* istanbul ignore if */ | ||
| 89 | + if (number >= maxNum) { | ||
| 90 | + return ''; | ||
| 91 | + } | ||
| 92 | + /* istanbul ignore if */ | ||
| 93 | + if (number == 0) { | ||
| 94 | + capitalStr = cnNums[0] + cnIntLast + cnInteger; | ||
| 95 | + return capitalStr; | ||
| 96 | + } | ||
| 97 | + // Convert to String | ||
| 98 | + number += ''; | ||
| 99 | + if (number.indexOf('.') == -1) { | ||
| 100 | + integerNum = number; | ||
| 101 | + decimalNum = ''; | ||
| 102 | + } else { | ||
| 103 | + parts = number.split('.'); | ||
| 104 | + integerNum = parts[0]; | ||
| 105 | + decimalNum = parts[1].substr(0, 4); | ||
| 106 | + } | ||
| 107 | + // Convert integer part | ||
| 108 | + if (parseInt(integerNum, 10) > 0) { | ||
| 109 | + var zeroCount = 0; | ||
| 110 | + for (var i = 0, IntLen = integerNum.length; i < IntLen; i++) { | ||
| 111 | + var n = integerNum.substr(i, 1); | ||
| 112 | + var p = IntLen - i - 1; | ||
| 113 | + var q = p / 4; | ||
| 114 | + var m = p % 4; | ||
| 115 | + if (n == '0') { | ||
| 116 | + zeroCount++; | ||
| 117 | + } else { | ||
| 118 | + if (zeroCount > 0) { | ||
| 119 | + capitalStr += cnNums[0]; | ||
| 120 | + } | ||
| 121 | + zeroCount = 0; | ||
| 122 | + capitalStr += cnNums[parseInt(n)] + cnIntRadice[m]; | ||
| 123 | + } | ||
| 124 | + if (m == 0 && zeroCount < 4) { | ||
| 125 | + capitalStr += cnIntUnits[q]; | ||
| 126 | + } | ||
| 127 | + } | ||
| 128 | + capitalStr += cnIntLast; | ||
| 129 | + } | ||
| 130 | + // Convert decimal part | ||
| 131 | + if (decimalNum !== '') { | ||
| 132 | + for (var i = 0, decLen = decimalNum.length; i < decLen; i++) { | ||
| 133 | + var n = decimalNum.substr(i, 1); | ||
| 134 | + if (n !== '0') { | ||
| 135 | + capitalStr += cnNums[Number(n)] + cnDecUnits[i]; | ||
| 136 | + } | ||
| 137 | + } | ||
| 138 | + } | ||
| 139 | + /* istanbul ignore if */ | ||
| 140 | + if (capitalStr == '') { | ||
| 141 | + capitalStr += cnNums[0] + cnIntLast + cnInteger; | ||
| 142 | + } else if (decimalNum == '') { | ||
| 143 | + capitalStr += cnInteger; | ||
| 144 | + } | ||
| 145 | + if (negative) { | ||
| 146 | + capitalStr = '' + cnNegative + capitalStr; | ||
| 147 | + } | ||
| 148 | + return capitalStr; | ||
| 149 | +}; | ||
| 150 | +export default { | ||
| 151 | + name: 'zui-amount', | ||
| 152 | + filters: { | ||
| 153 | + doPrecision: function(value, precision, isRoundUp) { | ||
| 154 | + var exponentialForm = Number(value + 'e' + precision); | ||
| 155 | + var rounded = isRoundUp ? Math.round(exponentialForm) : Math.floor(exponentialForm); | ||
| 156 | + return Number(rounded + 'e-' + precision).toFixed(precision); | ||
| 157 | + }, | ||
| 158 | + doFormat: function(value, hasSeparator, separator) { | ||
| 159 | + if (!hasSeparator) { | ||
| 160 | + return value; | ||
| 161 | + } | ||
| 162 | + var numberParts = value.split('.'); | ||
| 163 | + var integerValue = numberParts[0]; | ||
| 164 | + var decimalValue = numberParts[1] || ''; | ||
| 165 | + var sign = ''; | ||
| 166 | + if (integerValue.startsWith('-')) { | ||
| 167 | + integerValue = integerValue.substring(1); | ||
| 168 | + sign = '-'; | ||
| 169 | + } | ||
| 170 | + var formateValue = formatValueByGapStep(3, integerValue, separator, 'right', 0, 1); | ||
| 171 | + return decimalValue ? '' + sign + formateValue.value + '.' + decimalValue : '' + sign + formateValue.value; | ||
| 172 | + }, | ||
| 173 | + doCapital: function(value) { | ||
| 174 | + return numberCapital(value); | ||
| 175 | + } | ||
| 176 | + }, | ||
| 177 | + props: { | ||
| 178 | + value: { | ||
| 179 | + type: [Number, String], | ||
| 180 | + default: 0 | ||
| 181 | + }, | ||
| 182 | + precision: { | ||
| 183 | + type: Number, | ||
| 184 | + default: 2 | ||
| 185 | + }, | ||
| 186 | + isRoundUp: { | ||
| 187 | + type: Boolean, | ||
| 188 | + default: true | ||
| 189 | + }, | ||
| 190 | + hasSeparator: { | ||
| 191 | + type: Boolean, | ||
| 192 | + default: false | ||
| 193 | + }, | ||
| 194 | + separator: { | ||
| 195 | + type: String, | ||
| 196 | + default: ',' | ||
| 197 | + }, | ||
| 198 | + isCapital: { | ||
| 199 | + type: Boolean, | ||
| 200 | + default: false | ||
| 201 | + }, | ||
| 202 | + prefix: String | ||
| 203 | + }, | ||
| 204 | +}; | ||
| 205 | +</script> | ||
| 206 | + | ||
| 207 | +<style lang="scss"> | ||
| 208 | +@import './index.scss'; | ||
| 209 | +</style> |
| 1 | +++ a/components/button/index.scss | ||
| @@ -0,0 +1,69 @@ | @@ -0,0 +1,69 @@ | ||
| 1 | +.zui-button { | ||
| 2 | + color: #323233; | ||
| 3 | + background-color: #fff; | ||
| 4 | + border: 1upx solid $color-border; | ||
| 5 | + padding: $h-gap-md $v-gap-md; | ||
| 6 | + font-size: $font-md; | ||
| 7 | + cursor: pointer; | ||
| 8 | + transition: all 150ms; | ||
| 9 | + display: flex; | ||
| 10 | + align-items: center; | ||
| 11 | + justify-content: center; | ||
| 12 | + border-radius: 10upx; | ||
| 13 | + &.sm { | ||
| 14 | + padding: $h-gap-sm $v-gap-sm; | ||
| 15 | + font-size: $font-sm; | ||
| 16 | + } | ||
| 17 | + &.lg { | ||
| 18 | + padding: $h-gap-lg $v-gap-lg; | ||
| 19 | + font-size: $font-lg; | ||
| 20 | + } | ||
| 21 | + &.active { | ||
| 22 | + background-color: $bg-active; | ||
| 23 | + border-color: $bg-active; | ||
| 24 | + } | ||
| 25 | + &.primary { | ||
| 26 | + background-color: $color-primary; | ||
| 27 | + border-color: $color-primary; | ||
| 28 | + color: #FFF; | ||
| 29 | + &.active { | ||
| 30 | + background-color: darken($color-primary, 3%); | ||
| 31 | + border-color: darken($color-primary, 3%); | ||
| 32 | + } | ||
| 33 | + } | ||
| 34 | + &.secondary { | ||
| 35 | + background-color: lighten($color-primary, 40%); | ||
| 36 | + border-color: lighten($color-primary, 40%); | ||
| 37 | + color: $color-primary; | ||
| 38 | + &.active { | ||
| 39 | + background-color: lighten($color-primary, 30%); | ||
| 40 | + border-color: lighten($color-primary, 30%); | ||
| 41 | + color: darken($color-primary, 3%); | ||
| 42 | + } | ||
| 43 | + } | ||
| 44 | + &.link { | ||
| 45 | + padding: $h-gap-sm $v-gap-sm; | ||
| 46 | + background: inherit; | ||
| 47 | + border: inherit; | ||
| 48 | + color: $color-primary; | ||
| 49 | + &.active { | ||
| 50 | + color: darken($color-primary, 5%); | ||
| 51 | + } | ||
| 52 | + } | ||
| 53 | + &.disabled { | ||
| 54 | + border-color: $bg-disabled; | ||
| 55 | + background-color: $bg-disabled; | ||
| 56 | + color: $color-disabled; | ||
| 57 | + cursor: not-allowed; | ||
| 58 | + &.active { | ||
| 59 | + border-color: $bg-disabled; | ||
| 60 | + background-color: $bg-disabled; | ||
| 61 | + } | ||
| 62 | + } | ||
| 63 | + &.round { | ||
| 64 | + border-radius: 48upx; | ||
| 65 | + } | ||
| 66 | + &.square { | ||
| 67 | + border-radius: 0upx; | ||
| 68 | + } | ||
| 69 | +} | ||
| 0 | \ No newline at end of file | 70 | \ No newline at end of file |
| 1 | +++ a/components/button/index.vue | ||
| @@ -0,0 +1,47 @@ | @@ -0,0 +1,47 @@ | ||
| 1 | +<template> | ||
| 2 | + <view class="zui-button" hover-class="active" :class="classRender" :style="style" @click="onClick"> | ||
| 3 | + <slot></slot> | ||
| 4 | + </view> | ||
| 5 | +</template> | ||
| 6 | + | ||
| 7 | +<script> | ||
| 8 | +export default { | ||
| 9 | + name: 'zui-button', | ||
| 10 | + props: { | ||
| 11 | + type: { | ||
| 12 | + type: String, | ||
| 13 | + default: 'default' | ||
| 14 | + }, | ||
| 15 | + size: { | ||
| 16 | + type: String, | ||
| 17 | + default: 'md' | ||
| 18 | + }, | ||
| 19 | + block: { | ||
| 20 | + type: Boolean, | ||
| 21 | + default: false | ||
| 22 | + }, | ||
| 23 | + round: Boolean, | ||
| 24 | + square: Boolean, | ||
| 25 | + disabled: Boolean, | ||
| 26 | + }, | ||
| 27 | + computed: { | ||
| 28 | + style: function() { | ||
| 29 | + return `display: ${this.block ? '' : 'inline-block'};` ; | ||
| 30 | + }, | ||
| 31 | + classRender: function() { | ||
| 32 | + return [this.size, this.disabled ? 'disabled' : '', this.block ? 'block' : '', this.type, this.round ? 'round' : '', this.square ? 'square' : '']; | ||
| 33 | + } | ||
| 34 | + }, | ||
| 35 | + methods: { | ||
| 36 | + onClick: function() { | ||
| 37 | + if (!this.disabled) { | ||
| 38 | + this.$emit('click'); | ||
| 39 | + } | ||
| 40 | + } | ||
| 41 | + } | ||
| 42 | +} | ||
| 43 | +</script> | ||
| 44 | + | ||
| 45 | +<style lang="scss"> | ||
| 46 | +@import "./index.scss"; | ||
| 47 | +</style> | ||
| 0 | \ No newline at end of file | 48 | \ No newline at end of file |
| 1 | +++ a/components/cell/index.scss | ||
| @@ -0,0 +1,52 @@ | @@ -0,0 +1,52 @@ | ||
| 1 | +.zui-cell { | ||
| 2 | + position: relative; | ||
| 3 | + display: flex; | ||
| 4 | + box-sizing: border-box; | ||
| 5 | + width: 100%; | ||
| 6 | + padding: $h-gap-lg $v-gap-md; | ||
| 7 | + border-bottom: 1upx solid $color-border; | ||
| 8 | + overflow: hidden; | ||
| 9 | + background-color: #fff; | ||
| 10 | + &--clickable { | ||
| 11 | + cursor: pointer; | ||
| 12 | + transition: background-color 150ms; | ||
| 13 | + &.active { | ||
| 14 | + background-color: $bg-active; | ||
| 15 | + } | ||
| 16 | + } | ||
| 17 | + &__left-icon, &__right-icon { | ||
| 18 | + display: flex; | ||
| 19 | + align-items: center; | ||
| 20 | + font-size: 42upx; | ||
| 21 | + } | ||
| 22 | + &__left-icon { | ||
| 23 | + margin-left: $v-gap-sm; | ||
| 24 | + } | ||
| 25 | + &__right-icon { | ||
| 26 | + margin-left: $v-gap-sm; | ||
| 27 | + color: $color-disabled; | ||
| 28 | + } | ||
| 29 | + &__title, &__value { | ||
| 30 | + flex: 1; | ||
| 31 | + display: flex; | ||
| 32 | + } | ||
| 33 | + &__title { | ||
| 34 | + flex-direction: column; | ||
| 35 | + justify-content: center; | ||
| 36 | + } | ||
| 37 | + &__value { | ||
| 38 | + align-items: center; | ||
| 39 | + justify-content: flex-end; | ||
| 40 | + position: relative; | ||
| 41 | + overflow: hidden; | ||
| 42 | + color: $color-minor; | ||
| 43 | + text-align: right; | ||
| 44 | + vertical-align: middle; | ||
| 45 | + word-wrap: break-word; | ||
| 46 | + } | ||
| 47 | + &__label { | ||
| 48 | + padding-top: $h-gap-sm; | ||
| 49 | + color: $color-minor; | ||
| 50 | + font-size: $font-sm; | ||
| 51 | + } | ||
| 52 | +} |
| 1 | +++ a/components/cell/index.vue | ||
| @@ -0,0 +1,72 @@ | @@ -0,0 +1,72 @@ | ||
| 1 | +<template> | ||
| 2 | + <view class="zui-cell" hover-class="active" :class="classRender" @click="onClick"> | ||
| 3 | + <view v-if="$slots.icon || icon" class="zui-cell__left-icon"> | ||
| 4 | + <slot v-if="$slots.icon" name="icon"></slot> | ||
| 5 | + <zui-icon v-else-if="icon" class="zui-cell__left-icon" :name="icon"></zui-icon> | ||
| 6 | + </view> | ||
| 7 | + <view v-if="$slots.title" class="zui-cell__title"> | ||
| 8 | + <slot name="title"></slot> | ||
| 9 | + <view v-if="$slots.label" class="zui-cell__label"> | ||
| 10 | + <slot name="label"></slot> | ||
| 11 | + </view> | ||
| 12 | + <view v-else-if="label" class="zui-cell__label"> | ||
| 13 | + <text>{{ label }}</text> | ||
| 14 | + </view> | ||
| 15 | + </view> | ||
| 16 | + <view v-else-if="title" class="zui-cell__title"> | ||
| 17 | + <text>{{ title }}</text> | ||
| 18 | + <view v-if="$slots.label" class="zui-cell__label"> | ||
| 19 | + <slot name="label"></slot> | ||
| 20 | + </view> | ||
| 21 | + <view v-else-if="label" class="zui-cell__label"> | ||
| 22 | + <text>{{ label }}</text> | ||
| 23 | + </view> | ||
| 24 | + </view> | ||
| 25 | + <view v-if="$slots.default" class="zui-cell__value"> | ||
| 26 | + <slot></slot> | ||
| 27 | + </view> | ||
| 28 | + <view v-else-if="value" class="zui-cell__value">{{ value }}</view> | ||
| 29 | + <view v-if="$slots.right || rightIcon" class="zui-cell__right-icon"> | ||
| 30 | + <slot v-if="$slots.right" name="right"></slot> | ||
| 31 | + <zui-icon v-else-if="rightIcon && isLink" :name="rightIcon"></zui-icon> | ||
| 32 | + </view> | ||
| 33 | + </view> | ||
| 34 | +</template> | ||
| 35 | + | ||
| 36 | +<script> | ||
| 37 | +import ZuiIcon from '@/components/zui/icon'; | ||
| 38 | + | ||
| 39 | +export default { | ||
| 40 | + name: "zui-cell", | ||
| 41 | + components: { | ||
| 42 | + ZuiIcon | ||
| 43 | + }, | ||
| 44 | + props: { | ||
| 45 | + icon: String, | ||
| 46 | + title: String, | ||
| 47 | + value: String, | ||
| 48 | + label: String, | ||
| 49 | + isLink: Boolean, | ||
| 50 | + rightIcon: { | ||
| 51 | + type: String, | ||
| 52 | + default: "enter" | ||
| 53 | + } | ||
| 54 | + }, | ||
| 55 | + computed: { | ||
| 56 | + classRender: function() { | ||
| 57 | + return [this.isLink ? 'zui-cell--clickable' : '']; | ||
| 58 | + } | ||
| 59 | + }, | ||
| 60 | + methods: { | ||
| 61 | + onClick: function() { | ||
| 62 | + if (this.$listeners["click"]) { | ||
| 63 | + this.$emit("click"); | ||
| 64 | + } | ||
| 65 | + } | ||
| 66 | + } | ||
| 67 | +}; | ||
| 68 | +</script> | ||
| 69 | + | ||
| 70 | +<style lang="scss"> | ||
| 71 | +@import "./index.scss"; | ||
| 72 | +</style> | ||
| 0 | \ No newline at end of file | 73 | \ No newline at end of file |
| 1 | +++ a/components/icon/index.scss | ||
| @@ -0,0 +1,31 @@ | @@ -0,0 +1,31 @@ | ||
| 1 | +.zui-icon { | ||
| 2 | + position: relative; | ||
| 3 | + display: inline-block; | ||
| 4 | + text-rendering: auto; | ||
| 5 | + -webkit-font-smoothing: antialiased; | ||
| 6 | +} | ||
| 7 | + | ||
| 8 | +.zui-info { | ||
| 9 | + position: absolute; | ||
| 10 | + top: 0; | ||
| 11 | + right: 0; | ||
| 12 | + box-sizing: border-box; | ||
| 13 | + min-width: 32upx; | ||
| 14 | + padding: 0 4upx; | ||
| 15 | + color: #fff; | ||
| 16 | + font-weight: 500; | ||
| 17 | + font-size: 20upx; | ||
| 18 | + font-family: PingFang SC, Helvetica Neue, Arial, sans-serif; | ||
| 19 | + line-height: 1.5; | ||
| 20 | + text-align: center; | ||
| 21 | + background-color: $color-error; | ||
| 22 | + border: 1upx solid #fff; | ||
| 23 | + border-radius: 1rem; | ||
| 24 | + transform: translate(50%, -50%); | ||
| 25 | + transform-origin: 100%; | ||
| 26 | + &.dot { | ||
| 27 | + height: 24upx; | ||
| 28 | + width: 24upx; | ||
| 29 | + min-width: 24upx !important; | ||
| 30 | + } | ||
| 31 | +} |
| 1 | +++ a/components/icon/index.vue | ||
| @@ -0,0 +1,43 @@ | @@ -0,0 +1,43 @@ | ||
| 1 | +<template> | ||
| 2 | + <view class="zui-icon" :class="classRender" :style="styleRender"> | ||
| 3 | + <view v-if="info || dot" class="zui-info" :class="dot ? 'dot' : ''">{{ dot ? '' : info }}</view> | ||
| 4 | + </view> | ||
| 5 | +</template> | ||
| 6 | + | ||
| 7 | +<script> | ||
| 8 | +export default { | ||
| 9 | + name: 'zui-icon', | ||
| 10 | + props: { | ||
| 11 | + name: { | ||
| 12 | + type: String, | ||
| 13 | + default: '', | ||
| 14 | + }, | ||
| 15 | + fontFamily: { | ||
| 16 | + type: String, | ||
| 17 | + default: 'iconfont', | ||
| 18 | + }, | ||
| 19 | + classPrefix: { | ||
| 20 | + type: String, | ||
| 21 | + default: 'icon-' | ||
| 22 | + }, | ||
| 23 | + size: String, | ||
| 24 | + color: String, | ||
| 25 | + info: [Number, String], | ||
| 26 | + dot: Boolean, | ||
| 27 | + }, | ||
| 28 | + computed: { | ||
| 29 | + classRender: function() { | ||
| 30 | + var fontFamily = this.fontFamily || ''; | ||
| 31 | + var iconClass = this.classPrefix + this.name; | ||
| 32 | + return [fontFamily, iconClass]; | ||
| 33 | + }, | ||
| 34 | + styleRender: function() { | ||
| 35 | + return `${this.size ? `font-size: ${this.size};` : ''} ${this.color ? `color: ${this.color}` : ''};`; | ||
| 36 | + }, | ||
| 37 | + }, | ||
| 38 | +} | ||
| 39 | +</script> | ||
| 40 | + | ||
| 41 | +<style lang="scss"> | ||
| 42 | +@import "./index.scss"; | ||
| 43 | +</style> | ||
| 0 | \ No newline at end of file | 44 | \ No newline at end of file |
| 1 | +++ a/components/loading/index.scss | ||
| @@ -0,0 +1,126 @@ | @@ -0,0 +1,126 @@ | ||
| 1 | +.zui-loading { | ||
| 2 | + color: $color-minor; | ||
| 3 | + display: inline-flex; | ||
| 4 | + align-items: center; | ||
| 5 | + justify-content: center; | ||
| 6 | + &__spinner { | ||
| 7 | + position: relative; | ||
| 8 | + display: inline-block; | ||
| 9 | + width: 50upx; | ||
| 10 | + max-width: 100%; | ||
| 11 | + height: 50upx; | ||
| 12 | + max-height: 100%; | ||
| 13 | + vertical-align: middle; | ||
| 14 | + animation: zui-rotate 0.8s linear infinite; | ||
| 15 | + &--spinner { | ||
| 16 | + animation-timing-function: steps(12); | ||
| 17 | + .zui-loading__dot { | ||
| 18 | + position: absolute; | ||
| 19 | + top: 0; | ||
| 20 | + left: 0; | ||
| 21 | + width: 100%; | ||
| 22 | + height: 100%; | ||
| 23 | + &::before { | ||
| 24 | + display: block; | ||
| 25 | + width: 2upx; | ||
| 26 | + height: 25%; | ||
| 27 | + margin: 0 auto; | ||
| 28 | + background-color: currentColor; | ||
| 29 | + border-radius: 40%; | ||
| 30 | + content: ' '; | ||
| 31 | + } | ||
| 32 | + &:nth-of-type(1) { | ||
| 33 | + transform: rotate(30deg); | ||
| 34 | + opacity: 1; | ||
| 35 | + } | ||
| 36 | + &:nth-of-type(2) { | ||
| 37 | + transform: rotate(60deg); | ||
| 38 | + opacity: 0.9375; | ||
| 39 | + } | ||
| 40 | + &:nth-of-type(3) { | ||
| 41 | + transform: rotate(90deg); | ||
| 42 | + opacity: 0.875; | ||
| 43 | + } | ||
| 44 | + &:nth-of-type(4) { | ||
| 45 | + transform: rotate(120deg); | ||
| 46 | + opacity: 0.8125; | ||
| 47 | + } | ||
| 48 | + &:nth-of-type(5) { | ||
| 49 | + transform: rotate(150deg); | ||
| 50 | + opacity: 0.75; | ||
| 51 | + } | ||
| 52 | + &:nth-of-type(6) { | ||
| 53 | + transform: rotate(180deg); | ||
| 54 | + opacity: 0.6875; | ||
| 55 | + } | ||
| 56 | + &:nth-of-type(7) { | ||
| 57 | + transform: rotate(210deg); | ||
| 58 | + opacity: 0.625; | ||
| 59 | + } | ||
| 60 | + &:nth-of-type(8) { | ||
| 61 | + transform: rotate(240deg); | ||
| 62 | + opacity: 0.5625; | ||
| 63 | + } | ||
| 64 | + &:nth-of-type(9) { | ||
| 65 | + transform: rotate(270deg); | ||
| 66 | + opacity: 0.5; | ||
| 67 | + } | ||
| 68 | + &:nth-of-type(10) { | ||
| 69 | + transform: rotate(300deg); | ||
| 70 | + opacity: 0.4375; | ||
| 71 | + } | ||
| 72 | + &:nth-of-type(11) { | ||
| 73 | + transform: rotate(330deg); | ||
| 74 | + opacity: 0.375; | ||
| 75 | + } | ||
| 76 | + &:nth-of-type(12) { | ||
| 77 | + transform: rotate(360deg); | ||
| 78 | + opacity: 0.3125; | ||
| 79 | + } | ||
| 80 | + } | ||
| 81 | + } | ||
| 82 | + &--circular { | ||
| 83 | + border: 1upx solid transparent; | ||
| 84 | + border-top-color: currentColor; | ||
| 85 | + border-radius: 100%; | ||
| 86 | + } | ||
| 87 | + } | ||
| 88 | + &__text { | ||
| 89 | + margin-left: $v-gap-sm; | ||
| 90 | + color: $color-minor; | ||
| 91 | + font-size: $font-md; | ||
| 92 | + } | ||
| 93 | + &--vertical { | ||
| 94 | + flex-direction: column; | ||
| 95 | + .zui-loading__text { | ||
| 96 | + margin: $h-gap-sm 0 0; | ||
| 97 | + } | ||
| 98 | + } | ||
| 99 | +} | ||
| 100 | + | ||
| 101 | +@keyframes zui-circular { | ||
| 102 | + 0% { | ||
| 103 | + stroke-dasharray: 1, 200; | ||
| 104 | + stroke-dashoffset: 0; | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + 50% { | ||
| 108 | + stroke-dasharray: 90, 150; | ||
| 109 | + stroke-dashoffset: -40; | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + 100% { | ||
| 113 | + stroke-dasharray: 90, 150; | ||
| 114 | + stroke-dashoffset: -120; | ||
| 115 | + } | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | +@keyframes zui-rotate { | ||
| 119 | + from { | ||
| 120 | + transform: rotate(0deg); | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + to { | ||
| 124 | + transform: rotate(360deg); | ||
| 125 | + } | ||
| 126 | +} |
| 1 | +++ a/components/loading/index.vue | ||
| @@ -0,0 +1,57 @@ | @@ -0,0 +1,57 @@ | ||
| 1 | +<template> | ||
| 2 | + <view :class="classRender"> | ||
| 3 | + <view | ||
| 4 | + :class="innerClassRender" | ||
| 5 | + :style="styleRender" | ||
| 6 | + > | ||
| 7 | + <template v-if="type === 'spinner'"> | ||
| 8 | + <view | ||
| 9 | + v-for="index in 12" | ||
| 10 | + :key="index" | ||
| 11 | + class="zui-loading__dot" | ||
| 12 | + /> | ||
| 13 | + </template> | ||
| 14 | + </view> | ||
| 15 | + <view class="zui-loading__text" :style="textSizeRender"> | ||
| 16 | + <slot v-if="$slots.default"></slot> | ||
| 17 | + </view> | ||
| 18 | + </view> | ||
| 19 | +</template> | ||
| 20 | + | ||
| 21 | +<script> | ||
| 22 | +export default { | ||
| 23 | + name: 'zui-loading', | ||
| 24 | + props: { | ||
| 25 | + color: String, | ||
| 26 | + size: { | ||
| 27 | + type: [Number, String], | ||
| 28 | + default: '2rem' | ||
| 29 | + }, | ||
| 30 | + vertical: Boolean, | ||
| 31 | + textSize: [Number, String], | ||
| 32 | + type: { | ||
| 33 | + type: String, | ||
| 34 | + default: 'circular', | ||
| 35 | + }, | ||
| 36 | + }, | ||
| 37 | + computed: { | ||
| 38 | + classRender: function() { | ||
| 39 | + return ['zui-loading', this.type ? `zui-loading--${this.type}` : '', this.vertical ? 'zui-loading--vertical' : '']; | ||
| 40 | + }, | ||
| 41 | + innerClassRender: function() { | ||
| 42 | + return ['zui-loading__spinner', `zui-loading__spinner--${this.type}`]; | ||
| 43 | + }, | ||
| 44 | + styleRender: function() { | ||
| 45 | + const iconSize = typeof this.textSize === 'number' ? this.textSize + 'px' : this.textSize; | ||
| 46 | + return `color: ${this.color}; width: ${iconSize}; height: ${iconSize}`; | ||
| 47 | + }, | ||
| 48 | + textSizeRender: function() { | ||
| 49 | + return `font-size: ${this.textSize}${typeof this.textSize === 'number' ? 'px' : ''};`; | ||
| 50 | + } | ||
| 51 | + } | ||
| 52 | +}; | ||
| 53 | +</script> | ||
| 54 | + | ||
| 55 | +<style lang="scss"> | ||
| 56 | +@import "./index.scss"; | ||
| 57 | +</style> | ||
| 0 | \ No newline at end of file | 58 | \ No newline at end of file |
| 1 | +++ a/components/tag/index.scss | ||
| @@ -0,0 +1,68 @@ | @@ -0,0 +1,68 @@ | ||
| 1 | +.zui-tag { | ||
| 2 | + font-size: $font-sm; | ||
| 3 | + text-align: center; | ||
| 4 | + display: inline-block; | ||
| 5 | + -webkit-user-select: none; | ||
| 6 | + .default { | ||
| 7 | + background: rgba(0,0,0,0); | ||
| 8 | + color: $color-error; | ||
| 9 | + border-color: $color-error; | ||
| 10 | + } | ||
| 11 | + .shape-dot { | ||
| 12 | + border-radius: 50%; | ||
| 13 | + height: 32upx; | ||
| 14 | + width: 32upx; | ||
| 15 | + &.size-tiny { | ||
| 16 | + height: 16upx; | ||
| 17 | + width: 16upx; | ||
| 18 | + } | ||
| 19 | + } | ||
| 20 | + .shape-square { | ||
| 21 | + padding: 0 $v-gap-sm; | ||
| 22 | + border-radius: 0; | ||
| 23 | + } | ||
| 24 | + .shape-fillet { | ||
| 25 | + padding: $h-gap-sm $v-gap-sm; | ||
| 26 | + } | ||
| 27 | + .shape-bubble { | ||
| 28 | + width: 50upx; | ||
| 29 | + padding: 7upx 0; | ||
| 30 | + border-radius: 50%; | ||
| 31 | + border-bottom-left-radius: 0; | ||
| 32 | + box-sizing: border-box; | ||
| 33 | + &.size-small { | ||
| 34 | + width: 40upx; | ||
| 35 | + padding: 5upx 0; | ||
| 36 | + } | ||
| 37 | + &.size-tiny { | ||
| 38 | + width: 30upx; | ||
| 39 | + padding: 2upx 0; | ||
| 40 | + } | ||
| 41 | + } | ||
| 42 | + .type-fill { | ||
| 43 | + color: #fff; | ||
| 44 | + } | ||
| 45 | + .type-ghost { | ||
| 46 | + border: 1px solid $color-error; | ||
| 47 | + background: rgba(0,0,0,0); | ||
| 48 | + } | ||
| 49 | + .font-weight-normal { | ||
| 50 | + font-weight: normal; | ||
| 51 | + } | ||
| 52 | + .font-weight-bold { | ||
| 53 | + font-weight: bold; | ||
| 54 | + } | ||
| 55 | + .font-weight-bolder { | ||
| 56 | + font-weight: bolder; | ||
| 57 | + } | ||
| 58 | + .size-large { | ||
| 59 | + font-size: $font-md; | ||
| 60 | + } | ||
| 61 | + .size-small { | ||
| 62 | + font-size: $font-sm; | ||
| 63 | + } | ||
| 64 | + .size-tiny { | ||
| 65 | + font-size: $font-sm * 0.9; | ||
| 66 | + } | ||
| 67 | +} | ||
| 68 | + |
| 1 | +++ a/components/tag/index.vue | ||
| @@ -0,0 +1,161 @@ | @@ -0,0 +1,161 @@ | ||
| 1 | +<template> | ||
| 2 | + <view class="zui-tag"> | ||
| 3 | + <template v-if="showQuarter"> | ||
| 4 | + <view :class="computedClass"> | ||
| 5 | + <view class="quarter-content"> | ||
| 6 | + <slot></slot> | ||
| 7 | + </view> | ||
| 8 | + <view class="quarter-bg" :style="colorStyle"></view> | ||
| 9 | + </view> | ||
| 10 | + </template> | ||
| 11 | + <template v-else-if="showCoupon"> | ||
| 12 | + <view :class="computedClass"> | ||
| 13 | + <view class="coupon-container" :style="colorStyle"> | ||
| 14 | + <view class="left-coupon" :style="leftCoupon" v-if="showCoupon"></view> | ||
| 15 | + <slot></slot> | ||
| 16 | + <view class="right-coupon" :style="rightCoupon" v-if="showCoupon"></view> | ||
| 17 | + </view> | ||
| 18 | + </view> | ||
| 19 | + </template> | ||
| 20 | + <template v-else> | ||
| 21 | + <view :class="computedClass" :style="[colorStyle, sizeStyle]"> | ||
| 22 | + <slot></slot> | ||
| 23 | + </view> | ||
| 24 | + </template> | ||
| 25 | + </view> | ||
| 26 | +</template> | ||
| 27 | + | ||
| 28 | +<script> | ||
| 29 | +export default { | ||
| 30 | + name: "Tag", | ||
| 31 | + props: { | ||
| 32 | + size: { | ||
| 33 | + type: String, // tiny, small, large | ||
| 34 | + default: "large" | ||
| 35 | + }, | ||
| 36 | + shape: { | ||
| 37 | + // square, circle, fillet, quarter, coupon, bubble | ||
| 38 | + type: String, | ||
| 39 | + default: "square" | ||
| 40 | + }, | ||
| 41 | + sharp: { | ||
| 42 | + // top-left, top-right, bottom-left, bottom-right | ||
| 43 | + type: String, | ||
| 44 | + default: "" | ||
| 45 | + }, | ||
| 46 | + type: { | ||
| 47 | + // fill ghost | ||
| 48 | + type: String, | ||
| 49 | + default: "ghost" | ||
| 50 | + }, | ||
| 51 | + fillColor: { | ||
| 52 | + type: String, | ||
| 53 | + default: "" | ||
| 54 | + }, | ||
| 55 | + fontWeight: { | ||
| 56 | + // normal, bold, bolder | ||
| 57 | + type: String, | ||
| 58 | + default: "normal" | ||
| 59 | + }, | ||
| 60 | + fontColor: { | ||
| 61 | + type: String, | ||
| 62 | + default: "" | ||
| 63 | + }, | ||
| 64 | + dotSize: String, | ||
| 65 | + radius: String, | ||
| 66 | + }, | ||
| 67 | + data: function() { | ||
| 68 | + return { | ||
| 69 | + sizeStyle: {} | ||
| 70 | + }; | ||
| 71 | + }, | ||
| 72 | + mounted: function() { | ||
| 73 | + this.$nextTick(function() { | ||
| 74 | + if (this.shape == "circle") { | ||
| 75 | + var radius = this.$el.offsetHeight / 2; | ||
| 76 | + this.$set(this.sizeStyle, "paddingLeft", radius / 2 + "px"); | ||
| 77 | + this.$set(this.sizeStyle, "paddingRight", radius / 2 + "px"); | ||
| 78 | + this.$set(this.sizeStyle, "borderRadius", radius + "px"); | ||
| 79 | + if (this.sharp) { | ||
| 80 | + this.$set( | ||
| 81 | + this.sizeStyle, | ||
| 82 | + this.transformCamelCase("border-" + this.sharp + "-radius"), | ||
| 83 | + 0 | ||
| 84 | + ); | ||
| 85 | + } | ||
| 86 | + } | ||
| 87 | + }); | ||
| 88 | + }, | ||
| 89 | + computed: { | ||
| 90 | + computedClass: function() { | ||
| 91 | + return [ | ||
| 92 | + "default", | ||
| 93 | + "size-" + this.size, | ||
| 94 | + "shape-" + this.shape, | ||
| 95 | + "type-" + this.type, | ||
| 96 | + "font-weight-" + this.fontWeight | ||
| 97 | + ]; | ||
| 98 | + }, | ||
| 99 | + colorStyle: function() { | ||
| 100 | + var style = {}; | ||
| 101 | + if (this.type == "fill") { | ||
| 102 | + // eslint-disable-next-line | ||
| 103 | + style.background = this.fillColor || '#ff5151'; | ||
| 104 | + } | ||
| 105 | + if (this.shape == 'dot') { | ||
| 106 | + style.height = this.dotSize; | ||
| 107 | + style.width = this.dotSize; | ||
| 108 | + style.display = 'flex'; | ||
| 109 | + style.alignItems = 'center'; | ||
| 110 | + style.justifyContent = 'center'; | ||
| 111 | + } | ||
| 112 | + if (this.fontColor) { | ||
| 113 | + if (this.type == "ghost") { | ||
| 114 | + style.borderColor = this.fontColor; | ||
| 115 | + } | ||
| 116 | + style.color = this.fontColor; | ||
| 117 | + } | ||
| 118 | + if (this.radius) { | ||
| 119 | + style.borderRadius = this.radius; | ||
| 120 | + } | ||
| 121 | + return style; | ||
| 122 | + }, | ||
| 123 | + leftCoupon: function() { | ||
| 124 | + return { | ||
| 125 | + background: this.fillColor | ||
| 126 | + ? "radial-gradient(circle at left, transparent 33%, " + | ||
| 127 | + this.fillColor + | ||
| 128 | + " 33%)" | ||
| 129 | + : "" | ||
| 130 | + }; | ||
| 131 | + }, | ||
| 132 | + rightCoupon: function() { | ||
| 133 | + return { | ||
| 134 | + background: this.fillColor | ||
| 135 | + ? "radial-gradient(circle at right, transparent 33%, " + | ||
| 136 | + this.fillColor + | ||
| 137 | + " 33%)" | ||
| 138 | + : "" | ||
| 139 | + }; | ||
| 140 | + }, | ||
| 141 | + showQuarter: function() { | ||
| 142 | + return this.shape == "quarter"; | ||
| 143 | + }, | ||
| 144 | + showCoupon: function() { | ||
| 145 | + return this.shape == "coupon"; | ||
| 146 | + } | ||
| 147 | + }, | ||
| 148 | + methods: { | ||
| 149 | + transformCamelCase: function(str) { | ||
| 150 | + var re = /-(\w)/g; | ||
| 151 | + return str.replace(re, function($0, $1) { | ||
| 152 | + return $1.toUpperCase(); | ||
| 153 | + }); | ||
| 154 | + }, | ||
| 155 | + } | ||
| 156 | +}; | ||
| 157 | +</script> | ||
| 158 | + | ||
| 159 | +<style lang="scss"> | ||
| 160 | +@import "./index.scss"; | ||
| 161 | +</style> | ||
| 0 | \ No newline at end of file | 162 | \ No newline at end of file |
| 1 | +++ a/index.js | ||
| @@ -0,0 +1,15 @@ | @@ -0,0 +1,15 @@ | ||
| 1 | +import Amount from './components/amount'; | ||
| 2 | +import Button from './components/button'; | ||
| 3 | +import Cell from './components/cell'; | ||
| 4 | +import Icon from './components/icon'; | ||
| 5 | +import Loading from './components/loading'; | ||
| 6 | +import Tag from './components/tag'; | ||
| 7 | + | ||
| 8 | +export default { | ||
| 9 | + Amount, | ||
| 10 | + Button, | ||
| 11 | + Cell, | ||
| 12 | + Icon, | ||
| 13 | + Loading, | ||
| 14 | + Tag | ||
| 15 | +}; | ||
| 0 | \ No newline at end of file | 16 | \ No newline at end of file |