项目初始化
This commit is contained in:
261
pages/order/addressSelection.vue
Normal file
261
pages/order/addressSelection.vue
Normal file
@@ -0,0 +1,261 @@
|
||||
<!-- 下单界面,收货地址 or 自提门店的选择组件 -->
|
||||
<template>
|
||||
<view class="allAddress" :style="state.isPickUp ? '':'padding-top:10rpx;'">
|
||||
<view class="nav flex flex-wrap">
|
||||
<view class="item font-color" :class="state.deliveryType === 1 ? 'on' : 'on2'"
|
||||
@tap="switchDeliveryType(1)" v-if='state.isPickUp' />
|
||||
<view class="item font-color" :class="state.deliveryType === 2 ? 'on' : 'on2'"
|
||||
@tap="switchDeliveryType(2)" v-if='state.isPickUp' />
|
||||
</view>
|
||||
<!-- 情况一:收货地址的选择 -->
|
||||
<view class='address flex flex-wrap flex-center ss-row-between' @tap='onSelectAddress' v-if='state.deliveryType === 1'
|
||||
:style="state.isPickUp ? '':'border-top-left-radius: 14rpx;border-top-right-radius: 14rpx;'">
|
||||
<view class='addressCon' v-if="state.addressInfo.name">
|
||||
<view class='name'>{{ state.addressInfo.name }}
|
||||
<text class='phone'>{{ state.addressInfo.mobile }}</text>
|
||||
</view>
|
||||
<view class="flex flex-wrap">
|
||||
<text class='default font-color' v-if="state.addressInfo.defaultStatus">[默认]</text>
|
||||
<text class="line2">{{ state.addressInfo.areaName }} {{ state.addressInfo.detailAddress }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class='addressCon' v-else>
|
||||
<view class='setaddress'>设置收货地址</view>
|
||||
</view>
|
||||
<view class='iconfont'>
|
||||
<view class="ss-rest-button">
|
||||
<text class="_icon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 情况二:门店的选择 -->
|
||||
<view class='address flex flex-wrap flex-center ss-row-between' v-else @tap="onSelectAddress">
|
||||
<view class='addressCon' v-if="state.pickUpInfo.name">
|
||||
<view class='name'>{{ state.pickUpInfo.name }}
|
||||
<text class='phone'>{{ state.pickUpInfo.phone }}</text>
|
||||
</view>
|
||||
<view class="line1"> {{ state.pickUpInfo.areaName }}{{ ', ' + state.pickUpInfo.detailAddress }}
|
||||
</view>
|
||||
</view>
|
||||
<view class='addressCon' v-else>
|
||||
<view class='setaddress'>选择自提门店</view>
|
||||
</view>
|
||||
<view class='iconfont'>
|
||||
<view class="ss-rest-button">
|
||||
<text class="_icon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class='line'>
|
||||
<image :src="sheep.$url.static('/static/images/line.png', 'local')" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default() {},
|
||||
}
|
||||
});
|
||||
const emits = defineEmits(['update:modelValue']);
|
||||
|
||||
// computed 解决父子组件双向数据同步
|
||||
const state = computed({
|
||||
get(){
|
||||
return new Proxy(props.modelValue, {
|
||||
set(obj, name, val) {
|
||||
emits('update:modelValue', {
|
||||
...obj,
|
||||
[name]: val,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
})
|
||||
},
|
||||
set(val){
|
||||
emits('update:modelValue', val);
|
||||
}
|
||||
})
|
||||
|
||||
// 选择地址
|
||||
function onSelectAddress() {
|
||||
let emitName = 'SELECT_ADDRESS'
|
||||
let addressPage = '/pages/user/address/list?type=select';
|
||||
if (state.value.deliveryType === 2){
|
||||
emitName = 'SELECT_PICK_UP_INFO'
|
||||
addressPage = '/pages/user/goods_details_store/index'
|
||||
}
|
||||
uni.$once(emitName, (e) => {
|
||||
changeConsignee(e.addressInfo);
|
||||
});
|
||||
sheep.$router.go(addressPage);
|
||||
}
|
||||
|
||||
// 更改收货人地址&计算订单信息
|
||||
async function changeConsignee(addressInfo = {}) {
|
||||
if (!isEmpty(addressInfo)) {
|
||||
if (state.value.deliveryType === 1){
|
||||
state.value.addressInfo = addressInfo;
|
||||
}
|
||||
if (state.value.deliveryType === 2){
|
||||
state.value.pickUpInfo = addressInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 收货方式切换
|
||||
const switchDeliveryType = (type) =>{
|
||||
state.value.deliveryType = type;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.allAddress .font-color{
|
||||
color: #E93323!important
|
||||
}
|
||||
.line2{
|
||||
width: 504rpx;
|
||||
}
|
||||
.textR {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.line {
|
||||
width: 100%;
|
||||
height: 3rpx;
|
||||
}
|
||||
|
||||
.line image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.address {
|
||||
padding: 28rpx;
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.address .addressCon {
|
||||
width: 596rpx;
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.address .addressCon .name {
|
||||
font-size: 30rpx;
|
||||
color: #282828;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.address .addressCon .name .phone {
|
||||
margin-left: 50rpx;
|
||||
}
|
||||
|
||||
.address .addressCon .default {
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.address .addressCon .setaddress {
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.address .iconfont {
|
||||
font-size: 35rpx;
|
||||
color: #707070;
|
||||
}
|
||||
|
||||
.allAddress {
|
||||
width: 100%;
|
||||
background: linear-gradient(to bottom, #e93323 0%, #f5f5f5 100%);
|
||||
// background-image: linear-gradient(to bottom, #e93323 0%, #f5f5f5 100%);
|
||||
// background-image: -webkit-linear-gradient(to bottom, #e93323 0%, #f5f5f5 100%);
|
||||
// background-image: -moz-linear-gradient(to bottom, #e93323 0%, #f5f5f5 100%);
|
||||
//padding: 100rpx 30rpx 0 30rpx;
|
||||
padding-top: 100rpx;
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.allAddress .nav {
|
||||
width: 690rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.allAddress .nav .item {
|
||||
width: 334rpx;
|
||||
}
|
||||
|
||||
.allAddress .nav .item.on {
|
||||
position: relative;
|
||||
width: 230rpx;
|
||||
}
|
||||
|
||||
.allAddress .nav .item.on::before {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
content: "快递配送";
|
||||
font-size: 28rpx;
|
||||
display: block;
|
||||
height: 0;
|
||||
width: 336rpx;
|
||||
border-width: 0 20rpx 80rpx 0;
|
||||
border-style: none solid solid;
|
||||
border-color: transparent transparent #fff;
|
||||
z-index: 2;
|
||||
border-radius: 14rpx 36rpx 0 0;
|
||||
text-align: center;
|
||||
line-height: 80rpx;
|
||||
}
|
||||
|
||||
.allAddress .nav .item:nth-of-type(2).on::before {
|
||||
content: "到店自提";
|
||||
border-width: 0 0 80rpx 20rpx;
|
||||
border-radius: 36rpx 14rpx 0 0;
|
||||
}
|
||||
|
||||
.allAddress .nav .item.on2 {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.allAddress .nav .item.on2::before {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
content: "到店自提";
|
||||
font-size: 28rpx;
|
||||
display: block;
|
||||
height: 0;
|
||||
width: 401rpx;
|
||||
border-width: 0 0 60rpx 60rpx;
|
||||
border-style: none solid solid;
|
||||
border-color: transparent transparent #f7c1bd;
|
||||
border-radius: 36rpx 14rpx 0 0;
|
||||
text-align: center;
|
||||
line-height: 60rpx;
|
||||
}
|
||||
|
||||
.allAddress .nav .item:nth-of-type(1).on2::before {
|
||||
content: "快递配送";
|
||||
border-width: 0 60rpx 60rpx 0;
|
||||
border-radius: 14rpx 36rpx 0 0;
|
||||
}
|
||||
|
||||
.allAddress .address {
|
||||
width: 690rpx;
|
||||
max-height: 180rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.allAddress .line {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
351
pages/order/aftersale/apply.vue
Normal file
351
pages/order/aftersale/apply.vue
Normal file
@@ -0,0 +1,351 @@
|
||||
<!-- 售后申请 -->
|
||||
<template>
|
||||
<s-layout title="申请售后">
|
||||
<!-- 售后商品 -->
|
||||
<view class="goods-box">
|
||||
<s-goods-item
|
||||
:img="state.item.picUrl"
|
||||
:title="state.item.spuName"
|
||||
:skuText="state.item.properties?.map((property) => property.valueName).join(' ')"
|
||||
:price="state.item.price"
|
||||
:num="state.item.count"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<uni-forms ref="form" v-model="formData" :rules="rules" label-position="top">
|
||||
<!-- 售后类型 -->
|
||||
<view class="refund-item">
|
||||
<view class="item-title ss-m-b-20">售后类型</view>
|
||||
<view class="ss-flex-col">
|
||||
<radio-group @change="onRefundChange">
|
||||
<label
|
||||
class="ss-flex ss-col-center ss-p-y-10"
|
||||
v-for="(item, index) in state.wayList"
|
||||
:key="index"
|
||||
>
|
||||
<radio
|
||||
:checked="formData.type === item.value"
|
||||
color="var(--ui-BG-Main)"
|
||||
style="transform: scale(0.8)"
|
||||
:value="item.value"
|
||||
/>
|
||||
<view class="item-value ss-m-l-8">{{ item.text }}</view>
|
||||
</label>
|
||||
</radio-group>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 退款金额 -->
|
||||
<view class="refund-item ss-flex ss-col-center ss-row-between" @tap="state.showModal = true">
|
||||
<text class="item-title">退款金额</text>
|
||||
<view class="ss-flex refund-cause ss-col-center">
|
||||
<text class="ss-m-r-20">¥{{ fen2yuan(state.item.payPrice) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 申请原因 -->
|
||||
<view class="refund-item ss-flex ss-col-center ss-row-between" @tap="state.showModal = true">
|
||||
<text class="item-title">申请原因</text>
|
||||
<view class="ss-flex refund-cause ss-col-center">
|
||||
<text class="ss-m-r-20" v-if="formData.applyReason">{{ formData.applyReason }}</text>
|
||||
<text class="ss-m-r-20" v-else>请选择申请原因~</text>
|
||||
<text class="cicon-forward" style="height: 28rpx"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 留言 -->
|
||||
<view class="refund-item">
|
||||
<view class="item-title ss-m-b-20">相关描述</view>
|
||||
<view class="describe-box">
|
||||
<uni-easyinput
|
||||
:inputBorder="false"
|
||||
class="describe-content"
|
||||
type="textarea"
|
||||
maxlength="120"
|
||||
autoHeight
|
||||
v-model="formData.applyDescription"
|
||||
placeholder="客官~请描述您遇到的问题,建议上传照片"
|
||||
/>
|
||||
<!-- TODO 芋艿:上传的测试 -->
|
||||
<view class="upload-img">
|
||||
<s-uploader
|
||||
v-model:url="formData.images"
|
||||
fileMediatype="image"
|
||||
limit="9"
|
||||
mode="grid"
|
||||
:imageStyles="{ width: '168rpx', height: '168rpx' }"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-forms>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<su-fixed bottom placeholder>
|
||||
<view class="foot-wrap">
|
||||
<view class="foot_box ss-flex ss-col-center ss-row-between ss-p-x-30">
|
||||
<button class="ss-reset-button contcat-btn" @tap="sheep.$router.go('/pages/chat/index')">
|
||||
联系客服
|
||||
</button>
|
||||
<button class="ss-reset-button ui-BG-Main-Gradient sub-btn" @tap="submit">提交</button>
|
||||
</view>
|
||||
</view>
|
||||
</su-fixed>
|
||||
|
||||
<!-- 申请原因弹窗 -->
|
||||
<su-popup :show="state.showModal" round="10" :showClose="true" @close="state.showModal = false">
|
||||
<view class="modal-box page_box">
|
||||
<view class="modal-head item-title head_box ss-flex ss-row-center ss-col-center">
|
||||
申请原因
|
||||
</view>
|
||||
<view class="modal-content content_box">
|
||||
<radio-group @change="onChange">
|
||||
<label class="radio ss-flex ss-col-center" v-for="item in state.reasonList" :key="item">
|
||||
<view class="ss-flex-1 ss-p-20">{{ item }}</view>
|
||||
<radio
|
||||
:value="item"
|
||||
color="var(--ui-BG-Main)"
|
||||
:checked="item === state.currentValue"
|
||||
/>
|
||||
</label>
|
||||
</radio-group>
|
||||
</view>
|
||||
<view class="modal-foot foot_box ss-flex ss-row-center ss-col-center">
|
||||
<button class="ss-reset-button close-btn ui-BG-Main-Gradient" @tap="onReason">
|
||||
确定
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</su-popup>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive, ref } from 'vue';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import TradeConfigApi from '@/sheep/api/trade/config';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import AfterSaleApi from '@/sheep/api/trade/afterSale';
|
||||
import { WxaSubscribeTemplate } from '@/sheep/util/const';
|
||||
|
||||
const form = ref(null);
|
||||
const state = reactive({
|
||||
orderId: 0, // 订单编号
|
||||
itemId: 0, // 订单项编号
|
||||
order: {}, // 订单
|
||||
item: {}, // 订单项
|
||||
config: {}, // 交易配置
|
||||
|
||||
// 售后类型
|
||||
wayList: [
|
||||
{
|
||||
text: '仅退款',
|
||||
value: '10',
|
||||
},
|
||||
{
|
||||
text: '退款退货',
|
||||
value: '20',
|
||||
},
|
||||
],
|
||||
reasonList: [], // 可选的申请原因数组
|
||||
showModal: false, // 是否显示申请原因弹窗
|
||||
currentValue: '', // 当前选择的售后原因
|
||||
});
|
||||
let formData = reactive({
|
||||
way: '',
|
||||
applyReason: '',
|
||||
applyDescription: '',
|
||||
images: [],
|
||||
});
|
||||
const rules = reactive({});
|
||||
|
||||
// 提交表单
|
||||
async function submit() {
|
||||
let data = {
|
||||
orderItemId: state.itemId,
|
||||
refundPrice: state.item.payPrice,
|
||||
...formData,
|
||||
};
|
||||
const { code } = await AfterSaleApi.createAfterSale(data);
|
||||
if (code === 0) {
|
||||
uni.showToast({
|
||||
title: '申请成功',
|
||||
});
|
||||
sheep.$router.go('/pages/order/aftersale/list');
|
||||
}
|
||||
}
|
||||
|
||||
// 选择售后类型
|
||||
function onRefundChange(e) {
|
||||
formData.way = e.detail.value;
|
||||
// 清理理由
|
||||
state.reasonList =
|
||||
formData.way === '10'
|
||||
? state.config.afterSaleRefundReasons || []
|
||||
: state.config.afterSaleReturnReasons || [];
|
||||
formData.applyReason = '';
|
||||
state.currentValue = '';
|
||||
}
|
||||
|
||||
// 选择申请原因
|
||||
function onChange(e) {
|
||||
state.currentValue = e.detail.value;
|
||||
}
|
||||
|
||||
// 确定
|
||||
function onReason() {
|
||||
formData.applyReason = state.currentValue;
|
||||
state.showModal = false;
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
// 解析参数
|
||||
if (!options.orderId || !options.itemId) {
|
||||
sheep.$helper.toast(`缺少订单信息,请检查`);
|
||||
return;
|
||||
}
|
||||
state.orderId = options.orderId;
|
||||
state.itemId = parseInt(options.itemId);
|
||||
|
||||
// 读取订单信息
|
||||
const { code, data } = await OrderApi.getOrder(state.orderId);
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.order = data;
|
||||
state.item = data.items.find((item) => item.id === state.itemId) || {};
|
||||
|
||||
// 设置选项
|
||||
if (state.order.status === 10) {
|
||||
state.wayList.splice(1, 1);
|
||||
}
|
||||
|
||||
// 读取配置
|
||||
state.config = (await TradeConfigApi.getTradeConfig()).data;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.item-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
// margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
// 售后项目
|
||||
.refund-item {
|
||||
background-color: #fff;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
padding: 30rpx;
|
||||
|
||||
&:last-child {
|
||||
border: none;
|
||||
}
|
||||
|
||||
// 留言
|
||||
.describe-box {
|
||||
width: 690rpx;
|
||||
background: rgba(249, 250, 251, 1);
|
||||
padding: 30rpx;
|
||||
box-sizing: border-box;
|
||||
border-radius: 20rpx;
|
||||
|
||||
.describe-content {
|
||||
height: 200rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
// 联系方式
|
||||
.input-box {
|
||||
height: 84rpx;
|
||||
background: rgba(249, 250, 251, 1);
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-box {
|
||||
background: #fff;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.foot-wrap {
|
||||
height: 100rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.foot_box {
|
||||
height: 100rpx;
|
||||
background-color: #fff;
|
||||
|
||||
.sub-btn {
|
||||
width: 336rpx;
|
||||
line-height: 74rpx;
|
||||
border-radius: 38rpx;
|
||||
color: rgba(#fff, 0.9);
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.contcat-btn {
|
||||
width: 336rpx;
|
||||
line-height: 74rpx;
|
||||
background: rgba(238, 238, 238, 1);
|
||||
border-radius: 38rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.modal-box {
|
||||
width: 750rpx;
|
||||
// height: 680rpx;
|
||||
border-radius: 30rpx 30rpx 0 0;
|
||||
background: #fff;
|
||||
|
||||
.modal-head {
|
||||
height: 100rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.modal-foot {
|
||||
.close-btn {
|
||||
width: 710rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
color: rgba(#fff, 0.9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.success-box {
|
||||
width: 600rpx;
|
||||
padding: 90rpx 0 64rpx 0;
|
||||
|
||||
.cicon-check-round {
|
||||
font-size: 96rpx;
|
||||
color: #04b750;
|
||||
}
|
||||
|
||||
.success-title {
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.success-btn {
|
||||
width: 492rpx;
|
||||
height: 70rpx;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main-gradient), var(--ui-BG-Main));
|
||||
border-radius: 35rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
379
pages/order/aftersale/detail.vue
Normal file
379
pages/order/aftersale/detail.vue
Normal file
@@ -0,0 +1,379 @@
|
||||
<!-- 售后详情 -->
|
||||
<template>
|
||||
<s-layout title="售后详情" :navbar="!isEmpty(state.info) && state.loading ? 'inner' : 'normal'">
|
||||
<view class="content_box" v-if="!isEmpty(state.info) && state.loading">
|
||||
<!-- 步骤条 -->
|
||||
<view
|
||||
class="steps-box ss-flex"
|
||||
:style="[
|
||||
{
|
||||
marginTop: '-' + Number(statusBarHeight + 88) + 'rpx',
|
||||
paddingTop: Number(statusBarHeight + 88) + 'rpx',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<view class="ss-flex">
|
||||
<view class="steps-item" v-for="(item, index) in state.list" :key="index">
|
||||
<view class="ss-flex">
|
||||
<text
|
||||
class="sicon-circleclose"
|
||||
v-if="state.list.length - 1 === index && [61, 62, 63].includes(state.info.status)"
|
||||
/>
|
||||
<text
|
||||
class="sicon-circlecheck"
|
||||
v-else
|
||||
:class="state.active >= index ? 'activity-color' : 'info-color'"
|
||||
/>
|
||||
|
||||
<view
|
||||
v-if="state.list.length - 1 !== index"
|
||||
class="line"
|
||||
:class="state.active >= index ? 'activity-bg' : 'info-bg'"
|
||||
/>
|
||||
</view>
|
||||
<view
|
||||
class="steps-item-title"
|
||||
:class="state.active >= index ? 'activity-color' : 'info-color'"
|
||||
>
|
||||
{{ item.title }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 服务状态 -->
|
||||
<view
|
||||
class="status-box ss-flex ss-col-center ss-row-between ss-m-x-20"
|
||||
@tap="sheep.$router.go('/pages/order/aftersale/log', { id: state.id })"
|
||||
>
|
||||
<view class="">
|
||||
<view class="status-text">
|
||||
{{ formatAfterSaleStatusDescription(state.info) }}
|
||||
</view>
|
||||
<view class="status-time">
|
||||
{{ sheep.$helper.timeFormat(state.info.updateTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</view>
|
||||
</view>
|
||||
<text class="ss-iconfont _icon-forward" style="color: #666" />
|
||||
</view>
|
||||
|
||||
<!-- 退款金额 -->
|
||||
<view class="aftersale-money ss-flex ss-col-center ss-row-between">
|
||||
<view class="aftersale-money--title">退款总额</view>
|
||||
<view class="aftersale-money--num">¥{{ fen2yuan(state.info.refundPrice) }}</view>
|
||||
</view>
|
||||
<!-- 服务商品 -->
|
||||
<view class="order-shop">
|
||||
<s-goods-item
|
||||
:img="state.info.picUrl"
|
||||
:title="state.info.spuName"
|
||||
:titleWidth="480"
|
||||
:skuText="state.info.properties.map((property) => property.valueName).join(' ')"
|
||||
:num="state.info.count"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 服务内容 -->
|
||||
<view class="aftersale-content">
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">服务单号:</view>
|
||||
<view class="item-content ss-m-r-16">{{ state.info.no }}</view>
|
||||
<button class="ss-reset-button copy-btn" @tap="onCopy">复制</button>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">申请时间:</view>
|
||||
<view class="item-content">
|
||||
{{ sheep.$helper.timeFormat(state.info.createTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">售后类型:</view>
|
||||
<view class="item-content">{{ state.info.way === 10 ? '仅退款' : '退款退货' }}</view>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">申请原因:</view>
|
||||
<view class="item-content">{{ state.info.applyReason }}</view>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">相关描述:</view>
|
||||
<view class="item-content">{{ state.info.applyDescription }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作区 -->
|
||||
<s-empty
|
||||
v-if="isEmpty(state.info) && state.loading"
|
||||
icon="/static/order-empty.png"
|
||||
text="暂无该订单售后详情"
|
||||
/>
|
||||
<su-fixed bottom placeholder bg="bg-white" v-if="!isEmpty(state.info)">
|
||||
<view class="foot_box">
|
||||
<button
|
||||
class="ss-reset-button btn"
|
||||
v-if="state.info.buttons?.includes('cancel')"
|
||||
@tap="onApply(state.info.id)"
|
||||
>
|
||||
取消申请
|
||||
</button>
|
||||
<button
|
||||
class="ss-reset-button btn"
|
||||
v-if="state.info.buttons?.includes('delivery')"
|
||||
@tap="sheep.$router.go('/pages/order/aftersale/return-delivery', { id: state.info.id })"
|
||||
>
|
||||
填写退货
|
||||
</button>
|
||||
<button
|
||||
class="ss-reset-button contcat-btn btn"
|
||||
@tap="sheep.$router.go('/pages/chat/index')"
|
||||
>
|
||||
联系客服
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import {
|
||||
fen2yuan,
|
||||
formatAfterSaleStatusDescription,
|
||||
handleAfterSaleButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import AfterSaleApi from '@/sheep/api/trade/afterSale';
|
||||
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png');
|
||||
const state = reactive({
|
||||
id: 0, // 售后编号
|
||||
info: {}, // 收货信息
|
||||
loading: false,
|
||||
active: 0, // 在 list 的激活位置
|
||||
list: [
|
||||
{
|
||||
title: '提交申请',
|
||||
},
|
||||
{
|
||||
title: '处理中',
|
||||
},
|
||||
{
|
||||
title: '完成',
|
||||
},
|
||||
], // 时间轴
|
||||
});
|
||||
|
||||
function onApply(id) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消此申请吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await AfterSaleApi.cancelAfterSale(id);
|
||||
if (code === 0) {
|
||||
await getDetail(id);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 复制
|
||||
const onCopy = () => {
|
||||
sheep.$helper.copyText(state.info.no);
|
||||
};
|
||||
|
||||
async function getDetail(id) {
|
||||
state.loading = true;
|
||||
const { code, data } = await AfterSaleApi.getAfterSale(id);
|
||||
if (code !== 0) {
|
||||
state.info = null;
|
||||
return;
|
||||
}
|
||||
state.info = data;
|
||||
handleAfterSaleButtons(state.info);
|
||||
|
||||
// 处理时间轴
|
||||
if ([10].includes(state.info.status)) {
|
||||
state.active = 0;
|
||||
} else if ([20, 30].includes(state.info.status)) {
|
||||
state.active = 1;
|
||||
} else if ([40, 50].includes(state.info.status)) {
|
||||
state.active = 2;
|
||||
} else if ([61, 62, 63].includes(state.info.status)) {
|
||||
state.active = 2;
|
||||
}
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
if (!options.id) {
|
||||
sheep.$helper.toast(`缺少订单信息,请检查`);
|
||||
return;
|
||||
}
|
||||
state.id = options.id;
|
||||
getDetail(options.id);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 步骤条
|
||||
.steps-box {
|
||||
width: 100%;
|
||||
height: 190rpx;
|
||||
background: v-bind(headerBg) no-repeat,
|
||||
linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
background-size: 750rpx 100%;
|
||||
padding-left: 72rpx;
|
||||
|
||||
.steps-item {
|
||||
.sicon-circleclose {
|
||||
font-size: 24rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.sicon-circlecheck {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.steps-item-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
margin-top: 16rpx;
|
||||
margin-left: -36rpx;
|
||||
width: 100rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.activity-color {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.info-color {
|
||||
color: rgba(#fff, 0.4);
|
||||
}
|
||||
|
||||
.activity-bg {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.info-bg {
|
||||
background: rgba(#fff, 0.4);
|
||||
}
|
||||
|
||||
.line {
|
||||
width: 270rpx;
|
||||
height: 4rpx;
|
||||
}
|
||||
|
||||
// 服务状态
|
||||
.status-box {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx 20rpx 0px 0px;
|
||||
padding: 20rpx;
|
||||
margin-top: -20rpx;
|
||||
|
||||
.status-text {
|
||||
font-size: 28rpx;
|
||||
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.status-time {
|
||||
font-size: 24rpx;
|
||||
|
||||
font-weight: 400;
|
||||
color: rgba(153, 153, 153, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 退款金额
|
||||
.aftersale-money {
|
||||
background-color: #fff;
|
||||
height: 98rpx;
|
||||
padding: 0 20rpx;
|
||||
margin: 20rpx;
|
||||
|
||||
.aftersale-money--title {
|
||||
font-size: 28rpx;
|
||||
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
|
||||
.aftersale-money--num {
|
||||
font-size: 28rpx;
|
||||
font-family: OPPOSANS;
|
||||
font-weight: 500;
|
||||
color: #ff3000;
|
||||
}
|
||||
}
|
||||
|
||||
// order-shop
|
||||
.order-shop {
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
}
|
||||
|
||||
// 服务内容
|
||||
.aftersale-content {
|
||||
background-color: #fff;
|
||||
padding: 20rpx;
|
||||
margin: 0 20rpx;
|
||||
|
||||
.aftersale-item {
|
||||
height: 60rpx;
|
||||
|
||||
.copy-btn {
|
||||
background: #eeeeee;
|
||||
color: #333;
|
||||
border-radius: 20rpx;
|
||||
width: 75rpx;
|
||||
height: 40rpx;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.item-title {
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 底部功能
|
||||
.foot_box {
|
||||
height: 100rpx;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
|
||||
.btn {
|
||||
width: 160rpx;
|
||||
line-height: 60rpx;
|
||||
background: rgba(238, 238, 238, 1);
|
||||
border-radius: 30rpx;
|
||||
padding: 0;
|
||||
margin-right: 20rpx;
|
||||
font-size: 26rpx;
|
||||
|
||||
font-weight: 400;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
}
|
||||
</style>
|
210
pages/order/aftersale/list.vue
Normal file
210
pages/order/aftersale/list.vue
Normal file
@@ -0,0 +1,210 @@
|
||||
<!-- 售后列表 -->
|
||||
<template>
|
||||
<s-layout title="售后列表">
|
||||
<!-- tab -->
|
||||
<su-sticky bgColor="#fff">
|
||||
<su-tabs
|
||||
:list="tabMaps"
|
||||
:scrollable="false"
|
||||
@change="onTabsChange"
|
||||
:current="state.currentTab"
|
||||
/>
|
||||
</su-sticky>
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/data-empty.png" text="暂无数据" />
|
||||
<!-- 列表 -->
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view
|
||||
class="list-box ss-m-y-20"
|
||||
v-for="order in state.pagination.list"
|
||||
:key="order.id"
|
||||
@tap="sheep.$router.go('/pages/order/aftersale/detail', { id: order.id })"
|
||||
>
|
||||
<view class="order-head ss-flex ss-col-center ss-row-between">
|
||||
<text class="no">服务单号:{{ order.no }}</text>
|
||||
<text class="state">{{ formatAfterSaleStatus(order) }}</text>
|
||||
</view>
|
||||
<s-goods-item
|
||||
:img="order.picUrl"
|
||||
:title="order.spuName"
|
||||
:skuText="order.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="order.refundPrice"
|
||||
/>
|
||||
<view class="apply-box ss-flex ss-col-center ss-row-between border-bottom ss-p-x-20">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<view class="title ss-m-r-20">{{ order.way === 10 ? '仅退款' : '退款退货' }}</view>
|
||||
<view class="value">{{ formatAfterSaleStatusDescription(order) }}</view>
|
||||
</view>
|
||||
<text class="_icon-forward"></text>
|
||||
</view>
|
||||
<view class="tool-btn-box ss-flex ss-col-center ss-row-right ss-p-r-20">
|
||||
<!-- TODO 功能缺失:填写退货信息 -->
|
||||
<view>
|
||||
<button
|
||||
class="ss-reset-button tool-btn"
|
||||
@tap.stop="onApply(order.id)"
|
||||
v-if="order?.buttons.includes('cancel')"
|
||||
>取消申请</button
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
}"
|
||||
@tap="loadMore"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash-es';
|
||||
import {
|
||||
formatAfterSaleStatus,
|
||||
formatAfterSaleStatusDescription,
|
||||
handleAfterSaleButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import AfterSaleApi from '@/sheep/api/trade/afterSale';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
|
||||
const state = reactive({
|
||||
currentTab: 0,
|
||||
showApply: false,
|
||||
pagination: {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
loadStatus: '',
|
||||
});
|
||||
|
||||
// TODO 芋艿:优化点,增加筛选
|
||||
const tabMaps = [
|
||||
{
|
||||
name: '全部',
|
||||
value: 'all',
|
||||
},
|
||||
// {
|
||||
// name: '申请中',
|
||||
// value: 'nooper',
|
||||
// },
|
||||
// {
|
||||
// name: '处理中',
|
||||
// value: 'ing',
|
||||
// },
|
||||
// {
|
||||
// name: '已完成',
|
||||
// value: 'completed',
|
||||
// },
|
||||
// {
|
||||
// name: '已拒绝',
|
||||
// value: 'refuse',
|
||||
// },
|
||||
];
|
||||
|
||||
// 切换选项卡
|
||||
function onTabsChange(e) {
|
||||
resetPagination(state.pagination);
|
||||
state.currentTab = e.index;
|
||||
getOrderList();
|
||||
}
|
||||
|
||||
// 获取售后列表
|
||||
async function getOrderList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { data, code } = await AfterSaleApi.getAfterSalePage({
|
||||
// type: tabMaps[state.currentTab].value,
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
data.list.forEach((order) => handleAfterSaleButtons(order));
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
|
||||
function onApply(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消此申请吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await AfterSaleApi.cancelAfterSale(orderId);
|
||||
if (code === 0) {
|
||||
resetPagination(state.pagination);
|
||||
await getOrderList();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
if (options.type) {
|
||||
state.currentTab = options.type;
|
||||
}
|
||||
await getOrderList();
|
||||
});
|
||||
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
state.pagination.pageNo++;
|
||||
getOrderList();
|
||||
}
|
||||
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.list-box {
|
||||
background-color: #fff;
|
||||
|
||||
.order-head {
|
||||
padding: 0 25rpx;
|
||||
height: 77rpx;
|
||||
}
|
||||
|
||||
.apply-box {
|
||||
height: 82rpx;
|
||||
|
||||
.title {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 22rpx;
|
||||
color: $dark-6;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-btn-box {
|
||||
height: 100rpx;
|
||||
|
||||
.tool-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #f6f6f6;
|
||||
border-radius: 30rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
77
pages/order/aftersale/log-item.vue
Normal file
77
pages/order/aftersale/log-item.vue
Normal file
@@ -0,0 +1,77 @@
|
||||
<!-- 售后日志的每一项展示 -->
|
||||
<template>
|
||||
<view class="log-item ss-flex">
|
||||
<view class="log-icon ss-flex-col ss-col-center ss-m-r-20">
|
||||
<text class="cicon-title" :class="index === 0 ? 'activity-color' : ''" />
|
||||
<view v-if="data.length - 1 !== index" class="line" />
|
||||
</view>
|
||||
<view>
|
||||
<view class="text">{{ item.content }}</view>
|
||||
<view class="date">
|
||||
{{ sheep.$helper.timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object, // 当前日志
|
||||
default() {},
|
||||
},
|
||||
index: {
|
||||
type: Number, // item 在 data 的下标
|
||||
default: 0,
|
||||
},
|
||||
data: {
|
||||
type: Object, // 日志列表
|
||||
default() {},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.log-item {
|
||||
align-items: stretch;
|
||||
}
|
||||
.log-icon {
|
||||
height: inherit;
|
||||
.cicon-title {
|
||||
font-size: 30rpx;
|
||||
color: #dfdfdf;
|
||||
}
|
||||
.activity-color {
|
||||
color: #60bd45;
|
||||
}
|
||||
.line {
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
background: #dfdfdf;
|
||||
}
|
||||
}
|
||||
.text {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
}
|
||||
.richtext {
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: #999999;
|
||||
margin: 20rpx 0 0 0;
|
||||
}
|
||||
.content-img {
|
||||
margin-top: 20rpx;
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
}
|
||||
.date {
|
||||
margin-top: 20rpx;
|
||||
font-size: 24rpx;
|
||||
font-family: OPPOSANS;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
</style>
|
38
pages/order/aftersale/log.vue
Normal file
38
pages/order/aftersale/log.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<!-- 售后日志列表 -->
|
||||
<template>
|
||||
<s-layout title="售后进度">
|
||||
<view class="log-box">
|
||||
<view v-for="(item, index) in state.list" :key="item.id">
|
||||
<log-item :item="item" :index="index" :data="state.list" />
|
||||
</view>
|
||||
</view>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import logItem from './log-item.vue';
|
||||
import AfterSaleApi from '@/sheep/api/trade/afterSale';
|
||||
|
||||
const state = reactive({
|
||||
list: [],
|
||||
});
|
||||
|
||||
async function getDetail(id) {
|
||||
const { data } = await AfterSaleApi.getAfterSaleLogList(id);
|
||||
state.list = data;
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
state.aftersaleId = options.id;
|
||||
getDetail(options.id);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.log-box {
|
||||
padding: 24rpx 24rpx 24rpx 40rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
195
pages/order/aftersale/return-delivery.vue
Normal file
195
pages/order/aftersale/return-delivery.vue
Normal file
@@ -0,0 +1,195 @@
|
||||
<template>
|
||||
<s-layout title="退货物流">
|
||||
<view>
|
||||
<form @submit="subRefund" report-submit='true'>
|
||||
<view class='apply-return'>
|
||||
<view class='list borRadius14'>
|
||||
<view class='item acea-row row-between-wrapper' style="display: flex;align-items: center;">
|
||||
<view>物流公司</view>
|
||||
<view v-if="state.expresses.length>0" style="flex:1">
|
||||
<picker mode='selector' class='num' @change="bindPickerChange" :value="state.expressIndex"
|
||||
:range="state.expresses" range-key="name">
|
||||
<view class="picker acea-row row-between-wrapper" style="display: flex;justify-content: space-between;">
|
||||
<view class='reason'>{{ state.expresses[state.expressIndex].name }}</view>
|
||||
<text class='iconfont _icon-forward' />
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class='item textarea acea-row row-between' style="display: flex;align-items: center;">
|
||||
<view>物流单号</view>
|
||||
<input placeholder='请填写物流单号' class='num' name="logisticsNo"
|
||||
placeholder-class='placeholder' />
|
||||
</view>
|
||||
<button class='returnBnt bg-color ss-reset-button ui-BG-Main-Gradient sub-btn'
|
||||
form-type="submit"
|
||||
style="background: linear-gradient(90deg,var(--ui-BG-Main),var(--ui-BG-Main-gradient))!important">提交</button>
|
||||
</view>
|
||||
</view>
|
||||
</form>
|
||||
</view>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import AfterSaleApi from '@/sheep/api/trade/afterSale';
|
||||
import DeliveryApi from '@/sheep/api/trade/delivery';
|
||||
|
||||
const state = reactive({
|
||||
id: 0, // 售后编号
|
||||
expressIndex: 0, // 选中的 expresses 下标
|
||||
expresses: [], // 可选的快递列表
|
||||
})
|
||||
|
||||
function bindPickerChange(e) {
|
||||
state.expressIndex = e.detail.value;
|
||||
}
|
||||
|
||||
async function subRefund(e) {
|
||||
let data = {
|
||||
id: state.id,
|
||||
logisticsId: state.expresses[state.expressIndex].id,
|
||||
logisticsNo: e.detail.value.logisticsNo,
|
||||
};
|
||||
const { code } = await AfterSaleApi.deliveryAfterSale(data);
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
uni.showToast({
|
||||
title: '填写退货成功',
|
||||
});
|
||||
sheep.$router.go('/pages/order/aftersale/detail', { id: state.id });
|
||||
}
|
||||
|
||||
// 获得快递物流列表
|
||||
async function getExpressList() {
|
||||
const { code, data } = await DeliveryApi.getDeliveryExpressList();
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.expresses = data;
|
||||
}
|
||||
|
||||
onLoad(options => {
|
||||
if (!options.id) {
|
||||
sheep.$helper.toast(`缺少订单信息,请检查`);
|
||||
return
|
||||
}
|
||||
state.id = options.id;
|
||||
// 获得快递物流列表
|
||||
getExpressList();
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.apply-return {
|
||||
padding: 20rpx 30rpx 70rpx 30rpx;
|
||||
}
|
||||
|
||||
.apply-return .list {
|
||||
background-color: #fff;
|
||||
margin-top: 18rpx;
|
||||
padding: 0 24rpx 70rpx 24rpx;
|
||||
}
|
||||
|
||||
.apply-return .list .item {
|
||||
min-height: 90rpx;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.apply-return .list .item .num {
|
||||
color: #282828;
|
||||
margin-left: 27rpx;
|
||||
// width: 227rpx;
|
||||
// text-align: right;
|
||||
}
|
||||
|
||||
.apply-return .list .item .num .picker .reason {
|
||||
width: 385rpx;
|
||||
}
|
||||
|
||||
.apply-return .list .item .num .picker .iconfont {
|
||||
color: #666;
|
||||
font-size: 30rpx;
|
||||
margin-top: 2rpx;
|
||||
}
|
||||
|
||||
.apply-return .list .item.textarea {
|
||||
padding: 24rpx 0;
|
||||
}
|
||||
|
||||
.apply-return .list .item textarea {
|
||||
height: 100rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.apply-return .list .item .placeholder {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.apply-return .list .item .title {
|
||||
height: 95rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.apply-return .list .item .title .tip {
|
||||
font-size: 30rpx;
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.apply-return .list .item .upload {
|
||||
padding-bottom: 36rpx;
|
||||
}
|
||||
|
||||
.apply-return .list .item .upload .pictrue {
|
||||
border-radius: 14rpx;
|
||||
margin: 22rpx 23rpx 0 0;
|
||||
width: 156rpx;
|
||||
height: 156rpx;
|
||||
position: relative;
|
||||
font-size: 24rpx;
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.apply-return .list .item .upload .pictrue:nth-of-type(4n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.apply-return .list .item .upload .pictrue image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 14rpx;
|
||||
}
|
||||
|
||||
.apply-return .list .item .upload .pictrue .icon-guanbi1 {
|
||||
position: absolute;
|
||||
font-size: 45rpx;
|
||||
top: -10rpx;
|
||||
right: -10rpx;
|
||||
}
|
||||
|
||||
.apply-return .list .item .upload .pictrue .icon-icon25201 {
|
||||
color: #bfbfbf;
|
||||
font-size: 50rpx;
|
||||
}
|
||||
|
||||
.apply-return .list .item .upload .pictrue:nth-last-child(1) {
|
||||
border: 1rpx solid #ddd;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.apply-return .returnBnt {
|
||||
font-size: 32rpx;
|
||||
color: #fff;
|
||||
width: 100%;
|
||||
height: 86rpx;
|
||||
border-radius: 50rpx;
|
||||
text-align: center;
|
||||
line-height: 86rpx;
|
||||
margin: 43rpx auto;
|
||||
}
|
||||
</style>
|
182
pages/order/blind/components/layout.vue
Normal file
182
pages/order/blind/components/layout.vue
Normal file
@@ -0,0 +1,182 @@
|
||||
<!-- 虚拟列表演示(不使用内置列表)(vue) -->
|
||||
<!-- 写法较简单,在页面中对当前需要渲染的虚拟列表数据进行for循环,在vue3中兼容性良好 -->
|
||||
<!-- 在各平台兼容性请查阅https://z-paging.zxlee.cn/module/virtual-list.html -->
|
||||
<template>
|
||||
<view class="content">
|
||||
<!-- 如果页面中的cell高度是固定不变的,则不需要设置cell-height-mode,如果页面中高度是动态改变的,则设置cell-height-mode="dynamic" -->
|
||||
<!-- 原先的v-model修改为@virtualListChange="virtualListChange"并赋值处理后的虚拟列表 -->
|
||||
<z-paging ref="paging" :auto="false" use-virtual-list :force-close-inner-list="true" :paging-style="{ paddingTop: 0 + 'px', paddingBottom: paddingBottom + 'rpx' }" cell-height-mode="dynamic" @scroll="scroll" @virtualListChange="virtualListChange" @query="queryList">
|
||||
<!-- 需要固定在顶部不滚动的view放在slot="top"的view中,如果需要跟着滚动,则不要设置slot="top" -->
|
||||
<template #top>
|
||||
<su-navbar :title="title" statusBar></su-navbar>
|
||||
<tab-box :tabList="tabList" :currentValue="currentIndex" @change="tabChange"></tab-box>
|
||||
</template>
|
||||
|
||||
<!-- :id="`zp-id-${item.zp_index}`"和:key="item.zp_index" 必须写,必须写!!!! -->
|
||||
<!-- 这里for循环的index不是数组中真实的index了,请使用item.zp_index获取真实的index -->
|
||||
<order-list @onCancel="onCancel" @onConfirm="onConfirm" @onOrderConfirm="onOrderConfirm" :virtualList="virtualList"></order-list>
|
||||
|
||||
</z-paging>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TabBox from '@/pages/order/blind/components/tabBox.vue';
|
||||
import OrderList from '@/pages/order/blind/components/orderList.vue';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import { WxaSubscribeTemplate } from '@/sheep/util/const';
|
||||
import sheep from '@/sheep';
|
||||
import {
|
||||
formatBlindOrderStatus,
|
||||
handleBlindOrderButtons,
|
||||
fen2yuan,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
export default {
|
||||
components: {
|
||||
TabBox,
|
||||
OrderList,
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '抢单中心',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 虚拟列表数组,通过@virtualListChange监听获得最新数组
|
||||
virtualList: [],
|
||||
scrollTop: 0,
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
height: 0,
|
||||
|
||||
tabList: [{
|
||||
name: '全部',
|
||||
}, {
|
||||
name: '待抢单',
|
||||
value: 10,
|
||||
}, {
|
||||
name: '服务中',
|
||||
value: 20,
|
||||
}, {
|
||||
name: '已完成',
|
||||
value: 30,
|
||||
}],
|
||||
|
||||
currentIndex: 0,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
scroll(e) {
|
||||
this.scrollTop = e.detail.scrollTop;
|
||||
},
|
||||
// 监听虚拟列表数组改变并赋值给virtualList进行重新渲染
|
||||
virtualListChange(vList) {
|
||||
this.virtualList = vList;
|
||||
},
|
||||
queryList(pageNo, pageSize) {
|
||||
// 组件加载时会自动触发此方法,因此默认页面加载时会自动触发,无需手动调用
|
||||
// 这里的pageNo和pageSize会自动计算好,直接传给服务器即可
|
||||
// 模拟请求服务器获取分页数据,请替换成自己的网络请求
|
||||
const params = {
|
||||
pageNo: pageNo,
|
||||
pageSize: pageSize,
|
||||
status: this.tabList[this.currentIndex].value,
|
||||
commentStatus: this.tabList[this.currentIndex].value === 30 ? false : null,
|
||||
}
|
||||
OrderApi.getBlindOrderPage(params).then(res => {
|
||||
// 将请求的结果数组传递给z-paging
|
||||
res.data.list.forEach((order) => handleBlindOrderButtons(order, sheep.$store('user').userInfo.id));
|
||||
res.data.list.forEach((order) => formatBlindOrderStatus(order));
|
||||
res.data.list.forEach((order) => order.brokeragePrice = fen2yuan(order.brokeragePrice));
|
||||
this.$refs.paging.complete(res.data.list);
|
||||
}).catch(res => {
|
||||
// 如果请求失败写this.$refs.paging.complete(false);
|
||||
// 注意,每次都需要在catch中写这句话很麻烦,z-paging提供了方案可以全局统一处理
|
||||
// 在底层的网络请求抛出异常时,写uni.$emit('z-paging-error-emit');即可
|
||||
this.$refs.paging.complete(false);
|
||||
})
|
||||
},
|
||||
tabChange(e) {
|
||||
this.currentIndex = e;
|
||||
this.$refs.paging.reload();
|
||||
},
|
||||
// 取消订单
|
||||
async onCancel(orderId) {
|
||||
var that = this;
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消订单吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await OrderApi.cancelOrder(orderId);
|
||||
if (code === 0) {
|
||||
that.$refs.paging.reload();
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
// 开始接单
|
||||
async onOrderConfirm(order) {
|
||||
var that = this;
|
||||
uni.showModal({
|
||||
title: '是否确认抢单',
|
||||
content: '请确认符合老板要求',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
// 正常的确认收货流程
|
||||
const { code } = await OrderApi.deliveryOrder(order.id);
|
||||
if (code === 0) {
|
||||
that.tabChange(2);
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
// 确认收货
|
||||
async onConfirm(order) {
|
||||
// #ifdef MP
|
||||
// 订阅只能由用户主动触发,只能包一层 showModal 诱导用户点击
|
||||
this.subscribeMessage();
|
||||
// #endif
|
||||
|
||||
var that = this;
|
||||
uni.showModal({
|
||||
title: '确定要结束服务么?',
|
||||
content: '请确认经过老板同意',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 正常的确认收货流程
|
||||
const { code } = await OrderApi.receiveOrder(order.id);
|
||||
if (code === 0) {
|
||||
that.$refs.paging.reload();
|
||||
}
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
},
|
||||
subscribeMessage() {
|
||||
const event = [WxaSubscribeTemplate.CLERK_ORDER];
|
||||
event.push(WxaSubscribeTemplate.REWARD_SUCCESS);
|
||||
sheep.$platform.useProvider('wechat').subscribeMessage(event, () => {
|
||||
// 订阅后记录一下订阅状态
|
||||
uni.removeStorageSync(WxaSubscribeTemplate.CLERK_ORDER);
|
||||
uni.setStorageSync(WxaSubscribeTemplate.CLERK_ORDER, '已订阅');
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
248
pages/order/blind/components/orderList.vue
Normal file
248
pages/order/blind/components/orderList.vue
Normal file
@@ -0,0 +1,248 @@
|
||||
<template>
|
||||
<view @click="onOrderDetail(order.id)" :id="`zp-id-${order.zp_index}`" :key="order.zp_index" v-for="(order,index) in orderList" class="order-card">
|
||||
<view class="no-box">
|
||||
<view class="order-no">
|
||||
<u-icon name="order"></u-icon>
|
||||
<text class="number">{{ order.no }}</text>
|
||||
</view>
|
||||
<view class="status">{{order.statusStr}}</view>
|
||||
</view>
|
||||
|
||||
<view class="main-box" v-for="item in order.items" :key="item.id">
|
||||
<view>
|
||||
<u-avatar size="100" :src="order.avatar"></u-avatar>
|
||||
</view>
|
||||
<view class="right-box">
|
||||
<view class="nickname-box">
|
||||
<view class="nickname">{{order.nickname}}</view>
|
||||
<view class="info">订单时间:{{order.createTimeStr}}</view>
|
||||
<view class="info">服务内容:{{item.spuName}} {{item.properties.map((property) => property.valueName).join(' ')}}×{{item.count}}</view>
|
||||
<view class="info" v-if="order.sex == '1'">性别要求:女生</view>
|
||||
<view class="info" v-if="order.sex == '0'">性别要求:男生</view>
|
||||
<view class="info" v-if="userInfo.id == order.workerUserId">
|
||||
<text class="weixin">微信:{{order.weixin}}</text>
|
||||
<view @tap.stop="onCopy(order.weixin)">
|
||||
<u-icon name="outline-copy" custom-prefix="iconfont"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info">
|
||||
<text>剩余时间:</text>
|
||||
<view v-if="order.receiveTime">
|
||||
<text v-if="order.end">已结束</text>
|
||||
<view v-else>
|
||||
<u-count-down :timestamp="order.timestamp" format="DD天HH时mm分ss秒" @end="order.end = true"></u-count-down>
|
||||
</view>
|
||||
</view>
|
||||
<text v-else>暂未接单</text>
|
||||
</view>
|
||||
<view class="info" v-if="order.userRemark">备注:{{order.userRemark}}</view>
|
||||
<view class="info" v-if="order.cancelReason">取消原因:{{order.cancelReason}}</view>
|
||||
</view>
|
||||
<view class="price-box">
|
||||
<text class="price">{{order.brokeragePrice}}</text>
|
||||
<text>/钻</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-box">
|
||||
<view class="btn-box">
|
||||
<view v-if="order.buttons.includes('other')" class="btn">也被其它店员抢单</view>
|
||||
<view v-if="order.buttons.includes('detail')" @tap.stop="onOrderDetail(order.id)" class="btn">查看详情</view>
|
||||
<view v-if="order.buttons.includes('unpay')" @tap.stop="onOrderCancel(order.id, order.items[0].id)" class="btn">取消接单</view>
|
||||
<view v-if="order.buttons.includes('cancel')" @tap.stop="onCancel(order.id)" class="btn">取消订单</view>
|
||||
<view v-if="order.buttons.includes('invite')" @tap.stop="onBuy(order.items[0].spuId)" class="btn active">邀请好友抢单</view>
|
||||
<view v-if="order.buttons.includes('invite2')" @tap.stop="onBuy(order.items[0].spuId)" class="btn active">邀请评价</view>
|
||||
<view v-if="order.buttons.includes('agree')" @tap.stop="onOrderConfirm(order)" class="btn active">立即抢单</view>
|
||||
<view v-if="order.buttons.includes('confirm')" @tap.stop="onConfirm(order)" class="btn active">结束服务</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import sheep from '@/sheep';
|
||||
import dayjs from 'dayjs';
|
||||
export default {
|
||||
components: {
|
||||
|
||||
},
|
||||
props: {
|
||||
virtualList: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
emits: ["onCancel", "onConfirm", "onOrderConfirm"],
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
userInfo: {
|
||||
get() {
|
||||
return sheep.$store('user').userInfo;
|
||||
},
|
||||
},
|
||||
orderList() {
|
||||
this.virtualList.forEach((order) => order.createTimeStr = sheep.$helper.timeFormat(order.createTime, 'yyyy-mm-dd hh:MM:ss'));
|
||||
this.virtualList.forEach((order) => order.timestamp = order.receiveTime ? sheep.$helper.parseTimeData(order.receiveTime) : 0);
|
||||
return this.virtualList;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 订单详情
|
||||
onOrderDetail(id) {
|
||||
sheep.$router.go('/pages/order/blind/detail', {
|
||||
id,
|
||||
});
|
||||
},
|
||||
onCancel(orderId) {
|
||||
this.$emit('onCancel', orderId);
|
||||
},
|
||||
onBuy(id) {
|
||||
sheep.$router.go('/pages/clerk/detail/index', {
|
||||
id,
|
||||
});
|
||||
},
|
||||
// 评价
|
||||
onComment(id) {
|
||||
sheep.$router.go('/pages/goods/comment/worker/add', {
|
||||
id,
|
||||
});
|
||||
},
|
||||
// 继续支付
|
||||
onPay(payOrderId) {
|
||||
sheep.$router.go('/pages/pay/worker/index', {
|
||||
id: payOrderId,
|
||||
});
|
||||
},
|
||||
onOrderCancel(orderId, itemId) {
|
||||
sheep.$router.go('/pages/order/worker/aftersale/apply', {
|
||||
orderId: orderId,
|
||||
itemId: itemId
|
||||
});
|
||||
},
|
||||
onOrderConfirm(order) {
|
||||
this.$emit('onOrderConfirm', order);
|
||||
},
|
||||
// 复制
|
||||
onCopy(text) {
|
||||
sheep.$helper.copyText(text);
|
||||
},
|
||||
// 确认收货
|
||||
onConfirm(order) {
|
||||
this.$emit('onConfirm', order);
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order-card {
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
|
||||
.no-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
padding-bottom: 10px;
|
||||
color: rgb(100, 101, 102);
|
||||
|
||||
.order-no {
|
||||
|
||||
.number {
|
||||
margin-left: 5px;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.status {
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.main-box {
|
||||
display: flex;
|
||||
padding: 10px 0;
|
||||
border-top: 1px solid #fbf0f0;
|
||||
border-bottom: 1px solid #fbf0f0;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.right-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
margin-left: 10px;
|
||||
|
||||
.nickname {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.info {
|
||||
font-size: 22rpx;
|
||||
color: rgb(100, 101, 102);
|
||||
line-height: 22rpx;
|
||||
margin-bottom: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.weixin {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.price-box {
|
||||
font-size: 22rpx;
|
||||
color: rgb(100, 101, 102);
|
||||
|
||||
.price {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-box {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
.btn-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: #ddd;
|
||||
color: rgb(100, 101, 102);
|
||||
font-size: 22rpx;
|
||||
border-radius: 40px;
|
||||
padding: 5px 10px;
|
||||
margin-left: 10px;
|
||||
min-width: 140rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.active {
|
||||
background-color: var(--ui-BG-Main);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
47
pages/order/blind/components/tabBox.vue
Normal file
47
pages/order/blind/components/tabBox.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<view>
|
||||
<u-tabs :list="tabList" bg-color="#fff" font-size="28" active-color="var(--ui-BG-Main)" :is-scroll="false" v-model="current" @change="change"></u-tabs>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
components: {
|
||||
|
||||
},
|
||||
props: {
|
||||
currentValue: 0,
|
||||
tabList: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
current: {
|
||||
get() {
|
||||
return this.currentValue;
|
||||
},
|
||||
set(newValue) {
|
||||
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
change(index) {
|
||||
this.$emit('change', index);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tab-box {
|
||||
background-color: #fff;
|
||||
padding: 5px 0;
|
||||
}
|
||||
</style>
|
435
pages/order/blind/confirm.vue
Normal file
435
pages/order/blind/confirm.vue
Normal file
@@ -0,0 +1,435 @@
|
||||
<template>
|
||||
<s-layout title="确认订单">
|
||||
<!-- 商品信息 -->
|
||||
<view class="order-card-box ss-m-b-14">
|
||||
<s-goods-item
|
||||
v-for="item in state.orderInfo.items"
|
||||
:key="item.skuId"
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price"
|
||||
:num="item.count"
|
||||
marginBottom="10"
|
||||
/>
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between ss-p-x-20 bg-white ss-r-10">
|
||||
<view class="item-title">订单备注</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<uni-easyinput
|
||||
maxlength="20"
|
||||
placeholder="请输入备注内容"
|
||||
v-model="state.orderPayload.remark"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 价格信息 -->
|
||||
<view class="bg-white total-card-box ss-p-20 ss-m-b-14 ss-r-10">
|
||||
<view class="total-box-content border-bottom">
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between">
|
||||
<view class="item-title">技能金额</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="item-value ss-m-r-24">
|
||||
¥{{ fen2yuan(state.orderInfo.price.totalPrice) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.type === 6"
|
||||
>
|
||||
<view class="item-title">积分抵扣</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
{{ state.pointStatus ? '剩余积分' : '当前积分' }}
|
||||
<image
|
||||
:src="sheep.$url.static('/static/img/shop/goods/score1.svg')"
|
||||
class="score-img"
|
||||
/>
|
||||
<text class="item-value ss-m-r-24">
|
||||
{{ state.pointStatus ? state.orderInfo.totalPoint - state.orderInfo.usePoint : (state.orderInfo.totalPoint || 0) }}
|
||||
</text>
|
||||
<checkbox-group @change="changeIntegral">
|
||||
<checkbox :checked='state.pointStatus' :disabled="!state.orderInfo.totalPoint || state.orderInfo.totalPoint <= 0" />
|
||||
</checkbox-group>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="isPass" class="order-item ss-flex ss-col-center ss-row-between">
|
||||
<view class="item-title">TA添加你的微信号</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<uni-easyinput
|
||||
maxlength="20"
|
||||
placeholder="输入正确微信号"
|
||||
v-model="state.orderInfo.weixin"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 优惠劵:只有 type = 0 普通订单(非拼团、秒杀、砍价),才可以使用优惠劵 -->
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.type === 6"
|
||||
>
|
||||
<view class="item-title">优惠券</view>
|
||||
<view class="ss-flex ss-col-center" @tap="state.showCoupon = true">
|
||||
<text class="item-value text-red" v-if="state.orderPayload.couponId > 0">
|
||||
-¥{{ fen2yuan(state.orderInfo.price.couponPrice) }}
|
||||
</text>
|
||||
<text
|
||||
class="item-value"
|
||||
:class="state.couponInfo.length > 0 ? 'text-red' : 'text-disabled'"
|
||||
v-else
|
||||
>
|
||||
{{
|
||||
state.couponInfo.length > 0 ? state.couponInfo.length + ' 张可用' : '暂无可用优惠券'
|
||||
}}
|
||||
</text>
|
||||
<text class="_icon-forward item-icon" />
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.price.discountPrice > 0"
|
||||
>
|
||||
<view class="item-title">活动优惠</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<!-- @tap="state.showDiscount = true" TODO puhui999:【折扣】后续要把优惠信息打进去 -->
|
||||
<text class="item-value text-red">
|
||||
-¥{{ fen2yuan(state.orderInfo.price.discountPrice) }}
|
||||
</text>
|
||||
<text class="_icon-forward item-icon" />
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.price.vipPrice > 0"
|
||||
>
|
||||
<view class="item-title">会员优惠</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="item-value text-red">
|
||||
-¥{{ fen2yuan(state.orderInfo.price.vipPrice) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="total-box-footer ss-font-28 ss-flex ss-row-right ss-col-center ss-m-r-28">
|
||||
<view class="total-num ss-m-r-20">
|
||||
共{{ state.orderInfo.items.reduce((acc, item) => acc + item.count, 0) }}件
|
||||
</view>
|
||||
<view>合计:</view>
|
||||
<view class="total-num text-red"> ¥{{ fen2yuan(state.orderInfo.price.payPrice) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 选择优惠券弹框 -->
|
||||
<s-coupon-select
|
||||
v-model="state.couponInfo"
|
||||
:show="state.showCoupon"
|
||||
@confirm="onSelectCoupon"
|
||||
@close="state.showCoupon = false"
|
||||
/>
|
||||
|
||||
<!-- 满额折扣弹框 TODO @puhui999:【折扣】后续要把优惠信息打进去 -->
|
||||
<s-discount-list
|
||||
v-model="state.orderInfo"
|
||||
:show="state.showDiscount"
|
||||
@close="state.showDiscount = false"
|
||||
/>
|
||||
|
||||
<!-- 底部 -->
|
||||
<su-fixed bottom :opacity="false" bg="bg-white" placeholder :noFixed="false" :index="200">
|
||||
<view class="footer-box border-top ss-flex ss-row-between ss-p-x-20 ss-col-center">
|
||||
<view class="total-box-footer ss-flex ss-col-center">
|
||||
<view class="total-num ss-font-30 text-red">
|
||||
¥{{ fen2yuan(state.orderInfo.price.payPrice) }}
|
||||
</view>
|
||||
</view>
|
||||
<button
|
||||
class="ss-reset-button ui-BG-Main-Gradient ss-r-40 submit-btn ui-Shadow-Main"
|
||||
@tap="onConfirm"
|
||||
>
|
||||
提交订单
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
|
||||
<qrcode-modal />
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, watch, computed } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import AddressSelection from '@/pages/order/addressSelection.vue';
|
||||
import qrcodeModal from '@/components/qrcode-modal/qrcode-modal.vue';
|
||||
import sheep from '@/sheep';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
|
||||
const isPass = computed(() => {
|
||||
return sheep.$store('user').tradeConfig.weixinEnabled;
|
||||
});
|
||||
|
||||
const state = reactive({
|
||||
orderPayload: {},
|
||||
orderInfo: {
|
||||
items: [], // 商品项列表
|
||||
price: {}, // 价格信息
|
||||
},
|
||||
showCoupon: false, // 是否展示优惠劵
|
||||
couponInfo: [], // 优惠劵列表
|
||||
showDiscount: false, // 是否展示营销活动
|
||||
// ========== 积分 ==========
|
||||
pointStatus: false, //是否使用积分
|
||||
});
|
||||
|
||||
const addressState = ref({
|
||||
addressInfo: {}, // 选择的收货地址
|
||||
deliveryType: 1, // 收货方式:1-快递配送,2-门店自提
|
||||
isPickUp: true, // 门店自提是否开启 TODO puhui999: 默认开启,看看后端有开关的话接入
|
||||
pickUpInfo: {}, // 选择的自提门店信息
|
||||
weixin: '', // 收件人名称
|
||||
receiverMobile: '', // 收件人手机
|
||||
});
|
||||
|
||||
// ========== 积分 ==========
|
||||
/**
|
||||
* 使用积分抵扣
|
||||
*/
|
||||
const changeIntegral = async () => {
|
||||
state.pointStatus = !state.pointStatus;
|
||||
await getOrderInfo();
|
||||
};
|
||||
|
||||
// 选择优惠券
|
||||
async function onSelectCoupon(couponId) {
|
||||
state.orderPayload.couponId = couponId;
|
||||
await getOrderInfo();
|
||||
state.showCoupon = false;
|
||||
}
|
||||
|
||||
// 提交订单
|
||||
function onConfirm() {
|
||||
if (isPass && !state.orderInfo.weixin) {
|
||||
sheep.$helper.toast('请填写正确的微信号');
|
||||
return;
|
||||
}
|
||||
submitOrder();
|
||||
}
|
||||
|
||||
// 创建订单&跳转
|
||||
async function submitOrder() {
|
||||
const { code, data } = await OrderApi.createWorkerOrder({
|
||||
items: state.orderPayload.items,
|
||||
couponId: state.orderPayload.couponId,
|
||||
remark: state.orderPayload.remark,
|
||||
deliveryType: addressState.value.deliveryType,
|
||||
addressId: addressState.value.addressInfo.id, // 收件地址编号
|
||||
pickUpStoreId: addressState.value.pickUpInfo.id,//自提门店编号
|
||||
weixin: state.orderInfo.weixin,// 微信名称
|
||||
receiverMobile: addressState.value.receiverMobile,// 选择门店自提时,该字段为联系人手机
|
||||
pointStatus: state.pointStatus,
|
||||
combinationActivityId: state.orderPayload.combinationActivityId,
|
||||
combinationHeadId: state.orderPayload.combinationHeadId,
|
||||
seckillActivityId: state.orderPayload.seckillActivityId,
|
||||
workerClerkLevelId: state.orderPayload.workerClerkLevelId,
|
||||
sex: state.orderPayload.sex,
|
||||
blind: state.orderPayload.blind,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
// 更新购物车列表,如果来自购物车
|
||||
if (state.orderPayload.items[0].cartId > 0) {
|
||||
sheep.$store('cart').getList();
|
||||
}
|
||||
|
||||
// 跳转到支付页面
|
||||
sheep.$router.redirect('/pages/pay/worker/index', {
|
||||
id: data.payOrderId,
|
||||
});
|
||||
}
|
||||
|
||||
// 检查库存 & 计算订单价格
|
||||
async function getOrderInfo() {
|
||||
// 计算价格
|
||||
const { data, code } = await OrderApi.clerkOrder({
|
||||
items: state.orderPayload.items,
|
||||
couponId: state.orderPayload.couponId,
|
||||
deliveryType: addressState.value.deliveryType,
|
||||
addressId: addressState.value.addressInfo.id, // 收件地址编号
|
||||
pickUpStoreId: addressState.value.pickUpInfo.id,//自提门店编号
|
||||
weixin: state.orderInfo.weixin,// 微信名称
|
||||
receiverMobile: addressState.value.receiverMobile,// 选择门店自提时,该字段为联系人手机
|
||||
pointStatus: state.pointStatus,
|
||||
combinationActivityId: state.orderPayload.combinationActivityId,
|
||||
combinationHeadId: state.orderPayload.combinationHeadId,
|
||||
seckillActivityId: state.orderPayload.seckillActivityId,
|
||||
workerClerkLevelId: state.orderPayload.workerClerkLevelId,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.orderInfo = data;
|
||||
// 设置收货地址
|
||||
if (state.orderInfo.address) {
|
||||
addressState.value.addressInfo = state.orderInfo.address;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取可用优惠券
|
||||
async function getCoupons() {
|
||||
const { code, data } = await CouponApi.getMatchCouponList(
|
||||
state.orderInfo.price.payPrice,
|
||||
state.orderInfo.items.map((item) => item.spuId),
|
||||
state.orderPayload.items.map((item) => item.skuId),
|
||||
state.orderPayload.items.map((item) => item.categoryId),
|
||||
);
|
||||
if (code === 0) {
|
||||
state.couponInfo = data;
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
if (!options.data) {
|
||||
sheep.$helper.toast('参数不正确,请检查!');
|
||||
return;
|
||||
}
|
||||
state.orderPayload = JSON.parse(options.data);
|
||||
await getOrderInfo();
|
||||
await getCoupons();
|
||||
});
|
||||
|
||||
// 使用 watch 监听地址和配送方式的变化
|
||||
watch(addressState, async (newAddress, oldAddress) => {
|
||||
// 如果收货地址或配送方式有变化,则重新计算价格
|
||||
if (newAddress.addressInfo.id !== oldAddress.addressInfo.id || newAddress.deliveryType !== oldAddress.deliveryType) {
|
||||
await getOrderInfo();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep() {
|
||||
.uni-input-wrapper {
|
||||
width: 320rpx;
|
||||
}
|
||||
|
||||
.uni-easyinput__content-input {
|
||||
font-size: 28rpx;
|
||||
height: 72rpx;
|
||||
text-align: right !important;
|
||||
padding-right: 0 !important;
|
||||
|
||||
.uni-input-input {
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
font-size: 26rpx;
|
||||
height: 32rpx;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.uni-easyinput__content {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: right !important;
|
||||
}
|
||||
}
|
||||
|
||||
.score-img {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
|
||||
.order-item {
|
||||
height: 80rpx;
|
||||
|
||||
.item-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.item-value {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.text-disabled {
|
||||
color: #bbbbbb;
|
||||
}
|
||||
|
||||
.item-icon {
|
||||
color: $dark-9;
|
||||
}
|
||||
|
||||
.remark-input {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.item-placeholder {
|
||||
color: $dark-9;
|
||||
font-size: 26rpx;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.total-box-footer {
|
||||
height: 90rpx;
|
||||
|
||||
.total-num {
|
||||
color: #333333;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-box {
|
||||
height: 100rpx;
|
||||
|
||||
.submit-btn {
|
||||
width: 240rpx;
|
||||
height: 70rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
|
||||
.goto-pay-text {
|
||||
line-height: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
width: 240rpx;
|
||||
height: 80rpx;
|
||||
font-size: 26rpx;
|
||||
background-color: #e5e5e5;
|
||||
color: $dark-9;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.cicon-checkbox {
|
||||
font-size: 36rpx;
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
|
||||
.cicon-box {
|
||||
font-size: 36rpx;
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
599
pages/order/blind/detail.vue
Normal file
599
pages/order/blind/detail.vue
Normal file
@@ -0,0 +1,599 @@
|
||||
<!-- 订单详情 -->
|
||||
<template>
|
||||
<s-layout title="订单详情" class="index-wrap" navbar="inner">
|
||||
<!-- 订单状态 TODO -->
|
||||
<view
|
||||
class="state-box ss-flex-col ss-col-center ss-row-right"
|
||||
:style="[
|
||||
{
|
||||
marginTop: '-' + Number(statusBarHeight + 88 + 22) + 'rpx',
|
||||
paddingTop: Number(statusBarHeight + 88 + 22) + 'rpx',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<view class="ss-flex ss-m-t-32 ss-m-b-20">
|
||||
<image
|
||||
v-if="
|
||||
state.orderInfo.status_code == 'unpaid' ||
|
||||
state.orderInfo.status === 10 || // 待发货
|
||||
state.orderInfo.status_code == 'nocomment'
|
||||
"
|
||||
class="state-img"
|
||||
:src="sheep.$url.static('/static/img/shop/order/order_loading.png')"
|
||||
>
|
||||
</image>
|
||||
<image
|
||||
v-if="
|
||||
state.orderInfo.status_code == 'completed' ||
|
||||
state.orderInfo.status_code == 'refund_agree'
|
||||
"
|
||||
class="state-img"
|
||||
:src="sheep.$url.static('/static/img/shop/order/order_success.png')"
|
||||
>
|
||||
</image>
|
||||
<image
|
||||
v-if="state.orderInfo.status_code == 'cancel' || state.orderInfo.status_code == 'closed'"
|
||||
class="state-img"
|
||||
:src="sheep.$url.static('/static/img/shop/order/order_close.png')"
|
||||
>
|
||||
</image>
|
||||
<image
|
||||
v-if="state.orderInfo.status_code == 'noget'"
|
||||
class="state-img"
|
||||
:src="sheep.$url.static('/static/img/shop/order/order_express.png')"
|
||||
>
|
||||
</image>
|
||||
<view class="ss-font-30">{{ formatBlindOrderStatus(state.orderInfo) }}</view>
|
||||
</view>
|
||||
<view class="ss-font-26 ss-m-x-20 ss-m-b-70">
|
||||
{{ formatBlindOrderStatusDescription(state.orderInfo) }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 收货地址 -->
|
||||
<view class="order-address-box" v-if="state.orderInfo.receiverAreaId > 0">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="address-username">
|
||||
{{ state.orderInfo.receiverName }}
|
||||
</text>
|
||||
<text class="address-phone">{{ state.orderInfo.receiverMobile }}</text>
|
||||
</view>
|
||||
<view class="address-detail">
|
||||
{{ state.orderInfo.receiverAreaName }} {{ state.orderInfo.receiverDetailAddress }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="detail-goods"
|
||||
:style="[{ marginTop: state.orderInfo.receiverAreaId > 0 ? '0' : '-40rpx' }]"
|
||||
>
|
||||
<!-- 订单信 -->
|
||||
<view class="order-list" v-for="item in state.orderInfo.items" :key="item.goods_id">
|
||||
<view class="order-card">
|
||||
<s-goods-item
|
||||
@tap="onGoodsDetail(item.spuId)"
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price"
|
||||
:num="item.count"
|
||||
>
|
||||
<template #tool>
|
||||
<view class="ss-flex">
|
||||
<button
|
||||
class="ss-reset-button apply-btn"
|
||||
v-if="[10].includes(state.orderInfo.status) && item.afterSaleStatus === 0"
|
||||
@tap.stop="
|
||||
sheep.$router.go('/pages/order/blind/list', {
|
||||
type: 1,
|
||||
})
|
||||
"
|
||||
>
|
||||
立即抢单
|
||||
</button>
|
||||
<button
|
||||
class="ss-reset-button apply-btn"
|
||||
v-if="[20].includes(state.orderInfo.status) && item.afterSaleStatus === 0 && state.orderInfo.workerUserId == sheep.$store('user').userInfo.id"
|
||||
@tap.stop="
|
||||
sheep.$router.go('/pages/order/worker/aftersale/apply', {
|
||||
orderId: state.orderInfo.id,
|
||||
itemId: item.id,
|
||||
})
|
||||
"
|
||||
>
|
||||
取消接单
|
||||
</button>
|
||||
</view>
|
||||
</template>
|
||||
<template #priceSuffix>
|
||||
<button class="ss-reset-button tag-btn" v-if="item.status_text">
|
||||
{{ item.status_text }}
|
||||
</button>
|
||||
</template>
|
||||
</s-goods-item>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 自提核销 -->
|
||||
<PickUpVerify :order-info="state.orderInfo" :systemStore="systemStore" ref="pickUpVerifyRef"></PickUpVerify>
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<view class="notice-box">
|
||||
<view class="notice-box__content">
|
||||
<view class="notice-item--center">
|
||||
<view class="ss-flex ss-flex-1">
|
||||
<text class="title">订单编号:</text>
|
||||
<text class="detail">{{ state.orderInfo.no }}</text>
|
||||
</view>
|
||||
<button class="ss-reset-button copy-btn" @tap="onCopy">复制</button>
|
||||
</view>
|
||||
<view class="notice-item">
|
||||
<text class="title">下单时间:</text>
|
||||
<text class="detail">
|
||||
{{ sheep.$helper.timeFormat(state.orderInfo.createTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="notice-item" v-if="state.orderInfo.payTime">
|
||||
<text class="title">支付时间:</text>
|
||||
<text class="detail">
|
||||
{{ sheep.$helper.timeFormat(state.orderInfo.payTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="notice-item">
|
||||
<text class="title">支付方式:</text>
|
||||
<text class="detail">{{ state.orderInfo.payChannelName || '-' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 价格信息 -->
|
||||
<view class="order-price-box">
|
||||
<view class="notice-item ss-flex ss-row-between">
|
||||
<text class="title">订单总额</text>
|
||||
<view class="ss-flex">
|
||||
<text class="detail">¥{{ fen2yuan(state.orderInfo.totalPrice) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.couponPrice > 0">
|
||||
<text class="title">优惠劵金额</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.couponPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.pointPrice > 0">
|
||||
<text class="title">积分抵扣</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.pointPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.discountPrice > 0">
|
||||
<text class="title">活动优惠</text>
|
||||
<text class="detail">¥{{ fen2yuan(state.orderInfo.discountPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.vipPrice > 0">
|
||||
<text class="title">会员优惠</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.vipPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between">
|
||||
<text class="title">用户付款</text>
|
||||
<text class="detail">¥{{ fen2yuan(state.orderInfo.payPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between">
|
||||
<text class="title">佣金比例</text>
|
||||
<text class="detail">{{state.orderInfo.brokeragePercent}}%</text>
|
||||
</view>
|
||||
<view class="notice-item all-rpice-item ss-flex ss-m-t-20">
|
||||
<text class="title">{{ state.orderInfo.status == '30' ? '结算佣金' : '可得佣金' }}</text>
|
||||
<text class="detail all-price">¥{{ fen2yuan(state.orderInfo.brokeragePrice) }}</text>
|
||||
</view>
|
||||
<view
|
||||
class="notice-item all-rpice-item ss-flex ss-m-t-20"
|
||||
v-if="state.orderInfo.refundPrice > 0"
|
||||
>
|
||||
<text class="title">已退款</text>
|
||||
<text class="detail all-price">¥{{ fen2yuan(state.orderInfo.refundPrice) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import {
|
||||
fen2yuan,
|
||||
formatBlindOrderStatus,
|
||||
formatBlindOrderStatusDescription,
|
||||
handleOrderButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import DeliveryApi from '@/sheep/api/trade/delivery';
|
||||
import PickUpVerify from '@/pages/order/pickUpVerify.vue';
|
||||
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png');
|
||||
|
||||
const state = reactive({
|
||||
orderInfo: {},
|
||||
merchantTradeNo: '', // 商户订单号
|
||||
comeinType: '', // 进入订单详情的来源类型
|
||||
});
|
||||
|
||||
// ========== 门店自提(核销) ==========
|
||||
const systemStore = ref({}); // 门店信息
|
||||
|
||||
// 复制
|
||||
const onCopy = () => {
|
||||
sheep.$helper.copyText(state.orderInfo.no);
|
||||
};
|
||||
|
||||
// 去支付
|
||||
function onPay(payOrderId) {
|
||||
sheep.$router.go('/pages/pay/index', {
|
||||
id: payOrderId,
|
||||
});
|
||||
}
|
||||
|
||||
// 查看商品
|
||||
function onGoodsDetail(id) {
|
||||
if(id) {
|
||||
sheep.$router.go('/pages/clerk/detail/index', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 取消订单
|
||||
async function onCancel(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消订单吗?',
|
||||
success: async function(res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await OrderApi.cancelOrder(orderId);
|
||||
if (code === 0) {
|
||||
await getOrderDetail(orderId);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 查看物流
|
||||
async function onExpress(id) {
|
||||
sheep.$router.go('/pages/order/express/log', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 确认收货
|
||||
async function onConfirm(orderId, ignore = false) {
|
||||
// 需开启确认收货组件
|
||||
// todo: 芋艿:待接入微信
|
||||
// 1.怎么检测是否开启了发货组件功能?如果没有开启的话就不能在这里return出去
|
||||
// 2.如果开启了走mpConfirm方法,需要在App.vue的show方法中拿到确认收货结果
|
||||
let isOpenBusinessView = true;
|
||||
if (
|
||||
sheep.$platform.name === 'WechatMiniProgram' &&
|
||||
!isEmpty(state.orderInfo.wechat_extra_data) &&
|
||||
isOpenBusinessView &&
|
||||
!ignore
|
||||
) {
|
||||
mpConfirm(orderId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 正常的确认收货流程
|
||||
const { code } = await OrderApi.receiveOrder(orderId);
|
||||
if (code === 0) {
|
||||
await getOrderDetail(orderId);
|
||||
}
|
||||
}
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// 小程序确认收货组件
|
||||
function mpConfirm(orderId) {
|
||||
if (!wx.openBusinessView) {
|
||||
sheep.$helper.toast(`请升级微信版本`);
|
||||
return;
|
||||
}
|
||||
wx.openBusinessView({
|
||||
businessType: 'weappOrderConfirm',
|
||||
extraData: {
|
||||
merchant_trade_no: state.orderInfo.wechat_extra_data.merchant_trade_no,
|
||||
transaction_id: state.orderInfo.wechat_extra_data.transaction_id,
|
||||
},
|
||||
success(response) {
|
||||
console.log('success:', response);
|
||||
if (response.errMsg === 'openBusinessView:ok') {
|
||||
if (response.extraData.status === 'success') {
|
||||
onConfirm(orderId, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
fail(error) {
|
||||
console.log('error:', error);
|
||||
},
|
||||
complete(result) {
|
||||
console.log('result:', result);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// 评价
|
||||
function onComment(id) {
|
||||
sheep.$router.go('/pages/goods/comment/add', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
const pickUpVerifyRef = ref();
|
||||
|
||||
async function getOrderDetail(id) {
|
||||
// 对详情数据进行适配
|
||||
let res;
|
||||
if (state.comeinType === 'wechat') {
|
||||
// TODO 芋艿:微信场景下
|
||||
res = await OrderApi.getOrder(id, {
|
||||
merchant_trade_no: state.merchantTradeNo,
|
||||
});
|
||||
} else {
|
||||
res = await OrderApi.getOrder(id);
|
||||
}
|
||||
if (res.code === 0) {
|
||||
state.orderInfo = res.data;
|
||||
handleOrderButtons(state.orderInfo);
|
||||
// 配送方式:门店自提
|
||||
if (res.data.pickUpStoreId) {
|
||||
const { data } = await DeliveryApi.getDeliveryPickUpStore(res.data.pickUpStoreId);
|
||||
systemStore.value = data || {};
|
||||
}
|
||||
if (state.orderInfo.deliveryType === 2 && state.orderInfo.payStatus) {
|
||||
pickUpVerifyRef.value && pickUpVerifyRef.value.markCode(res.data.pickUpVerifyCode);
|
||||
}
|
||||
} else {
|
||||
sheep.$router.back();
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
let id = 0;
|
||||
if (options.id) {
|
||||
id = options.id;
|
||||
}
|
||||
// TODO 芋艿:下面两个变量,后续接入
|
||||
state.comeinType = options.comein_type;
|
||||
if (state.comeinType === 'wechat') {
|
||||
state.merchantTradeNo = options.merchant_trade_no;
|
||||
}
|
||||
await getOrderDetail(id);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.score-img {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
|
||||
.apply-btn {
|
||||
width: 140rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
border: 2rpx solid #dcdcdc;
|
||||
line-height: normal;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.state-box {
|
||||
color: rgba(#fff, 0.9);
|
||||
width: 100%;
|
||||
background: v-bind(headerBg) no-repeat,
|
||||
linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
background-size: 750rpx 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.state-img {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.order-address-box {
|
||||
background-color: #fff;
|
||||
border-radius: 10rpx;
|
||||
margin: -50rpx 20rpx 16rpx 20rpx;
|
||||
padding: 44rpx 34rpx 42rpx 20rpx;
|
||||
font-size: 30rpx;
|
||||
box-sizing: border-box;
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
|
||||
.address-username {
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.address-detail {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: rgba(153, 153, 153, 1);
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-goods {
|
||||
border-radius: 10rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
|
||||
.order-list {
|
||||
margin-bottom: 20rpx;
|
||||
background-color: #fff;
|
||||
|
||||
.order-card {
|
||||
padding: 20rpx 0;
|
||||
|
||||
.order-sku {
|
||||
font-size: 24rpx;
|
||||
|
||||
font-weight: 400;
|
||||
color: rgba(153, 153, 153, 1);
|
||||
width: 450rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.order-num {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tag-btn {
|
||||
margin-left: 16rpx;
|
||||
font-size: 24rpx;
|
||||
height: 36rpx;
|
||||
color: var(--ui-BG-Main);
|
||||
border: 2rpx solid var(--ui-BG-Main);
|
||||
border-radius: 14rpx;
|
||||
padding: 0 4rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 订单信息。
|
||||
.notice-box {
|
||||
background: #fff;
|
||||
border-radius: 10rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
|
||||
.notice-box__head {
|
||||
font-size: 30rpx;
|
||||
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
line-height: 80rpx;
|
||||
border-bottom: 1rpx solid #dfdfdf;
|
||||
padding: 0 25rpx;
|
||||
}
|
||||
|
||||
.notice-box__content {
|
||||
padding: 20rpx;
|
||||
|
||||
.self-pickup-box {
|
||||
width: 100%;
|
||||
|
||||
.self-pickup--img {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin: 40rpx 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.notice-item,
|
||||
.notice-item--center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: normal;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.detail {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copy-btn {
|
||||
width: 100rpx;
|
||||
line-height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
padding: 0;
|
||||
background: rgba(238, 238, 238, 1);
|
||||
font-size: 22rpx;
|
||||
font-weight: 400;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
|
||||
// 订单价格信息
|
||||
.order-price-box {
|
||||
background-color: #fff;
|
||||
border-radius: 10rpx;
|
||||
padding: 20rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
|
||||
.notice-item {
|
||||
line-height: 70rpx;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.detail {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
}
|
||||
|
||||
.all-rpice-item {
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
.title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.all-price {
|
||||
font-size: 26rpx;
|
||||
font-family: OPPOSANS;
|
||||
line-height: normal;
|
||||
color: $red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 底部
|
||||
.footer-box {
|
||||
height: 100rpx;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border-radius: 10rpx;
|
||||
padding-right: 20rpx;
|
||||
|
||||
.cancel-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #eeeeee;
|
||||
border-radius: 30rpx;
|
||||
margin-right: 20rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.pay-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
font-size: 26rpx;
|
||||
border-radius: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
45
pages/order/blind/list.vue
Normal file
45
pages/order/blind/list.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<view class="page-app theme-light main-green font-1">
|
||||
<layout ref="order"></layout>
|
||||
|
||||
<s-menu-tools />
|
||||
<s-auth-modal />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import layout from '@/pages/order/blind/components/layout.vue';
|
||||
export default {
|
||||
components: {
|
||||
layout,
|
||||
},
|
||||
props: {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentIndex: 0,
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
if (options.type) {
|
||||
this.currentIndex = options.type;
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.$refs.order.tabChange(this.currentIndex);
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-app {
|
||||
background-color: #fafafa;
|
||||
padding-bottom: 140rpx;
|
||||
height: calc(100vh);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
</style>
|
468
pages/order/confirm.vue
Normal file
468
pages/order/confirm.vue
Normal file
@@ -0,0 +1,468 @@
|
||||
<template>
|
||||
<s-layout title="确认订单">
|
||||
<!-- 头部地址选择【配送地址】【自提地址】 -->
|
||||
<AddressSelection v-model="addressState" />
|
||||
|
||||
<!-- 商品信息 -->
|
||||
<view class="order-card-box ss-m-b-14">
|
||||
<s-goods-item
|
||||
v-for="item in state.orderInfo.items"
|
||||
:key="item.skuId"
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price"
|
||||
:num="item.count"
|
||||
marginBottom="10"
|
||||
/>
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between ss-p-x-20 bg-white ss-r-10">
|
||||
<view class="item-title">订单备注</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<uni-easyinput
|
||||
maxlength="20"
|
||||
placeholder="建议留言前先与商家沟通"
|
||||
v-model="state.orderPayload.remark"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 价格信息 -->
|
||||
<view class="bg-white total-card-box ss-p-20 ss-m-b-14 ss-r-10">
|
||||
<view class="total-box-content border-bottom">
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between">
|
||||
<view class="item-title">商品金额</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="item-value ss-m-r-24">
|
||||
¥{{ fen2yuan(state.orderInfo.price.totalPrice) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.type === 0"
|
||||
>
|
||||
<view class="item-title">积分抵扣</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
{{ state.pointStatus ? '剩余积分' : '当前积分' }}
|
||||
<image
|
||||
:src="sheep.$url.static('/static/img/shop/goods/score1.svg')"
|
||||
class="score-img"
|
||||
/>
|
||||
<text class="item-value ss-m-r-24">
|
||||
{{ state.pointStatus ? state.orderInfo.totalPoint - state.orderInfo.usePoint : (state.orderInfo.totalPoint || 0) }}
|
||||
</text>
|
||||
<checkbox-group @change="changeIntegral">
|
||||
<checkbox :checked='state.pointStatus' :disabled="!state.orderInfo.totalPoint || state.orderInfo.totalPoint <= 0" />
|
||||
</checkbox-group>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 快递配置时,信息的展示 -->
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between" v-if='addressState.deliveryType === 1'>
|
||||
<view class="item-title">运费</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="item-value ss-m-r-24" v-if="state.orderInfo.price.deliveryPrice > 0">
|
||||
+¥{{ fen2yuan(state.orderInfo.price.deliveryPrice) }}
|
||||
</text>
|
||||
<view class='item-value ss-m-r-24' v-else>免运费</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 门店自提时,需要填写姓名和手机号 -->
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between" v-if='addressState.deliveryType === 2'>
|
||||
<view class="item-title">联系人</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<uni-easyinput
|
||||
maxlength="20"
|
||||
placeholder="请填写您的联系姓名"
|
||||
v-model="addressState.receiverName"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between" v-if='addressState.deliveryType === 2'>
|
||||
<view class="item-title">联系电话</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<uni-easyinput
|
||||
maxlength="20"
|
||||
placeholder="请填写您的联系电话"
|
||||
v-model="addressState.receiverMobile"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 优惠劵:只有 type = 0 普通订单(非拼团、秒杀、砍价),才可以使用优惠劵 -->
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.type === 0"
|
||||
>
|
||||
<view class="item-title">优惠券</view>
|
||||
<view class="ss-flex ss-col-center" @tap="state.showCoupon = true">
|
||||
<text class="item-value text-red" v-if="state.orderPayload.couponId > 0">
|
||||
-¥{{ fen2yuan(state.orderInfo.price.couponPrice) }}
|
||||
</text>
|
||||
<text
|
||||
class="item-value"
|
||||
:class="state.couponInfo.length > 0 ? 'text-red' : 'text-disabled'"
|
||||
v-else
|
||||
>
|
||||
{{
|
||||
state.couponInfo.length > 0 ? state.couponInfo.length + ' 张可用' : '暂无可用优惠券'
|
||||
}}
|
||||
</text>
|
||||
<text class="_icon-forward item-icon" />
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.price.discountPrice > 0"
|
||||
>
|
||||
<view class="item-title">活动优惠</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<!-- @tap="state.showDiscount = true" TODO puhui999:【折扣】后续要把优惠信息打进去 -->
|
||||
<text class="item-value text-red">
|
||||
-¥{{ fen2yuan(state.orderInfo.price.discountPrice) }}
|
||||
</text>
|
||||
<text class="_icon-forward item-icon" />
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.price.vipPrice > 0"
|
||||
>
|
||||
<view class="item-title">会员优惠</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="item-value text-red">
|
||||
-¥{{ fen2yuan(state.orderInfo.price.vipPrice) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="total-box-footer ss-font-28 ss-flex ss-row-right ss-col-center ss-m-r-28">
|
||||
<view class="total-num ss-m-r-20">
|
||||
共{{ state.orderInfo.items.reduce((acc, item) => acc + item.count, 0) }}件
|
||||
</view>
|
||||
<view>合计:</view>
|
||||
<view class="total-num text-red"> ¥{{ fen2yuan(state.orderInfo.price.payPrice) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 选择优惠券弹框 -->
|
||||
<s-coupon-select
|
||||
v-model="state.couponInfo"
|
||||
:show="state.showCoupon"
|
||||
@confirm="onSelectCoupon"
|
||||
@close="state.showCoupon = false"
|
||||
/>
|
||||
|
||||
<!-- 满额折扣弹框 TODO @puhui999:【折扣】后续要把优惠信息打进去 -->
|
||||
<s-discount-list
|
||||
v-model="state.orderInfo"
|
||||
:show="state.showDiscount"
|
||||
@close="state.showDiscount = false"
|
||||
/>
|
||||
|
||||
<!-- 底部 -->
|
||||
<su-fixed bottom :opacity="false" bg="bg-white" placeholder :noFixed="false" :index="200">
|
||||
<view class="footer-box border-top ss-flex ss-row-between ss-p-x-20 ss-col-center">
|
||||
<view class="total-box-footer ss-flex ss-col-center">
|
||||
<view class="total-num ss-font-30 text-red">
|
||||
¥{{ fen2yuan(state.orderInfo.price.payPrice) }}
|
||||
</view>
|
||||
</view>
|
||||
<button
|
||||
class="ss-reset-button ui-BG-Main-Gradient ss-r-40 submit-btn ui-Shadow-Main"
|
||||
@tap="onConfirm"
|
||||
>
|
||||
提交订单
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import AddressSelection from '@/pages/order/addressSelection.vue';
|
||||
import sheep from '@/sheep';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
|
||||
const state = reactive({
|
||||
orderPayload: {},
|
||||
orderInfo: {
|
||||
items: [], // 商品项列表
|
||||
price: {}, // 价格信息
|
||||
},
|
||||
showCoupon: false, // 是否展示优惠劵
|
||||
couponInfo: [], // 优惠劵列表
|
||||
showDiscount: false, // 是否展示营销活动
|
||||
// ========== 积分 ==========
|
||||
pointStatus: false, //是否使用积分
|
||||
});
|
||||
|
||||
const addressState = ref({
|
||||
addressInfo: {}, // 选择的收货地址
|
||||
deliveryType: 1, // 收货方式:1-快递配送,2-门店自提
|
||||
isPickUp: true, // 门店自提是否开启 TODO puhui999: 默认开启,看看后端有开关的话接入
|
||||
pickUpInfo: {}, // 选择的自提门店信息
|
||||
receiverName: '', // 收件人名称
|
||||
receiverMobile: '', // 收件人手机
|
||||
});
|
||||
|
||||
// ========== 积分 ==========
|
||||
/**
|
||||
* 使用积分抵扣
|
||||
*/
|
||||
const changeIntegral = async () => {
|
||||
state.pointStatus = !state.pointStatus;
|
||||
await getOrderInfo();
|
||||
};
|
||||
|
||||
// 选择优惠券
|
||||
async function onSelectCoupon(couponId) {
|
||||
state.orderPayload.couponId = couponId;
|
||||
await getOrderInfo();
|
||||
state.showCoupon = false;
|
||||
}
|
||||
|
||||
// 提交订单
|
||||
function onConfirm() {
|
||||
if (addressState.value.deliveryType === 1 && !addressState.value.addressInfo.id) {
|
||||
sheep.$helper.toast('请选择收货地址');
|
||||
return;
|
||||
}
|
||||
if (addressState.value.deliveryType === 2) {
|
||||
if (!addressState.value.pickUpInfo.id) {
|
||||
sheep.$helper.toast('请选择自提门店地址');
|
||||
return;
|
||||
}
|
||||
if (addressState.value.receiverName === '' || addressState.value.receiverMobile === '') {
|
||||
sheep.$helper.toast('请填写联系人或联系人电话');
|
||||
return;
|
||||
}
|
||||
if (!/^[\u4e00-\u9fa5\w]{2,16}$/.test(addressState.value.receiverName)) {
|
||||
sheep.$helper.toast('请填写您的真实姓名');
|
||||
return;
|
||||
}
|
||||
if (!/^1(3|4|5|7|8|9|6)\d{9}$/.test(addressState.value.receiverMobile)) {
|
||||
sheep.$helper.toast('请填写正确的手机号');
|
||||
return;
|
||||
}
|
||||
}
|
||||
submitOrder();
|
||||
}
|
||||
|
||||
// 创建订单&跳转
|
||||
async function submitOrder() {
|
||||
const { code, data } = await OrderApi.createOrder({
|
||||
items: state.orderPayload.items,
|
||||
couponId: state.orderPayload.couponId,
|
||||
remark: state.orderPayload.remark,
|
||||
deliveryType: addressState.value.deliveryType,
|
||||
addressId: addressState.value.addressInfo.id, // 收件地址编号
|
||||
pickUpStoreId: addressState.value.pickUpInfo.id,//自提门店编号
|
||||
receiverName: addressState.value.receiverName,// 选择门店自提时,该字段为联系人名
|
||||
receiverMobile: addressState.value.receiverMobile,// 选择门店自提时,该字段为联系人手机
|
||||
pointStatus: state.pointStatus,
|
||||
combinationActivityId: state.orderPayload.combinationActivityId,
|
||||
combinationHeadId: state.orderPayload.combinationHeadId,
|
||||
seckillActivityId: state.orderPayload.seckillActivityId,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
// 更新购物车列表,如果来自购物车
|
||||
if (state.orderPayload.items[0].cartId > 0) {
|
||||
sheep.$store('cart').getList();
|
||||
}
|
||||
|
||||
// 跳转到支付页面
|
||||
sheep.$router.redirect('/pages/pay/index', {
|
||||
id: data.payOrderId,
|
||||
});
|
||||
}
|
||||
|
||||
// 检查库存 & 计算订单价格
|
||||
async function getOrderInfo() {
|
||||
// 计算价格
|
||||
const { data, code } = await OrderApi.settlementOrder({
|
||||
items: state.orderPayload.items,
|
||||
couponId: state.orderPayload.couponId,
|
||||
deliveryType: addressState.value.deliveryType,
|
||||
addressId: addressState.value.addressInfo.id, // 收件地址编号
|
||||
pickUpStoreId: addressState.value.pickUpInfo.id,//自提门店编号
|
||||
receiverName: addressState.value.receiverName,// 选择门店自提时,该字段为联系人名
|
||||
receiverMobile: addressState.value.receiverMobile,// 选择门店自提时,该字段为联系人手机
|
||||
pointStatus: state.pointStatus,
|
||||
combinationActivityId: state.orderPayload.combinationActivityId,
|
||||
combinationHeadId: state.orderPayload.combinationHeadId,
|
||||
seckillActivityId: state.orderPayload.seckillActivityId,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.orderInfo = data;
|
||||
// 设置收货地址
|
||||
if (state.orderInfo.address) {
|
||||
addressState.value.addressInfo = state.orderInfo.address;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取可用优惠券
|
||||
async function getCoupons() {
|
||||
const { code, data } = await CouponApi.getMatchCouponList(
|
||||
state.orderInfo.price.payPrice,
|
||||
state.orderInfo.items.map((item) => item.spuId),
|
||||
state.orderPayload.items.map((item) => item.skuId),
|
||||
state.orderPayload.items.map((item) => item.categoryId),
|
||||
);
|
||||
if (code === 0) {
|
||||
state.couponInfo = data;
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
if (!options.data) {
|
||||
sheep.$helper.toast('参数不正确,请检查!');
|
||||
return;
|
||||
}
|
||||
state.orderPayload = JSON.parse(options.data);
|
||||
await getOrderInfo();
|
||||
await getCoupons();
|
||||
});
|
||||
|
||||
// 使用 watch 监听地址和配送方式的变化
|
||||
watch(addressState, async (newAddress, oldAddress) => {
|
||||
// 如果收货地址或配送方式有变化,则重新计算价格
|
||||
if (newAddress.addressInfo.id !== oldAddress.addressInfo.id || newAddress.deliveryType !== oldAddress.deliveryType) {
|
||||
await getOrderInfo();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep() {
|
||||
.uni-input-wrapper {
|
||||
width: 320rpx;
|
||||
}
|
||||
|
||||
.uni-easyinput__content-input {
|
||||
font-size: 28rpx;
|
||||
height: 72rpx;
|
||||
text-align: right !important;
|
||||
padding-right: 0 !important;
|
||||
|
||||
.uni-input-input {
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
font-size: 26rpx;
|
||||
height: 32rpx;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.uni-easyinput__content {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: right !important;
|
||||
}
|
||||
}
|
||||
|
||||
.score-img {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
|
||||
.order-item {
|
||||
height: 80rpx;
|
||||
|
||||
.item-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.item-value {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.text-disabled {
|
||||
color: #bbbbbb;
|
||||
}
|
||||
|
||||
.item-icon {
|
||||
color: $dark-9;
|
||||
}
|
||||
|
||||
.remark-input {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.item-placeholder {
|
||||
color: $dark-9;
|
||||
font-size: 26rpx;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.total-box-footer {
|
||||
height: 90rpx;
|
||||
|
||||
.total-num {
|
||||
color: #333333;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-box {
|
||||
height: 100rpx;
|
||||
|
||||
.submit-btn {
|
||||
width: 240rpx;
|
||||
height: 70rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
|
||||
.goto-pay-text {
|
||||
line-height: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
width: 240rpx;
|
||||
height: 80rpx;
|
||||
font-size: 26rpx;
|
||||
background-color: #e5e5e5;
|
||||
color: $dark-9;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.cicon-checkbox {
|
||||
font-size: 36rpx;
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
|
||||
.cicon-box {
|
||||
font-size: 36rpx;
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
655
pages/order/detail.vue
Normal file
655
pages/order/detail.vue
Normal file
@@ -0,0 +1,655 @@
|
||||
<!-- 订单详情 -->
|
||||
<template>
|
||||
<s-layout title="订单详情" class="index-wrap" navbar="inner">
|
||||
<!-- 订单状态 TODO -->
|
||||
<view
|
||||
class="state-box ss-flex-col ss-col-center ss-row-right"
|
||||
:style="[
|
||||
{
|
||||
marginTop: '-' + Number(statusBarHeight + 88) + 'rpx',
|
||||
paddingTop: Number(statusBarHeight + 88) + 'rpx',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<view class="ss-flex ss-m-t-32 ss-m-b-20">
|
||||
<image
|
||||
v-if="
|
||||
state.orderInfo.status_code == 'unpaid' ||
|
||||
state.orderInfo.status === 10 || // 待发货
|
||||
state.orderInfo.status_code == 'nocomment'
|
||||
"
|
||||
class="state-img"
|
||||
:src="sheep.$url.static('/static/img/shop/order/order_loading.png')"
|
||||
>
|
||||
</image>
|
||||
<image
|
||||
v-if="
|
||||
state.orderInfo.status_code == 'completed' ||
|
||||
state.orderInfo.status_code == 'refund_agree'
|
||||
"
|
||||
class="state-img"
|
||||
:src="sheep.$url.static('/static/img/shop/order/order_success.png')"
|
||||
>
|
||||
</image>
|
||||
<image
|
||||
v-if="state.orderInfo.status_code == 'cancel' || state.orderInfo.status_code == 'closed'"
|
||||
class="state-img"
|
||||
:src="sheep.$url.static('/static/img/shop/order/order_close.png')"
|
||||
>
|
||||
</image>
|
||||
<image
|
||||
v-if="state.orderInfo.status_code == 'noget'"
|
||||
class="state-img"
|
||||
:src="sheep.$url.static('/static/img/shop/order/order_express.png')"
|
||||
>
|
||||
</image>
|
||||
<view class="ss-font-30">{{ formatOrderStatus(state.orderInfo) }}</view>
|
||||
</view>
|
||||
<view class="ss-font-26 ss-m-x-20 ss-m-b-70">
|
||||
{{ formatOrderStatusDescription(state.orderInfo) }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 收货地址 -->
|
||||
<view class="order-address-box" v-if="state.orderInfo.receiverAreaId > 0">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="address-username">
|
||||
{{ state.orderInfo.receiverName }}
|
||||
</text>
|
||||
<text class="address-phone">{{ state.orderInfo.receiverMobile }}</text>
|
||||
</view>
|
||||
<view class="address-detail">
|
||||
{{ state.orderInfo.receiverAreaName }} {{ state.orderInfo.receiverDetailAddress }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="detail-goods"
|
||||
:style="[{ marginTop: state.orderInfo.receiverAreaId > 0 ? '0' : '-40rpx' }]"
|
||||
>
|
||||
<!-- 订单信 -->
|
||||
<view class="order-list" v-for="item in state.orderInfo.items" :key="item.goods_id">
|
||||
<view class="order-card">
|
||||
<s-goods-item
|
||||
@tap="onGoodsDetail(item.spuId)"
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price"
|
||||
:num="item.count"
|
||||
>
|
||||
<template #tool>
|
||||
<view class="ss-flex">
|
||||
<button
|
||||
class="ss-reset-button apply-btn"
|
||||
v-if="[10, 20, 30].includes(state.orderInfo.status) && item.afterSaleStatus === 0"
|
||||
@tap.stop="
|
||||
sheep.$router.go('/pages/order/aftersale/apply', {
|
||||
orderId: state.orderInfo.id,
|
||||
itemId: item.id,
|
||||
})
|
||||
"
|
||||
>
|
||||
申请售后
|
||||
</button>
|
||||
<button
|
||||
class="ss-reset-button apply-btn"
|
||||
v-if="item.afterSaleStatus === 10"
|
||||
@tap.stop="
|
||||
sheep.$router.go('/pages/order/aftersale/detail', {
|
||||
id: item.afterSaleId,
|
||||
})
|
||||
"
|
||||
>
|
||||
退款中
|
||||
</button>
|
||||
<button
|
||||
class="ss-reset-button apply-btn"
|
||||
v-if="item.afterSaleStatus === 20"
|
||||
@tap.stop="
|
||||
sheep.$router.go('/pages/order/aftersale/detail', {
|
||||
id: item.afterSaleId,
|
||||
})
|
||||
"
|
||||
>
|
||||
退款成功
|
||||
</button>
|
||||
</view>
|
||||
</template>
|
||||
<template #priceSuffix>
|
||||
<button class="ss-reset-button tag-btn" v-if="item.status_text">
|
||||
{{ item.status_text }}
|
||||
</button>
|
||||
</template>
|
||||
</s-goods-item>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 自提核销 -->
|
||||
<PickUpVerify :order-info="state.orderInfo" :systemStore="systemStore" ref="pickUpVerifyRef"></PickUpVerify>
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<view class="notice-box">
|
||||
<view class="notice-box__content">
|
||||
<view class="notice-item--center">
|
||||
<view class="ss-flex ss-flex-1">
|
||||
<text class="title">订单编号:</text>
|
||||
<text class="detail">{{ state.orderInfo.no }}</text>
|
||||
</view>
|
||||
<button class="ss-reset-button copy-btn" @tap="onCopy">复制</button>
|
||||
</view>
|
||||
<view class="notice-item">
|
||||
<text class="title">下单时间:</text>
|
||||
<text class="detail">
|
||||
{{ sheep.$helper.timeFormat(state.orderInfo.createTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="notice-item" v-if="state.orderInfo.payTime">
|
||||
<text class="title">支付时间:</text>
|
||||
<text class="detail">
|
||||
{{ sheep.$helper.timeFormat(state.orderInfo.payTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="notice-item">
|
||||
<text class="title">支付方式:</text>
|
||||
<text class="detail">{{ state.orderInfo.payChannelName || '-' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 价格信息 -->
|
||||
<view class="order-price-box">
|
||||
<view class="notice-item ss-flex ss-row-between">
|
||||
<text class="title">商品总额</text>
|
||||
<view class="ss-flex">
|
||||
<text class="detail">¥{{ fen2yuan(state.orderInfo.totalPrice) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between">
|
||||
<text class="title">运费</text>
|
||||
<text class="detail">¥{{ fen2yuan(state.orderInfo.deliveryPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.couponPrice > 0">
|
||||
<text class="title">优惠劵金额</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.couponPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.pointPrice > 0">
|
||||
<text class="title">积分抵扣</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.pointPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.discountPrice > 0">
|
||||
<text class="title">活动优惠</text>
|
||||
<text class="detail">¥{{ fen2yuan(state.orderInfo.discountPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.vipPrice > 0">
|
||||
<text class="title">会员优惠</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.vipPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item all-rpice-item ss-flex ss-m-t-20">
|
||||
<text class="title">{{ state.orderInfo.payStatus ? '已付款' : '需付款' }}</text>
|
||||
<text class="detail all-price">¥{{ fen2yuan(state.orderInfo.payPrice) }}</text>
|
||||
</view>
|
||||
<view
|
||||
class="notice-item all-rpice-item ss-flex ss-m-t-20"
|
||||
v-if="state.orderInfo.refundPrice > 0"
|
||||
>
|
||||
<text class="title">已退款</text>
|
||||
<text class="detail all-price">¥{{ fen2yuan(state.orderInfo.refundPrice) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<!-- TODO: 查看物流、等待成团、评价完后返回页面没刷新页面 -->
|
||||
<su-fixed bottom placeholder bg="bg-white" v-if="state.orderInfo.buttons?.length">
|
||||
<view class="footer-box ss-flex ss-col-center ss-row-right">
|
||||
<button
|
||||
class="ss-reset-button cancel-btn"
|
||||
v-if="state.orderInfo.buttons?.includes('cancel')"
|
||||
@tap="onCancel(state.orderInfo.id)"
|
||||
>
|
||||
取消订单
|
||||
</button>
|
||||
<button
|
||||
class="ss-reset-button pay-btn ui-BG-Main-Gradient"
|
||||
v-if="state.orderInfo.buttons?.includes('pay')"
|
||||
@tap="onPay(state.orderInfo.payOrderId)"
|
||||
>
|
||||
继续支付
|
||||
</button>
|
||||
<button
|
||||
class="ss-reset-button cancel-btn"
|
||||
v-if="state.orderInfo.buttons?.includes('combination')"
|
||||
@tap="
|
||||
sheep.$router.go('/pages/activity/groupon/detail', {
|
||||
id: state.orderInfo.combinationRecordId,
|
||||
})
|
||||
"
|
||||
>
|
||||
拼团详情
|
||||
</button>
|
||||
<button
|
||||
class="ss-reset-button cancel-btn"
|
||||
v-if="state.orderInfo.buttons?.includes('express')"
|
||||
@tap="onExpress(state.orderInfo.id)"
|
||||
>
|
||||
查看物流
|
||||
</button>
|
||||
<button
|
||||
class="ss-reset-button cancel-btn"
|
||||
v-if="state.orderInfo.buttons?.includes('confirm')"
|
||||
@tap="onConfirm(state.orderInfo.id)"
|
||||
>
|
||||
确认收货
|
||||
</button>
|
||||
<button
|
||||
class="ss-reset-button cancel-btn"
|
||||
v-if="state.orderInfo.buttons?.includes('comment')"
|
||||
@tap="onComment(state.orderInfo.id)"
|
||||
>
|
||||
评价
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import {
|
||||
fen2yuan,
|
||||
formatOrderStatus,
|
||||
formatOrderStatusDescription,
|
||||
handleOrderButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import DeliveryApi from '@/sheep/api/trade/delivery';
|
||||
import PickUpVerify from '@/pages/order/pickUpVerify.vue';
|
||||
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png');
|
||||
|
||||
const state = reactive({
|
||||
orderInfo: {},
|
||||
merchantTradeNo: '', // 商户订单号
|
||||
comeinType: '', // 进入订单详情的来源类型
|
||||
});
|
||||
|
||||
// ========== 门店自提(核销) ==========
|
||||
const systemStore = ref({}); // 门店信息
|
||||
|
||||
// 复制
|
||||
const onCopy = () => {
|
||||
sheep.$helper.copyText(state.orderInfo.no);
|
||||
};
|
||||
|
||||
// 去支付
|
||||
function onPay(payOrderId) {
|
||||
sheep.$router.go('/pages/pay/index', {
|
||||
id: payOrderId,
|
||||
});
|
||||
}
|
||||
|
||||
// 查看商品
|
||||
function onGoodsDetail(id) {
|
||||
sheep.$router.go('/pages/goods/index', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 取消订单
|
||||
async function onCancel(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消订单吗?',
|
||||
success: async function(res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await OrderApi.cancelOrder(orderId);
|
||||
if (code === 0) {
|
||||
await getOrderDetail(orderId);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 查看物流
|
||||
async function onExpress(id) {
|
||||
sheep.$router.go('/pages/order/express/log', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 确认收货
|
||||
async function onConfirm(orderId, ignore = false) {
|
||||
// 需开启确认收货组件
|
||||
// todo: 芋艿:待接入微信
|
||||
// 1.怎么检测是否开启了发货组件功能?如果没有开启的话就不能在这里return出去
|
||||
// 2.如果开启了走mpConfirm方法,需要在App.vue的show方法中拿到确认收货结果
|
||||
let isOpenBusinessView = true;
|
||||
if (
|
||||
sheep.$platform.name === 'WechatMiniProgram' &&
|
||||
!isEmpty(state.orderInfo.wechat_extra_data) &&
|
||||
isOpenBusinessView &&
|
||||
!ignore
|
||||
) {
|
||||
mpConfirm(orderId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 正常的确认收货流程
|
||||
const { code } = await OrderApi.receiveOrder(orderId);
|
||||
if (code === 0) {
|
||||
await getOrderDetail(orderId);
|
||||
}
|
||||
}
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// 小程序确认收货组件
|
||||
function mpConfirm(orderId) {
|
||||
if (!wx.openBusinessView) {
|
||||
sheep.$helper.toast(`请升级微信版本`);
|
||||
return;
|
||||
}
|
||||
wx.openBusinessView({
|
||||
businessType: 'weappOrderConfirm',
|
||||
extraData: {
|
||||
merchant_trade_no: state.orderInfo.wechat_extra_data.merchant_trade_no,
|
||||
transaction_id: state.orderInfo.wechat_extra_data.transaction_id,
|
||||
},
|
||||
success(response) {
|
||||
console.log('success:', response);
|
||||
if (response.errMsg === 'openBusinessView:ok') {
|
||||
if (response.extraData.status === 'success') {
|
||||
onConfirm(orderId, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
fail(error) {
|
||||
console.log('error:', error);
|
||||
},
|
||||
complete(result) {
|
||||
console.log('result:', result);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// 评价
|
||||
function onComment(id) {
|
||||
sheep.$router.go('/pages/goods/comment/add', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
const pickUpVerifyRef = ref();
|
||||
|
||||
async function getOrderDetail(id) {
|
||||
// 对详情数据进行适配
|
||||
let res;
|
||||
if (state.comeinType === 'wechat') {
|
||||
// TODO 芋艿:微信场景下
|
||||
res = await OrderApi.getOrder(id, {
|
||||
merchant_trade_no: state.merchantTradeNo,
|
||||
});
|
||||
} else {
|
||||
res = await OrderApi.getOrder(id);
|
||||
}
|
||||
if (res.code === 0) {
|
||||
state.orderInfo = res.data;
|
||||
handleOrderButtons(state.orderInfo);
|
||||
// 配送方式:门店自提
|
||||
if (res.data.pickUpStoreId) {
|
||||
const { data } = await DeliveryApi.getDeliveryPickUpStore(res.data.pickUpStoreId);
|
||||
systemStore.value = data || {};
|
||||
}
|
||||
if (state.orderInfo.deliveryType === 2 && state.orderInfo.payStatus) {
|
||||
pickUpVerifyRef.value && pickUpVerifyRef.value.markCode(res.data.pickUpVerifyCode);
|
||||
}
|
||||
} else {
|
||||
sheep.$router.back();
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
let id = 0;
|
||||
if (options.id) {
|
||||
id = options.id;
|
||||
}
|
||||
// TODO 芋艿:下面两个变量,后续接入
|
||||
state.comeinType = options.comein_type;
|
||||
if (state.comeinType === 'wechat') {
|
||||
state.merchantTradeNo = options.merchant_trade_no;
|
||||
}
|
||||
await getOrderDetail(id);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.score-img {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
|
||||
.apply-btn {
|
||||
width: 140rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
border: 2rpx solid #dcdcdc;
|
||||
line-height: normal;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.state-box {
|
||||
color: rgba(#fff, 0.9);
|
||||
width: 100%;
|
||||
background: v-bind(headerBg) no-repeat,
|
||||
linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
background-size: 750rpx 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.state-img {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.order-address-box {
|
||||
background-color: #fff;
|
||||
border-radius: 10rpx;
|
||||
margin: -50rpx 20rpx 16rpx 20rpx;
|
||||
padding: 44rpx 34rpx 42rpx 20rpx;
|
||||
font-size: 30rpx;
|
||||
box-sizing: border-box;
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
|
||||
.address-username {
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.address-detail {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: rgba(153, 153, 153, 1);
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-goods {
|
||||
border-radius: 10rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
|
||||
.order-list {
|
||||
margin-bottom: 20rpx;
|
||||
background-color: #fff;
|
||||
|
||||
.order-card {
|
||||
padding: 20rpx 0;
|
||||
|
||||
.order-sku {
|
||||
font-size: 24rpx;
|
||||
|
||||
font-weight: 400;
|
||||
color: rgba(153, 153, 153, 1);
|
||||
width: 450rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.order-num {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tag-btn {
|
||||
margin-left: 16rpx;
|
||||
font-size: 24rpx;
|
||||
height: 36rpx;
|
||||
color: var(--ui-BG-Main);
|
||||
border: 2rpx solid var(--ui-BG-Main);
|
||||
border-radius: 14rpx;
|
||||
padding: 0 4rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 订单信息。
|
||||
.notice-box {
|
||||
background: #fff;
|
||||
border-radius: 10rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
|
||||
.notice-box__head {
|
||||
font-size: 30rpx;
|
||||
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
line-height: 80rpx;
|
||||
border-bottom: 1rpx solid #dfdfdf;
|
||||
padding: 0 25rpx;
|
||||
}
|
||||
|
||||
.notice-box__content {
|
||||
padding: 20rpx;
|
||||
|
||||
.self-pickup-box {
|
||||
width: 100%;
|
||||
|
||||
.self-pickup--img {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin: 40rpx 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.notice-item,
|
||||
.notice-item--center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: normal;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.detail {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copy-btn {
|
||||
width: 100rpx;
|
||||
line-height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
padding: 0;
|
||||
background: rgba(238, 238, 238, 1);
|
||||
font-size: 22rpx;
|
||||
font-weight: 400;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
|
||||
// 订单价格信息
|
||||
.order-price-box {
|
||||
background-color: #fff;
|
||||
border-radius: 10rpx;
|
||||
padding: 20rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
|
||||
.notice-item {
|
||||
line-height: 70rpx;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.detail {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
}
|
||||
|
||||
.all-rpice-item {
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
.title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.all-price {
|
||||
font-size: 26rpx;
|
||||
font-family: OPPOSANS;
|
||||
line-height: normal;
|
||||
color: $red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 底部
|
||||
.footer-box {
|
||||
height: 100rpx;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border-radius: 10rpx;
|
||||
padding-right: 20rpx;
|
||||
|
||||
.cancel-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #eeeeee;
|
||||
border-radius: 30rpx;
|
||||
margin-right: 20rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.pay-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
font-size: 26rpx;
|
||||
border-radius: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
162
pages/order/express/log.vue
Normal file
162
pages/order/express/log.vue
Normal file
@@ -0,0 +1,162 @@
|
||||
<!-- 物流追踪 -->
|
||||
<template>
|
||||
<s-layout title="物流追踪">
|
||||
<view class="log-wrap">
|
||||
<!-- 商品信息 -->
|
||||
<view class="log-card ss-flex ss-m-20 ss-r-10" v-if="goodsImages.length > 0">
|
||||
<uni-swiper-dot :info="goodsImages" :current="state.current" mode="round">
|
||||
<swiper class="swiper-box">
|
||||
<swiper-item v-for="(item, index) in goodsImages" :key="index">
|
||||
<image class="log-card-img" :src="sheep.$url.static(item.image)" />
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</uni-swiper-dot>
|
||||
<view class="log-card-msg">
|
||||
<!-- TODO 芋艿:【物流】优化点:展示状态 -->
|
||||
<!-- <view class="ss-flex ss-m-b-8">-->
|
||||
<!-- <view>物流状态:</view>-->
|
||||
<!-- <view class="warning-color">{{ state.info.status_text }}</view>-->
|
||||
<!-- </view>-->
|
||||
<view class="ss-m-b-8">快递单号:{{ state.info.logisticsNo }}</view>
|
||||
<view>快递公司:{{ state.info.logisticsName }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 物流轨迹 -->
|
||||
<view class="log-content ss-m-20 ss-r-10">
|
||||
<view
|
||||
class="log-content-box ss-flex"
|
||||
v-for="(item, index) in state.tracks"
|
||||
:key="item.title"
|
||||
>
|
||||
<view class="log-icon ss-flex-col ss-col-center ss-m-r-20">
|
||||
<text class="cicon-title" />
|
||||
<view v-if="state.tracks.length - 1 !== index" class="line" />
|
||||
</view>
|
||||
<view class="log-content-msg">
|
||||
<!-- TODO 芋艿:【物流】优化点:展示状态 -->
|
||||
<!-- <view class="log-msg-title ss-m-b-20">-->
|
||||
<!-- {{ item.status_text }}-->
|
||||
<!-- </view>-->
|
||||
<view class="log-msg-desc ss-m-b-16">{{ item.content }}</view>
|
||||
<view class="log-msg-date ss-m-b-40">
|
||||
{{ sheep.$helper.timeFormat(item.time, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { computed, reactive } from 'vue';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
|
||||
const state = reactive({
|
||||
info: [],
|
||||
tracks: [],
|
||||
});
|
||||
|
||||
const goodsImages = computed(() => {
|
||||
let array = [];
|
||||
if (state.info.items) {
|
||||
state.info.items.forEach((item) => {
|
||||
array.push({
|
||||
image: item.picUrl,
|
||||
});
|
||||
});
|
||||
}
|
||||
return array;
|
||||
});
|
||||
|
||||
async function getExpressDetail(id) {
|
||||
const { data } = await OrderApi.getOrderExpressTrackList(id);
|
||||
state.tracks = data.reverse();
|
||||
}
|
||||
|
||||
async function getOrderDetail(id) {
|
||||
const { data } = await OrderApi.getOrder(id)
|
||||
state.info = data;
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
getExpressDetail(options.id);
|
||||
getOrderDetail(options.id);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.swiper-box {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
}
|
||||
.log-card {
|
||||
border-top: 2rpx solid rgba(#dfdfdf, 0.5);
|
||||
padding: 20rpx;
|
||||
background: #fff;
|
||||
margin-bottom: 20rpx;
|
||||
.log-card-img {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
.log-card-msg {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
width: 490rpx;
|
||||
color: #333333;
|
||||
.warning-color {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
.log-content {
|
||||
padding: 34rpx 20rpx 0rpx 20rpx;
|
||||
background: #fff;
|
||||
.log-content-box {
|
||||
align-items: stretch;
|
||||
}
|
||||
.log-icon {
|
||||
height: inherit;
|
||||
.cicon-title {
|
||||
color: #ccc;
|
||||
font-size: 40rpx;
|
||||
}
|
||||
.activity-color {
|
||||
color: #f0c785;
|
||||
font-size: 40rpx;
|
||||
}
|
||||
.info-color {
|
||||
color: #ccc;
|
||||
font-size: 40rpx;
|
||||
}
|
||||
.line {
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
background: #d8d8d8;
|
||||
}
|
||||
}
|
||||
|
||||
.log-content-msg {
|
||||
.log-msg-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
.log-msg-desc {
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
.log-msg-date {
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
495
pages/order/list.vue
Normal file
495
pages/order/list.vue
Normal file
@@ -0,0 +1,495 @@
|
||||
<!-- 订单列表 -->
|
||||
<template>
|
||||
<s-layout title="我的订单">
|
||||
<su-sticky bgColor="#fff">
|
||||
<su-tabs
|
||||
:list="tabMaps"
|
||||
:scrollable="false"
|
||||
@change="onTabsChange"
|
||||
:current="state.currentTab"
|
||||
/>
|
||||
</su-sticky>
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/order-empty.png" text="暂无订单" />
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view
|
||||
class="bg-white order-list-card-box ss-r-10 ss-m-t-14 ss-m-20"
|
||||
v-for="order in state.pagination.list"
|
||||
:key="order.id"
|
||||
@tap="onOrderDetail(order.id)"
|
||||
>
|
||||
<view class="order-card-header ss-flex ss-col-center ss-row-between ss-p-x-20">
|
||||
<view class="order-no">订单号:{{ order.no }}</view>
|
||||
<view class="order-state ss-font-26" :class="formatOrderColor(order)">
|
||||
{{ formatOrderStatus(order) }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="border-bottom" v-for="item in order.items" :key="item.id">
|
||||
<s-goods-item
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price"
|
||||
:num="item.count"
|
||||
/>
|
||||
</view>
|
||||
<view class="pay-box ss-m-t-30 ss-flex ss-row-right ss-p-r-20">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<view class="discounts-title pay-color"
|
||||
>共 {{ order.productCount }} 件商品,总金额:</view
|
||||
>
|
||||
<view class="discounts-money pay-color"> ¥{{ fen2yuan(order.payPrice) }} </view>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-card-footer ss-flex ss-col-center ss-p-x-20"
|
||||
:class="order.buttons.length > 3 ? 'ss-row-between' : 'ss-row-right'"
|
||||
>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<button
|
||||
v-if="order.buttons.includes('combination')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onOrderGroupon(order)"
|
||||
>
|
||||
拼团详情
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.length === 0"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onOrderDetail(order.id)"
|
||||
>
|
||||
查看详情
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('confirm')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onConfirm(order)"
|
||||
>
|
||||
确认收货
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('express')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onExpress(order.id)"
|
||||
>
|
||||
查看物流
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('cancel')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onCancel(order.id)"
|
||||
>
|
||||
取消订单
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('comment')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onComment(order.id)"
|
||||
>
|
||||
评价
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('delete')"
|
||||
class="delete-btn ss-reset-button"
|
||||
@tap.stop="onDelete(order.id)"
|
||||
>
|
||||
删除订单
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('pay')"
|
||||
class="tool-btn ss-reset-button ui-BG-Main-Gradient"
|
||||
@tap.stop="onPay(order.payOrderId)"
|
||||
>
|
||||
继续支付
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多 -->
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
}"
|
||||
@tap="loadMore"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app';
|
||||
import {
|
||||
fen2yuan,
|
||||
formatOrderColor,
|
||||
formatOrderStatus,
|
||||
handleOrderButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import sheep from '@/sheep';
|
||||
import _ from 'lodash-es';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
|
||||
// 数据
|
||||
const state = reactive({
|
||||
currentTab: 0, // 选中的 tabMaps 下标
|
||||
pagination: {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 5,
|
||||
},
|
||||
loadStatus: '',
|
||||
});
|
||||
|
||||
const tabMaps = [
|
||||
{
|
||||
name: '全部',
|
||||
},
|
||||
{
|
||||
name: '待付款',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: '待发货',
|
||||
value: 10,
|
||||
},
|
||||
{
|
||||
name: '待收货',
|
||||
value: 20,
|
||||
},
|
||||
{
|
||||
name: '待评价',
|
||||
value: 30,
|
||||
},
|
||||
];
|
||||
|
||||
// 切换选项卡
|
||||
function onTabsChange(e) {
|
||||
if (state.currentTab === e.index) {
|
||||
return;
|
||||
}
|
||||
// 重头加载代码
|
||||
resetPagination(state.pagination);
|
||||
state.currentTab = e.index;
|
||||
getOrderList();
|
||||
}
|
||||
|
||||
// 订单详情
|
||||
function onOrderDetail(id) {
|
||||
sheep.$router.go('/pages/order/detail', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 跳转拼团记录的详情
|
||||
function onOrderGroupon(order) {
|
||||
sheep.$router.go('/pages/activity/groupon/detail', {
|
||||
id: order.combinationRecordId,
|
||||
});
|
||||
}
|
||||
|
||||
// 继续支付
|
||||
function onPay(payOrderId) {
|
||||
sheep.$router.go('/pages/pay/index', {
|
||||
id: payOrderId,
|
||||
});
|
||||
}
|
||||
|
||||
// 评价
|
||||
function onComment(id) {
|
||||
sheep.$router.go('/pages/goods/comment/add', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 确认收货 TODO 芋艿:待测试
|
||||
async function onConfirm(order, ignore = false) {
|
||||
// 需开启确认收货组件
|
||||
// todo: 芋艿:需要后续接入微信收货组件
|
||||
// 1.怎么检测是否开启了发货组件功能?如果没有开启的话就不能在这里return出去
|
||||
// 2.如果开启了走mpConfirm方法,需要在App.vue的show方法中拿到确认收货结果
|
||||
let isOpenBusinessView = true;
|
||||
if (
|
||||
sheep.$platform.name === 'WechatMiniProgram' &&
|
||||
!isEmpty(order.wechat_extra_data) &&
|
||||
isOpenBusinessView &&
|
||||
!ignore
|
||||
) {
|
||||
mpConfirm(order);
|
||||
return;
|
||||
}
|
||||
|
||||
// 正常的确认收货流程
|
||||
const { code } = await OrderApi.receiveOrder(order.id);
|
||||
if (code === 0) {
|
||||
resetPagination(state.pagination);
|
||||
await getOrderList();
|
||||
}
|
||||
}
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// 小程序确认收货组件 TODO 芋艿:后续再接入
|
||||
function mpConfirm(order) {
|
||||
if (!wx.openBusinessView) {
|
||||
sheep.$helper.toast(`请升级微信版本`);
|
||||
return;
|
||||
}
|
||||
wx.openBusinessView({
|
||||
businessType: 'weappOrderConfirm',
|
||||
extraData: {
|
||||
merchant_id: '1481069012',
|
||||
merchant_trade_no: order.wechat_extra_data.merchant_trade_no,
|
||||
transaction_id: order.wechat_extra_data.transaction_id,
|
||||
},
|
||||
success(response) {
|
||||
console.log('success:', response);
|
||||
if (response.errMsg === 'openBusinessView:ok') {
|
||||
if (response.extraData.status === 'success') {
|
||||
onConfirm(order, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
fail(error) {
|
||||
console.log('error:', error);
|
||||
},
|
||||
complete(result) {
|
||||
console.log('result:', result);
|
||||
},
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
|
||||
// 查看物流
|
||||
async function onExpress(id) {
|
||||
sheep.$router.go('/pages/order/express/log', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 取消订单
|
||||
async function onCancel(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消订单吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await OrderApi.cancelOrder(orderId);
|
||||
if (code === 0) {
|
||||
// 修改数据的状态
|
||||
let index = state.pagination.list.findIndex((order) => order.id === orderId);
|
||||
const orderInfo = state.pagination.list[index];
|
||||
orderInfo.status = 40;
|
||||
handleOrderButtons(orderInfo);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 删除订单
|
||||
function onDelete(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要删除订单吗?',
|
||||
success: async function (res) {
|
||||
if (res.confirm) {
|
||||
const { code } = await OrderApi.deleteOrder(orderId);
|
||||
if (code === 0) {
|
||||
// 删除数据
|
||||
let index = state.pagination.list.findIndex((order) => order.id === orderId);
|
||||
state.pagination.list.splice(index, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 获取订单列表
|
||||
async function getOrderList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { code, data } = await OrderApi.getOrderPage({
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize,
|
||||
status: tabMaps[state.currentTab].value,
|
||||
commentStatus: tabMaps[state.currentTab].value === 30 ? false : null,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
data.list.forEach((order) => handleOrderButtons(order));
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
if (options.type) {
|
||||
state.currentTab = options.type;
|
||||
}
|
||||
await getOrderList();
|
||||
});
|
||||
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
state.pagination.pageNo++;
|
||||
getOrderList();
|
||||
}
|
||||
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
|
||||
// 下拉刷新
|
||||
onPullDownRefresh(() => {
|
||||
resetPagination(state.pagination);
|
||||
getOrderList();
|
||||
setTimeout(function () {
|
||||
uni.stopPullDownRefresh();
|
||||
}, 800);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.score-img {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
|
||||
.tool-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #f6f6f6;
|
||||
font-size: 26rpx;
|
||||
border-radius: 30rpx;
|
||||
margin-right: 10rpx;
|
||||
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
width: 160rpx;
|
||||
height: 56rpx;
|
||||
color: #ff3000;
|
||||
background: #fee;
|
||||
border-radius: 28rpx;
|
||||
font-size: 26rpx;
|
||||
margin-right: 10rpx;
|
||||
line-height: normal;
|
||||
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.apply-btn {
|
||||
width: 140rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
border: 2rpx solid #dcdcdc;
|
||||
line-height: normal;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.swiper-box {
|
||||
flex: 1;
|
||||
|
||||
.swiper-item {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.order-list-card-box {
|
||||
.order-card-header {
|
||||
height: 80rpx;
|
||||
|
||||
.order-no {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.order-state {
|
||||
}
|
||||
}
|
||||
|
||||
.pay-box {
|
||||
.discounts-title {
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.discounts-money {
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
color: #999;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.pay-color {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.order-card-footer {
|
||||
height: 100rpx;
|
||||
|
||||
.more-item-box {
|
||||
padding: 20rpx;
|
||||
|
||||
.more-item {
|
||||
height: 60rpx;
|
||||
|
||||
.title {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.more-btn {
|
||||
color: $dark-9;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 154rpx;
|
||||
color: #333333;
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.uni-tooltip-popup) {
|
||||
background: var(--ui-BG);
|
||||
}
|
||||
|
||||
.warning-color {
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
.danger-color {
|
||||
color: #ff3000;
|
||||
}
|
||||
|
||||
.success-color {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.info-color {
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
333
pages/order/my/aftersale/apply.vue
Normal file
333
pages/order/my/aftersale/apply.vue
Normal file
@@ -0,0 +1,333 @@
|
||||
<!-- 售后申请 -->
|
||||
<template>
|
||||
<s-layout title="取消订单">
|
||||
<!-- 售后商品 -->
|
||||
<view class="goods-box">
|
||||
<s-goods-item
|
||||
:img="state.item.picUrl"
|
||||
:title="state.item.spuName"
|
||||
:skuText="state.item.properties?.map((property) => property.valueName).join(' ')"
|
||||
:price="state.item.price"
|
||||
:num="state.item.count"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<uni-forms ref="form" v-model="formData" :rules="rules" label-position="top">
|
||||
|
||||
<!-- 退款金额 -->
|
||||
<view class="refund-item ss-flex ss-col-center ss-row-between" @tap="state.showModal = true">
|
||||
<text class="item-title">退回余额</text>
|
||||
<view class="ss-flex refund-cause ss-col-center">
|
||||
<text class="ss-m-r-20">¥{{ fen2yuan(state.item.payPrice) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 申请原因 -->
|
||||
<!-- <view class="refund-item ss-flex ss-col-center ss-row-between" @tap="state.showModal = true">
|
||||
<text class="item-title">取消原因</text>
|
||||
<view class="ss-flex refund-cause ss-col-center">
|
||||
<text class="ss-m-r-20" v-if="formData.applyReason">{{ formData.applyReason }}</text>
|
||||
<text class="ss-m-r-20" v-else>请选择取消原因~</text>
|
||||
<text class="cicon-forward" style="height: 28rpx"></text>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 留言 -->
|
||||
<view class="refund-item">
|
||||
<view class="item-title ss-m-b-20">取消原因</view>
|
||||
<view class="describe-box">
|
||||
<uni-easyinput
|
||||
:inputBorder="false"
|
||||
class="describe-content"
|
||||
type="textarea"
|
||||
maxlength="120"
|
||||
autoHeight
|
||||
v-model="formData.applyDescription"
|
||||
placeholder="客官~请描述您遇到的问题,建议上传照片"
|
||||
/>
|
||||
<!-- TODO 芋艿:上传的测试 -->
|
||||
<view class="upload-img">
|
||||
<s-uploader
|
||||
v-model:url="formData.images"
|
||||
fileMediatype="image"
|
||||
limit="9"
|
||||
mode="grid"
|
||||
:imageStyles="{ width: '168rpx', height: '168rpx' }"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-forms>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<su-fixed bottom placeholder>
|
||||
<view class="foot-wrap">
|
||||
<view class="foot_box ss-flex ss-col-center ss-row-between ss-p-x-30">
|
||||
<button class="ss-reset-button contcat-btn" @tap="sheep.$router.go('/pages/chat/index')">
|
||||
联系客服
|
||||
</button>
|
||||
<button class="ss-reset-button ui-BG-Main-Gradient sub-btn" @tap="submit">提交</button>
|
||||
</view>
|
||||
</view>
|
||||
</su-fixed>
|
||||
|
||||
<!-- 申请原因弹窗 -->
|
||||
<su-popup :show="state.showModal" round="10" :showClose="true" @close="state.showModal = false">
|
||||
<view class="modal-box page_box">
|
||||
<view class="modal-head item-title head_box ss-flex ss-row-center ss-col-center">
|
||||
取消原因
|
||||
</view>
|
||||
<view class="modal-content content_box">
|
||||
<radio-group @change="onChange">
|
||||
<label class="radio ss-flex ss-col-center" v-for="item in state.reasonList" :key="item">
|
||||
<view class="ss-flex-1 ss-p-20">{{ item }}</view>
|
||||
<radio
|
||||
:value="item"
|
||||
color="var(--ui-BG-Main)"
|
||||
:checked="item === state.currentValue"
|
||||
/>
|
||||
</label>
|
||||
</radio-group>
|
||||
</view>
|
||||
<view class="modal-foot foot_box ss-flex ss-row-center ss-col-center">
|
||||
<button class="ss-reset-button close-btn ui-BG-Main-Gradient" @tap="onReason">
|
||||
确定
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</su-popup>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive, ref } from 'vue';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import TradeConfigApi from '@/sheep/api/trade/config';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import AfterSaleApi from '@/sheep/api/trade/afterSale';
|
||||
import { WxaSubscribeTemplate } from '@/sheep/util/const';
|
||||
|
||||
const form = ref(null);
|
||||
const state = reactive({
|
||||
orderId: 0, // 订单编号
|
||||
itemId: 0, // 订单项编号
|
||||
order: {}, // 订单
|
||||
item: {}, // 订单项
|
||||
config: {}, // 交易配置
|
||||
|
||||
// 售后类型
|
||||
wayList: [
|
||||
{
|
||||
text: '仅退款',
|
||||
value: '10',
|
||||
},
|
||||
{
|
||||
text: '退款退货',
|
||||
value: '20',
|
||||
},
|
||||
],
|
||||
reasonList: [], // 可选的申请原因数组
|
||||
showModal: false, // 是否显示申请原因弹窗
|
||||
currentValue: '', // 当前选择的售后原因
|
||||
});
|
||||
let formData = reactive({
|
||||
way: '',
|
||||
applyReason: '',
|
||||
applyDescription: '',
|
||||
images: [],
|
||||
});
|
||||
const rules = reactive({});
|
||||
|
||||
// 提交表单
|
||||
async function submit() {
|
||||
let data = {
|
||||
orderItemId: state.itemId,
|
||||
refundPrice: state.item.payPrice,
|
||||
...formData,
|
||||
};
|
||||
const { code } = await AfterSaleApi.createAfterSale(data);
|
||||
if (code === 0) {
|
||||
uni.showToast({
|
||||
title: '取消成功',
|
||||
});
|
||||
sheep.$router.go('/pages/order/my/list');
|
||||
}
|
||||
}
|
||||
|
||||
// 选择售后类型
|
||||
function onRefundChange(e) {
|
||||
formData.way = e;
|
||||
// 清理理由
|
||||
state.reasonList =
|
||||
formData.way === '10'
|
||||
? state.config.afterSaleRefundReasons || []
|
||||
: state.config.afterSaleReturnReasons || [];
|
||||
formData.applyReason = '';
|
||||
state.currentValue = '';
|
||||
}
|
||||
|
||||
// 选择申请原因
|
||||
function onChange(e) {
|
||||
state.currentValue = e.detail.value;
|
||||
}
|
||||
|
||||
// 确定
|
||||
function onReason() {
|
||||
formData.applyReason = state.currentValue;
|
||||
state.showModal = false;
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
// 解析参数
|
||||
if (!options.orderId || !options.itemId) {
|
||||
sheep.$helper.toast(`缺少订单信息,请检查`);
|
||||
return;
|
||||
}
|
||||
state.orderId = options.orderId;
|
||||
state.itemId = parseInt(options.itemId);
|
||||
|
||||
// 读取订单信息
|
||||
const { code, data } = await OrderApi.getOrder(state.orderId);
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.order = data;
|
||||
state.item = data.items.find((item) => item.id === state.itemId) || {};
|
||||
|
||||
// 设置选项
|
||||
if (state.order.status === 10) {
|
||||
state.wayList.splice(1, 1);
|
||||
}
|
||||
|
||||
// 读取配置
|
||||
state.config = (await TradeConfigApi.getTradeConfig()).data;
|
||||
|
||||
onRefundChange("10");
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.item-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
// margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
// 售后项目
|
||||
.refund-item {
|
||||
background-color: #fff;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
padding: 30rpx;
|
||||
|
||||
&:last-child {
|
||||
border: none;
|
||||
}
|
||||
|
||||
// 留言
|
||||
.describe-box {
|
||||
width: 690rpx;
|
||||
background: rgba(249, 250, 251, 1);
|
||||
padding: 30rpx;
|
||||
box-sizing: border-box;
|
||||
border-radius: 20rpx;
|
||||
|
||||
.describe-content {
|
||||
height: 200rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
// 联系方式
|
||||
.input-box {
|
||||
height: 84rpx;
|
||||
background: rgba(249, 250, 251, 1);
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-box {
|
||||
background: #fff;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.foot-wrap {
|
||||
height: 100rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.foot_box {
|
||||
height: 100rpx;
|
||||
background-color: #fff;
|
||||
|
||||
.sub-btn {
|
||||
width: 336rpx;
|
||||
line-height: 74rpx;
|
||||
border-radius: 38rpx;
|
||||
color: rgba(#fff, 0.9);
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.contcat-btn {
|
||||
width: 336rpx;
|
||||
line-height: 74rpx;
|
||||
background: rgba(238, 238, 238, 1);
|
||||
border-radius: 38rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.modal-box {
|
||||
width: 750rpx;
|
||||
// height: 680rpx;
|
||||
border-radius: 30rpx 30rpx 0 0;
|
||||
background: #fff;
|
||||
|
||||
.modal-head {
|
||||
height: 100rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.modal-foot {
|
||||
.close-btn {
|
||||
width: 710rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
color: rgba(#fff, 0.9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.success-box {
|
||||
width: 600rpx;
|
||||
padding: 90rpx 0 64rpx 0;
|
||||
|
||||
.cicon-check-round {
|
||||
font-size: 96rpx;
|
||||
color: #04b750;
|
||||
}
|
||||
|
||||
.success-title {
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.success-btn {
|
||||
width: 492rpx;
|
||||
height: 70rpx;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main-gradient), var(--ui-BG-Main));
|
||||
border-radius: 35rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
184
pages/order/my/aftersale/list.vue
Normal file
184
pages/order/my/aftersale/list.vue
Normal file
@@ -0,0 +1,184 @@
|
||||
<!-- 售后列表 -->
|
||||
<template>
|
||||
<s-layout title="退款列表">
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/data-empty.png" text="暂无数据" />
|
||||
<!-- 列表 -->
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view
|
||||
class="list-box ss-m-y-20"
|
||||
v-for="order in state.pagination.list"
|
||||
:key="order.id"
|
||||
@tap="sheep.$router.go('/pages/clerk/detail/index', { id: order.spuId })"
|
||||
>
|
||||
<view class="order-head ss-flex ss-col-center ss-row-between">
|
||||
<text class="no">服务单号:{{ order.no }}</text>
|
||||
<text class="state">{{ formatAfterSaleStatus(order) }}</text>
|
||||
</view>
|
||||
<s-goods-item
|
||||
:img="order.picUrl"
|
||||
:title="order.spuName"
|
||||
:skuText="order.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="order.refundPrice"
|
||||
/>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
}"
|
||||
@tap="loadMore"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash-es';
|
||||
import {
|
||||
formatAfterSaleStatus,
|
||||
formatAfterSaleStatusDescription,
|
||||
handleAfterSaleButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import AfterSaleApi from '@/sheep/api/trade/afterSale';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
|
||||
const state = reactive({
|
||||
currentTab: 0,
|
||||
showApply: false,
|
||||
pagination: {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
loadStatus: '',
|
||||
});
|
||||
|
||||
// TODO 芋艿:优化点,增加筛选
|
||||
const tabMaps = [
|
||||
{
|
||||
name: '全部',
|
||||
value: 'all',
|
||||
},
|
||||
// {
|
||||
// name: '申请中',
|
||||
// value: 'nooper',
|
||||
// },
|
||||
// {
|
||||
// name: '处理中',
|
||||
// value: 'ing',
|
||||
// },
|
||||
// {
|
||||
// name: '已完成',
|
||||
// value: 'completed',
|
||||
// },
|
||||
// {
|
||||
// name: '已拒绝',
|
||||
// value: 'refuse',
|
||||
// },
|
||||
];
|
||||
|
||||
// 切换选项卡
|
||||
function onTabsChange(e) {
|
||||
resetPagination(state.pagination);
|
||||
state.currentTab = e.index;
|
||||
getOrderList();
|
||||
}
|
||||
|
||||
// 获取售后列表
|
||||
async function getOrderList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { data, code } = await AfterSaleApi.getAfterSalePage({
|
||||
// type: tabMaps[state.currentTab].value,
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
data.list.forEach((order) => handleAfterSaleButtons(order));
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
|
||||
function onApply(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消此申请吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await AfterSaleApi.cancelAfterSale(orderId);
|
||||
if (code === 0) {
|
||||
resetPagination(state.pagination);
|
||||
await getOrderList();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
if (options.type) {
|
||||
state.currentTab = options.type;
|
||||
}
|
||||
await getOrderList();
|
||||
});
|
||||
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
state.pagination.pageNo++;
|
||||
getOrderList();
|
||||
}
|
||||
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.list-box {
|
||||
background-color: #fff;
|
||||
|
||||
.order-head {
|
||||
padding: 0 25rpx;
|
||||
height: 77rpx;
|
||||
}
|
||||
|
||||
.apply-box {
|
||||
height: 82rpx;
|
||||
|
||||
.title {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 22rpx;
|
||||
color: $dark-6;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-btn-box {
|
||||
height: 100rpx;
|
||||
|
||||
.tool-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #f6f6f6;
|
||||
border-radius: 30rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
130
pages/order/my/components/layout.vue
Normal file
130
pages/order/my/components/layout.vue
Normal file
@@ -0,0 +1,130 @@
|
||||
<!-- 虚拟列表演示(不使用内置列表)(vue) -->
|
||||
<!-- 写法较简单,在页面中对当前需要渲染的虚拟列表数据进行for循环,在vue3中兼容性良好 -->
|
||||
<!-- 在各平台兼容性请查阅https://z-paging.zxlee.cn/module/virtual-list.html -->
|
||||
<template>
|
||||
<view class="content">
|
||||
<!-- 如果页面中的cell高度是固定不变的,则不需要设置cell-height-mode,如果页面中高度是动态改变的,则设置cell-height-mode="dynamic" -->
|
||||
<!-- 原先的v-model修改为@virtualListChange="virtualListChange"并赋值处理后的虚拟列表 -->
|
||||
<z-paging ref="paging" :auto="false" use-virtual-list :force-close-inner-list="true" :paging-style="{ paddingTop: 0 + 'px', paddingBottom: paddingBottom + 'rpx' }" cell-height-mode="dynamic" @scroll="scroll" @virtualListChange="virtualListChange" @query="queryList">
|
||||
<!-- 需要固定在顶部不滚动的view放在slot="top"的view中,如果需要跟着滚动,则不要设置slot="top" -->
|
||||
<template #top>
|
||||
<su-navbar :title="title" statusBar></su-navbar>
|
||||
<tab-box :tabList="tabList" :currentValue="currentIndex" @change="tabChange"></tab-box>
|
||||
</template>
|
||||
|
||||
<!-- :id="`zp-id-${item.zp_index}`"和:key="item.zp_index" 必须写,必须写!!!! -->
|
||||
<!-- 这里for循环的index不是数组中真实的index了,请使用item.zp_index获取真实的index -->
|
||||
<order-list @onCancel="onCancel" :virtualList="virtualList"></order-list>
|
||||
|
||||
</z-paging>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TabBox from '@/pages/order/my/components/tabBox.vue';
|
||||
import OrderList from '@/pages/order/my/components/orderList.vue';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import {
|
||||
formatMyOrderStatus,
|
||||
handleMyOrderButtons,
|
||||
fen2yuan,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
export default {
|
||||
components: {
|
||||
TabBox,
|
||||
OrderList,
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '我的订单',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 虚拟列表数组,通过@virtualListChange监听获得最新数组
|
||||
virtualList: [],
|
||||
scrollTop: 0,
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
height: 0,
|
||||
|
||||
tabList: [{
|
||||
name: '全部',
|
||||
}, {
|
||||
name: '待付款',
|
||||
value: 0,
|
||||
}, {
|
||||
name: '待服务',
|
||||
value: 10,
|
||||
}, {
|
||||
name: '服务中',
|
||||
value: 20,
|
||||
}, {
|
||||
name: '待评价',
|
||||
value: 30,
|
||||
}],
|
||||
|
||||
currentIndex: 0,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
scroll(e) {
|
||||
this.scrollTop = e.detail.scrollTop;
|
||||
},
|
||||
// 监听虚拟列表数组改变并赋值给virtualList进行重新渲染
|
||||
virtualListChange(vList) {
|
||||
this.virtualList = vList;
|
||||
},
|
||||
queryList(pageNo, pageSize) {
|
||||
// 组件加载时会自动触发此方法,因此默认页面加载时会自动触发,无需手动调用
|
||||
// 这里的pageNo和pageSize会自动计算好,直接传给服务器即可
|
||||
// 模拟请求服务器获取分页数据,请替换成自己的网络请求
|
||||
const params = {
|
||||
pageNo: pageNo,
|
||||
pageSize: pageSize,
|
||||
status: this.tabList[this.currentIndex].value,
|
||||
commentStatus: this.tabList[this.currentIndex].value === 30 ? false : null,
|
||||
}
|
||||
OrderApi.getOrderPage(params).then(res => {
|
||||
// 将请求的结果数组传递给z-paging
|
||||
res.data.list.forEach((order) => handleMyOrderButtons(order));
|
||||
res.data.list.forEach((order) => formatMyOrderStatus(order));
|
||||
res.data.list.forEach((order) => order.payPrice = fen2yuan(order.payPrice));
|
||||
this.$refs.paging.complete(res.data.list);
|
||||
}).catch(res => {
|
||||
// 如果请求失败写this.$refs.paging.complete(false);
|
||||
// 注意,每次都需要在catch中写这句话很麻烦,z-paging提供了方案可以全局统一处理
|
||||
// 在底层的网络请求抛出异常时,写uni.$emit('z-paging-error-emit');即可
|
||||
this.$refs.paging.complete(false);
|
||||
})
|
||||
},
|
||||
tabChange(e) {
|
||||
this.currentIndex = e;
|
||||
this.$refs.paging.reload();
|
||||
},
|
||||
// 取消订单
|
||||
async onCancel(orderId) {
|
||||
var that = this;
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消订单吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await OrderApi.cancelOrder(orderId);
|
||||
if (code === 0) {
|
||||
that.$refs.paging.reload();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
219
pages/order/my/components/orderList.vue
Normal file
219
pages/order/my/components/orderList.vue
Normal file
@@ -0,0 +1,219 @@
|
||||
<template>
|
||||
<view @click="onOrderDetail(order.id)" :id="`zp-id-${order.zp_index}`" :key="order.zp_index" v-for="(order,index) in orderList" class="order-card">
|
||||
<view class="no-box">
|
||||
<view class="order-no">
|
||||
<u-icon name="order"></u-icon>
|
||||
<text class="number">{{ order.no }}</text>
|
||||
</view>
|
||||
<view class="status">{{order.statusStr}}</view>
|
||||
</view>
|
||||
|
||||
<view class="main-box" v-for="item in order.items" :key="item.id">
|
||||
<view @tap.stop="onBuy(item.spuId)">
|
||||
<u-avatar size="100" :src="item.avatar"></u-avatar>
|
||||
</view>
|
||||
<view class="right-box">
|
||||
<view class="nickname-box">
|
||||
<view class="nickname" v-if="item.nickname">{{item.nickname}}</view>
|
||||
<view class="nickname" v-else>待接单..</view>
|
||||
<view class="info">订单时间:{{order.createTimeStr}}</view>
|
||||
<view class="info">服务内容:{{item.spuName}} {{item.properties.map((property) => property.valueName).join(' ')}}×{{item.count}}</view>
|
||||
<view class="info">开始服务时间:{{order.deliveryTimeStr}}</view>
|
||||
<view class="info">
|
||||
<text>剩余时间:</text>
|
||||
<view v-if="order.receiveTime">
|
||||
<text v-if="order.end">已结束</text>
|
||||
<view v-else>
|
||||
<u-count-down :timestamp="order.timestamp" format="DD天HH时mm分ss秒" @end="order.end = true"></u-count-down>
|
||||
</view>
|
||||
</view>
|
||||
<text v-else>暂未接单</text>
|
||||
</view>
|
||||
<view class="info" v-if="order.status == 40">取消原因:{{order.cancelReason}}</view>
|
||||
</view>
|
||||
<view class="price-box">
|
||||
<text class="price">{{order.payPrice}}</text>
|
||||
<text>/钻</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-box">
|
||||
<view class="btn-box">
|
||||
<view v-if="order.buttons.includes('detail')" @tap.stop="onOrderDetail(order.id)" class="btn">查看详情</view>
|
||||
<view v-if="order.buttons.includes('unpay')" @tap.stop="onOrderDetail(order.id)" class="btn">取消订单</view>
|
||||
<view v-if="order.buttons.includes('cancel')" @tap.stop="onCancel(order.id)" class="btn">取消订单</view>
|
||||
<view v-if="order.buttons.includes('buy') && order.items[0].spuId" @tap.stop="onBuy(order.items[0].spuId)" class="btn active">再来一单</view>
|
||||
<view v-if="order.buttons.includes('comment')" @tap.stop="onComment(order.id)" class="btn active">评价</view>
|
||||
<view v-if="order.buttons.includes('pay')" @tap.stop="onPay(order.payOrderId)" class="btn active">继续支付</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import sheep from '@/sheep';
|
||||
import dayjs from 'dayjs';
|
||||
export default {
|
||||
components: {
|
||||
|
||||
},
|
||||
props: {
|
||||
virtualList: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
emits: ["onCancel"],
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
orderList() {
|
||||
this.virtualList.forEach((order) => order.createTimeStr = sheep.$helper.timeFormat(order.createTime, 'yyyy-mm-dd hh:MM:ss'));
|
||||
this.virtualList.forEach((order) => order.deliveryTimeStr = order.deliveryTime ? sheep.$helper.timeFormat(order.deliveryTime, 'yyyy-mm-dd hh:MM:ss') : '');
|
||||
this.virtualList.forEach((order) => order.timestamp = order.receiveTime ? sheep.$helper.parseTimeData(order.receiveTime) : 0);
|
||||
return this.virtualList;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 订单详情
|
||||
onOrderDetail(id) {
|
||||
sheep.$router.go('/pages/order/my/detail', {
|
||||
id,
|
||||
});
|
||||
},
|
||||
onCancel(orderId) {
|
||||
this.$emit('onCancel', orderId);
|
||||
},
|
||||
onBuy(id) {
|
||||
if(id){
|
||||
sheep.$router.go('/pages/clerk/detail/index', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
},
|
||||
// 评价
|
||||
onComment(id) {
|
||||
sheep.$router.go('/pages/goods/comment/worker/add', {
|
||||
id,
|
||||
});
|
||||
},
|
||||
// 继续支付
|
||||
onPay(payOrderId) {
|
||||
sheep.$router.go('/pages/pay/worker/index', {
|
||||
id: payOrderId,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order-card {
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
|
||||
.no-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
padding-bottom: 10px;
|
||||
color: rgb(100, 101, 102);
|
||||
|
||||
.order-no {
|
||||
|
||||
.number {
|
||||
margin-left: 5px;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.status {
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.main-box {
|
||||
display: flex;
|
||||
padding: 10px 0;
|
||||
border-top: 1px solid #fbf0f0;
|
||||
border-bottom: 1px solid #fbf0f0;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.right-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
margin-left: 10px;
|
||||
|
||||
.nickname {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.info {
|
||||
font-size: 22rpx;
|
||||
color: rgb(100, 101, 102);
|
||||
line-height: 22rpx;
|
||||
margin-bottom: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.weixin {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.price-box {
|
||||
font-size: 22rpx;
|
||||
color: rgb(100, 101, 102);
|
||||
|
||||
.price {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-box {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
.btn-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: #ddd;
|
||||
color: rgb(100, 101, 102);
|
||||
font-size: 22rpx;
|
||||
border-radius: 40px;
|
||||
padding: 5px 10px;
|
||||
margin-left: 10px;
|
||||
min-width: 140rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.active {
|
||||
background-color: var(--ui-BG-Main);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
47
pages/order/my/components/tabBox.vue
Normal file
47
pages/order/my/components/tabBox.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<view>
|
||||
<u-tabs :list="tabList" bg-color="#fff" font-size="28" active-color="var(--ui-BG-Main)" :is-scroll="false" v-model="current" @change="change"></u-tabs>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
components: {
|
||||
|
||||
},
|
||||
props: {
|
||||
currentValue: 0,
|
||||
tabList: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
current: {
|
||||
get() {
|
||||
return this.currentValue;
|
||||
},
|
||||
set(newValue) {
|
||||
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
change(index) {
|
||||
this.$emit('change', index);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tab-box {
|
||||
background-color: #fff;
|
||||
padding: 5px 0;
|
||||
}
|
||||
</style>
|
426
pages/order/my/confirm.vue
Normal file
426
pages/order/my/confirm.vue
Normal file
@@ -0,0 +1,426 @@
|
||||
<template>
|
||||
<s-layout title="确认订单">
|
||||
<!-- 商品信息 -->
|
||||
<view class="order-card-box ss-m-b-14">
|
||||
<s-goods-item
|
||||
v-for="item in state.orderInfo.items"
|
||||
:key="item.skuId"
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price"
|
||||
:num="item.count"
|
||||
marginBottom="10"
|
||||
/>
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between ss-p-x-20 bg-white ss-r-10">
|
||||
<view class="item-title">订单备注</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<uni-easyinput
|
||||
maxlength="20"
|
||||
placeholder="请输入备注内容"
|
||||
v-model="state.orderPayload.remark"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 价格信息 -->
|
||||
<view class="bg-white total-card-box ss-p-20 ss-m-b-14 ss-r-10">
|
||||
<view class="total-box-content border-bottom">
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between">
|
||||
<view class="item-title">商品金额</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="item-value ss-m-r-24">
|
||||
¥{{ fen2yuan(state.orderInfo.price.totalPrice) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.type === 5"
|
||||
>
|
||||
<view class="item-title">积分抵扣</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
{{ state.pointStatus ? '剩余积分' : '当前积分' }}
|
||||
<image
|
||||
:src="sheep.$url.static('/static/img/shop/goods/score1.svg')"
|
||||
class="score-img"
|
||||
/>
|
||||
<text class="item-value ss-m-r-24">
|
||||
{{ state.pointStatus ? state.orderInfo.totalPoint - state.orderInfo.usePoint : (state.orderInfo.totalPoint || 0) }}
|
||||
</text>
|
||||
<checkbox-group @change="changeIntegral">
|
||||
<checkbox :checked='state.pointStatus' :disabled="!state.orderInfo.totalPoint || state.orderInfo.totalPoint <= 0" />
|
||||
</checkbox-group>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between">
|
||||
<view class="item-title">你的微信号</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<uni-easyinput
|
||||
maxlength="20"
|
||||
placeholder="请输入正确的微信号"
|
||||
v-model="addressState.receiverName"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 优惠劵:只有 type = 0 普通订单(非拼团、秒杀、砍价),才可以使用优惠劵 -->
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.type === 0"
|
||||
>
|
||||
<view class="item-title">优惠券</view>
|
||||
<view class="ss-flex ss-col-center" @tap="state.showCoupon = true">
|
||||
<text class="item-value text-red" v-if="state.orderPayload.couponId > 0">
|
||||
-¥{{ fen2yuan(state.orderInfo.price.couponPrice) }}
|
||||
</text>
|
||||
<text
|
||||
class="item-value"
|
||||
:class="state.couponInfo.length > 0 ? 'text-red' : 'text-disabled'"
|
||||
v-else
|
||||
>
|
||||
{{
|
||||
state.couponInfo.length > 0 ? state.couponInfo.length + ' 张可用' : '暂无可用优惠券'
|
||||
}}
|
||||
</text>
|
||||
<text class="_icon-forward item-icon" />
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.price.discountPrice > 0"
|
||||
>
|
||||
<view class="item-title">活动优惠</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<!-- @tap="state.showDiscount = true" TODO puhui999:【折扣】后续要把优惠信息打进去 -->
|
||||
<text class="item-value text-red">
|
||||
-¥{{ fen2yuan(state.orderInfo.price.discountPrice) }}
|
||||
</text>
|
||||
<text class="_icon-forward item-icon" />
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.price.vipPrice > 0"
|
||||
>
|
||||
<view class="item-title">会员优惠</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="item-value text-red">
|
||||
-¥{{ fen2yuan(state.orderInfo.price.vipPrice) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="total-box-footer ss-font-28 ss-flex ss-row-right ss-col-center ss-m-r-28">
|
||||
<view class="total-num ss-m-r-20">
|
||||
共{{ state.orderInfo.items.reduce((acc, item) => acc + item.count, 0) }}件
|
||||
</view>
|
||||
<view>合计:</view>
|
||||
<view class="total-num text-red"> ¥{{ fen2yuan(state.orderInfo.price.payPrice) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 选择优惠券弹框 -->
|
||||
<s-coupon-select
|
||||
v-model="state.couponInfo"
|
||||
:show="state.showCoupon"
|
||||
@confirm="onSelectCoupon"
|
||||
@close="state.showCoupon = false"
|
||||
/>
|
||||
|
||||
<!-- 满额折扣弹框 TODO @puhui999:【折扣】后续要把优惠信息打进去 -->
|
||||
<s-discount-list
|
||||
v-model="state.orderInfo"
|
||||
:show="state.showDiscount"
|
||||
@close="state.showDiscount = false"
|
||||
/>
|
||||
|
||||
<!-- 底部 -->
|
||||
<su-fixed bottom :opacity="false" bg="bg-white" placeholder :noFixed="false" :index="200">
|
||||
<view class="footer-box border-top ss-flex ss-row-between ss-p-x-20 ss-col-center">
|
||||
<view class="total-box-footer ss-flex ss-col-center">
|
||||
<view class="total-num ss-font-30 text-red">
|
||||
¥{{ fen2yuan(state.orderInfo.price.payPrice) }}
|
||||
</view>
|
||||
</view>
|
||||
<button
|
||||
class="ss-reset-button ui-BG-Main-Gradient ss-r-40 submit-btn ui-Shadow-Main"
|
||||
@tap="onConfirm"
|
||||
>
|
||||
提交订单
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import AddressSelection from '@/pages/order/addressSelection.vue';
|
||||
import sheep from '@/sheep';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
|
||||
const state = reactive({
|
||||
orderPayload: {},
|
||||
orderInfo: {
|
||||
items: [], // 商品项列表
|
||||
price: {}, // 价格信息
|
||||
},
|
||||
showCoupon: false, // 是否展示优惠劵
|
||||
couponInfo: [], // 优惠劵列表
|
||||
showDiscount: false, // 是否展示营销活动
|
||||
// ========== 积分 ==========
|
||||
pointStatus: false, //是否使用积分
|
||||
});
|
||||
|
||||
const addressState = ref({
|
||||
addressInfo: {}, // 选择的收货地址
|
||||
deliveryType: 1, // 收货方式:1-快递配送,2-门店自提
|
||||
isPickUp: true, // 门店自提是否开启 TODO puhui999: 默认开启,看看后端有开关的话接入
|
||||
pickUpInfo: {}, // 选择的自提门店信息
|
||||
receiverName: '', // 收件人名称
|
||||
receiverMobile: '', // 收件人手机
|
||||
});
|
||||
|
||||
// ========== 积分 ==========
|
||||
/**
|
||||
* 使用积分抵扣
|
||||
*/
|
||||
const changeIntegral = async () => {
|
||||
state.pointStatus = !state.pointStatus;
|
||||
await getOrderInfo();
|
||||
};
|
||||
|
||||
// 选择优惠券
|
||||
async function onSelectCoupon(couponId) {
|
||||
state.orderPayload.couponId = couponId;
|
||||
await getOrderInfo();
|
||||
state.showCoupon = false;
|
||||
}
|
||||
|
||||
// 提交订单
|
||||
function onConfirm() {
|
||||
if (addressState.value.receiverName === '') {
|
||||
sheep.$helper.toast('请填写正确的微信号');
|
||||
return;
|
||||
}
|
||||
submitOrder();
|
||||
}
|
||||
|
||||
// 创建订单&跳转
|
||||
async function submitOrder() {
|
||||
const { code, data } = await OrderApi.createWorkerOrder({
|
||||
items: state.orderPayload.items,
|
||||
couponId: state.orderPayload.couponId,
|
||||
remark: state.orderPayload.remark,
|
||||
deliveryType: addressState.value.deliveryType,
|
||||
addressId: addressState.value.addressInfo.id, // 收件地址编号
|
||||
pickUpStoreId: addressState.value.pickUpInfo.id,//自提门店编号
|
||||
receiverName: addressState.value.receiverName,// 选择门店自提时,该字段为联系人名
|
||||
receiverMobile: addressState.value.receiverMobile,// 选择门店自提时,该字段为联系人手机
|
||||
pointStatus: state.pointStatus,
|
||||
combinationActivityId: state.orderPayload.combinationActivityId,
|
||||
combinationHeadId: state.orderPayload.combinationHeadId,
|
||||
seckillActivityId: state.orderPayload.seckillActivityId,
|
||||
clerkId: state.orderPayload.clerkId,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
// 更新购物车列表,如果来自购物车
|
||||
if (state.orderPayload.items[0].cartId > 0) {
|
||||
sheep.$store('cart').getList();
|
||||
}
|
||||
|
||||
// 跳转到支付页面
|
||||
sheep.$router.redirect('/pages/pay/index', {
|
||||
id: data.payOrderId,
|
||||
});
|
||||
}
|
||||
|
||||
// 检查库存 & 计算订单价格
|
||||
async function getOrderInfo() {
|
||||
// 计算价格
|
||||
const { data, code } = await OrderApi.clerkOrder({
|
||||
items: state.orderPayload.items,
|
||||
couponId: state.orderPayload.couponId,
|
||||
deliveryType: addressState.value.deliveryType,
|
||||
addressId: addressState.value.addressInfo.id, // 收件地址编号
|
||||
pickUpStoreId: addressState.value.pickUpInfo.id,//自提门店编号
|
||||
receiverName: addressState.value.receiverName,// 选择门店自提时,该字段为联系人名
|
||||
receiverMobile: addressState.value.receiverMobile,// 选择门店自提时,该字段为联系人手机
|
||||
pointStatus: state.pointStatus,
|
||||
combinationActivityId: state.orderPayload.combinationActivityId,
|
||||
combinationHeadId: state.orderPayload.combinationHeadId,
|
||||
seckillActivityId: state.orderPayload.seckillActivityId,
|
||||
clerkId: state.orderPayload.clerkId,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.orderInfo = data;
|
||||
// 设置收货地址
|
||||
if (state.orderInfo.address) {
|
||||
addressState.value.addressInfo = state.orderInfo.address;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取可用优惠券
|
||||
async function getCoupons() {
|
||||
const { code, data } = await CouponApi.getMatchCouponList(
|
||||
state.orderInfo.price.payPrice,
|
||||
state.orderInfo.items.map((item) => item.spuId),
|
||||
state.orderPayload.items.map((item) => item.skuId),
|
||||
state.orderPayload.items.map((item) => item.categoryId),
|
||||
);
|
||||
if (code === 0) {
|
||||
state.couponInfo = data;
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
if (!options.data) {
|
||||
sheep.$helper.toast('参数不正确,请检查!');
|
||||
return;
|
||||
}
|
||||
state.orderPayload = JSON.parse(options.data);
|
||||
await getOrderInfo();
|
||||
await getCoupons();
|
||||
});
|
||||
|
||||
// 使用 watch 监听地址和配送方式的变化
|
||||
watch(addressState, async (newAddress, oldAddress) => {
|
||||
// 如果收货地址或配送方式有变化,则重新计算价格
|
||||
if (newAddress.addressInfo.id !== oldAddress.addressInfo.id || newAddress.deliveryType !== oldAddress.deliveryType) {
|
||||
await getOrderInfo();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep() {
|
||||
.uni-input-wrapper {
|
||||
width: 320rpx;
|
||||
}
|
||||
|
||||
.uni-easyinput__content-input {
|
||||
font-size: 28rpx;
|
||||
height: 72rpx;
|
||||
text-align: right !important;
|
||||
padding-right: 0 !important;
|
||||
|
||||
.uni-input-input {
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
font-size: 26rpx;
|
||||
height: 32rpx;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.uni-easyinput__content {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: right !important;
|
||||
}
|
||||
}
|
||||
|
||||
.score-img {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
|
||||
.order-item {
|
||||
height: 80rpx;
|
||||
|
||||
.item-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.item-value {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.text-disabled {
|
||||
color: #bbbbbb;
|
||||
}
|
||||
|
||||
.item-icon {
|
||||
color: $dark-9;
|
||||
}
|
||||
|
||||
.remark-input {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.item-placeholder {
|
||||
color: $dark-9;
|
||||
font-size: 26rpx;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.total-box-footer {
|
||||
height: 90rpx;
|
||||
|
||||
.total-num {
|
||||
color: #333333;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-box {
|
||||
height: 100rpx;
|
||||
|
||||
.submit-btn {
|
||||
width: 240rpx;
|
||||
height: 70rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
|
||||
.goto-pay-text {
|
||||
line-height: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
width: 240rpx;
|
||||
height: 80rpx;
|
||||
font-size: 26rpx;
|
||||
background-color: #e5e5e5;
|
||||
color: $dark-9;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.cicon-checkbox {
|
||||
font-size: 36rpx;
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
|
||||
.cicon-box {
|
||||
font-size: 36rpx;
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
580
pages/order/my/detail.vue
Normal file
580
pages/order/my/detail.vue
Normal file
@@ -0,0 +1,580 @@
|
||||
<!-- 订单详情 -->
|
||||
<template>
|
||||
<s-layout title="订单详情" class="index-wrap" navbar="inner">
|
||||
<!-- 订单状态 TODO -->
|
||||
<view
|
||||
class="state-box ss-flex-col ss-col-center ss-row-right"
|
||||
:style="[
|
||||
{
|
||||
marginTop: '-' + Number(statusBarHeight + 88 + 22) + 'rpx',
|
||||
paddingTop: Number(statusBarHeight + 88 + 22) + 'rpx',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<view class="ss-flex ss-m-t-32 ss-m-b-20">
|
||||
<image
|
||||
v-if="
|
||||
state.orderInfo.status_code == 'unpaid' ||
|
||||
state.orderInfo.status === 10 || // 待发货
|
||||
state.orderInfo.status_code == 'nocomment'
|
||||
"
|
||||
class="state-img"
|
||||
:src="sheep.$url.static('/static/img/shop/order/order_loading.png')"
|
||||
>
|
||||
</image>
|
||||
<image
|
||||
v-if="
|
||||
state.orderInfo.status_code == 'completed' ||
|
||||
state.orderInfo.status_code == 'refund_agree'
|
||||
"
|
||||
class="state-img"
|
||||
:src="sheep.$url.static('/static/img/shop/order/order_success.png')"
|
||||
>
|
||||
</image>
|
||||
<image
|
||||
v-if="state.orderInfo.status_code == 'cancel' || state.orderInfo.status_code == 'closed'"
|
||||
class="state-img"
|
||||
:src="sheep.$url.static('/static/img/shop/order/order_close.png')"
|
||||
>
|
||||
</image>
|
||||
<image
|
||||
v-if="state.orderInfo.status_code == 'noget'"
|
||||
class="state-img"
|
||||
:src="sheep.$url.static('/static/img/shop/order/order_express.png')"
|
||||
>
|
||||
</image>
|
||||
<view class="ss-font-30">{{ formatWorkerOrderStatus(state.orderInfo) }}</view>
|
||||
</view>
|
||||
<view class="ss-font-26 ss-m-x-20 ss-m-b-70">
|
||||
{{ formatMyOrderStatusDescription(state.orderInfo) }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 收货地址 -->
|
||||
<view class="order-address-box" v-if="state.orderInfo.receiverAreaId > 0">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="address-username">
|
||||
{{ state.orderInfo.receiverName }}
|
||||
</text>
|
||||
<text class="address-phone">{{ state.orderInfo.receiverMobile }}</text>
|
||||
</view>
|
||||
<view class="address-detail">
|
||||
{{ state.orderInfo.receiverAreaName }} {{ state.orderInfo.receiverDetailAddress }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="detail-goods"
|
||||
:style="[{ marginTop: state.orderInfo.receiverAreaId > 0 ? '0' : '-40rpx' }]"
|
||||
>
|
||||
<!-- 订单信 -->
|
||||
<view class="order-list" v-for="item in state.orderInfo.items" :key="item.goods_id">
|
||||
<view class="order-card">
|
||||
<s-goods-item
|
||||
@tap="onGoodsDetail(item.spuId)"
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price"
|
||||
:num="item.count"
|
||||
>
|
||||
<template #tool>
|
||||
<view class="ss-flex">
|
||||
<button
|
||||
class="ss-reset-button apply-btn"
|
||||
v-if="[10].includes(state.orderInfo.status) && item.afterSaleStatus === 0"
|
||||
@tap.stop="
|
||||
sheep.$router.go('/pages/order/my/aftersale/apply', {
|
||||
orderId: state.orderInfo.id,
|
||||
itemId: item.id,
|
||||
})
|
||||
"
|
||||
>
|
||||
确认取消
|
||||
</button>
|
||||
</view>
|
||||
</template>
|
||||
<template #priceSuffix>
|
||||
<button class="ss-reset-button tag-btn" v-if="item.status_text">
|
||||
{{ item.status_text }}
|
||||
</button>
|
||||
</template>
|
||||
</s-goods-item>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 自提核销 -->
|
||||
<PickUpVerify :order-info="state.orderInfo" :systemStore="systemStore" ref="pickUpVerifyRef"></PickUpVerify>
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<view class="notice-box">
|
||||
<view class="notice-box__content">
|
||||
<view class="notice-item--center">
|
||||
<view class="ss-flex ss-flex-1">
|
||||
<text class="title">订单编号:</text>
|
||||
<text class="detail">{{ state.orderInfo.no }}</text>
|
||||
</view>
|
||||
<button class="ss-reset-button copy-btn" @tap="onCopy">复制</button>
|
||||
</view>
|
||||
<view class="notice-item">
|
||||
<text class="title">下单时间:</text>
|
||||
<text class="detail">
|
||||
{{ sheep.$helper.timeFormat(state.orderInfo.createTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="notice-item" v-if="state.orderInfo.payTime">
|
||||
<text class="title">支付时间:</text>
|
||||
<text class="detail">
|
||||
{{ sheep.$helper.timeFormat(state.orderInfo.payTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="notice-item">
|
||||
<text class="title">支付方式:</text>
|
||||
<text class="detail">{{ state.orderInfo.payChannelName || '-' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 价格信息 -->
|
||||
<view class="order-price-box">
|
||||
<view class="notice-item ss-flex ss-row-between">
|
||||
<text class="title">订单总额</text>
|
||||
<view class="ss-flex">
|
||||
<text class="detail">¥{{ fen2yuan(state.orderInfo.totalPrice) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.couponPrice > 0">
|
||||
<text class="title">优惠劵金额</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.couponPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.pointPrice > 0">
|
||||
<text class="title">积分抵扣</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.pointPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.discountPrice > 0">
|
||||
<text class="title">活动优惠</text>
|
||||
<text class="detail">¥{{ fen2yuan(state.orderInfo.discountPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.vipPrice > 0">
|
||||
<text class="title">会员优惠</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.vipPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item all-rpice-item ss-flex ss-m-t-20">
|
||||
<text class="title">{{ state.orderInfo.payStatus ? '实付款' : '需付款' }}</text>
|
||||
<text class="detail all-price">¥{{ fen2yuan(state.orderInfo.payPrice) }}</text>
|
||||
</view>
|
||||
<view
|
||||
class="notice-item all-rpice-item ss-flex ss-m-t-20"
|
||||
v-if="state.orderInfo.refundPrice > 0"
|
||||
>
|
||||
<text class="title">已退款</text>
|
||||
<text class="detail all-price">¥{{ fen2yuan(state.orderInfo.refundPrice) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import {
|
||||
fen2yuan,
|
||||
formatWorkerOrderStatus,
|
||||
formatMyOrderStatusDescription,
|
||||
handleOrderButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import DeliveryApi from '@/sheep/api/trade/delivery';
|
||||
import PickUpVerify from '@/pages/order/pickUpVerify.vue';
|
||||
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png');
|
||||
|
||||
const state = reactive({
|
||||
orderInfo: {},
|
||||
merchantTradeNo: '', // 商户订单号
|
||||
comeinType: '', // 进入订单详情的来源类型
|
||||
});
|
||||
|
||||
// ========== 门店自提(核销) ==========
|
||||
const systemStore = ref({}); // 门店信息
|
||||
|
||||
// 复制
|
||||
const onCopy = () => {
|
||||
sheep.$helper.copyText(state.orderInfo.no);
|
||||
};
|
||||
|
||||
// 去支付
|
||||
function onPay(payOrderId) {
|
||||
sheep.$router.go('/pages/pay/index', {
|
||||
id: payOrderId,
|
||||
});
|
||||
}
|
||||
|
||||
// 查看商品
|
||||
function onGoodsDetail(id) {
|
||||
if(id) {
|
||||
sheep.$router.go('/pages/clerk/detail/index', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 取消订单
|
||||
async function onCancel(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消订单吗?',
|
||||
success: async function(res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await OrderApi.cancelOrder(orderId);
|
||||
if (code === 0) {
|
||||
await getOrderDetail(orderId);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 查看物流
|
||||
async function onExpress(id) {
|
||||
sheep.$router.go('/pages/order/express/log', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 确认收货
|
||||
async function onConfirm(orderId, ignore = false) {
|
||||
// 需开启确认收货组件
|
||||
// todo: 芋艿:待接入微信
|
||||
// 1.怎么检测是否开启了发货组件功能?如果没有开启的话就不能在这里return出去
|
||||
// 2.如果开启了走mpConfirm方法,需要在App.vue的show方法中拿到确认收货结果
|
||||
let isOpenBusinessView = true;
|
||||
if (
|
||||
sheep.$platform.name === 'WechatMiniProgram' &&
|
||||
!isEmpty(state.orderInfo.wechat_extra_data) &&
|
||||
isOpenBusinessView &&
|
||||
!ignore
|
||||
) {
|
||||
mpConfirm(orderId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 正常的确认收货流程
|
||||
const { code } = await OrderApi.receiveOrder(orderId);
|
||||
if (code === 0) {
|
||||
await getOrderDetail(orderId);
|
||||
}
|
||||
}
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// 小程序确认收货组件
|
||||
function mpConfirm(orderId) {
|
||||
if (!wx.openBusinessView) {
|
||||
sheep.$helper.toast(`请升级微信版本`);
|
||||
return;
|
||||
}
|
||||
wx.openBusinessView({
|
||||
businessType: 'weappOrderConfirm',
|
||||
extraData: {
|
||||
merchant_trade_no: state.orderInfo.wechat_extra_data.merchant_trade_no,
|
||||
transaction_id: state.orderInfo.wechat_extra_data.transaction_id,
|
||||
},
|
||||
success(response) {
|
||||
console.log('success:', response);
|
||||
if (response.errMsg === 'openBusinessView:ok') {
|
||||
if (response.extraData.status === 'success') {
|
||||
onConfirm(orderId, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
fail(error) {
|
||||
console.log('error:', error);
|
||||
},
|
||||
complete(result) {
|
||||
console.log('result:', result);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// 评价
|
||||
function onComment(id) {
|
||||
sheep.$router.go('/pages/goods/comment/add', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
const pickUpVerifyRef = ref();
|
||||
|
||||
async function getOrderDetail(id) {
|
||||
// 对详情数据进行适配
|
||||
let res;
|
||||
if (state.comeinType === 'wechat') {
|
||||
// TODO 芋艿:微信场景下
|
||||
res = await OrderApi.getOrder(id, {
|
||||
merchant_trade_no: state.merchantTradeNo,
|
||||
});
|
||||
} else {
|
||||
res = await OrderApi.getOrder(id);
|
||||
}
|
||||
if (res.code === 0) {
|
||||
state.orderInfo = res.data;
|
||||
handleOrderButtons(state.orderInfo);
|
||||
// 配送方式:门店自提
|
||||
if (res.data.pickUpStoreId) {
|
||||
const { data } = await DeliveryApi.getDeliveryPickUpStore(res.data.pickUpStoreId);
|
||||
systemStore.value = data || {};
|
||||
}
|
||||
if (state.orderInfo.deliveryType === 2 && state.orderInfo.payStatus) {
|
||||
pickUpVerifyRef.value && pickUpVerifyRef.value.markCode(res.data.pickUpVerifyCode);
|
||||
}
|
||||
} else {
|
||||
sheep.$router.back();
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
let id = 0;
|
||||
if (options.id) {
|
||||
id = options.id;
|
||||
}
|
||||
// TODO 芋艿:下面两个变量,后续接入
|
||||
state.comeinType = options.comein_type;
|
||||
if (state.comeinType === 'wechat') {
|
||||
state.merchantTradeNo = options.merchant_trade_no;
|
||||
}
|
||||
await getOrderDetail(id);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.score-img {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
|
||||
.apply-btn {
|
||||
width: 140rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
border: 2rpx solid #dcdcdc;
|
||||
line-height: normal;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.state-box {
|
||||
color: rgba(#fff, 0.9);
|
||||
width: 100%;
|
||||
background: v-bind(headerBg) no-repeat,
|
||||
linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
background-size: 750rpx 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.state-img {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.order-address-box {
|
||||
background-color: #fff;
|
||||
border-radius: 10rpx;
|
||||
margin: -50rpx 20rpx 16rpx 20rpx;
|
||||
padding: 44rpx 34rpx 42rpx 20rpx;
|
||||
font-size: 30rpx;
|
||||
box-sizing: border-box;
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
|
||||
.address-username {
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.address-detail {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: rgba(153, 153, 153, 1);
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-goods {
|
||||
border-radius: 10rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
|
||||
.order-list {
|
||||
margin-bottom: 20rpx;
|
||||
background-color: #fff;
|
||||
|
||||
.order-card {
|
||||
padding: 20rpx 0;
|
||||
|
||||
.order-sku {
|
||||
font-size: 24rpx;
|
||||
|
||||
font-weight: 400;
|
||||
color: rgba(153, 153, 153, 1);
|
||||
width: 450rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.order-num {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tag-btn {
|
||||
margin-left: 16rpx;
|
||||
font-size: 24rpx;
|
||||
height: 36rpx;
|
||||
color: var(--ui-BG-Main);
|
||||
border: 2rpx solid var(--ui-BG-Main);
|
||||
border-radius: 14rpx;
|
||||
padding: 0 4rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 订单信息。
|
||||
.notice-box {
|
||||
background: #fff;
|
||||
border-radius: 10rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
|
||||
.notice-box__head {
|
||||
font-size: 30rpx;
|
||||
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
line-height: 80rpx;
|
||||
border-bottom: 1rpx solid #dfdfdf;
|
||||
padding: 0 25rpx;
|
||||
}
|
||||
|
||||
.notice-box__content {
|
||||
padding: 20rpx;
|
||||
|
||||
.self-pickup-box {
|
||||
width: 100%;
|
||||
|
||||
.self-pickup--img {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin: 40rpx 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.notice-item,
|
||||
.notice-item--center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: normal;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.detail {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copy-btn {
|
||||
width: 100rpx;
|
||||
line-height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
padding: 0;
|
||||
background: rgba(238, 238, 238, 1);
|
||||
font-size: 22rpx;
|
||||
font-weight: 400;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
|
||||
// 订单价格信息
|
||||
.order-price-box {
|
||||
background-color: #fff;
|
||||
border-radius: 10rpx;
|
||||
padding: 20rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
|
||||
.notice-item {
|
||||
line-height: 70rpx;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.detail {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
}
|
||||
|
||||
.all-rpice-item {
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
.title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.all-price {
|
||||
font-size: 26rpx;
|
||||
font-family: OPPOSANS;
|
||||
line-height: normal;
|
||||
color: $red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 底部
|
||||
.footer-box {
|
||||
height: 100rpx;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border-radius: 10rpx;
|
||||
padding-right: 20rpx;
|
||||
|
||||
.cancel-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #eeeeee;
|
||||
border-radius: 30rpx;
|
||||
margin-right: 20rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.pay-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
font-size: 26rpx;
|
||||
border-radius: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
39
pages/order/my/index.vue
Normal file
39
pages/order/my/index.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<view class="page-app theme-light main-green font-1">
|
||||
<layout></layout>
|
||||
|
||||
<s-menu-tools />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import layout from '@/pages/order/my/components/layout.vue';
|
||||
export default {
|
||||
components: {
|
||||
layout,
|
||||
},
|
||||
props: {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-app {
|
||||
background-color: #fafafa;
|
||||
padding-bottom: 140rpx;
|
||||
height: calc(100vh);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
</style>
|
514
pages/order/my/list - 副本.vue
Normal file
514
pages/order/my/list - 副本.vue
Normal file
@@ -0,0 +1,514 @@
|
||||
<!-- 订单列表 -->
|
||||
<template>
|
||||
<s-layout title="我的订单">
|
||||
<su-sticky bgColor="#fff">
|
||||
<su-tabs
|
||||
:list="tabMaps"
|
||||
:scrollable="false"
|
||||
@change="onTabsChange"
|
||||
:current="state.currentTab"
|
||||
/>
|
||||
</su-sticky>
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/order-empty.png" text="暂无订单" />
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view
|
||||
class="bg-white order-list-card-box ss-r-10 ss-m-t-14 ss-m-20"
|
||||
v-for="order in state.pagination.list"
|
||||
:key="order.id"
|
||||
>
|
||||
<view class="order-card-header ss-flex ss-col-center ss-row-between ss-p-x-20">
|
||||
<view class="order-no">订单号:{{ order.no }}</view>
|
||||
<view class="order-state ss-font-26" :class="formatOrderColor(order)">
|
||||
{{ formatWorkerOrderStatus(order) }}
|
||||
</view>
|
||||
</view>
|
||||
<view @tap.stop="onBuy(order.items[0].spuId)" class="border-bottom" v-for="item in order.items" :key="item.id">
|
||||
<s-worker-item
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price"
|
||||
:num="item.count"
|
||||
/>
|
||||
</view>
|
||||
<view class="pay-box ss-m-t-30 ss-flex ss-row-right ss-p-r-20">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<view class="discounts-title pay-color"
|
||||
>共 {{ order.productCount }} 件商品,总金额:</view
|
||||
>
|
||||
<view class="discounts-money pay-color"> ¥{{ fen2yuan(order.payPrice) }} </view>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-card-footer ss-flex ss-col-center ss-p-x-20"
|
||||
:class="order.buttons.length > 3 ? 'ss-row-between' : 'ss-row-right'"
|
||||
>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<button
|
||||
v-if="order.buttons.includes('combination')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onOrderGroupon(order)"
|
||||
>
|
||||
拼团详情
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('detail')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onOrderDetail(order.id)"
|
||||
>
|
||||
查看详情
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('confirm')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onConfirm(order)"
|
||||
>
|
||||
确认收货
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('express')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onExpress(order.id)"
|
||||
>
|
||||
查看物流
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('cancel')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onCancel(order.id)"
|
||||
>
|
||||
取消订单
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('unpay')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onOrderDetail(order.id)"
|
||||
>
|
||||
取消订单
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('comment')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onComment(order.id)"
|
||||
>
|
||||
评价
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('delete')"
|
||||
class="delete-btn ss-reset-button"
|
||||
@tap.stop="onDelete(order.id)"
|
||||
>
|
||||
删除订单
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('pay')"
|
||||
class="tool-btn ss-reset-button ui-BG-Main-Gradient"
|
||||
@tap.stop="onPay(order.payOrderId)"
|
||||
>
|
||||
继续支付
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('buy')"
|
||||
class="tool-btn ss-reset-button ui-BG-Main-Gradient"
|
||||
@tap.stop="onBuy(order.items[0].spuId)"
|
||||
>
|
||||
再来一单
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多 -->
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
}"
|
||||
@tap="loadMore"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app';
|
||||
import {
|
||||
fen2yuan,
|
||||
formatOrderColor,
|
||||
formatWorkerOrderStatus,
|
||||
handleMyOrderButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import sheep from '@/sheep';
|
||||
import _ from 'lodash-es';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
|
||||
// 数据
|
||||
const state = reactive({
|
||||
currentTab: 0, // 选中的 tabMaps 下标
|
||||
pagination: {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 5,
|
||||
},
|
||||
loadStatus: '',
|
||||
});
|
||||
|
||||
const tabMaps = [
|
||||
{
|
||||
name: '全部',
|
||||
},
|
||||
{
|
||||
name: '待付款',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: '待服务',
|
||||
value: 10,
|
||||
},
|
||||
{
|
||||
name: '服务中',
|
||||
value: 20,
|
||||
},
|
||||
{
|
||||
name: '待评价',
|
||||
value: 30,
|
||||
},
|
||||
];
|
||||
|
||||
// 切换选项卡
|
||||
function onTabsChange(e) {
|
||||
if (state.currentTab === e.index) {
|
||||
return;
|
||||
}
|
||||
// 重头加载代码
|
||||
resetPagination(state.pagination);
|
||||
state.currentTab = e.index;
|
||||
getOrderList();
|
||||
}
|
||||
|
||||
// 订单详情
|
||||
function onOrderDetail(id) {
|
||||
sheep.$router.go('/pages/order/my/detail', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
function onBuy(id) {
|
||||
sheep.$router.go('/pages/clerk/detail/index', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 跳转拼团记录的详情
|
||||
function onOrderGroupon(order) {
|
||||
sheep.$router.go('/pages/activity/groupon/detail', {
|
||||
id: order.combinationRecordId,
|
||||
});
|
||||
}
|
||||
|
||||
// 继续支付
|
||||
function onPay(payOrderId) {
|
||||
sheep.$router.go('/pages/pay/worker/index', {
|
||||
id: payOrderId,
|
||||
});
|
||||
}
|
||||
|
||||
// 评价
|
||||
function onComment(id) {
|
||||
sheep.$router.go('/pages/goods/comment/worker/add', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 确认收货 TODO 芋艿:待测试
|
||||
async function onConfirm(order, ignore = false) {
|
||||
// 需开启确认收货组件
|
||||
// todo: 芋艿:需要后续接入微信收货组件
|
||||
// 1.怎么检测是否开启了发货组件功能?如果没有开启的话就不能在这里return出去
|
||||
// 2.如果开启了走mpConfirm方法,需要在App.vue的show方法中拿到确认收货结果
|
||||
let isOpenBusinessView = true;
|
||||
if (
|
||||
sheep.$platform.name === 'WechatMiniProgram' &&
|
||||
!isEmpty(order.wechat_extra_data) &&
|
||||
isOpenBusinessView &&
|
||||
!ignore
|
||||
) {
|
||||
mpConfirm(order);
|
||||
return;
|
||||
}
|
||||
|
||||
// 正常的确认收货流程
|
||||
const { code } = await OrderApi.receiveOrder(order.id);
|
||||
if (code === 0) {
|
||||
resetPagination(state.pagination);
|
||||
await getOrderList();
|
||||
}
|
||||
}
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// 小程序确认收货组件 TODO 芋艿:后续再接入
|
||||
function mpConfirm(order) {
|
||||
if (!wx.openBusinessView) {
|
||||
sheep.$helper.toast(`请升级微信版本`);
|
||||
return;
|
||||
}
|
||||
wx.openBusinessView({
|
||||
businessType: 'weappOrderConfirm',
|
||||
extraData: {
|
||||
merchant_id: '1481069012',
|
||||
merchant_trade_no: order.wechat_extra_data.merchant_trade_no,
|
||||
transaction_id: order.wechat_extra_data.transaction_id,
|
||||
},
|
||||
success(response) {
|
||||
console.log('success:', response);
|
||||
if (response.errMsg === 'openBusinessView:ok') {
|
||||
if (response.extraData.status === 'success') {
|
||||
onConfirm(order, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
fail(error) {
|
||||
console.log('error:', error);
|
||||
},
|
||||
complete(result) {
|
||||
console.log('result:', result);
|
||||
},
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
|
||||
// 查看物流
|
||||
async function onExpress(id) {
|
||||
sheep.$router.go('/pages/order/express/log', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 取消订单
|
||||
async function onCancel(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消订单吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await OrderApi.cancelOrder(orderId);
|
||||
if (code === 0) {
|
||||
// 修改数据的状态
|
||||
let index = state.pagination.list.findIndex((order) => order.id === orderId);
|
||||
const orderInfo = state.pagination.list[index];
|
||||
orderInfo.status = 40;
|
||||
handleMyOrderButtons(orderInfo);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 删除订单
|
||||
function onDelete(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要删除订单吗?',
|
||||
success: async function (res) {
|
||||
if (res.confirm) {
|
||||
const { code } = await OrderApi.deleteOrder(orderId);
|
||||
if (code === 0) {
|
||||
// 删除数据
|
||||
let index = state.pagination.list.findIndex((order) => order.id === orderId);
|
||||
state.pagination.list.splice(index, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 获取订单列表
|
||||
async function getOrderList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { code, data } = await OrderApi.getOrderPage({
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize,
|
||||
status: tabMaps[state.currentTab].value,
|
||||
commentStatus: tabMaps[state.currentTab].value === 30 ? false : null,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
data.list.forEach((order) => handleMyOrderButtons(order));
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
if (options.type) {
|
||||
state.currentTab = options.type;
|
||||
}
|
||||
await getOrderList();
|
||||
});
|
||||
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
state.pagination.pageNo++;
|
||||
getOrderList();
|
||||
}
|
||||
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
|
||||
// 下拉刷新
|
||||
onPullDownRefresh(() => {
|
||||
resetPagination(state.pagination);
|
||||
getOrderList();
|
||||
setTimeout(function () {
|
||||
uni.stopPullDownRefresh();
|
||||
}, 800);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.score-img {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
|
||||
.tool-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #f6f6f6;
|
||||
font-size: 26rpx;
|
||||
border-radius: 30rpx;
|
||||
margin-right: 10rpx;
|
||||
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
width: 160rpx;
|
||||
height: 56rpx;
|
||||
color: #ff3000;
|
||||
background: #fee;
|
||||
border-radius: 28rpx;
|
||||
font-size: 26rpx;
|
||||
margin-right: 10rpx;
|
||||
line-height: normal;
|
||||
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.apply-btn {
|
||||
width: 140rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
border: 2rpx solid #dcdcdc;
|
||||
line-height: normal;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.swiper-box {
|
||||
flex: 1;
|
||||
|
||||
.swiper-item {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.order-list-card-box {
|
||||
.order-card-header {
|
||||
height: 80rpx;
|
||||
|
||||
.order-no {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.order-state {
|
||||
}
|
||||
}
|
||||
|
||||
.pay-box {
|
||||
.discounts-title {
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.discounts-money {
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
color: #999;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.pay-color {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.order-card-footer {
|
||||
height: 100rpx;
|
||||
|
||||
.more-item-box {
|
||||
padding: 20rpx;
|
||||
|
||||
.more-item {
|
||||
height: 60rpx;
|
||||
|
||||
.title {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.more-btn {
|
||||
color: $dark-9;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 154rpx;
|
||||
color: #333333;
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.uni-tooltip-popup) {
|
||||
background: var(--ui-BG);
|
||||
}
|
||||
|
||||
.warning-color {
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
.danger-color {
|
||||
color: #ff3000;
|
||||
}
|
||||
|
||||
.success-color {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.info-color {
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
45
pages/order/my/list.vue
Normal file
45
pages/order/my/list.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<view class="page-app theme-light main-green font-1">
|
||||
<layout ref="order"></layout>
|
||||
|
||||
<s-menu-tools />
|
||||
<s-auth-modal />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import layout from '@/pages/order/my/components/layout.vue';
|
||||
export default {
|
||||
components: {
|
||||
layout,
|
||||
},
|
||||
props: {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentIndex: 0,
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
if (options.type) {
|
||||
this.currentIndex = options.type;
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.$refs.order.tabChange(this.currentIndex);
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-app {
|
||||
background-color: #fafafa;
|
||||
padding-bottom: 140rpx;
|
||||
height: calc(100vh);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
</style>
|
261
pages/order/pickUpVerify.vue
Normal file
261
pages/order/pickUpVerify.vue
Normal file
@@ -0,0 +1,261 @@
|
||||
<template>
|
||||
<view class='order-details'>
|
||||
<!-- 自提商品核销 -->
|
||||
<view v-if="orderInfo.deliveryType === 2 && orderInfo.payStatus" class="writeOff borRadius14">
|
||||
<view class="title">核销信息</view>
|
||||
<view class="grayBg flex-center">
|
||||
<view class="pictrue">
|
||||
<image
|
||||
v-if="!!painterImageUrl"
|
||||
:src="painterImageUrl"
|
||||
:style="{width: `${state.qrcodeSize}px`, height: `${state.qrcodeSize}px`}"
|
||||
:show-menu-by-longpress="true"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="gear">
|
||||
<image :src="sheep.$url.static('/static/images/writeOff.png', 'local')"></image>
|
||||
</view>
|
||||
<view class="num">{{ orderInfo.pickUpVerifyCode }}</view>
|
||||
<view class="rules">
|
||||
<!-- TODO puhui999: 需要后端放回:使用 receiveTime 即可 -->
|
||||
<!-- <view class="item">-->
|
||||
<!-- <view class="rulesTitle flex flex-wrap align-center">-->
|
||||
<!-- 核销时间-->
|
||||
<!-- </view>-->
|
||||
<!-- <view class="info">-->
|
||||
<!-- 每日:-->
|
||||
<!-- <text class="time">2020-2-+52</text>-->
|
||||
<!-- </view>-->
|
||||
<!-- </view>-->
|
||||
<view class="item">
|
||||
<view class="rulesTitle flex flex-wrap align-center">
|
||||
<text class="iconfont icon-shuoming1"></text>
|
||||
使用说明
|
||||
</view>
|
||||
<view class="info">可将二维码出示给店员扫描或提供数字核销码</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="orderInfo.deliveryType === 2" class="map flex flex-wrap align-center ss-row-between borRadius14">
|
||||
<view>自提地址信息</view>
|
||||
<view class="place cart-color flex flex-wrap flex-center" @tap="showMaoLocation">
|
||||
查看位置
|
||||
</view>
|
||||
</view>
|
||||
<!-- 海报画板:默认隐藏只用来生成海报。生成方式为主动调用 -->
|
||||
<l-painter
|
||||
v-if="showPainter"
|
||||
isCanvasToTempFilePath
|
||||
pathType="url"
|
||||
@success="setPainterImageUrl"
|
||||
hidden
|
||||
ref="painterRef"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { reactive, ref } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
orderInfo: {
|
||||
type: Object,
|
||||
default() {},
|
||||
},
|
||||
systemStore:{
|
||||
type: Object,
|
||||
default() {},
|
||||
}
|
||||
});
|
||||
const state = reactive({
|
||||
qrcodeSize: 145
|
||||
})
|
||||
|
||||
/**
|
||||
* 打开地图
|
||||
*/
|
||||
const showMaoLocation = () => {
|
||||
console.log(props.systemStore);
|
||||
if (!props.systemStore.latitude || !props.systemStore.longitude) {
|
||||
sheep.$helper.toast('缺少经纬度信息无法查看地图!');
|
||||
return
|
||||
}
|
||||
uni.openLocation({
|
||||
latitude: props.systemStore.latitude,
|
||||
longitude: props.systemStore.longitude,
|
||||
scale: 8,
|
||||
name: props.systemStore.name,
|
||||
address: props.systemStore.areaName + props.systemStore.detailAddress,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 拨打电话
|
||||
*/
|
||||
const makePhone = () => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: props.systemStore.phone
|
||||
})
|
||||
}
|
||||
|
||||
const painterRef = ref(); // 海报画板
|
||||
const painterImageUrl = ref(); // 海报 url
|
||||
const showPainter = ref(true)
|
||||
// 渲染海报
|
||||
const renderPoster = async (poster) => {
|
||||
await painterRef.value.render(poster);
|
||||
};
|
||||
// 获得生成的图片
|
||||
const setPainterImageUrl = (path) => {
|
||||
painterImageUrl.value = path;
|
||||
showPainter.value = false
|
||||
};
|
||||
/**
|
||||
* 生成核销二维码
|
||||
*/
|
||||
const markCode = (text) => {
|
||||
renderPoster({
|
||||
css: {
|
||||
width: `${state.qrcodeSize}px`,
|
||||
height: `${state.qrcodeSize}px`
|
||||
},
|
||||
views:[
|
||||
{
|
||||
type: 'qrcode',
|
||||
text: text,
|
||||
css: {
|
||||
width: `${state.qrcodeSize}px`,
|
||||
height: `${state.qrcodeSize}px`
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
defineExpose({
|
||||
markCode
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
// TODO puhui999: 样式需要调整有 bug
|
||||
.borRadius14 {
|
||||
border-radius: 14rpx !important;
|
||||
}
|
||||
.cart-color {
|
||||
color: #E93323 !important;
|
||||
border: 1px solid #E93323 !important
|
||||
}
|
||||
.order-details{
|
||||
border-radius: 10rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
}
|
||||
.order-details .writeOff {
|
||||
background-color: #fff;
|
||||
margin-top: 15rpx;
|
||||
padding-bottom: 50rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .title {
|
||||
font-size: 30rpx;
|
||||
color: #282828;
|
||||
height: 87rpx;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
padding: 0 24rpx;
|
||||
line-height: 87rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .grayBg {
|
||||
background-color: #f2f5f7;
|
||||
width: 590rpx;
|
||||
height: 384rpx;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
margin: 50rpx auto 0 auto;
|
||||
padding-top: 55rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .grayBg .pictrue {
|
||||
width: 290rpx;
|
||||
height: 290rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .grayBg .pictrue image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.order-details .writeOff .gear {
|
||||
width: 590rpx;
|
||||
height: 30rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.order-details .writeOff .gear image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.order-details .writeOff .num {
|
||||
background-color: #f0c34c;
|
||||
width: 590rpx;
|
||||
height: 84rpx;
|
||||
color: #282828;
|
||||
font-size: 48rpx;
|
||||
margin: 0 auto;
|
||||
border-radius: 0 0 20rpx 20rpx;
|
||||
text-align: center;
|
||||
padding-top: 4rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules {
|
||||
margin: 46rpx 30rpx 0 30rpx;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
padding-top: 10rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules .item {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules .item .rulesTitle {
|
||||
font-size: 28rpx;
|
||||
color: #282828;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules .item .rulesTitle .iconfont {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
margin-right: 8rpx;
|
||||
margin-top: 5rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules .item .info {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
margin-top: 7rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules .item .info .time {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.order-details .map {
|
||||
height: 86rpx;
|
||||
font-size: 30rpx;
|
||||
color: #282828;
|
||||
line-height: 86rpx;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
margin-top: 15rpx;
|
||||
background-color: #fff;
|
||||
padding: 0 24rpx;
|
||||
}
|
||||
|
||||
.order-details .map .place {
|
||||
font-size: 26rpx;
|
||||
width: 176rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
line-height: 50rpx;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
93
pages/order/receive/components/layout.vue
Normal file
93
pages/order/receive/components/layout.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<!-- 虚拟列表演示(不使用内置列表)(vue) -->
|
||||
<!-- 写法较简单,在页面中对当前需要渲染的虚拟列表数据进行for循环,在vue3中兼容性良好 -->
|
||||
<!-- 在各平台兼容性请查阅https://z-paging.zxlee.cn/module/virtual-list.html -->
|
||||
<template>
|
||||
<view class="content">
|
||||
<!-- 如果页面中的cell高度是固定不变的,则不需要设置cell-height-mode,如果页面中高度是动态改变的,则设置cell-height-mode="dynamic" -->
|
||||
<!-- 原先的v-model修改为@virtualListChange="virtualListChange"并赋值处理后的虚拟列表 -->
|
||||
<z-paging ref="paging" use-virtual-list :force-close-inner-list="true" :paging-style="{ paddingTop: 0 + 'px', paddingBottom: paddingBottom + 'rpx' }" cell-height-mode="dynamic" @scroll="scroll" @virtualListChange="virtualListChange" @query="queryList">
|
||||
<!-- 需要固定在顶部不滚动的view放在slot="top"的view中,如果需要跟着滚动,则不要设置slot="top" -->
|
||||
<template #top>
|
||||
<su-navbar :title="title" statusBar></su-navbar>
|
||||
<tab-box></tab-box>
|
||||
</template>
|
||||
|
||||
<!-- :id="`zp-id-${item.zp_index}`"和:key="item.zp_index" 必须写,必须写!!!! -->
|
||||
<!-- 这里for循环的index不是数组中真实的index了,请使用item.zp_index获取真实的index -->
|
||||
<order-list :virtualList="virtualList"></order-list>
|
||||
|
||||
</z-paging>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TabBox from '@/pages/order/receive/components/tabBox.vue';
|
||||
import OrderList from '@/pages/order/receive/components/orderList.vue';
|
||||
import UserApi from '@/sheep/api/member/user';
|
||||
export default {
|
||||
components: {
|
||||
TabBox,
|
||||
OrderList,
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '接单中心',
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 虚拟列表数组,通过@virtualListChange监听获得最新数组
|
||||
virtualList: [],
|
||||
scrollTop: 0,
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
height: 0,
|
||||
|
||||
current: 0,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initNav(e) {
|
||||
this.height = e.height;
|
||||
this.paddingTop = this.height;
|
||||
},
|
||||
scroll(e) {
|
||||
this.scrollTop = e.detail.scrollTop;
|
||||
},
|
||||
// 监听虚拟列表数组改变并赋值给virtualList进行重新渲染
|
||||
virtualListChange(vList) {
|
||||
this.virtualList = vList;
|
||||
},
|
||||
queryList(pageNo, pageSize) {
|
||||
// 组件加载时会自动触发此方法,因此默认页面加载时会自动触发,无需手动调用
|
||||
// 这里的pageNo和pageSize会自动计算好,直接传给服务器即可
|
||||
// 模拟请求服务器获取分页数据,请替换成自己的网络请求
|
||||
const params = {
|
||||
pageNo: pageNo,
|
||||
pageSize: pageSize,
|
||||
random: this.tabIndex === 1
|
||||
}
|
||||
UserApi.getUserPage(params).then(res => {
|
||||
// 将请求的结果数组传递给z-paging
|
||||
this.$refs.paging.complete(res.data.list);
|
||||
}).catch(res => {
|
||||
// 如果请求失败写this.$refs.paging.complete(false);
|
||||
// 注意,每次都需要在catch中写这句话很麻烦,z-paging提供了方案可以全局统一处理
|
||||
// 在底层的网络请求抛出异常时,写uni.$emit('z-paging-error-emit');即可
|
||||
this.$refs.paging.complete(false);
|
||||
})
|
||||
},
|
||||
change(e) {
|
||||
this.current = e;
|
||||
this.scrollTop = 0;
|
||||
this.$refs.paging.reload();
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
163
pages/order/receive/components/orderList.vue
Normal file
163
pages/order/receive/components/orderList.vue
Normal file
@@ -0,0 +1,163 @@
|
||||
<template>
|
||||
<view @click="detail(item)" :id="`zp-id-${item.zp_index}`" :key="item.zp_index" v-for="(item,index) in virtualList" class="order-card">
|
||||
<view class="no-box">
|
||||
<view class="order-no">
|
||||
<u-icon name="order"></u-icon>
|
||||
<text class="number">123213123123</text>
|
||||
</view>
|
||||
<view class="status">待服务</view>
|
||||
</view>
|
||||
|
||||
<view class="main-box">
|
||||
<u-avatar size="100" src="http://cos.duopei.feiniaowangluo.com/34/clerk/1720278125689P34fP9MU1c.jpg?imageView2/1/w/200/h/200"></u-avatar>
|
||||
<view class="right-box">
|
||||
<view class="nickname-box">
|
||||
<view class="nickname">碎冰冰</view>
|
||||
<view class="info">订单时间:2024-08-10</view>
|
||||
<view class="info">服务内容:文字×1</view>
|
||||
<view class="info">
|
||||
<text class="weixin">微信:rbtnet</text>
|
||||
<u-icon name="outline-copy" custom-prefix="iconfont"></u-icon>
|
||||
</view>
|
||||
<view class="info">剩余时间:已结束</view>
|
||||
<view class="info">取消原因:</view>
|
||||
</view>
|
||||
<view class="price-box">
|
||||
<text class="price">5.00</text>
|
||||
<text>/钻</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-box">
|
||||
<view class="btn-box">
|
||||
<view class="btn active">结束服务</view>
|
||||
<view class="btn">取消接单</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
components: {
|
||||
|
||||
},
|
||||
props: {
|
||||
virtualList: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order-card {
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
|
||||
.no-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
padding-bottom: 10px;
|
||||
color: rgb(100, 101, 102);
|
||||
|
||||
.order-no {
|
||||
|
||||
.number {
|
||||
margin-left: 5px;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.status {
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.main-box {
|
||||
display: flex;
|
||||
padding: 10px 0;
|
||||
border-top: 1px solid #fbf0f0;
|
||||
border-bottom: 1px solid #fbf0f0;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.right-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
margin-left: 10px;
|
||||
|
||||
.nickname {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.info {
|
||||
font-size: 22rpx;
|
||||
color: rgb(100, 101, 102);
|
||||
line-height: 22rpx;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.weixin {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.price-box {
|
||||
font-size: 22rpx;
|
||||
color: rgb(100, 101, 102);
|
||||
|
||||
.price {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-box {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
.btn-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: #ddd;
|
||||
color: rgb(100, 101, 102);
|
||||
font-size: 22rpx;
|
||||
border-radius: 40px;
|
||||
padding: 5px 10px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.active {
|
||||
background-color: var(--ui-BG-Main);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
49
pages/order/receive/components/tabBox.vue
Normal file
49
pages/order/receive/components/tabBox.vue
Normal file
@@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<view>
|
||||
<u-tabs :list="list" bg-color="#fff" font-size="28" active-color="var(--ui-BG-Main)" :is-scroll="false" v-model="current" @change="change"></u-tabs>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
components: {
|
||||
|
||||
},
|
||||
props: {
|
||||
currentValue: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: [{
|
||||
name: '全部'
|
||||
}, {
|
||||
name: '待接单'
|
||||
}, {
|
||||
name: '服务中',
|
||||
}, {
|
||||
name: '已完成',
|
||||
}],
|
||||
|
||||
current: 0,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.current = this.currentValue;
|
||||
},
|
||||
methods: {
|
||||
change(index) {
|
||||
this.$emit('change', index);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tab-box {
|
||||
background-color: #fff;
|
||||
padding: 5px 0;
|
||||
}
|
||||
</style>
|
39
pages/order/receive/index.vue
Normal file
39
pages/order/receive/index.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<view class="page-app theme-light main-green font-1">
|
||||
<layout></layout>
|
||||
|
||||
<s-menu-tools />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import layout from '@/pages/order/receive/components/layout.vue';
|
||||
export default {
|
||||
components: {
|
||||
layout,
|
||||
},
|
||||
props: {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-app {
|
||||
background-color: #fafafa;
|
||||
padding-bottom: 140rpx;
|
||||
height: calc(100vh);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
</style>
|
318
pages/order/worker/aftersale/apply.vue
Normal file
318
pages/order/worker/aftersale/apply.vue
Normal file
@@ -0,0 +1,318 @@
|
||||
<!-- 售后申请 -->
|
||||
<template>
|
||||
<s-layout title="取消接单">
|
||||
<!-- 售后商品 -->
|
||||
<view class="goods-box">
|
||||
<s-goods-item
|
||||
:img="state.item.picUrl"
|
||||
:title="state.item.spuName"
|
||||
:skuText="state.item.properties?.map((property) => property.valueName).join(' ')"
|
||||
:price="state.item.price"
|
||||
:num="state.item.count"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<uni-forms ref="form" v-model="formData" :rules="rules" label-position="top">
|
||||
|
||||
<!-- 退款金额 -->
|
||||
<view class="refund-item ss-flex ss-col-center ss-row-between" @tap="state.showModal = true">
|
||||
<text class="item-title">退款金额</text>
|
||||
<view class="ss-flex refund-cause ss-col-center">
|
||||
<text class="ss-m-r-20">¥{{ fen2yuan(state.item.payPrice) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 留言 -->
|
||||
<view class="refund-item">
|
||||
<view class="item-title ss-m-b-20">取消原因</view>
|
||||
<view class="describe-box">
|
||||
<uni-easyinput
|
||||
:inputBorder="false"
|
||||
class="describe-content"
|
||||
type="textarea"
|
||||
maxlength="120"
|
||||
autoHeight
|
||||
v-model="formData.applyDescription"
|
||||
placeholder="如果因为个人原因暂时无法接单,建议先添加老板约定其它服务时间~"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</uni-forms>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<su-fixed bottom placeholder>
|
||||
<view class="foot-wrap">
|
||||
<view class="foot_box ss-flex ss-col-center ss-row-between ss-p-x-30">
|
||||
<button class="ss-reset-button contcat-btn" @tap="sheep.$router.go('/pages/chat/index')">
|
||||
联系客服
|
||||
</button>
|
||||
<button class="ss-reset-button ui-BG-Main-Gradient sub-btn" @tap="submit">提交</button>
|
||||
</view>
|
||||
</view>
|
||||
</su-fixed>
|
||||
|
||||
<!-- 申请原因弹窗 -->
|
||||
<su-popup :show="state.showModal" round="10" :showClose="true" @close="state.showModal = false">
|
||||
<view class="modal-box page_box">
|
||||
<view class="modal-head item-title head_box ss-flex ss-row-center ss-col-center">
|
||||
申请原因
|
||||
</view>
|
||||
<view class="modal-content content_box">
|
||||
<radio-group @change="onChange">
|
||||
<label class="radio ss-flex ss-col-center" v-for="item in state.reasonList" :key="item">
|
||||
<view class="ss-flex-1 ss-p-20">{{ item }}</view>
|
||||
<radio
|
||||
:value="item"
|
||||
color="var(--ui-BG-Main)"
|
||||
:checked="item === state.currentValue"
|
||||
/>
|
||||
</label>
|
||||
</radio-group>
|
||||
</view>
|
||||
<view class="modal-foot foot_box ss-flex ss-row-center ss-col-center">
|
||||
<button class="ss-reset-button close-btn ui-BG-Main-Gradient" @tap="onReason">
|
||||
确定
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</su-popup>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive, ref } from 'vue';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import TradeConfigApi from '@/sheep/api/trade/config';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import AfterSaleApi from '@/sheep/api/trade/afterSale';
|
||||
import { WxaSubscribeTemplate } from '@/sheep/util/const';
|
||||
|
||||
const form = ref(null);
|
||||
const state = reactive({
|
||||
orderId: 0, // 订单编号
|
||||
itemId: 0, // 订单项编号
|
||||
order: {}, // 订单
|
||||
item: {}, // 订单项
|
||||
config: {}, // 交易配置
|
||||
|
||||
// 售后类型
|
||||
wayList: [
|
||||
{
|
||||
text: '仅退款',
|
||||
value: '10',
|
||||
},
|
||||
{
|
||||
text: '退款退货',
|
||||
value: '20',
|
||||
},
|
||||
],
|
||||
reasonList: [], // 可选的申请原因数组
|
||||
showModal: false, // 是否显示申请原因弹窗
|
||||
currentValue: '', // 当前选择的售后原因
|
||||
});
|
||||
let formData = reactive({
|
||||
way: '',
|
||||
applyReason: '',
|
||||
applyDescription: '',
|
||||
images: [],
|
||||
});
|
||||
const rules = reactive({});
|
||||
|
||||
// 提交表单
|
||||
async function submit() {
|
||||
if(!formData.applyDescription){
|
||||
sheep.$helper.toast(`请输入取消原因`);
|
||||
return;
|
||||
}
|
||||
|
||||
let data = {
|
||||
orderItemId: state.itemId,
|
||||
refundPrice: state.item.payPrice,
|
||||
...formData,
|
||||
};
|
||||
const { code } = await AfterSaleApi.createAfterSale(data);
|
||||
if (code === 0) {
|
||||
uni.showToast({
|
||||
title: '申请成功',
|
||||
});
|
||||
sheep.$router.go('/pages/order/worker/list');
|
||||
}
|
||||
}
|
||||
|
||||
// 选择售后类型
|
||||
function onRefundChange(e) {
|
||||
formData.way = e;
|
||||
// 清理理由
|
||||
state.reasonList =
|
||||
formData.way === '10'
|
||||
? state.config.afterSaleRefundReasons || []
|
||||
: state.config.afterSaleReturnReasons || [];
|
||||
formData.applyReason = '';
|
||||
state.currentValue = '';
|
||||
}
|
||||
|
||||
// 选择申请原因
|
||||
function onChange(e) {
|
||||
state.currentValue = e.detail.value;
|
||||
}
|
||||
|
||||
// 确定
|
||||
function onReason() {
|
||||
formData.applyReason = state.currentValue;
|
||||
state.showModal = false;
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
// 解析参数
|
||||
if (!options.orderId || !options.itemId) {
|
||||
sheep.$helper.toast(`缺少订单信息,请检查`);
|
||||
return;
|
||||
}
|
||||
state.orderId = options.orderId;
|
||||
state.itemId = parseInt(options.itemId);
|
||||
|
||||
// 读取订单信息
|
||||
const { code, data } = await OrderApi.getOrder(state.orderId);
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.order = data;
|
||||
state.item = data.items.find((item) => item.id === state.itemId) || {};
|
||||
|
||||
// 设置选项
|
||||
if (state.order.status === 10) {
|
||||
state.wayList.splice(1, 1);
|
||||
}
|
||||
|
||||
// 读取配置
|
||||
state.config = (await TradeConfigApi.getTradeConfig()).data;
|
||||
|
||||
onRefundChange("10");
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.item-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
// margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
// 售后项目
|
||||
.refund-item {
|
||||
background-color: #fff;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
padding: 30rpx;
|
||||
|
||||
&:last-child {
|
||||
border: none;
|
||||
}
|
||||
|
||||
// 留言
|
||||
.describe-box {
|
||||
width: 690rpx;
|
||||
background: rgba(249, 250, 251, 1);
|
||||
padding: 30rpx;
|
||||
box-sizing: border-box;
|
||||
border-radius: 20rpx;
|
||||
|
||||
.describe-content {
|
||||
height: 200rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
// 联系方式
|
||||
.input-box {
|
||||
height: 84rpx;
|
||||
background: rgba(249, 250, 251, 1);
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-box {
|
||||
background: #fff;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.foot-wrap {
|
||||
height: 100rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.foot_box {
|
||||
height: 100rpx;
|
||||
background-color: #fff;
|
||||
|
||||
.sub-btn {
|
||||
width: 336rpx;
|
||||
line-height: 74rpx;
|
||||
border-radius: 38rpx;
|
||||
color: rgba(#fff, 0.9);
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.contcat-btn {
|
||||
width: 336rpx;
|
||||
line-height: 74rpx;
|
||||
background: rgba(238, 238, 238, 1);
|
||||
border-radius: 38rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.modal-box {
|
||||
width: 750rpx;
|
||||
// height: 680rpx;
|
||||
border-radius: 30rpx 30rpx 0 0;
|
||||
background: #fff;
|
||||
|
||||
.modal-head {
|
||||
height: 100rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.modal-foot {
|
||||
.close-btn {
|
||||
width: 710rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
color: rgba(#fff, 0.9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.success-box {
|
||||
width: 600rpx;
|
||||
padding: 90rpx 0 64rpx 0;
|
||||
|
||||
.cicon-check-round {
|
||||
font-size: 96rpx;
|
||||
color: #04b750;
|
||||
}
|
||||
|
||||
.success-title {
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.success-btn {
|
||||
width: 492rpx;
|
||||
height: 70rpx;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main-gradient), var(--ui-BG-Main));
|
||||
border-radius: 35rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
184
pages/order/worker/aftersale/list.vue
Normal file
184
pages/order/worker/aftersale/list.vue
Normal file
@@ -0,0 +1,184 @@
|
||||
<!-- 售后列表 -->
|
||||
<template>
|
||||
<s-layout title="取消列表">
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/data-empty.png" text="暂无数据" />
|
||||
<!-- 列表 -->
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view
|
||||
class="list-box ss-m-y-20"
|
||||
v-for="order in state.pagination.list"
|
||||
:key="order.id"
|
||||
@tap="sheep.$router.go('/pages/clerk/detail/index', { id: order.spuId })"
|
||||
>
|
||||
<view class="order-head ss-flex ss-col-center ss-row-between">
|
||||
<text class="no">服务单号:{{ order.no }}</text>
|
||||
<text class="state">{{ formatAfterSaleStatus(order) }}</text>
|
||||
</view>
|
||||
<s-goods-item
|
||||
:img="order.picUrl"
|
||||
:title="order.spuName"
|
||||
:skuText="order.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="order.refundPrice"
|
||||
/>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
}"
|
||||
@tap="loadMore"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash-es';
|
||||
import {
|
||||
formatAfterSaleStatus,
|
||||
formatAfterSaleStatusDescription,
|
||||
handleAfterSaleButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import AfterSaleApi from '@/sheep/api/trade/afterSale';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
|
||||
const state = reactive({
|
||||
currentTab: 0,
|
||||
showApply: false,
|
||||
pagination: {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
loadStatus: '',
|
||||
});
|
||||
|
||||
// TODO 芋艿:优化点,增加筛选
|
||||
const tabMaps = [
|
||||
{
|
||||
name: '全部',
|
||||
value: 'all',
|
||||
},
|
||||
// {
|
||||
// name: '申请中',
|
||||
// value: 'nooper',
|
||||
// },
|
||||
// {
|
||||
// name: '处理中',
|
||||
// value: 'ing',
|
||||
// },
|
||||
// {
|
||||
// name: '已完成',
|
||||
// value: 'completed',
|
||||
// },
|
||||
// {
|
||||
// name: '已拒绝',
|
||||
// value: 'refuse',
|
||||
// },
|
||||
];
|
||||
|
||||
// 切换选项卡
|
||||
function onTabsChange(e) {
|
||||
resetPagination(state.pagination);
|
||||
state.currentTab = e.index;
|
||||
getOrderList();
|
||||
}
|
||||
|
||||
// 获取售后列表
|
||||
async function getOrderList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { data, code } = await AfterSaleApi.getAfterSalePage({
|
||||
// type: tabMaps[state.currentTab].value,
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
data.list.forEach((order) => handleAfterSaleButtons(order));
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
|
||||
function onApply(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消此申请吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await AfterSaleApi.cancelAfterSale(orderId);
|
||||
if (code === 0) {
|
||||
resetPagination(state.pagination);
|
||||
await getOrderList();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
if (options.type) {
|
||||
state.currentTab = options.type;
|
||||
}
|
||||
await getOrderList();
|
||||
});
|
||||
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
state.pagination.pageNo++;
|
||||
getOrderList();
|
||||
}
|
||||
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.list-box {
|
||||
background-color: #fff;
|
||||
|
||||
.order-head {
|
||||
padding: 0 25rpx;
|
||||
height: 77rpx;
|
||||
}
|
||||
|
||||
.apply-box {
|
||||
height: 82rpx;
|
||||
|
||||
.title {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 22rpx;
|
||||
color: $dark-6;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-btn-box {
|
||||
height: 100rpx;
|
||||
|
||||
.tool-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #f6f6f6;
|
||||
border-radius: 30rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
182
pages/order/worker/components/layout.vue
Normal file
182
pages/order/worker/components/layout.vue
Normal file
@@ -0,0 +1,182 @@
|
||||
<!-- 虚拟列表演示(不使用内置列表)(vue) -->
|
||||
<!-- 写法较简单,在页面中对当前需要渲染的虚拟列表数据进行for循环,在vue3中兼容性良好 -->
|
||||
<!-- 在各平台兼容性请查阅https://z-paging.zxlee.cn/module/virtual-list.html -->
|
||||
<template>
|
||||
<view class="content">
|
||||
<!-- 如果页面中的cell高度是固定不变的,则不需要设置cell-height-mode,如果页面中高度是动态改变的,则设置cell-height-mode="dynamic" -->
|
||||
<!-- 原先的v-model修改为@virtualListChange="virtualListChange"并赋值处理后的虚拟列表 -->
|
||||
<z-paging ref="paging" :auto="false" use-virtual-list :force-close-inner-list="true" :paging-style="{ paddingTop: 0 + 'px', paddingBottom: paddingBottom + 'rpx' }" cell-height-mode="dynamic" @scroll="scroll" @virtualListChange="virtualListChange" @query="queryList">
|
||||
<!-- 需要固定在顶部不滚动的view放在slot="top"的view中,如果需要跟着滚动,则不要设置slot="top" -->
|
||||
<template #top>
|
||||
<su-navbar :title="title" statusBar></su-navbar>
|
||||
<tab-box :tabList="tabList" :currentValue="currentIndex" @change="tabChange"></tab-box>
|
||||
</template>
|
||||
|
||||
<!-- :id="`zp-id-${item.zp_index}`"和:key="item.zp_index" 必须写,必须写!!!! -->
|
||||
<!-- 这里for循环的index不是数组中真实的index了,请使用item.zp_index获取真实的index -->
|
||||
<order-list @onCancel="onCancel" @onConfirm="onConfirm" @onOrderConfirm="onOrderConfirm" :virtualList="virtualList"></order-list>
|
||||
|
||||
</z-paging>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TabBox from '@/pages/order/worker/components/tabBox.vue';
|
||||
import OrderList from '@/pages/order/worker/components/orderList.vue';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import { WxaSubscribeTemplate } from '@/sheep/util/const';
|
||||
import sheep from '@/sheep';
|
||||
import {
|
||||
formatWorkerOrderStatus,
|
||||
handleWorkerOrderButtons,
|
||||
fen2yuan,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
export default {
|
||||
components: {
|
||||
TabBox,
|
||||
OrderList,
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '接单中心',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 虚拟列表数组,通过@virtualListChange监听获得最新数组
|
||||
virtualList: [],
|
||||
scrollTop: 0,
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
height: 0,
|
||||
|
||||
tabList: [{
|
||||
name: '全部',
|
||||
}, {
|
||||
name: '待接单',
|
||||
value: 10,
|
||||
}, {
|
||||
name: '服务中',
|
||||
value: 20,
|
||||
}, {
|
||||
name: '已完成',
|
||||
value: 30,
|
||||
}],
|
||||
|
||||
currentIndex: 0,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
scroll(e) {
|
||||
this.scrollTop = e.detail.scrollTop;
|
||||
},
|
||||
// 监听虚拟列表数组改变并赋值给virtualList进行重新渲染
|
||||
virtualListChange(vList) {
|
||||
this.virtualList = vList;
|
||||
},
|
||||
queryList(pageNo, pageSize) {
|
||||
// 组件加载时会自动触发此方法,因此默认页面加载时会自动触发,无需手动调用
|
||||
// 这里的pageNo和pageSize会自动计算好,直接传给服务器即可
|
||||
// 模拟请求服务器获取分页数据,请替换成自己的网络请求
|
||||
const params = {
|
||||
pageNo: pageNo,
|
||||
pageSize: pageSize,
|
||||
status: this.tabList[this.currentIndex].value,
|
||||
//commentStatus: this.tabList[this.currentIndex].value === 30 ? false : null,
|
||||
}
|
||||
OrderApi.getWorkerOrderPage(params).then(res => {
|
||||
// 将请求的结果数组传递给z-paging
|
||||
res.data.list.forEach((order) => handleWorkerOrderButtons(order));
|
||||
res.data.list.forEach((order) => formatWorkerOrderStatus(order));
|
||||
res.data.list.forEach((order) => order.brokeragePrice = fen2yuan(order.brokeragePrice));
|
||||
this.$refs.paging.complete(res.data.list);
|
||||
}).catch(res => {
|
||||
// 如果请求失败写this.$refs.paging.complete(false);
|
||||
// 注意,每次都需要在catch中写这句话很麻烦,z-paging提供了方案可以全局统一处理
|
||||
// 在底层的网络请求抛出异常时,写uni.$emit('z-paging-error-emit');即可
|
||||
this.$refs.paging.complete(false);
|
||||
})
|
||||
},
|
||||
tabChange(e) {
|
||||
this.currentIndex = e;
|
||||
this.$refs.paging.reload();
|
||||
},
|
||||
// 取消订单
|
||||
async onCancel(orderId) {
|
||||
var that = this;
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消订单吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await OrderApi.cancelOrder(orderId);
|
||||
if (code === 0) {
|
||||
that.$refs.paging.reload();
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
// 开始接单
|
||||
async onOrderConfirm(order) {
|
||||
var that = this;
|
||||
uni.showModal({
|
||||
title: '是否开始接单',
|
||||
content: '请确认已经联系到老板',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
// 正常的确认收货流程
|
||||
const { code } = await OrderApi.deliveryOrder(order.id);
|
||||
if (code === 0) {
|
||||
that.$refs.paging.reload();
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
// 确认收货
|
||||
async onConfirm(order) {
|
||||
// #ifdef MP
|
||||
// 订阅只能由用户主动触发,只能包一层 showModal 诱导用户点击
|
||||
this.subscribeMessage();
|
||||
// #endif
|
||||
|
||||
var that = this;
|
||||
uni.showModal({
|
||||
title: '确定要结束服务么?',
|
||||
content: '请确认经过老板同意',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 正常的确认收货流程
|
||||
const { code } = await OrderApi.receiveOrder(order.id);
|
||||
if (code === 0) {
|
||||
that.$refs.paging.reload();
|
||||
}
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
},
|
||||
subscribeMessage() {
|
||||
const event = [WxaSubscribeTemplate.CLERK_ORDER];
|
||||
event.push(WxaSubscribeTemplate.REWARD_SUCCESS);
|
||||
sheep.$platform.useProvider('wechat').subscribeMessage(event, () => {
|
||||
// 订阅后记录一下订阅状态
|
||||
uni.removeStorageSync(WxaSubscribeTemplate.CLERK_ORDER);
|
||||
uni.setStorageSync(WxaSubscribeTemplate.CLERK_ORDER, '已订阅');
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
242
pages/order/worker/components/orderList.vue
Normal file
242
pages/order/worker/components/orderList.vue
Normal file
@@ -0,0 +1,242 @@
|
||||
<template>
|
||||
<view @click="onOrderDetail(order.id)" :id="`zp-id-${order.zp_index}`" :key="order.zp_index" v-for="(order,index) in orderList" class="order-card">
|
||||
<view class="no-box">
|
||||
<view class="order-no">
|
||||
<u-icon name="order"></u-icon>
|
||||
<text class="number">{{ order.no }}</text>
|
||||
</view>
|
||||
<view class="status">{{order.statusStr}}</view>
|
||||
</view>
|
||||
|
||||
<view class="main-box" v-for="item in order.items" :key="item.id">
|
||||
<view>
|
||||
<u-avatar size="100" :src="order.avatar"></u-avatar>
|
||||
</view>
|
||||
<view class="right-box">
|
||||
<view class="nickname-box">
|
||||
<view class="nickname">{{order.nickname}}</view>
|
||||
<view class="info">订单时间:{{order.createTimeStr}}</view>
|
||||
<view class="info">服务内容:{{item.spuName}} {{item.properties.map((property) => property.valueName).join(' ')}}×{{item.count}}</view>
|
||||
<view class="info">
|
||||
<text class="weixin">微信:{{order.weixin}}</text>
|
||||
<view @tap.stop="onCopy(order.weixin)">
|
||||
<u-icon name="outline-copy" custom-prefix="iconfont"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info">
|
||||
<text>剩余时间:</text>
|
||||
<view v-if="order.receiveTime">
|
||||
<text v-if="order.end">已结束</text>
|
||||
<view v-else>
|
||||
<u-count-down :timestamp="order.timestamp" format="DD天HH时mm分ss秒" @end="order.end = true"></u-count-down>
|
||||
</view>
|
||||
</view>
|
||||
<text v-else>暂未接单</text>
|
||||
</view>
|
||||
<view class="info" v-if="order.userRemark">备注:{{order.userRemark}}</view>
|
||||
<view class="info" v-if="order.cancelReason">取消原因:{{order.cancelReason}}</view>
|
||||
</view>
|
||||
<view class="price-box">
|
||||
<text class="price">{{order.brokeragePrice}}</text>
|
||||
<text>/钻</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-box">
|
||||
<view class="btn-box">
|
||||
<view v-if="order.buttons.includes('detail')" @tap.stop="onOrderDetail(order.id)" class="btn">查看详情</view>
|
||||
<view v-if="order.buttons.includes('unpay')" @tap.stop="onOrderCancel(order.id, order.items[0].id)" class="btn">取消接单</view>
|
||||
<view v-if="order.buttons.includes('cancel')" @tap.stop="onCancel(order.id)" class="btn">取消订单</view>
|
||||
<view v-if="order.buttons.includes('buy')" @tap.stop="onBuy(order.items[0].spuId)" class="btn active">再来一单</view>
|
||||
<view v-if="order.buttons.includes('comment')" @tap.stop="onComment(order.id)" class="btn active">评价</view>
|
||||
<view v-if="order.buttons.includes('pay')" @tap.stop="onPay(order.payOrderId)" class="btn active">继续支付</view>
|
||||
<view v-if="order.buttons.includes('agree')" @tap.stop="onOrderConfirm(order)" class="btn active">开始接单</view>
|
||||
<view v-if="order.buttons.includes('confirm')" @tap.stop="onConfirm(order)" class="btn active">结束服务</view>
|
||||
<view v-if="order.buttons.includes('invite')" @tap.stop="onBuy(order.items[0].spuId)" class="btn active">邀请老板</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import sheep from '@/sheep';
|
||||
import dayjs from 'dayjs';
|
||||
export default {
|
||||
components: {
|
||||
|
||||
},
|
||||
props: {
|
||||
virtualList: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
emits: ["onCancel", "onConfirm", "onOrderConfirm"],
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
orderList() {
|
||||
this.virtualList.forEach((order) => order.createTimeStr = sheep.$helper.timeFormat(order.createTime, 'yyyy-mm-dd hh:MM:ss'));
|
||||
this.virtualList.forEach((order) => order.timestamp = order.receiveTime ? sheep.$helper.parseTimeData(order.receiveTime) : 0);
|
||||
return this.virtualList;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 订单详情
|
||||
onOrderDetail(id) {
|
||||
sheep.$router.go('/pages/order/worker/detail', {
|
||||
id,
|
||||
});
|
||||
},
|
||||
onCancel(orderId) {
|
||||
this.$emit('onCancel', orderId);
|
||||
},
|
||||
onBuy(id) {
|
||||
sheep.$router.go('/pages/clerk/detail/index', {
|
||||
id,
|
||||
});
|
||||
},
|
||||
// 评价
|
||||
onComment(id) {
|
||||
sheep.$router.go('/pages/goods/comment/worker/add', {
|
||||
id,
|
||||
});
|
||||
},
|
||||
// 继续支付
|
||||
onPay(payOrderId) {
|
||||
sheep.$router.go('/pages/pay/worker/index', {
|
||||
id: payOrderId,
|
||||
});
|
||||
},
|
||||
onOrderCancel(orderId, itemId) {
|
||||
sheep.$router.go('/pages/order/worker/aftersale/apply', {
|
||||
orderId: orderId,
|
||||
itemId: itemId
|
||||
});
|
||||
},
|
||||
onOrderConfirm(order) {
|
||||
this.$emit('onOrderConfirm', order);
|
||||
},
|
||||
// 复制
|
||||
onCopy(text) {
|
||||
sheep.$helper.copyText(text);
|
||||
},
|
||||
// 确认收货
|
||||
onConfirm(order) {
|
||||
this.$emit('onConfirm', order);
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order-card {
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
|
||||
.no-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
padding-bottom: 10px;
|
||||
color: rgb(100, 101, 102);
|
||||
|
||||
.order-no {
|
||||
|
||||
.number {
|
||||
margin-left: 5px;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.status {
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.main-box {
|
||||
display: flex;
|
||||
padding: 10px 0;
|
||||
border-top: 1px solid #fbf0f0;
|
||||
border-bottom: 1px solid #fbf0f0;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.right-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
margin-left: 10px;
|
||||
|
||||
.nickname {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.info {
|
||||
font-size: 22rpx;
|
||||
color: rgb(100, 101, 102);
|
||||
line-height: 22rpx;
|
||||
margin-bottom: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.weixin {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.price-box {
|
||||
font-size: 22rpx;
|
||||
color: rgb(100, 101, 102);
|
||||
|
||||
.price {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-box {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
.btn-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: #ddd;
|
||||
color: rgb(100, 101, 102);
|
||||
font-size: 22rpx;
|
||||
border-radius: 40px;
|
||||
padding: 5px 10px;
|
||||
margin-left: 10px;
|
||||
min-width: 140rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.active {
|
||||
background-color: var(--ui-BG-Main);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
47
pages/order/worker/components/tabBox.vue
Normal file
47
pages/order/worker/components/tabBox.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<view>
|
||||
<u-tabs :list="tabList" bg-color="#fff" font-size="28" active-color="var(--ui-BG-Main)" :is-scroll="false" v-model="current" @change="change"></u-tabs>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
components: {
|
||||
|
||||
},
|
||||
props: {
|
||||
currentValue: 0,
|
||||
tabList: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
current: {
|
||||
get() {
|
||||
return this.currentValue;
|
||||
},
|
||||
set(newValue) {
|
||||
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
change(index) {
|
||||
this.$emit('change', index);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tab-box {
|
||||
background-color: #fff;
|
||||
padding: 5px 0;
|
||||
}
|
||||
</style>
|
433
pages/order/worker/confirm.vue
Normal file
433
pages/order/worker/confirm.vue
Normal file
@@ -0,0 +1,433 @@
|
||||
<template>
|
||||
<s-layout title="确认订单">
|
||||
<!-- 商品信息 -->
|
||||
<view class="order-card-box ss-m-b-14">
|
||||
<s-goods-item
|
||||
v-for="item in state.orderInfo.items"
|
||||
:key="item.skuId"
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price"
|
||||
:num="item.count"
|
||||
marginBottom="10"
|
||||
/>
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between ss-p-x-20 bg-white ss-r-10">
|
||||
<view class="item-title">订单备注</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<uni-easyinput
|
||||
maxlength="20"
|
||||
placeholder="请输入备注内容"
|
||||
v-model="state.orderPayload.remark"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 价格信息 -->
|
||||
<view class="bg-white total-card-box ss-p-20 ss-m-b-14 ss-r-10">
|
||||
<view class="total-box-content border-bottom">
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between">
|
||||
<view class="item-title">技能金额</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="item-value ss-m-r-24">
|
||||
¥{{ fen2yuan(state.orderInfo.price.totalPrice) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.type === 5"
|
||||
>
|
||||
<view class="item-title">积分抵扣</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
{{ state.pointStatus ? '剩余积分' : '当前积分' }}
|
||||
<image
|
||||
:src="sheep.$url.static('/static/img/shop/goods/score1.svg')"
|
||||
class="score-img"
|
||||
/>
|
||||
<text class="item-value ss-m-r-24">
|
||||
{{ state.pointStatus ? state.orderInfo.totalPoint - state.orderInfo.usePoint : (state.orderInfo.totalPoint || 0) }}
|
||||
</text>
|
||||
<checkbox-group @change="changeIntegral">
|
||||
<checkbox :checked='state.pointStatus' :disabled="!state.orderInfo.totalPoint || state.orderInfo.totalPoint <= 0" />
|
||||
</checkbox-group>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="isPass" class="order-item ss-flex ss-col-center ss-row-between">
|
||||
<view class="item-title">TA添加你的微信号</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<uni-easyinput
|
||||
maxlength="20"
|
||||
placeholder="请输入正确的微信号"
|
||||
v-model="state.orderInfo.weixin"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 优惠劵:只有 type = 0 普通订单(非拼团、秒杀、砍价),才可以使用优惠劵 -->
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.type === 5"
|
||||
>
|
||||
<view class="item-title">优惠券</view>
|
||||
<view class="ss-flex ss-col-center" @tap="state.showCoupon = true">
|
||||
<text class="item-value text-red" v-if="state.orderPayload.couponId > 0">
|
||||
-¥{{ fen2yuan(state.orderInfo.price.couponPrice) }}
|
||||
</text>
|
||||
<text
|
||||
class="item-value"
|
||||
:class="state.couponInfo.length > 0 ? 'text-red' : 'text-disabled'"
|
||||
v-else
|
||||
>
|
||||
{{
|
||||
state.couponInfo.length > 0 ? state.couponInfo.length + ' 张可用' : '暂无可用优惠券'
|
||||
}}
|
||||
</text>
|
||||
<text class="_icon-forward item-icon" />
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.price.discountPrice > 0"
|
||||
>
|
||||
<view class="item-title">活动优惠</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<!-- @tap="state.showDiscount = true" TODO puhui999:【折扣】后续要把优惠信息打进去 -->
|
||||
<text class="item-value text-red">
|
||||
-¥{{ fen2yuan(state.orderInfo.price.discountPrice) }}
|
||||
</text>
|
||||
<text class="_icon-forward item-icon" />
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.price.vipPrice > 0"
|
||||
>
|
||||
<view class="item-title">会员优惠</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="item-value text-red">
|
||||
-¥{{ fen2yuan(state.orderInfo.price.vipPrice) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="total-box-footer ss-font-28 ss-flex ss-row-right ss-col-center ss-m-r-28">
|
||||
<view class="total-num ss-m-r-20">
|
||||
共{{ state.orderInfo.items.reduce((acc, item) => acc + item.count, 0) }}件
|
||||
</view>
|
||||
<view>合计:</view>
|
||||
<view class="total-num text-red"> ¥{{ fen2yuan(state.orderInfo.price.payPrice) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 选择优惠券弹框 -->
|
||||
<s-coupon-select
|
||||
v-model="state.couponInfo"
|
||||
:show="state.showCoupon"
|
||||
@confirm="onSelectCoupon"
|
||||
@close="state.showCoupon = false"
|
||||
/>
|
||||
|
||||
<!-- 满额折扣弹框 TODO @puhui999:【折扣】后续要把优惠信息打进去 -->
|
||||
<s-discount-list
|
||||
v-model="state.orderInfo"
|
||||
:show="state.showDiscount"
|
||||
@close="state.showDiscount = false"
|
||||
/>
|
||||
|
||||
<!-- 底部 -->
|
||||
<su-fixed bottom :opacity="false" bg="bg-white" placeholder :noFixed="false" :index="200">
|
||||
<view class="footer-box border-top ss-flex ss-row-between ss-p-x-20 ss-col-center">
|
||||
<view class="total-box-footer ss-flex ss-col-center">
|
||||
<view class="total-num ss-font-30 text-red">
|
||||
¥{{ fen2yuan(state.orderInfo.price.payPrice) }}
|
||||
</view>
|
||||
</view>
|
||||
<button
|
||||
class="ss-reset-button ui-BG-Main-Gradient ss-r-40 submit-btn ui-Shadow-Main"
|
||||
@tap="onConfirm"
|
||||
>
|
||||
提交订单
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<qrcode-modal />
|
||||
</su-fixed>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, watch, computed } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import AddressSelection from '@/pages/order/addressSelection.vue';
|
||||
import qrcodeModal from '@/components/qrcode-modal/qrcode-modal.vue';
|
||||
import sheep from '@/sheep';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
|
||||
const isPass = computed(() => {
|
||||
return sheep.$store('user').tradeConfig.weixinEnabled;
|
||||
});
|
||||
|
||||
const state = reactive({
|
||||
orderPayload: {},
|
||||
orderInfo: {
|
||||
items: [], // 商品项列表
|
||||
price: {}, // 价格信息
|
||||
},
|
||||
showCoupon: false, // 是否展示优惠劵
|
||||
couponInfo: [], // 优惠劵列表
|
||||
showDiscount: false, // 是否展示营销活动
|
||||
// ========== 积分 ==========
|
||||
pointStatus: false, //是否使用积分
|
||||
});
|
||||
|
||||
const addressState = ref({
|
||||
addressInfo: {}, // 选择的收货地址
|
||||
deliveryType: 1, // 收货方式:1-快递配送,2-门店自提
|
||||
isPickUp: true, // 门店自提是否开启 TODO puhui999: 默认开启,看看后端有开关的话接入
|
||||
pickUpInfo: {}, // 选择的自提门店信息
|
||||
weixin: '', // 收件人名称
|
||||
receiverMobile: '', // 收件人手机
|
||||
});
|
||||
|
||||
// ========== 积分 ==========
|
||||
/**
|
||||
* 使用积分抵扣
|
||||
*/
|
||||
const changeIntegral = async () => {
|
||||
state.pointStatus = !state.pointStatus;
|
||||
await getOrderInfo();
|
||||
};
|
||||
|
||||
// 选择优惠券
|
||||
async function onSelectCoupon(couponId) {
|
||||
state.orderPayload.couponId = couponId;
|
||||
await getOrderInfo();
|
||||
state.showCoupon = false;
|
||||
}
|
||||
|
||||
// 提交订单
|
||||
function onConfirm() {
|
||||
if (isPass && !state.orderInfo.weixin) {
|
||||
sheep.$helper.toast('请填写正确的微信号');
|
||||
return;
|
||||
}
|
||||
submitOrder();
|
||||
}
|
||||
|
||||
// 创建订单&跳转
|
||||
async function submitOrder() {
|
||||
const { code, data } = await OrderApi.createWorkerOrder({
|
||||
items: state.orderPayload.items,
|
||||
couponId: state.orderPayload.couponId,
|
||||
remark: state.orderPayload.remark,
|
||||
deliveryType: addressState.value.deliveryType,
|
||||
addressId: addressState.value.addressInfo.id, // 收件地址编号
|
||||
pickUpStoreId: addressState.value.pickUpInfo.id,//自提门店编号
|
||||
weixin: state.orderInfo.weixin,// 微信名称
|
||||
receiverMobile: addressState.value.receiverMobile,// 选择门店自提时,该字段为联系人手机
|
||||
pointStatus: state.pointStatus,
|
||||
combinationActivityId: state.orderPayload.combinationActivityId,
|
||||
combinationHeadId: state.orderPayload.combinationHeadId,
|
||||
seckillActivityId: state.orderPayload.seckillActivityId,
|
||||
clerkId: state.orderPayload.clerkId,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
// 更新购物车列表,如果来自购物车
|
||||
if (state.orderPayload.items[0].cartId > 0) {
|
||||
sheep.$store('cart').getList();
|
||||
}
|
||||
|
||||
// 跳转到支付页面
|
||||
sheep.$router.redirect('/pages/pay/worker/index', {
|
||||
id: data.payOrderId,
|
||||
});
|
||||
}
|
||||
|
||||
// 检查库存 & 计算订单价格
|
||||
async function getOrderInfo() {
|
||||
// 计算价格
|
||||
const { data, code } = await OrderApi.clerkOrder({
|
||||
items: state.orderPayload.items,
|
||||
couponId: state.orderPayload.couponId,
|
||||
deliveryType: addressState.value.deliveryType,
|
||||
addressId: addressState.value.addressInfo.id, // 收件地址编号
|
||||
pickUpStoreId: addressState.value.pickUpInfo.id,//自提门店编号
|
||||
weixin: state.orderInfo.weixin,// 微信名称
|
||||
receiverMobile: addressState.value.receiverMobile,// 选择门店自提时,该字段为联系人手机
|
||||
pointStatus: state.pointStatus,
|
||||
combinationActivityId: state.orderPayload.combinationActivityId,
|
||||
combinationHeadId: state.orderPayload.combinationHeadId,
|
||||
seckillActivityId: state.orderPayload.seckillActivityId,
|
||||
clerkId: state.orderPayload.clerkId,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.orderInfo = data;
|
||||
// 设置收货地址
|
||||
if (state.orderInfo.address) {
|
||||
addressState.value.addressInfo = state.orderInfo.address;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取可用优惠券
|
||||
async function getCoupons() {
|
||||
const { code, data } = await CouponApi.getMatchCouponList(
|
||||
state.orderInfo.price.payPrice,
|
||||
state.orderInfo.items.map((item) => item.spuId),
|
||||
state.orderPayload.items.map((item) => item.skuId),
|
||||
state.orderPayload.items.map((item) => item.categoryId),
|
||||
);
|
||||
if (code === 0) {
|
||||
state.couponInfo = data;
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
if (!options.data) {
|
||||
sheep.$helper.toast('参数不正确,请检查!');
|
||||
return;
|
||||
}
|
||||
state.orderPayload = JSON.parse(options.data);
|
||||
await getOrderInfo();
|
||||
await getCoupons();
|
||||
});
|
||||
|
||||
// 使用 watch 监听地址和配送方式的变化
|
||||
watch(addressState, async (newAddress, oldAddress) => {
|
||||
// 如果收货地址或配送方式有变化,则重新计算价格
|
||||
if (newAddress.addressInfo.id !== oldAddress.addressInfo.id || newAddress.deliveryType !== oldAddress.deliveryType) {
|
||||
await getOrderInfo();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep() {
|
||||
.uni-input-wrapper {
|
||||
width: 320rpx;
|
||||
}
|
||||
|
||||
.uni-easyinput__content-input {
|
||||
font-size: 28rpx;
|
||||
height: 72rpx;
|
||||
text-align: right !important;
|
||||
padding-right: 0 !important;
|
||||
|
||||
.uni-input-input {
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
font-size: 26rpx;
|
||||
height: 32rpx;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.uni-easyinput__content {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: right !important;
|
||||
}
|
||||
}
|
||||
|
||||
.score-img {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
|
||||
.order-item {
|
||||
height: 80rpx;
|
||||
|
||||
.item-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.item-value {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.text-disabled {
|
||||
color: #bbbbbb;
|
||||
}
|
||||
|
||||
.item-icon {
|
||||
color: $dark-9;
|
||||
}
|
||||
|
||||
.remark-input {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.item-placeholder {
|
||||
color: $dark-9;
|
||||
font-size: 26rpx;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.total-box-footer {
|
||||
height: 90rpx;
|
||||
|
||||
.total-num {
|
||||
color: #333333;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-box {
|
||||
height: 100rpx;
|
||||
|
||||
.submit-btn {
|
||||
width: 240rpx;
|
||||
height: 70rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
|
||||
.goto-pay-text {
|
||||
line-height: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
width: 240rpx;
|
||||
height: 80rpx;
|
||||
font-size: 26rpx;
|
||||
background-color: #e5e5e5;
|
||||
color: $dark-9;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.cicon-checkbox {
|
||||
font-size: 36rpx;
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
|
||||
.cicon-box {
|
||||
font-size: 36rpx;
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
593
pages/order/worker/detail.vue
Normal file
593
pages/order/worker/detail.vue
Normal file
@@ -0,0 +1,593 @@
|
||||
<!-- 订单详情 -->
|
||||
<template>
|
||||
<s-layout title="订单详情" class="index-wrap" navbar="inner">
|
||||
<!-- 订单状态 TODO -->
|
||||
<view
|
||||
class="state-box ss-flex-col ss-col-center ss-row-right"
|
||||
:style="[
|
||||
{
|
||||
marginTop: '-' + Number(statusBarHeight + 88 + 22) + 'rpx',
|
||||
paddingTop: Number(statusBarHeight + 88 + 22) + 'rpx',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<view class="ss-flex ss-m-t-32 ss-m-b-20">
|
||||
<image
|
||||
v-if="
|
||||
state.orderInfo.status_code == 'unpaid' ||
|
||||
state.orderInfo.status === 10 || // 待发货
|
||||
state.orderInfo.status_code == 'nocomment'
|
||||
"
|
||||
class="state-img"
|
||||
:src="sheep.$url.static('/static/img/shop/order/order_loading.png')"
|
||||
>
|
||||
</image>
|
||||
<image
|
||||
v-if="
|
||||
state.orderInfo.status_code == 'completed' ||
|
||||
state.orderInfo.status_code == 'refund_agree'
|
||||
"
|
||||
class="state-img"
|
||||
:src="sheep.$url.static('/static/img/shop/order/order_success.png')"
|
||||
>
|
||||
</image>
|
||||
<image
|
||||
v-if="state.orderInfo.status_code == 'cancel' || state.orderInfo.status_code == 'closed'"
|
||||
class="state-img"
|
||||
:src="sheep.$url.static('/static/img/shop/order/order_close.png')"
|
||||
>
|
||||
</image>
|
||||
<image
|
||||
v-if="state.orderInfo.status_code == 'noget'"
|
||||
class="state-img"
|
||||
:src="sheep.$url.static('/static/img/shop/order/order_express.png')"
|
||||
>
|
||||
</image>
|
||||
<view class="ss-font-30">{{ formatWorkerOrderStatus(state.orderInfo) }}</view>
|
||||
</view>
|
||||
<view class="ss-font-26 ss-m-x-20 ss-m-b-70">
|
||||
{{ formatWorkerOrderStatusDescription(state.orderInfo) }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 收货地址 -->
|
||||
<view class="order-address-box" v-if="state.orderInfo.receiverAreaId > 0">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="address-username">
|
||||
{{ state.orderInfo.receiverName }}
|
||||
</text>
|
||||
<text class="address-phone">{{ state.orderInfo.receiverMobile }}</text>
|
||||
</view>
|
||||
<view class="address-detail">
|
||||
{{ state.orderInfo.receiverAreaName }} {{ state.orderInfo.receiverDetailAddress }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="detail-goods"
|
||||
:style="[{ marginTop: state.orderInfo.receiverAreaId > 0 ? '0' : '-40rpx' }]"
|
||||
>
|
||||
<!-- 订单信 -->
|
||||
<view class="order-list" v-for="item in state.orderInfo.items" :key="item.goods_id">
|
||||
<view class="order-card">
|
||||
<s-goods-item
|
||||
@tap="onGoodsDetail(item.spuId)"
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price"
|
||||
:num="item.count"
|
||||
>
|
||||
<template #tool>
|
||||
<view class="ss-flex">
|
||||
<button
|
||||
class="ss-reset-button apply-btn"
|
||||
v-if="[10, 20].includes(state.orderInfo.status) && item.afterSaleStatus === 0"
|
||||
@tap.stop="
|
||||
sheep.$router.go('/pages/order/worker/aftersale/apply', {
|
||||
orderId: state.orderInfo.id,
|
||||
itemId: item.id,
|
||||
})
|
||||
"
|
||||
>
|
||||
取消接单
|
||||
</button>
|
||||
<button
|
||||
class="ss-reset-button apply-btn"
|
||||
v-if="[0,30,40].includes(state.orderInfo.status)"
|
||||
@tap.stop="onGoodsDetail(item.spuId)"
|
||||
>
|
||||
邀请老板
|
||||
</button>
|
||||
</view>
|
||||
</template>
|
||||
<template #priceSuffix>
|
||||
<button class="ss-reset-button tag-btn" v-if="item.status_text">
|
||||
{{ item.status_text }}
|
||||
</button>
|
||||
</template>
|
||||
</s-goods-item>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 自提核销 -->
|
||||
<PickUpVerify :order-info="state.orderInfo" :systemStore="systemStore" ref="pickUpVerifyRef"></PickUpVerify>
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<view class="notice-box">
|
||||
<view class="notice-box__content">
|
||||
<view class="notice-item--center">
|
||||
<view class="ss-flex ss-flex-1">
|
||||
<text class="title">订单编号:</text>
|
||||
<text class="detail">{{ state.orderInfo.no }}</text>
|
||||
</view>
|
||||
<button class="ss-reset-button copy-btn" @tap="onCopy">复制</button>
|
||||
</view>
|
||||
<view class="notice-item">
|
||||
<text class="title">下单时间:</text>
|
||||
<text class="detail">
|
||||
{{ sheep.$helper.timeFormat(state.orderInfo.createTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="notice-item" v-if="state.orderInfo.payTime">
|
||||
<text class="title">支付时间:</text>
|
||||
<text class="detail">
|
||||
{{ sheep.$helper.timeFormat(state.orderInfo.payTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="notice-item">
|
||||
<text class="title">支付方式:</text>
|
||||
<text class="detail">{{ state.orderInfo.payChannelName || '-' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 价格信息 -->
|
||||
<view class="order-price-box">
|
||||
<view class="notice-item ss-flex ss-row-between">
|
||||
<text class="title">订单总额</text>
|
||||
<view class="ss-flex">
|
||||
<text class="detail">¥{{ fen2yuan(state.orderInfo.totalPrice) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.couponPrice > 0">
|
||||
<text class="title">优惠劵金额</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.couponPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.pointPrice > 0">
|
||||
<text class="title">积分抵扣</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.pointPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.discountPrice > 0">
|
||||
<text class="title">活动优惠</text>
|
||||
<text class="detail">¥{{ fen2yuan(state.orderInfo.discountPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.vipPrice > 0">
|
||||
<text class="title">会员优惠</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.vipPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between">
|
||||
<text class="title">用户付款</text>
|
||||
<text class="detail">¥{{ fen2yuan(state.orderInfo.payPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between">
|
||||
<text class="title">佣金比例</text>
|
||||
<text class="detail">{{state.orderInfo.brokeragePercent}}%</text>
|
||||
</view>
|
||||
<view class="notice-item all-rpice-item ss-flex ss-m-t-20">
|
||||
<text class="title">{{ state.orderInfo.payStatus ? '结算佣金' : '可得佣金' }}</text>
|
||||
<text class="detail all-price">¥{{ fen2yuan(state.orderInfo.brokeragePrice) }}</text>
|
||||
</view>
|
||||
<view
|
||||
class="notice-item all-rpice-item ss-flex ss-m-t-20"
|
||||
v-if="state.orderInfo.refundPrice > 0"
|
||||
>
|
||||
<text class="title">已退款</text>
|
||||
<text class="detail all-price">¥{{ fen2yuan(state.orderInfo.refundPrice) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import {
|
||||
fen2yuan,
|
||||
formatWorkerOrderStatus,
|
||||
formatWorkerOrderStatusDescription,
|
||||
handleOrderButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import DeliveryApi from '@/sheep/api/trade/delivery';
|
||||
import PickUpVerify from '@/pages/order/pickUpVerify.vue';
|
||||
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png');
|
||||
|
||||
const state = reactive({
|
||||
orderInfo: {},
|
||||
merchantTradeNo: '', // 商户订单号
|
||||
comeinType: '', // 进入订单详情的来源类型
|
||||
});
|
||||
|
||||
// ========== 门店自提(核销) ==========
|
||||
const systemStore = ref({}); // 门店信息
|
||||
|
||||
// 复制
|
||||
const onCopy = () => {
|
||||
sheep.$helper.copyText(state.orderInfo.no);
|
||||
};
|
||||
|
||||
// 去支付
|
||||
function onPay(payOrderId) {
|
||||
sheep.$router.go('/pages/pay/index', {
|
||||
id: payOrderId,
|
||||
});
|
||||
}
|
||||
|
||||
// 查看商品
|
||||
function onGoodsDetail(id) {
|
||||
sheep.$router.go('/pages/clerk/detail/index', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 取消订单
|
||||
async function onCancel(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消订单吗?',
|
||||
success: async function(res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await OrderApi.cancelOrder(orderId);
|
||||
if (code === 0) {
|
||||
await getOrderDetail(orderId);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 查看物流
|
||||
async function onExpress(id) {
|
||||
sheep.$router.go('/pages/order/express/log', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 确认收货
|
||||
async function onConfirm(orderId, ignore = false) {
|
||||
// 需开启确认收货组件
|
||||
// todo: 芋艿:待接入微信
|
||||
// 1.怎么检测是否开启了发货组件功能?如果没有开启的话就不能在这里return出去
|
||||
// 2.如果开启了走mpConfirm方法,需要在App.vue的show方法中拿到确认收货结果
|
||||
let isOpenBusinessView = true;
|
||||
if (
|
||||
sheep.$platform.name === 'WechatMiniProgram' &&
|
||||
!isEmpty(state.orderInfo.wechat_extra_data) &&
|
||||
isOpenBusinessView &&
|
||||
!ignore
|
||||
) {
|
||||
mpConfirm(orderId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 正常的确认收货流程
|
||||
const { code } = await OrderApi.receiveOrder(orderId);
|
||||
if (code === 0) {
|
||||
await getOrderDetail(orderId);
|
||||
}
|
||||
}
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// 小程序确认收货组件
|
||||
function mpConfirm(orderId) {
|
||||
if (!wx.openBusinessView) {
|
||||
sheep.$helper.toast(`请升级微信版本`);
|
||||
return;
|
||||
}
|
||||
wx.openBusinessView({
|
||||
businessType: 'weappOrderConfirm',
|
||||
extraData: {
|
||||
merchant_trade_no: state.orderInfo.wechat_extra_data.merchant_trade_no,
|
||||
transaction_id: state.orderInfo.wechat_extra_data.transaction_id,
|
||||
},
|
||||
success(response) {
|
||||
console.log('success:', response);
|
||||
if (response.errMsg === 'openBusinessView:ok') {
|
||||
if (response.extraData.status === 'success') {
|
||||
onConfirm(orderId, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
fail(error) {
|
||||
console.log('error:', error);
|
||||
},
|
||||
complete(result) {
|
||||
console.log('result:', result);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// 评价
|
||||
function onComment(id) {
|
||||
sheep.$router.go('/pages/goods/comment/add', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
const pickUpVerifyRef = ref();
|
||||
|
||||
async function getOrderDetail(id) {
|
||||
// 对详情数据进行适配
|
||||
let res;
|
||||
if (state.comeinType === 'wechat') {
|
||||
// TODO 芋艿:微信场景下
|
||||
res = await OrderApi.getOrder(id, {
|
||||
merchant_trade_no: state.merchantTradeNo,
|
||||
});
|
||||
} else {
|
||||
res = await OrderApi.getOrder(id);
|
||||
}
|
||||
if (res.code === 0) {
|
||||
state.orderInfo = res.data;
|
||||
handleOrderButtons(state.orderInfo);
|
||||
// 配送方式:门店自提
|
||||
if (res.data.pickUpStoreId) {
|
||||
const { data } = await DeliveryApi.getDeliveryPickUpStore(res.data.pickUpStoreId);
|
||||
systemStore.value = data || {};
|
||||
}
|
||||
if (state.orderInfo.deliveryType === 2 && state.orderInfo.payStatus) {
|
||||
pickUpVerifyRef.value && pickUpVerifyRef.value.markCode(res.data.pickUpVerifyCode);
|
||||
}
|
||||
} else {
|
||||
sheep.$router.back();
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
let id = 0;
|
||||
if (options.id) {
|
||||
id = options.id;
|
||||
}
|
||||
// TODO 芋艿:下面两个变量,后续接入
|
||||
state.comeinType = options.comein_type;
|
||||
if (state.comeinType === 'wechat') {
|
||||
state.merchantTradeNo = options.merchant_trade_no;
|
||||
}
|
||||
await getOrderDetail(id);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.score-img {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
|
||||
.apply-btn {
|
||||
width: 140rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
border: 2rpx solid #dcdcdc;
|
||||
line-height: normal;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.state-box {
|
||||
color: rgba(#fff, 0.9);
|
||||
width: 100%;
|
||||
background: v-bind(headerBg) no-repeat,
|
||||
linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
background-size: 750rpx 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.state-img {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.order-address-box {
|
||||
background-color: #fff;
|
||||
border-radius: 10rpx;
|
||||
margin: -50rpx 20rpx 16rpx 20rpx;
|
||||
padding: 44rpx 34rpx 42rpx 20rpx;
|
||||
font-size: 30rpx;
|
||||
box-sizing: border-box;
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
|
||||
.address-username {
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.address-detail {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: rgba(153, 153, 153, 1);
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-goods {
|
||||
border-radius: 10rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
|
||||
.order-list {
|
||||
margin-bottom: 20rpx;
|
||||
background-color: #fff;
|
||||
|
||||
.order-card {
|
||||
padding: 20rpx 0;
|
||||
|
||||
.order-sku {
|
||||
font-size: 24rpx;
|
||||
|
||||
font-weight: 400;
|
||||
color: rgba(153, 153, 153, 1);
|
||||
width: 450rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.order-num {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tag-btn {
|
||||
margin-left: 16rpx;
|
||||
font-size: 24rpx;
|
||||
height: 36rpx;
|
||||
color: var(--ui-BG-Main);
|
||||
border: 2rpx solid var(--ui-BG-Main);
|
||||
border-radius: 14rpx;
|
||||
padding: 0 4rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 订单信息。
|
||||
.notice-box {
|
||||
background: #fff;
|
||||
border-radius: 10rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
|
||||
.notice-box__head {
|
||||
font-size: 30rpx;
|
||||
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
line-height: 80rpx;
|
||||
border-bottom: 1rpx solid #dfdfdf;
|
||||
padding: 0 25rpx;
|
||||
}
|
||||
|
||||
.notice-box__content {
|
||||
padding: 20rpx;
|
||||
|
||||
.self-pickup-box {
|
||||
width: 100%;
|
||||
|
||||
.self-pickup--img {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin: 40rpx 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.notice-item,
|
||||
.notice-item--center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: normal;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.detail {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copy-btn {
|
||||
width: 100rpx;
|
||||
line-height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
padding: 0;
|
||||
background: rgba(238, 238, 238, 1);
|
||||
font-size: 22rpx;
|
||||
font-weight: 400;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
|
||||
// 订单价格信息
|
||||
.order-price-box {
|
||||
background-color: #fff;
|
||||
border-radius: 10rpx;
|
||||
padding: 20rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
|
||||
.notice-item {
|
||||
line-height: 70rpx;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.detail {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
}
|
||||
|
||||
.all-rpice-item {
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
.title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.all-price {
|
||||
font-size: 26rpx;
|
||||
font-family: OPPOSANS;
|
||||
line-height: normal;
|
||||
color: $red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 底部
|
||||
.footer-box {
|
||||
height: 100rpx;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border-radius: 10rpx;
|
||||
padding-right: 20rpx;
|
||||
|
||||
.cancel-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #eeeeee;
|
||||
border-radius: 30rpx;
|
||||
margin-right: 20rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.pay-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
font-size: 26rpx;
|
||||
border-radius: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
45
pages/order/worker/list.vue
Normal file
45
pages/order/worker/list.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<view class="page-app theme-light main-green font-1">
|
||||
<layout ref="order"></layout>
|
||||
|
||||
<s-menu-tools />
|
||||
<s-auth-modal />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import layout from '@/pages/order/worker/components/layout.vue';
|
||||
export default {
|
||||
components: {
|
||||
layout,
|
||||
},
|
||||
props: {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentIndex: 0,
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
if (options.type) {
|
||||
this.currentIndex = options.type;
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.$refs.order.tabChange(this.currentIndex);
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-app {
|
||||
background-color: #fafafa;
|
||||
padding-bottom: 140rpx;
|
||||
height: calc(100vh);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user