Merge pull request #98 from chenjiahan/dev

add PayOrder component
This commit is contained in:
neverland 2017-08-29 17:00:00 +08:00 committed by GitHub
commit 982b20b219
12 changed files with 398 additions and 13 deletions

View File

@ -60,6 +60,7 @@ module.exports = {
{
loader: 'vue-loader',
options: {
preserveWhitespace: false,
loaders: {
postcss: ExtractTextPlugin.extract({
use: styleLoaders,

View File

@ -0,0 +1,87 @@
## PayOrder 支付订单
<script>
import { Toast } from 'packages/index';
export default {
methods: {
onClickButton() {
Toast('点击按钮');
}
}
}
</script>
<style>
.demo-pay-order {
.van-pay-order {
position: relative;
}
}
</style>
### 使用指南
``` javascript
import { PayOrder } from 'vant';
Vue.component(PayOrder.name, PayOrder);
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<van-pay-order
:price="3050"
button-text="提交订单"
@submit="onClickButton"
/>
```
:::
#### 禁用状态
禁用状态下不会触发`submit`事件
:::demo 禁用状态
```html
<van-pay-order
disabled
:price="3050"
button-text="提交订单"
tip="您的收货地址不支持同城送, 我们已为您推荐快递"
@submit="onClickButton"
/>
```
:::
#### 加载状态
加载状态下不会触发`submit`事件
:::demo 加载状态
```html
<van-pay-order
loading
:price="3050"
button-text="提交订单"
@submit="onClickButton"
/>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 必须 |
|-----------|-----------|-----------|-------------|-------------|
| price | 价格(单位分) | `Number` | | 是 |
| button-text | 按钮文字 | `String` | | 是 |
| button-type | 按钮类型 | `String` | `danger` | 否 |
| tip | 提示文案 | `String` | | 否 |
| disabled | 是否禁用按钮 | `Boolean` | `false` | 否 |
| loading | 是否显示加载中的按钮 | `Boolean` | `false` | 否 |
### Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| submit | 按钮点击事件回调 | - |

View File

@ -189,6 +189,10 @@ module.exports = {
"path": "/express-way",
"title": "ExpressWay 配送方式"
},
{
"path": "/pay-order",
"title": "PayOrder 提交订单栏"
},
{
"path": "/switch-cell",
"title": "SwitchCell 开关单元格"

View File

@ -48,7 +48,7 @@
"vue": "2.4.2"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"autoprefixer": "^7.1.3",
"avoriaz": "2.0.0",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
@ -117,6 +117,6 @@
"webpack": "^3.5.5",
"webpack-dev-server": "^2.7.1",
"webpack-merge": "^4.1.0",
"zan-doc": "^0.2.5"
"zan-doc": "^0.2.6"
}
}

View File

@ -19,6 +19,7 @@ import Lazyload from './lazyload';
import Loading from './loading';
import NoticeBar from './notice-bar';
import Panel from './panel';
import PayOrder from './pay-order';
import Picker from './picker';
import Popup from './popup';
import Progress from './progress';
@ -60,6 +61,7 @@ const components = [
Loading,
NoticeBar,
Panel,
PayOrder,
Picker,
Popup,
Progress,
@ -117,6 +119,7 @@ export {
Loading,
NoticeBar,
Panel,
PayOrder,
Picker,
Popup,
Progress,

View File

@ -99,6 +99,7 @@ export default {
* 显示popup
*/
open() {
/* istanbul ignore if */
if (this.$isServer) return;
if (this.opened) return;

View File

@ -0,0 +1,63 @@
<template>
<div class="van-pay-order">
<div class="van-pay-order__tip" v-show="tip">{{ tip }}</div>
<div class="van-pay-order__bar">
<div class="van-pay-order__price">
<template v-if="hasPrice">
<span class="van-pay-order__price-text">合计</span>
<span class="van-pay-order__price-interger">¥{{ priceInterger }}.</span>
<span class="van-pay-order__price-decimal">{{ priceDecimal }}</span>
</template>
</div>
<van-button :type="buttonType" :disabled="disabled" :loading="loading" @click="onSubmit">
{{ loading ? '' : buttonText }}
</van-button>
</div>
</div>
</template>
<script>
import Button from '../button';
export default {
name: 'van-pay-order',
components: {
[Button.name]: Button
},
props: {
tip: String,
type: Number,
price: Number,
loading: Boolean,
disabled: Boolean,
buttonText: String,
buttonType: {
type: String,
default: 'danger'
}
},
computed: {
hasPrice() {
return typeof this.price === 'number';
},
priceInterger() {
return Math.floor(this.price / 100);
},
priceDecimal() {
const decimal = this.price % 100;
return (decimal < 10 ? '0' : '') + decimal;
}
},
methods: {
onSubmit() {
if (!this.disabled && !this.loading) {
this.$emit('submit');
}
}
}
};
</script>

View File

@ -33,3 +33,4 @@
@import './notice-bar.css';
@import './switch-cell.css';
@import './express-way.css';
@import './pay-order.css';

View File

@ -0,0 +1,59 @@
.van-pay-order {
left: 0;
bottom: 0;
width: 100%;
z-index: 100;
position: fixed;
user-select: none;
&__tip {
color: #f60;
font-size: 12px;
line-height: 18px;
padding: 10px 10px;
background-color: #fff6e1;
}
&__bar {
height: 50px;
display: flex;
line-height: 50px;
background-color: #fff;
}
&__price {
flex: 1;
text-align: right;
padding-right: 10px;
}
&__price-text {
color: #666;
font-size: 16px;
}
&__price-interger {
color: #f44;
font-size: 16px;
}
&__price-decimal {
color: #f44;
font-size: 12px;
}
.van-button {
width: 110px;
height: 100%;
border-radius: 0;
&--disabled {
border: none;
}
.van-loading__spinner--white {
border-color: rgba(255,255,255, .8);
border-top-color: transparent;
}
}
}

View File

@ -0,0 +1,98 @@
import PayOrder from 'packages/pay-order';
import { mount } from 'avoriaz';
import { DOMChecker } from '../utils';
describe('PayOrder', () => {
let wrapper;
afterEach(() => {
wrapper && wrapper.destroy();
});
it('default', () => {
const props = {
price: 3050,
buttonText: '提交订单',
tip: '您的收货地址不支持同城送, 我们已为您推荐快递'
};
wrapper = mount(PayOrder, {
propsData: props
});
DOMChecker(wrapper, {
text: {
'.van-button__text': props.buttonText,
'.van-pay-order__price-interger': '¥30.',
'.van-pay-order__price-decimal': '50',
'.van-pay-order__tip': props.tip
}
});
});
it('no tip', () => {
wrapper = mount(PayOrder, {
propsData: {
price: 3005,
buttonText: '提交订单',
buttonType: 'default'
}
});
DOMChecker(wrapper, {
text: {
'.van-button__text': '提交订单',
'.van-pay-order__price-interger': '¥30.',
'.van-pay-order__price-decimal': '05',
'.van-pay-order__tip': ''
}
});
});
it('handle submit', () => {
wrapper = mount(PayOrder, {
propsData: {
price: 3005,
buttonText: '提交订单'
}
});
const submitSpyFunc = sinon.spy();
wrapper.vm.$on('submit', submitSpyFunc);
wrapper.find('.van-button')[0].trigger('click');
setTimeout(() => {
expect(submitSpyFunc.calledOnce).to.be.true;
}, 300);
});
it('can not submit when disabled', () => {
wrapper = mount(PayOrder, {
propsData: {
disabled: true,
buttonText: '提交订单'
}
});
const submitSpyFunc = sinon.spy();
wrapper.vm.$on('submit', submitSpyFunc);
wrapper.find('.van-button')[0].trigger('click');
setTimeout(() => {
expect(submitSpyFunc.calledOnce).to.be.false;
}, 300);
});
it('can not submit when loading', () => {
wrapper = mount(PayOrder, {
propsData: {
loading: true,
buttonText: '提交订单'
}
});
const submitSpyFunc = sinon.spy();
wrapper.vm.$on('submit', submitSpyFunc);
wrapper.find('.van-button')[0].trigger('click');
setTimeout(() => {
expect(submitSpyFunc.calledOnce).to.be.false;
}, 300);
});
});

View File

@ -1,5 +1,6 @@
import Popup from 'packages/popup';
import { mount } from 'avoriaz';
import { triggerTouch } from '../utils';
describe('Popup', () => {
let wrapper;
@ -57,4 +58,60 @@ describe('Popup', () => {
expect(wrapper.hasClass('van-popup')).to.be.true;
expect(wrapper.instance().currentTransition).to.equal('popup-fade');
});
it('popup prevent scroll', (done) => {
wrapper = mount(Popup, {
propsData: {
preventScroll: true,
value: true
}
});
expect(wrapper.hasClass('van-popup')).to.be.true;
setTimeout(() => {
expect(wrapper.data().currentValue).to.be.true;
wrapper.vm.value = false;
triggerTouch(document, 'touchstart', 0, 0);
triggerTouch(document, 'touchmove', 0, 10);
triggerTouch(document, 'touchmove', 0, 30);
triggerTouch(document, 'touchmove', 0, -30);
setTimeout(() => {
expect(wrapper.data().currentValue).to.be.false;
done();
}, 300);
}, 300);
});
it('popup modal', (done) => {
wrapper = mount(Popup, {
propsData: {
preventScroll: true,
value: true
}
});
wrapper.vm.$on('input', val => {
wrapper.vm.value = val;
});
expect(wrapper.hasClass('van-popup')).to.be.true;
const modal = document.querySelector('.van-modal');
setTimeout(() => {
triggerTouch(modal, 'touchstart', 0, 0);
triggerTouch(modal, 'touchmove', 0, 10);
triggerTouch(modal, 'touchmove', 0, 30);
triggerTouch(modal, 'touchmove', 0, -30);
expect(modal).to.exist;
modal.click();
setTimeout(() => {
expect(wrapper.data().currentValue).to.be.false;
done();
}, 300);
}, 300);
});
});

View File

@ -334,15 +334,15 @@ autoprefixer@^6.3.1:
postcss "^5.2.16"
postcss-value-parser "^3.2.3"
autoprefixer@^7.1.2:
version "7.1.2"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.1.2.tgz#fbeaf07d48fd878e0682bf7cbeeade728adb2b18"
autoprefixer@^7.1.3:
version "7.1.3"
resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.1.3.tgz#0e8d337976d6f13644db9f8813b4c42f3d1ccc34"
dependencies:
browserslist "^2.1.5"
caniuse-lite "^1.0.30000697"
browserslist "^2.4.0"
caniuse-lite "^1.0.30000718"
normalize-range "^0.1.2"
num2fraction "^1.2.2"
postcss "^6.0.6"
postcss "^6.0.10"
postcss-value-parser "^3.2.3"
avoriaz@2.0.0:
@ -1204,13 +1204,20 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6:
caniuse-db "^1.0.30000639"
electron-to-chromium "^1.2.7"
browserslist@^2.1.2, browserslist@^2.1.5:
browserslist@^2.1.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.3.3.tgz#2b0cabc4d28489f682598605858a0782f14b154c"
dependencies:
caniuse-lite "^1.0.30000715"
electron-to-chromium "^1.3.18"
browserslist@^2.4.0:
version "2.4.0"
resolved "https://registry.npmjs.org/browserslist/-/browserslist-2.4.0.tgz#693ee93d01e66468a6348da5498e011f578f87f8"
dependencies:
caniuse-lite "^1.0.30000718"
electron-to-chromium "^1.3.18"
buffer-indexof@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.0.tgz#f54f647c4f4e25228baa656a2e57e43d5f270982"
@ -1304,10 +1311,14 @@ caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
version "1.0.30000715"
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000715.tgz#0b9b5c795950dfbaf301a8806bafe87f126da8ca"
caniuse-lite@^1.0.30000697, caniuse-lite@^1.0.30000715:
caniuse-lite@^1.0.30000715:
version "1.0.30000715"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000715.tgz#c327f5e6d907ebcec62cde598c3bf0dd793fb9a0"
caniuse-lite@^1.0.30000718:
version "1.0.30000718"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000718.tgz#0dd24290beb11310b2d80f6b70a823c2a65a6fad"
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
@ -7959,9 +7970,9 @@ yeast@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
zan-doc@^0.2.5:
version "0.2.5"
resolved "https://registry.npmjs.org/zan-doc/-/zan-doc-0.2.5.tgz#4f82e1b75db1a348b57436cd1d4ffb607bc18562"
zan-doc@^0.2.6:
version "0.2.6"
resolved "https://registry.npmjs.org/zan-doc/-/zan-doc-0.2.6.tgz#27cc789460c32f6bed7687e050e2d9063b2725d5"
dependencies:
cheerio "0.22.0"
decamelize "^1.2.0"