Authored by QC-L

Merge branch 'master' into feature/offline-signup-report

... ... @@ -108,8 +108,8 @@
"id": 12,
"name": "商品详情线下店",
"pathName": "pages/productDetail/index",
"query": "q=https%3a%2f%2fo.yohobuy.com%2fufo%3fp%3d167215%2c1%26skup%3d167215%26skn%3d10001240",
"scene": "1011"
"query": "q=https%3A%2F%2Fo.yohobuy.com%2Fufo%3Fp%3D6298%2C70%26skup%3D6298%26skn%3D10001242%20",
"scene": 1011
},
{
"id": -1,
... ...
... ... @@ -76,7 +76,8 @@ class App extends Component {
"pages/zeroSell/detail",
"pages/zeroSell/myList",
"pages/zeroSell/snapshootShare",
"pages/zeroSell/h5Page"
"pages/zeroSell/h5Page",
"pages/myCoupon/index"
],
"permission": {
"scope.userLocation": {
... ...
import OrderListService from '../../pages/orderList/orderListService.js';
import OrderActionService from './orderActionService.js';
import event from '../../utils/event';
Component({
properties: {
showConfirm: {
type: Boolean,
value: false
},
orderCode: {
type: String,
value: '',
observer: '_orderChange'
},
navBack: {
type: Number,
value: 0
}
},
data: {
slideLeft: 0,
startX: 0,
hideSlide: true,
hideTip: false,
containerWidth: 0,
slideIconWidth: 0,
status: '',
orderPrice: '',
orderPriceDesc: '',
penaltyAmount: '',
penaltyDesc: '',
penaltyRate: '',
refundAmount: '',
refundDesc: ''
},
methods: {
closeSlide: function() {
this.setData({
hideSlide: true
});
},
touchStart: function (e) {
this.data.startX = e.touches[0].clientX;
},
touchMove: function (e) {
let currentX = e.touches[0].clientX;
if (currentX - this.data.startX < 0 || this.data.complete) {
return;
}
if (currentX - this.data.startX > (this.data.containerWidth - this.data.slideIconWidth - 4)) {
this.data.complete = true;
this.setData({
slideLeft: this.data.containerWidth - this.data.slideIconWidth - 4
});
return this.slideComplete();
}
this.setData({
hideTip: true,
slideLeft: currentX - this.data.startX
});
},
touchEnd: function (e) {
if (!this.data.complete) {
this.setData({
slideLeft: 0,
hideTip: false
});
}
},
confirm: function() {
let ctx = this;
if (!this.data.needPenalty) {
let api = new OrderActionService();
let params = {
method: 'ufo.buyer.cancel',
orderCode: this.data.orderCode
};
this.setData({
showConfirm: false
});
api.actionOrder(params).then(() => {
if (+this.data.navBack === 1){
wx.navigateBack({
delta: 1
});
}
event.emit('refresh-order');
});
return;
}
this.setData({
showConfirm: false,
hideSlide: false
}, () => {
let query = this.createSelectorQuery();
query.select('.slide-container').boundingClientRect();
query.exec(function (res) {
if (res && res[0] && res[0].width) {
ctx.data.containerWidth = res[0].width;
}
});
query = this.createSelectorQuery();
query.select('.slide-icon').boundingClientRect();
query.exec(function (res) {
if (res && res[0] && res[0].width) {
ctx.data.slideIconWidth = res[0].width;
}
});
});
},
keep: function () {
this.setData({
showConfirm: false
});
},
slideComplete: function() {
this._reset();
let api = new OrderActionService();
let params = {
method: 'ufo.buyer.cancel',
orderCode: this.data.orderCode
};
api.actionOrder(params).then(() => {
if (+this.data.navBack === 1){
wx.navigateBack({
delta: 1
});
}
event.emit('refresh-order');
});
},
_reset: function() {
this.setData({
hideSlide: true,
slideLeft: 0,
hideTip: false,
complete: false
});
},
_orderChange: function (val) {
if (!val) {
return;
}
let api = new OrderListService();
this.data.complete = false;
this.setData({
hideSlide: true,
slideLeft: 0
});
api.getCancelOrderInfo({orderCode: val}).then(data => {
this.data.needPenalty = data && data.needPenalty || false;
if (data && !data.needPenalty) {
this.setData({
...data,
status: '0',
cancelText: data && data.confirmDesc || '确定取消订单?',
cancelBtnText: '取消订单'
});
}
if (data && data.needPenalty) {
if (data && data.showPrice) {
this.setData({
...data,
status: '1',
cancelText: data && data.confirmDesc || '确定取消订单?',
cancelBtnText: '赔付并取消订单'
});
} else {
this.setData({
status: '2',
cancelText: data && data.confirmDesc || '确定取消订单?',
cancelBtnText: '赔付并取消订单'
});
}
}
});
}
}
});
... ...
{
"component": true,
"usingComponents": {
}
}
... ...
<view class="cancel-order-dialog">
<view class="confirm-layer {{status == '0' || status == '2' ? 'no-penalty' : ''}}}" wx:if="{{showConfirm}}">
<view class="mask"></view>
<view class="info">
<block wx:if="{{status == '0'}}">
<view class="item solo">{{cancelText}}</view>
</block>
<block wx:if="{{status == '1'}}">
<view class="item"><text class="left">{{orderPriceDesc}}</text><text class="right">{{orderPrice}}</text></view>
<view class="item"><text class="left">{{penaltyDesc}}({{penaltyRate}})</text><text class="right danger">{{penaltyAmount}}</text></view>
<view class="item"><text class="left">{{refundDesc}}</text><text class="right">{{refundAmount}}</text></view>
</block>
<block wx:if="{{status == '2'}}">
<view class="item solo">{{cancelText}}</view>
</block>
<view class="bottom-btn">
<view class="cancel btn {{status == '0' ? 'invalid' : ''}}" bindtap="confirm">{{cancelBtnText}}</view>
<view class="keep btn" bindtap="keep">保留订单</view>
</view>
</view>
</view>
<view class="slide-layer" hidden="{{hideSlide}}">
<view class="slide-mask">
<image class="close-icon"
bindtap="closeSlide"
src="../../assets/images/close.png"></image>
</view>
<view class="slide">
<view class="slide-container">
<view class="tip" hidden="{{hideTip}}">滑动确认赔付并取消订单</view>
<image class="slide-icon"
catchtouchstart="touchStart"
catchtouchmove="touchMove"
catchtouchend="touchEnd"
style="margin-left:{{slideLeft}}px"
src="../../assets/images/slide.png"></image>
</view>
</view>
</view>
</view>
... ...
.cancel-order-dialog .confirm-layer .info {
position: fixed;
width: 560rpx;
height: 400rpx;
z-index: 1000;
top: 50%;
left: 50%;
margin-left: -280rpx;
margin-top: -240rpx;
background-color: #ffffff;
text-align: center;
padding: 80rpx 44rpx 0 44rpx;
box-sizing: border-box;
}
.cancel-order-dialog .confirm-layer .info .item {
font-size: 28px;
color: #000000;
letter-spacing: 0;
text-align: left;
margin-bottom: 14rpx;
}
.cancel-order-dialog .confirm-layer .info .item .right {
float: right;
}
.cancel-order-dialog .confirm-layer .info .item .right.danger {
color: #D0021B;
}
.cancel-order-dialog .confirm-layer .info .item.solo {
text-align: center;
font-size: 38rpx;
margin-top: 30rpx;
}
.cancel-order-dialog .confirm-layer .info .bottom-btn{
position: absolute;
left: 0;
bottom: 0;
right: 0;
height: 100rpx;
font-size: 0;
border-top: 1px solid #EEEEEE;
}
.cancel-order-dialog .confirm-layer .bottom-btn .btn {
display: inline-block;
width: 50%;
line-height: 100rpx;
text-align: center;
font-size: 24rpx;
box-sizing: border-box;
}
.cancel-order-dialog .confirm-layer .bottom-btn .btn.keep {
font-size: 30px;
color: #000000;
letter-spacing: 0;
text-align: center;
font-weight: 500;
}
.cancel-order-dialog .confirm-layer .bottom-btn .btn.cancel {
font-size: 30px;
color: #D0021B;
letter-spacing: 0;
text-align: center;
border-right: 1px solid #EEEEEE;
}
.cancel-order-dialog .confirm-layer .bottom-btn .btn.cancel.invalid {
color: #e0e0e0;
}
.cancel-order-dialog .confirm-layer .mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 0.4;
z-index: 999;
background: #000000;
}
.cancel-order-dialog .confirm-layer.no-penalty .info {
position: fixed;
width: 560rpx;
height: 260rpx;
z-index: 1000;
top: 50%;
left: 50%;
margin-left: -280rpx;
margin-top: -120rpx;
background-color: #ffffff;
text-align: center;
padding: 34rpx 44rpx 0 44rpx;
box-sizing: border-box;
}
.cancel-order-dialog .confirm-layer.no-penalty .item.solo {
text-align: center;
font-size: 28rpx;
}
.cancel-order-dialog .slide-mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 0.9;
z-index: 999;
background: #000000;
}
.cancel-order-dialog .slide-layer .close-icon {
position: fixed;
top: 60rpx;
right: 40rpx;
width: 48rpx;
height: 48rpx;
}
.cancel-order-dialog .slide-container {
position: absolute;
width: 640rpx;
height: 140rpx;
z-index: 9999;
background: #FFFFFF;
border-radius: 70rpx;
top: 50%;
left: 50%;
margin-top: -70rpx;
margin-left: -320rpx;
}
.cancel-order-dialog .slide-container .tip {
font-size: 28px;
color: #444444;
letter-spacing: 0;
text-align: center;
line-height: 140rpx;
margin-left: 122rpx;
}
.cancel-order-dialog .slide-container .slide-icon {
position: absolute;
width: 132rpx;
height: 132rpx;
top: 4rpx;
left: 4rpx;
}
... ...
<view class="cancel-order-dialog">
<view class="confirm-layer {{status == '0' || status == '2' ? 'no-penalty' : ''}}}" wx:if="{{showConfirm}}">
<view class="confirm-layer {{status == '1' ? 'need-penalty' : ''}}}" wx:if="{{showConfirm}}">
<view class="mask"></view>
<view class="info">
<block wx:if="{{status == '0'}}">
... ...
.cancel-order-dialog .confirm-layer .info {
position: fixed;
width: 560rpx;
height: 400rpx;
z-index: 1000;
top: 50%;
left: 50%;
margin-left: -280rpx;
margin-top: -240rpx;
background-color: #ffffff;
text-align: center;
padding: 80rpx 44rpx 0 44rpx;
box-sizing: border-box;
}
.cancel-order-dialog .confirm-layer .info .item {
font-size: 28px;
color: #000000;
... ... @@ -85,7 +70,7 @@
background: #000000;
}
.cancel-order-dialog .confirm-layer.no-penalty .info {
.cancel-order-dialog .confirm-layer .info {
position: fixed;
width: 560rpx;
height: 260rpx;
... ... @@ -100,7 +85,22 @@
box-sizing: border-box;
}
.cancel-order-dialog .confirm-layer.no-penalty .item.solo {
.cancel-order-dialog .confirm-layer.need-penalty .info {
position: fixed;
width: 560rpx;
height: 400rpx;
z-index: 1000;
top: 50%;
left: 50%;
margin-left: -280rpx;
margin-top: -240rpx;
background-color: #ffffff;
text-align: center;
padding: 80rpx 44rpx 0 44rpx;
box-sizing: border-box;
}
.cancel-order-dialog .confirm-layer .item.solo {
text-align: center;
font-size: 28rpx;
}
... ...
Component({
properties: {
show: {
type: Boolean,
value: false,
observer: '_show'
},
coupons: {
type: Array,
value: []
},
selectedCode: {
type: String,
value: ''
}
},
data: {
chosenIdx: ''
},
methods: {
confirm: function () {
let item = this.data.coupons[this.data.chosenIdx];
let code = item && item.coupon_code || '';
let amount = item && item.coupon_value_str || '';
this.triggerEvent('confirmselect', {code, amount})
},
cancel: function () {
this.triggerEvent('cancel')
},
check: function (e) {
let idx = e.currentTarget.dataset.idx;
this.data.coupons.forEach((item, index) => {
if (index !== idx && item.isChosen) {
this.setData({
[`coupons[${index}].isChosen`]: false
});
}
if (index === idx) {
this.setData({
[`coupons[${idx}].isChosen`]: true
});
}
});
this.data.chosenIdx = idx;
},
uncheck: function (e) {
let idx = e.currentTarget.dataset.idx;
this.setData({
[`coupons[${idx}].isChosen`]: false
});
this.data.chosenIdx = '';
},
_show: function (show) {
if (show) {
if (this.data.selectedCode) {
this.data.coupons.forEach((item, index) => {
if (item.coupon_code === this.data.selectedCode) {
this.setData({
[`coupons[${index}].isChosen`]: true
});
this.data.chosenIdx = index;
} else {
this.setData({
[`coupons[${index}].isChosen`]: false
});
}
});
} else {
this.data.coupons.forEach((item, index) => {
this.setData({
[`coupons[${index}].isChosen`]: false
});
});
this.data.chosenIdx = '';
}
}
}
}
});
... ...
{
"component": true,
"usingComponents": {
}
}
... ...
<view class="coupon-use-select" wx:if="{{show}}">
<view class="mask"></view>
<view class="content">
<view class="header">选择优惠券
<image class="close" bindtap="cancel" src="../../assets/images/close-gray.png"></image></view>
<view class="empty" catchtouchmove="true" wx:if="{{!coupons.length}}">
没有可使用的优惠券哦
</view>
<block wx:else>
<scroll-view class="coupon-scroll" scroll-y>
<block wx:for="{{coupons}}" wx:key="{{item.coupon_code}}">
<view class="coupon-item">
<view class="left">
<block wx:if="{{item.use_rule_str}}">
<text class="value">{{item.coupon_value_str}}</text>
</block>
<block wx:else>
<text class="value solo">{{item.coupon_value_str}}</text>
</block>
<text class="condition" wx:if="{{item.use_rule_str}}">{{item.use_rule_str}}</text>
</view>
<view class="right">
<text class="name"><text class="prefix">[UFO]</text>{{item.coupon_name}}</text>
<text class="period">{{item.coupon_validity}}</text>
<block wx:if="{{item.isChosen}}">
<image bindtap="uncheck" class="checked" data-idx="{{index}}"
src="../../assets/images/checked.png"></image>
</block>
<block wx:else>
<view bindtap="check" class="check" data-idx="{{index}}"></view>
</block>
</view>
</view>
</block>
</scroll-view>
</block>
<view class="confirm" bindtap="confirm">确定</view>
</view>
</view>
... ...
.coupon-use-select .mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 0.4;
z-index: 999;
background: #000000;
}
.coupon-use-select .content {
position: fixed;
left: 0;
right: 0;
bottom: 0;
height: 960rpx;
z-index: 1000;
background-color: #F5F5F5;
}
.coupon-use-select .coupon-scroll {
overflow-y: scroll;
height: 720rpx;
padding-bottom: 120rpx;
text-align: center;
font-size: 0;
}
.coupon-use-select .empty {
padding-top: 316rpx;
text-align: center;
font-size: 28px;
color: #CCCCCC;
letter-spacing: 0;
height: 720rpx;
background-color: #ffffff;
}
.coupon-use-select .header {
position: relative;
height: 120rpx;
background-color: #ffffff;
padding-left: 40rpx;
line-height: 120rpx;
font-size: 32px;
color: #000000;
letter-spacing: 0;
font-weight: 500;
}
.coupon-use-select .header .close {
width: 40rpx;
height: 40rpx;
float: right;
margin-top: 40rpx;
margin-right: 40rpx;
}
.coupon-use-select .coupon-item {
display: inline-block;
position: relative;
height: 200rpx;
width: 720rpx;
background: url("https://img10.static.yhbimg.com/yhb-img01/2019/03/05/20/01b68a5d4f22945fe5afcf0f768538cfd3.png") no-repeat;
background-size: 720rpx 200rpx;
}
.coupon-use-select .coupon-item:first-child {
margin-top: 10rpx;
}
.coupon-use-select .coupon-item:last-child {
margin-bottom: 10rpx;
}
.coupon-use-select .coupon-item .left {
position: absolute;
top: 0;
left: 10rpx;
height: 200rpx;
width: 220rpx;
padding-top: 38rpx;
text-align: center;
box-sizing: border-box;
}
.coupon-use-select .coupon-item .left .value {
display: block;
font-weight: bold;
font-size: 72px;
color: #002B47;
letter-spacing: 0;
text-align: center;
line-height: 1;
}
.coupon-use-select .coupon-item .left .value.solo {
line-height: 1.5;
}
.coupon-use-select .coupon-item .left .condition {
display: block;
font-size: 24px;
color: #002B47;
letter-spacing: 0;
text-align: center;
line-height: 1;
margin-top: 16rpx;
}
.coupon-use-select .coupon-item .right {
padding-top: 30rpx;
padding-left: 240rpx;
padding-right: 80rpx;
box-sizing: border-box;
}
.coupon-use-select .coupon-item .right .name {
display: block;
font-size: 24px;
color: #222222;
letter-spacing: 0;
line-height: 30rpx;
word-break: break-all;
overflow : hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
text-align: left;
}
.coupon-use-select .coupon-item .right .name .prefix {
font-size: 24px;
color: #002B47;
letter-spacing: 0;
font-weight: 500;
margin-right: 10px;
}
.coupon-use-select .coupon-item .right .period {
display: block;
font-size: 22px;
color: #999999;
letter-spacing: 0;
margin-top: 26rpx;
text-align: left;
}
.coupon-use-select .coupon-item .right .check {
position: absolute;
top: 50%;
right: 50rpx;
width: 48rpx;
height: 48rpx;
margin-top: -24rpx;
border: 2rpx solid #cccccc;
border-radius: 48rpx;
box-sizing: border-box;
}
.coupon-use-select .coupon-item .right .checked {
position: absolute;
top: 50%;
right: 50rpx;
width: 48rpx;
height: 48rpx;
margin-top: -24rpx;
}
.coupon-use-select .confirm {
position: fixed;
left: 0;
right: 0;
bottom: 0;
height: 120rpx;
font-size: 32px;
color: #FFFFFF;
letter-spacing: 0;
text-align: center;
line-height: 120rpx;
background: #002B47;
}
... ...
... ... @@ -9,8 +9,6 @@ const SHOW_DETAIL = 'show_detail';
const SHOW_EXPRESS = 'show_express';
import event from '../../utils/event';
let interval;
Component({
/**
* 组件的属性列表
... ... @@ -47,7 +45,6 @@ attached: function () {
let that = this;
if (that.data.buttons){
let lastIndex = that.data.buttons.length - 1;
console.log("lastIndex===" + lastIndex);
that.setData({ lastIndex: lastIndex });
}
... ... @@ -56,7 +53,8 @@ attached: function () {
let timer = that.data.timer;
if (timer > 0){
interval = setInterval(() => {
this.data.interval && clearInterval(this.data.interval);
this.data.interval = setInterval(() => {
timer = timer - 1;
leftTime = formatTimeByMin(timer, 'm:s');
if (timer <= 0) {
... ... @@ -64,7 +62,7 @@ attached: function () {
setTimeout(() => {
event.emit('refresh-order');
}, 2000);
clearInterval(interval);
clearInterval(this.data.interval);
}
that.setData({
lefttime: leftTime,
... ... @@ -77,8 +75,8 @@ attached: function () {
},
detached: function () {
if (interval){
clearInterval(interval);
if (this.data.interval){
clearInterval(this.data.interval);
}
},
... ... @@ -112,7 +110,7 @@ detached: function () {
}
router.go('logistics', params);
} else {
if (actionCode === 'cancel_order') {
if (actionCode === 'cancel_order' && !this.data.isStore) {
return this.triggerEvent('cancelorder', {
orderCode
});
... ...
import BaseService from '../libs/services/baseService'
export default class couponModel extends BaseService {
constructor(options) {
super(options)
}
myCouponList(complete) {
return this.GET(
{
method: 'ufo.coupons.get',
},
{
path: '/coupon',
complete
}
)
}
}
... ...
... ... @@ -2,6 +2,7 @@ import api from '../utils/api';
const UFO_ORDER_SUMMARY = 'ufo.order.summary'
const UFO_FAVORITE_NUMBER = 'ufo.user.favoriteNum'
const UFO_COUPONS_COUNT = 'ufo.coupons.cnt'
export default {
getUFO_OrderSummary(params) {
... ... @@ -18,5 +19,13 @@ export default {
method: UFO_FAVORITE_NUMBER
}, params)
})
},
getUFOTotalCoupons(params) {
return api.get({
url: '/coupon',
data: Object.assign({
method: UFO_COUPONS_COUNT
}, params)
})
}
}
\ No newline at end of file
}
... ...
import Taro, {Component} from '@tarojs/taro';
import {View, Text, Navigator, Image} from '@tarojs/components';
import './index.scss'
import down from '../../assets/images/down@2x.png';
import couponModel from '../../models/coupon';
import nullBg from '../../assets/images/null.png';
const model = new couponModel();
export default class MyCoupon extends Component {
constructor() {
super(...arguments);
this.state = {
couponList: [],
complete: false
};
}
config = {};
componentWillMount() {
this.getCouponList();
}
async getCouponList() {
let couponList = await model.myCouponList();
this.setState({couponList, complete: true});
};
showNote = (value) => {
let {couponList} = this.state;
couponList[value].showNotes = !couponList[value].showNotes;
this.setState({
couponList
});
this.forceUpdate();
};
render() {
let {couponList, complete} = this.state;
if (!complete) return;
return (
<View className={couponList && couponList.length ? 'page bg' : 'page'}>
<View className='title'>优惠券</View>
{couponList && couponList.length ?
<View className='content'>
{couponList.map((value, index) => {
return <View className='item'>
<View className='ticket'>
<View className='left'>
<View className={!value.use_rule ? 'price solo' : 'price'}>{value.coupon_value}</View>
{
value.use_rule ? <View className='use-rule'>{value.use_rule}</View> : ''
}
</View>
<View className='right'>
<View className='name'><Text className='prefix'>[UFO]</Text> {value.coupon_name}</View>
<View className='date'>{value.coupon_validity}</View>
<View className='desc' onClick={this.showNote.bind(this, index)}>使用说明
<Image mode='aspectFit' src={down} className={value.showNotes ? 'up' : 'down'}></Image>
</View>
</View>
</View>
<View className='desc-info' style={{display: value.showNotes ? 'block' : 'none'}}>
{value.notes.map((note) => {
return <View className='p'><View className='point'>·</View><View className='info'>{note}</View></View>
})}
</View>
</View>
})}
</View> :
<View>
<View className='null'><Image src={nullBg} className='nullBg' mode='aspectFit'></Image></View>
<View className='nullText'>暂时没有优惠券哦</View>
</View>
}
</View>
)
}
}
... ...
.bg {
background-color: #F5F5F5;
}
.null {
position: relative;
margin-top: 174px;
}
.nullBg {
width: 280px;
height: 280px;
display: block;
margin: 0 auto;
}
.nullText {
color: #CCCCCC;
font-size: 28px;
text-align: center;
margin-top: 20px;
}
.page {
font-family: PingFang-SC-Regular;
display: block;
min-height: 100%;
width: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 1;
font-size: 24px;
.title {
padding-left: 40px;
font-size: 68px;
background: #fff;
font-family: SFProDisplay-Bold;
font-weight: 500;
}
.content {
margin-top: 10px
}
.ticket {
background: url(https://img10.static.yhbimg.com/yhb-img01/2019/03/05/20/01b68a5d4f22945fe5afcf0f768538cfd3.png) no-repeat;
background-size: contain;
width: 730px;
height: 222px;
margin-left: 10px;
z-index: 10;
position: relative;
.left {
color: #002B47;
width: 240px;
text-align: center;
float: left;
.price {
font-size: 72px;
margin-top: 38px;
font-weight: 600;
font-family: SFProText-Semibold;
}
.price.solo {
line-height: 1.8;
}
.type {
font-size: 24px;
}
}
.right {
float: left;
color: #999999;
.name {
margin-top: 27px;
color: #222222;
width: 450px;
height: 72px;
display: block;
font-size: 24px;
letter-spacing: 0;
word-break: break-all;
overflow : hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
text-align: left;
.prefix {
color: #002B47;
margin-right: 10px;
}
}
.date {
margin-bottom: 26px;
}
.desc {
font-size: 22px;
}
.down {
width: 20px;
height: 20px;
}
.up {
transform: rotate(180deg);
width: 20px;
height: 20px;
}
}
}
.desc-info {
position: relative;
background: #fcfcfc;
padding: 20px;
margin: -21px 20px 20px;
.p {
margin-top: 8px;
color: #444444;
}
.point {
margin-right:10px;
display:inline-block;
vertical-align:top;
}
.info {
word-wrap: break-word;word-break: break-all;overflow: hidden;
display:inline-block;
width: 645px;
}
}
}
... ...
... ... @@ -4,6 +4,8 @@ import { formatTimeByDefined } from '../../utils/index.js'
import Yas from '../../utils/yas';
let yas;
let {screenWidth} = wx.getSystemInfoSync();
let radio = (screenWidth / 750).toFixed(2);
Page({
... ... @@ -37,18 +39,9 @@ Page({
* 画progress底部背景
*/
drawProgressbg: function (summary) {
// let summary = {
// totalIncome: '130.98',
// goodsIncome: '30.98',
// compensateIncome: '100',
// }
// this.setData({
// summary: summary
// });
// 使用 wx.createContext 获取绘图上下文 context
var ctx = wx.createCanvasContext('canvasProgressbg')
// 设置圆环的宽度
ctx.setLineWidth(14);
ctx.setLineWidth(28 * radio);
// 设置圆环的颜色
let strokeColor = '#E0E0E0'
if (summary && summary.totalIncome > 0) {
... ... @@ -61,7 +54,7 @@ Page({
ctx.beginPath();
//设置一个原点(110,110),半径为100的圆的路径到当前路径
console.log("起始点:" + Math.PI)
ctx.arc(60, 60, 51, 0, 2 * Math.PI, false);
ctx.arc(120 * radio, 120 * radio, 100 * radio, 0, 2 * Math.PI, false);
//对当前路径进行描边
ctx.stroke();
//开始绘制
... ... @@ -75,7 +68,7 @@ Page({
// 使用 wx.createContext 获取绘图上下文 context
var context = wx.createCanvasContext('canvasProgress');
// 设置圆环的宽度
context.setLineWidth(14);
context.setLineWidth(28 * radio);
// 设置圆环的颜色
let strokeColor = '#002B47'
// if (this.data.summary.totalIncome <= 0){
... ... @@ -87,7 +80,7 @@ Page({
//开始一个新的路径
context.beginPath();
//参数step 为绘制的圆环周长,从0到2为一周 。 -Math.PI / 2 将起始角设在12点钟位置 ,结束角 通过改变 step 的值确定
context.arc(60, 60, 51, -Math.PI / 2, step * Math.PI - Math.PI / 2, false);
context.arc(120 * radio, 120 * radio, 100 * radio, -Math.PI / 2, step * Math.PI - Math.PI / 2, false);
//对当前路径进行描边
context.stroke();
//开始绘制
... ...
Component({
properties: {
amount: {
type: String,
value: ''
}
},
data: {},
methods: {
select: function(){
this.triggerEvent('select',{})
}
}
});
... ...
<view class="coupon-cell" bindtap="select">
优惠券
<view class="choose">
<block wx:if="{{amount}}">
<text class="value chosen">-¥{{amount}}</text>
</block>
<block wx:else>
<text class="value">选择优惠券</text>
</block>
<image class="right"
src="../../../../static/images/arrow-right-2.png"></image>
</view>
</view>
... ...
.coupon-cell {
height: 120rpx;
font-size: 32px;
color: #000000;
letter-spacing: 0.8rpx;
line-height: 119rpx;
border-bottom: 2rpx solid #eeeeee;
}
.choose {
position: relative;
float: right;
padding-right: 40rpx;
font-size: 28px;
color: #999999;
letter-spacing: 0;
}
.choose .value.chosen {
color: #D0021B;
}
.choose .right {
position: absolute;
top: 34rpx;
right: 0;
height: 48rpx;
width: 48rpx;
}
... ...
... ... @@ -25,7 +25,11 @@ Page({
checkImage: '../../../assets/images/select@2x.png',
unCheckImage: '../../../assets/images/unselect@2x.png',
isStore: 0,
storeId: 0
storeId: 0,
coupons: [],
selectCouponCode: '',
selectCouponAmount: '',
selectingCoupon: false
},
onLoad: async function (option) {
yas = new Yas(this);
... ... @@ -43,6 +47,50 @@ Page({
}
},
showSelectCoupon: function () {
this.setData({
selectingCoupon: true
});
},
async confirmSelectCoupon({detail}) {
let code = detail.code;
let amount = detail.amount || '';
this.setData({
selectCouponAmount: amount,
selectCouponCode: code,
selectingCoupon: false
});
// 区分线上线下
let info;
try {
if (this.data.isStore) {
info = await api.orderOfflineCompute({
skup: this.data.skup,
coupon_code: code
}, () => wx.hideLoading());
} else {
info = await api.orderCompute({
skup: this.data.skup,
coupon_code: code
}, () => wx.hideLoading());
}
} catch(e) {}
this.setData({
amount: info.amount,
promotionFormulaList: info.promotionFormulaList
});
},
cancelSelectCoupon: function () {
this.setData({
selectingCoupon: false
});
},
async fetchData(isStore) {
wx.showLoading({
title: '',
... ... @@ -64,6 +112,12 @@ Page({
} else {
data = await api.createPaymentInfo(params, () => wx.hideLoading())
}
api.orderSelectCoupon(this.data.skup, () => wx.hideLoading()).then(data => {
let coupons = data || [];
this.setData(coupons)
});
if (data.good && data.good.goodImg) {
data.good.goodImg = getImgUrl(data.good.goodImg, 270, 270)
}
... ... @@ -116,9 +170,11 @@ Page({
if (!checkRes.result) return;
let param = checkRes.data;
param.skup = this.data.skup
wx.showLoading({
title: '',
})
param.coupon_code = this.data.selectCouponCode || '';
// wx.showLoading({
// title: '',
// })
data = await api.storeBuyerSubmit(param, () => {
wx.hideLoading()
})
... ... @@ -134,11 +190,12 @@ Page({
let addressId = this.data.hasAddress && this.data.address && this.data.address.address_id
let skup = this.data.skup
let channelNo = '';
let couponCode = this.data.selectCouponCode || '';
wx.showLoading({
title: '',
})
data = await api.buyerSubmit(skup, channelNo, addressId, () => wx.hideLoading());
// wx.showLoading({
// title: '',
// })
data = await api.buyerSubmit(skup, channelNo, addressId, couponCode, () => wx.hideLoading());
}
if (data && data.orderCode) {
let skup = this.data.skup
... ...
... ... @@ -6,7 +6,9 @@
"productCell": "./components/productCell",
"priceCell": "./components/priceCell",
"payDeliveryCell": "./components/payDeliveryCell",
"couponCell": "./components/couponCell",
"storeAddress":"./components/storeAddress",
"checkstore":"../../../components/checkstore/checkstore"
"checkstore":"../../../components/checkstore/checkstore",
"couponSelect":"../../../components/order/coupon-select"
}
}
... ...
<!-- <view> -->
<!-- <view class="orderContainer"> -->
<scroll-view scroll-y class="orderContainer">
<text class='message-title'>确认订单</text>
<addressCell hasAddress="{{hasAddress}}" address="{{address}}" bindaddressevent="chooseAddress"
... ... @@ -8,6 +6,7 @@
wx:else></storeAddress>
<productCell productInfo="{{good}}" isStore="{{isStore === 1}}"></productCell>
<couponCell bindselect="showSelectCoupon" amount="{{selectCouponAmount}}"></couponCell>
<priceCell promotionFormulaList="{{promotionFormulaList}}" damagesDesc="{{damagesDesc}}" isStore="{{isStore === 1}}"></priceCell>
<payDeliveryCell paymentWay="{{paymentWay}}" deliveryWay="{{deliveryWay}}"></payDeliveryCell>
</scroll-view>
... ... @@ -37,4 +36,6 @@
</view>
</view>
</view>
<couponSelect bindconfirmselect="confirmSelectCoupon" show="{{selectingCoupon}}" selected-code="{{selectCouponCode}}"
bindcancel="cancelSelectCoupon" coupons="{{coupons}}"></couponSelect>
<checkstore id="check" storeId="{{storeId}}" productId="{{product_id}}"></checkstore>
... ...
... ... @@ -15,6 +15,9 @@ const COMPUTE_COMPENSATE = 'ufo.buyer.computeCompensate'
const PRODUCT_RECOMMEND = 'ufo.product.data.search.recommend'
const CREATE_OFFLINE_PAYMENTINFO = 'ufo.order.offlinePayment';
const STORE_BUYER_SUBMIT = 'ufo.order.offlineSubmit'
const ORDER_SELECT_COUPON = 'ufo.order.selectCoupon'
const ORDER_COMPUTE = 'ufo.order.compute'
const ORDER_OFFLINE_COMPUTE = 'ufo.order.offlineCompute'
export default class orderService extends BaseService {
constructor(options) {
super(options)
... ... @@ -53,13 +56,14 @@ export default class orderService extends BaseService {
})
}
async buyerSubmit(skup, channelNo = '2919', addressId, complete) {
async buyerSubmit(skup, channelNo = '2919', addressId, couponCode, complete) {
return await this.GET({
method: BUYER_SUBMIT,
skup,
channelNo,
addressId,
coupon_code: couponCode || ''
}, {
path: '/shopping',
complete
... ... @@ -109,5 +113,35 @@ export default class orderService extends BaseService {
})
}
async orderSelectCoupon(skup, complete) {
return await this.GET({
skup,
method: ORDER_SELECT_COUPON,
}, {
path: '/shopping',
complete
})
}
async orderOfflineCompute(params, complete) {
return await this.GET({
...params,
method: ORDER_OFFLINE_COMPUTE,
}, {
path: '/shopping',
complete
})
}
async orderCompute(params, complete) {
return await this.GET({
...params,
method: ORDER_COMPUTE,
}, {
path: '/shopping',
complete
})
}
}
... ...
import orderService from './orderService.js'
import router from '../../router/index.js'
import Taro from '@tarojs/taro';
import wx from '../../libs/wx';
// const api = new orderService();
/**
... ... @@ -8,9 +10,9 @@ import router from '../../router/index.js'
*/
export const prePay = function (productId, orderCode, fromWhere, isStore) {
let api = new orderService()
wx.showLoading({
title: '',
})
// wx.showLoading({
// title: '',
// })
let openID = '';
try {
openID = wx.getStorageSync('openid')
... ... @@ -23,10 +25,33 @@ export const prePay = function (productId, orderCode, fromWhere, isStore) {
.then(data => {
if (data) {
callWxPay(data, productId, orderCode, fromWhere, isStore)
} else {
throw new Error('ufo.order.pay fail.')
}
})
.catch(error => {
console.log(error)
.catch(() => {
// 调用出错
Taro.showToast({
title: '订单不可支付',
duration: 1500,
icon: 'none'
});
let currentRoute;
let currentPages = getCurrentPages();
if (currentPages && currentPages.length) {
currentRoute = currentPages[currentPages.length - 1].route;
}
let noRedirectRoutes = ['pages/orderDetail/index', 'pages/orderList/index'];
if (noRedirectRoutes.indexOf(currentRoute) > -1) {
return;
}
setTimeout(() => {
wx.redirectTo({
url: '/pages/orderDetail/index?orderCode=' + orderCode
});
}, 1500);
})
} else {
//提示重新登录
... ... @@ -54,7 +79,7 @@ function callWxPay(data, productId, orderCode, fromWhere ,isStore) {
}
if (res.errMsg == 'requestPayment:fail cancel') {
if (fromWhere == 0) {
router.go('orderDetail', params);
router.go('orderDetail', params, 'redirectTo');
}
} else {
... ... @@ -64,7 +89,7 @@ function callWxPay(data, productId, orderCode, fromWhere ,isStore) {
confirmText: "确定",
complete: function (res) {
if (fromWhere == 0) {
router.go('orderDetail', params);
router.go('orderDetail', params, 'redirectTo');
}
}
})
... ...
... ... @@ -10,7 +10,6 @@ import Yas from '../../utils/yas';
const BUY_AGAIN = 'buy_again';
const NOW_BUY = 'now_buy';
const SHOW_EXPRESS = 'show_express';
let interval;
let yas;
... ... @@ -28,7 +27,8 @@ Page({
orderCode: '',
cancelConfirm: false,
cancelOrderCode: '',
navBack: 1
navBack: 1,
interval: ''
},
/**
... ... @@ -64,8 +64,8 @@ Page({
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
if (interval) {
clearInterval(interval);
if (this.data.interval) {
clearInterval(this.data.interval);
}
},
... ... @@ -73,8 +73,8 @@ Page({
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
if (interval) {
clearInterval(interval);
if (this.data.interval) {
clearInterval(this.data.interval);
}
},
... ... @@ -117,8 +117,6 @@ Page({
data.buttons = data.buttons.filter(item => {
return item.code !== 'modify_address';
});
console.log(data.buttons)
}
if (data && data.buttons && data.buttons.length > 0) {
... ... @@ -137,7 +135,9 @@ Page({
that.setData({
timer: formatTimeByMin(leftTime, 'm:s')
});
interval = setInterval(() => {
this.data.interval && clearInterval(this.data.interval);
this.data.interval = setInterval(() => {
leftTime = leftTime - 1;
timer = formatTimeByMin(leftTime, 'm:s');
if (leftTime <= 0) {
... ... @@ -145,7 +145,7 @@ Page({
setTimeout(() => {
that.fetchOrderDetail(code);
}, 2000);
clearInterval(interval);
clearInterval(this.data.interval);
}
that.setData({
timer: timer,
... ... @@ -183,7 +183,7 @@ Page({
}
router.go('logistics', params);
} else {
if (actionCode === 'cancel_order') {
if (actionCode === 'cancel_order' && this.data.data.isOffline !== 'Y') {
return ctx.setData({
cancelConfirm: true,
cancelOrderCode: orderCode
... ...
... ... @@ -42,6 +42,12 @@
<text class='order-detail-sum-grey-txt'>运费:</text>
<text class='order-detail-sum-grey-txt'>¥{{data.priceInfo.feePrice}}</text>
</view>
<view class='order-detail-count-view' wx:if="{{data.priceInfo.couponCutPrice}}">
<block wx:if="{{data.priceInfo.couponCutPrice != '0.00' && data.priceInfo.couponCutPrice != '0'}}">
<text class='order-detail-sum-grey-txt'>优惠券:</text>
<text class='order-detail-sum-grey-txt'>-¥{{data.priceInfo.couponCutPrice}}</text>
</block>
</view>
<view class='order-detail-count-view'>
<text class='order-detail-sum-black-txt'>实际金额:</text>
<text class='order-detail-sum-red-txt'>¥{{data.priceInfo.realPayPrice}}</text>
... ...
... ... @@ -44,6 +44,11 @@ export default class UserCenter extends Component {
page: 'myassets'
},
{
text: '优惠券',
page: 'myCoupon',
num: 0
},
{
text: '客服与帮助',
mt: true,
page: 'webview',
... ... @@ -248,6 +253,16 @@ export default class UserCenter extends Component {
});
}
}).catch(error => {});
personalModel.getUFOTotalCoupons().then(ret => {
if (ret && ret.code === 200 && ret.data) {
let list = this.state.list;
let num = ret.data;
list[3].num = num;
this.setState({
list
});
}
}).catch(error => {});
} else {
this.setState({
userInfo: this.props.globalData.userInfo,
... ...
export default {
home: {
home: {
path: '/pages/index/index'
},
productDetail: {
... ... @@ -28,9 +28,6 @@ export default {
myassets: {
path: '/pages/myassets/index'
},
webview: {
path: '/pages/webview/webview'
},
search: {
path: '/pages/search/index'
},
... ... @@ -54,5 +51,8 @@ export default {
},
selectCountry: {
path: '/pages/select-country/select-country'
},
myCoupon:{
path: '/pages/myCoupon/index'
}
}
... ...
... ... @@ -6688,7 +6688,6 @@ url-to-options@^1.0.1:
url@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=
dependencies:
punycode "1.3.2"
querystring "0.2.0"
... ...