mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
Merge branch 'dev' of https://github.com/youzan/vant into dev
This commit is contained in:
commit
6c7f8342b9
@ -31,6 +31,8 @@ Vue.component('demo-section', DemoSection);
|
|||||||
|
|
||||||
Locale.add({
|
Locale.add({
|
||||||
'zh-CN': {
|
'zh-CN': {
|
||||||
|
add: '增加',
|
||||||
|
decrease: '减少',
|
||||||
red: '红色',
|
red: '红色',
|
||||||
orange: '橙色',
|
orange: '橙色',
|
||||||
yellow: '黄色',
|
yellow: '黄色',
|
||||||
@ -56,6 +58,8 @@ Locale.add({
|
|||||||
passwordPlaceholder: '请输入密码'
|
passwordPlaceholder: '请输入密码'
|
||||||
},
|
},
|
||||||
'en-US': {
|
'en-US': {
|
||||||
|
add: 'Add',
|
||||||
|
decrease: 'Decrease',
|
||||||
red: 'Red',
|
red: 'Red',
|
||||||
orange: 'Orange',
|
orange: 'Orange',
|
||||||
yellow: 'Yellow',
|
yellow: 'Yellow',
|
||||||
|
@ -31,6 +31,7 @@ export default {
|
|||||||
'cell-swipe': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/cell-swipe'), 'cell-swipe')), 'cell-swipe')),
|
'cell-swipe': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/cell-swipe'), 'cell-swipe')), 'cell-swipe')),
|
||||||
'cell': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/cell'), 'cell')), 'cell')),
|
'cell': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/cell'), 'cell')), 'cell')),
|
||||||
'checkbox': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/checkbox'), 'checkbox')), 'checkbox')),
|
'checkbox': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/checkbox'), 'checkbox')), 'checkbox')),
|
||||||
|
'circle': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/circle'), 'circle')), 'circle')),
|
||||||
'contact': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/contact'), 'contact')), 'contact')),
|
'contact': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/contact'), 'contact')), 'contact')),
|
||||||
'coupon': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/coupon'), 'coupon')), 'coupon')),
|
'coupon': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/coupon'), 'coupon')), 'coupon')),
|
||||||
'datetime-picker': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/datetime-picker'), 'datetime-picker')), 'datetime-picker')),
|
'datetime-picker': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/datetime-picker'), 'datetime-picker')), 'datetime-picker')),
|
||||||
|
78
docs/demos/views/circle.vue
Normal file
78
docs/demos/views/circle.vue
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<template>
|
||||||
|
<demo-section>
|
||||||
|
<demo-block :title="$t('basicUsage')">
|
||||||
|
<van-circle
|
||||||
|
v-model="currentRate1"
|
||||||
|
:rate="rate"
|
||||||
|
:speed="100"
|
||||||
|
size="120px"
|
||||||
|
:text="currentRate1.toFixed(0) + '%'"
|
||||||
|
/>
|
||||||
|
<van-circle
|
||||||
|
v-model="currentRate2"
|
||||||
|
color="#13ce66"
|
||||||
|
fill="#fff"
|
||||||
|
:rate="rate"
|
||||||
|
size="120px"
|
||||||
|
layer-color="#eee"
|
||||||
|
:speed="100"
|
||||||
|
:stroke-width="60"
|
||||||
|
:clockwise="false"
|
||||||
|
:text="currentRate2.toFixed(0) + '%'"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<van-button :text="$t('add')" type="primary" size="small" @click="add" />
|
||||||
|
<van-button :text="$t('decrease')" type="danger" size="small" @click="reduce" />
|
||||||
|
</div>
|
||||||
|
</demo-block>
|
||||||
|
</demo-section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const format = rate => Math.min(Math.max(rate, 0), 100);
|
||||||
|
|
||||||
|
export default {
|
||||||
|
i18n: {
|
||||||
|
'zh-CN': {
|
||||||
|
title2: '样式定制'
|
||||||
|
},
|
||||||
|
'en-US': {
|
||||||
|
title2: 'Custom Style'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
rate: 30,
|
||||||
|
currentRate1: 0,
|
||||||
|
currentRate2: 0
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
add() {
|
||||||
|
this.rate = format(this.rate + 20);
|
||||||
|
},
|
||||||
|
|
||||||
|
reduce() {
|
||||||
|
this.rate = format(this.rate - 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="postcss">
|
||||||
|
.demo-circle {
|
||||||
|
.van-circle {
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.van-button {
|
||||||
|
margin: 15px 0 0 10px;
|
||||||
|
|
||||||
|
&:first-of-type {
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -13,6 +13,7 @@
|
|||||||
:reset-stepper-on-hide="true"
|
:reset-stepper-on-hide="true"
|
||||||
:reset-selected-sku-on-hide="true"
|
:reset-selected-sku-on-hide="true"
|
||||||
:disable-stepper-input="true"
|
:disable-stepper-input="true"
|
||||||
|
:message-config="messageConfig"
|
||||||
@buy-clicked="onBuyClicked"
|
@buy-clicked="onBuyClicked"
|
||||||
@add-cart="onAddCartClicked"
|
@add-cart="onAddCartClicked"
|
||||||
/>
|
/>
|
||||||
@ -23,7 +24,7 @@
|
|||||||
<demo-block :title="$t('title2')">
|
<demo-block :title="$t('title2')">
|
||||||
<div class="sku-container">
|
<div class="sku-container">
|
||||||
<van-sku
|
<van-sku
|
||||||
v-model="showBase"
|
v-model="showStepper"
|
||||||
:sku="$t('sku').sku"
|
:sku="$t('sku').sku"
|
||||||
:goods="$t('sku').goods_info"
|
:goods="$t('sku').goods_info"
|
||||||
:goods-id="$t('sku').goods_id"
|
:goods-id="$t('sku').goods_id"
|
||||||
@ -34,7 +35,7 @@
|
|||||||
@buy-clicked="onBuyClicked"
|
@buy-clicked="onBuyClicked"
|
||||||
@add-cart="onAddCartClicked"
|
@add-cart="onAddCartClicked"
|
||||||
/>
|
/>
|
||||||
<van-button type="primary" @click="showBase = true" block>{{ $t('title2') }}</van-button>
|
<van-button type="primary" @click="showStepper = true" block>{{ $t('title2') }}</van-button>
|
||||||
</div>
|
</div>
|
||||||
</demo-block>
|
</demo-block>
|
||||||
|
|
||||||
@ -94,6 +95,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
showBase: false,
|
showBase: false,
|
||||||
showCustom: false,
|
showCustom: false,
|
||||||
|
showStepper: false,
|
||||||
initialSku: {
|
initialSku: {
|
||||||
s1: '30349',
|
s1: '30349',
|
||||||
s2: '1193'
|
s2: '1193'
|
||||||
@ -113,6 +115,14 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
messageConfig: {
|
||||||
|
uploadImg: () => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => resolve('https://img.yzcdn.cn/upload_files/2017/02/21/FjKTOxjVgnUuPmHJRdunvYky9OHP.jpg!100x100.jpg'), 1000);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
uploadMaxSize: 3
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -61,6 +61,7 @@ Actionsheet will get another style if there is a `title` prop.
|
|||||||
| cancel-text | Text of cancel button | `String` | - | - |
|
| cancel-text | Text of cancel button | `String` | - | - |
|
||||||
| overlay | Whether to show overlay | `Boolean` | - | - |
|
| overlay | Whether to show overlay | `Boolean` | - | - |
|
||||||
| close-on-click-overlay | Whether to close when click overlay | `Boolean` | - | - |
|
| close-on-click-overlay | Whether to close when click overlay | `Boolean` | - | - |
|
||||||
|
| get-container | Return the mount node for actionsheet | `Function` | - | `() => HTMLElement` |
|
||||||
|
|
||||||
### Data struct of actions
|
### Data struct of actions
|
||||||
|
|
||||||
|
69
docs/markdown/en-US/circle.md
Normal file
69
docs/markdown/en-US/circle.md
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
## Circle
|
||||||
|
|
||||||
|
### Install
|
||||||
|
``` javascript
|
||||||
|
import { Circle } from 'vant';
|
||||||
|
|
||||||
|
Vue.use(Circle);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
#### Basic Usage
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-circle
|
||||||
|
v-model="currentRate"
|
||||||
|
:rate="30"
|
||||||
|
:speed="100"
|
||||||
|
:text="text"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
``` javascript
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
currentRate: 0
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
text() {
|
||||||
|
return this.currentRate.toFixed(0) + '%'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Custom style
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-circle
|
||||||
|
v-model="currentRate"
|
||||||
|
color="#13ce66"
|
||||||
|
fill="#fff"
|
||||||
|
size="120px"
|
||||||
|
layer-color="#eee"
|
||||||
|
:text="text"
|
||||||
|
:rate="rate"
|
||||||
|
:speed="100"
|
||||||
|
:clockwise="false"
|
||||||
|
:stroke-width="60"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### API
|
||||||
|
|
||||||
|
| Attribute | Description | Type | Default | Accepted Values |
|
||||||
|
|-----------|-----------|-----------|-------------|-------------|
|
||||||
|
| v-model | Current rate | `Number` | - | - |
|
||||||
|
| rate | Target rate | `Number` | `100` | - |
|
||||||
|
| size | Circle size | `String` | `100px` | - |
|
||||||
|
| color | Progress bar color | `String` | `#38f` | - |
|
||||||
|
| layer-color | Layer color | `String` | `#fff` | - |
|
||||||
|
| fill | Fill color | `String` | `none` | - |
|
||||||
|
| speed | Animate speed(rate/s)| `Number` | - | - |
|
||||||
|
| text | Text | `String` | - | - |
|
||||||
|
| stroke-width | Stroke width | `Number` | `40` | - |
|
||||||
|
| clockwise | Is clockwise | `Boolean` | `true` | - |
|
@ -48,3 +48,4 @@ Use `position` prop to set popup display position
|
|||||||
| close-on-click-overlay | Close popup when click overlay | `Boolean` | `true` | - |
|
| close-on-click-overlay | Close popup when click overlay | `Boolean` | `true` | - |
|
||||||
| transition | Transition | `String` | `popup-slide` | - |
|
| transition | Transition | `String` | `popup-slide` | - |
|
||||||
| prevent-scroll | Prevent background scroll | `Boolean` | `false` | - |
|
| prevent-scroll | Prevent background scroll | `Boolean` | `false` | - |
|
||||||
|
| get-container | Return the mount node for Popup | `Function` | - | `() => HTMLElement` |
|
||||||
|
@ -22,6 +22,7 @@ Vue.use(Sku);
|
|||||||
:reset-stepper-on-hide="resetStepperOnHide"
|
:reset-stepper-on-hide="resetStepperOnHide"
|
||||||
:reset-selected-sku-on-hide="resetSelectedSkuOnHide"
|
:reset-selected-sku-on-hide="resetSelectedSkuOnHide"
|
||||||
:disable-stepper-input="disableStepperInput"
|
:disable-stepper-input="disableStepperInput"
|
||||||
|
:message-config="messageConfig"
|
||||||
@buy-clicked="onBuyClicked"
|
@buy-clicked="onBuyClicked"
|
||||||
@add-cart="onAddCartClicked"
|
@add-cart="onAddCartClicked"
|
||||||
/>
|
/>
|
||||||
@ -90,6 +91,8 @@ Vue.use(Sku);
|
|||||||
| disable-stepper-input | Whether to disable stepper input | `Boolean` | `false` | - |
|
| disable-stepper-input | Whether to disable stepper input | `Boolean` | `false` | - |
|
||||||
| stepper-title | Quantity title | `String` | `Quantity` | - |
|
| stepper-title | Quantity title | `String` | `Quantity` | - |
|
||||||
| custom-stepper-config | Custom stepper related config | `Object` | `{}` | - |
|
| custom-stepper-config | Custom stepper related config | `Object` | `{}` | - |
|
||||||
|
| message-config | Message related config | `Object` | `{}` | - |
|
||||||
|
| get-container | Return the mount node for sku | `Function` | - | `() => HTMLElement` |
|
||||||
|
|
||||||
### Event
|
### Event
|
||||||
|
|
||||||
@ -200,6 +203,26 @@ customStepperConfig: {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### messageConfig Data Structure
|
||||||
|
```javascript
|
||||||
|
messageConfig: {
|
||||||
|
// the upload image callback
|
||||||
|
uploadImg: () => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => resolve('https://img.yzcdn.cn/upload_files/2017/02/21/FjKTOxjVgnUuPmHJRdunvYky9OHP.jpg!100x100.jpg'), 1000);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// max file size (MB)
|
||||||
|
uploadMaxSize: 3,
|
||||||
|
// placehold config
|
||||||
|
placeholderMap: {
|
||||||
|
text: 'xxx',
|
||||||
|
tel: 'xxx',
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### Event Params Data Structure
|
#### Event Params Data Structure
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
@ -25,6 +25,7 @@ export default {
|
|||||||
'zh-CN/changelog-generated': wrapper(r => require.ensure([], () => r(require('./zh-CN/changelog-generated.md')), 'zh-CN/changelog-generated')),
|
'zh-CN/changelog-generated': wrapper(r => require.ensure([], () => r(require('./zh-CN/changelog-generated.md')), 'zh-CN/changelog-generated')),
|
||||||
'zh-CN/changelog': wrapper(r => require.ensure([], () => r(require('./zh-CN/changelog.md')), 'zh-CN/changelog')),
|
'zh-CN/changelog': wrapper(r => require.ensure([], () => r(require('./zh-CN/changelog.md')), 'zh-CN/changelog')),
|
||||||
'zh-CN/checkbox': wrapper(r => require.ensure([], () => r(require('./zh-CN/checkbox.md')), 'zh-CN/checkbox')),
|
'zh-CN/checkbox': wrapper(r => require.ensure([], () => r(require('./zh-CN/checkbox.md')), 'zh-CN/checkbox')),
|
||||||
|
'zh-CN/circle': wrapper(r => require.ensure([], () => r(require('./zh-CN/circle.md')), 'zh-CN/circle')),
|
||||||
'zh-CN/contact': wrapper(r => require.ensure([], () => r(require('./zh-CN/contact.md')), 'zh-CN/contact')),
|
'zh-CN/contact': wrapper(r => require.ensure([], () => r(require('./zh-CN/contact.md')), 'zh-CN/contact')),
|
||||||
'zh-CN/coupon': wrapper(r => require.ensure([], () => r(require('./zh-CN/coupon.md')), 'zh-CN/coupon')),
|
'zh-CN/coupon': wrapper(r => require.ensure([], () => r(require('./zh-CN/coupon.md')), 'zh-CN/coupon')),
|
||||||
'zh-CN/datetime-picker': wrapper(r => require.ensure([], () => r(require('./zh-CN/datetime-picker.md')), 'zh-CN/datetime-picker')),
|
'zh-CN/datetime-picker': wrapper(r => require.ensure([], () => r(require('./zh-CN/datetime-picker.md')), 'zh-CN/datetime-picker')),
|
||||||
@ -77,6 +78,7 @@ export default {
|
|||||||
'en-US/cell': wrapper(r => require.ensure([], () => r(require('./en-US/cell.md')), 'en-US/cell')),
|
'en-US/cell': wrapper(r => require.ensure([], () => r(require('./en-US/cell.md')), 'en-US/cell')),
|
||||||
'en-US/changelog': wrapper(r => require.ensure([], () => r(require('./en-US/changelog.md')), 'en-US/changelog')),
|
'en-US/changelog': wrapper(r => require.ensure([], () => r(require('./en-US/changelog.md')), 'en-US/changelog')),
|
||||||
'en-US/checkbox': wrapper(r => require.ensure([], () => r(require('./en-US/checkbox.md')), 'en-US/checkbox')),
|
'en-US/checkbox': wrapper(r => require.ensure([], () => r(require('./en-US/checkbox.md')), 'en-US/checkbox')),
|
||||||
|
'en-US/circle': wrapper(r => require.ensure([], () => r(require('./en-US/circle.md')), 'en-US/circle')),
|
||||||
'en-US/contact': wrapper(r => require.ensure([], () => r(require('./en-US/contact.md')), 'en-US/contact')),
|
'en-US/contact': wrapper(r => require.ensure([], () => r(require('./en-US/contact.md')), 'en-US/contact')),
|
||||||
'en-US/coupon': wrapper(r => require.ensure([], () => r(require('./en-US/coupon.md')), 'en-US/coupon')),
|
'en-US/coupon': wrapper(r => require.ensure([], () => r(require('./en-US/coupon.md')), 'en-US/coupon')),
|
||||||
'en-US/datetime-picker': wrapper(r => require.ensure([], () => r(require('./en-US/datetime-picker.md')), 'en-US/datetime-picker')),
|
'en-US/datetime-picker': wrapper(r => require.ensure([], () => r(require('./en-US/datetime-picker.md')), 'en-US/datetime-picker')),
|
||||||
|
@ -72,6 +72,7 @@ export default {
|
|||||||
| cancel-text | 取消按钮文案 | `String` | - | - |
|
| cancel-text | 取消按钮文案 | `String` | - | - |
|
||||||
| overlay | 是否显示遮罩 | `Boolean` | - | - |
|
| overlay | 是否显示遮罩 | `Boolean` | - | - |
|
||||||
| close-on-click-overlay | 点击遮罩是否关闭`Actionsheet` | `Boolean` | - | - |
|
| close-on-click-overlay | 点击遮罩是否关闭`Actionsheet` | `Boolean` | - | - |
|
||||||
|
| get-container | 指定挂载的 HTML 节点 | `Function` | - | `() => HTMLElement` |
|
||||||
|
|
||||||
### actions
|
### actions
|
||||||
|
|
||||||
|
70
docs/markdown/zh-CN/circle.md
Normal file
70
docs/markdown/zh-CN/circle.md
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
## Circle 环形进度条
|
||||||
|
|
||||||
|
### 使用指南
|
||||||
|
``` javascript
|
||||||
|
import { Circle } from 'vant';
|
||||||
|
|
||||||
|
Vue.use(Circle);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 代码演示
|
||||||
|
|
||||||
|
#### 基础用法
|
||||||
|
通过 `rate` 指定目标进度,`v-model` 代表当前进度,`speed` 控制动画速度
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-circle
|
||||||
|
v-model="currentRate"
|
||||||
|
:rate="30"
|
||||||
|
:speed="100"
|
||||||
|
:text="text"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
``` javascript
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
currentRate: 0
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
text() {
|
||||||
|
return this.currentRate.toFixed(0) + '%'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 样式定制
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-circle
|
||||||
|
v-model="currentRate"
|
||||||
|
color="#13ce66"
|
||||||
|
fill="#fff"
|
||||||
|
size="120px"
|
||||||
|
layer-color="#eee"
|
||||||
|
:text="text"
|
||||||
|
:rate="rate"
|
||||||
|
:speed="100"
|
||||||
|
:clockwise="false"
|
||||||
|
:stroke-width="60"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### API
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
||||||
|
|-----------|-----------|-----------|-------------|-------------|
|
||||||
|
| v-model | 当前进度 | `Number` | - | - |
|
||||||
|
| rate | 目标进度 | `Number` | `100` | - |
|
||||||
|
| size | 圆环直径 | `String` | `100px` | - |
|
||||||
|
| color | 进度条颜色 | `String` | `#38f` | - |
|
||||||
|
| layer-color | 轨道颜色 | `String` | `#fff` | - |
|
||||||
|
| fill | 填充颜色 | `String` | `none` | - |
|
||||||
|
| speed | 动画速度(单位为 rate/s)| `Number` | - | - |
|
||||||
|
| text | 文字 | `String` | - | - |
|
||||||
|
| stroke-width | 进度条宽度 | `Number` | `40` | - |
|
||||||
|
| clockwise | 是否顺时针增加 | `Boolean` | `true` | - |
|
@ -48,3 +48,4 @@ export default {
|
|||||||
| close-on-click-overlay | 点击蒙层是否关闭 Popup | `Boolean` | `true` | - |
|
| close-on-click-overlay | 点击蒙层是否关闭 Popup | `Boolean` | `true` | - |
|
||||||
| transition | transition 名称 | `String` | `popup-slide` | - |
|
| transition | transition 名称 | `String` | `popup-slide` | - |
|
||||||
| prevent-scroll | 是否防止滚动穿透 | `Boolean` | `false` | - |
|
| prevent-scroll | 是否防止滚动穿透 | `Boolean` | `false` | - |
|
||||||
|
| get-container | 指定弹出层挂载的 HTML 节点 | `Function` | - | `() => HTMLElement` |
|
||||||
|
@ -22,6 +22,7 @@ Vue.use(Sku);
|
|||||||
:reset-stepper-on-hide="resetStepperOnHide"
|
:reset-stepper-on-hide="resetStepperOnHide"
|
||||||
:reset-selected-sku-on-hide="resetSelectedSkuOnHide"
|
:reset-selected-sku-on-hide="resetSelectedSkuOnHide"
|
||||||
:disable-stepper-input="disableStepperInput"
|
:disable-stepper-input="disableStepperInput"
|
||||||
|
:message-config="messageConfig"
|
||||||
@buy-clicked="onBuyClicked"
|
@buy-clicked="onBuyClicked"
|
||||||
@add-cart="onAddCartClicked"
|
@add-cart="onAddCartClicked"
|
||||||
/>
|
/>
|
||||||
@ -91,6 +92,8 @@ Vue.use(Sku);
|
|||||||
| disable-stepper-input | 是否禁用sku中stepper的input框 | `Boolean` | `false` | - |
|
| disable-stepper-input | 是否禁用sku中stepper的input框 | `Boolean` | `false` | - |
|
||||||
| stepper-title | 数量选择组件左侧文案 | `String` | `购买数量` | - |
|
| stepper-title | 数量选择组件左侧文案 | `String` | `购买数量` | - |
|
||||||
| custom-stepper-config | 步进器相关自定义配置 | `Object` | `{}` | - |
|
| custom-stepper-config | 步进器相关自定义配置 | `Object` | `{}` | - |
|
||||||
|
| message-config | 留言相关配置 | `Object` | `{}` | - |
|
||||||
|
| get-container | 指定挂载的 HTML 节点 | `Function` | - | `() => HTMLElement` |
|
||||||
|
|
||||||
### Event
|
### Event
|
||||||
|
|
||||||
@ -206,6 +209,26 @@ customStepperConfig: {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### messageConfig Data Structure
|
||||||
|
```javascript
|
||||||
|
messageConfig: {
|
||||||
|
// 图片上传回调,需要返回一个promise,promise正确执行的结果需要是一个图片url
|
||||||
|
uploadImg: () => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => resolve('https://img.yzcdn.cn/upload_files/2017/02/21/FjKTOxjVgnUuPmHJRdunvYky9OHP.jpg!100x100.jpg'), 1000);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 最大上传体积 (MB)
|
||||||
|
uploadMaxSize: 3,
|
||||||
|
// placehold配置
|
||||||
|
placeholderMap: {
|
||||||
|
text: 'xxx',
|
||||||
|
tel: 'xxx',
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### 添加购物车和点击购买回调函数接收的 skuData 对象结构
|
#### 添加购物车和点击购买回调函数接收的 skuData 对象结构
|
||||||
```javascript
|
```javascript
|
||||||
skuData: {
|
skuData: {
|
||||||
|
@ -80,6 +80,10 @@ module.exports = {
|
|||||||
path: '/cell',
|
path: '/cell',
|
||||||
title: 'Cell - 单元格'
|
title: 'Cell - 单元格'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/circle',
|
||||||
|
title: 'Circle - 环形进度条'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/icon',
|
path: '/icon',
|
||||||
title: 'Icon - 图标'
|
title: 'Icon - 图标'
|
||||||
@ -358,6 +362,10 @@ module.exports = {
|
|||||||
path: '/cell',
|
path: '/cell',
|
||||||
title: 'Cell'
|
title: 'Cell'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/circle',
|
||||||
|
title: 'Circle'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/icon',
|
path: '/icon',
|
||||||
title: 'Icon'
|
title: 'Icon'
|
||||||
|
@ -60,10 +60,6 @@ export default create({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
|
||||||
this.value && this.open();
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onClickItem(item) {
|
onClickItem(item) {
|
||||||
if (typeof item.callback === 'function') {
|
if (typeof item.callback === 'function') {
|
||||||
|
126
packages/circle/index.vue
Normal file
126
packages/circle/index.vue
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<template>
|
||||||
|
<div class="van-circle" :style="style">
|
||||||
|
<svg viewBox="0 0 1060 1060">
|
||||||
|
<path class="van-circle__hover" :style="hoverStyle" :d="path" />
|
||||||
|
<path class="van-circle__layer" :style="layerStyle" :d="path" />
|
||||||
|
</svg>
|
||||||
|
<slot>
|
||||||
|
<div class="van-circle__text">{{ text }}</div>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { create } from '../utils';
|
||||||
|
import { raf, cancel } from '../utils/raf';
|
||||||
|
|
||||||
|
export default create({
|
||||||
|
name: 'van-circle',
|
||||||
|
|
||||||
|
props: {
|
||||||
|
text: String,
|
||||||
|
value: Number,
|
||||||
|
speed: Number,
|
||||||
|
size: {
|
||||||
|
type: String,
|
||||||
|
default: '100px'
|
||||||
|
},
|
||||||
|
fill: {
|
||||||
|
type: String,
|
||||||
|
default: 'none'
|
||||||
|
},
|
||||||
|
rate: {
|
||||||
|
type: Number,
|
||||||
|
default: 100
|
||||||
|
},
|
||||||
|
layerColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#fff'
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: '#38f'
|
||||||
|
},
|
||||||
|
strokeWidth: {
|
||||||
|
type: Number,
|
||||||
|
default: 40
|
||||||
|
},
|
||||||
|
clockwise: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeCreate() {
|
||||||
|
this.perimeter = Math.PI * 1000;
|
||||||
|
this.path = 'M 530 530 m -500, 0 a 500, 500 0 1, 1 1000, 0 a 500, 500 0 1, 1 -1000, 0';
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
style() {
|
||||||
|
return {
|
||||||
|
width: this.size,
|
||||||
|
height: this.size
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
layerStyle() {
|
||||||
|
let offset = this.perimeter * (100 - this.value) / 100;
|
||||||
|
offset = this.clockwise ? offset : this.perimeter * 2 - offset;
|
||||||
|
return {
|
||||||
|
stroke: `${this.color}`,
|
||||||
|
strokeDashoffset: `${offset}px`,
|
||||||
|
strokeWidth: `${this.strokeWidth + 1}px`
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
hoverStyle() {
|
||||||
|
return {
|
||||||
|
fill: `${this.fill}`,
|
||||||
|
stroke: `${this.layerColor}`,
|
||||||
|
strokeWidth: `${this.strokeWidth}px`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.render();
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
rate() {
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
render() {
|
||||||
|
this.startTime = Date.now();
|
||||||
|
this.startRate = this.value;
|
||||||
|
this.endRate = this.format(this.rate);
|
||||||
|
this.increase = this.endRate > this.startRate;
|
||||||
|
this.duration = Math.abs((this.startRate - this.endRate) * 1000 / this.speed);
|
||||||
|
if (this.speed) {
|
||||||
|
cancel(this.rafId);
|
||||||
|
this.rafId = raf(this.animate);
|
||||||
|
} else {
|
||||||
|
this.$emit('input', this.endRate);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
animate() {
|
||||||
|
const now = Date.now();
|
||||||
|
const progress = Math.min((now - this.startTime) / this.duration, 1);
|
||||||
|
const rate = progress * (this.endRate - this.startRate) + this.startRate;
|
||||||
|
this.$emit('input', this.format(parseFloat(rate.toFixed(1))));
|
||||||
|
if (this.increase ? rate < this.endRate : rate > this.endRate) {
|
||||||
|
this.rafId = raf(this.animate);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
format(rate) {
|
||||||
|
return Math.min(Math.max(rate, 0), 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
@ -53,7 +53,6 @@ import Cell from '../cell';
|
|||||||
import CellGroup from '../cell-group';
|
import CellGroup from '../cell-group';
|
||||||
import CouponItem from './Item';
|
import CouponItem from './Item';
|
||||||
import Field from '../field';
|
import Field from '../field';
|
||||||
import Popup from '../popup';
|
|
||||||
import VanButton from '../button';
|
import VanButton from '../button';
|
||||||
|
|
||||||
export default create({
|
export default create({
|
||||||
@ -64,7 +63,6 @@ export default create({
|
|||||||
Cell,
|
Cell,
|
||||||
CellGroup,
|
CellGroup,
|
||||||
Field,
|
Field,
|
||||||
Popup,
|
|
||||||
CouponItem
|
CouponItem
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import CellGroup from './cell-group';
|
|||||||
import CellSwipe from './cell-swipe';
|
import CellSwipe from './cell-swipe';
|
||||||
import Checkbox from './checkbox';
|
import Checkbox from './checkbox';
|
||||||
import CheckboxGroup from './checkbox-group';
|
import CheckboxGroup from './checkbox-group';
|
||||||
|
import Circle from './circle';
|
||||||
import Col from './col';
|
import Col from './col';
|
||||||
import ContactCard from './contact-card';
|
import ContactCard from './contact-card';
|
||||||
import ContactEdit from './contact-edit';
|
import ContactEdit from './contact-edit';
|
||||||
@ -77,6 +78,7 @@ const components = [
|
|||||||
CellSwipe,
|
CellSwipe,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
CheckboxGroup,
|
CheckboxGroup,
|
||||||
|
Circle,
|
||||||
Col,
|
Col,
|
||||||
ContactCard,
|
ContactCard,
|
||||||
ContactEdit,
|
ContactEdit,
|
||||||
@ -149,6 +151,7 @@ export {
|
|||||||
CellSwipe,
|
CellSwipe,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
CheckboxGroup,
|
CheckboxGroup,
|
||||||
|
Circle,
|
||||||
Col,
|
Col,
|
||||||
ContactCard,
|
ContactCard,
|
||||||
ContactEdit,
|
ContactEdit,
|
||||||
|
@ -113,10 +113,12 @@ export default {
|
|||||||
},
|
},
|
||||||
vanSkuMessages: {
|
vanSkuMessages: {
|
||||||
fill: 'Please fill',
|
fill: 'Please fill',
|
||||||
|
upload: 'Please upload',
|
||||||
number: 'Please fill in the correct number format message',
|
number: 'Please fill in the correct number format message',
|
||||||
email: 'Please fill in the correct email message',
|
email: 'Please fill in the correct email message',
|
||||||
idcard: 'Please fill in the correct ID number message',
|
idcard: 'Please fill in the correct ID number message',
|
||||||
overlimit: 'not more than 200 words',
|
overlimit: 'not more than 200 words',
|
||||||
|
onePic: 'only one picture',
|
||||||
placeholder: {
|
placeholder: {
|
||||||
'id_no': 'Idcard Number',
|
'id_no': 'Idcard Number',
|
||||||
text: 'Text',
|
text: 'Text',
|
||||||
@ -127,6 +129,15 @@ export default {
|
|||||||
textarea: 'Text'
|
textarea: 'Text'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
vanSkuImgUploader: {
|
||||||
|
or: 'Or',
|
||||||
|
uploading: 'Uploading...',
|
||||||
|
rephoto: 'Take Again',
|
||||||
|
photo: 'Take',
|
||||||
|
reselect: 'Reselect',
|
||||||
|
select: 'Select Photo',
|
||||||
|
maxSize: maxSize => `The upload limit is up to ${maxSize}MB,please try to compress the photo`
|
||||||
|
},
|
||||||
vanSkuStepper: {
|
vanSkuStepper: {
|
||||||
title: 'Quantity',
|
title: 'Quantity',
|
||||||
remain: count => `Remain ${count} items`,
|
remain: count => `Remain ${count} items`,
|
||||||
|
@ -117,10 +117,12 @@ export default {
|
|||||||
},
|
},
|
||||||
vanSkuMessages: {
|
vanSkuMessages: {
|
||||||
fill: '请填写',
|
fill: '请填写',
|
||||||
|
upload: '请上传',
|
||||||
number: '请填写正确的数字格式留言',
|
number: '请填写正确的数字格式留言',
|
||||||
email: '请填写正确的邮箱',
|
email: '请填写正确的邮箱',
|
||||||
'id_no': '请填写正确的身份证号码',
|
'id_no': '请填写正确的身份证号码',
|
||||||
overlimit: '写的太多了,不要超过200字',
|
overlimit: '写的太多了,不要超过200字',
|
||||||
|
onePic: '仅限一张',
|
||||||
placeholder: {
|
placeholder: {
|
||||||
'id_no': '输入18位身份证号码',
|
'id_no': '输入18位身份证号码',
|
||||||
text: '输入文本',
|
text: '输入文本',
|
||||||
@ -131,6 +133,15 @@ export default {
|
|||||||
textarea: '点击填写段落文本'
|
textarea: '点击填写段落文本'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
vanSkuImgUploader: {
|
||||||
|
or: '或',
|
||||||
|
uploading: '正在上传...',
|
||||||
|
rephoto: '重拍',
|
||||||
|
photo: '拍照',
|
||||||
|
reselect: '重新选择照片',
|
||||||
|
select: '选择照片',
|
||||||
|
maxSize: maxSize => `最大可上传图片为${maxSize}MB,请尝试压缩图片尺寸`
|
||||||
|
},
|
||||||
vanSkuStepper: {
|
vanSkuStepper: {
|
||||||
title: '购买数量',
|
title: '购买数量',
|
||||||
remain: count => `剩余${count}件`,
|
remain: count => `剩余${count}件`,
|
||||||
|
@ -19,6 +19,8 @@ export default {
|
|||||||
zIndex: [String, Number],
|
zIndex: [String, Number],
|
||||||
// prevent touchmove scroll
|
// prevent touchmove scroll
|
||||||
preventScroll: Boolean,
|
preventScroll: Boolean,
|
||||||
|
// return the mount node for popup
|
||||||
|
getContainer: Function,
|
||||||
// prevent body scroll
|
// prevent body scroll
|
||||||
lockOnScroll: {
|
lockOnScroll: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@ -26,17 +28,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
|
||||||
value(val) {
|
|
||||||
this[val ? 'open' : 'close']();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeMount() {
|
|
||||||
this._popupId = 'popup-' + context.plusKey('idSeed');
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
|
this._popupId = 'popup-' + context.plusKey('idSeed');
|
||||||
return {
|
return {
|
||||||
opened: false,
|
opened: false,
|
||||||
pos: {
|
pos: {
|
||||||
@ -46,6 +39,29 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
value(val) {
|
||||||
|
this[val ? 'open' : 'close']();
|
||||||
|
},
|
||||||
|
|
||||||
|
getContainer() {
|
||||||
|
this.move();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
if (this.getContainer) {
|
||||||
|
this.move();
|
||||||
|
}
|
||||||
|
if (this.value) {
|
||||||
|
this.open();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy() {
|
||||||
|
this.doAfterClose();
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
recordPosition(e) {
|
recordPosition(e) {
|
||||||
this.pos = {
|
this.pos = {
|
||||||
@ -65,12 +81,14 @@ export default {
|
|||||||
|
|
||||||
let status = '11';
|
let status = '11';
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
if (scrollTop === 0) {
|
if (scrollTop === 0) {
|
||||||
status = offsetHeight >= scrollHeight ? '00' : '01';
|
status = offsetHeight >= scrollHeight ? '00' : '01';
|
||||||
} else if (scrollTop + offsetHeight >= scrollHeight) {
|
} else if (scrollTop + offsetHeight >= scrollHeight) {
|
||||||
status = '10';
|
status = '10';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
if (
|
if (
|
||||||
status !== '11' &&
|
status !== '11' &&
|
||||||
isVertical &&
|
isVertical &&
|
||||||
@ -82,6 +100,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
open() {
|
open() {
|
||||||
|
/* istanbul ignore next */
|
||||||
if (this.opened || this.$isServer) {
|
if (this.opened || this.$isServer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -137,10 +156,14 @@ export default {
|
|||||||
off(document, 'touchstart', this.recordPosition);
|
off(document, 'touchstart', this.recordPosition);
|
||||||
off(document, 'touchmove', this.watchTouchMove);
|
off(document, 'touchmove', this.watchTouchMove);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
|
||||||
|
|
||||||
beforeDestroy() {
|
move() {
|
||||||
this.doAfterClose();
|
if (this.getContainer) {
|
||||||
|
this.getContainer().appendChild(this.$el);
|
||||||
|
} else if (this.$parent) {
|
||||||
|
this.$parent.$el.appendChild(this.$el);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -41,6 +41,7 @@ const manager = {
|
|||||||
const { id, dom } = config;
|
const { id, dom } = config;
|
||||||
const exist = context.stack.some(item => item.id === id);
|
const exist = context.stack.some(item => item.id === id);
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
if (!exist) {
|
if (!exist) {
|
||||||
const targetNode = dom && dom.parentNode && dom.parentNode.nodeType !== 11 ? dom.parentNode : document.body;
|
const targetNode = dom && dom.parentNode && dom.parentNode.nodeType !== 11 ? dom.parentNode : document.body;
|
||||||
context.stack.push({ instance, id, config, targetNode });
|
context.stack.push({ instance, id, config, targetNode });
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
<li
|
<li
|
||||||
v-for="(option, index) in options"
|
v-for="(option, index) in options"
|
||||||
v-text="getOptionText(option)"
|
v-text="getOptionText(option)"
|
||||||
|
class="van-ellipsis"
|
||||||
:class="{
|
:class="{
|
||||||
'van-picker-column--disabled': isDisabled(option),
|
'van-picker-column--disabled': isDisabled(option),
|
||||||
'van-picker-column--selected': index === currentIndex
|
'van-picker-column--selected': index === currentIndex
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
<div class="van-picker__toolbar van-hairline--top-bottom" v-if="showToolbar">
|
<div class="van-picker__toolbar van-hairline--top-bottom" v-if="showToolbar">
|
||||||
<slot>
|
<slot>
|
||||||
<div class="van-picker__cancel" @click="emit('cancel')">{{ cancelButtonText || $t('cancel') }}</div>
|
<div class="van-picker__cancel" @click="emit('cancel')">{{ cancelButtonText || $t('cancel') }}</div>
|
||||||
|
<div class="van-picker__title van-ellipsis" v-if="title" v-text="title" />
|
||||||
<div class="van-picker__confirm" @click="emit('confirm')">{{ confirmButtonText || $t('confirm') }}</div>
|
<div class="van-picker__confirm" @click="emit('confirm')">{{ confirmButtonText || $t('confirm') }}</div>
|
||||||
<div class="van-picker__title" v-if="title" v-text="title" />
|
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
<div class="van-picker__columns" @touchmove.prevent>
|
<div class="van-picker__columns" @touchmove.prevent>
|
||||||
|
@ -41,12 +41,6 @@ export default create({
|
|||||||
currentValue: false,
|
currentValue: false,
|
||||||
currentTransition: transition
|
currentTransition: transition
|
||||||
};
|
};
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
if (this.value) {
|
|
||||||
this.open();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<popup v-model="show" v-if="!isSkuEmpty" position="bottom" lock-on-scroll prevent-scroll>
|
<popup
|
||||||
|
v-if="!isSkuEmpty"
|
||||||
|
v-model="show"
|
||||||
|
position="bottom"
|
||||||
|
lock-on-scroll
|
||||||
|
prevent-scroll
|
||||||
|
:get-container="getContainer"
|
||||||
|
>
|
||||||
<div class="van-sku-container">
|
<div class="van-sku-container">
|
||||||
<div class="van-sku-layout">
|
<div class="van-sku-layout">
|
||||||
<!-- sku-header -->
|
<!-- sku-header -->
|
||||||
@ -74,7 +81,7 @@
|
|||||||
<sku-messages
|
<sku-messages
|
||||||
ref="skuMessages"
|
ref="skuMessages"
|
||||||
:goods-id="goodsId"
|
:goods-id="goodsId"
|
||||||
:message-placeholder-map="messagePlaceholderMap"
|
:message-config="messageConfig"
|
||||||
:messages="sku.messages"
|
:messages="sku.messages"
|
||||||
/>
|
/>
|
||||||
</slot>
|
</slot>
|
||||||
@ -134,6 +141,7 @@ export default create({
|
|||||||
goodsId: [Number, String],
|
goodsId: [Number, String],
|
||||||
stepperTitle: String,
|
stepperTitle: String,
|
||||||
hideStock: Boolean,
|
hideStock: Boolean,
|
||||||
|
getContainer: Function,
|
||||||
resetStepperOnHide: Boolean,
|
resetStepperOnHide: Boolean,
|
||||||
resetSelectedSkuOnHide: Boolean,
|
resetSelectedSkuOnHide: Boolean,
|
||||||
disableStepperInput: Boolean,
|
disableStepperInput: Boolean,
|
||||||
@ -157,9 +165,13 @@ export default create({
|
|||||||
type: Number,
|
type: Number,
|
||||||
default: 200
|
default: 200
|
||||||
},
|
},
|
||||||
messagePlaceholderMap: {
|
messageConfig: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({})
|
default: () => ({
|
||||||
|
placeholderMap: {},
|
||||||
|
uploadImg: () => Promise.resolve(),
|
||||||
|
uploadMaxSize: 5
|
||||||
|
})
|
||||||
},
|
},
|
||||||
customStepperConfig: {
|
customStepperConfig: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<img class="van-sku__goods-img" :src="goodsImg" >
|
<img class="van-sku__goods-img" :src="goodsImg" >
|
||||||
</div>
|
</div>
|
||||||
<div class="van-sku-header__goods-info">
|
<div class="van-sku-header__goods-info">
|
||||||
<div class="van-sku__goods-name">{{ goods.title }}</div>
|
<div class="van-sku__goods-name van-ellipsis">{{ goods.title }}</div>
|
||||||
<div class="van-sku__goods-price"><span class="van-sku__price-symbol">¥</span><span class="van-sku__price-num">{{ price }}</span></div>
|
<div class="van-sku__goods-price"><span class="van-sku__price-symbol">¥</span><span class="van-sku__price-num">{{ price }}</span></div>
|
||||||
<span class="van-sku__close-icon" @click="skuEventBus.$emit('sku:close')" />
|
<span class="van-sku__close-icon" @click="skuEventBus.$emit('sku:close')" />
|
||||||
</div>
|
</div>
|
||||||
|
122
packages/sku/components/SkuImgUploader.vue
Normal file
122
packages/sku/components/SkuImgUploader.vue
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<template>
|
||||||
|
<div class="van-sku-img-uploader">
|
||||||
|
<!-- 头部 -->
|
||||||
|
<van-uploader
|
||||||
|
:disabled="!canUpload"
|
||||||
|
:before-read="beforeReadFile"
|
||||||
|
:after-read="afterReadFile"
|
||||||
|
accept="image/*">
|
||||||
|
<div class="van-sku-img-uploader__header">
|
||||||
|
<div v-if="paddingImg">{{ $t('uploading') }}</div>
|
||||||
|
<template v-else>
|
||||||
|
<van-icon name="photograph" />
|
||||||
|
<span class="label">{{ getPhotoText(value) }}</span> {{ $t('or') }}
|
||||||
|
<van-icon name="photo" />
|
||||||
|
<span class="label">{{ getPicText(value) }}</span>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</van-uploader>
|
||||||
|
<!-- 图片列表区域 -->
|
||||||
|
<div class="van-sku-img-uploader__imglist" v-if="paddingImg || imgList.length > 0">
|
||||||
|
<!-- 已有的图片,图片右上角显示删除按钮 -->
|
||||||
|
<div
|
||||||
|
v-for="(img, index) in imgList"
|
||||||
|
:key="index"
|
||||||
|
class="van-sku-img-uploader__img-container">
|
||||||
|
<span class="van-sku-img-uploader__delete-picture" @click="deleteImg(index)">
|
||||||
|
<van-icon name="clear" />
|
||||||
|
</span>
|
||||||
|
<img :src="img">
|
||||||
|
</div>
|
||||||
|
<!-- 正在上传的图片,有上传等待提示 -->
|
||||||
|
<div
|
||||||
|
v-if="paddingImg"
|
||||||
|
class="van-sku-img-uploader__img-container">
|
||||||
|
<img :src="paddingImg">
|
||||||
|
<van-loading class="van-sku-img-uploader__uploading" type="spinner" color="black" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Icon from '../../icon';
|
||||||
|
import Uploader from '../../uploader';
|
||||||
|
import Loading from '../../loading';
|
||||||
|
import { create } from '../../utils';
|
||||||
|
|
||||||
|
export default create({
|
||||||
|
name: 'van-sku-img-uploader',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
'van-uploader': Uploader,
|
||||||
|
'van-icon': Icon,
|
||||||
|
'van-loading': Loading
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
value: String,
|
||||||
|
uploadImg: {
|
||||||
|
type: Function,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
maxSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 正在上传的图片base 64
|
||||||
|
paddingImg: ''
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
imgList() {
|
||||||
|
return this.value && !this.paddingImg ? [this.value] : [];
|
||||||
|
},
|
||||||
|
canUpload() {
|
||||||
|
// 判断当前是否允许上传图片
|
||||||
|
if (this.paddingImg) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
getPhotoText(value) {
|
||||||
|
return value ? this.$t('rephoto') : this.$t('photo');
|
||||||
|
},
|
||||||
|
|
||||||
|
getPicText(value) {
|
||||||
|
return value ? this.$t('reselect') : this.$t('select');
|
||||||
|
},
|
||||||
|
beforeReadFile(file) {
|
||||||
|
// 拦截非图片的文件,以及大小限制
|
||||||
|
if (file.size > this.maxSize * 1024 * 1024) {
|
||||||
|
Toast(this.$t('maxSize', this.maxSize));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
afterReadFile(file) {
|
||||||
|
// 上传文件
|
||||||
|
this.paddingImg = file.content;
|
||||||
|
this.uploadImg(file.file).then(img => {
|
||||||
|
this.updateImg(img);
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.paddingImg = '';
|
||||||
|
});
|
||||||
|
}).catch(() => {
|
||||||
|
this.paddingImg = '';
|
||||||
|
});
|
||||||
|
},
|
||||||
|
deleteImg() {
|
||||||
|
this.$emit('input', '');
|
||||||
|
},
|
||||||
|
updateImg(img) {
|
||||||
|
this.$emit('input', img);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
@ -1,14 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<cell-group class="van-sku-messages">
|
<cell-group class="van-sku-messages">
|
||||||
<field
|
<template v-for="(message, index) in messages">
|
||||||
v-for="(message, index) in internalMessages"
|
<cell
|
||||||
v-model="messageValues[index]"
|
v-if="message.type === 'image'"
|
||||||
:key="`${goodsId}-${index}`"
|
class="van-sku-messages__image-cell"
|
||||||
:required="message.required == '1'"
|
:label="$t('onePic')"
|
||||||
:label="message.name"
|
:key="`${goodsId}-${index}`"
|
||||||
:placeholder="getPlaceholder(message)"
|
:required="message.required == '1'"
|
||||||
:type="getType(message)"
|
:title="message.name">
|
||||||
/>
|
<sku-img-uploader
|
||||||
|
v-model="messageValues[index].value"
|
||||||
|
:upload-img="messageConfig.uploadImg"
|
||||||
|
:max-size="messageConfig.uploadMaxSize"
|
||||||
|
/>
|
||||||
|
</cell>
|
||||||
|
<field
|
||||||
|
v-else
|
||||||
|
v-model="messageValues[index].value"
|
||||||
|
:key="`${goodsId}-${index}`"
|
||||||
|
:required="message.required == '1'"
|
||||||
|
:label="message.name"
|
||||||
|
:placeholder="getPlaceholder(message)"
|
||||||
|
:type="getType(message)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
</cell-group>
|
</cell-group>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -16,30 +31,36 @@
|
|||||||
import { create } from '../../utils';
|
import { create } from '../../utils';
|
||||||
import Field from '../../field';
|
import Field from '../../field';
|
||||||
import CellGroup from '../../cell-group';
|
import CellGroup from '../../cell-group';
|
||||||
|
import Cell from '../../cell';
|
||||||
import validateEmail from '../../utils/validate/email';
|
import validateEmail from '../../utils/validate/email';
|
||||||
import validateNumber from '../../utils/validate/number';
|
import validateNumber from '../../utils/validate/number';
|
||||||
|
import SkuImgUploader from './SkuImgUploader';
|
||||||
|
|
||||||
export default create({
|
export default create({
|
||||||
name: 'van-sku-messages',
|
name: 'van-sku-messages',
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
|
SkuImgUploader,
|
||||||
Field,
|
Field,
|
||||||
|
Cell,
|
||||||
CellGroup
|
CellGroup
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
messages: Array,
|
messages: Array,
|
||||||
messagePlaceholderMap: Object,
|
messageConfig: Object,
|
||||||
goodsId: [Number, String]
|
goodsId: [Number, String]
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
data() {
|
||||||
internalMessages() {
|
return {
|
||||||
return Array.isArray(this.messages) ? this.messages.filter(message => message.type !== 'image') : [];
|
messageValues: this.messages.map(() => ({ value: '' }))
|
||||||
},
|
};
|
||||||
|
},
|
||||||
|
|
||||||
messageValues() {
|
computed: {
|
||||||
return this.internalMessages.map(() => '');
|
messagePlaceholderMap() {
|
||||||
|
return this.messageConfig.placeholderMap || {};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -57,8 +78,9 @@ export default create({
|
|||||||
getMessages() {
|
getMessages() {
|
||||||
const messages = {};
|
const messages = {};
|
||||||
|
|
||||||
this.messageValues.forEach((value, index) => {
|
this.messageValues.forEach((item, index) => {
|
||||||
if (this.internalMessages[index].datetime > 0) {
|
let value = item.value;
|
||||||
|
if (this.messages[index].datetime > 0) {
|
||||||
value = value.replace(/T/g, ' ');
|
value = value.replace(/T/g, ' ');
|
||||||
}
|
}
|
||||||
messages[`message_${index}`] = value;
|
messages[`message_${index}`] = value;
|
||||||
@ -70,8 +92,9 @@ export default create({
|
|||||||
getCartMessages() {
|
getCartMessages() {
|
||||||
const messages = {};
|
const messages = {};
|
||||||
|
|
||||||
this.messageValues.forEach((value, index) => {
|
this.messageValues.forEach((item, index) => {
|
||||||
const message = this.internalMessages[index];
|
let value = item.value;
|
||||||
|
const message = this.messages[index];
|
||||||
if (message.datetime > 0) {
|
if (message.datetime > 0) {
|
||||||
value = value.replace(/T/g, ' ');
|
value = value.replace(/T/g, ' ');
|
||||||
}
|
}
|
||||||
@ -90,17 +113,16 @@ export default create({
|
|||||||
const values = this.messageValues;
|
const values = this.messageValues;
|
||||||
|
|
||||||
for (let i = 0; i < values.length; i++) {
|
for (let i = 0; i < values.length; i++) {
|
||||||
const value = values[i];
|
const value = values[i].value;
|
||||||
const message = this.internalMessages[i];
|
const message = this.messages[i];
|
||||||
|
|
||||||
if (value === '') {
|
if (value === '') {
|
||||||
// 必填字段的校验
|
// 必填字段的校验
|
||||||
if (message.required == '1') { // eslint-disable-line
|
if (message.required == '1') { // eslint-disable-line
|
||||||
if (message.type === 'image') {
|
const textType = message.type === 'image'
|
||||||
continue;
|
? 'upload'
|
||||||
} else {
|
: 'fill';
|
||||||
return this.$t('fill') + message.name;
|
return this.$t(textType) + message.name;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (message.type === 'tel' && !validateNumber(value)) {
|
if (message.type === 'tel' && !validateNumber(value)) {
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
:max="stepperLimit"
|
:max="stepperLimit"
|
||||||
:disable-input="disableStepperInput"
|
:disable-input="disableStepperInput"
|
||||||
@overlimit="onOverLimit"
|
@overlimit="onOverLimit"
|
||||||
|
@change="onChange"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!hideStock" class="van-sku__stock">{{ $t('remain', stock) }}</div>
|
<div v-if="!hideStock" class="van-sku__stock">{{ $t('remain', stock) }}</div>
|
||||||
@ -104,7 +105,6 @@ export default create({
|
|||||||
setCurrentNum(num) {
|
setCurrentNum(num) {
|
||||||
this.currentNum = num;
|
this.currentNum = num;
|
||||||
},
|
},
|
||||||
|
|
||||||
onOverLimit(action) {
|
onOverLimit(action) {
|
||||||
this.skuEventBus.$emit('sku:overLimit', {
|
this.skuEventBus.$emit('sku:overLimit', {
|
||||||
action,
|
action,
|
||||||
@ -112,6 +112,10 @@ export default create({
|
|||||||
quota: this.quota,
|
quota: this.quota,
|
||||||
quotaUsed: this.quotaUsed
|
quotaUsed: this.quotaUsed
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
onChange(currentValue) {
|
||||||
|
const { handleStepperChange } = this.customStepperConfig;
|
||||||
|
handleStepperChange && handleStepperChange(currentValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="van-steps__message">
|
<div class="van-steps__message">
|
||||||
<div class="van-steps__title" v-text="title" />
|
<div class="van-steps__title" v-text="title" />
|
||||||
<div class="van-steps__desc" v-text="description" />
|
<div class="van-steps__desc van-ellipsis" v-text="description" />
|
||||||
</div>
|
</div>
|
||||||
<slot name="message-extra" />
|
<slot name="message-extra" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
@click="onClick(index)"
|
@click="onClick(index)"
|
||||||
>
|
>
|
||||||
<van-node v-if="tab.$slots.title" :node="tab.$slots.title" />
|
<van-node v-if="tab.$slots.title" :node="tab.$slots.title" />
|
||||||
<span v-else>{{ tab.title }}</span>
|
<span class="van-ellipsis" v-else>{{ tab.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<div class="van-tree-select__nav">
|
<div class="van-tree-select__nav">
|
||||||
<div
|
<div
|
||||||
v-for="(item, index) in items"
|
v-for="(item, index) in items"
|
||||||
class="van-tree-select__nitem"
|
class="van-tree-select__nitem van-ellipsis"
|
||||||
:class="{ 'van-tree-select__nitem--active': mainActiveIndex === index }"
|
:class="{ 'van-tree-select__nitem--active': mainActiveIndex === index }"
|
||||||
@click="$emit('navclick', index)">
|
@click="$emit('navclick', index)">
|
||||||
{{ item.text }}
|
{{ item.text }}
|
||||||
@ -13,7 +13,7 @@
|
|||||||
<div
|
<div
|
||||||
v-for="item in subItems"
|
v-for="item in subItems"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
class="van-tree-select__item"
|
class="van-tree-select__item van-ellipsis"
|
||||||
:class="{ 'van-tree-select__item--active': activeId === item.id }"
|
:class="{ 'van-tree-select__item--active': activeId === item.id }"
|
||||||
@click="onItemSelect(item)">
|
@click="onItemSelect(item)">
|
||||||
{{ item.text }}
|
{{ item.text }}
|
||||||
|
@ -4,5 +4,6 @@
|
|||||||
|
|
||||||
@import "./common/var.css";
|
@import "./common/var.css";
|
||||||
@import "./common/normalize.css";
|
@import "./common/normalize.css";
|
||||||
|
@import "./common/ellipsis.css";
|
||||||
@import "./common/hairline.css";
|
@import "./common/hairline.css";
|
||||||
@import "./common/animation.css";
|
@import "./common/animation.css";
|
||||||
|
32
packages/vant-css/src/circle.css
Normal file
32
packages/vant-css/src/circle.css
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
@import './common/var.css';
|
||||||
|
|
||||||
|
.van-circle {
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__layer {
|
||||||
|
fill: none;
|
||||||
|
stroke-dasharray: 3140px;
|
||||||
|
stroke-dashoffset: 3140px;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
transform-origin: 530px 530px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
color: $text-color;
|
||||||
|
position: absolute;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
}
|
5
packages/vant-css/src/common/ellipsis.css
Normal file
5
packages/vant-css/src/common/ellipsis.css
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
@import '../mixins/ellipsis.css';
|
||||||
|
|
||||||
|
.van-ellipsis {
|
||||||
|
@mixin ellipsis;
|
||||||
|
}
|
@ -12,7 +12,7 @@
|
|||||||
@import './badge.css';
|
@import './badge.css';
|
||||||
@import './button.css';
|
@import './button.css';
|
||||||
@import './cell.css';
|
@import './cell.css';
|
||||||
@import './card.css';
|
@import './circle.css';
|
||||||
@import './loading.css';
|
@import './loading.css';
|
||||||
@import './nav-bar.css';
|
@import './nav-bar.css';
|
||||||
@import './notice-bar.css';
|
@import './notice-bar.css';
|
||||||
@ -53,6 +53,7 @@
|
|||||||
/* business components */
|
/* business components */
|
||||||
@import './address-edit.css';
|
@import './address-edit.css';
|
||||||
@import './address-list.css';
|
@import './address-list.css';
|
||||||
|
@import './card.css';
|
||||||
@import './contact-card.css';
|
@import './contact-card.css';
|
||||||
@import './contact-list.css';
|
@import './contact-list.css';
|
||||||
@import './contact-edit.css';
|
@import './contact-edit.css';
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
@import './common/var.css';
|
@import './common/var.css';
|
||||||
@import './mixins/ellipsis.css';
|
|
||||||
|
|
||||||
.van-picker {
|
.van-picker {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -7,8 +6,10 @@
|
|||||||
background-color: $white;
|
background-color: $white;
|
||||||
|
|
||||||
&__toolbar {
|
&__toolbar {
|
||||||
|
display: flex;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__cancel,
|
&__cancel,
|
||||||
@ -21,17 +22,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__cancel {
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__confirm {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__title {
|
&__title {
|
||||||
|
max-width: 50%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@mixin ellipsis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&__columns {
|
&__columns {
|
||||||
@ -52,13 +45,12 @@
|
|||||||
&-column {
|
&-column {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-size: 18px;
|
font-size: 17px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
padding: 0 10px;
|
padding: 0 5px;
|
||||||
color: $gray-darker;
|
color: $gray-darker;
|
||||||
@mixin ellipsis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
li&--selected {
|
li&--selected {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
@import './common/var.css';
|
@import './common/var.css';
|
||||||
|
@import './mixins/clearfix.css';
|
||||||
|
|
||||||
.van-sku {
|
.van-sku {
|
||||||
&-container {
|
&-container {
|
||||||
@ -67,9 +68,6 @@
|
|||||||
|
|
||||||
&__goods-name {
|
&__goods-name {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&__price-symbol {
|
&__price-symbol {
|
||||||
@ -147,7 +145,7 @@
|
|||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__stepper {
|
&__stepper {
|
||||||
top: 7px;
|
top: 7px;
|
||||||
left: 4px;
|
left: 4px;
|
||||||
@ -166,13 +164,85 @@
|
|||||||
color: $gray-dark;
|
color: $gray-dark;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__quota {
|
&__quota {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
color: $red;
|
color: $red;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-messages {
|
||||||
|
&__image-cell {
|
||||||
|
.van-cell__title {
|
||||||
|
width: 90px;
|
||||||
|
}
|
||||||
|
.van-cell__value {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-img-uploader {
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
&__header {
|
||||||
|
padding: 0 10px;
|
||||||
|
border: 1px solid #e5e5e5;
|
||||||
|
line-height: 24px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
.van-icon {
|
||||||
|
top: 3px;
|
||||||
|
margin-right: 5px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__imglist {
|
||||||
|
@mixin clearfix;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__img-container {
|
||||||
|
height: 60px;
|
||||||
|
width: 60px;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
float: left;
|
||||||
|
position: relative;
|
||||||
|
border: #e5e5e5 1px solid;
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
top: 50%;
|
||||||
|
position: relative;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__delete-picture {
|
||||||
|
position: absolute;
|
||||||
|
color: $red;
|
||||||
|
top: -10px;
|
||||||
|
right: -17px;
|
||||||
|
z-index: 1;
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__uploading {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
margin: auto;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* sku actions */
|
/* sku actions */
|
||||||
&-actions {
|
&-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
@import './common/var.css';
|
@import './common/var.css';
|
||||||
@import './mixins/ellipsis.css';
|
|
||||||
|
|
||||||
.van-steps {
|
.van-steps {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -49,7 +48,6 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
color: $gray-dark;
|
color: $gray-dark;
|
||||||
@mixin ellipsis;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
@import './common/var.css';
|
@import './common/var.css';
|
||||||
@import './mixins/ellipsis.css';
|
|
||||||
|
|
||||||
$van-tabs-line-height: 44px;
|
$van-tabs-line-height: 44px;
|
||||||
$van-tabs-card-height: 30px;
|
$van-tabs-card-height: 30px;
|
||||||
@ -118,7 +117,6 @@ $van-tabs-card-height: 30px;
|
|||||||
|
|
||||||
span {
|
span {
|
||||||
display: block;
|
display: block;
|
||||||
@mixin ellipsis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
line-height: 44px;
|
line-height: 44px;
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
@mixin ellipsis;
|
|
||||||
|
|
||||||
&--active {
|
&--active {
|
||||||
background-color: $background-color;
|
background-color: $background-color;
|
||||||
@ -41,7 +40,6 @@
|
|||||||
line-height: 44px;
|
line-height: 44px;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
padding-right: 18px;
|
padding-right: 18px;
|
||||||
@mixin ellipsis;
|
|
||||||
|
|
||||||
&--active {
|
&--active {
|
||||||
color: $button-danger-background-color;
|
color: $button-danger-background-color;
|
||||||
@ -54,5 +52,6 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
line-height: inherit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
65
test/unit/specs/circle.spec.js
Normal file
65
test/unit/specs/circle.spec.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { mount } from 'avoriaz';
|
||||||
|
import Circle from 'packages/circle';
|
||||||
|
|
||||||
|
describe('Circle', () => {
|
||||||
|
let wrapper;
|
||||||
|
afterEach(() => {
|
||||||
|
wrapper && wrapper.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('create a circle', () => {
|
||||||
|
wrapper = mount(Circle, {
|
||||||
|
propsData: {
|
||||||
|
text: 'test'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper.hasClass('van-circle')).to.be.true;
|
||||||
|
expect(wrapper.find('.van-circle__text')[0].text()).to.equal('test');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('circle rate', done => {
|
||||||
|
let currentRate = 0;
|
||||||
|
wrapper = mount(Circle, {
|
||||||
|
propsData: {
|
||||||
|
rate: 0,
|
||||||
|
value: 0,
|
||||||
|
clockwise: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
wrapper.vm.$on('input', rate => {
|
||||||
|
currentRate = rate;
|
||||||
|
});
|
||||||
|
wrapper.vm.rate = 50;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(currentRate).to.equal(50);
|
||||||
|
done();
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('circle animation', done => {
|
||||||
|
let currentRate = 0;
|
||||||
|
wrapper = mount(Circle, {
|
||||||
|
propsData: {
|
||||||
|
rate: 0,
|
||||||
|
value: 0,
|
||||||
|
speed: 500,
|
||||||
|
clockwise: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
wrapper.vm.$on('input', rate => {
|
||||||
|
currentRate = rate;
|
||||||
|
});
|
||||||
|
wrapper.vm.rate = 50;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(currentRate === 50).to.be.false;
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(currentRate === 50).to.be.true;
|
||||||
|
done();
|
||||||
|
}, 200);
|
||||||
|
}, 50);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -22,7 +22,10 @@ describe('Popup', () => {
|
|||||||
it('create a show popup', (done) => {
|
it('create a show popup', (done) => {
|
||||||
wrapper = mount(Popup, {
|
wrapper = mount(Popup, {
|
||||||
propsData: {
|
propsData: {
|
||||||
value: false
|
value: false,
|
||||||
|
zIndex: 100,
|
||||||
|
overlay: false,
|
||||||
|
lockOnScroll: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -125,4 +128,23 @@ describe('Popup', () => {
|
|||||||
|
|
||||||
expect(wrapper.vm.lockOnScroll).to.be.true;
|
expect(wrapper.vm.lockOnScroll).to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('get container prop', done => {
|
||||||
|
const testNode = document.createElement('div');
|
||||||
|
document.body.appendChild(testNode);
|
||||||
|
|
||||||
|
wrapper = mount(Popup, {
|
||||||
|
propsData: {
|
||||||
|
getContainer: () => testNode
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper.vm.$el.parentNode === testNode).to.be.true;
|
||||||
|
wrapper.vm.getContainer = () => document.body;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(wrapper.vm.$el.parentNode === document.body).to.be.true;
|
||||||
|
done();
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import Sku from 'packages/sku';
|
import Sku from 'packages/sku';
|
||||||
|
import Uploader from 'packages/uploader';
|
||||||
import Toast from 'packages/toast';
|
import Toast from 'packages/toast';
|
||||||
import { mount } from 'avoriaz';
|
import { mount } from 'avoriaz';
|
||||||
import { DOMChecker } from '../utils';
|
import { DOMChecker } from '../utils';
|
||||||
@ -13,6 +14,13 @@ const initialSku = {
|
|||||||
};
|
};
|
||||||
goods.picture = goods.picture[0];
|
goods.picture = goods.picture[0];
|
||||||
|
|
||||||
|
const File = function() {
|
||||||
|
this.name = 'test';
|
||||||
|
this.size = 10000;
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockFile = new File([], '/Users');
|
||||||
|
|
||||||
describe('Sku', (done) => {
|
describe('Sku', (done) => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -239,7 +247,15 @@ describe('Sku', (done) => {
|
|||||||
value: true,
|
value: true,
|
||||||
sku: data.sku,
|
sku: data.sku,
|
||||||
goodsId: data.goods_id,
|
goodsId: data.goods_id,
|
||||||
goods: goods
|
goods: goods,
|
||||||
|
messageConfig: {
|
||||||
|
uploadImg: () => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => resolve('https://img.yzcdn.cn/upload_files/2017/02/21/FjKTOxjVgnUuPmHJRdunvYky9OHP.jpg!100x100.jpg'), 1000);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
uploadMaxSize: 3
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -247,12 +263,15 @@ describe('Sku', (done) => {
|
|||||||
const skuMessages = wrapper.find('.van-sku-messages')[0];
|
const skuMessages = wrapper.find('.van-sku-messages')[0];
|
||||||
const inputs = skuMessages.find('input');
|
const inputs = skuMessages.find('input');
|
||||||
const textarea = skuMessages.find('textarea')[0];
|
const textarea = skuMessages.find('textarea')[0];
|
||||||
|
const uploader = wrapper.find(Uploader)[0];
|
||||||
// 修改留言内容
|
// 修改留言内容
|
||||||
inputs[0].element.value = 123;
|
inputs[0].element.value = 123;
|
||||||
// 测试身份证号
|
// 测试身份证号
|
||||||
inputs[1].element.value = 234;
|
inputs[1].element.value = 234;
|
||||||
inputs[0].trigger('input');
|
inputs[0].trigger('input');
|
||||||
inputs[1].trigger('input');
|
inputs[1].trigger('input');
|
||||||
|
// 测试图片
|
||||||
|
uploader.vm.onChange({ target: { files: [mockFile] }});
|
||||||
|
|
||||||
wrapper.vm.$nextTick(() => {
|
wrapper.vm.$nextTick(() => {
|
||||||
// 点击购买
|
// 点击购买
|
||||||
@ -276,9 +295,9 @@ describe('Sku', (done) => {
|
|||||||
|
|
||||||
textarea.element.value = '';
|
textarea.element.value = '';
|
||||||
// 测试数字留言
|
// 测试数字留言
|
||||||
inputs[2].element.value = 'abc';
|
inputs[3].element.value = 'abc';
|
||||||
textarea.trigger('input');
|
textarea.trigger('input');
|
||||||
inputs[2].trigger('input');
|
inputs[3].trigger('input');
|
||||||
|
|
||||||
wrapper.vm.$nextTick(() => {
|
wrapper.vm.$nextTick(() => {
|
||||||
buyBtn.trigger('click');
|
buyBtn.trigger('click');
|
||||||
@ -286,10 +305,10 @@ describe('Sku', (done) => {
|
|||||||
wrapper.vm.$nextTick(() => {
|
wrapper.vm.$nextTick(() => {
|
||||||
expect(toastText.textContent).to.equal('请填写正确的数字格式留言');
|
expect(toastText.textContent).to.equal('请填写正确的数字格式留言');
|
||||||
|
|
||||||
inputs[2].element.value = 0;
|
inputs[3].element.value = 0;
|
||||||
inputs[3].element.value = 345;
|
inputs[4].element.value = 345;
|
||||||
inputs[2].trigger('input');
|
|
||||||
inputs[3].trigger('input');
|
inputs[3].trigger('input');
|
||||||
|
inputs[4].trigger('input');
|
||||||
|
|
||||||
wrapper.vm.$nextTick(() => {
|
wrapper.vm.$nextTick(() => {
|
||||||
buyBtn.trigger('click');
|
buyBtn.trigger('click');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user