From 6422b072fcabbdffae8d85e6ed2debf971231a00 Mon Sep 17 00:00:00 2001 From: 1154079537 <1154079537@qq.com> Date: Sat, 8 Jun 2024 16:11:45 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=80=E6=AC=BE=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/shopListPopup.vue | 354 ++++++++++++++++---------------- pages/afterSales/afterSales.vue | 84 +++++--- pages/index/index.vue | 3 +- pagesOrder/order/order.vue | 262 +++++++++++++++++------ 4 files changed, 436 insertions(+), 267 deletions(-) diff --git a/components/shopListPopup.vue b/components/shopListPopup.vue index fc36a0c..3db5fa5 100644 --- a/components/shopListPopup.vue +++ b/components/shopListPopup.vue @@ -1,208 +1,212 @@ <template> - <up-popup :show="show" closeable round="10" @close="close"> - <view class="address-popup"> - <view class="head-title">提货点</view> - <view class="list-admin"> - <up-search placeholder="请输入提货点名称" @search="searchKeyword" v-model="keyword" @custom="searchKeyword"></up-search> - </view> - <scroll-view style="height: 600rpx;padding-bottom: 20rpx;" scroll-y> - <view class="list-li border" v-for="(item,index) in list" :key="index" @click="addressType=item.mer_id"> - <view class="list-li-top"> - <view class=""> - <text>{{item.mer_name}}</text> - <text v-if="index==0&&item.distance" - style="background-color: #38BE41;color: white;font-size: 18rpx;margin-left: 24rpx;padding: 0 5rpx;">距离最近</text> - <text v-if="item.distance" class="distance">步行{{item.distance}}</text> - </view> - </view> - <view class=""> - {{item.mer_address||''}} - </view> - <view style="color: #999;"> - <text v-if="item.service_phone" @click.stop="onCall(item.service_phone)">{{item.mer_real_name||''}} - {{ item.service_phone||'' }}</text> - </view> - <view class="check"> - <image style="width: 36rpx;height: 36rpx" v-if="addressType==item.mer_id" src="@/static/icon/check.png"> - </image> - <image style="width: 36rpx;height: 36rpx" v-else src="@/static/icon/n-check.png"></image> - </view> - </view> - </scroll-view> - <up-button color="#20B128" shape="circle" @click="submitAddress">确认提货点 </up-button> - </view> - <!-- <modal title="是否要拨打电话" :content="`即将拨打电话${phone}`" cancleText="取消" confirmText="拨打" :show="callShow" @close="callShow = false" + <up-popup :show="show" closeable round="10" @close="close"> + <view class="address-popup"> + <view class="head-title">提货点</view> + <view class="list-admin"> + <up-search placeholder="请输入提货点名称" @search="searchKeyword" v-model="keyword" + @custom="searchKeyword"></up-search> + </view> + <scroll-view style="height: 600rpx;padding-bottom: 20rpx;" scroll-y> + <view class="list-li border" v-for="(item,index) in list" :key="index" @click="addressType=item.mer_id"> + <view class="list-li-top"> + <view class=""> + <text>{{item.mer_name}}</text> + <text v-if="index==0&&item.distance" + style="background-color: #38BE41;color: white;font-size: 18rpx;margin-left: 24rpx;padding: 0 5rpx;">距离最近</text> + <text v-if="item.distance" class="distance">步行{{item.distance}}</text> + </view> + </view> + <view class=""> + {{item.mer_address||''}} + </view> + <view style="color: #999;"> + <text v-if="item.service_phone" + @click.stop="onCall(item.service_phone)">{{item.mer_real_name||''}} + {{ item.service_phone||'' }}</text> + </view> + <view class="check"> + <image style="width: 36rpx;height: 36rpx" v-if="addressType==item.mer_id" + src="@/static/icon/check.png"> + </image> + <image style="width: 36rpx;height: 36rpx" v-else src="@/static/icon/n-check.png"></image> + </view> + </view> + </scroll-view> + <up-button color="#20B128" shape="circle" @click="submitAddress">确认提货点 </up-button> + </view> + <!-- <modal title="是否要拨打电话" :content="`即将拨打电话${phone}`" cancleText="取消" confirmText="拨打" :show="callShow" @close="callShow = false" @change="onCall" /> --> - </up-popup> + </up-popup> </template> <script setup> - import { - ref - } from "vue"; - import modal from "@/components/modal.vue"; + import { + ref + } from "vue"; + import modal from "@/components/modal.vue"; - const addressType = ref(-1) - // const callShow = ref(false) - // const phone = ref(''); - // const mer_real_name = (e) => { - // callShow.value = true; - // phone.value = e; - // } - const onCall = (e) => { - uni.makePhoneCall({ - phoneNumber: e, - success() { - callShow.value = false - } - }) - } + const addressType = ref(-1) + // const callShow = ref(false) + // const phone = ref(''); + // const mer_real_name = (e) => { + // callShow.value = true; + // phone.value = e; + // } + const onCall = (e) => { + uni.makePhoneCall({ + phoneNumber: e, + success() { + callShow.value = false + } + }) + } - const props = defineProps({ - show: { - type: Boolean, - default: false - }, - list: { - type: Array, - default: () => [] - }, - }) + const props = defineProps({ + show: { + type: Boolean, + default: false + }, + list: { + type: Array, + default: () => [] + }, + }) - const emit = defineEmits(['close', 'change', 'search']); - const close = () => { - emit('close'); - } + const emit = defineEmits(['close', 'change', 'search']); + const close = () => { + emit('close'); + } - const submitAddress = () => { - let e = props.list.find(item => item.mer_id == addressType.value); - if (addressType.value <= 0 || !e) return uni.$u.toast('请选择提货点'); - emit('change', e); - } + const submitAddress = () => { + let e = props.list.find(item => item.mer_id == addressType.value); + if (addressType.value <= 0 || !e) return uni.$u.toast('请选择提货点'); + emit('change', e); + } - const keyword = ref('') - const searchKeyword = () => { - emit('search', keyword.value); - } + const keyword = ref('') + const searchKeyword = () => { + emit('search', keyword.value); + } - const navTo = (url) => { - uni.navigateTo({ - url: url - }) - } + const navTo = (url) => { + uni.navigateTo({ + url: url + }) + } - const setCheck = (e) => { - addressType.value = e; - } - defineExpose({ - setCheck - }) + const setCheck = (e) => { + addressType.value = e; + } + defineExpose({ + setCheck + }) </script> <style scoped lang="scss"> - .address-popup { - padding: 30rpx; + .address-popup { + padding: 30rpx; - .head-title { - font-weight: bold; - text-align: center; - margin-bottom: 20rpx; - } + .head-title { + font-weight: bold; + text-align: center; + margin-bottom: 20rpx; + padding: 20rpx; + } - .list-admin { - display: flex; - justify-content: space-between; - margin-bottom: 20rpx; + .list-admin { + display: flex; + justify-content: space-between; + margin-bottom: 20rpx; - .admin-btn { - display: flex; - color: #20B128; + .admin-btn { + display: flex; + color: #20B128; - .btn { - margin-left: 20rpx; - display: flex; - align-items: center; + .btn { + margin-left: 20rpx; + display: flex; + align-items: center; - &:active { - color: rgba(#20B128, 0.8); - transition: background-color 0.5s; - animation: disappear 0.5s 0.5s forwards; - } - } - } - } + &:active { + color: rgba(#20B128, 0.8); + transition: background-color 0.5s; + animation: disappear 0.5s 0.5s forwards; + } + } + } + } - .row { - display: flex; - align-items: center; - justify-content: space-between; - padding-bottom: 20rpx; - border-bottom: 1rpx solid #f6f6f6; - margin-bottom: 20rpx; + .row { + display: flex; + align-items: center; + justify-content: space-between; + padding-bottom: 20rpx; + border-bottom: 1rpx solid #f6f6f6; + margin-bottom: 20rpx; - &:last-child { - border-bottom: none; - margin-bottom: 0; - } + &:last-child { + border-bottom: none; + margin-bottom: 0; + } - .content { - .top { - display: flex; + .content { + .top { + display: flex; - view { - margin-right: 20rpx; - } - } + view { + margin-right: 20rpx; + } + } - .bottom {} - } + .bottom {} + } - image { - width: 40rpx; - height: 40rpx; - flex-shrink: 0; - } - } - } + image { + width: 40rpx; + height: 40rpx; + flex-shrink: 0; + } + } + } - .border { - border-bottom: 1px solid #F3F3F3; - } + .border { + border-bottom: 1px solid #F3F3F3; + } - .list-li { - padding: 30rpx 0; - font-size: 24rpx; - position: relative; + .list-li { + padding: 30rpx 0; + font-size: 24rpx; + position: relative; - .list-li-top { - display: flex; - justify-content: space-between; - margin-bottom: 10rpx; - font-size: 30rpx; - } + .list-li-top { + display: flex; + justify-content: space-between; + margin-bottom: 10rpx; + font-size: 30rpx; + } - .distance { - border: 1px solid #40AE36; - font-size: 18rpx; - color: #40AE36; - margin-left: 20rpx; - padding: 0 5rpx; - } + .distance { + border: 1px solid #40AE36; + font-size: 18rpx; + color: #40AE36; + margin-left: 20rpx; + padding: 0 5rpx; + } - .check { - position: absolute; - right: 20rpx; - top: 50%; - transform: translateY(-50%); - } - } + .check { + position: absolute; + right: 20rpx; + top: 50%; + transform: translateY(-50%); + } + } - @keyframes disappear { - to { - opacity: 0; - /* 渐隐 */ - transform: scale(0); - /* 缩小 */ - } - } + @keyframes disappear { + to { + opacity: 0; + /* 渐隐 */ + transform: scale(0); + /* 缩小 */ + } + } </style> \ No newline at end of file diff --git a/pages/afterSales/afterSales.vue b/pages/afterSales/afterSales.vue index 5903335..447ded8 100644 --- a/pages/afterSales/afterSales.vue +++ b/pages/afterSales/afterSales.vue @@ -5,30 +5,30 @@ <up-cell-group :border="false" class="cellGroup"> <up-cell title="退款原因" :value="refundForm.refund_message?refundForm.refund_message:'请选择'" titleStyle="color:#444;font-size:30rpx;" isLink :required="true" @click="show = true"></up-cell> - <up-cell title="退款件数" :border="false"> + <!-- <up-cell title="退款件数" :border="false"> <template #value> <up-number-box v-model="refundForm.refund_num"></up-number-box> </template> - </up-cell> + </up-cell> --> </up-cell-group> </view> <!-- 商品信息 --> <view class="afterSales-goods"> - <view class="afterSales-goods-wrap"> + <view class="afterSales-goods-wrap" v-for="(item,indx) in goodsList" :key="indx"> <view class="afterSales-goods-left"> - <up-image width="140rpx" height="140rpx" border="8rpx"></up-image> + <up-image width="140rpx" height="140rpx" radius="8rpx" :src="item.image" /> </view> <view class="afterSales-goods-right"> <view class="afterSales-goods-right-title"> - <text class="goods_name">黄牛牛腩</text> + <text class="goods_name">{{item.store_name}}</text> <text class="goods_price"> <text style='font-size: 24rpx;'>¥</text> - <text style="font-size: 32rpx;">10</text> + <text style="font-size: 32rpx;">{{item.price}}</text> </text> </view> <view class="afterSales-goods-right-info"> - <text class="goods_desc">牛腩块</text> + <text class="goods_desc">{{item.unit}}</text> <text class="goods_num">x5</text> </view> </view> @@ -53,11 +53,11 @@ <view class="afterSales-remark"> <view class="afterSales-remark-title"> <view class="afterSales-remark-title-txt">备注说明</view> - <view class="afterSales-remark-title-count">0/200</view> + <view class="afterSales-remark-title-count"></view> </view> <view class="afterSales-remark-textarea"> - <up-textarea :count="true"></up-textarea> + <up-textarea :count="true" v-model="refundForm.mark"></up-textarea> </view> <view class="afterSales-remark-title"> @@ -71,7 +71,7 @@ </view> <!-- btn --> - <view class="afterSales-btn"> + <view class="afterSales-btn" @click="onSubmitApply"> <view class="afterSales-btn-wrap"> <text>提交申请</text> </view> @@ -107,7 +107,8 @@ } from "vue"; import { orderListApi, - refundReasonListApi + refundReasonListApi, + applyRefundApi } from "@/api/order.js"; import { config @@ -128,10 +129,26 @@ refund_message: '', //退款原因 refund_num: '', //退款数量 id: '', //订单id - old_cart_id: '', //购物车id + old_cart_id: [], //购物车id refund_type: '', //0 仅退款 1 退款退货 2换货 + refund_reason_wap_img: '', + mark: '' + }); + const goodsList = ref([]); + + onLoad(() => { + getRefundReasonData(); + + // 上一个页面传递的售后参数 + const eventChannel = instance.getOpenerEventChannel(); + eventChannel.on('orderDetail', function(data) { + console.log(data); + refundForm.id = data.id; + refundForm.old_cart_id = data.old_cart_id; + refundForm.refund_type = data.refund_type; + goodsList.value = data.goodsList; + }) }); - const shopInfo = ref(null); // 图片上传 const fileList1 = ref([]); @@ -175,6 +192,9 @@ }, success: (res) => { setTimeout(() => { + if (typeof res.data == 'string') { + res.data = JSON.parse(res.data) + } resolve(res.data.data); }, 1000); }, @@ -182,23 +202,37 @@ }); }; - onLoad(() => { - getRefundReasonData(); - - const eventChannel = instance.getOpenerEventChannel(); - eventChannel.on('orderDetail', function(data) { - shopInfo.value = data; - refundForm.value.id = shopInfo.value.order_id; - refundForm.value.old_cart_id = shopInfo.value.cart_id; - }) - }); - - // 提交退款原因 + // 退款原因 const onSubmitReason = () => { show.value = false; refundForm.refund_message = refundType.value; } + // 申请提交 + const onSubmitApply = () => { + if (!refundForm.refund_message) return uni.$u.toast('请选择退款原因'); + let urls = []; + //图片 refund_reason_wap_img + if (fileList1.value.length > 0) { + fileList1.value.map(i => { + console.log(i.url.uri); + urls.push(i.url.uri); + }); + refundForm.refund_reason_wap_img = urls.join(','); + } + + applyRefundApi(refundForm).then(res => { + if (res.code == 1) { + uni.$u.toast(res.msg); + uni.$u.sleep(1500).then(res => { + uni.navigateBack(); + }) + } else { + uni.$u.toast(res.msg); + } + }) + } + // 取消原因列表 const refundReasonList = ref([]); const getRefundReasonData = () => { diff --git a/pages/index/index.vue b/pages/index/index.vue index 61fbff2..b6398e5 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -415,7 +415,8 @@ //统计商品的访问记录 productLogApi({ product_id: item.product_id, - cate_id: item.cate_id + cate_id: item.cate_id, + store_id: uni.getStorageSync('STORE_INFO').id || '' }); }; diff --git a/pagesOrder/order/order.vue b/pagesOrder/order/order.vue index 5e78aef..e438f0f 100644 --- a/pagesOrder/order/order.vue +++ b/pagesOrder/order/order.vue @@ -53,29 +53,51 @@ <view class="afterSales-type"> <view class="afterSales-type-title">售后类型</view> <view class="afterSales-type-con"> - <view class="afterSales-type-item">仅退款</view> - <view class="afterSales-type-item">退款退货</view> - <view class="afterSales-type-item">换货</view> + <view class="afterSales-type-item" :class="{'fuck-active':afterSalesType===0}" + @click="afterSalesType=0">仅退款</view> + <view class="afterSales-type-item" :class="{'fuck-active':afterSalesType==1}" + @click="afterSalesType=1">退款退货</view> + <view class="afterSales-type-item" :class="{'fuck-active':afterSalesType==2}" + @click="afterSalesType=2">换货</view> </view> + <view class="afterSales-type-tip" v-if="afterSalesType===0">当前售后类型仅支持未备货商品</view> + <view class="afterSales-type-tip" v-if="afterSalesType==1">当前售后类型仅支持非生鲜类商品</view> + <view class="afterSales-type-tip" v-if="afterSalesType==2">当前售后类型仅支持选择单个商品</view> </view> - - <scroll-view style="max-height: 50vh;padding-bottom: 20rpx;" scroll-y> - - - - <block v-for="(item,index) in refundReasonList" :key="index"> - <view class="row" @click="refundType = item.value"> - <view class="content"> - <view class="top"></view> - <view class="bottom u-line-2">{{item.value}}</view> + <view class="scroll-wrap"> + <scroll-view style="max-height: 50vh;padding-bottom: 20rpx;" scroll-y> + <block v-for="(item,index) in goodsList" :key="index"> + <view class="goods"> + <view class="goods-item"> + <view class="goods-item-left"> + <view class="goods-item-left-img"> + <up-image width="164rpx" height="164rpx" :src="item.image" radius="8rpx" /> + </view> + <view class="goods-item-left-info"> + <view class="goods_name">{{item.store_name}}</view> + <view class="goods_detail"> + <view class="goods-detail_num">数量{{item.cart_num}}</view> + <view class="goods_detail_price"> + <text class="symbol">¥</text> + <text class="numbers">{{item.price}}</text> + </view> + </view> + </view> + </view> + <view class="goods-item-right" @click="onChooseGoods(item)"> + <image v-if="item.isSelected" src="@/static/icon/check.png"></image> + <image v-else src="@/static/icon/n-check.png"></image> + </view> + </view> </view> - <image v-if="refundType==item.value" src="@/static/icon/check.png"></image> - <image v-else src="@/static/icon/n-check.png"></image> - </view> - </block> - </scroll-view> - <up-button color="#20B128" shape="circle" @click="onSubmitReason">提交</up-button> + </block> + </scroll-view> + </view> + <view style="height: 120rpx;display: flex;justify-content: center;padding: 0 30rpx;align-items: center;" + @click="onPageToAfterSales"> + <up-button color="#20B128" shape="circle" @click="onSubmitReason">提交</up-button> + </view> </view> </up-popup> </template> @@ -188,18 +210,58 @@ }) } - const refundShow = ref(true); + // 申请售后<!--sb项目--> + const refundShow = ref(false); + const goodsList = ref([]); // 申请售后商品 + const afterSalesType = ref(''); //申请售后类型 0 1 2 + const orderId = ref(''); // 申请售后 const applyAfterSales = (item) => { + refundShow.value = true; + goodsList.value = item.goods_list; + orderId.value = item.order_id; + } + + // 跳转到申请售后 + const onPageToAfterSales = () => { + if (afterSalesType.value === '') return uni.$u.toast('请选择售后类型'); + if (!goodsList.value || goodsList.value.length == 0) return uni.$u.toast('暂无可申请售后的商品'); + let goods = goodsList.value.find(i => i.isSelected); + if (goods == undefined) return uni.$u.toast('请选择需要申请售后的商品'); + + let ids = []; + let goodsListSel = []; + goodsList.value.map(i => { + if (i.isSelected) { + ids.push(i.old_cart_id); + goodsListSel.push(i); + } + }); + uni.navigateTo({ url: "/pages/afterSales/afterSales", success(res) { - res.eventChannel.emit('orderDetail', item) + refundShow.value = false; // close modal + res.eventChannel.emit('orderDetail', { + id: orderId.value, //订单id + old_cart_id: ids, + refund_type: afterSalesType.value, + goodsList: goodsListSel + }) } }) } + // 选择物品 + const onChooseGoods = (item) => { + if (item.hasOwnProperty('isSelected')) { + item.isSelected = !item.isSelected; + } else { + item.isSelected = true; + } + } + const rePay = (e) => { rePaymentApi({ order_id: e.id, @@ -369,68 +431,136 @@ } .address-popup { - padding: 30rpx; + // padding: 30rpx; + background-color: #F6F6F6; .head-title { font-weight: bold; text-align: center; margin-bottom: 20rpx; + padding: 20rpx; } - .list-admin { - display: flex; - justify-content: space-between; - margin-bottom: 20rpx; + .afterSales-type { + margin: 0 20rpx 20rpx; + background: #FFFFFF; + border-radius: 16rpx; + padding: 20rpx; + box-sizing: border-box; - .admin-btn { + .afterSales-type-title { + font-size: 32rpx; + color: #444444; + margin-bottom: 28rpx; + } + + .afterSales-type-con { display: flex; - color: #20B128; + align-items: center; + margin-bottom: 20rpx; - .btn { - margin-left: 20rpx; + .afterSales-type-item { + width: 200rpx; + height: 70rpx; + line-height: 70rpx; + border-radius: 12rpx; + color: #777777; + border: 2rpx solid #D3D3D3; + font-size: 28rpx; + text-align: center; + + &:not(:nth-last-child(1)) { + margin-right: 24rpx; + } + } + + .fuck-active { + color: #FC452F; + border: 2rpx solid #FC452F; + font-weight: 600; + } + } + + .afterSales-type-tip { + font-size: 20rpx; + color: #FC452F; + } + } + + .scroll-wrap { + margin: 0 20rpx; + background: #FFFFFF; + border-radius: 16rpx; + padding: 20rpx 20rpx 1rpx; + box-sizing: border-box; + + .goods { + .goods-item { display: flex; align-items: center; + justify-content: space-between; + margin-bottom: 30rpx; - &:active { - color: rgba(#20B128, 0.8); - transition: background-color 0.5s; - animation: disappear 0.5s 0.5s forwards; + .goods-item-left { + display: flex; + align-items: center; + + .goods-item-left-img { + margin-right: 20rpx; + } + + .goods-item-left-info { + display: flex; + flex-direction: column; + justify-content: space-between; + height: 164rpx; + + .goods_name { + font-size: 28rpx; + color: #060606; + max-width: 400rpx; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + .goods_detail { + display: flex; + align-items: center; + + .goods-detail_num { + margin-right: 30rpx; + font-size: 28rpx; + color: #333333; + } + + .goods_detail_price { + display: flex; + + .symbol { + align-self: flex-end; + font-size: 22rpx; + color: #333333; + } + + .numbers { + font-size: 32rpx; + color: #333333; + } + } + } + } + } + + .goods-item-right { + image { + width: 48rpx; + height: 48rpx; + } } } } } - - .row { - display: flex; - align-items: center; - justify-content: space-between; - padding-bottom: 20rpx; - border-bottom: 1rpx solid #f6f6f6; - margin-bottom: 20rpx; - - &:last-child { - border-bottom: none; - margin-bottom: 0; - } - - .content { - .top { - display: flex; - - view { - margin-right: 20rpx; - } - } - - .bottom {} - } - - image { - width: 40rpx; - height: 40rpx; - flex-shrink: 0; - } - } } @keyframes disappear {