chore: merge branch "dev"

This commit is contained in:
陈嘉涵 2019-12-02 11:05:15 +08:00
commit 9302cae9ba
38 changed files with 502 additions and 116 deletions

View File

@ -1,5 +1,47 @@
# Changelog # Changelog
### [v2.3.0-beta.1](https://github.com/youzan/vant/tree/v2.3.0-beta.1)
`2019-11-30`
**Style**
Upgrading the style of business components:
- AddressEdit
- Card
- ContactList
- ContactCard
- ContactEdit
- SubmitBar
**Features**
- Card: add price-top slot [\#5134](https://github.com/youzan/vant/pull/5134)
- Circle: add stroke-linecap prop [\#5087](https://github.com/youzan/vant/pull/5087)
- CountDown: support SS and S format [\#5154](https://github.com/youzan/vant/pull/5154)
- Sku: add new startSaleNum prop [\#5105](https://github.com/youzan/vant/pull/5105)
- SubmitBar: add text-align prop [\#5130](https://github.com/youzan/vant/pull/5130)
- AddressList: add default-tag-text prop [\#5106](https://github.com/youzan/vant/pull/5106)
- ContactList: add default-tag-text prop [\#5089](https://github.com/youzan/vant/pull/5089)
- ContactCard: add show-set-default prop [\#5083](https://github.com/youzan/vant/pull/5083)
- Toast: improve type definitions [\#5086](https://github.com/youzan/vant/pull/5086)
**Bug Fixes**
- fix TreeSelect should sync value before trigger click-item event [\#5153](https://github.com/youzan/vant/pull/5153)
- fix TouchEmulator compatibility issues on firefox [\#5118](https://github.com/youzan/vant/pull/5118)
- fix Card allow use bottom slot without price or num [\#5116](https://github.com/youzan/vant/pull/5116)
- fix NumberKeyboard should not trigger blur event when hidden [\#5110](https://github.com/youzan/vant/pull/5110)
### [v2.2.15](https://github.com/youzan/vant/tree/v2.2.15)
`2019-11-28`
**Bug Fixes**
- fix List incorrect list status in some cases
### [v2.2.14](https://github.com/youzan/vant/tree/v2.2.14) ### [v2.2.14](https://github.com/youzan/vant/tree/v2.2.14)
`2019-11-22` `2019-11-22`

View File

@ -10,6 +10,49 @@ Vant 遵循 [Semver](https://semver.org/lang/zh-CN/) 语义化版本规范。
- 次版本号:每隔一至二个月发布,包含新特性和较大的功能更新,向下兼容。 - 次版本号:每隔一至二个月发布,包含新特性和较大的功能更新,向下兼容。
- 主版本号:发布时间不定,包含不兼容更新,预计下一个主版本会与 Vue 3.0 同期发布。 - 主版本号:发布时间不定,包含不兼容更新,预计下一个主版本会与 Vue 3.0 同期发布。
### [v2.3.0-beta.1](https://github.com/youzan/vant/tree/v2.3.0-beta.1)
`2019-11-30`
**Style**
在 2.3.0 版本中,我们对业务组件的样式进行了全新升级,涉及以下组件:
- AddressEdit
- Card
- ContactList
- ContactCard
- ContactEdit
- SubmitBar
**Features**
- Card: 新增 price-top 插槽 [\#5134](https://github.com/youzan/vant/pull/5134)
- Circle: 新增 stroke-linecap 属性 [\#5087](https://github.com/youzan/vant/pull/5087)
- CountDown: 支持 SS 和 S 格式 [\#5154](https://github.com/youzan/vant/pull/5154)
- Sku: 新增 new startSaleNum 属性 [\#5105](https://github.com/youzan/vant/pull/5105)
- SubmitBar: 新增 text-align 属性 [\#5130](https://github.com/youzan/vant/pull/5130)
- AddressList: 新增 default-tag-text 属性 [\#5106](https://github.com/youzan/vant/pull/5106)
- ContactList: 新增 default-tag-text 属性 [\#5089](https://github.com/youzan/vant/pull/5089)
- ContactCard: 新增 show-set-default 属性 [\#5083](https://github.com/youzan/vant/pull/5083)
- Toast: 完善 TS 类型定义 [\#5086](https://github.com/youzan/vant/pull/5086)
**Bug Fixes**
- 修复 TreeSelect 事件触发顺序错误的问题 [\#5153](https://github.com/youzan/vant/pull/5153)
- 修复 TouchEmulator 在 Firefox 上的兼容性问题 [\#5118](https://github.com/youzan/vant/pull/5118)
- 修复 Card 在未使用 price 属性的情况下 bottom 插槽不生效的问题 [\#5116](https://github.com/youzan/vant/pull/5116)
- 修复 NumberKeyboard 在隐藏状态下也会触发 blur 事件的问题 [\#5110](https://github.com/youzan/vant/pull/5110)
### [v2.2.15](https://github.com/youzan/vant/tree/v2.2.15)
`2019-11-28`
**Bug Fixes**
- 修复 List 组件在部分情况下加载状态未重置的问题
### [v2.2.14](https://github.com/youzan/vant/tree/v2.2.14) ### [v2.2.14](https://github.com/youzan/vant/tree/v2.2.14)
`2019-11-22` `2019-11-22`

View File

@ -1,6 +1,6 @@
{ {
"name": "vant", "name": "vant",
"version": "2.2.14", "version": "2.3.0-beta.1",
"description": "Mobile UI Components built on Vue", "description": "Mobile UI Components built on Vue",
"main": "lib/index.js", "main": "lib/index.js",
"module": "es/index.js", "module": "es/index.js",

View File

@ -94,6 +94,7 @@ Use slot to custom content.
| num | Custom num | | num | Custom num |
| price | Custom price | | price | Custom price |
| origin-price | Custom origin price | | origin-price | Custom origin price |
| price-top | Custom price top |
| bottom | Custom price bottom | | bottom | Custom price bottom |
| thumb | Custom thumb | | thumb | Custom thumb |
| tag | Custom thumb tag | | tag | Custom thumb tag |

View File

@ -96,6 +96,7 @@ Vue.use(Card);
| num | 自定义数量 | | num | 自定义数量 |
| price | 自定义价格 | | price | 自定义价格 |
| origin-price | 自定义商品原价 | | origin-price | 自定义商品原价 |
| price-top | 自定义价格上方区域 |
| bottom | 自定义价格下方区域 | | bottom | 自定义价格下方区域 |
| thumb | 自定义图片 | | thumb | 自定义图片 |
| tag | 自定义图片角标 | | tag | 自定义图片角标 |

View File

@ -22,6 +22,7 @@
width: @card-thumb-size; width: @card-thumb-size;
height: @card-thumb-size; height: @card-thumb-size;
margin-right: @padding-xs; margin-right: @padding-xs;
border-radius: @card-thumb-border-radius;
} }
&__content { &__content {
@ -29,6 +30,7 @@
display: flex; display: flex;
flex: 1; flex: 1;
flex-direction: column; flex-direction: column;
justify-content: space-between;
min-width: 0; /* hack for flex box ellipsis */ min-width: 0; /* hack for flex box ellipsis */
min-height: @card-thumb-size; min-height: @card-thumb-size;
@ -62,6 +64,11 @@
display: inline-block; display: inline-block;
color: @card-price-color; color: @card-price-color;
font-weight: @font-weight-bold; font-weight: @font-weight-bold;
&--integer {
font-size: @card-price-integer-font-size;
font-family: @card-price-font-family;
}
} }
&__origin-price { &__origin-price {
@ -74,6 +81,7 @@
&__num { &__num {
float: right; float: right;
color: @card-num-color;
} }
&__tag { &__tag {

View File

@ -32,6 +32,7 @@ export type CardSlots = DefaultSlots & {
bottom?: ScopedSlot; bottom?: ScopedSlot;
footer?: ScopedSlot; footer?: ScopedSlot;
'origin-price'?: ScopedSlot; 'origin-price'?: ScopedSlot;
'price-top'?: ScopedSlot;
}; };
export type CardEvents = { export type CardEvents = {
@ -114,11 +115,22 @@ function Card(
} }
} }
function PriceContent() {
const priceArr = props.price!.toString().split('.');
return (
<div>
{props.currency}
<span class={bem('price', 'integer')}>{priceArr[0]}</span>.
{priceArr[1]}
</div>
);
}
function Price() { function Price() {
if (showPrice) { if (showPrice) {
return ( return (
<div class={bem('price')}> <div class={bem('price')}>
{slots.price ? slots.price() : `${props.currency} ${props.price}`} {slots.price ? slots.price() : PriceContent()}
</div> </div>
); );
} }
@ -152,11 +164,14 @@ function Card(
<div class={bem('header')}> <div class={bem('header')}>
{Thumb()} {Thumb()}
<div class={bem('content', { centered: props.centered })}> <div class={bem('content', { centered: props.centered })}>
<div>
{Title()} {Title()}
{Desc()} {Desc()}
{slots.tags && slots.tags()} {slots.tags && slots.tags()}
</div>
{showBottom && ( {showBottom && (
<div class="van-card__bottom"> <div class="van-card__bottom">
{slots['price-top'] && slots['price-top']()}
{Price()} {Price()}
{OriginPrice()} {OriginPrice()}
{Num()} {Num()}

View File

@ -11,10 +11,14 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</a> </a>
<div class="van-card__content"> <div class="van-card__content">
<div>
<div class="van-card__title van-multi-ellipsis--l2">商品名称</div> <div class="van-card__title van-multi-ellipsis--l2">商品名称</div>
<div class="van-card__desc van-ellipsis">描述信息</div> <div class="van-card__desc van-ellipsis">描述信息</div>
</div>
<div class="van-card__bottom"> <div class="van-card__bottom">
<div class="van-card__price">¥ 2.00</div> <div class="van-card__price">
<div>¥<span class="van-card__price van-card__price--integer">2</span>.00</div>
</div>
<div class="van-card__num">x2</div> <div class="van-card__num">x2</div>
</div> </div>
</div> </div>
@ -31,10 +35,14 @@ exports[`renders demo correctly 1`] = `
<div class="van-card__tag"><span class="van-tag van-tag--mark van-tag--danger">标签</span></div> <div class="van-card__tag"><span class="van-tag van-tag--mark van-tag--danger">标签</span></div>
</a> </a>
<div class="van-card__content"> <div class="van-card__content">
<div>
<div class="van-card__title van-multi-ellipsis--l2">商品名称</div> <div class="van-card__title van-multi-ellipsis--l2">商品名称</div>
<div class="van-card__desc van-ellipsis">描述信息</div> <div class="van-card__desc van-ellipsis">描述信息</div>
</div>
<div class="van-card__bottom"> <div class="van-card__bottom">
<div class="van-card__price">¥ 2.00</div> <div class="van-card__price">
<div>¥<span class="van-card__price van-card__price--integer">2</span>.00</div>
</div>
<div class="van-card__origin-price">¥ 10.00</div> <div class="van-card__origin-price">¥ 10.00</div>
<div class="van-card__num">x2</div> <div class="van-card__num">x2</div>
</div> </div>
@ -51,6 +59,7 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</a> </a>
<div class="van-card__content"> <div class="van-card__content">
<div>
<div class="van-card__title van-multi-ellipsis--l2">商品名称</div> <div class="van-card__title van-multi-ellipsis--l2">商品名称</div>
<div class="van-card__desc van-ellipsis">描述信息</div> <div class="van-card__desc van-ellipsis">描述信息</div>
<div><span class="van-tag van-tag--plain van-tag--danger van-hairline--surround" style="margin-right: 5px;"> <div><span class="van-tag van-tag--plain van-tag--danger van-hairline--surround" style="margin-right: 5px;">
@ -58,8 +67,11 @@ exports[`renders demo correctly 1`] = `
</span> <span class="van-tag van-tag--plain van-tag--danger van-hairline--surround"> </span> <span class="van-tag van-tag--plain van-tag--danger van-hairline--surround">
标签 标签
</span></div> </span></div>
</div>
<div class="van-card__bottom"> <div class="van-card__bottom">
<div class="van-card__price">¥ 2.00</div> <div class="van-card__price">
<div>¥<span class="van-card__price van-card__price--integer">2</span>.00</div>
</div>
<div class="van-card__num">x2</div> <div class="van-card__num">x2</div>
</div> </div>
</div> </div>

View File

@ -4,6 +4,7 @@ exports[`render bottom slot 1`] = `
<div class="van-card"> <div class="van-card">
<div class="van-card__header"> <div class="van-card__header">
<div class="van-card__content"> <div class="van-card__content">
<div></div>
<div class="van-card__bottom">Custom Bottom</div> <div class="van-card__bottom">Custom Bottom</div>
</div> </div>
</div> </div>
@ -14,6 +15,7 @@ exports[`render origin-price slot 1`] = `
<div class="van-card"> <div class="van-card">
<div class="van-card__header"> <div class="van-card__header">
<div class="van-card__content"> <div class="van-card__content">
<div></div>
<div class="van-card__bottom"> <div class="van-card__bottom">
<div class="van-card__origin-price">Custom Origin Price</div> <div class="van-card__origin-price">Custom Origin Price</div>
</div> </div>
@ -26,6 +28,7 @@ exports[`render price & num slot 1`] = `
<div class="van-card"> <div class="van-card">
<div class="van-card__header"> <div class="van-card__header">
<div class="van-card__content"> <div class="van-card__content">
<div></div>
<div class="van-card__bottom"> <div class="van-card__bottom">
<div class="van-card__price">Custom Price</div> <div class="van-card__price">Custom Price</div>
<div class="van-card__num">Custom Num</div> <div class="van-card__num">Custom Num</div>
@ -38,7 +41,9 @@ exports[`render price & num slot 1`] = `
exports[`render thumb & tag slot 1`] = ` exports[`render thumb & tag slot 1`] = `
<div class="van-card"> <div class="van-card">
<div class="van-card__header"><a class="van-card__thumb">Custom Thumb<div class="van-card__tag">Custom Tag</div></a> <div class="van-card__header"><a class="van-card__thumb">Custom Thumb<div class="van-card__tag">Custom Tag</div></a>
<div class="van-card__content"></div> <div class="van-card__content">
<div></div>
</div>
</div> </div>
</div> </div>
`; `;
@ -46,7 +51,21 @@ exports[`render thumb & tag slot 1`] = `
exports[`render title & desc slot 1`] = ` exports[`render title & desc slot 1`] = `
<div class="van-card"> <div class="van-card">
<div class="van-card__header"> <div class="van-card__header">
<div class="van-card__content">Custom TitleCustom desc</div> <div class="van-card__content">
<div>Custom TitleCustom desc</div>
</div>
</div>
</div>
`;
exports[`render price & price-top slot 1`] = `
<div class="van-card">
<div class="van-card__header">
<div class="van-card__content">
<div></div>
<div class="van-card__bottom">Custom Price-top<div class="van-card__price">Custom Price</div>
</div>
</div>
</div> </div>
</div> </div>
`; `;

View File

@ -94,3 +94,14 @@ test('render title & desc slot', () => {
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
test('render price & price-top slot', () => {
const wrapper = mount(Card, {
scopedSlots: {
price: () => 'Custom Price',
'price-top': () => 'Custom Price-top'
}
});
expect(wrapper).toMatchSnapshot();
});

View File

@ -42,7 +42,7 @@ export default {
<van-count-down <van-count-down
millisecond millisecond
:time="time" :time="time"
format="HH:mm:ss:SSS" format="HH:mm:ss:SS"
/> />
``` ```
@ -114,10 +114,22 @@ export default {
| Attribute | Description | Type | Default | Version | | Attribute | Description | Type | Default | Version |
|------|------|------|------|------| |------|------|------|------|------|
| time | Total time | *number* | - | - | | time | Total time | *number* | - | - |
| format | Time formatDD-dayHH-hourmm-minutess-secondSSS-millisecond | *string* | `HH:mm:ss` | - | | format | Time format | *string* | `HH:mm:ss` | - |
| auto-start | Whether to auto start count down | *boolean* | `true` | - | | auto-start | Whether to auto start count down | *boolean* | `true` | - |
| millisecond | Whether to enable millisecond render | *boolean* | `false` | - | | millisecond | Whether to enable millisecond render | *boolean* | `false` | - |
### Available formats
| Format | Description |
|------|------|
| DD | Day |
| HH | Hour |
| mm | Minute |
| ss | Second |
| S | Millisecond, 1-digit |
| SS | Millisecond, 2-digits |
| SSS | Millisecond, 3-digits |
### Events ### Events
| Event | Description | Arguments | | Event | Description | Arguments |

View File

@ -48,7 +48,7 @@ export default {
<van-count-down <van-count-down
millisecond millisecond
:time="time" :time="time"
format="HH:mm:ss:SSS" format="HH:mm:ss:SS"
/> />
``` ```
@ -124,10 +124,22 @@ export default {
| 参数 | 说明 | 类型 | 默认值 | 版本 | | 参数 | 说明 | 类型 | 默认值 | 版本 |
|------|------|------|------|------| |------|------|------|------|------|
| time | 倒计时时长,单位毫秒 | *number* | - | - | | time | 倒计时时长,单位毫秒 | *number* | - | - |
| format | 时间格式DD-日HH-时mm-分ss-秒SSS-毫秒 | *string* | `HH:mm:ss` | - | | format | 时间格式 | *string* | `HH:mm:ss` | - |
| auto-start | 是否自动开始倒计时 | *boolean* | `true` | - | | auto-start | 是否自动开始倒计时 | *boolean* | `true` | - |
| millisecond | 是否开启毫秒级渲染 | *boolean* | `false` | - | | millisecond | 是否开启毫秒级渲染 | *boolean* | `false` | - |
### format 格式
| 格式 | 说明 |
|------|------|
| DD | 天数 |
| HH | 小时 |
| mm | 分钟 |
| ss | 秒数 |
| S | 毫秒1 位) |
| SS | 毫秒2 位) |
| SSS | 毫秒3 位) |
### Events ### Events
| 事件名 | 说明 | 回调参数 | | 事件名 | 说明 | 回调参数 |

View File

@ -15,7 +15,7 @@
<van-count-down <van-count-down
millisecond millisecond
:time="time" :time="time"
format="HH:mm:ss:SSS" format="HH:mm:ss:SS"
/> />
</demo-block> </demo-block>

View File

@ -5,3 +5,7 @@ exports[`complete format prop 1`] = `<div class="van-count-down">01-05-59-59-999
exports[`disable auto-start prop 1`] = `<div class="van-count-down">100</div>`; exports[`disable auto-start prop 1`] = `<div class="van-count-down">100</div>`;
exports[`incomplate format prop 1`] = `<div class="van-count-down">29-59-59-999</div>`; exports[`incomplate format prop 1`] = `<div class="van-count-down">29-59-59-999</div>`;
exports[`milliseconds format S 1`] = `<div class="van-count-down">01-5</div>`;
exports[`milliseconds format SS 1`] = `<div class="van-count-down">01-50</div>`;

View File

@ -141,6 +141,30 @@ test('complete format prop', () => {
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
test('milliseconds format SS', () => {
const wrapper = mount(CountDown, {
propsData: {
time: 1500,
autoStart: false,
format: 'ss-SS'
}
});
expect(wrapper).toMatchSnapshot();
});
test('milliseconds format S', () => {
const wrapper = mount(CountDown, {
propsData: {
time: 1500,
autoStart: false,
format: 'ss-S'
}
});
expect(wrapper).toMatchSnapshot();
});
test('incomplate format prop', () => { test('incomplate format prop', () => {
const wrapper = mount(CountDown, { const wrapper = mount(CountDown, {
propsData: { propsData: {

View File

@ -57,7 +57,19 @@ export function parseFormat(format: string, timeData: TimeData): string {
format = format.replace('ss', padZero(seconds)); format = format.replace('ss', padZero(seconds));
} }
return format.replace('SSS', padZero(milliseconds, 3)); if (format.indexOf('S') !== -1) {
const ms = padZero(milliseconds, 3);
if (format.indexOf('SSS') !== -1) {
format = format.replace('SSS', ms);
} else if (format.indexOf('SS') !== -1) {
format = format.replace('SS', ms.slice(0, 2));
} else {
format = format.replace('S', ms.charAt(0));
}
}
return format;
} }
export function isSameSecond(time1: number, time2: number): boolean { export function isSameSecond(time1: number, time2: number): boolean {

View File

@ -89,7 +89,7 @@ declare global {
} }
} }
const version = '2.2.14'; const version = '2.3.0-beta.1';
const components = [ const components = [
ActionSheet, ActionSheet,
AddressEdit, AddressEdit,

View File

@ -49,6 +49,10 @@ export default createComponent({
}; };
}, },
updated() {
this.innerLoading = this.loading;
},
mounted() { mounted() {
if (this.immediateCheck) { if (this.immediateCheck) {
this.check(); this.check();
@ -56,11 +60,8 @@ export default createComponent({
}, },
watch: { watch: {
finished: 'check', loading: 'check',
loading(val) { finished: 'check'
this.innerLoading = val;
this.check();
}
}, },
methods: { methods: {
@ -112,7 +113,7 @@ export default createComponent({
}, },
genLoading() { genLoading() {
if (this.innerLoading) { if (this.innerLoading && !this.finished) {
return ( return (
<div class={bem('loading')} key="loading"> <div class={bem('loading')} key="loading">
{this.slots('loading') || ( {this.slots('loading') || (

View File

@ -141,6 +141,7 @@ export default {
| message-config | Message related config | *object* | `{}` | - | | message-config | Message related config | *object* | `{}` | - |
| get-container | Return the mount node for sku | *string \| () => Element* | - | - | | get-container | Return the mount node for sku | *string \| () => Element* | - | - |
| safe-area-inset-bottom | Whether to enable bottom safe area adaptation | *boolean* | `false` | 2.2.1 | | safe-area-inset-bottom | Whether to enable bottom safe area adaptation | *boolean* | `false` | 2.2.1 |
| start-sale-num | Minimum quantity | *number* | `1` | 2.2.15 |
### Events ### Events
@ -258,10 +259,10 @@ customStepperConfig: {
quotaText: 'only 5 can buy', quotaText: 'only 5 can buy',
// custom callback when over limit // custom callback when over limit
handleOverLimit: (data) => { handleOverLimit: (data) => {
const { action, limitType, quota, quotaUsed } = data; const { action, limitType, quota, quotaUsed, startSaleNum } = data;
if (action === 'minus') { if (action === 'minus') {
Toast('at least select one'); Toast(`at least select ${startSaleNum > 1 ? startSaleNum : 'one'}`);
} else if (action === 'plus') { } else if (action === 'plus') {
// const { LIMIT_TYPE } = Sku.skuConstants; // const { LIMIT_TYPE } = Sku.skuConstants;
if (limitType === LIMIT_TYPE.QUOTA_LIMIT) { if (limitType === LIMIT_TYPE.QUOTA_LIMIT) {

View File

@ -145,6 +145,7 @@ export default {
| initial-sku | 默认选中的 sku具体参考高级用法 | *object* | `{}` | - | | initial-sku | 默认选中的 sku具体参考高级用法 | *object* | `{}` | - |
| show-soldout-sku | 是否展示售罄的 sku默认展示并置灰 | *boolean* | `true` | - | | show-soldout-sku | 是否展示售罄的 sku默认展示并置灰 | *boolean* | `true` | - |
| safe-area-inset-bottom | 是否开启底部安全区适配,[详细说明](#/zh-CN/quickstart#di-bu-an-quan-qu-gua-pei) | *boolean* | `false` | 2.2.1 | | safe-area-inset-bottom | 是否开启底部安全区适配,[详细说明](#/zh-CN/quickstart#di-bu-an-quan-qu-gua-pei) | *boolean* | `false` | 2.2.1 |
| start-sale-num | 起售数量 | *number* | `1` | 2.2.15 |
### Events ### Events
@ -270,10 +271,10 @@ customStepperConfig: {
quotaText: '每次限购xxx件', quotaText: '每次限购xxx件',
// 自定义步进器超过限制时的回调 // 自定义步进器超过限制时的回调
handleOverLimit: (data) => { handleOverLimit: (data) => {
const { action, limitType, quota, quotaUsed } = data; const { action, limitType, quota, quotaUsed, startSaleNum } = data;
if (action === 'minus') { if (action === 'minus') {
Toast('至少选择一件商品'); Toast(startSaleNum > 1 ? `${startSaleNum}件起售` : '至少选择一件商品');
} else if (action === 'plus') { } else if (action === 'plus') {
// const { LIMIT_TYPE } = Sku.skuConstants; // const { LIMIT_TYPE } = Sku.skuConstants;
if (limitType === LIMIT_TYPE.QUOTA_LIMIT) { if (limitType === LIMIT_TYPE.QUOTA_LIMIT) {

View File

@ -45,6 +45,10 @@ export default createComponent({
type: Number, type: Number,
default: 0 default: 0
}, },
startSaleNum: {
type: Number,
default: 1
},
initialSku: { initialSku: {
type: Object, type: Object,
default: () => ({}) default: () => ({})
@ -236,22 +240,6 @@ export default createComponent({
]; ];
}, },
quotaText() {
const { quotaText, hideQuotaText } = this.customStepperConfig;
if (hideQuotaText) return '';
let text = '';
if (quotaText) {
text = quotaText;
} else if (this.quota > 0) {
text = t('quotaLimit', this.quota);
}
return text;
},
selectedText() { selectedText() {
if (this.selectedSkuComb) { if (this.selectedSkuComb) {
return `${t('selected')} ${this.selectedSkuValues.map(item => item.name).join('')}`; return `${t('selected')} ${this.selectedSkuValues.map(item => item.name).join('')}`;
@ -274,6 +262,7 @@ export default createComponent({
skuEventBus.$on('sku:numChange', this.onNumChange); skuEventBus.$on('sku:numChange', this.onNumChange);
skuEventBus.$on('sku:previewImage', this.onPreviewImage); skuEventBus.$on('sku:previewImage', this.onPreviewImage);
skuEventBus.$on('sku:overLimit', this.onOverLimit); skuEventBus.$on('sku:overLimit', this.onOverLimit);
skuEventBus.$on('sku:stepperState', this.onStepperState);
skuEventBus.$on('sku:addCart', this.onAddCart); skuEventBus.$on('sku:addCart', this.onAddCart);
skuEventBus.$on('sku:buy', this.onBuy); skuEventBus.$on('sku:buy', this.onBuy);
@ -289,6 +278,8 @@ export default createComponent({
const { skuStepper } = this.$refs; const { skuStepper } = this.$refs;
const { selectedNum } = this.initialSku; const { selectedNum } = this.initialSku;
const num = isDef(selectedNum) ? selectedNum : 1; const num = isDef(selectedNum) ? selectedNum : 1;
// 用来缓存不合法的情况
this.stepperError = null;
if (skuStepper) { if (skuStepper) {
skuStepper.setCurrentNum(num); skuStepper.setCurrentNum(num);
@ -409,18 +400,35 @@ export default createComponent({
} }
if (action === 'minus') { if (action === 'minus') {
if (this.startSaleNum > 1) {
Toast(t('minusStartTip', this.startSaleNum));
} else {
Toast(t('minusTip')); Toast(t('minusTip'));
}
} else if (action === 'plus') { } else if (action === 'plus') {
if (limitType === QUOTA_LIMIT) { if (limitType === QUOTA_LIMIT) {
let msg = t('quotaLimit', quota); if (quotaUsed > 0) {
if (quotaUsed > 0) msg += `${t('quotaCount', quotaUsed)}`; Toast(t('quotaUsedTip', quota, quotaUsed));
Toast(msg); } else {
Toast(t('quotaTip', quota));
}
} else { } else {
Toast(t('soldout')); Toast(t('soldout'));
} }
} }
}, },
onStepperState(data) {
if (data.valid) {
this.stepperError = null;
} else {
this.stepperError = {
...data,
action: 'plus',
};
}
},
onAddCart() { onAddCart() {
this.onBuyOrAddCart('add-cart'); this.onBuyOrAddCart('add-cart');
}, },
@ -430,6 +438,10 @@ export default createComponent({
}, },
onBuyOrAddCart(type) { onBuyOrAddCart(type) {
// 有信息表示该sku根本不符合购买条件
if (this.stepperError) {
return this.onOverLimit(this.stepperError);
}
const error = this.validateSku(); const error = this.validateSku();
if (error) { if (error) {
Toast(error); Toast(error);
@ -463,7 +475,6 @@ export default createComponent({
selectedSku, selectedSku,
selectedNum, selectedNum,
stepperTitle, stepperTitle,
hideQuotaText,
selectedSkuComb selectedSkuComb
} = this; } = this;
@ -494,7 +505,6 @@ export default createComponent({
{!this.hideStock && ( {!this.hideStock && (
<SkuHeaderItem> <SkuHeaderItem>
<span class="van-sku__stock">{this.stockText}</span> <span class="van-sku__stock">{this.stockText}</span>
{!hideQuotaText && this.quotaText && <span class="van-sku__quota">({this.quotaText})</span>}
</SkuHeaderItem> </SkuHeaderItem>
)} )}
{this.hasSku && !this.hideSelectedText && ( {this.hasSku && !this.hideSelectedText && (
@ -530,6 +540,7 @@ export default createComponent({
stock={this.stock} stock={this.stock}
quota={this.quota} quota={this.quota}
quotaUsed={this.quotaUsed} quotaUsed={this.quotaUsed}
startSaleNum={this.startSaleNum}
skuEventBus={skuEventBus} skuEventBus={skuEventBus}
selectedNum={selectedNum} selectedNum={selectedNum}
selectedSku={selectedSku} selectedSku={selectedSku}
@ -537,6 +548,7 @@ export default createComponent({
skuStockNum={sku.stock_num} skuStockNum={sku.stock_num}
disableStepperInput={this.disableStepperInput} disableStepperInput={this.disableStepperInput}
customStepperConfig={this.customStepperConfig} customStepperConfig={this.customStepperConfig}
hideQuotaText={this.hideQuotaText}
onChange={event => { onChange={event => {
this.$emit('stepper-change', event); this.$emit('stepper-change', event);
}} }}

View File

@ -16,6 +16,7 @@ export default createComponent({
stepperTitle: String, stepperTitle: String,
disableStepperInput: Boolean, disableStepperInput: Boolean,
customStepperConfig: Object, customStepperConfig: Object,
hideQuotaText: Boolean,
quota: { quota: {
type: Number, type: Number,
default: 0 default: 0
@ -23,7 +24,11 @@ export default createComponent({
quotaUsed: { quotaUsed: {
type: Number, type: Number,
default: 0 default: 0
} },
startSaleNum: {
type: Number,
default: 1,
},
}, },
data() { data() {
@ -40,9 +45,17 @@ export default createComponent({
}, },
stepperLimit(limit) { stepperLimit(limit) {
if (limit < this.currentNum) { if (limit < this.currentNum && this.stepperMinLimit <= limit) {
this.currentNum = limit; this.currentNum = limit;
} }
this.checkState(this.stepperMinLimit, limit);
},
stepperMinLimit(start) {
if (start > this.currentNum || start > this.stepperLimit) {
this.currentNum = start;
}
this.checkState(start, this.stepperLimit);
} }
}, },
@ -62,7 +75,35 @@ export default createComponent({
} }
return limit; return limit;
},
stepperMinLimit() {
return this.startSaleNum < 1 ? 1 : this.startSaleNum;
},
quotaText() {
const { quotaText, hideQuotaText } = this.customStepperConfig;
if (hideQuotaText) return '';
let text = '';
if (quotaText) {
text = quotaText;
} else {
const textArr = [];
if (this.startSaleNum > 1) {
textArr.push(t('quotaStart', this.startSaleNum));
} }
if (this.quota > 0) {
textArr.push(t('quotaLimit', this.quota));
}
text = textArr.join(t('comma'));
}
return text;
},
},
created() {
this.checkState(this.stepperMinLimit, this.stepperLimit);
}, },
methods: { methods: {
@ -75,7 +116,8 @@ export default createComponent({
action, action,
limitType: this.limitType, limitType: this.limitType,
quota: this.quota, quota: this.quota,
quotaUsed: this.quotaUsed quotaUsed: this.quotaUsed,
startSaleNum: this.startSaleNum,
}); });
}, },
@ -83,7 +125,27 @@ export default createComponent({
const { handleStepperChange } = this.customStepperConfig; const { handleStepperChange } = this.customStepperConfig;
handleStepperChange && handleStepperChange(currentValue); handleStepperChange && handleStepperChange(currentValue);
this.$emit('change', currentValue); this.$emit('change', currentValue);
},
checkState(min, max) {
// 如果选择小于起售,则强制变为起售
if (this.currentNum < min || min > max) {
this.currentNum = min;
} else if (this.currentNum > max) {
// 当前选择数量大于最大可选时,需要重置已选数量
this.currentNum = max;
} }
this.skuEventBus.$emit('sku:stepperState', {
valid: min <= max,
min,
max,
limitType: this.limitType,
quota: this.quota,
quotaUsed: this.quotaUsed,
startSaleNum: this.startSaleNum,
});
},
}, },
render() { render() {
@ -94,11 +156,13 @@ export default createComponent({
<Stepper <Stepper
vModel={this.currentNum} vModel={this.currentNum}
class="van-sku__stepper" class="van-sku__stepper"
min={this.stepperMinLimit}
max={this.stepperLimit} max={this.stepperLimit}
disableInput={this.disableStepperInput} disableInput={this.disableStepperInput}
onOverlimit={this.onOverLimit} onOverlimit={this.onOverLimit}
onChange={this.onChange} onChange={this.onChange}
/> />
{!this.hideQuotaText && this.quotaText && <span class="van-sku__stepper-quota">({this.quotaText})</span>}
</div> </div>
</div> </div>
); );

View File

@ -2,6 +2,7 @@ export default {
goods_id: '946755', goods_id: '946755',
quota: 15, quota: 15,
quota_used: 0, quota_used: 0,
start_sale_num: 10,
goods_info: { goods_info: {
title: '测试商品', title: '测试商品',
picture: picture:

View File

@ -11,6 +11,7 @@
:hide-stock="skuData.sku.hide_stock" :hide-stock="skuData.sku.hide_stock"
:quota="skuData.quota" :quota="skuData.quota"
:quota-used="skuData.quota_used" :quota-used="skuData.quota_used"
:start-sale-num="skuData.start_sale_num"
:close-on-click-overlay="closeOnClickOverlay" :close-on-click-overlay="closeOnClickOverlay"
:message-config="messageConfig" :message-config="messageConfig"
:custom-sku-validator="customSkuValidator" :custom-sku-validator="customSkuValidator"
@ -42,6 +43,7 @@
:hide-stock="skuData.sku.hide_stock" :hide-stock="skuData.sku.hide_stock"
:quota="skuData.quota" :quota="skuData.quota"
:quota-used="skuData.quota_used" :quota-used="skuData.quota_used"
:start-sale-num="skuData.start_sale_num"
:custom-stepper-config="customStepperConfig" :custom-stepper-config="customStepperConfig"
:message-config="messageConfig" :message-config="messageConfig"
hide-quota-text hide-quota-text
@ -70,6 +72,7 @@
:hide-stock="skuData.sku.hide_stock" :hide-stock="skuData.sku.hide_stock"
:quota="skuData.quota" :quota="skuData.quota"
:quota-used="skuData.quota_used" :quota-used="skuData.quota_used"
:start-sale-num="skuData.start_sale_num"
:custom-stepper-config="customStepperConfig" :custom-stepper-config="customStepperConfig"
:message-config="messageConfig" :message-config="messageConfig"
:show-soldout-sku="false" :show-soldout-sku="false"
@ -99,6 +102,7 @@
:hide-stock="skuData.sku.hide_stock" :hide-stock="skuData.sku.hide_stock"
:quota="skuData.quota" :quota="skuData.quota"
:quota-used="skuData.quota_used" :quota-used="skuData.quota_used"
:start-sale-num="skuData.start_sale_num"
show-add-cart-btn show-add-cart-btn
reset-stepper-on-hide reset-stepper-on-hide
safe-area-inset-bottom safe-area-inset-bottom
@ -126,7 +130,7 @@
square square
size="large" size="large"
type="danger" type="danger"
@click="props.skuEventBus.$emit('sku:buy')" @click="skuEventBus.$emit('sku:buy')"
> >
{{ $t('button2') }} {{ $t('button2') }}
</van-button> </van-button>
@ -185,10 +189,10 @@ export default {
quotaText: '单次限购100件', quotaText: '单次限购100件',
stockFormatter: (stock) => `剩余${stock}`, stockFormatter: (stock) => `剩余${stock}`,
handleOverLimit: (data) => { handleOverLimit: (data) => {
const { action, limitType, quota } = data; const { action, limitType, quota, startSaleNum = 1 } = data;
if (action === 'minus') { if (action === 'minus') {
this.$toast('至少选择一件商品'); this.$toast(startSaleNum > 1 ? `${startSaleNum}件起售` : '至少选择一件商品');
} else if (action === 'plus') { } else if (action === 'plus') {
if (limitType === LIMIT_TYPE.QUOTA_LIMIT) { if (limitType === LIMIT_TYPE.QUOTA_LIMIT) {
this.$toast(`限购${quota}`); this.$toast(`限购${quota}`);

View File

@ -196,18 +196,28 @@
} }
&-container { &-container {
height: 30px; min-height: 30px;
margin-right: 20px; margin-right: 20px;
overflow: hidden;
} }
} }
&__stepper { &__stepper {
float: right; float: right;
padding-left: @padding-base;
&-title { &-title {
float: left; float: left;
line-height: 30px; line-height: 30px;
} }
&-quota {
display: inline-block;
float: right;
color: @red;
font-size: @font-size-sm;
line-height: 30px;
}
} }
&__stock { &__stock {
@ -221,12 +231,6 @@
} }
} }
&__quota {
display: inline-block;
color: @red;
font-size: @font-size-sm;
}
&-messages { &-messages {
padding-bottom: @padding-xl; padding-bottom: @padding-xl;

View File

@ -11,11 +11,12 @@ export default {
soldout: '库存不足', soldout: '库存不足',
originPrice: '原价', originPrice: '原价',
minusTip: '至少选择一件', minusTip: '至少选择一件',
minusStartTip: (start: number) => `${start}件起售`,
unavailable: '商品已经无法购买啦', unavailable: '商品已经无法购买啦',
stock: '剩余', stock: '剩余',
stockUnit: '件', stockUnit: '件',
quotaLimit: (quota: number) => `每人限购${quota}`, quotaTip: (quota: number) => `每人限购${quota}`,
quotaCount: (count: number) => `你已购买${count}` quotaUsedTip: (quota: number, count: number) => `每人限购${quota}件,你已购买${count}`
}, },
vanSkuActions: { vanSkuActions: {
buy: '立即购买', buy: '立即购买',
@ -26,6 +27,9 @@ export default {
fail: '上传失败<br />重新上传' fail: '上传失败<br />重新上传'
}, },
vanSkuStepper: { vanSkuStepper: {
quotaLimit: (quota: number) => `限购${quota}`,
quotaStart: (start: number) => `${start}件起售`,
comma: '',
num: '购买数量' num: '购买数量'
}, },
vanSkuMessages: { vanSkuMessages: {

View File

@ -42,6 +42,7 @@
@font-size-md: 14px; @font-size-md: 14px;
@font-size-lg: 16px; @font-size-lg: 16px;
@font-weight-bold: 500; @font-weight-bold: 500;
@price-integer-font-family: Avenir-Heavy PingFang SC, Helvetica Neue, Arial, sans-serif;
// Animation // Animation
@animation-duration-base: .3s; @animation-duration-base: .3s;
@ -52,6 +53,7 @@
@border-width-base: 1px; @border-width-base: 1px;
@border-radius-sm: 2px; @border-radius-sm: 2px;
@border-radius-md: 4px; @border-radius-md: 4px;
@border-radius-lg: 8px;
@border-radius-max: 999px; @border-radius-max: 999px;
// ActionSheet // ActionSheet
@ -137,13 +139,17 @@
@card-font-size: @font-size-sm; @card-font-size: @font-size-sm;
@card-text-color: @text-color; @card-text-color: @text-color;
@card-background-color: @background-color-light; @card-background-color: @background-color-light;
@card-thumb-size: 90px; @card-thumb-size: 88px;
@card-thumb-border-radius: @border-radius-lg;
@card-title-line-height: 16px; @card-title-line-height: 16px;
@card-desc-color: @gray-7; @card-desc-color: @gray-7;
@card-desc-line-height: 20px; @card-desc-line-height: 20px;
@card-price-color: @red; @card-price-color: @gray-8;
@card-origin-price-color: @gray-7; @card-origin-price-color: @gray-6;
@card-num-color: @gray-6;
@card-origin-price-font-size: @font-size-xs; @card-origin-price-font-size: @font-size-xs;
@card-price-integer-font-size: @font-size-lg;
@card-price-font-family: @price-integer-font-family;
// Cell // Cell
@cell-font-size: @font-size-md; @cell-font-size: @font-size-md;
@ -596,7 +602,7 @@
@submit-bar-background-color: @white; @submit-bar-background-color: @white;
@submit-bar-button-width: 110px; @submit-bar-button-width: 110px;
@submit-bar-price-color: @red; @submit-bar-price-color: @red;
@submit-bar-price-font-size: 18px; @submit-bar-price-font-size: @font-size-md;
@submit-bar-currency-font-size: @font-size-md; @submit-bar-currency-font-size: @font-size-md;
@submit-bar-text-color: @text-color; @submit-bar-text-color: @text-color;
@submit-bar-text-font-size: @font-size-md; @submit-bar-text-font-size: @font-size-md;
@ -606,6 +612,10 @@
@submit-bar-tip-color: #f56723; @submit-bar-tip-color: #f56723;
@submit-bar-tip-background-color: #fff7cc; @submit-bar-tip-background-color: #fff7cc;
@submit-bar-tip-icon-size: 12px; @submit-bar-tip-icon-size: 12px;
@submit-bar-button-height: 40px;
@submit-bar-padding: 0 @padding-md;
@submit-bar-price-integer-font-size: 20px;
@submit-bar-price-font-family: @price-integer-font-family;
// Swipe // Swipe
@swipe-indicator-size: 6px; @swipe-indicator-size: 6px;
@ -669,7 +679,7 @@
@tag-text-color: @white; @tag-text-color: @white;
@tag-border-radius: .2em; @tag-border-radius: .2em;
@tag-round-border-radius: @border-radius-max; @tag-round-border-radius: @border-radius-max;
@tag-dander-color: @red; @tag-danger-color: @red;
@tag-primary-color: @blue; @tag-primary-color: @blue;
@tag-success-color: @green; @tag-success-color: @green;
@tag-warning-color: @orange; @tag-warning-color: @orange;
@ -683,7 +693,7 @@
@toast-loading-icon-color: @white; @toast-loading-icon-color: @white;
@toast-line-height: 20px; @toast-line-height: 20px;
@toast-border-radius: @border-radius-md; @toast-border-radius: @border-radius-md;
@toast-background-color: rgba(@text-color, .88); @toast-background-color: fade(@text-color, 88%);
@toast-icon-size: 40px; @toast-icon-size: 40px;
@toast-text-min-width: 96px; @toast-text-min-width: 96px;
@toast-text-padding: @padding-xs @padding-sm; @toast-text-padding: @padding-xs @padding-sm;

View File

@ -75,6 +75,7 @@ Use slot to add custom contents.
| price | Price | *number* | - | - | | price | Price | *number* | - | - |
| label | Price left label | *string* | `Total` | - | | label | Price left label | *string* | `Total` | - |
| suffix-label | Price right label | *string* | - | - | | suffix-label | Price right label | *string* | - | - |
| text-align | Price label text align can be set to `right` `left` | *string* | `right` | - |
| button-text | Button text | *string* | - | - | | button-text | Button text | *string* | - | - |
| button-type | Button type | *string* | `danger` | - | | button-type | Button type | *string* | `danger` | - |
| tip | Tip | *string* | - | - | | tip | Tip | *string* | - | - |

View File

@ -75,6 +75,7 @@ Vue.use(SubmitBar);
| price | 价格(单位分) | *number* | - | - | | price | 价格(单位分) | *number* | - | - |
| label | 价格左侧文案 | *string* | `合计:` | - | | label | 价格左侧文案 | *string* | `合计:` | - |
| suffix-label | 价格右侧文案 | *string* | - | - | | suffix-label | 价格右侧文案 | *string* | - | - |
| text-align | 价格文案对齐方向,可选值为 `right` `left` | *string* | `right` | - |
| button-text | 按钮文字 | *string* | - | - | | button-text | 按钮文字 | *string* | - | - |
| button-type | 按钮类型 | *string* | `danger` | - | | button-type | 按钮类型 | *string* | `danger` | - |
| tip | 提示文案 | *string* | - | - | | tip | 提示文案 | *string* | - | - |

View File

@ -102,7 +102,7 @@ export default {
} }
.van-checkbox { .van-checkbox {
margin-left: @padding-sm; margin-right: @padding-sm;
} }
} }
</style> </style>

View File

@ -32,6 +32,7 @@
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
height: @submit-bar-height; height: @submit-bar-height;
padding: @submit-bar-padding;
font-size: @submit-bar-text-font-size; font-size: @submit-bar-text-font-size;
} }
@ -39,7 +40,6 @@
flex: 1; flex: 1;
padding-right: @padding-sm; padding-right: @padding-sm;
color: @submit-bar-text-color; color: @submit-bar-text-color;
font-weight: @font-weight-bold;
text-align: right; text-align: right;
span { span {
@ -49,19 +49,30 @@
&__suffix-label { &__suffix-label {
margin-left: 5px; margin-left: 5px;
font-weight: @font-weight-bold;
} }
&__price { &__price {
color: @submit-bar-price-color; color: @submit-bar-price-color;
font-size: @submit-bar-price-font-size; font-weight: @font-weight-bold;
font-size: @font-size-sm;
&::first-letter { &--integer {
font-size: @submit-bar-currency-font-size; font-size: @submit-bar-price-integer-font-size;
font-family: @submit-bar-price-font-family;
} }
} }
&__button { &__button {
width: @submit-bar-button-width; width: @submit-bar-button-width;
height: @submit-bar-button-height;
font-weight: @font-weight-bold;
line-height: @submit-bar-button-height;
border: none;
&--danger {
background: @goods-action-button-danger-color;
}
} }
&--safe-area-inset-bottom { &--safe-area-inset-bottom {

View File

@ -20,6 +20,7 @@ export type SubmitBarProps = {
suffixLabel?: string; suffixLabel?: string;
decimalLength: number; decimalLength: number;
safeAreaInsetBottom?: boolean; safeAreaInsetBottom?: boolean;
textAlign?: 'right' | 'left';
}; };
export type SubmitBarSlots = DefaultSlots & { export type SubmitBarSlots = DefaultSlots & {
@ -39,12 +40,14 @@ function SubmitBar(
function Text() { function Text() {
if (typeof price === 'number') { if (typeof price === 'number') {
const priceText = `${props.currency} ${(price / 100).toFixed(props.decimalLength)}`; const priceArr = (price / 100).toFixed(props.decimalLength).split('.');
return ( return (
<div class={bem('text')}> <div style={{ textAlign: props.textAlign ? props.textAlign : '' }} class={bem('text')}>
<span>{props.label || t('label')}</span> <span>{props.label || t('label')}</span>
<span class={bem('price')}>{priceText}</span> <span class={bem('price')}>
{props.currency}
<span class={bem('price', 'integer')}>{priceArr[0]}</span>.{priceArr[1]}
</span>
{props.suffixLabel && ( {props.suffixLabel && (
<span class={bem('suffix-label')}>{props.suffixLabel}</span> <span class={bem('suffix-label')}>{props.suffixLabel}</span>
)} )}
@ -76,9 +79,8 @@ function SubmitBar(
{slots.default && slots.default()} {slots.default && slots.default()}
{Text()} {Text()}
<Button <Button
square round
size="large" class={bem('button', props.buttonType)}
class={bem('button')}
type={props.buttonType} type={props.buttonType}
loading={props.loading} loading={props.loading}
disabled={props.disabled} disabled={props.disabled}
@ -113,7 +115,8 @@ SubmitBar.props = {
buttonType: { buttonType: {
type: String, type: String,
default: 'danger' default: 'danger'
} },
textAlign: String,
}; };
export default createComponent<SubmitBarProps, {}, SubmitBarSlots>(SubmitBar); export default createComponent<SubmitBarProps, {}, SubmitBarSlots>(SubmitBar);

View File

@ -5,7 +5,7 @@ exports[`renders demo correctly 1`] = `
<div> <div>
<div class="van-submit-bar"> <div class="van-submit-bar">
<div class="van-submit-bar__bar"> <div class="van-submit-bar__bar">
<div class="van-submit-bar__text"><span>合计:</span><span class="van-submit-bar__price">¥ 30.50</span></div><button class="van-button van-button--danger van-button--large van-button--square van-submit-bar__button"><span class="van-button__text">提交订单</span></button> <div class="van-submit-bar__text"><span>合计:</span><span class="van-submit-bar__price">¥<span class="van-submit-bar__price van-submit-bar__price--integer">30</span>.50</span></div><button class="van-button van-button--danger van-button--normal van-button--round van-submit-bar__button van-submit-bar__button--danger"><span class="van-button__text">提交订单</span></button>
</div> </div>
</div> </div>
</div> </div>
@ -14,14 +14,14 @@ exports[`renders demo correctly 1`] = `
<div class="van-submit-bar__tip"><i class="van-icon van-icon-info-o van-submit-bar__tip-icon"> <div class="van-submit-bar__tip"><i class="van-icon van-icon-info-o van-submit-bar__tip-icon">
<!----></i><span class="van-submit-bar__tip-text">你的收货地址不支持同城送, 我们已为你推荐快递</span></div> <!----></i><span class="van-submit-bar__tip-text">你的收货地址不支持同城送, 我们已为你推荐快递</span></div>
<div class="van-submit-bar__bar"> <div class="van-submit-bar__bar">
<div class="van-submit-bar__text"><span>合计:</span><span class="van-submit-bar__price">¥ 30.50</span></div><button disabled="disabled" class="van-button van-button--danger van-button--large van-button--disabled van-button--square van-submit-bar__button"><span class="van-button__text">提交订单</span></button> <div class="van-submit-bar__text"><span>合计:</span><span class="van-submit-bar__price">¥<span class="van-submit-bar__price van-submit-bar__price--integer">30</span>.50</span></div><button disabled="disabled" class="van-button van-button--danger van-button--normal van-button--disabled van-button--round van-submit-bar__button van-submit-bar__button--danger"><span class="van-button__text">提交订单</span></button>
</div> </div>
</div> </div>
</div> </div>
<div> <div>
<div class="van-submit-bar"> <div class="van-submit-bar">
<div class="van-submit-bar__bar"> <div class="van-submit-bar__bar">
<div class="van-submit-bar__text"><span>合计:</span><span class="van-submit-bar__price">¥ 30.50</span></div><button class="van-button van-button--danger van-button--large van-button--square van-submit-bar__button"> <div class="van-submit-bar__text"><span>合计:</span><span class="van-submit-bar__price">¥<span class="van-submit-bar__price van-submit-bar__price--integer">30</span>.50</span></div><button class="van-button van-button--danger van-button--normal van-button--round van-submit-bar__button van-submit-bar__button--danger">
<div class="van-loading van-loading--circular van-button__loading"><span class="van-loading__spinner van-loading__spinner--circular" style="color: currentColor; width: 20px; height: 20px;"><svg viewBox="25 25 50 50" class="van-loading__circular"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span></div> <div class="van-loading van-loading--circular van-button__loading"><span class="van-loading__spinner van-loading__spinner--circular" style="color: currentColor; width: 20px; height: 20px;"><svg viewBox="25 25 50 50" class="van-loading__circular"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span></div>
</button> </button>
</div> </div>
@ -39,7 +39,7 @@ exports[`renders demo correctly 1`] = `
<div class="van-checkbox__icon van-checkbox__icon--round van-checkbox__icon--checked"><i class="van-icon van-icon-success"> <div class="van-checkbox__icon van-checkbox__icon--round van-checkbox__icon--checked"><i class="van-icon van-icon-success">
<!----></i></div><span class="van-checkbox__label">全选</span> <!----></i></div><span class="van-checkbox__label">全选</span>
</div> </div>
<div class="van-submit-bar__text"><span>合计:</span><span class="van-submit-bar__price">¥ 30.50</span></div><button class="van-button van-button--danger van-button--large van-button--square van-submit-bar__button"><span class="van-button__text">提交订单</span></button> <div class="van-submit-bar__text"><span>合计:</span><span class="van-submit-bar__price">¥<span class="van-submit-bar__price van-submit-bar__price--integer">30</span>.50</span></div><button class="van-button van-button--danger van-button--normal van-button--round van-submit-bar__button van-submit-bar__button--danger"><span class="van-button__text">提交订单</span></button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -3,7 +3,7 @@
exports[`decimal-length prop 1`] = ` exports[`decimal-length prop 1`] = `
<div class="van-submit-bar"> <div class="van-submit-bar">
<div class="van-submit-bar__bar"> <div class="van-submit-bar__bar">
<div class="van-submit-bar__text"><span>合计:</span><span class="van-submit-bar__price">¥ 1.1</span></div><button class="van-button van-button--danger van-button--large van-button--square van-submit-bar__button"></button> <div class="van-submit-bar__text"><span>合计:</span><span class="van-submit-bar__price">¥<span class="van-submit-bar__price van-submit-bar__price--integer">1</span>.1</span></div><button class="van-button van-button--danger van-button--normal van-button--round van-submit-bar__button van-submit-bar__button--danger"></button>
</div> </div>
</div> </div>
`; `;
@ -11,7 +11,7 @@ exports[`decimal-length prop 1`] = `
exports[`disable submit 1`] = ` exports[`disable submit 1`] = `
<div class="van-submit-bar"> <div class="van-submit-bar">
<div class="van-submit-bar__bar"> <div class="van-submit-bar__bar">
<div class="van-submit-bar__text"><span>合计:</span><span class="van-submit-bar__price">¥ 0.01</span></div><button disabled="disabled" class="van-button van-button--danger van-button--large van-button--disabled van-button--square van-submit-bar__button"></button> <div class="van-submit-bar__text"><span>合计:</span><span class="van-submit-bar__price">¥<span class="van-submit-bar__price van-submit-bar__price--integer">0</span>.01</span></div><button disabled="disabled" class="van-button van-button--danger van-button--normal van-button--disabled van-button--round van-submit-bar__button van-submit-bar__button--danger"></button>
</div> </div>
</div> </div>
`; `;
@ -19,18 +19,26 @@ exports[`disable submit 1`] = `
exports[`suffix-label prop 1`] = ` exports[`suffix-label prop 1`] = `
<div class="van-submit-bar"> <div class="van-submit-bar">
<div class="van-submit-bar__bar"> <div class="van-submit-bar__bar">
<div class="van-submit-bar__text"><span>Label</span><span class="van-submit-bar__price">¥ 1.11</span><span class="van-submit-bar__suffix-label">Suffix Label</span></div><button class="van-button van-button--danger van-button--large van-button--square van-submit-bar__button"></button> <div class="van-submit-bar__text"><span>Label</span><span class="van-submit-bar__price">¥<span class="van-submit-bar__price van-submit-bar__price--integer">1</span>.11</span><span class="van-submit-bar__suffix-label">Suffix Label</span></div><button class="van-button van-button--danger van-button--normal van-button--round van-submit-bar__button van-submit-bar__button--danger"></button>
</div>
</div>
`;
exports[`text-align prop 1`] = `
<div class="van-submit-bar">
<div class="van-submit-bar__bar">
<div class="van-submit-bar__text" style="text-align: left;"><span>合计:</span><span class="van-submit-bar__price">¥<span class="van-submit-bar__price van-submit-bar__price--integer">1</span>.11</span></div><button class="van-button van-button--danger van-button--normal van-button--round van-submit-bar__button van-submit-bar__button--danger"></button>
</div> </div>
</div> </div>
`; `;
exports[`top slot 1`] = ` exports[`top slot 1`] = `
<div class="van-submit-bar">top<div class="van-submit-bar__bar"><button class="van-button van-button--danger van-button--large van-button--square van-submit-bar__button"></button></div> <div class="van-submit-bar">top<div class="van-submit-bar__bar"><button class="van-button van-button--danger van-button--normal van-button--round van-submit-bar__button van-submit-bar__button--danger"></button></div>
</div> </div>
`; `;
exports[`without price 1`] = ` exports[`without price 1`] = `
<div class="van-submit-bar"> <div class="van-submit-bar">
<div class="van-submit-bar__bar"><button class="van-button van-button--danger van-button--large van-button--square van-submit-bar__button"></button></div> <div class="van-submit-bar__bar"><button class="van-button van-button--danger van-button--normal van-button--round van-submit-bar__button van-submit-bar__button--danger"></button></div>
</div> </div>
`; `;

View File

@ -85,3 +85,15 @@ test('suffix-label prop', () => {
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
test('text-align prop', () => {
const wrapper = mount(SubmitBar, {
context: {
props: {
price: 111,
textAlign: 'left'
}
}
});
expect(wrapper).toMatchSnapshot();
});

View File

@ -23,10 +23,10 @@
} }
&--danger { &--danger {
background-color: @tag-dander-color; background-color: @tag-danger-color;
&.van-tag--plain { &.van-tag--plain {
color: @tag-dander-color; color: @tag-danger-color;
} }
} }

View File

@ -97,9 +97,8 @@ function TreeSelect(
} }
} }
emit(ctx, 'click-item', item);
emit(ctx, 'update:active-id', newActiveId); emit(ctx, 'update:active-id', newActiveId);
emit(ctx, 'click-item', item);
// compatible for old usage, should be removed in next major version // compatible for old usage, should be removed in next major version
emit(ctx, 'itemclick', item); emit(ctx, 'itemclick', item);
} }
@ -119,9 +118,8 @@ function TreeSelect(
class={bem('nav')} class={bem('nav')}
activeKey={mainActiveIndex} activeKey={mainActiveIndex}
onChange={(index: number) => { onChange={(index: number) => {
emit(ctx, 'click-nav', index);
emit(ctx, 'update:main-active-index', index); emit(ctx, 'update:main-active-index', index);
emit(ctx, 'click-nav', index);
// compatible for old usage, should be removed in next major version // compatible for old usage, should be removed in next major version
emit(ctx, 'navclick', index); emit(ctx, 'navclick', index);
}} }}

View File

@ -295,3 +295,37 @@ test('className of nav', () => {
const items = wrapper.findAll('.van-tree-select__nav-item'); const items = wrapper.findAll('.van-tree-select__nav-item');
expect(items.at(0).element.classList.contains('my-class')).toBeTruthy(); expect(items.at(0).element.classList.contains('my-class')).toBeTruthy();
}); });
test('should sync value before trigger click-item event', done => {
const wrapper = mount({
template: `
<van-tree-select
:items="items"
:main-active-index="0"
:active-id.sync="activeId"
@click-item="onClickItem"
/>
`,
data() {
return {
activeId: mockItem.id,
mainActiveIndex: 0,
items: [
{
text: 'group1',
children: [mockItem, mockItem2]
}
]
};
},
methods: {
onClickItem() {
expect(wrapper.vm.activeId).toEqual(mockItem2.id);
done();
}
}
});
const items = wrapper.findAll('.van-tree-select__item');
items.at(1).trigger('click');
});