|
|
@@ -1,7 +1,9 @@
|
|
|
<!--
|
|
|
售后/退款记录列表
|
|
|
- 用途:工作台「退款记录」;顶部对齐 home/order.vue(日期+搜客户+状态Tab+筛选)。
|
|
|
- 接口:GET /refund/list?useDefaultLast30=1&sameDay=&status=&customId=
|
|
|
+ 用途:工作台「售后记录」;顶栏搜客户+筛选,日期进筛选面板,对齐 PC refund-list。
|
|
|
+ 筛选:售后申请日/通过日互斥、近30天默认、原单时间、订单日期、操作人。
|
|
|
+ Tab 带着日期口径:待审核只申请日;已通过默认通过日仍可切回;全部两个都能选。
|
|
|
+ Tab:全部 / 待审核 / 已通过。接口 GET /refund/list。
|
|
|
-->
|
|
|
<template>
|
|
|
<view class="app-content">
|
|
|
@@ -30,15 +32,6 @@
|
|
|
</view>
|
|
|
|
|
|
<view class="input-wrap_box">
|
|
|
- <view class="select-dn_bx">
|
|
|
- <DateSelect
|
|
|
- ref="dateSelectRef"
|
|
|
- class="bar"
|
|
|
- top="0"
|
|
|
- defaultShowName="近30天"
|
|
|
- @selectDateFn="selectDateFn"
|
|
|
- />
|
|
|
- </view>
|
|
|
<view class="search-container">
|
|
|
<AppSearchModule ref="appSearch" placeholder="这里搜索" @input="searchFn" />
|
|
|
<view v-if="customId != 0" class="search-clear-overlay" @click.stop="clearSearch">清空</view>
|
|
|
@@ -49,7 +42,7 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 状态 Tab:对齐 home/order.vue -->
|
|
|
+ <!-- 状态 Tab:对齐 PC,全部/待审核/已通过 -->
|
|
|
<view class="app-tabs">
|
|
|
<app-tabs
|
|
|
:tabs="tabs"
|
|
|
@@ -57,7 +50,7 @@
|
|
|
:top="50"
|
|
|
:currentTab="tabIndex"
|
|
|
:height="100"
|
|
|
- itemWidth="20%"
|
|
|
+ itemWidth="33.33%"
|
|
|
@change="onTabChange"
|
|
|
/>
|
|
|
</view>
|
|
|
@@ -109,10 +102,14 @@
|
|
|
<text class="meta-label">操作</text>
|
|
|
<text class="meta-value">{{ item.shopAdminName || '-' }}</text>
|
|
|
</view>
|
|
|
- <view class="meta-item meta-item--full">
|
|
|
- <text class="meta-label">日期</text>
|
|
|
+ <view class="meta-item">
|
|
|
+ <text class="meta-label">申请</text>
|
|
|
<text class="meta-value">{{ item.addTime ? item.addTime.substr(5, 11) : '-' }}</text>
|
|
|
</view>
|
|
|
+ <view class="meta-item" v-if="filterStatus !== 0">
|
|
|
+ <text class="meta-label">通过</text>
|
|
|
+ <text class="meta-value">{{ item.passTime ? item.passTime.substr(5, 11) : '-' }}</text>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
|
|
|
<view class="remark-box" v-if="!$util.isEmpty(item.remark)">
|
|
|
@@ -159,13 +156,39 @@
|
|
|
</block>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 筛选面板:仅售后类型(状态已提到顶部 Tab) -->
|
|
|
+ <!-- 筛选:申请日/通过日互斥 + 近30天、原单时间、订单日期、操作人 -->
|
|
|
<view v-if="showFilterPanel" class="filter-overlay" @click="closeFilterPanel">
|
|
|
<view class="filter-panel" @click.stop>
|
|
|
<view class="filter-header">筛选售后</view>
|
|
|
<scroll-view class="filter-body" scroll-y>
|
|
|
+ <view class="filter-section" v-if="showAfterSaleDateToggle">
|
|
|
+ <view class="filter-title">售后时间</view>
|
|
|
+ <view class="filter-options">
|
|
|
+ <view
|
|
|
+ v-for="(item, index) in afterSaleDateTypeOptions"
|
|
|
+ :key="index"
|
|
|
+ class="filter-option"
|
|
|
+ :class="{ active: afterSaleDateType === item.value }"
|
|
|
+ @click="onSelectAfterSaleDateType(index)"
|
|
|
+ >
|
|
|
+ {{ item.label }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
<view class="filter-section">
|
|
|
- <view class="filter-title">售后类型</view>
|
|
|
+ <view class="filter-title">{{ afterSaleDateTitle }}</view>
|
|
|
+ <view class="filter-date-wrap">
|
|
|
+ <DateSelect
|
|
|
+ ref="dateSelectRef"
|
|
|
+ class="bar"
|
|
|
+ top="0"
|
|
|
+ :defaultShowName="dateRangeLabel"
|
|
|
+ @selectDateFn="selectDateFn"
|
|
|
+ />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="filter-section">
|
|
|
+ <view class="filter-title">原单时间</view>
|
|
|
<view class="filter-options">
|
|
|
<view
|
|
|
v-for="(item, index) in sameDayOptions"
|
|
|
@@ -178,6 +201,37 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
+ <view class="filter-section">
|
|
|
+ <view class="filter-title">订单日期</view>
|
|
|
+ <view class="filter-date-wrap">
|
|
|
+ <DateSelect
|
|
|
+ ref="orderDateSelectRef"
|
|
|
+ class="bar"
|
|
|
+ top="0"
|
|
|
+ :defaultShowName="orderDateLabel"
|
|
|
+ @selectDateFn="selectOrderDateFn"
|
|
|
+ />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="filter-section">
|
|
|
+ <view class="filter-title">操作人</view>
|
|
|
+ <view class="filter-options">
|
|
|
+ <view
|
|
|
+ class="filter-option"
|
|
|
+ :class="{ active: filterShopAdminId === 0 }"
|
|
|
+ @click="onSelectStaff(0)"
|
|
|
+ >全部</view>
|
|
|
+ <view
|
|
|
+ v-for="(item, index) in staffList"
|
|
|
+ :key="index"
|
|
|
+ class="filter-option"
|
|
|
+ :class="{ active: filterShopAdminId === item.id }"
|
|
|
+ @click="onSelectStaff(item.id)"
|
|
|
+ >
|
|
|
+ {{ item.name }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
</scroll-view>
|
|
|
<view class="filter-actions">
|
|
|
<button class="filter-action-btn clear-btn" @click="clearFilters">重置</button>
|
|
|
@@ -196,6 +250,8 @@ import DateSelect from '@/components/module/dateSelect'
|
|
|
import { list } from '@/mixins'
|
|
|
import { refundList } from '@/api/refund'
|
|
|
import { getList } from '@/api/member'
|
|
|
+import { getStaffList } from '@/api/staff'
|
|
|
+import { mapGetters } from 'vuex'
|
|
|
|
|
|
export default {
|
|
|
name: 'freeRefundList',
|
|
|
@@ -203,43 +259,78 @@ export default {
|
|
|
mixins: [list],
|
|
|
data() {
|
|
|
return {
|
|
|
+ // 售后时间:默认近30天,申请日/通过日互斥共用这一份
|
|
|
+ afterSaleDateType: 'apply',
|
|
|
searchTime: 'last30Days',
|
|
|
startTime: '',
|
|
|
endTime: '',
|
|
|
+ dateRangeLabel: '近30天',
|
|
|
+ // 订单日期:不限时不传 searchTime,避免和售后日抢参数
|
|
|
+ orderSearchTime: '',
|
|
|
+ orderStartTime: '',
|
|
|
+ orderEndTime: '',
|
|
|
+ orderDateLabel: '不限',
|
|
|
totalAmount: 0,
|
|
|
- // -1全部 1当天售后 0跨天售后
|
|
|
+ // -1全部 1当天订单 0历史订单,对齐 PC 原单时间
|
|
|
sameDay: -1,
|
|
|
+ filterShopAdminId: 0,
|
|
|
+ staffList: [],
|
|
|
customId: 0,
|
|
|
searchList: [],
|
|
|
showSearch: false,
|
|
|
showFilterPanel: false,
|
|
|
tabIndex: 0,
|
|
|
- // id=-1 全部;其余与售后单 status 一致
|
|
|
+ // id=-1 全部;其余与售后单 status 一致;驳回/取消仍可在「全部」里看到
|
|
|
tabs: [
|
|
|
{ name: '全部', value: 0, id: -1 },
|
|
|
{ name: '待审核', value: 0, id: 0 },
|
|
|
- { name: '已通过', value: 0, id: 1 },
|
|
|
- { name: '已驳回', value: 0, id: 2 },
|
|
|
- { name: '已取消', value: 0, id: 3 }
|
|
|
+ { name: '已通过', value: 0, id: 1 }
|
|
|
+ ],
|
|
|
+ afterSaleDateTypeOptions: [
|
|
|
+ { label: '申请日期', value: 'apply' },
|
|
|
+ { label: '通过日期', value: 'pass' }
|
|
|
],
|
|
|
sameDayOptions: [
|
|
|
{ label: '全部', value: -1 },
|
|
|
- { label: '当天售后', value: 1 },
|
|
|
- { label: '跨天售后', value: 0 }
|
|
|
+ { label: '当天订单', value: 1 },
|
|
|
+ { label: '历史订单', value: 0 }
|
|
|
]
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
+ ...mapGetters(['getDictionariesInfo']),
|
|
|
+ /**
|
|
|
+ * 红点:相对当前 Tab 的默认口径才算「有筛选」。
|
|
|
+ * 已通过默认就是通过日,不能因为 pass 一直亮点。
|
|
|
+ */
|
|
|
hasActiveFilters() {
|
|
|
- return this.sameDay !== -1
|
|
|
+ const defaultDateType = this.filterStatus === 1 ? 'pass' : 'apply'
|
|
|
+ return (
|
|
|
+ this.sameDay !== -1
|
|
|
+ || this.afterSaleDateType !== defaultDateType
|
|
|
+ || this.searchTime !== 'last30Days'
|
|
|
+ || !!this.startTime
|
|
|
+ || !!this.endTime
|
|
|
+ || !!this.orderSearchTime
|
|
|
+ || this.filterShopAdminId !== 0
|
|
|
+ )
|
|
|
},
|
|
|
/** 当前 Tab 对应的 status,全部为 -1 */
|
|
|
filterStatus() {
|
|
|
const tab = this.tabs[this.tabIndex]
|
|
|
return tab ? tab.id : -1
|
|
|
+ },
|
|
|
+ /** 待审核不给通过日切换,避免筛空 */
|
|
|
+ showAfterSaleDateToggle() {
|
|
|
+ return this.filterStatus !== 0
|
|
|
+ },
|
|
|
+ /** 时间范围标题:跟着当前口径走,待审核没有切换按钮时也能看懂 */
|
|
|
+ afterSaleDateTitle() {
|
|
|
+ return this.afterSaleDateType === 'pass' ? '通过日期' : '申请日期'
|
|
|
}
|
|
|
},
|
|
|
onLoad() {
|
|
|
+ this.loadStaffList()
|
|
|
this.resetList()
|
|
|
this._list()
|
|
|
},
|
|
|
@@ -282,12 +373,48 @@ export default {
|
|
|
const map = { 0: '待审核', 1: '已通过', 2: '已驳回', 3: '已取消' }
|
|
|
return map[status] || ''
|
|
|
},
|
|
|
+ /**
|
|
|
+ * 售后时间范围:只记参数,点「确定」再刷列表,避免面板里选日期立刻关面板。
|
|
|
+ */
|
|
|
selectDateFn(val) {
|
|
|
this.searchTime = val.searchTime || 'last30Days'
|
|
|
this.startTime = val.startTime || ''
|
|
|
this.endTime = val.endTime || ''
|
|
|
- this.resetList()
|
|
|
- this._list()
|
|
|
+ this.dateRangeLabel = this.resolveDateLabel(val, '近30天')
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 订单日期:单独一组 searchTime,和售后日互不影响。
|
|
|
+ */
|
|
|
+ selectOrderDateFn(val) {
|
|
|
+ this.orderSearchTime = val.searchTime || ''
|
|
|
+ this.orderStartTime = val.startTime || ''
|
|
|
+ this.orderEndTime = val.endTime || ''
|
|
|
+ this.orderDateLabel = this.resolveDateLabel(val, '不限')
|
|
|
+ },
|
|
|
+ /** 根据 DateSelect 回传还原展示文案 */
|
|
|
+ resolveDateLabel(val, fallback) {
|
|
|
+ if (!val || !val.searchTime) {
|
|
|
+ return fallback
|
|
|
+ }
|
|
|
+ if (val.searchTime === 'custom' && val.startTime) {
|
|
|
+ const s = String(val.startTime).substring(5)
|
|
|
+ const e = String(val.endTime || val.startTime).substring(5)
|
|
|
+ return s === e ? s : s + '/' + e
|
|
|
+ }
|
|
|
+ if (val.searchTime === 'byMonth' && val.startTime) {
|
|
|
+ return val.startTime
|
|
|
+ }
|
|
|
+ const opts = (this.getDictionariesInfo && this.getDictionariesInfo.dateDefaultOption) || []
|
|
|
+ const hit = opts.find((o) => o.value === val.searchTime)
|
|
|
+ return hit ? hit.name : fallback
|
|
|
+ },
|
|
|
+ /** 拉员工列表,给筛选「操作人」用 */
|
|
|
+ loadStaffList() {
|
|
|
+ getStaffList().then((res) => {
|
|
|
+ if (res.code == 1) {
|
|
|
+ this.staffList = (res.data && res.data.list) || []
|
|
|
+ }
|
|
|
+ })
|
|
|
},
|
|
|
/**
|
|
|
* 搜索客户:本页下拉联想(对齐 order.vue),不跳转 selectCustom
|
|
|
@@ -343,18 +470,52 @@ export default {
|
|
|
this.sameDay = item.value
|
|
|
}
|
|
|
},
|
|
|
- /** 切换状态 Tab,刷新列表 */
|
|
|
+ /** 申请日 / 通过日二选一,日期范围复用 */
|
|
|
+ onSelectAfterSaleDateType(index) {
|
|
|
+ const item = this.afterSaleDateTypeOptions[index]
|
|
|
+ if (item) {
|
|
|
+ this.afterSaleDateType = item.value
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * Tab 带着日期口径走:待审核强制申请日,已通过默认通过日,全部保持当前选择。
|
|
|
+ */
|
|
|
+ syncDateTypeByTab() {
|
|
|
+ if (this.filterStatus === 0) {
|
|
|
+ this.afterSaleDateType = 'apply'
|
|
|
+ } else if (this.filterStatus === 1) {
|
|
|
+ this.afterSaleDateType = 'pass'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onSelectStaff(id) {
|
|
|
+ this.filterShopAdminId = id
|
|
|
+ },
|
|
|
+ /** 订单日期改回不限,避免误把原单日当成售后日 */
|
|
|
+ clearOrderDate() {
|
|
|
+ this.orderSearchTime = ''
|
|
|
+ this.orderStartTime = ''
|
|
|
+ this.orderEndTime = ''
|
|
|
+ this.orderDateLabel = '不限'
|
|
|
+ if (this.$refs.orderDateSelectRef && this.$refs.orderDateSelectRef.reset) {
|
|
|
+ this.$refs.orderDateSelectRef.reset()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /** 切换状态 Tab,先对齐日期口径再刷列表 */
|
|
|
onTabChange(e) {
|
|
|
if (this.tabIndex === e.index) {
|
|
|
return
|
|
|
}
|
|
|
this.tabIndex = e.index
|
|
|
+ this.syncDateTypeByTab()
|
|
|
this.resetList()
|
|
|
this._list()
|
|
|
},
|
|
|
clearFilters() {
|
|
|
this.sameDay = -1
|
|
|
+ this.afterSaleDateType = this.filterStatus === 1 ? 'pass' : 'apply'
|
|
|
+ this.filterShopAdminId = 0
|
|
|
this.resetDefaultDateRange()
|
|
|
+ this.clearOrderDate()
|
|
|
this.closeFilterPanel()
|
|
|
this.resetList()
|
|
|
this._list()
|
|
|
@@ -363,6 +524,7 @@ export default {
|
|
|
this.searchTime = 'last30Days'
|
|
|
this.startTime = ''
|
|
|
this.endTime = ''
|
|
|
+ this.dateRangeLabel = '近30天'
|
|
|
if (this.$refs.dateSelectRef && this.$refs.dateSelectRef.reset) {
|
|
|
this.$refs.dateSelectRef.reset()
|
|
|
}
|
|
|
@@ -464,16 +626,31 @@ export default {
|
|
|
})
|
|
|
})
|
|
|
},
|
|
|
+ /**
|
|
|
+ * 申请日走 refundSearchTime,通过日走 passSearchTime;自定义区间用 refund/pass 的 Start/End,
|
|
|
+ * 不占用 startTime(那是订单日期),否则自定义售后日对不上。
|
|
|
+ */
|
|
|
_list() {
|
|
|
const params = {
|
|
|
page: this.list.page,
|
|
|
- useDefaultLast30: 1,
|
|
|
- refundSearchTime: this.searchTime,
|
|
|
- startTime: this.startTime,
|
|
|
- endTime: this.endTime,
|
|
|
sameDay: this.sameDay,
|
|
|
status: this.filterStatus,
|
|
|
- customId: this.customId || ''
|
|
|
+ customId: this.customId || '',
|
|
|
+ shopAdminId: this.filterShopAdminId || ''
|
|
|
+ }
|
|
|
+ if (this.afterSaleDateType === 'pass') {
|
|
|
+ params.passSearchTime = this.searchTime
|
|
|
+ params.passStartTime = this.startTime
|
|
|
+ params.passEndTime = this.endTime
|
|
|
+ } else {
|
|
|
+ params.refundSearchTime = this.searchTime
|
|
|
+ params.refundStartTime = this.startTime
|
|
|
+ params.refundEndTime = this.endTime
|
|
|
+ }
|
|
|
+ if (this.orderSearchTime) {
|
|
|
+ params.searchTime = this.orderSearchTime
|
|
|
+ params.startTime = this.orderStartTime
|
|
|
+ params.endTime = this.orderEndTime
|
|
|
}
|
|
|
return refundList(params).then((res) => {
|
|
|
this.completes(res)
|
|
|
@@ -545,11 +722,6 @@ export default {
|
|
|
padding: 0 10upx;
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
-.select-dn_bx {
|
|
|
- padding-left: 10upx;
|
|
|
- padding-right: 10upx;
|
|
|
- flex-shrink: 0;
|
|
|
-}
|
|
|
.search-container {
|
|
|
position: relative;
|
|
|
flex: 1;
|
|
|
@@ -815,6 +987,19 @@ export default {
|
|
|
font-size: 28upx;
|
|
|
font-weight: 700;
|
|
|
}
|
|
|
+/* 筛选内 DateSelect:抬高层级,避免被筛选遮罩挡住 */
|
|
|
+.filter-date-wrap {
|
|
|
+ padding: 10upx 0;
|
|
|
+ ::v-deep .select-mark-view {
|
|
|
+ z-index: 10000001 !important;
|
|
|
+ }
|
|
|
+ ::v-deep .select-fixed_bx {
|
|
|
+ z-index: 10000002 !important;
|
|
|
+ }
|
|
|
+ ::v-deep .picker {
|
|
|
+ z-index: 10000003 !important;
|
|
|
+ }
|
|
|
+}
|
|
|
.filter-options {
|
|
|
display: flex;
|
|
|
flex-wrap: wrap;
|