喻文俊 3 gadi atpakaļ
vecāks
revīzija
9b08975d0a

+ 210 - 0
components/cm-module/cm-choose-address/cm-choose-address.vue

@@ -0,0 +1,210 @@
+<template>
+	<view class="address-template">
+		 <!-- 地址 -->
+		 <view @click="handleClick" class="address-section">
+			<view class="address-empty" v-if="isEmpty">
+			 	<text class="iconfont icon-tianjiadizhi"></text><text>添加收货地址</text>
+			</view>
+		 	<view class="address-content" v-else>
+		 		<view class="address-cen">
+		 			<view class="top">
+		 				<view class="name">{{addressData.shouHuoRen ? addressData.shouHuoRen : ''}}</view>
+		 				<view class="mobile">{{addressData.mobile ? addressData.mobile : ''}}</view>
+		 			</view>
+		 			<view class="address">
+						<view class="address-icon">
+							<text class="iconfont icon-shouhuodizhi"></text>
+						</view>
+						<view class="address-text">
+							收货地址:
+							{{addressData.provinceName ? addressData.provinceName : ''}}
+							{{addressData.cityName ? addressData.cityName : ''}}
+							{{addressData.townName ? addressData.townName : ''}}
+							{{addressData.address ? addressData.address : ''}}
+						</view>
+					</view>
+					<view class="nexpage" v-if="!disabled"><text class="iconfont icon-genghuan"></text></view>
+		 		</view>
+		 	</view>
+		 </view>
+		 <image  :src="StaticUrl+'icon-line.png'" mode=""></image>
+	</view>
+</template>
+
+<script>
+	export default{
+		name:'CmChoosAddress',
+		props:{
+			addressData:{
+				type:Object
+			},
+            disabled: {
+                type:Boolean,
+                default: false
+            }
+		},
+		data() {
+			return{
+				StaticUrl:this.$Static,
+				isEmpty:false,
+				addressSrc:'',
+			}
+		},
+		created(){
+			this.initData(this.addressData)
+		},
+		computed: {
+
+		},
+		watch:{
+			addressData:{
+				handler:function(val){
+					this.initData(val)
+				}
+			}
+		},
+		methods:{
+			initData(res) {
+				if(Object.keys(res).length == 0){
+					this.isEmpty = true
+					this.addressSrc = '/pages/user/address/addressManage'
+				}else{
+					this.isEmpty = false
+					this.$parent.isFreight = false
+					this.addressSrc = '/pages/user/address/address?type=select'
+				}
+			},
+            handleClick(){
+                if(this.disabled) return
+                this.$api.navigateTo(this.addressSrc)
+            }
+		}
+	}
+</script>
+
+<style lang="scss">
+	.address-template{
+		width: 100%;
+		height: auto;
+		background: #FFFFFF;
+		border-top: 1px solid #F8F8F8;
+        overflow: hidden;
+		image{
+			float: left;
+			width: 100%;
+			height: 6rpx;
+		}
+	}
+	.address-section {
+		width: 100%;
+		height: auto;
+		position: relative;
+		
+		.address-empty{
+			width: 100%;
+			height: 117rpx;
+			line-height: 117rpx;
+			color: $color-system;
+			text-align: center;
+			font-size: $font-size-26;
+			font-weight: bold;
+			background: #fff;
+			float: left;
+			.icon-tianjiadizhi{
+				font-size: 34rpx;
+				margin: 0 8rpx;
+			}
+		}
+		.address-content {
+			display: flex;
+			align-items: center;
+			padding:20rpx 24rpx;
+			background: #fff;
+		}
+		.icon-shouhuodizhi {
+			flex-shrink: 0;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			width: 40rpx;
+			color: $color-system;
+			font-size: 40rpx;
+			margin-right: 10rpx;
+		}	
+		.address-cen {
+			width: 100%;
+			height: auto;
+			position: relative;
+			.top{
+				padding-left: 50rpx;
+				height: 42rpx;
+				line-height: 42rpx;
+				text-align: left;
+				font-size: $font-size-30;
+				color: $text-color;
+				padding-bottom: 8rpx;
+				display: flex;
+				float: left;
+				.name{
+					font-weight: bold;
+					margin-right: 48rpx;
+				}
+				.mobile{
+					margin-right: 40rpx;
+					font-weight: bold;
+				}
+			}
+			.address {
+				width: 100%;
+				height: auto;
+				float: left;
+				.address-icon{
+					width: 40rpx;
+					height: auto;
+					float: left;
+					line-height: 40rpx;
+				}
+				.address-text{
+					width: 610rpx;
+					padding-left: 10rpx;
+					float: left;
+					line-height: 40rpx;
+					font-size: $font-size-28;
+					color: $text-color;
+					text-align: left;
+					-o-text-overflow: ellipsis;
+					text-overflow: ellipsis;
+					display: -webkit-box;
+					word-break: break-all;
+					-webkit-box-orient: vertical;
+					-webkit-line-clamp: 2;
+					overflow: hidden;
+				}
+			}
+			.nexpage{
+				text-align: right;
+				font-size: $font-size-30;
+				color: #666666;
+				position: absolute;
+				right: 0;
+				top: 45rpx;
+				.icon-genghuan{
+					font-size: $font-size-30;
+				}
+			}
+		}
+		.icon-chakangengduo {
+			font-size: 32rpx;
+			color: $text-color;
+			margin-right: 30rpx;
+		}
+		.a-bg {
+			position: absolute;
+			left: 0;
+			bottom: 0;
+			display: block;
+			width: 100%;
+			height: 5rpx;
+		}
+	}
+</style>

+ 104 - 0
components/cm-module/cm-order-control-nav/cm-order-control-nav.vue

@@ -0,0 +1,104 @@
+<template>
+    <view class="cm-order-control-nav">
+        <view class="btn type1" v-if="btnState.share" @click.stop="handleClick('share')">邀好友拼单</view>
+        <view class="btn type2" v-if="btnState.cancel" @click.stop="handleClick('cancel')">取消订单</view>
+        <view class="btn type2" v-if="btnState.delete" @click.stop="handleClick('delete')">删除订单</view>
+        <view class="btn type2" v-if="btnState.query" @click.stop="handleClick('query')">查看物流</view>
+        <view class="btn type1" v-if="btnState.pay" @click.stop="handleClick('pay')">付款</view>
+        <view class="btn type1" v-if="btnState.again" @click.stop="handleClick('again')">再次购买</view>
+        <!-- <view class="btn type1" @click="handleClick('again')">再次购买</view> -->
+        <view class="btn type2" v-if="btnState.confirm" @click.stop="handleClick('confirm')">确认收货</view>
+    </view>
+</template>
+
+<script>
+export default {
+    props: {
+        orderInfo: {
+            type: Object,
+            default: () => {}
+        }
+    },
+    data() {
+        return {
+            mapState: {
+                share: [],
+                query: [4, 5, 12, 13, 33, 22, 23, 32, 77],
+                delete: [6],
+                cancel: [0, 111],
+                confirm: [33],
+                again: [33],
+                pay: [11, 12, 13, 21, 22, 23, 111]
+            },
+            buttonCount: 0
+        }
+    },
+    computed: {
+        btnState() {
+            return this.initData()
+        }
+    },
+    watch:{
+        buttonCount(nVal){
+            this.$emit('change', {
+                count: nVal
+            })
+        }
+    },
+    methods: {
+        /**
+         * @分享按钮统一显示
+         * @按钮根据状态显示
+         * @(4、5、7、12、22、23、32)显示[查看物流]按钮,其他隐藏
+         * @(6)显示[删除订单],其他隐藏
+         * @(0、111)显示[取消订单],其他隐藏
+         * @(21,31)只显示分享
+         * @(13,33)显示[确认收货]和[查看物流]
+         */
+        initData(resVal) {
+            const btnState = {}
+            const orderStatus = parseInt(this.orderInfo.status)
+
+            for (let key in this.mapState) {
+                btnState[key] = this.mapState[key].includes(orderStatus)
+                if(btnState[key]) {
+                    this.buttonCount ++
+                }
+            }
+            return btnState
+        },
+        handleClick(type) {
+            this.$emit('confirm', { type, order: this.orderInfo })
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.cm-order-control-nav {
+    padding: 0 24rpx;
+    text-align: right;
+
+    .btn {
+        display: inline-block;
+        width: 160rpx;
+        height: 56rpx;
+        border-radius: 32rpx;
+        margin-left: 24rpx;
+        font-size: 26rpx;
+        box-sizing: border-box;
+        text-align: center;
+        line-height: 54rpx;
+
+        &.type1 {
+            border: 1rpx solid #ff457b;
+            color: #ff457b;
+        }
+
+        &.type2 {
+            border: 1rpx solid #333;
+            color: #333;
+        }
+    }
+}
+</style>

+ 38 - 0
components/cm-module/cm-order-coupon-section/cm-order-coupon-section.vue

@@ -0,0 +1,38 @@
+<template>
+    <view class="coupon section cm-order-coupon-section">
+        <view class="lable">优惠券</view>
+        <view class="content">
+            <text class="text">-¥30.00 </text> <text class="iconfont icon-chakangengduo"></text>
+        </view>
+    </view>
+</template>
+
+<script></script>
+
+<style lang="scss" scoped>
+.section {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+
+    padding: 0 24rpx;
+    line-height: 90rpx;
+    font-size: 28rpx;
+
+    background: #fff;
+
+    .label {
+        color: #333333;
+        font-weight: 500;
+    }
+
+    .content {
+        color: #ff457b;
+
+        .iconfont {
+            color: #b2b2b2;
+            margin-left: 8rpx;
+        }
+    }
+}
+</style>

+ 60 - 0
components/cm-module/cm-order-filter-control/cm-order-filter-control.vue

@@ -0,0 +1,60 @@
+<template>
+    <view class="filter">
+        <view
+            class="btn"
+            :class="{ active: active === btn.id }"
+            @click="handleClick(btn.id)"
+            v-for="(btn, index) in buttonGroup"
+            :key="index"
+            v-text="btn.name"
+        ></view>
+    </view>
+</template>
+
+<script>
+export default {
+    props: {
+        buttonGroup: {
+            type: Array,
+            default: () => []
+        }
+    },
+    data() {
+        return {
+            active: 0
+        }
+    },
+    methods: {
+        handleClick(index) {
+            this.active = index
+            this.$emit('click', { index })
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.filter {
+    height: 40px;
+    display: flex;
+    justify-content: space-around;
+    align-items: center;
+    background: #fff;
+
+    .btn {
+        height: 48rpx;
+        border-radius: 24rpx;
+        background: #f7f7f7;
+        line-height: 48rpx;
+        font-size: 26rpx;
+        color: #333333;
+        text-align: center;
+        padding: 0 24rpx;
+
+        &.active {
+            color: #ff457b;
+            background-color: #fff3f7;
+        }
+    }
+}
+</style>

+ 50 - 0
components/cm-module/cm-order-freight-section/cm-order-freight-section.vue

@@ -0,0 +1,50 @@
+<template>
+    <view class="freight section cm-order-freight-section">
+        <view class="lable">运费</view>
+        <view class="content">
+            <text class="text">包邮</text>
+        </view>
+    </view>
+</template>
+
+<script></script>
+
+<style lang="scss" scoped>
+.section {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+
+    padding: 0 24rpx;
+    line-height: 90rpx;
+    font-size: 28rpx;
+
+    background: #fff;
+
+    .label {
+        color: #333333;
+        font-weight: 500;
+    }
+
+    .content {
+        .iconfont {
+            color: #b2b2b2;
+            margin-left: 8rpx;
+        }
+    }
+
+    &.coupon {
+        .content {
+            color: #ff457b;
+        }
+    }
+
+    &.freight {
+        .content {
+            .text {
+                color: #2398ff;
+            }
+        }
+    }
+}
+</style>

+ 133 - 0
components/cm-module/cm-order-information/cm-order-information.vue

@@ -0,0 +1,133 @@
+<template>
+    <view class="detail">
+        <view class="title">订单信息:</view>
+        <view class="row">
+            <view class="col">
+                <view class="label">订单编号:</view>
+                <view class="content">
+                    <text>{{ orderInfo.orderNo }}</text> <text class="copy" @click="copyOrderNum">复制</text>
+                </view>
+            </view>
+        </view>
+        <view class="row">
+            <view class="col">
+                <view class="label">订单总额:</view>
+                <view class="content">¥{{ orderInfo.payTotalFee | formatPrice }}</view>
+            </view>
+        </view>
+        <view class="row">
+            <view class="col">
+                <view class="label">下单时间:</view> <view class="content">{{ orderInfo.orderTime }}</view>
+            </view>
+            <view class="col"> <view class="label">运费:</view> <view class="content">包邮</view> </view>
+        </view>
+        <view class="row">
+            <view class="col" v-if="orderInfo.receiptDate">
+                <view class="label">支付时间:</view> <view class="content"> {{ orderInfo.receiptDate }} </view>
+            </view>
+            <view class="col"> <view class="label">分享减免:</view> <view class="content">¥100.00</view> </view>
+        </view>
+        <view class="row">
+            <view class="col" v-if="orderInfo.couponAmount">
+                <view class="label">优惠券:</view>
+                <view class="content">¥{{ orderInfo.couponAmount | formatPrice }}</view>
+            </view>
+            <view class="col">
+                <view class="label">已退货/已取消:</view>
+                <view class="content">{{ orderInfo.returnedNum }}/{{ orderInfo.actualCancelNum }}</view>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+export default {
+    props: {
+        orderInfo: {
+            type: Object,
+            default: () => {}
+        }
+    },
+    filters: {
+        formatPrice(price) {
+            if (!price) return '0.00'
+            return Number(price).toFixed(2)
+        }
+    },
+    methods: {
+        copyOrderNum() {
+            uni.setClipboardData({
+                data: this.orderInfo.orderNo,
+                success: () => {
+                    this.$util.msg('复制成功', 2000, true, 'success')
+                },
+                fail: () => {
+                    this.$util.msg('复制失败', 2000, true, 'none')
+                }
+            })
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.detail {
+    padding: 24rpx;
+    background: #fff;
+    line-height: 1.6;
+
+    .title {
+        display: flex;
+        align-items: center;
+
+        margin-bottom: 32rpx;
+
+        font-size: 30rpx;
+        color: #333333;
+
+        &::before {
+            content: '';
+            display: block;
+            width: 6rpx;
+            height: 22rpx;
+            background: #ff457b;
+            border-radius: 3rpx;
+            margin-right: 8rpx;
+        }
+    }
+    .row {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 8rpx 0;
+
+        font-size: 26rpx;
+        color: #333333;
+
+        .label {
+            color: #999999;
+        }
+        .content {
+            position: relative;
+            .copy {
+                display: inline-block;
+                line-height: 40rpx;
+                width: 80rpx;
+                height: 40rpx;
+                margin-left: 40rpx;
+                background: #fff8fd;
+                border-radius: 8px;
+
+                font-size: 24rpx;
+                color: #ff457b;
+                vertical-align: middle;
+                text-align: center;
+            }
+        }
+        .col {
+            display: flex;
+            align-items: center;
+        }
+    }
+}
+</style>

+ 124 - 0
components/cm-module/cm-order-invalid-modal/cm-order-invalid-modal.vue

@@ -0,0 +1,124 @@
+<template>
+    <!-- 再次购买部分商品失效弹窗 -->
+    <tui-modal :show="visible" @cancel="$emit('cancel')" :custom="true">
+        <view class="tui-modal">
+            <view class="goods-list">
+                <view class="title">以下商品已失效,不能进行购买;是否先将其他商品加入购物车?</view>
+                <scroll-view scroll-y class="goods-list-scroll">
+                    <view class="goods-section" v-for="(goods, index) in goodsList" :key="index">
+                        <image :src="goods.productImage" class="goods-cover"></image>
+                        <view class="goods-title">{{ goods.name }}</view>
+                    </view>
+                </scroll-view>
+            </view>
+            <view class="tui-modal-button">
+                <button class="modal-button cancel" @click="handleClick(0)">我再想想</button>
+                <button class="modal-button confirm" @click="handleClick(1)">加入购物车</button>
+            </view>
+        </view>
+    </tui-modal>
+</template>
+
+<script>
+export default {
+    props: {
+        goodsList: {
+            type: Array,
+            default: () => []
+        },
+        visible: {
+            type: Boolean,
+            default: false
+        }
+    },
+    methods: {
+        handleClick(type) {
+            this.$emit('confirm', { index: type })
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.tui-modal {
+    .goods-list {
+        margin-bottom: 30rpx;
+
+        .title {
+            width: 100%;
+            height: auto;
+            font-size: 30rpx;
+            text-align: justify;
+            color: #333333;
+            line-height: 1.6;
+            margin-bottom: 30rpx;
+        }
+
+        .goods-list-scroll {
+            width: 100%;
+            max-height: 350rpx;
+
+            .goods-section {
+                width: 100%;
+                
+                display: flex;
+                justify-content: space-between;
+                align-items: center;
+
+                margin-top: 24rpx;
+                
+                &:first-child{
+                    margin-top: 0;
+                }
+
+                .goods-cover {
+                    display: block;
+                    width: 86rpx;
+                    height: 86rpx;
+
+                    border-radius: 6rpx;
+                    border: 1px solid #e1e1e1;
+                    box-sizing: border-box;
+                }
+
+                .goods-title {
+                    flex: 1;
+                    height: 86rpx;
+                    margin-left: 18rpx;
+                    line-height: 1.6;
+                    font-size: 26rpx;
+                    color: #666666;
+                    text-overflow: ellipsis;
+                    text-align: justify;
+                    overflow: hidden;
+                    display: -webkit-box;
+                    -webkit-line-clamp: 2;
+                    line-clamp: 2;
+                    -webkit-box-orient: vertical;
+                }
+            }
+        }
+    }
+    .tui-modal-button {
+        width: 100%;
+        height: 72rpx;
+        display: flex;
+        .modal-button {
+            width: 200rpx;
+            height: 72rpx;
+            line-height: 72rpx;
+            border-radius: 36rpx;
+            box-sizing: border-box;
+            &.cancel {
+                border: 1px solid #b2b2b2;
+                background: #ffffff;
+                color: #333333;
+            }
+            &.confirm {
+                background: $btn-confirm;
+                color: #ffffff;
+            }
+        }
+    }
+}
+</style>

+ 148 - 0
components/cm-module/cm-order-prodcut/cm-order-prodcut.vue

@@ -0,0 +1,148 @@
+<template>
+    <view class="cm-order-prodcut">
+        <image :src="goodsData.productImage" class="cover"></image>
+        <view class="content">
+            <view class="title">{{ goodsData.name}}</view>
+            <view class="unit">规格:{{ goodsData.productUnit }}</view>
+            <view class="tags">
+                <view class="tag type1">促销</view>
+                <view class="tag type1">自营</view>
+                <view class="tag type3">拼团价</view> 
+                <view class="tag type2">活动价</view>
+                <view class="tag type2">优惠券</view>
+            </view>
+            <view class="price"> 
+                <text>¥{{ goodsData.price | formatPrice }}</text> 
+                <text class="delete">单买价:¥400.00</text> 
+            </view>
+        </view>
+        <text class="count" v-if="countVisible">×{{ goodsData.num }}</text>
+    </view>
+</template>
+
+<script>
+export default {
+    props:{
+        countVisible: {
+            type: Boolean,
+            default: true
+        },
+        goodsData: {
+            type: Object,
+            default:()=>{}
+        }
+    },
+    filters:{
+      formatPrice(price){
+          if(!price) return ''
+          return Number(price).toFixed(2)
+      }  
+    },
+    data() {
+        return {}
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+/* scss中可以用mixin来扩展 */
+@mixin ellipsis($line: 1) {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    display: -webkit-box;
+    -webkit-line-clamp: $line;
+    -webkit-box-orient: vertical;
+}
+
+.cm-order-prodcut {
+    position: relative;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 0 24rpx;
+    
+    overflow: hidden;
+
+    .count{
+        position: absolute;
+        font-size: 26rpx;
+        color: #333333;
+        right: 24rpx;
+        bottom: 0;
+    }
+
+
+    .cover {
+        display: block;
+        width: 180rpx;
+        height: 180rpx;
+        border-radius: 8rpx;
+        box-sizing: border-box;
+        border: 1px solid #F7F7F7;
+    }
+
+    .content {
+        flex: 1;
+        margin-left: 24rpx;
+        .title {
+            @include ellipsis(2);
+            font-size: 26rpx;
+            color: #333333;
+            text-align: justify;
+            line-height: 1.6;
+            height: 80rpx;
+        }
+        .unit {
+            margin-bottom: 8rpx;
+            font-size: 20rpx;
+            color: #999999;
+        }
+        .price {
+            margin-top: 4rpx;
+            font-size: 26rpx;
+            color: #ff457b;
+            .delete {
+                margin-left: 32rpx;
+                font-size: 20rpx;
+                color: #999999;
+            }
+        }
+
+        .tags {
+            display: flex;
+            justify-content: flex-start;
+            align-items: center;
+            width: 100%;
+            height: 30rpx;
+            .tag {
+                margin-right: 8rpx;
+                font-size: 22rpx;
+                height: 30rpx;
+                line-height: 30rpx;
+                text-align: center;
+                
+                &.type1{
+                    padding: 0 8rpx;
+                    background: #f83c6c;
+                    border-radius: 4rpx;
+                    color: #fff;
+                }
+                
+                &.type2 {
+                    width: 80rpx;
+                    color: #f83c6c;
+                    background: url(https://static.caimei365.com/app/mini-hehe/icon/icon-active.png) top center
+                        no-repeat;
+                    background-size: contain;
+                }
+                &.type3 {
+                    width: 80rpx;
+                    background: linear-gradient(270deg, #ff457b 0%, #b03bb8 51%, #6431f2 100%);
+                    color: #fff;
+                    border-radius: 4rpx;
+                }
+            }
+        }
+    }
+}
+</style>

+ 67 - 0
components/cm-module/cm-order-submit-nav/cm-order-submit-nav.vue

@@ -0,0 +1,67 @@
+<template>
+    <view class="cm-order-submit-nav submit">
+        <view class="count">共1件商品</view>
+        <view class="total">
+            <view class="price"> <text class="label">总计:</text> <text>¥200.00</text> </view>
+            <view class="reduce"> <text class="label">共减:</text> <text>¥20.00</text> </view>
+        </view>
+        <button class="btn">提交订单</button>
+    </view>
+</template>
+
+<script></script>
+
+<style lang="scss" scoped>
+.submit {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    box-sizing: border-box;
+    position: fixed;
+    width: 100%;
+    height: 100rpx;
+    bottom: 0;
+    left: 0;
+
+    padding: 0 24rpx;
+    background: #fff;
+
+    .count {
+        font-size: 28rpx;
+        color: #333333;
+    }
+    .total {
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: flex-start;
+
+        margin: 0 24rpx;
+
+        .price {
+            font-size: 26rpx;
+            color: #ff457b;
+
+            .label {
+                color: #333333;
+            }
+        }
+        .reduce {
+            margin-top: 4rpx;
+            font-size: 24rpx;
+            color: #ff457b;
+        }
+    }
+    .btn {
+        width: 210rpx;
+        height: 80rpx;
+        background: linear-gradient(90deg, #fa55bf 0%, #f83c6c 100%);
+        opacity: 1;
+        color: #fff;
+        line-height: 80rpx;
+        text-align: center;
+        border-radius: 40rpx;
+        margin: 0;
+    }
+}
+</style>

+ 44 - 0
pages/fight-order/components/countdown-box.vue

@@ -0,0 +1,44 @@
+<template>
+    <view class="countdown-box">
+        <view class="hour">23</view> <text>:</text> <view class="minute">59</view> <text>:</text>
+        <view class="second">59</view> <text>后结束</text>
+    </view>
+</template>
+
+<script></script>
+
+<style lang="scss" scoped>
+.flex-center-box {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+.countdown-box {
+    @extend .flex-center-box;
+    .hour,
+    .minute,
+    .second {
+        text-align: center;
+        align-items: center;
+        width: 48rpx;
+        height: 48rpx;
+        background: #ff457b;
+        border-radius: 50%;
+        color: #fff;
+        font-size: 26rpx;
+        line-height: 48rpx;
+    }
+    text {
+        margin: 0 8rpx;
+        font-size: 30rpx;
+        color: #ff457b;
+        font-size: 26rpx;
+        &:last-child {
+            margin-right: 0;
+            margin-left: 16rpx;
+            color: #333333;
+            font-size: 30rpx;
+        }
+    }
+}
+</style>

+ 70 - 0
pages/fight-order/components/user-list.vue

@@ -0,0 +1,70 @@
+<template>
+    <view class="user-list">
+        <view class="user first">
+            <image src="https://picsum.photos/100/100?random=1" class="user-head"></image> <text>拼主</text>
+        </view>
+        <view class="user"> <image src="https://picsum.photos/100/100?random=2" class="user-head"></image> </view>
+    </view>
+</template>
+
+<script></script>
+
+<style lang="scss" scoped>
+.flex-center-box {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+.user-list {
+    @extend .flex-center-box;
+    .user {
+        @extend .flex-center-box;
+        position: relative;
+        width: 100rpx;
+        height: 100rpx;
+
+        border-radius: 50%;
+
+        border: 2rpx dashed #cccccc;
+        border-radius: 50%;
+        box-sizing: border-box;
+
+        &::before {
+            content: '?';
+            font-size: 36rpx;
+            color: #999999;
+        }
+
+        &.first {
+            margin-right: 32rpx;
+        }
+
+        .user-head {
+            position: absolute;
+            left: -2rpx;
+            top: -2rpx;
+            z-index: 1;
+            display: block;
+            width: 100rpx;
+            height: 100rpx;
+            border-radius: 50%;
+        }
+
+        text {
+            @extend .flex-center-box;
+            position: absolute;
+            left: -20rpx;
+            top: 0;
+            z-index: 2;
+            width: 56rpx;
+            height: 28rpx;
+            background: #ff457b;
+            border: 1rpx solid #ffffff;
+            border-radius: 14rpx;
+            font-size: 20rpx;
+            color: #ffffff;
+        }
+    }
+}
+</style>

+ 148 - 0
pages/fight-order/fight-create-order.vue

@@ -0,0 +1,148 @@
+<template>
+    <view class="figth-create-order">
+        <!-- 收货地址 -->
+        <cm-choose-address :addressData="addressData"></cm-choose-address>
+        <view class="grid"></view>
+        <!-- 订单列表 -->
+        <view class="order-list">
+            <view class="order-section">
+                <!-- 供应商 -->
+                <view class="origin">
+                    <image class="cover" src="https://picsum.photos/100/100?random=1"></image>
+                    <view class="name">华熙生物</view>
+                </view>
+                <!-- 商品列表 -->
+                <view class="goods-list">
+                    <!-- 商品信息 -->
+                    <view class="order-goods"><cm-order-prodcut></cm-order-prodcut></view>
+                    <view class="order-goods"><cm-order-prodcut></cm-order-prodcut></view>
+                </view>
+                <!-- 合计 -->
+                <view class="total-price"> <text>合计:</text> <text class="price">¥900.00</text> </view>
+                <!-- 留言 -->
+                <view class="remark">
+                    <view class="label">留言:</view> <input class="control" type="text" placeholder="请输入内容" />
+                </view>
+            </view>
+        </view>
+        <view class="grid"></view>
+        <!-- 优惠券 -->
+        <cm-order-coupon-section></cm-order-coupon-section>
+        <view class="grid"></view>
+        <!-- 运费 -->
+        <cm-order-freight-section></cm-order-freight-section>
+        <!-- 提交导航 -->
+        <cm-order-submit-nav></cm-order-submit-nav>
+    </view>
+</template>
+
+<script>
+import CmChooseAddress from '@/components/cm-module/cm-choose-address/cm-choose-address.vue'
+import CmOrderProdcut from '@/components/cm-module/cm-order-prodcut/cm-order-prodcut.vue'
+import CmOrderSubmitNav from '@/components/cm-module/cm-order-submit-nav/cm-order-submit-nav.vue'
+import CmOrderCouponSection from '@/components/cm-module/cm-order-coupon-section/cm-order-coupon-section.vue'
+import CmOrderFreightSection from '@/components/cm-module/cm-order-freight-section/cm-order-freight-section.vue'
+
+export default {
+    components: {
+        CmOrderProdcut,
+        CmChooseAddress,
+        CmOrderSubmitNav,
+        CmOrderCouponSection,
+        CmOrderFreightSection
+    },
+    data() {
+        return {
+            addressData: {}
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.figth-create-order {
+    background: #f7f7f7;
+    min-height: 100vh;
+}
+
+.grid {
+    width: 100%;
+    height: 20rpx;
+    background: #f7f7f7;
+}
+
+.order-list {
+    background: #fff;
+
+    .order-section {
+        padding: 38rpx 0;
+        margin-top: 20rpx;
+        &:first-child {
+            margin-top: 0;
+        }
+    }
+
+    .goods-list {
+        .order-goods {
+            padding-top: 32rpx;
+            &:first-child {
+                padding-top: 0;
+            }
+        }
+    }
+
+    .origin {
+        padding: 0 24rpx;
+        margin-bottom: 16rpx;
+        display: flex;
+        justify-content: flex-start;
+        align-items: center;
+        .cover {
+            width: 56rpx;
+            height: 56rpx;
+            border-radius: 4rpx;
+        }
+        .name {
+            margin-left: 16rpx;
+            font-size: 30rpx;
+            color: #333333;
+        }
+    }
+}
+
+.total-price {
+    padding: 24rpx;
+    text-align: right;
+    font-size: 26rpx;
+    color: #333;
+    background: #fff;
+
+    .price {
+        color: #ff457b;
+    }
+}
+
+.remark {
+    padding: 0 24rpx;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    background: #fff;
+
+    .label {
+        width: 78rpx;
+        font-size: 26rpx;
+        color: #999999;
+        margin-right: 16rpx;
+    }
+
+    .control {
+        flex: 1;
+        font-size: 26rpx;
+        color: #333333;
+        padding: 8rpx 16rpx;
+        background: #f7f7f7;
+        border-radius: 8rpx;
+    }
+}
+</style>

+ 229 - 0
pages/fight-order/fight-detail.vue

@@ -0,0 +1,229 @@
+<template>
+    <view class="fight-detail">
+        <view class="row">
+            <view class="fight-tip">
+                <view class="success" v-if="success">恭喜您,拼团成功!</view>
+                <view v-else>还差<text>1</text>人,赶快邀请好友来拼单吧!</view>
+            </view>
+            
+            <!-- 成功 -->
+            <template v-if="success">
+                <user-list></user-list>
+            </template>
+            <!-- 等待完成 -->
+            <template v-else>
+               <!-- 倒计时 -->
+               <countdown-box></countdown-box>
+            </template>
+            
+            <!-- 操作 -->
+            <view class="fight-control success" v-if="success">
+                <view class="btn type1" @click="handleClick(1)">去首页逛逛</view>
+                <view class="link" @click="handleClick(3)">查看订单详情 ></view>
+            </view>
+            <view class="fight-control" v-else>
+                <button class="btn type1" @click="handleClick(2)">邀请好友拼单</button>
+                <view class="btn type2" @click="handleClick(1)">去首页逛逛</view>
+            </view>
+            
+            <!-- 商品 + 用户信息 -->
+            <template v-if="!success">
+                <view class="grid"></view>
+                <!-- 拼单用户列表 -->
+                <user-list></user-list>
+                <view class="line"></view>
+                <view class="goods-info">
+                    <image src="https://picsum.photos/100/100?random=3" class="cover"></image>
+                    <view class="title">肌本演绎360愉悦修护套组 PLUS 尊享版防晒修复 补水保湿</view>
+                </view>
+            </template>
+        </view>
+    </view>
+</template>
+
+<script>
+import UserList from './components/user-list.vue'
+import CountdownBox from './components/countdown-box.vue'
+export default {
+    components: {
+        UserList,
+        CountdownBox
+    },
+    computed:{
+        success(){
+            return true
+        }
+    },
+    data(){
+        return{}
+    },
+    onShareTimeline(e) {
+        // 加密参数
+        const shareData = {
+            type: 4,
+            inviteUserId: this.userId
+        }
+        // 加密
+        const state_str = encodeURIComponent(this.$crypto.encrypt(shareData))
+        return {
+            title: '哈喽,赶快来参团吧!这件商品拼团买更便宜~~',
+            path: `pages/tabBar/index/index?state_str=${state_str}`,
+            imageUrl: 'https://picsum.photos/400/400?random=3'
+        }
+    },
+    onShareAppMessage(e) {
+        // 加密参数
+        const shareData = {
+            type: 4,
+            inviteUserId: this.userId
+        }
+        // 加密
+        const state_str = encodeURIComponent(this.$crypto.encrypt(shareData))
+        return {
+            title: '哈喽,赶快来参团吧!这件商品拼团买更便宜~~',
+            path: `pages/tabBar/index/index?state_str=${state_str}`,
+            imageUrl: 'https://picsum.photos/400/400?random=3'
+        }
+    },
+    methods:{
+        handleClick(type){
+            const clickFunc = {
+                1: this.toHome,
+                2: this.toShare,
+                3: this.toOrder
+            }
+            clickFunc[type].apply(this)
+        },
+        // 跳转首页
+        toHome(){
+            console.log('首页')
+        },
+        // 分享
+        toShare(){
+            console.log('分享')
+        },
+        // 跳转订单
+        toOrder(){
+            console.log('订单')
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+/* scss中可以用mixin来扩展 */
+@mixin ellipsis($line: 1) {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    display: -webkit-box;
+    -webkit-line-clamp: $line;
+    -webkit-box-orient: vertical;
+}
+
+.flex-center-box {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+.fight-detail {
+    background: #f7f7f7;
+    min-height: 100vh;
+    
+    .row{
+        background: #fff;
+        overflow: hidden;
+    }
+    
+    .fight-tip {
+        @extend .flex-center-box;
+        margin-top: 70rpx;
+        margin-bottom: 48rpx;
+        font-size: 30rpx;
+        font-weight: 400;
+        color: #333333;
+        text {
+            color: #ff457b;
+        }
+        .success{
+            font-size: 34rpx;
+            color: #333333;
+            font-weight: bold;
+        }
+    }
+
+    .fight-control {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        flex-direction: column;
+        margin-top: 48rpx;
+        margin-bottom: 48rpx;
+        
+        .success{
+            margin-bottom: 66rpx;
+        }
+        
+        .link{
+            margin-top: 24rpx;
+            font-size: 26rpx;
+            line-height: 38rpx;
+            color: #999999;
+        }
+        .btn {
+            @extend .flex-center-box;
+            width: 600rpx;
+            height: 90rpx;
+            border-radius: 45rpx;
+            box-sizing: border-box;
+            font-size: 30rpx;
+
+            &.type1 {
+                color: #ffffff;
+                background: linear-gradient(90deg, #fc32b4 0%, #f83c6c 100%);
+            }
+            &.type2 {
+                margin-top: 24rpx;
+                color: #ff457b;
+                border: 1px solid #ff457b;
+            }
+        }
+    }
+
+    .grid {
+        margin: 48rpx 0 48rpx;
+        width: 750rpx;
+        height: 20rpx;
+        background: #f7f7f7;
+    }
+
+    .line {
+        width: 702rpx;
+        height: 1px;
+        margin: 48rpx auto 48rpx auto;
+        background: #e1e1e1;
+    }
+
+    .goods-info {
+        @extend .flex-center-box;
+        padding: 0 24rpx 48rpx;
+        .cover {
+            width: 80rpx;
+            height: 80rpx;
+            background: eee;
+            border: 1rpx solid #e1e1e1;
+            border-radius: 8rpx;
+            border: 50%;
+        }
+        .title {
+            flex: 1;
+            margin-left: 24rpx;
+            word-break: break-word;
+            font-size: 26rpx;
+            line-height: 1.6;
+            color: #333333;
+            text-align: justify;
+            @include ellipsis(2);
+        }
+    }
+}
+</style>

+ 230 - 0
pages/fight-order/fight-share-entry.vue

@@ -0,0 +1,230 @@
+<template>
+    <view class="fight-share-entry">
+        <view class="row">
+            <!-- 商品信息 -->
+            <cm-order-prodcut :countVisible="false"></cm-order-prodcut>
+            
+            <view class="service">
+                <view class="iconfont icon-wuyoushouhou"><text>无忧退货</text></view>
+                <view class="iconfont icon-wuyoushouhou"><text>快速退款</text></view>
+                <view class="iconfont icon-wuyoushouhou"><text>正品保证</text></view>
+            </view>
+            
+            
+            <view class="grid t0b48"></view>
+            
+            <view class="fight-tip">还差<text>1</text>人,赶快邀请好友来拼单吧!</view>
+            <!-- 倒计时 -->
+            <countdown-box></countdown-box>
+
+            <!-- 操作 -->
+            <view class="fight-control">
+                <button class="btn type1" @click="handleClick">立即参团</button>
+            </view>
+
+            <view class="grid t48b48"></view>
+            <!-- 拼单用户列表 -->
+            <user-list></user-list>
+            <view class="line"></view>
+            <view class="goods-info">
+                <image src="https://picsum.photos/100/100?random=3" class="cover"></image>
+                <view class="title">肌本演绎360愉悦修护套组 PLUS 尊享版防晒修复 补水保湿</view>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+import UserList from './components/user-list.vue'
+import CountdownBox from './components/countdown-box.vue'
+import CmOrderProdcut from '@/components/cm-module/cm-order-prodcut/cm-order-prodcut.vue'
+export default {
+    components: {
+        UserList,
+        CountdownBox,
+        CmOrderProdcut
+    },
+    computed: {
+        
+    },
+    data() {
+        return {}
+    },
+    onShareTimeline(e) {
+        // 加密参数
+        const shareData = {
+            type: 4,
+            inviteUserId: this.userId
+        }
+        // 加密
+        const state_str = encodeURIComponent(this.$crypto.encrypt(shareData))
+        return {
+            title: '哈喽,赶快来参团吧!这件商品拼团买更便宜~~',
+            path: `pages/tabBar/index/index?state_str=${state_str}`,
+            imageUrl: 'https://picsum.photos/400/400?random=3'
+        }
+    },
+    onShareAppMessage(e) {
+        // 加密参数
+        const shareData = {
+            type: 4,
+            inviteUserId: this.userId
+        }
+        // 加密
+        const state_str = encodeURIComponent(this.$crypto.encrypt(shareData))
+        return {
+            title: '哈喽,赶快来参团吧!这件商品拼团买更便宜~~',
+            path: `pages/tabBar/index/index?state_str=${state_str}`,
+            imageUrl: 'https://picsum.photos/400/400?random=3'
+        }
+    },
+    methods: {
+        handleClick(type) {
+            console.log('拼单')
+        },
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+/* scss中可以用mixin来扩展 */
+@mixin ellipsis($line: 1) {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    display: -webkit-box;
+    -webkit-line-clamp: $line;
+    -webkit-box-orient: vertical;
+}
+
+.flex-center-box {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+.fight-share-entry {
+    background: #f7f7f7;
+    min-height: 100vh;
+
+    .row {
+        padding-top: 48rpx;
+        background: #fff;
+        overflow: hidden;
+    }
+   
+    .service {
+        display: flex;
+        justify-content: space-around;
+        align-items: center;
+        color: #ff457b;
+        width: 750rpx;
+        height: 72rpx;
+        padding: 0 24rpx;
+        margin-top: 64rpx;
+        background: #FFF8FD;
+        opacity: 1;
+        box-sizing: border-box;
+        
+        .iconfont {
+            font-size: 24rpx;
+            line-height: 24rpx;
+            text {
+                color: #FF457B;
+                margin-left: 4rpx;
+            }
+        }
+    }
+    
+    
+
+    .fight-tip {
+        @extend .flex-center-box;
+        margin-top: 48rpx;
+        margin-bottom: 32rpx;
+        font-size: 30rpx;
+        font-weight: 400;
+        color: #333333;
+        text {
+            color: #ff457b;
+        }
+    }
+
+    .fight-control {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        flex-direction: column;
+        margin-top: 40rpx;
+        margin-bottom: 48rpx;
+
+        .link {
+            margin-top: 24rpx;
+            font-size: 26rpx;
+            line-height: 38rpx;
+            color: #999999;
+        }
+        .btn {
+            @extend .flex-center-box;
+            width: 600rpx;
+            height: 90rpx;
+            border-radius: 45rpx;
+            box-sizing: border-box;
+            font-size: 30rpx;
+
+            &.type1 {
+                color: #ffffff;
+                background: linear-gradient(90deg, #fc32b4 0%, #f83c6c 100%);
+            }
+            &.type2 {
+                margin-top: 24rpx;
+                color: #ff457b;
+                border: 1px solid #ff457b;
+            }
+        }
+    }
+
+    .grid {
+        width: 750rpx;
+        height: 20rpx;
+        background: #f7f7f7;
+        &.t48b48{
+            margin-top: 48rpx;
+            margin-bottom: 48rpx;
+        }
+        
+        &.t0b48{
+            margin-top: 0;
+            margin-bottom: 48rpx;
+        }
+    }
+
+    .line {
+        width: 702px;
+        height: 1px;
+        margin: 32rpx auto 24rpx auto;
+        background: #e1e1e1;
+    }
+
+    .goods-info {
+        @extend .flex-center-box;
+        padding: 0 24rpx 40rpx;
+        .cover {
+            width: 80rpx;
+            height: 80rpx;
+            background: eee;
+            border: 1rpx solid #e1e1e1;
+            border-radius: 8rpx;
+            border: 50%;
+        }
+        .title {
+            flex: 1;
+            margin-left: 24rpx;
+            word-break: break-word;
+            font-size: 26rpx;
+            line-height: 1.6;
+            color: #333333;
+            text-align: justify;
+            @include ellipsis(2);
+        }
+    }
+}
+</style>

+ 148 - 0
pages/order/create-order.vue

@@ -0,0 +1,148 @@
+<template>
+    <view class="create-order">
+        <!-- 收货地址 -->
+        <cm-choose-address :addressData="addressData"></cm-choose-address>
+        <view class="grid"></view>
+        <!-- 订单列表 -->
+        <view class="order-list">
+            <view class="order-section">
+                <!-- 供应商 -->
+                <view class="origin">
+                    <image class="cover" src="https://picsum.photos/100/100?random=1"></image>
+                    <view class="name">华熙生物</view>
+                </view>
+                <!-- 商品列表 -->
+                <view class="goods-list">
+                    <!-- 商品信息 -->
+                    <view class="order-goods"><cm-order-prodcut></cm-order-prodcut></view>
+                    <view class="order-goods"><cm-order-prodcut></cm-order-prodcut></view>
+                </view>
+                <!-- 合计 -->
+                <view class="total-price"> <text>合计:</text> <text class="price">¥900.00</text> </view>
+                <!-- 留言 -->
+                <view class="remark">
+                    <view class="label">留言:</view> <input class="control" type="text" placeholder="请输入内容" />
+                </view>
+            </view>
+        </view>
+        <view class="grid"></view>
+        <!-- 优惠券 -->
+        <cm-order-coupon-section></cm-order-coupon-section>
+        <view class="grid"></view>
+        <!-- 运费 -->
+        <cm-order-freight-section></cm-order-freight-section>
+        <!-- 提交导航 -->
+        <cm-order-submit-nav></cm-order-submit-nav>
+    </view>
+</template>
+
+<script>
+import CmChooseAddress from '@/components/cm-module/cm-choose-address/cm-choose-address.vue'
+import CmOrderProdcut from '@/components/cm-module/cm-order-prodcut/cm-order-prodcut.vue'
+import CmOrderSubmitNav from '@/components/cm-module/cm-order-submit-nav/cm-order-submit-nav.vue'
+import CmOrderCouponSection from '@/components/cm-module/cm-order-coupon-section/cm-order-coupon-section.vue'
+import CmOrderFreightSection from '@/components/cm-module/cm-order-freight-section/cm-order-freight-section.vue'
+
+export default {
+    components: {
+        CmOrderProdcut,
+        CmChooseAddress,
+        CmOrderSubmitNav,
+        CmOrderCouponSection,
+        CmOrderFreightSection
+    },
+    data() {
+        return {
+            addressData: {}
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.create-order {
+    background: #f7f7f7;
+    min-height: 100vh;
+}
+
+.grid {
+    width: 100%;
+    height: 20rpx;
+    background: #f7f7f7;
+}
+
+.order-list {
+    background: #fff;
+
+    .order-section {
+        padding: 38rpx 0;
+        margin-top: 20rpx;
+        &:first-child {
+            margin-top: 0;
+        }
+    }
+
+    .goods-list {
+        .order-goods {
+            padding-top: 32rpx;
+            &:first-child {
+                padding-top: 0;
+            }
+        }
+    }
+
+    .origin {
+        padding: 0 24rpx;
+        margin-bottom: 16rpx;
+        display: flex;
+        justify-content: flex-start;
+        align-items: center;
+        .cover {
+            width: 56rpx;
+            height: 56rpx;
+            border-radius: 4rpx;
+        }
+        .name {
+            margin-left: 16rpx;
+            font-size: 30rpx;
+            color: #333333;
+        }
+    }
+}
+
+.total-price {
+    padding: 24rpx;
+    text-align: right;
+    font-size: 26rpx;
+    color: #333;
+    background: #fff;
+
+    .price {
+        color: #ff457b;
+    }
+}
+
+.remark {
+    padding: 0 24rpx;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    background: #fff;
+
+    .label {
+        width: 78rpx;
+        font-size: 26rpx;
+        color: #999999;
+        margin-right: 16rpx;
+    }
+
+    .control {
+        flex: 1;
+        font-size: 26rpx;
+        color: #333333;
+        padding: 8rpx 16rpx;
+        background: #f7f7f7;
+        border-radius: 8rpx;
+    }
+}
+</style>

+ 165 - 0
pages/order/mixins/orderList.js

@@ -0,0 +1,165 @@
+const orderList = {
+    data() {
+        return {
+            hanldOrder: {}, // 当前要处理的订单信息
+            modal: false,
+            modalText: '',
+            buyAgainModal: false,
+            invalidList: [], // 失效商品列表
+        }
+    },
+
+    methods: {
+        // 操作订单
+        handleConfirmClick(e) {
+            const { type, order } = (this.hanldOrder = e)
+            switch (type) {
+            // 其他操作
+            case 'again':
+                this.buyAgain()
+                break
+            case 'share':
+                this.handleShare()
+                break
+            case 'query':
+                this.isModalLayer = true
+                this.$api.navigateTo('/pages/order/order-logistics?orderId=' + order.orderId)
+                break
+                // 常规操作
+            case 'cancel':
+                this.modal = true
+                this.modalText = '确认取消该订单吗?'
+                break
+            case 'delete':
+                this.modal = true
+                this.modalText = '确认删除该订单吗?'
+                break
+            case 'confirm':
+                this.modal = true
+                this.modalText = '是否确认收货?'
+                break
+            case 'pay':
+                this.modal = true
+                this.modalText = '确认支付?'
+                break
+            }
+        },
+        // 确认收货
+        handleConfirm(order) {
+            console.log('确认收货')
+            return this.OrderService.ConfirmReceipt({ orderId: order.orderId })
+        },
+        // 取消订单
+        handleCancel(order) {
+            console.log('取消订单')
+            return this.OrderService.CancelOrder({ orderId: order.orderId })
+        },
+        // 删除订单
+        handleDelete(order) {
+            console.log('删除订单')
+            return this.OrderService.DeleteOrder({ orderId: order.orderId })
+        },
+        // 支付订单
+        handlePay(order) {
+            console.log('支付')
+            this.miniWxPayFor(order)
+        },
+        // 再次购买初始化查询订单商品信息
+        handleAgain(order) {
+            console.log('再次购买初始化查询订单商品信息')
+            return this.OrderService.GetOrderBuyAgain({ orderId: order.orderId })
+        },
+        // 查看物流
+        handleQuery(order) {
+            console.log('查看物流')
+        },
+        // 分享
+        handleShare(order) {
+            console.log('分享')
+        },
+        // 再次购买
+        async buyAgain() {
+            const { type, order } = this.hanldOrder
+            try {
+                await this.handleAgain(order)
+                this.joinToCart(order)
+            } catch (error) {
+                if (error.data && error.data.length > 0) {
+                    this.buyAgainModal = true
+                    this.invalidList = error.data
+                }
+            }
+        },
+
+        // 确认再次购买
+        buyAgainModalClick(e) {
+            this.buyAgainModal = false
+            if (!e.index) return
+            this.joinToCart(this.hanldOrder.order)
+        },
+
+        // 再次购买弹窗关闭
+        buyAgainModalHide() {
+            console.log('再次购买弹窗关闭')
+            this.invalidList = []
+        },
+
+        // 一键加入购物车
+        async joinToCart(order) {
+            try {
+                await this.ProductService.ShoppingAgainCart({ orderId: order.orderId })
+                this.$store.dispatch('cart/getCartNumber')
+                this.$api.switchTabTo('/pages/tabBar/cart/index')
+            } catch (error) {
+                console.log(error.message)
+                // this.$util.msg(error.msg, 2000)
+            }
+        },
+
+        // 操作订单确认事件
+        async handleModalConfirm(e) {
+            this.modal = false
+            if (!e.index) return
+
+            const { type, order } = this.hanldOrder
+
+            // 操作订单
+            const confirmFunc = {
+                cancel: this.handleCancel, //取消订单
+                delete: this.handleDelete, //删除订单
+                pay: this.handlePay, //支付订单
+                confirm: this.handleConfirm //确认收货
+            }
+            try {
+                const res = await confirmFunc[type](order)
+                this.resetOrderList()
+                if (res && res.msg) this.$util.msg(res.msg, 2000, true, 'success')
+            } catch (error) {
+                this.$util.msg(error.msg, 2000)
+            }
+        },
+        //订单状态文字
+        stateExpFormat(status) {
+            const stateTextObject = {
+                4: '交易完成',
+                5: '订单完成',
+                6: '已关闭',
+                7: '交易全退',
+                77: '交易全退',
+                11: '待付款待发货',
+                12: '待付款部分发货',
+                13: '待付款已发货',
+                21: '部分付款待发货',
+                22: '部分付款部分发货',
+                23: '部分付款已发货',
+                31: '已付款待发货',
+                32: '已付款部分发货',
+                33: '已付款已发货',
+                111: '待付款待发货'
+            }
+            return stateTextObject[status] || ''
+        },
+    }
+}
+
+export default orderList

+ 79 - 0
pages/order/mixins/wechatPay.js

@@ -0,0 +1,79 @@
+import authorize from '@/common/authorize.js'
+
+// 调用微信支付
+function wxRequestPayment(payment) {
+    return new Promise((resolve, reject) => {
+        uni.requestPayment({
+            timeStamp: payment.timeStamp,
+            nonceStr: payment.nonceStr,
+            package: payment.package,
+            signType: payment.signType,
+            paySign: payment.paySign,
+            success: () => {
+                resolve(true)
+            },
+            fail: () => {
+                reject({ msg: 'error' })
+            }
+        })
+    })
+}
+
+// 微信支付
+const wechatPay = {
+    data() {
+        return {
+            loadingText: '请稍等...',
+            isSubLoading: false,
+        }
+    },
+    methods: {
+        // 验证微信支付是否可用
+        miniWxPayFor(data) {
+            this.isSubLoading = true
+            this.PayService.PayOrderOnLineSwitch().then(response => {
+                if (response.data === 1) {
+                    this.weChatMiniWxPay(data)
+                } else {
+                    this.isSubLoading = false
+                    this.$api.navigateTo(`/pages/user/order/order-payment?money=${data.payableAmount}`)
+                }
+            })
+        },
+        // 获取微信支付payment
+        async weChatMiniWxPay(data) {
+            if (this.loadingText) this.loadingText = '等待支付中'
+            try {
+                // 获取微信code
+                const wechatCode = await authorize.getCode('weixin')
+                // 微信支付请求 返回支付信息
+                const response = await this.PayService.WeChatMiniWxPay({
+                    payAmount: data.payableAmount * 100,
+                    payWay: 'WEIXIN',
+                    code: wechatCode,
+                    orderId: data.orderId
+                })
+                // 处理支付信息 调用微信支付
+                const payment = JSON.parse(response.data.data.payInfo)
+                const payFlag = await wxRequestPayment(payment)
+                // 支付成功重定向
+                uni.setStorageSync('orderInfo', this.hanldOrder.order)
+                if (payFlag) {
+                    uni.redirectTo({ url: '/pages/user/order/success' })
+                } else {
+                    uni.redirectTo({ url: '/pages/user/order/error' })
+                }
+            } catch (error) {
+                // 微信支付失败
+                if (error.msg === 'error') {
+                    uni.setStorageSync('orderInfo', this.hanldOrder.order)
+                    uni.redirectTo({ url: '/pages/user/order/error' })
+                } else this.$util.msg(error.msg, 2000)
+            } finally {
+                this.isSubLoading = false
+            }
+        }
+    }
+}
+
+export default wechatPay

+ 253 - 0
pages/order/order-detail.vue

@@ -0,0 +1,253 @@
+<template>
+    <view class="order-detail" :class="{ hasBottom: hasControlNav }">
+        <!-- 收货地址 -->
+        <view class="address">
+            <cm-choose-address :addressData="userInfo" disabled></cm-choose-address>
+        </view>
+        
+        <!-- 订单商品列表 -->
+        <template v-for="(shopOrder, shopOrderIndex) in shopOrderList">
+            <view class="grid" :key="shopOrderIndex"></view>
+            <view class="shop-section" :key="shopOrderIndex">
+                <!-- 供应商 -->
+                <view class="origin">
+                    <image class="cover" :src="shopOrder.shopLogo"></image>
+                    <view class="name">{{ shopOrder.shopName }}</view>
+                </view>
+                <!-- 商品列表 -->
+                <view class="goods-list">
+                    <!-- 商品信息 -->
+                    <view class="order-goods" v-for="goods in shopOrder.orderProductList" :key="goods.productId">
+                        <cm-order-prodcut :goods-data="goods"></cm-order-prodcut>
+                    </view>
+                </view>
+                <view class="line"></view>
+                <!-- 统计 -->
+                <view class="total">
+                    <view class="count">共{{ shopOrder.itemCount }}件商品</view>
+                    <view class="status">
+                        <text class="label">商品总额:</text> <text>¥{{ shopOrder.totalAmount | formatPrice }}</text>
+                    </view>
+                </view>
+            </view>
+        </template>
+
+        <view class="grid"></view>
+        <!-- 订单详细信息 -->
+        <cm-order-information :orderInfo="orderInfo"></cm-order-information>
+        
+        <!-- 操作 -->
+        <view class="order-control" v-if="hasControlNav">
+            <cm-order-control-nav
+                :orderInfo="orderInfo"
+                @confirm="handleConfirmClick"
+                @change="getCount"
+            ></cm-order-control-nav>
+        </view>
+        
+        <!-- 操作弹窗 -->
+        <tui-modal
+            :show="modal"
+            :content="modalText"
+            :size="32"
+            :maskClosable="false"
+            color="#333"
+            shape="circle"
+            @click="handleModalConfirm"
+        ></tui-modal>
+        
+        <!-- 加载框 -->
+        <cm-loading :visible="isSubLoading" :text="loadingText"></cm-loading>
+        
+        <!-- 失效商品列表 -->
+        <cm-order-invalid-modal
+            :goodsList="invalidList"
+            :visible="buyAgainModal"
+            @confirm="buyAgainModalClick"
+            @cancel="buyAgainModalHide"
+        ></cm-order-invalid-modal>
+        
+        <!-- 底部占位 -->
+        <view class="reserved" v-if="isIphoneX"></view>
+    </view>
+</template>
+
+<script>
+import CmChooseAddress from '@/components/cm-module/cm-choose-address/cm-choose-address.vue' //地址信息
+import CmOrderProdcut from '@/components/cm-module/cm-order-prodcut/cm-order-prodcut.vue'
+import CmOrderInformation from '@/components/cm-module/cm-order-information/cm-order-information.vue'
+import CmOrderControlNav from '@/components/cm-module/cm-order-control-nav/cm-order-control-nav.vue'
+import CmOrderInvalidModal from '@/components/cm-module/cm-order-invalid-modal/cm-order-invalid-modal.vue'
+import CmLoading from '@/components/cm-module/cm-loading/cm-loading.vue'
+import orderList from './mixins/orderList.js'
+import wechatPay from './mixins/wechatPay.js'
+
+import { mapGetters } from 'vuex'
+export default {
+    mixins: [wechatPay, orderList],
+    components: {
+        CmOrderProdcut,
+        CmOrderInformation,
+        CmOrderControlNav,
+        CmOrderInvalidModal,
+        CmLoading,
+        CmChooseAddress
+    },
+    data() {
+        return {
+            orderId: '',
+            discernReceiptList: [],
+            shopOrderList: [],
+            orderInfo: {},
+            userInfo: {},
+            buttonCount: 0
+        }
+    },
+    filters: {
+        formatPrice(price) {
+            if (!price) return '0.00'
+            return Number(price).toFixed(2)
+        }
+    },
+    computed: {
+        ...mapGetters(['userId', 'userIdentity', 'isIphoneX']),
+        // 当前用户是否为协销
+        isDealer() {
+            return this.userIdentity === 2
+        },
+        hasControlNav(){
+            return this.orderInfo.buyUserId === this.userId && this.buttonCount > 0
+        }
+    },
+    onLoad(option) {
+        this.orderId = option.orderId
+        this.getOrderDetail()
+    },
+    methods: {
+        getOrderDetail() {
+            this.OrderService.QueryOrderDetails({ orderId: this.orderId })
+                .then(res => {
+                    console.log(res)
+                    this.discernReceiptList = res.data.discernReceiptList
+                    this.shopOrderList = res.data.shopOrderList
+                    this.orderInfo = res.data.order
+                    this.userInfo = res.data.userInfo
+                })
+                .catch(err => {
+                    console.log(err)
+                })
+        },
+        getCount(e){
+            this.buttonCount = e.count
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.order-detail {
+    min-height: 100vh;
+    background: #f7f7f7;
+    
+    padding-top: 138rpx;
+    box-sizing: border-box;
+    
+    &.has-bottom{
+        padding-bottom: 100rpx;
+    }
+
+    .grid {
+        height: 20rpx;
+        background: #f7f7f7;
+    }
+    
+    .address{
+        height: 138rpx;
+        position: fixed;
+        top: 0;
+    }
+    
+
+    .shop-section {
+        background: #fff;
+        overflow: hidden;
+
+        .line {
+            width: 702rpx;
+            height: 1px;
+            background: #f7f7f7;
+            margin: 0 auto;
+        }
+
+        .origin {
+            padding: 0 24rpx;
+            margin-top: 24rpx;
+            margin-bottom: 16rpx;
+            display: flex;
+            justify-content: flex-start;
+            align-items: center;
+
+            .cover {
+                width: 56rpx;
+                height: 56rpx;
+                border-radius: 4rpx;
+                border: 1px solid #F7F7F7;
+                box-sizing: border-box;
+            }
+
+            .name {
+                margin-left: 16rpx;
+                font-size: 30rpx;
+                color: #333333;
+                font-weight: bold;
+            }
+        }
+
+        .goods-list {
+            margin-bottom: 32rpx;
+            .order-goods {
+                padding-top: 32rpx;
+                &:first-child {
+                    padding-top: 0;
+                }
+            }
+        }
+    }
+
+    .total {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+
+        padding: 0 24rpx;
+        margin: 32rpx 0;
+
+        font-size: 26rpx;
+        color: #333333;
+
+        .count {
+            font-weight: bold;
+        }
+
+        .status {
+            color: #ff457b;
+
+            .label {
+                color: #333333;
+            }
+        }
+    }
+    
+    .order-control{
+        position: fixed;
+        width: 100%;
+        box-sizing: border-box;
+        height: 100rpx;
+        display: flex;
+        justify-content: flex-end;
+        align-items: center;
+        bottom: 0;
+        background: #fff;
+    }
+}
+</style>

+ 458 - 0
pages/order/order-list.vue

@@ -0,0 +1,458 @@
+<template>
+    <view class="order-list">
+        <tui-skeleton v-if="isRequest" loadingType="2"></tui-skeleton>
+        
+        <!-- 滑块 tabs -->
+        <tui-tabs
+            :tabs="tabs"
+            :currentTab="currentTab"
+            @change="tabChange"
+            :sliderWidth="48"
+            color="#333333"
+            selectedColor="#FF457B"
+            sliderBgColor="#FF457B"
+        ></tui-tabs>
+        
+        <!-- 协销筛选订单 -->
+        <cm-order-filter-control
+            @click="handleFilter"
+            :buttonGroup="screenTabBar"
+            v-if="isDealer"
+        ></cm-order-filter-control>
+
+        <swiper
+            :indicator-dots="false"
+            :autoplay="false"
+            class="swiper"
+            :class="!isDealer ? 'swiper-hegiht1' : 'swiper-hegiht2'"
+            :current="currentTab"
+            @change="swiperChange"
+        >
+            <swiper-item v-for="tab in tabs" :key="tab.state">
+                <!-- tab.orderList.length === 0 -->
+                <view class="order-empty" v-if="tab.orderList.length === 0">
+                    <cm-empty :image="emptyInfo.image" :message="emptyInfo.message" :offset="100"></cm-empty>
+                </view>
+                <scroll-view scroll-y="true" v-else class="scroll-box" @scrolltolower="scrollBottom">
+                    <template v-for="(orderInfo, orderIndex) in tab.orderList">
+                        <view class="grid" :key="orderIndex"></view>
+                        <view class="order-section" :key="orderIndex" @click="handleToDetail(orderInfo)">
+                            <!-- 订单信息 -->
+                            <view class="order-info">
+                                <view class="order-num">
+                                    <text class="label">订单编号:</text> <text>{{ orderInfo.orderNo }}</text>
+                                </view>
+                                <view class="order-time">
+                                    <text class="label">下单时间:</text> <text>{{ orderInfo.orderTime }}</text>
+                                </view>
+                                <view class="status">{{ stateExpFormat(orderInfo.status) }}</view>
+                            </view>
+                            <view class="line"></view>
+                            <view
+                                class="shop-order"
+                                v-for="(shopOrder, shopOrderIndex) in orderInfo.shopOrderList"
+                                :key="shopOrderIndex"
+                            >
+                                <!-- 供应商 -->
+                                <view class="origin">
+                                    <image class="cover" :src="shopOrder.shopLogo"></image>
+                                    <view class="name">{{ shopOrder.shopName }}</view>
+                                </view>
+                                <!-- 商品列表 -->
+                                <view class="goods-list">
+                                    <!-- 商品信息 -->
+                                    <view
+                                        class="order-goods"
+                                        v-for="goods in shopOrder.orderProductList"
+                                        :key="goods.productId"
+                                    >
+                                        <cm-order-prodcut :goods-data="goods"></cm-order-prodcut>
+                                    </view>
+                                </view>
+                            </view>
+                            <!-- 统计 -->
+                            <view class="total">
+                                <view class="count">共{{ orderInfo.productCount }}件商品</view>
+                                <view class="status">
+                                    <template v-if="['31', '32', '33'].includes(orderInfo.status)">
+                                        <text class="label">已支付:</text>
+                                        <text>¥{{ orderInfo.receiptAmount | formatPrice }}</text>
+                                    </template>
+                                    <template v-else>
+                                        <text class="label">待付总额:</text>
+                                        <text>¥{{ orderInfo.pendingPayments | formatPrice }}</text>
+                                    </template>
+                                </view>
+                            </view>
+                            <!-- 操作 -->
+                            <cm-order-control-nav
+                                v-if="orderInfo.userId == userId"
+                                :orderInfo="orderInfo"
+                                @confirm="handleConfirmClick"
+                            ></cm-order-control-nav>
+                        </view>
+                    </template>
+                    <!-- loading -->
+                    <view class="loading-more">
+                        <tui-loadmore :index="3" :visible="loadmore"></tui-loadmore>
+                        <tui-nomore :text="loadMoreText" :visible="!loadmore" backgroundColor="#f7f7f7"></tui-nomore>
+                    </view>
+                </scroll-view>
+            </swiper-item>
+        </swiper>
+
+        <!-- 操作弹窗 -->
+        <tui-modal
+            :show="modal"
+            :content="modalText"
+            :size="32"
+            :maskClosable="false"
+            color="#333"
+            shape="circle"
+            @click="handleModalConfirm"
+        ></tui-modal>
+        <!-- 加载框 -->
+        <cm-loading :visible="isSubLoading" :text="loadingText"></cm-loading>
+        <!-- 失效商品列表 -->
+        <cm-order-invalid-modal
+            :goodsList="invalidList"
+            :visible="buyAgainModal"
+            @confirm="buyAgainModalClick"
+            @cancel="buyAgainModalHide"
+        ></cm-order-invalid-modal>
+    </view>
+</template>
+
+<script>
+import CmOrderProdcut from '@/components/cm-module/cm-order-prodcut/cm-order-prodcut.vue'
+import CmOrderControlNav from '@/components/cm-module/cm-order-control-nav/cm-order-control-nav.vue'
+import CmOrderInvalidModal from '@/components/cm-module/cm-order-invalid-modal/cm-order-invalid-modal.vue'
+import CmOrderFilterControl from '@/components/cm-module/cm-order-filter-control/cm-order-filter-control.vue'
+import CmLoading from '@/components/cm-module/cm-loading/cm-loading.vue'
+import CmEmpty from '@/components/cm-module/cm-empty/cm-empty.vue'
+import { debounce } from '@/common/common.js'
+import orderList from './mixins/orderList.js'
+import wechatPay from './mixins/wechatPay.js'
+import { mapGetters } from 'vuex'
+export default {
+    mixins: [wechatPay, orderList],
+    components: {
+        CmOrderProdcut,
+        CmOrderControlNav,
+        CmOrderInvalidModal,
+        CmOrderFilterControl,
+        CmLoading,
+        CmEmpty
+    },
+    data() {
+        return {
+            tabs: [
+                {
+                    name: '全部',
+                    state: 0,
+                    pageNum: 1,
+                    orderList: []
+                },
+                {
+                    name: '待付款',
+                    state: 1,
+                    pageNum: 1,
+                    orderList: []
+                },
+                {
+                    name: '待发货',
+                    state: 2,
+                    pageNum: 1,
+                    orderList: []
+                },
+                {
+                    name: '已发货',
+                    state: 3,
+                    pageNum: 1,
+                    orderList: []
+                },
+                {
+                    name: '退货/款',
+                    state: 4,
+                    pageNum: 1,
+                    orderList: []
+                }
+            ],
+            currentTab: 0,
+            screenTabBar: [{ id: 0, name: '全部订单' }, { id: 1, name: '用户订单' }, { id: 2, name: '自身订单' }],
+            screenTab: 0,
+            refresh: false,
+            loadmore: false, // 正在加载更多
+            isRequest: true,
+        }
+    },
+    filters: {
+        formatPrice(price) {
+            if (!price) return '0.00'
+            return Number(price).toFixed(2)
+        }
+    },
+    computed: {
+        ...mapGetters(['userId', 'userIdentity']),
+        // 当前用户是否为协销
+        isDealer() {
+            return this.userIdentity === 2
+        },
+        tabInfo() {
+            return this.tabs[this.currentTab]
+        },
+        loadMoreText() {
+            if (this.tabInfo.orderList.length === 0) return '没有更多了'
+            return this.tabInfo.hasMore ? '上拉加载更多' : '没有更多了'
+        },
+        emptyInfo() {
+            const info = {}
+            info.image = `${this.$Static}icon-empty-address.png`
+
+            if (this.tabInfo.state === 0) {
+                info.message = '您还没有任何的订单哟~_~'
+            } else {
+                info.message = '您还没有相关的订单哟~_~'
+            }
+
+            return info
+        }
+    },
+    created() {
+        setTimeout(() => {
+            this.fetchOrderData()
+        }, 2000)
+    },
+    // 下拉刷新
+    onPullDownRefresh() {
+        this.resetOrderList()
+    },
+    methods: {
+        // 重置订单列表
+        resetOrderList() {
+            this.refresh = true
+            this.tabInfo.pageNum = 1
+            this.fetchOrderData()
+        },
+
+        // 更新订单列表
+        updateOrderList(response) {
+            const { name, state, pageNum } = this.tabInfo
+            this.$set(this.tabs, this.currentTab, {
+                name,
+                state,
+                pageNum: pageNum + 1,
+                orderList: this.tabInfo.orderList.concat(response.data.list),
+                hasMore: response.data.hasNextPage
+            })
+        },
+
+        // 获取订单列表 使用防抖函数封装
+        fetchOrderData: debounce(function() {
+            this.loadmore = true
+
+            const params = {
+                orderState: this.currentTab,
+                userId: this.userId,
+                orderType: this.screenTab,
+                pageNum: this.tabInfo.pageNum,
+                pageSize: 10
+            }
+
+            if (this.isDealer) {
+                this.queryOrderDealerList(params)
+            } else {
+                this.queryOrderList(params)
+            }
+        }, 500),
+
+        // 普通用户获取订单列表
+        queryOrderList(params) {
+            this.OrderService.QueryOrderList(params)
+                .then(res => {
+                    if (this.refresh) this.tabInfo.orderList = []
+                    this.updateOrderList(res)
+                })
+                .catch(err => {
+                    console.log(err)
+                })
+                .finally(() => {
+                    uni.stopPullDownRefresh()
+                    this.refresh = false
+                    this.loadmore = false
+                    this.isRequest = false
+                })
+        },
+
+        // 分销者获取订单列表
+        queryOrderDealerList(params) {
+            console.log(params)
+            this.OrderService.QueryOrderDealerList(params)
+                .then(res => {
+                    if (this.refresh) this.tabInfo.orderList = []
+                    this.updateOrderList(res)
+                })
+                .catch(err => {
+                    console.log(err)
+                })
+                .finally(() => {
+                    uni.stopPullDownRefresh()
+                    this.refresh = false
+                    this.loadmore = false
+                    this.isRequest = false
+                })
+        },
+
+        // 筛选订单
+        handleFilter(e) {
+            console.log(e.index)
+            this.screenTab = e.index
+            this.resetOrderList()
+            this.fetchOrderData()
+        },
+        
+        // 跳转详情
+        handleToDetail(orderInfo){
+            this.$api.navigateTo('/pages/order/order-detail?orderId=' + orderInfo.orderId)
+        },
+
+        // 滚动到底部
+        scrollBottom() {
+            if (!this.tabInfo.hasMore) return
+            this.fetchOrderData()
+        },
+
+        // tab切换
+        tabChange(e) {
+            this.currentTab = e.index
+        },
+
+        // 轮播切换
+        swiperChange(e) {
+            this.currentTab = e.detail.current
+            if (this.tabInfo.pageNum !== 1) return
+            this.isRequest = true
+            this.fetchOrderData()
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.order-list {
+    min-height: 100vh;
+    background: #f7f7f7;
+
+    .swiper {
+        &.swiper-hegiht1 {
+            height: calc(100vh - 40px);
+        }
+
+        &.swiper-hegiht2 {
+            height: calc(100vh - 80px);
+        }
+
+        .scroll-box {
+            height: 100%;
+        }
+    }
+
+    .grid {
+        height: 20rpx;
+        background: #f7f7f7;
+    }
+
+    .order-section {
+        padding: 38rpx 0;
+        background-color: #fff;
+
+        .line {
+            width: 702rpx;
+            height: 1px;
+            background: #f7f7f7;
+        }
+
+        .order-info {
+            position: relative;
+            padding: 0 24rpx;
+            margin-bottom: 32rpx;
+            line-height: 1.6;
+
+            .order-num,
+            .order-time {
+                font-size: 26rpx;
+                color: #333333;
+
+                .label {
+                    color: #999999;
+                }
+            }
+
+            .status {
+                position: absolute;
+                font-size: 26rpx;
+                color: #ff457b;
+                right: 24rpx;
+                bottom: 0;
+            }
+        }
+
+        .origin {
+            padding: 0 24rpx;
+            margin-top: 24rpx;
+            margin-bottom: 16rpx;
+            display: flex;
+            justify-content: flex-start;
+            align-items: center;
+
+            .cover {
+                width: 56rpx;
+                height: 56rpx;
+                border-radius: 4rpx;
+                border: 1px solid #F7F7F7;
+                box-sizing: border-box;
+            }
+
+            .name {
+                margin-left: 16rpx;
+                font-size: 30rpx;
+                color: #333333;
+                font-weight: bold;
+            }
+        }
+
+        .goods-list {
+            .order-goods {
+                padding-top: 32rpx;
+                &:first-child {
+                    padding-top: 0;
+                }
+            }
+        }
+
+        .total {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+
+            padding: 0 24rpx;
+            margin: 32rpx 0;
+
+            font-size: 26rpx;
+            color: #333333;
+
+            .count {
+                font-weight: bold;
+            }
+
+            .status {
+                color: #ff457b;
+
+                .label {
+                    color: #333333;
+                }
+            }
+        }
+    }
+}
+</style>

+ 422 - 0
pages/order/order-logistics.vue

@@ -0,0 +1,422 @@
+<template>
+    <view class="container logistics clearfix">
+        <!-- 商品 -->
+        <view class="logistics-container">
+            <view class="logistics-batch" v-for="(item, index) in goodsList" :key="index">
+                <view class="order-item" v-for="(comItem, comIndex) in item.companyList" :key="comIndex">
+                    <view class="goods-title">
+                        <view class="title-logo"><image :src="comItem.shopLogo" mode=""></image></view>
+                        <view class="title-text">{{ comItem.name }}</view>
+                    </view>
+                    <view class="goods-item" v-for="(pros, prosIndex) in comItem.productsList" :key="prosIndex">
+                        <view class="goods-pros-t">
+                            <view class="pros-img"><image :src="pros.image" alt=""/></view>
+                            <view class="pros-product">
+                                <view class="producttitle">{{ pros.productName }}</view>
+                                <view class="productspec">
+                                    购买数量:<text class="color">{{ pros.number }}</text>
+                                </view>
+                                <view class="productspec">
+                                    已发货数量:<text class="color">{{ pros.logNumber }}</text>
+                                </view>
+                            </view>
+                        </view>
+                    </view>
+                </view>
+                <view class="logistics-template">
+                    <!-- 物流信息 -->
+                    <view
+                        class="logistics-content"
+                        v-if="item.logisticsData.length > 0"
+                        v-for="(loItem, loIndex) in item.logisticsData"
+                        :key="loIndex"
+                    >
+                        <view class="logistics-top"> <text class="name">物流信息</text> </view>
+                        <view class="logistics-warp">
+                            <view class="logistics-warp__wrapper">
+                                <view class="logistics-main">
+                                    <view class="logistics-main-top">
+                                        <view class="main-top" @click="showlogistics(index, loIndex)">
+                                            {{ loItem.expressname }}:<text class="expressNumber">{{
+                                                loItem.expressNumber
+                                            }}</text>
+                                            <text class="clipboard" @click.stop="clipboard(loItem.expressNumber)"
+                                                >复制</text
+                                            >
+                                            <text
+                                                class="arrow-showMore iconfont icon-web_xiangxiazhankai"
+                                                :style="{
+                                                    transform: loItem.isOpen ? 'rotate(180deg)' : 'rotate(0)',
+                                                    transition: 'transform 0.3s ease'
+                                                }"
+                                            ></text>
+                                        </view>
+                                        <view class="main-bot"> 发货时间:{{ loItem.expressNewtime }} </view>
+                                    </view>
+                                    <view
+                                        v-if="loItem.expressRecord.length > 0"
+                                        v-for="(infoItem, infoIndex) in loItem.expressRecord"
+                                        :key="infoIndex"
+                                        :class="{ 'logistics-warp--hide': !loItem.isOpen }"
+                                        class="logistics-main-bot logistics-animation"
+                                        :style="{
+                                            transform: loItem.isOpen ? 'translateY(0)' : 'translateY(-50%)',
+                                            '-webkit-transform': loItem.isOpen ? 'translateY(0)' : 'translateY(-50%)'
+                                        }"
+                                    >
+                                        {{ infoItem.time }} {{ infoItem.desc }}
+                                    </view>
+                                    <view
+                                        v-if="loItem.expressRecord.length < 1"
+                                        :class="{ 'logistics-warp--hide': !loItem.isOpen }"
+                                        class="logistics-main-bot logistics-animation"
+                                        :style="{
+                                            transform: loItem.isOpen ? 'translateY(0)' : 'translateY(-50%)',
+                                            '-webkit-transform': loItem.isOpen ? 'translateY(0)' : 'translateY(-50%)'
+                                        }"
+                                    >
+                                        暂无物流信息
+                                    </view>
+                                </view>
+                            </view>
+                        </view>
+                    </view>
+                    <view class="logistics-content" v-else> 暂无物流信息 </view>
+                </view>
+            </view>
+        </view>
+        <!-- 物流信息 -->
+        <!-- <logistics-record ref="logistics"></logistics-record> -->
+    </view>
+</template>
+
+<script>
+import thorui from '@/components/clipboard/clipboard.thorui.js'
+export default {
+    components: {
+        // logisticsRecord,
+    },
+    data() {
+        return {
+            orderId: '',
+            goodsList: []
+        }
+    },
+    onLoad(option) {
+        //商品数据
+        this.orderId = option.orderId
+        this.getData()
+    },
+    methods: {
+        navToListPage(id) {
+            this.$api.navigateTo(`/pages/goods/product?id=${id}`)
+        },
+        showlogistics(index, loIndex) {
+            let getGoodsList = this.goodsList[index],
+                isOpen = getGoodsList.logisticsData[loIndex]['isOpen']
+            this.goodsList[index].logisticsData[loIndex]['isOpen'] = !isOpen
+        },
+        clipboard(data) {
+            console.log(data)
+            thorui.getClipboardData(data, res => {
+                if (res) {
+                    this.$util.msg('复制成功', 2000, true, 'success')
+                } else {
+                    this.$util.msg('复制失败', 2000, true, 'none')
+                }
+            })
+        },
+        getData() {
+            this.OrderService.QueryLogistics({
+                orderId: this.orderId
+            })
+                .then(response => {
+                    const resData = response.data
+                    // 添加订单列表信息
+                    let orderListArr = []
+                    resData.forEach((item, index) => {
+                        let logisticsArr = [],
+                            companyList = [],
+                            shopOrderList = item.shopOrderList,
+                            logisticsInfos = item.logisticsInformationList
+                        // 添加物流信息
+                        if (logisticsInfos.length > 0) {
+                            logisticsInfos.forEach((loItem, loIndex) => {
+                                let newRouters = []
+                                logisticsArr.push({
+                                    expressname: loItem['logisticsCompanyName'],
+                                    expressNumber: loItem['nu'],
+                                    expressNewtime: item.deliveryTime,
+                                    isOpen: false
+                                })
+                                if (loIndex == 0) {
+                                    logisticsArr[loIndex]['isOpen'] = true
+                                }
+                                if (loItem.routers) {
+                                    loItem.routers.forEach((rItem, rIndex) => {
+                                        newRouters.push({
+                                            desc: rItem.desc,
+                                            time: this.$api.timestampToTime(rItem.time)
+                                        })
+                                    })
+                                    logisticsArr[loIndex]['expressRecord'] = [...newRouters]
+                                } else {
+                                    logisticsArr[loIndex]['expressRecord'] = []
+                                }
+                            })
+                        }
+                        // 供应商信息
+                        shopOrderList.forEach((shopItem, shopIndex) => {
+                            let prosListArr = [],
+                                cmLogisticsRecords = shopItem.logisticsRecordList
+                            // 商品信息
+                            cmLogisticsRecords.forEach((prosItem, prosIndex) => {
+                                prosListArr.push({
+                                    id: prosItem.organizeProductID,
+                                    productName: prosItem.productName,
+                                    image: prosItem.image,
+                                    number: prosItem.buyNum,
+                                    logNumber: prosItem.num
+                                })
+                            })
+                            companyList.push({
+                                shopLogo: shopItem.shopLogo,
+                                name: shopItem.shopName,
+                                showGoods: cmLogisticsRecords.length > 0,
+                                productsList: [...prosListArr]
+                            })
+                        })
+                        orderListArr.push({
+                            logisticsData: [...logisticsArr],
+                            companyList: [...companyList]
+                        })
+                    })
+                    this.goodsList = [...orderListArr]
+                })
+                .catch(error => {
+                    this.$util.msg(error.msg, 2000)
+                })
+        }
+    }
+}
+</script>
+
+<style lang="scss">
+page {
+    height: auto;
+}
+.logistics-container {
+    width: 100%;
+    height: auto;
+    float: left;
+    background: #f7f7f7;
+    border-top: 1px solid #f8f8f8;
+    .logistics-batch {
+        display: flex;
+        flex-direction: column;
+        margin-bottom: 24rpx;
+    }
+    .order-item {
+        width: 702rpx;
+        padding: 24rpx 24rpx 12rpx 24rpx;
+        height: auto;
+        float: left;
+        background: #ffffff;
+        margin-bottom: 20rpx;
+        .goods-title {
+            width: 100%;
+            height: 48rpx;
+            float: left;
+            margin-bottom: 12rpx;
+            .title-logo {
+                width: 48rpx;
+                height: 48rpx;
+                float: left;
+                border-radius: 8rpx;
+                border: 1px solid #e1e1e1;
+                image {
+                    border-radius: 8rpx;
+                    width: 48rpx;
+                    height: 48rpx;
+                }
+            }
+            .title-text {
+                float: left;
+                margin-left: 16rpx;
+                font-size: $font-size-28;
+                color: $text-color;
+                text-align: left;
+                line-height: 48rpx;
+                font-weight: bold;
+            }
+        }
+        .goods-item {
+            width: 100%;
+            height: auto;
+            border-bottom: 1px solid #e1e1e1;
+            &:last-child {
+                border-bottom: none;
+            }
+        }
+        .goods-pros-t {
+            display: flex;
+            align-items: center;
+            width: 100%;
+            height: 180rpx;
+            padding: 20rpx 0;
+            .pros-img {
+                width: 180rpx;
+                height: 180rpx;
+                border-radius: 10rpx;
+                margin: 0 26rpx 0 0;
+                border: 1px solid #f3f3f3;
+                image {
+                    width: 100%;
+                    height: 100%;
+                    border-radius: 10rpx;
+                }
+            }
+        }
+        .pros-product {
+            width: 468rpx;
+            height: 100%;
+            line-height: 36rpx;
+            font-size: $font-size-26;
+            position: relative;
+            .producttitle {
+                width: 100%;
+                display: inline-block;
+                height: auto;
+                text-overflow: ellipsis;
+                display: -webkit-box;
+                word-break: break-all;
+                -webkit-box-orient: vertical;
+                -webkit-line-clamp: 2;
+                overflow: hidden;
+                margin-bottom: 28rpx;
+            }
+            .productspec {
+                height: 36rpx;
+                color: #999999;
+                line-height: 36rpx;
+                font-size: $font-size-26;
+                .color {
+                    color: $text-color;
+                }
+            }
+        }
+    }
+}
+
+.logistics-template {
+    width: 702rpx;
+    height: 100%;
+    background: #ffffff;
+    float: left;
+    padding: 24rpx 24rpx 12rpx 24rpx;
+    .logistics-content {
+        width: 100%;
+        padding: 20rpx 0;
+        height: auto;
+        .arrow-showMore {
+            position: absolute;
+            right: 24rpx;
+            z-index: 99;
+        }
+        .logistics-top {
+            width: 100%;
+            height: 40rpx;
+            line-height: 40rpx;
+            font-size: $font-size-28;
+            color: $text-color;
+            text-align: left;
+            padding-bottom: 24rpx;
+            border-bottom: 1px solid #f8f8f8;
+            .name {
+                float: left;
+                font-weight: bold;
+            }
+            .icon-web_xiangxiazhankai {
+                transform: rotate(0deg);
+                transform-origin: center center;
+                float: right;
+                font-size: $font-size-32;
+                color: #000000;
+                /* transition: transform 0.3s ease;*/
+                transition-property: transform;
+                transition-duration: 0.3s;
+                transition-timing-function: ease;
+            }
+            .icon-web_xiangxiazhankai-active {
+                transform: rotate(180deg);
+            }
+        }
+        .logistics-warp {
+            width: 100%;
+            overflow: hidden;
+            .table {
+                height: 76rpx;
+                line-height: 76rpx;
+                font-size: $font-size-26;
+                color: $text-color;
+                text-align: left;
+            }
+            .expressNumber {
+                width: 250rpx;
+                display: inline-block;
+            }
+        }
+        .logistics-main-top {
+            width: 100%;
+            height: auto;
+            float: left;
+            padding-top: 24rpx;
+            .main-top,
+            .main-bot {
+                font-size: $font-size-28;
+                color: $text-color;
+                line-height: 40rpx;
+                margin: 4rpx 0;
+            }
+        }
+        .logistics-main-bot {
+            width: 100%;
+            height: auto;
+            font-size: $font-size-24;
+            color: $text-color;
+            line-height: 56rpx;
+            text-align: justify;
+            float: left;
+        }
+        .logistics-animation {
+            /* transition: transform 0.3s ease;*/
+            transition-property: transform;
+            transition-duration: 0.3s;
+            transition-timing-function: ease;
+        }
+        .logistics-warp__wrapper {
+            /* #ifndef APP-NVUE */
+            display: flex;
+            /* #endif */
+            flex-direction: column;
+        }
+        .logistics-warp--hide {
+            // padding: 0 0;
+            // height: 0px;
+            // line-height: 0px;
+            display: none;
+        }
+        .clipboard {
+            width: 80rpx;
+            height: 40rpx;
+            background: #fff8fd;
+            text-align: center;
+            font-size: $font-size-22;
+            color: #ff457b;
+            border-radius: 7rpx;
+            line-height: 40rpx;
+            display: inline-block;
+        }
+    }
+}
+</style>