Browse Source

add mall logic for tid1878

tid1878
刘嘉炜 5 months ago
parent
commit
2918155f6f
  1. 42
      src/pages.json
  2. 4
      src/subpackage/mall/components/index_search_bar.vue
  3. 12
      src/subpackage/mall/js/api.js
  4. 93
      src/subpackage/mall/pages/appraise_list.vue
  5. 51
      src/subpackage/mall/pages/goods_info.vue
  6. 260
      src/subpackage/mall/pages/goods_search.vue
  7. 59
      src/subpackage/mall/pages/index.vue
  8. 4
      src/subpackage/mall/pages/modules/order/order_list_item.vue
  9. 1
      src/subpackage/mall/pages/modules/order/product_info.vue
  10. 1
      src/subpackage/mall/pages/order/order_details.vue
  11. 6
      src/subpackage/mall/pages/order/order_list.vue
  12. 203
      src/subpackage/mall/pages/order/order_search.vue
  13. 143
      src/subpackage/mall/pages/order/order_share.vue
  14. 729
      src/subpackage/mall/pages/order/refund_details.vue
  15. 324
      src/subpackage/mall/pages/order/refund_list.vue
  16. 287
      src/subpackage/mall/pages/order/refund_logs.vue
  17. BIN
      src/subpackage/mall/static/images/cancel.png
  18. BIN
      src/subpackage/mall/static/images/close_c97_2.png
  19. BIN
      src/subpackage/mall/static/images/del.png
  20. BIN
      src/subpackage/mall/static/images/index/menu_1.png
  21. BIN
      src/subpackage/mall/static/images/index/menu_2.png
  22. BIN
      src/subpackage/mall/static/images/index/menu_3.png
  23. BIN
      src/subpackage/mall/static/images/price.png

42
src/pages.json

@ -1072,6 +1072,48 @@
"style" : { "style" : {
"navigationBarTitleText": "评价" "navigationBarTitleText": "评价"
} }
},
{
"path": "pages/goods_search",
"style" : {
"navigationBarTitleText": "搜索"
}
},
{
"path": "pages/appraise_list",
"style" : {
"navigationBarTitleText": "商品详情"
}
},
{
"path": "pages/order/order_share",
"style" : {
"navigationBarTitleText": "分享我的订单"
}
},
{
"path": "pages/order/order_search",
"style" : {
"navigationBarTitleText": "我的订单"
}
},
{
"path": "pages/order/refund_list",
"style" : {
"navigationBarTitleText": "售后订单"
}
},
{
"path": "pages/order/refund_details",
"style" : {
"navigationBarTitleText": "退款详情"
}
},
{
"path": "pages/order/refund_logs",
"style" : {
"navigationBarTitleText": "协商记录"
}
} }
] ]
} }

4
src/subpackage/mall/components/index_search_bar.vue

@ -1,8 +1,8 @@
<template> <template>
<view class="index-search-bar"> <view class="index-search-bar">
<view class="isb-frame">
<view class="isb-frame" @click="$emit('click:search')">
<image class="if-icon" mode="aspectFit" src="/subpackage/mall/static/images/search.png"></image> <image class="if-icon" mode="aspectFit" src="/subpackage/mall/static/images/search.png"></image>
<input class="if-ipt" />
<input class="if-ipt" disabled />
<view class="if-btn">搜索</view> <view class="if-btn">搜索</view>
</view> </view>
<view class="isb-box" v-if="shoppingCart" @click="$emit('click:scart')"> <view class="isb-box" v-if="shoppingCart" @click="$emit('click:scart')">

12
src/subpackage/mall/js/api.js

@ -42,6 +42,18 @@ export const MALL_API = {
goodsComment:`${ORIGIN}/shop2/goodsComment`, //商品评价列表 goodsComment:`${ORIGIN}/shop2/goodsComment`, //商品评价列表
goodsCommentPublish:`${ORIGIN}/shop2/goodsCommentPublish`, //商品评价 goodsCommentPublish:`${ORIGIN}/shop2/goodsCommentPublish`, //商品评价
feedbackList:`${ORIGIN}/stadium/order/feedback/list`, //售后反馈-信息列表 OrderType="product_order"
feedbackDetail:`${ORIGIN}/stadium/order/feedback/get/`, //售后反馈-信息详情
feedbackCancel:`${ORIGIN}/stadium/order/feedback/cancel/`, //售后反馈-信息撤销
feedbackDelete:`${ORIGIN}/stadium/order/feedback/del/`, //售后反馈-信息删除
goodsOrdeRefund:`${ORIGIN}/shop2/goodsOrdeRefund`, //订单 - 售后 - 申请退款
goodsOrdeRefundCancel:`${ORIGIN}/shop2/goodsOrdeRefundCancel`, //订单 - 售后 - 撤销退款申请
feedbackExpress:`${ORIGIN}/stadium/order/feedback/express`, //售后反馈-商城快递
feedbackRecords:`${ORIGIN}/stadium/order/feedback/records`, //售后反馈-协商信息
expressList:`${ORIGIN}/stadium/order/express/list`, // 物流公司列表
} }
export default { ORIGIN, MALL_API }; export default { ORIGIN, MALL_API };

93
src/subpackage/mall/pages/appraise_list.vue

@ -0,0 +1,93 @@
<template>
<view class="appraise-list">
<view class="al-name">{{ optionsQuery.product_name || '-' }}</view>
<view class="al-desc">
<view class="ad-tit">评价({{commentList.length}})</view>
<block v-for="(e,i) in commentList" :key="i">
<appraise-item
:name="e.sys_optuname"
:avater="e.sys_optuimgs"
:time="e.created_at"
:appraise="e.product_comment_text"
:level-num="e.product_comment_level"
:img-list="e.product_comment_imgs"
></appraise-item>
</block>
</view>
<view class="al-end">没有更多了</view>
</view>
</template>
<script>
import { jsonPar, showLoad, hideLoad } from '@/utils/util';
import { MALL_API } from "../js/api";
import server from "../js/server";
import appraiseItem from "../components/appraise_item.vue";
export default {
components: { appraiseItem },
data() {
return {
optionsQuery: {},
commentList: [],
}
},
onLoad(options) {
let _query = jsonPar(options.query);
this.optionsQuery = _query
this.getCommentList({
proid: _query.product_id,
brand_id: options?.brand_id ?? ''
});
},
methods: {
//
getCommentList({ brand_id, proid }) {
showLoad();
server.post({
url: MALL_API.goodsComment,
data: { brand_id, proid },
failMsg: '加载数据失败!'
})
.then(res => {
hideLoad();
console.log('商品评价列表: ', res);
this.commentList = res.list || []
});
},
}
}
</script>
<style lang="scss">
.appraise-list{
.al-name{
padding: 22rpx 24rpx;
margin-bottom: 24rpx;
background-color: #fff;
display: flex;
flex-grow: 1;
color: #333;
font-size: 32rpx;
font-weight: 700;
// @include textHide(1);
}
.al-desc{
padding: 40rpx 0;
background-color: #fff;
.ad-tit{
color: #333;
font-size: 28rpx;
margin-left: 28rpx;
}
}
.al-end{
padding: 46rpx 0;
flex-grow: 1;
color: #9A9A9D;
font-size: 28rpx;
text-align: center;
}
}
</style>

51
src/subpackage/mall/pages/goods_info.vue

@ -8,7 +8,7 @@
<image class="gb-img" mode="aspectFill" :src="e"></image> <image class="gb-img" mode="aspectFill" :src="e"></image>
</swiper-item> </swiper-item>
</swiper> </swiper>
<button class="gb-share">
<button class="gb-share" open-type="share">
<image class="gs-img" mode="aspectFit" src="/subpackage/mall/static/images/share.png"></image> <image class="gs-img" mode="aspectFit" src="/subpackage/mall/static/images/share.png"></image>
</button> </button>
<view class="gb-num" v-if="bannerNumStr">{{ bannerNumStr }}</view> <view class="gb-num" v-if="bannerNumStr">{{ bannerNumStr }}</view>
@ -76,7 +76,7 @@
<view class="gi-appraise-info"> <view class="gi-appraise-info">
<view class="gai-title-bar"> <view class="gai-title-bar">
<view class="gtb-tit">评价({{ appraiseList.length || 0 }})</view> <view class="gtb-tit">评价({{ appraiseList.length || 0 }})</view>
<view class="gtb-link">
<view class="gtb-link" @click="toAllAppraise">
<text>查看全部</text> <text>查看全部</text>
<image class="gl-icon" mode="aspectFit" src="/subpackage/mall/static/images/arrow_874.png"></image> <image class="gl-icon" mode="aspectFit" src="/subpackage/mall/static/images/arrow_874.png"></image>
</view> </view>
@ -107,11 +107,11 @@
<!-- 底部悬浮按钮 --> <!-- 底部悬浮按钮 -->
<view class="gd-fixed-bar"> <view class="gd-fixed-bar">
<view class="gfb-left"> <view class="gfb-left">
<view class="gl-box">
<view class="gl-box" @click="toIndex">
<image class="gb-icon" mode="aspectFit" src="/subpackage/mall/static/images/home.png"></image> <image class="gb-icon" mode="aspectFit" src="/subpackage/mall/static/images/home.png"></image>
<view class="gb-txt">首页</view> <view class="gb-txt">首页</view>
</view> </view>
<view class="gl-box">
<view class="gl-box" @click="toShoppingCart">
<image class="gb-icon" mode="aspectFit" src="/subpackage/mall/static/images/shopping_cart.png"></image> <image class="gb-icon" mode="aspectFit" src="/subpackage/mall/static/images/shopping_cart.png"></image>
<view class="gb-txt">购物车</view> <view class="gb-txt">购物车</view>
<view class="gb-num" v-if="goodsCartNum>0">{{ goodsCartNum }}</view> <view class="gb-num" v-if="goodsCartNum>0">{{ goodsCartNum }}</view>
@ -217,6 +217,15 @@ export default {
return '' return ''
} }
}, },
onShareAppMessage(res) {
let { goodsInfo } = this;
let url = `/subpackage/mall/pages/goods_info?id=${goodsInfo?.id ?? ''}&brand_id=${goodsInfo?.brand_id ?? ''}`;
return {
title: goodsInfo.product_name ?? '',
path: url,
imageUrl: goodsInfo?.product_imgs?.[0] ?? ''
}
},
onLoad(options){ onLoad(options){
let _bid = options?.brand_id ?? ''; let _bid = options?.brand_id ?? '';
this.getGoodsInfo({ this.getGoodsInfo({
@ -230,6 +239,40 @@ export default {
}); });
}, },
methods: { methods: {
//
toAllAppraise(){
let { goodsInfo } = this;
let _query = {};
_query['product_name'] = goodsInfo.product_name;
_query['product_id'] = goodsInfo.id;
routeTo(`/subpackage/mall/pages/appraise_list?query=${jsonStr(_query)}&brand_id=${goodsInfo?.brand_id ?? ''}`, 'nT');
},
toIndex(){
let { goodsInfo } = this;
this.checkPagesForNavigate({ path: 'subpackage/mall/pages/index', qryStr: `brand_id=${goodsInfo?.brand_id}` });
},
toShoppingCart(){
let { goodsInfo } = this;
this.checkPagesForNavigate({ path: 'subpackage/mall/pages/shopping_cart', qryStr: `brand_id=${goodsInfo?.brand_id}` });
},
// zhang
/**
* @param {String} path 路由路径
* @param {String} qryStr 路由参数
* @param {String} methods 路由跳转方式
* */
checkPagesForNavigate({ path, qryStr = '', methods = 'nT' }){
let _pageLs = getCurrentPages();
let _pathLs = _pageLs.map(e=>e.route);
let _pathIdx = _pathLs.indexOf(path);
if(_pathIdx >= 0){
uni.navigateBack({ delta: _pageLs.length - (_pathIdx + 1) });
}else{
let _path = '/' + path + (qryStr ? '?' + qryStr : '');
routeTo(_path, methods);
}
},
//
specificationLineClick(){ specificationLineClick(){
let { goodsInfo, getQueryForSpecificationModal } = this; let { goodsInfo, getQueryForSpecificationModal } = this;
let _sModalRef = this.$refs.specificationModal; let _sModalRef = this.$refs.specificationModal;

260
src/subpackage/mall/pages/goods_search.vue

@ -0,0 +1,260 @@
<template>
<view class="goods-search" :class="{bgChange: searchText!=''}">
<view class="gs-head">
<view class="gh-ipt">
<image v-if="searchText==''" class="m-right" mode="aspectFit" src="/subpackage/mall/static/images/search.png"></image>
<input placeholder="请输入商品名称" type="text" confirm-type="search" @confirm="onSearch" v-model="searchText" @focus="inputFocus" @change="inputChange"/>
<image v-if="searchText!=''" mode="aspectFit" src="/subpackage/mall/static/images/cancel.png" @click.stop="clearChange()"></image>
</view>
</view>
<view class="gs-history" v-if="searchText==''">
<view class="gh-line">
<view>历史搜索</view>
<image src="/subpackage/mall/static/images/del.png" @click="delHistory"></image>
</view>
<view class="gh-item" v-for="(e, i) in historyList" :key="i" @click="onHistroy(e)">{{e}}</view>
</view>
<view class="gs-list" v-if="goodsList.length > 0 && searchText!=''">
<view class="gl-item" v-for="(e, i) in goodsList" :key="i" v-if="goodsList.length > 0 && searchText!=''">
<goods-item
:poster="(e.product_imgs&&e.product_imgs[0]) || ''"
:name="e.product_name"
:price="e.product_price"
:product-id="e.id"
:brand-id="brand_id"
:is-del-price="e.product_spec_multi === 0&&e.product_price_show != 0"
:del-price="e.product_price_show || 0"
@click:add="goodsItemAddBtn(e)"
></goods-item>
</view>
</view>
<view class="gs-on-list" v-if="goodsList.length == 0 && searchText!=''&&isFocus">没有找到相关的商品~</view>
<!-- 分类 -->
<specification-modal ref="spacificationModal" button-txt="加入购物车"></specification-modal>
</view>
</template>
<script>
import util from '@/utils/util';
import { MALL_API } from "../js/api";
import server from "../js/server";
import goodsItem from "../components/goods_item.vue";
import specificationModal from "../components/specification_modal.vue";
export default {
components: {
goodsItem,
specificationModal
},
data() {
return {
page: 1,
searchText: '',
historyList: [],
goodsList: [],
isFocus: false,
brand_id: '',
}
},
onLoad(options) {
this.brand_id = options?.brand_id ?? '';
this.historyList = uni.getStorageSync("mallGoodsSearch") || [];
},
onReachBottom(){
let { page, brand_id } = this;
this.getGoodsList({
brand_id,
page: ++page
})
},
methods: {
goodsItemAddBtn(e){
let { brand_id } = this;
//
// product_spec_multi 1
if(e.product_spec_multi == 1){
this.$refs.spacificationModal.alert({
id: e?.id ?? '',
brand_id: brand_id,
poster: e?.product_imgs?.[0] ?? '',
name: e?.product_name ?? '',
price: e?.product_price ?? '',
specArr: e?.product_spec ?? [],
});
return
}
this.$refs?.spacificationModal?.goodsCartAdd({ brand_id, id: e?.id, });
},
//
getGoodsList({ brand_id, key='', page = 1, page_size = 20}){
let _query = {
brand_id,
key,
page,
page_size,
}
util.showLoad();
server.get({
url: MALL_API.goodsList,
data: _query,
failMsg: '加载数据失败!'
})
.then(res => {
util.hideLoad();
console.log('商品列表: ', res);
// this.goodsList = res.list || []
this.getHistory(key)
let _list = res.list || [];
if(_list.length == 0) this.isFocus = true;
if(page == 1){
this.goodsList = _list;
return
}
if(_list.length<=0)return;// util.showNone('');
this.page = page;
this.goodsList = [...this.goodsList, ...res.list];
});
},
getHistory(key){
if(!key)return;
let _arr = [...new Set([key, ...this.historyList])].slice(0,6);
this.historyList = _arr;
uni.setStorageSync("mallGoodsSearch", _arr)
},
//
onSearch(){
let { brand_id } = this;
this.getGoodsList({
brand_id,
key: this.searchText,
})
},
//
onHistroy(e){
let { brand_id } = this;
this.searchText = e
this.isFocus = true
this.getGoodsList({
brand_id,
key: this.searchText,
})
},
//
clearChange(){
this.searchText = ''
this.setPageInfo()
},
//
delHistory(){
this.historyList = []
uni.removeStorageSync('mallGoodsSearch')
},
inputChange(e){
let { brand_id } = this;
if(e.detail.value == '')return this.goodsList = [];
this.getGoodsList({
brand_id,
key: e.detail.value,
})
},
inputFocus(e){
this.setPageInfo()
},
setPageInfo(){
this.isFocus = false;
this.goodsList = []
},
}
}
</script>
<style lang="scss">
.goods-search{
position: relative;
padding-top: 156rpx;
min-height: 100vh;
background-color: #fff;
.gs-head{
position: fixed;
top: 0;
z-index: 2;
width: 100%;
padding: 32rpx 24rpx;
background-color: #fff;
.gh-ipt{
flex-grow: 1;
padding: 0 28rpx;
height: 72rpx;
border-radius: 36rpx;
border: 2rpx solid $mColor;
@include ctf(flex-start);
>image{
flex-shrink: 0;
width: 30rpx;
height: 30rpx;
}
& input{
flex-grow: 1;
height: 100%;
font-size: 28rpx;
color: #333;
// background-color: #007AFF;
margin-right: 20rpx;
}
.m-right{
margin-right: 24rpx;
}
}
}
.gs-history{
background-color: #fff;
padding: 0 40rpx;
.gh-line{
padding: 26rpx 0;
@include ctf(space-between);
>view{
color: #181818;
font-size: 32rpx;
}
>image{
width: 34rpx;
height: 34rpx;
}
}
.gh-item{
display: inline-block;
background-color: #F2F2F7;
border-radius: 32rpx;
color: #C1C1C7;
font-size: 28rpx;
padding: 12rpx 44rpx;
margin: 0 20rpx 20rpx 0;
}
}
.gs-list{
padding: 0 24rpx;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.gl-item {
flex-shrink: 0;
margin-bottom: 24rpx;
}
}
.gs-on-list{
margin-top: 200rpx;
width: 750rpx;
color: #9A9A9D;
font-size: 28rpx;
text-align: center;
}
}
.bgChange{
background-color: #F2F2F7;
}
</style>

59
src/subpackage/mall/pages/index.vue

@ -1,7 +1,7 @@
<template> <template>
<view class="mall-index"> <view class="mall-index">
<view class="mi-header"> <view class="mi-header">
<index-search-bar v-if="isShow('搜索栏')"></index-search-bar>
<index-search-bar v-if="isShow('搜索栏')" @click:search="toSearch"></index-search-bar>
<block v-if="isShow('轮播图')&&banner.length"> <block v-if="isShow('轮播图')&&banner.length">
<view class="mh-graph"></view> <view class="mh-graph"></view>
<swiper class="mh-swiper" autoplay indicator-dots indicator-active-color='#009874'> <swiper class="mh-swiper" autoplay indicator-dots indicator-active-color='#009874'>
@ -65,9 +65,15 @@
</view> </view>
</view> </view>
</block> </block>
<view class="mi-fix-btn">
<image class="mfb-img" src="/subpackage/mall/static/images/index/menu_1.png" @click="toClassify"></image>
<view class="mfb-line"></view>
<image class="mfb-img" src="/subpackage/mall/static/images/index/menu_2.png" @click="toOrderLs"></image>
<view class="mfb-line"></view>
<image class="mfb-img" src="/subpackage/mall/static/images/index/menu_3.png" @click="toShoppingCart"></image>
</view>
<!-- 分类 --> <!-- 分类 -->
<spacification-modal ref="spacificationModal" button-txt="加入购物车"></spacification-modal>
<specification-modal ref="specificationModal" button-txt="加入购物车"></specification-modal>
</view> </view>
</template> </template>
@ -75,7 +81,7 @@
import indexSearchBar from "../components/index_search_bar.vue"; import indexSearchBar from "../components/index_search_bar.vue";
import indexClassifyBar from "../components/index_classify_bar.vue"; import indexClassifyBar from "../components/index_classify_bar.vue";
import goodsItem from "../components/goods_item.vue"; import goodsItem from "../components/goods_item.vue";
import spacificationModal from "../components/specification_modal.vue";
import specificationModal from "../components/specification_modal.vue";
import { routeTo, showLoad, hideLoad, showModal, tsRoute, jsonStr } from "@/utils/util.js"; import { routeTo, showLoad, hideLoad, showModal, tsRoute, jsonStr } from "@/utils/util.js";
import { MALL_API } from "../js/api"; import { MALL_API } from "../js/api";
import server from "../js/server"; import server from "../js/server";
@ -84,7 +90,7 @@ export default {
indexSearchBar, indexSearchBar,
indexClassifyBar, indexClassifyBar,
goodsItem, goodsItem,
spacificationModal
specificationModal
}, },
computed: { computed: {
banner(){ banner(){
@ -119,10 +125,26 @@ export default {
this.getHomeData({ brand_id: _bid }); this.getHomeData({ brand_id: _bid });
}, },
methods: { methods: {
toSearch(){
let { brand_id } = this;
routeTo(`/subpackage/mall/pages/goods_search?brand_id=${brand_id}`, 'nT');
},
//
toShoppingCart(){
let { brand_id } = this;
routeTo(`/subpackage/mall/pages/shopping_cart?brand_id=${brand_id}`,'nT');
},
//
toOrderLs(){
let { brand_id } = this;
routeTo(`/subpackage/mall/pages/order/order_list?brand_id=${brand_id}`,'nT');
},
//
toClassify(){ toClassify(){
let { brand_id } = this; let { brand_id } = this;
routeTo(`/subpackage/mall/pages/classify?brand_id=${brand_id}`,'nT'); routeTo(`/subpackage/mall/pages/classify?brand_id=${brand_id}`,'nT');
}, },
// keygrid_setting
getGridLsFor(key){ getGridLsFor(key){
let { showdata } = this; let { showdata } = this;
return showdata?.[key]?.grid_setting ?? []; return showdata?.[key]?.grid_setting ?? [];
@ -154,7 +176,7 @@ export default {
// //
// product_spec_multi 1 // product_spec_multi 1
if(e.product_spec_multi == 1){ if(e.product_spec_multi == 1){
this.$refs.spacificationModal.alert({
this.$refs.specificationModal.alert({
id: e?.id ?? '', id: e?.id ?? '',
brand_id: brand_id, brand_id: brand_id,
poster: e?.product_imgs?.[0] ?? '', poster: e?.product_imgs?.[0] ?? '',
@ -164,8 +186,7 @@ export default {
}); });
return return
} }
this.$refs?.spacificationModal?.goodsCartAdd({ brand_id, id: e?.id, });
this.$refs?.specificationModal?.goodsCartAdd({ brand_id, id: e?.id, });
}, },
// //
isShow(val) { isShow(val) {
@ -304,4 +325,26 @@ export default {
} }
} }
} }
.mi-fix-btn{
position: fixed;
left: 0rpx;
bottom: 50upx;
bottom: calc(50upx + constant(safe-area-inset-bottom)); /* 兼容 iOS < 11.2 */
bottom: calc(50upx + env(safe-area-inset-bottom)); /* 兼容 iOS >= 11.2 */
padding: 14rpx 15rpx;
border-radius: 14rpx;
background: rgba($color: #000000, $alpha: .8);
@include ctf(center);
.mfb-img{
width: 48rpx;
height: 48rpx;
margin: 0rpx 9rpx;
}
.mfb-line{
width: 2rpx;
height: 48rpx;
margin: 0rpx 9rpx;
background-color: #979797;
}
}
</style> </style>

4
src/subpackage/mall/pages/modules/order/order_list_item.vue

@ -54,11 +54,9 @@ import server from "../../../js/server";
export default { export default {
props:{ props:{
orderInfo: { orderInfo: {
type: Object,
default: ()=>({}) default: ()=>({})
}, },
brandId: { brandId: {
type: Number,
default: 0 default: 0
} }
}, },
@ -108,7 +106,7 @@ export default {
if(status == 1 || status == 2 || status == 3){ if(status == 1 || status == 2 || status == 3){
let _query = {} let _query = {}
_query['goodsList'] = this.orderInfo.goods || [] _query['goodsList'] = this.orderInfo.goods || []
return util.routeTo(`/subpackage/mall/pages/order/order_share/order_share?query=${util.jsonStr(_query)}`,'nT');
return util.routeTo(`/subpackage/mall/pages/order/order_share?query=${util.jsonStr(_query)}&brand_id=${brandId}`,'nT');
} }
if(status == 4 || status == 5 || status == 7 || status == 8) return this.determineOperate(1); if(status == 4 || status == 5 || status == 7 || status == 8) return this.determineOperate(1);
if(status == 6 ) return console.log("退款详情"); if(status == 6 ) return console.log("退款详情");

1
src/subpackage/mall/pages/modules/order/product_info.vue

@ -38,7 +38,6 @@ export default {
} }
}, },
goodsNums: { // goodsNums: { //
type: Number,
default: 0, default: 0,
}, },
isRefund: { isRefund: {

1
src/subpackage/mall/pages/order/order_details.vue

@ -458,6 +458,7 @@ export default {
}); });
}, },
phoneCall() { phoneCall() {
return util.showNone('暂未开放');
let { orderInfo } = this; let { orderInfo } = this;
let _phoneStr = orderInfo.contact_mobile || ''; let _phoneStr = orderInfo.contact_mobile || '';
let _phoneArr = _phoneStr.split(',') || []; let _phoneArr = _phoneStr.split(',') || [];

6
src/subpackage/mall/pages/order/order_list.vue

@ -94,10 +94,12 @@ export default {
}, },
methods: { methods: {
toOrderSearch(){ toOrderSearch(){
util.routeTo(`../order_search/order_search`,'nT')
let { brand_id } = this;
util.routeTo(`/subpackage/mall/pages/order/order_search?brand_id=${brand_id}`,'nT');
}, },
toRefundList(){ toRefundList(){
util.routeTo(`../refund_list/refund_list`,'nT')
let { brand_id } = this;
util.routeTo(`/subpackage/mall/pages/order/refund_list?brand_id=${brand_id}`,'nT')
}, },
defineChange(e){ defineChange(e){
let { brand_id } = this; let { brand_id } = this;

203
src/subpackage/mall/pages/order/order_search.vue

@ -0,0 +1,203 @@
<template>
<view class="order-search" :class="{bgChange: searchText!=''}">
<view class="os-head">
<view class="oh-ipt">
<image v-if="searchText==''" class="m-right" mode="aspectFit" src="/subpackage/mall/static/images/search.png"></image>
<input placeholder="搜索我的订单" type="text" confirm-type="search" @confirm="onSearch" v-model="searchText" @focus="inputFocus" @change="inputChange"/>
<image v-if="searchText!=''" mode="aspectFit" src="/subpackage/mall/static/images/cancel.png" @click.stop="clearChange()"></image>
</view>
</view>
<view class="os-history" v-if="searchText==''">
<view class="oh-line">
<view>历史搜索</view>
<image src="/subpackage/mall/static/images/del.png" @click="delHistory"></image>
</view>
<view class="oh-item" v-for="(e, i) in historyList" :key="i" @click="onHistroy(e)">{{e}}</view>
</view>
<block v-for="(e, i) in orderList" :key="i" v-if="orderList.length > 0 && searchText!=''">
<order-list-item
:brand-id="brand_id"
:orderInfo="e"
@defineChange="defineChange"
></order-list-item>
</block>
<view class="gs-on-list" v-if="orderList.length == 0 && searchText!=''&&isFocus">您还没有相关的订单~</view>
</view>
</template>
<script>
import util from '@/utils/util';
import { MALL_API } from "../../js/api";
import server from "../../js/server";
import orderListItem from '../modules/order/order_list_item.vue';
export default {
components: { orderListItem },
data() {
return {
page: 1,
orderList: [],
searchText: '',
historyList: [],
isFocus: false,
brand_id: '',
}
},
onLoad(options) {
this.brand_id = options?.brand_id ?? '';
this.historyList = uni.getStorageSync("mallOrderHistorySearch") || [];
},
methods: {
defineChange(e){
let { brand_id } = this;
if(e == true) this.getOrderList({ brand_id, key: this.searchText });
},
getOrderList({ brand_id, key }){ //page = 1, page_size = 20,
let _query = {
brand_id,
key,
}
util.showLoad();
server.get({
url: MALL_API.goodsOrderList,
data: _query,
failMsg: '加载数据失败!'
})
.then(res => {
util.hideLoad();
console.log('订单列表: ', res);
this.orderList = res.list || [];
if(this.orderList.length == 0) this.isFocus = true;
if(!key)return;
let _arr = [...new Set([key, ...this.historyList])].slice(0,6);
this.historyList = _arr;
uni.setStorageSync("mallOrderHistorySearch", _arr)
});
},
//
onSearch(){
let { brand_id } = this;
this.getOrderList({
key: this.searchText,
brand_id
})
},
//
onHistroy(e){
let { brand_id } = this;
this.searchText = e
this.isFocus = true
this.getOrderList({
key: this.searchText,
brand_id
})
},
//
clearChange(){
this.searchText = ''
this.setPageInfo()
},
//
delHistory(){
this.historyList = []
uni.removeStorageSync('mallOrderHistorySearch')
},
inputChange(e){
let { brand_id } = this;
console.log("搜索999: ",e.detail.value)
if(e.detail.value == '')return this.orderList = [];
this.getOrderList({
key: e.detail.value,
brand_id
})
},
inputFocus(e){
this.setPageInfo()
},
setPageInfo(){
this.isFocus = false;
this.orderList = []
},
}
}
</script>
<style lang="scss">
.order-search{
position: relative;
padding-top: 156rpx;
min-height: 100vh;
background-color: #fff;
.os-head{
position: fixed;
top: 0;
z-index: 2;
width: 100%;
padding: 32rpx 24rpx;
background-color: #fff;
.oh-ipt{
flex-grow: 1;
padding: 0 28rpx;
height: 72rpx;
border-radius: 36rpx;
border: 2rpx solid $mColor;
@include ctf(flex-start);
>image{
flex-shrink: 0;
width: 30rpx;
height: 30rpx;
}
& input{
flex-grow: 1;
height: 100%;
font-size: 28rpx;
color: #333;
// background-color: #007AFF;
margin-right: 20rpx;
}
.m-right{
margin-right: 24rpx;
}
}
}
.os-history{
background-color: #fff;
padding: 0 40rpx;
.oh-line{
padding: 26rpx 0;
@include ctf(space-between);
>view{
color: #181818;
font-size: 32rpx;
}
>image{
width: 34rpx;
height: 34rpx;
}
}
.oh-item{
display: inline-block;
background-color: #F2F2F7;
border-radius: 32rpx;
color: #C1C1C7;
font-size: 28rpx;
padding: 12rpx 44rpx;
margin: 0 20rpx 20rpx 0;
}
}
.gs-on-list{
margin-top: 200rpx;
width: 750rpx;
color: #9A9A9D;
font-size: 28rpx;
text-align: center;
}
}
.bgChange{
background-color: #F2F2F7;
}
</style>

143
src/subpackage/mall/pages/order/order_share.vue

@ -0,0 +1,143 @@
<template>
<view class="order-share">
<view class="os-title">{{pageInfo.product_name || '-'}}</view>
<image class="os-img" mode="aspectFill" :src="pageInfo.product_imgs || ''"></image>
<view class="os-box">
<view class="ob-txt">请选择一件要分享的好货</view>
<view class="ob-item" v-for="(e,i) in goodsList" :key="i" @click="onClickItem(e)">
<image class="oi-img" :class="{itemChange: e.product_id == pageInfo.product_id}" :src="e.product_imgs || ''"></image>
<image class="oi-icon" src="/subpackage/mall/static/images/selected2.png" v-if="e.product_id == pageInfo.product_id"></image>
</view>
</view>
<view class="os-btn">
<button class="ob-share" hover-class='hover-active' type="" open-type="share" >
分享给好友
</button>
<!-- <view>分享给好友</view> -->
</view>
</view>
</template>
<script>
import util from '@/utils/util';
export default {
data() {
return {
goodsList: [],
pageInfo: {},
brand_id: '',
}
},
async onLoad(options) {
this.brand_id = options?.brand_id ?? '';
try{
let _query = util.jsonPar(options.query);
this.goodsList = _query.goodsList
this.pageInfo = this.goodsList[0]
}catch(err){
console.error('init-share-error',err);
}
},
onShareAppMessage(res) {
let { pageInfo, brand_id } = this;
let url = `/subpackage/mall/pages/goods_info?id=${pageInfo.product_id}&brand_id=${brand_id}`
return {
title: pageInfo.product_name ?? '',
path: url,
imageUrl: pageInfo?.product_imgs ?? ''
}
},
methods: {
onClickItem(item){
console.warn(item)
this.pageInfo = item
},
}
}
</script>
<style lang="scss">
page{
background-color: #fff;
}
.order-share{
position: relative;
@include isPd(110upx);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.os-title{
color: #000;
font-size: 32rpx;
max-width: 480rpx;
text-align: center;
line-height: 44rpx;
margin: 44rpx 0;
}
.os-img{
width: 528rpx;
height: 528rpx;
border-radius: 10rpx;
}
.os-box{
width: 100%;
padding: 10rpx 0 0 40rpx;
.ob-txt{
color: #000;
font-size: 28rpx;
margin: 34rpx 20rpx;
}
.ob-item{
position: relative;
display: inline-block;
width: 208rpx;
height: 208rpx;
margin: 0rpx 0rpx 20rpx 20rpx;
.oi-img{
width: 200rpx;
height: 200rpx;
border-radius: 10rpx;
}
.oi-icon{
position: absolute;
top: 8rpx;
right: 16rpx;
width: 32rpx;
height: 32rpx;
}
.itemChange{
width: 196rpx;
height: 196rpx;
border: 4rpx solid $mColor;
}
}
}
.os-btn{
position: fixed;
bottom: 0;
left: 0;
width: 100%;
padding: 18rpx 0;
@include isPd(18rpx);
background-color: #fff;
button::after{
border: none;
background-color: none;
}
.ob-share {
margin: 0 24rpx;
flex-grow: 1;
border: none;
background: linear-gradient(90deg, #44D7B6 0%, $mColor 100%);
border-radius: 36rpx;
padding: 2rpx 0;
text-align: center;
color: #FFF;
font-size: 28rpx;
}
}
}
</style>

729
src/subpackage/mall/pages/order/refund_details.vue

@ -0,0 +1,729 @@
<template>
<view class="refund-details">
<view class="rd-head">
<view class="rh-view">
<view>{{pageInfo.extension.header || '-'}}</view>
<view>{{pageInfo.extension.title || '-'}}<view v-if="pageInfo.express_status == 1">请在<text>{{pageInfo.extension.time || '-'}}</text>内响应</view></view>
</view>
<image src="/subpackage/mall/static/images/order/status_5.png"></image>
</view>
<!-- 退货地址 -->
<view class="rd-addr" v-if="pageInfo.feedback_type==1 && pageInfo.express_status == 1">
<view class="ra-line">
<view>退货地址</view>
<view @click="copyOrder(shipInfo)">复制</view>
</view>
<view class="ra-name">
<text>{{pageInfo.feedback_express.contacts || '-'}}</text>
<text>{{pageInfo.feedback_express.mobile || '-'}}</text>
</view>
<view class="ra-position">{{pageInfo.feedback_express.addr || '-'}}</view>
</view>
<view class="rd-annal" @click="toRrefundLogs">
<view>查看协商记录</view>
<image src="/subpackage/mall/static/images/arrow_9ad.png"></image>
</view>
<view class="rd-price">
<view>
<image src="/subpackage/mall/static/images/price.png"></image>
<text>退款金额</text>
</view>
<view>{{pageInfo.refund_amount || 0}}</view>
</view>
<!-- 退款商品 -->
<view class="rd-goods">
<view class="rg-tit">
<text>退款商品</text>
<text>{{productNums}}</text>
</view>
<view class="rg-list" v-for="(e, i) in pageInfo.goods" :key="i">
<view class="rl-item">
<image mode="aspectFill" :src="e.product_imgs || ''"></image>
<view class="ri-section">
<view class="rs-name">{{e.product_name || '-'}}</view>
<view class="rs-line">
<view>{{setSpecText(e)}}</view>
<view>×{{e.product_nums || 0}}</view>
</view>
<view class="rs-price">
<text>实付¥</text>
<text>{{e.refundable_amount || 0}}</text>
</view>
</view>
</view>
</view>
</view>
<!-- 退款信息 -->
<view class="rd-info">
<view class="ri-line">
<view>退款类型</view>
<view>{{ feedbackType }}</view>
</view>
<view class="ri-line">
<view>退款原因</view>
<view>{{pageInfo.question_type || '-'}}</view>
</view>
<view class="ri-line">
<view>退款金额</view>
<view>{{pageInfo.refund_amount || 0}}含运费¥0</view>
</view>
<view class="ri-line">
<view>退款积分</view>
<view>{{pageInfo.refund_deduction_integral || 0}}积分</view>
</view>
<view class="ri-line">
<view>售后单号</view>
<view>
{{pageInfo.feedback_no || '-'}}
<text @click="copyOrder(pageInfo.feedback_no)">复制</text>
</view>
</view>
<view class="ri-line">
<view>申请时间</view>
<view>{{pageInfo.apply_time || '-'}}</view>
</view>
</view>
<view class="rd-btn">
<view class="rb-btn1" hover-class="hover-active" @click="btnChange(1)">联系商家</view>
<view v-if="isFeedbackBtn" class="rb-btn2" hover-class="hover-active" @click="btnChange(2)">撤销退款</view>
<view v-if="pageInfo.feedback_type==1 && pageInfo.express_status == 1" class="rb-btn3" hover-class="hover-active" @click="isShowLogistics = !isShowLogistics">填写物流</view>
</view>
<!-- 填写物流信息 -->
<view class="fixed-mask" v-if="isShowLogistics" @touchmove.stop.prevent="moveHandle">
<view class="rd-logistics-modal">
<view class="rlm-close">
<image src="/subpackage/mall/static/images/close_c97_2.png" @click="isShowLogistics = !isShowLogistics"></image>
</view>
<view class="rlm-tit">填写物流信息</view>
<view class="rlm-box">
<view><text>*</text>物流公司</view>
<picker class="rb-picker" :range="expressList" @change="pickerChange">
<view class="rp-view">
<input v-model="expressInfo.express_name" disabled="true"/>
<image src="/subpackage/mall/static/images/arrow_9ad.png" style="transform: rotateZ(90deg)"></image>
</view>
</picker>
</view>
<view class="rlm-box">
<view><text>*</text>物流单号</view>
<view>
<input type="text" v-model="expressInfo.express_no" @change="iptNoChange"/>
</view>
</view>
<view class="rlm-box">
<view>备注</view>
<view>
<input placeholder="选填" type="text" v-model="expressInfo.express_mark" @change="iptMarkChange"/>
</view>
</view>
<view class="rlm-btn" hover-class="hover-active" @click="expressBtn">确认</view>
</view>
</view>
</view>
</template>
<script>
import util from '@/utils/util';
import { MALL_API } from "../../js/api";
import server from "../../js/server";
export default {
computed: {
feedbackType(){
let status = this.pageInfo.feedback_type
let arr = ['仅退款','退货退款']
return arr[status] || '-';
},
isFeedbackBtn(){
//
// feedback_status = 0 & reply_status = 0 --> 退
// feedback_status = 1 & reply_status = 0 ---> 退
// feedback_status = 1 & reply_status = 1 ---> 退
// feedback_status = 2 & reply_status = 0 --> 退
let { pageInfo } = this
if(pageInfo.feedback_type==0){
if(pageInfo.feedback_status == 0 && pageInfo.reply_status == 0) return true;
else return false;
}
if(pageInfo.feedback_type==1){
if(pageInfo.express_status == 0 || pageInfo.express_status == 1) return true;
else return false;
}
},
productNums(){
let { pageInfo } = this
let _list = this.pageInfo.goods
let num = 0
for(var i in _list){
num = _list[i].product_nums + num
}
return num;
},
productCartIds(){
let list = this.pageInfo.goods
let _arr = []
for(var i in list){
_arr.push(list[i].product_cart_id)
}
return _arr;
},
},
data() {
return {
isShowLogistics: false,
pageInfo: {},
expressInfo: {
express_name: '',
express_no: '',
express_mark: '',
},
expressList: [],
shipInfo: '', //
brand_id: '',
}
},
onLoad(options) {
let _bid = options?.brand_id ?? '';
this.brand_id = _bid;
this.getFeedbackDetail({
brand_id: _bid,
id: options.id,
})
this.getExpressList()
},
methods: {
moveHandle(){},
toRrefundLogs(){
let{ brand_id, pageInfo } = this;
util.routeTo(`/subpackage/mall/pages/order/refund_logs?id=${pageInfo?.id ?? ''}&brand_id=${brand_id}`,'nT')
},
//
copyOrder(data) {
uni.setClipboardData({ data });
},
setSpecText(info){
if(info.product_spec_multi == 1){
let specStr = (info.product_spec_multi_info.spec_info).join(";")
return specStr;
}
return '';
},
getFeedbackDetail({ brand_id, id }){
let _query = { brand_id, id }
util.showLoad();
server.get({
url: MALL_API.feedbackDetail + id,
data: _query,
failMsg: '加载数据失败!'
})
.then(res => {
util.hideLoad();
console.log('售后详情: ', res);
this.pageInfo = res
this.shipInfo = "收货人:" + res.feedback_express.contacts + "\n手机号码:" + res.feedback_express.mobile + "\n收货地址:" + res.feedback_express.addr;
});
},
btnChange(type){ // type 1 2退
if(type == 1){
return util.showNone('暂未开放');
let _phoneStr = ''
let _phoneArr = _phoneStr.split(',') || [];
uni.showActionSheet({
itemList: _phoneArr,
success: res =>{
uni.makePhoneCall({
phoneNumber: _phoneArr[res.tapIndex]
})
}
})
return;
}
if(type == 2) return this.feedBachOperate({info: this.pageInfo, type: 0});
},
feedBachOperate: util.debounce(function({info, type}){
util.showModal({
title: '',
content: type == 0?'确认撤销退款吗?':'确认删除记录吗?',
showCancel: true,
success: modalRes=>{
if(modalRes.confirm){
let _API;
if(type == 0)_API = MALL_API.feedbackCancel; //
if(type == 1)_API = MALL_API.feedbackDelete; //
util.showLoad();
server.get({
url: _API + info.id,
data: {
id: info.id,
brand_id: info.brand_id
},
isDefaultGet: false
})
.then(res=>{
util.hideLoad();
console.log('撤销/删除: ', res);
if(res.data.code == 0){
util.showNone(res.data.message || '操作成功!');
if(type == 0){
this.getOrdeRefundCancel({
brand_id: info.brand_id,
order_no: info.order_no,
product_cart_ids: this.productCartIds,
})
}
setTimeout(_=>this.refreshList(), 1200);
}else{
util.showNone(res.data.message || '操作失败!');
}
})
.catch(util.hideLoad)
}
}
})
}, 300, 300),
refreshList(){
let { brand_id } = this;
this.getFeedbackDetail({
brand_id,
id: this.pageInfo.id,
})
},
getOrdeRefundCancel({ brand_id, order_no, product_cart_ids }){
server.post({
url: MALL_API.goodsOrdeRefundCancel,
data: {
brand_id,
order_no,
product_cart_ids,
},
failMsg: '加载数据失败!'
})
.then(res => {
console.log('getOrdeRefundCancel: ', res);
});
},
//
getExpressList(){
server.post({
url: MALL_API.expressList,
data: {},
failMsg: '加载数据失败!'
})
.then(res => {
console.log('getExpressList: ', res);
for(var i in res){
this.expressList.push(res[i].name)
}
});
},
//
getFeedbackExpress({ brand_id, id, express_name, express_no, express_mark }){
server.post({
url: MALL_API.feedbackExpress,
data: {
brand_id,
id,
express_name, //
express_no, //
express_mark, //
},
failMsg: '加载数据失败!'
})
.then(res => {
console.log('getFeedbackExpress: ', res);
this.isShowLogistics = false
util.showNone("操作成功!");
});
},
pickerChange(e){
console.log(e);
let _questionList = this.expressList || [];
this.expressInfo.express_name = _questionList[e.detail.value] || ''
},
//
iptNoChange: util.debounce(function(e) {
this.expressInfo.express_no = e.detail.value || '';
},300,300),
//
iptMarkChange: util.debounce(function(e) {
this.expressInfo.express_mark = e.detail.value || '';
},300,300),
expressBtn(){
let { expressInfo, pageInfo, brand_id } = this
if(expressInfo.express_name=='' || expressInfo.express_no=='')return util.showNone("请填写完整物流信息!");
this.getFeedbackExpress({
brand_id,
id: pageInfo.id,
express_name: expressInfo.express_name,
express_no: expressInfo.express_no,
express_mark: expressInfo.express_mark,
})
},
}
}
</script>
<style lang="scss">
.refund-details{
position: relative;
width: 100%;
@include isPd(128upx);
.rd-head{
position: relative;
width: 100%;
height: 160rpx;
background-color: $mColor;
@include ctf(flex-end);
>image{
width: 266rpx;
height: 160rpx;
}
.rh-view{
position: absolute;
left: 44rpx;
top: 22rpx;
margin-right: 44rpx;
>view{
&:first-child{
color: #FFF;
font-size: 36rpx;
font-weight: 700;
@include tHide(1);
}
&:nth-child(2){
font-size: 24rpx;
color: rgba($color: #fff, $alpha: 0.6);
margin-top: 2rpx;
@include tHide(2);
@include ctf(flex-start);
>view{
font-size: 24rpx;
color: rgba($color: #fff, $alpha: 0.6);
>text{
color: #FFBA2C;
}
}
}
}
}
}
.rd-addr{
margin: 24rpx 24rpx 0rpx;
padding: 30rpx 20rpx;
border-radius: 10rpx;
background-color: #fff;
.ra-line{
@include ctf(space-between);
>view{
&:first-child{
color: #333;
font-size: 32rpx;
font-weight: 700;
}
&:nth-child(2){
font-size: 28rpx;
color: $mColor;
margin-right: 10rpx;
}
}
}
.ra-name{
margin: 30rpx 0rpx 10rpx;
>text{
color: #333;
font-size: 32rpx;
font-weight: 700;
&:first-child{
}
&:nth-child(2){
margin-left: 52rpx;
}
}
}
.ra-position{
color: #9A9A9D;
font-size: 28rpx;
}
}
.rd-annal{
margin: 24rpx;
padding: 24rpx 20rpx;
border-radius: 10rpx;
background-color: #fff;
@include ctf(space-between);
>view{
flex-grow: 1;
color: #333;
font-size: 28rpx;
}
>image{
flex-shrink: 0;
width: 30rpx;
height: 30rpx;
}
}
.rd-price{
margin: 0rpx 24rpx 24rpx;
padding: 24rpx 20rpx;
border-radius: 10rpx;
background-color: #fff;
@include ctf(space-between);
>view{
&:first-child{
flex-grow: 1;
@include ctf(flex-start);
>image{
flex-shrink: 0;
width: 34rpx;
height: 34rpx;
margin-right: 20rpx;
}
>text{
flex-grow: 1;
color: #FF873D;
font-size: 28rpx;
}
}
&:nth-child(2){
flex-shrink: 0;
color: #FF873D;
font-size: 28rpx;
}
}
}
.rd-goods{
margin: 0 24rpx;
padding: 0 20rpx;
border-radius: 10rpx;
background-color: #fff;
.rg-tit{
padding: 22rpx 0;
>text{
font-size: 28rpx;
&:first-child{
color: #333;
}
&:nth-child(2){
color: #9A9A9D;
margin-left: 28rpx;
}
}
}
.rg-list{
flex-grow: 1;
.rl-item{
flex-grow: 1;
padding: 30rpx 0 34rpx;
border-top: 2rpx solid #D8D8D8;
@include ctf(flex-start);
>image{
flex-shrink: 0;
margin-right: 20rpx;
width: 180rpx;
height: 180rpx;
border-radius: 10rpx;
}
.ri-section{
flex-grow: 1;
.rs-name{
flex-grow: 1;
color: #333;
font-size: 28rpx;
margin-right: 120rpx;
@include tHide(2);
}
.rs-line{
margin: 12rpx 0 14rpx;
@include ctf(space-between);
>view{
color: #9A9A9D;
&:first-child{
flex-grow: 1;
font-size: 24rpx;
}
&:nth-child(2){
flex-shrink: 0;
font-size: 28rpx;
margin-left: 20rpx;
}
}
}
.rs-price{
>text{
color: #FF873D;
&:first-child{
font-size: 28rpx;
}
&:nth-child(2){
font-size: 36rpx;
font-weight: 700;
}
}
}
}
}
}
}
.rd-info{
margin: 24rpx;
padding: 30rpx 28rpx;
border-radius: 10rpx;
background-color: #fff;
.ri-line{
@include ctf(flex-start);
>view{
font-size: 28rpx;
line-height: 60rpx;
&:first-child{
color: #9A9A9D;
}
&:nth-child(2){
color: #333;
margin-left: 40rpx;
>text{
color: $mColor;
margin-left: 40rpx;
}
}
}
}
}
.rd-btn{
position: fixed;
bottom: 0;
width: 100%;
padding: 20rpx 18rpx 20rpx 0rpx;
@include isPd(20upx);
background-color: #fff;
border-top: 2rpx solid #f2f2f7;
@include ctf(flex-end);
>view{
width: 192rpx;
padding: 24rpx 0;
margin-right: 20rpx;
border-radius: 44rpx;
text-align: center;
font-size: 28rpx;
}
.rb-btn1{
color: #9A9A9D;
border: 2rpx solid #D8D8D8;
}
.rb-btn2{
color: $mColor;
border: 2rpx solid $mColor;
}
.rb-btn3{
color: #fff;
background: linear-gradient(90deg, #44D7B6 0%, $mColor 100%);
}
}
.rd-logistics-modal{
position: absolute;
left: 65rpx;
top: 20%;
background-color: #fff;
width: 620rpx;
padding: 30rpx;
border-radius: 10rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.rlm-close{
width: 100%;
@include ctf(flex-end);
>image{
width: 32rpx;
height: 32rpx;
}
}
.rlm-tit{
margin: 16rpx 0 60rpx;
color: #333;
font-size: 32rpx;
font-weight: 700;
}
.rlm-box{
margin-bottom: 20rpx;
@include ctf(flex-start);
>view{
&:first-child{
position: relative;
color: #333;
font-size: 28rpx;
margin-right: 22rpx;
width: 112rpx;
>text{
position: absolute;
left: -18rpx;
top: 8rpx;
color: #FF873D;
font-size: 28rpx;
}
}
&:nth-child(2){
width: 398rpx;
height: 88rpx;
border-radius: 10rpx;
border: 2rpx solid #979797;
@include ctf(space-between);
>input{
flex-grow: 1;
margin: 0 20rpx;
font-size: 28rpx;
color: #333;
}
// >image{
// flex-shrink: 0;
// width: 30rpx;
// height: 30rpx;
// margin-right: 20rpx;
// }
}
}
.rb-picker{
width: 398rpx;
.rp-view{
width: 398rpx;
height: 88rpx;
border-radius: 10rpx;
border: 2rpx solid #979797;
@include ctf(space-between);
& input{
flex-grow: 1;
margin: 0 20rpx;
font-size: 28rpx;
color: #333;
}
>image{
flex-shrink: 0;
width: 30rpx;
height: 30rpx;
margin-right: 20rpx;
}
}
}
}
.rlm-btn{
width: 240rpx;
margin: 40rpx 0rpx 50rpx;
padding: 22rpx 0;
color: #fff;
font-size: 32rpx;
text-align: center;
border-radius: 44rpx;
background-color: $mColor;
}
}
}
</style>

324
src/subpackage/mall/pages/order/refund_list.vue

@ -0,0 +1,324 @@
<template>
<view class="refund-list" :class="[refundLen? 'bgChange':'']">
<view class="rl-list" v-for="(e,i) in refundList" :key="i" @click="toDetailChange(e.id)" v-if="refundList.length > 0">
<view class="rl-line">
<view class="rl-address">
<image mode="aspectFit" :src="e.image || ''"></image>
<view class="ra-view">
<view>{{e.name || '-'}}</view>
<view>
<text>退款</text>
<text>{{e.apply_time || '-'}}</text>
<text>申请</text>
</view>
</view>
</view>
<view class="rl-status">{{setFeedbackStatus(e)}}</view>
</view>
<product-info :goodsInfo="e.goods" :goodsNums="e.goods.length" :isRefund="true"></product-info>
<view class="rl-price">
<text>退款</text>
<text>¥</text>
<text>{{e.refund_amount || 0}}</text>
</view>
<view class="rl-btn">
<view v-if="isBtnDel(e)" class="rb1" hover-class="hover-active" @click.stop="feedBachOperate({info: e, type: 1})">删除记录</view>
<view v-if="isBtnCancel(e)" class="rb2" hover-class="hover-active" @click.stop="feedBachOperate({info: e, type: 0})">一键撤销退款</view>
</view>
</view>
<view class="rl-no-list" v-if="refundList.length == 0">
<image src="/subpackage/mall/static/images/no_venue_order.png"></image>
</view>
</view>
</template>
<script>
import util from '@/utils/util';
import { MALL_API } from "../../js/api";
import server from "../../js/server";
import productInfo from '../modules/order/product_info.vue';
export default {
components: { productInfo },
computed: {
refundLen(){
if(this.refundList.length > 0)return true;
else return false;
},
},
data() {
return {
page: 1,
refundList: [],
brand_id: '',
}
},
onLoad(options) {
this.brand_id = options?.brand_id ?? '';
},
onShow() {
let { brand_id } = this;
this.getFeedbackList({ brand_id });
},
onReachBottom(){
let { page, brand_id } = this;
this.getFeedbackList({ brand_id, page: ++page });
},
methods: {
setFeedbackStatus(e){
//
// feedback_status = 0 & reply_status = 0 --> 退
// feedback_status = 1 & reply_status = 0 ---> 退
// feedback_status = 1 & reply_status = 1 ---> 退
// feedback_status = 2 & reply_status = 0 --> 退
let status = 0
if(e.feedback_status == 0 && e.reply_status == 0) status = 0;
if(e.feedback_status == 1 && e.reply_status == 0) status = 2;
if(e.feedback_status == 1 && e.reply_status == 1) status = 1;
if(e.feedback_status == 2 && e.reply_status == 0) status = 2;
let arr = ['退款中','退款完成','退款关闭']
return arr[status] || '-'
},
isBtnDel(e){
// true
if(e.feedback_status == 0 && e.reply_status == 0)return false;
if(e.feedback_status == 1 && e.reply_status == 0)return true;
if(e.feedback_status == 1 && e.reply_status == 1)return true;
if(e.feedback_status == 2 && e.reply_status == 0)return true;
},
isBtnCancel(e){
// true
if(e.feedback_type == 0){
if(e.feedback_status == 0 && e.reply_status == 0)return true;
else return false;
}
if(e.feedback_type == 1){
if(e.express_status == 0 || e.express_status == 1) return true;
else return false;
}
},
getFeedbackList({ brand_id, page = 1, page_size = 20,}){
let _query = {
brand_id,
order_type: 'product_order',
page,
page_size,
}
util.showLoad();
server.get({
url: MALL_API.feedbackList,
data: _query,
failMsg: '加载数据失败!'
})
.then(res => {
util.hideLoad();
console.log('售后列表: ', res);
let _list = res.list || [];
if(page == 1){
this.refundList = _list;
return
}
if(_list.length<=0)return util.showNone('没有更多!');// util.showNone('');
this.page = page;
this.refundList = [...this.refundList, ...res.list];
console.log(res);
});
},
getOrdeRefundCancel({ brand_id, order_no, product_cart_ids}){
server.post({
url: MALL_API.goodsOrdeRefundCancel,
data: {
brand_id,
order_no,
product_cart_ids,
},
failMsg: '加载数据失败!'
})
.then(res => {
console.log('getOrdeRefundCancel: ', res);
});
},
productCartIds(list){
let _arr = []
for(var i in list){
_arr.push(list[i].product_cart_id)
}
return _arr;
},
feedBachOperate: util.debounce(function({info, type}){
util.showModal({
title: '',
content: type == 0?'确认撤销退款吗?':'确认删除记录吗?',
showCancel: true,
success: modalRes=>{
if(modalRes.confirm){
let _API;
if(type == 0)_API = MALL_API.feedbackCancel; //
if(type == 1)_API = MALL_API.feedbackDelete; //
util.showLoad();
server.get({
url: _API + info.id,
data: {
id: info.id,
brand_id: info.brand_id
},
isDefaultGet: false
})
.then(res=>{
util.hideLoad();
console.log('撤销/删除: ', res);
if(res.data.code == 0){
util.showNone(res.data.message || '操作成功!');
if(type == 0){
this.getOrdeRefundCancel({
brand_id: info?.brand_id ?? '',
order_no: info.order_no,
product_cart_ids: this.productCartIds(info.goods),
})
}
setTimeout(_=>this.refreshList(), 1200);
}else{
util.showNone(res.data.message || '操作失败!');
}
})
.catch(util.hideLoad)
}
}
})
}, 300, 300),
refreshList(){
let { brand_id } = this;
this.refundList = null;
this.getFeedbackList({ brand_id });
},
toDetailChange(id){
let { brand_id } = this;
util.routeTo(`/subpackage/mall/pages/order/refund_details?id=${id}&brand_id=${brand_id}`,'nT')
},
}
}
</script>
<style lang="scss">
@import '~style/public.scss';
.refund-list{
padding-top: 24rpx;
min-height: 100vh;
background-color: #fff;
.rl-no-list{
width: 750rpx;
margin-top: 200rpx;
@include ctf(center);
>image{
width: 346rpx;
height: 346rpx;
}
}
.rl-list{
margin: 0 24rpx 24rpx;
padding: 22rpx 20rpx 30rpx;
background-color: #fff;
border-radius: 10rpx;
.rl-line{
display: flex;
flex-direction: row;
justify-content: space-between;
padding-bottom: 24rpx;
margin-bottom: 32rpx;
border-bottom: 2rpx solid #D8D8D8;
.rl-address{
flex-grow: 1;
display: flex;
flex-direction: row;
justify-content: flex-start;
>image{
flex-shrink: 0;
margin-right: 14rpx;
width: 40rpx;
height: 40rpx;
border-radius: 10rpx;
}
.ra-view{
flex-grow: 1;
>view{
&:first-child{
color: #333;
font-size: 28rpx;
@include tHide(1);
}
&:nth-child(2){
color: #9A9A9D;
font-size: 24rpx;
margin-top: 12rpx;
>text{
&:first-child{
color: #E60213;
}
&:nth-child(2){
}
&:nth-child(3){
margin-left: 30rpx;
}
}
}
}
}
}
.rl-status{
flex-shrink: 0;
color: $mColor;
font-size: 28rpx;
}
}
.rl-price{
margin: 36rpx 0 10rpx;
flex-grow: 1;
text-align: right;
>text{
line-height: 40rpx;
color: #333;
&:first-child{
font-size: 28rpx;
}
&:nth-child(2){
font-size: 24rpx;
}
&:nth-child(3){
font-size: 32rpx;
}
}
}
.rl-btn{
flex-grow: 1;
margin-top: 26rpx;
@include ctf(flex-end);
>view{
padding: 16rpx 34rpx;
font-size: 28rpx;
text-align: center;
border-radius: 36rpx;
margin-right: 16rpx;
}
.rb1{
color: #9A9A9D;
border: 2rpx solid #D8D8D8;
}
.rb2{
color: $mColor;
border: 2rpx solid $mColor;
}
}
}
}
.bgChange{
background-color: #F2F2F7;
}
</style>

287
src/subpackage/mall/pages/order/refund_logs.vue

@ -0,0 +1,287 @@
<template>
<!-- 协商记录 -->
<view class="refund-logs">
<!-- 商家同意退款申请 -->
<view class="rl-box" v-if="pageInfo.sellerRefund">
<view class="rb-store">
<image mode="aspectFill" :src="pageInfo.sellerRefund.image || ''"></image>
<view class="rs-name">
<view>{{pageInfo.sellerRefund.name || '-'}}</view>
<view>{{pageInfo.sellerRefund.record_time || '-'}}</view>
</view>
</view>
<view class="rb-tit">{{pageInfo.sellerRefund.title || '-'}}</view>
<view class="rb-line">
<view>退款金额</view>
<view>¥{{pageInfo.sellerRefund.refund_amount || 0}}含运费¥0</view>
</view>
<view class="rb-line">
<view>退积分</view>
<view>{{pageInfo.sellerRefund.refund_integral || 0}}积分</view>
</view>
<view class="rb-line">
<view>备注</view>
<view>{{pageInfo.sellerRefund.reply_content || ''}}</view>
</view>
</view>
<!-- 商家拒绝退款 -->
<view class="rl-box" v-if="pageInfo.sellerRefuse">
<view class="rb-store">
<image mode="aspectFill" :src="pageInfo.sellerRefuse.image || ''"></image>
<view class="rs-name">
<view>{{pageInfo.sellerRefuse.name || '-'}}</view>
<view>{{pageInfo.sellerRefuse.record_time || '-'}}</view>
</view>
</view>
<view class="rb-tit">{{pageInfo.sellerRefuse.title || '-'}}</view>
<view class="rb-line">
<view>退款金额</view>
<view>¥{{pageInfo.sellerRefuse.refund_amount || 0}}含运费¥0</view>
</view>
<view class="rb-line">
<view>退积分</view>
<view>{{pageInfo.sellerRefuse.refund_integral || 0}}积分</view>
</view>
<view class="rb-line">
<view>备注</view>
<view>{{pageInfo.sellerRefuse.reply_content || ''}}</view>
</view>
</view>
<!-- 买家已退货 -->
<view class="rl-box" v-if="pageInfo.buyerReturn">
<view class="rb-store">
<image mode="aspectFill" :src="pageInfo.buyerReturn.image || ''"></image>
<view class="rs-name">
<view>{{pageInfo.buyerReturn.name || '-'}}</view>
<view>{{pageInfo.buyerReturn.record_time || '-'}}</view>
</view>
</view>
<view class="rb-tit">{{pageInfo.buyerReturn.title || '-'}}</view>
<view class="rb-line">
<view>物流公司</view>
<view>{{pageInfo.buyerReturn.express.name || '-'}}</view>
</view>
<view class="rb-line">
<view>物流单号</view>
<view>{{pageInfo.buyerReturn.express.no || '-'}}</view>
</view>
<view class="rb-line">
<view>备注</view>
<view>{{pageInfo.buyerReturn.express.mark || ''}}</view>
</view>
</view>
<!-- 商家同意退货 -->
<view class="rl-box" v-if="pageInfo.sellerReturn">
<view class="rb-store">
<image mode="aspectFill" :src="pageInfo.sellerReturn.image"></image>
<view class="rs-name">
<view>{{pageInfo.sellerReturn.name || '-'}}</view>
<view>{{pageInfo.sellerReturn.record_time || '-'}}</view>
</view>
</view>
<view class="rb-tit">{{pageInfo.sellerReturn.title || '-'}}</view>
<view class="rb-line">
<view>退货地址</view>
</view>
<view class="rb-user">
<text>{{pageInfo.sellerReturn.express.contacts || '-'}}</text>
<text>{{pageInfo.sellerReturn.express.mobile || '-'}}</text>
</view>
<view class="rb-addr">{{pageInfo.sellerReturn.express.addr || '-'}}</view>
<view class="rb-line">
<view>备注</view>
<view>{{pageInfo.sellerReturn.reply_content || ''}}</view>
</view>
</view>
<!-- 买家发起退款申请 -->
<view class="rl-box" v-if="pageInfo.buyerApply">
<view class="rb-store">
<image mode="aspectFill" :src="pageInfo.buyerApply.image || ''"></image>
<view class="rs-name">
<view>{{pageInfo.buyerApply.name || '-'}}</view>
<view>{{pageInfo.buyerApply.record_time || '-'}}</view>
</view>
</view>
<view class="rb-tit">{{pageInfo.buyerApply.title || '-'}}</view>
<view class="rb-line">
<view>退款类型</view>
<view>{{pageInfo.buyerApply.feedback_type == 0? '仅退款':'退货退款'}}</view>
</view>
<view class="rb-line">
<view>退款金额</view>
<view>¥{{pageInfo.buyerApply.refund_amount || 0}}含运费¥0</view>
</view>
<view class="rb-line">
<view>退积分</view>
<view>{{pageInfo.buyerApply.refund_integral || 0}}积分</view>
</view>
<view class="rb-line">
<view>退款原因</view>
<view>{{pageInfo.buyerApply.question_type || '-'}}</view>
</view>
<view class="rb-line">
<view>退款描述</view>
<view>{{pageInfo.buyerApply.question_desc || '-'}}</view>
</view>
<view class="rb-img">
<image mode="aspectFill" v-for="(e,i) in pageInfo.buyerApply.question_img" :key="i" :src="e"></image>
</view>
</view>
</view>
</template>
<script>
import util from '@/utils/util';
import { MALL_API } from "../../js/api";
import server from "../../js/server";
export default {
data() {
return {
recordsList: [],
buyerApply: {}, //退
sellerRefund: {}, //退
sellerReturn: {}, //退
buyerReturn: {}, //退
sellerRefuse: {}, //退
pageInfo: {},
}
},
onLoad(options) {
this.getFeedbackRecords({
brand_id: options?.brand_id ?? '',
id: options.id,
})
},
methods: {
//
getFeedbackRecords({ brand_id, id }){
util.showLoad();
server.get({
url: MALL_API.feedbackRecords,
data: {
brand_id,
id,
},
failMsg: '加载数据失败!'
})
.then(res => {
util.hideLoad();
console.log('getFeedbackRecords: ', res);
this.recordsList = res || []
let list = res || []
//record_status
// 0 退
// 1 退, 退
// 2 退
// 3 退
// 4 退退
// 5 退
let { recordsList } = this
if(list.length == 0)return -1;
for(var i in list){
if(list[i].record_status == 0){
this.pageInfo.buyerApply = list[i];
this.pageInfo.buyerApply.question_img = this.pageInfo.buyerApply.question_img.split(",")
}
if(list[i].record_status == 1)this.pageInfo.sellerRefund = list[i];
if(list[i].record_status == 2)this.pageInfo.sellerReturn = list[i];
if(list[i].record_status == 3)this.pageInfo.buyerReturn = list[i];
if(list[i].record_status == 4)this.pageInfo.sellerRefund = list[i];
if(list[i].record_status == 5)this.pageInfo.sellerRefuse = list[i];
}
});
},
}
}
</script>
<style lang="scss">
.refund-logs{
width: 100%;
.rl-box{
margin: 0rpx 24rpx 24rpx;
padding: 0 20rpx 30rpx;
border-radius: 10rpx;
background-color: #fff;
.rb-store{
padding: 20rpx 0;
border-bottom: 2rpx solid #D8D8D8;
@include ctf(flex-start);
>image{
flex-shrink: 0;
width: 88rpx;
height: 88rpx;
border-radius: 50%;
margin-right: 20rpx;
}
.rs-name{
>view{
&:first-child{
color: #333;
font-size: 28rpx;
font-weight: 700;
}
&:nth-child(2){
color: #9A9A9D;
font-size: 24rpx;
margin-top: 8rpx;
}
}
}
}
.rb-tit{
color: #333;
font-size: 28rpx;
padding: 16rpx 0;
}
.rb-line{
display: flex;
flex-direction: row;
justify-content: flex-start;
>view{
font-size: 28rpx;
line-height: 52rpx;
&:first-child{
flex-shrink: 0;
color: #9A9A9D;
width: 112rpx;
margin-right: 40rpx;
}
&:nth-child(2){
flex-grow: 1;
color: #333333;
}
}
}
.rb-user{
margin: 8rpx 0 12rpx;
>text{
font-size: 28rpx;
color: #333;
&:first-child{
}
&:nth-child(2){
margin-left: 30rpx;
}
}
}
.rb-addr{
color: #333;
font-size: 28rpx;
margin-bottom: 20rpx;
}
.rb-img{
margin-top: 32rpx;
>image{
display: inline-block;
width: 200rpx;
height: 200rpx;
border-radius: 10rpx;
margin-right: 20rpx;
}
}
}
}
</style>

BIN
src/subpackage/mall/static/images/cancel.png

After

Width: 32  |  Height: 32  |  Size: 356 B

BIN
src/subpackage/mall/static/images/close_c97_2.png

After

Width: 34  |  Height: 34  |  Size: 233 B

BIN
src/subpackage/mall/static/images/del.png

After

Width: 34  |  Height: 34  |  Size: 498 B

BIN
src/subpackage/mall/static/images/index/menu_1.png

After

Width: 48  |  Height: 48  |  Size: 311 B

BIN
src/subpackage/mall/static/images/index/menu_2.png

After

Width: 48  |  Height: 48  |  Size: 684 B

BIN
src/subpackage/mall/static/images/index/menu_3.png

After

Width: 48  |  Height: 48  |  Size: 851 B

BIN
src/subpackage/mall/static/images/price.png

After

Width: 34  |  Height: 34  |  Size: 1.3 KiB

Loading…
Cancel
Save