|
|
@@ -16,7 +16,7 @@
|
|
|
<view class="date-filter-icon">
|
|
|
<view class="date-filter-icon-line"></view>
|
|
|
</view>
|
|
|
- <text class="date-filter-text">{{ period === 'custom' ? startDate + ' 至 ' + endDate : '时间区间' }}</text>
|
|
|
+ <text class="date-filter-text">{{ period === 'custom' ? '已选' : '时间' }}</text>
|
|
|
<!-- <text class="date-filter-hint">{{ period === 'custom' ? '重选' : '选择日期' }}</text> -->
|
|
|
<view class="date-filter-arrow"></view>
|
|
|
</view>
|
|
|
@@ -28,7 +28,7 @@
|
|
|
@click="changePeriod(p.value)"
|
|
|
>{{ p.name }}</view>
|
|
|
</view>
|
|
|
- <scroll-view scroll-x class="status-tabs">
|
|
|
+ <view class="status-tabs">
|
|
|
<view
|
|
|
v-for="tab in statusTabs"
|
|
|
:key="tab.key"
|
|
|
@@ -39,7 +39,7 @@
|
|
|
<text>{{ tab.name }}</text>
|
|
|
<text class="tab-num">{{ counts[tab.key] || 0 }}</text>
|
|
|
</view>
|
|
|
- </scroll-view>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
|
|
|
<view class="list-wrap">
|
|
|
@@ -47,6 +47,7 @@
|
|
|
v-for="(item, index) in list.data"
|
|
|
:key="item.id || index"
|
|
|
class="gift-card"
|
|
|
+ @click="goCustomDetail(index)"
|
|
|
>
|
|
|
<image v-if="item.avatar" class="avatar" :src="item.avatar" mode="aspectFill" />
|
|
|
<view v-else class="avatar placeholder" />
|
|
|
@@ -60,18 +61,17 @@
|
|
|
:src="memberBadgeSrc(item.member)"
|
|
|
mode="aspectFit"
|
|
|
/>
|
|
|
- <text v-if="item.memberName" class="level-name">{{ item.memberName }}</text>
|
|
|
</view>
|
|
|
<view class="info-row">
|
|
|
<view class="info-lines">
|
|
|
- <view v-if="item.status === 0" class="line link" @click="fillBirthday(index, list.data)">点击填写生日</view>
|
|
|
- <view v-else class="line">生日:{{ item.birthdayDisplay }}</view>
|
|
|
- <view class="line gift-line">生日赠礼:{{ item.giftName || '—' }}</view>
|
|
|
- <view v-if="item.status === 3 && item.pickupTime" class="line sub">预约领取时间:{{ formatTime(item.pickupTime) }}</view>
|
|
|
+ <view v-if="item.status === 0" class="line link" @click.stop="fillBirthday(index, list.data)">点击填写生日</view>
|
|
|
+ <view v-else class="line gift-line">生日:{{ item.birthdayDisplay }}</view>
|
|
|
+ <view class="line gift-line">礼品:{{ item.giftName || '—' }}</view>
|
|
|
+ <view v-if="item.status === 3 && item.pickupTime" class="line sub">预约时间:{{ formatTime(item.pickupTime) }}</view>
|
|
|
<view v-if="item.status === 4 && item.collectTime" class="line sub">领取时间:{{ formatTime(item.collectTime) }}</view>
|
|
|
- <view v-if="item.status === 5" class="line sub">预约领取时间:超时自动放弃</view>
|
|
|
</view>
|
|
|
<view
|
|
|
+ v-if="shouldShowStatusBadge(item)"
|
|
|
class="status-badge"
|
|
|
:class="['st-' + item.status, { clickable: canOperateStatus(item), disabled: isNotifyDisabled(item) }]"
|
|
|
@click.stop="confirmStatusAction(index, list.data)"
|
|
|
@@ -170,6 +170,7 @@ import ModalModule from '@/components/plugin/modal'
|
|
|
import { getBoardList, getBoardCounts, notifyTomorrow, notifyBirthdayGift, modifyBirthday, collectBirthdayGift } from '@/api/birthday'
|
|
|
import { iconSrc } from '@/utils/iconSrc'
|
|
|
|
|
|
+// 生日看板供花店员工查看客户生日与赠礼状态,并处理通知、领取及生日补录流程。
|
|
|
export default {
|
|
|
name: 'BirthdayBoard',
|
|
|
components: { AppWrapperEmpty, ModalModule },
|
|
|
@@ -177,7 +178,7 @@ export default {
|
|
|
data() {
|
|
|
return {
|
|
|
searchText: '',
|
|
|
- period: 'week',
|
|
|
+ period: 'tomorrow',
|
|
|
startDate: '',
|
|
|
endDate: '',
|
|
|
draftStartDate: '',
|
|
|
@@ -192,8 +193,8 @@ export default {
|
|
|
monthArray: Array.from({ length: 12 }, (_, i) => i + 1),
|
|
|
dateArray: Array.from({ length: 31 }, (_, i) => i + 1),
|
|
|
periodTabs: [
|
|
|
- { name: '今日', value: 'today' },
|
|
|
- { name: '明日', value: 'tomorrow' },
|
|
|
+ { name: '今天', value: 'today' },
|
|
|
+ { name: '明天', value: 'tomorrow' },
|
|
|
{ name: '近一周', value: 'week' },
|
|
|
{ name: '全部', value: 'all' }
|
|
|
],
|
|
|
@@ -202,8 +203,8 @@ export default {
|
|
|
{ name: '待通知', key: 'pendingNotify', value: 1 },
|
|
|
{ name: '待领取', key: 'pendingClaim', value: 2 },
|
|
|
{ name: '已领取', key: 'collected', value: 4 },
|
|
|
- { name: '未填写', key: 'noBirthday', value: 0 },
|
|
|
- { name: '超时放弃', key: 'expired', value: 5 }
|
|
|
+ { name: '已放弃', key: 'expired', value: 5 },
|
|
|
+ { name: '没生日', key: 'noBirthday', value: 0 }
|
|
|
],
|
|
|
counts: {},
|
|
|
collectSubmitting: false,
|
|
|
@@ -344,6 +345,18 @@ export default {
|
|
|
isNotifyDisabled(item = {}) {
|
|
|
return Number(item.status) === 1 && !this.canNotify(item)
|
|
|
},
|
|
|
+ // 控制状态标签是否展示;待通知记录的公历生日早于今天时隐藏,日期缺失或格式异常时保留展示。
|
|
|
+ shouldShowStatusBadge(item = {}) {
|
|
|
+ if (item.statusName !== '待通知') return true
|
|
|
+ const match = String(item.birthdayDisplay || '').match(/(\d{1,2})月(\d{1,2})日/)
|
|
|
+ if (!match) return true
|
|
|
+ const birthdayMonth = Number(match[1])
|
|
|
+ const birthdayDate = Number(match[2])
|
|
|
+ const today = new Date()
|
|
|
+ const currentMonth = today.getMonth() + 1
|
|
|
+ const currentDate = today.getDate()
|
|
|
+ return birthdayMonth > currentMonth || (birthdayMonth === currentMonth && birthdayDate >= currentDate)
|
|
|
+ },
|
|
|
confirmStatusAction(index, list) {
|
|
|
const item = list[index]
|
|
|
if (this.canNotify(item)) {
|
|
|
@@ -401,6 +414,20 @@ export default {
|
|
|
getCustomId(item = {}) {
|
|
|
return item.customId || item.custom_id || item.custom?.id || ''
|
|
|
},
|
|
|
+ // 点击列表项进入客户详情(用 index 取数,兼容小程序 click 不传 item 的问题)
|
|
|
+ goCustomDetail(index) {
|
|
|
+ const item = this.list.data[index]
|
|
|
+ if (!item) {
|
|
|
+ this.$msg('客户信息异常')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const id = this.getCustomId(item)
|
|
|
+ if (!id) {
|
|
|
+ this.$msg('客户信息异常')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.$util.pageTo({ url: '/admin/member/detail?id=' + id })
|
|
|
+ },
|
|
|
fillBirthday(index, list) {
|
|
|
const item = list[index]
|
|
|
this.birthdayModal = true
|
|
|
@@ -465,14 +492,19 @@ export default {
|
|
|
gap: 12upx;
|
|
|
}
|
|
|
.green-btn {
|
|
|
- padding: 12upx 22upx;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ min-height: 80upx;
|
|
|
+ padding: 0 28upx;
|
|
|
background: linear-gradient(135deg, #19d471, #08b955);
|
|
|
color: #fff;
|
|
|
- font-size: 26upx;
|
|
|
+ font-size: 28upx;
|
|
|
border-radius: 8upx;
|
|
|
}
|
|
|
.green-btn.outline {
|
|
|
- padding: 10upx 22upx;
|
|
|
+ min-height: 80upx;
|
|
|
+ padding: 0 28upx;
|
|
|
background: #fff;
|
|
|
color: #08b955;
|
|
|
border: 1upx solid #08b955;
|
|
|
@@ -483,11 +515,11 @@ export default {
|
|
|
position: relative;
|
|
|
}
|
|
|
.search-inp {
|
|
|
- height: 64upx;
|
|
|
+ height: 80upx;
|
|
|
background: #f1f3f2;
|
|
|
- border-radius: 32upx;
|
|
|
+ border-radius: 40upx;
|
|
|
padding: 0 72upx 0 24upx;
|
|
|
- font-size: 26upx;
|
|
|
+ font-size: 28upx;
|
|
|
}
|
|
|
.search-clear {
|
|
|
position: absolute;
|
|
|
@@ -510,25 +542,34 @@ export default {
|
|
|
}
|
|
|
.filter-row {
|
|
|
display: flex;
|
|
|
- align-items: center;
|
|
|
+ align-items: stretch;
|
|
|
margin-top: 20upx;
|
|
|
- flex-wrap: wrap;
|
|
|
+}
|
|
|
+.filter-row > view:not(:first-child) {
|
|
|
+ margin-left: 10upx;
|
|
|
}
|
|
|
.date-filter-trigger {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
display: flex;
|
|
|
+ flex-direction: row;
|
|
|
align-items: center;
|
|
|
- height: 52upx;
|
|
|
- padding: 0 18upx;
|
|
|
- margin-right: 12upx;
|
|
|
- margin-bottom: 10upx;
|
|
|
+ justify-content: center;
|
|
|
+ height: 68upx;
|
|
|
+ padding: 0 12upx;
|
|
|
+ box-sizing: border-box;
|
|
|
background: #f0fbf5;
|
|
|
border: 1upx solid #08b955;
|
|
|
- border-radius: 28upx;
|
|
|
+ border-radius: 34upx;
|
|
|
box-shadow: 0 4upx 12upx rgba(8, 185, 85, 0.12);
|
|
|
}
|
|
|
.date-filter-icon {
|
|
|
- width: 24upx;
|
|
|
- height: 24upx;
|
|
|
+ flex-shrink: 0;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 28upx;
|
|
|
+ height: 28upx;
|
|
|
margin-right: 8upx;
|
|
|
border: 2upx solid #08b955;
|
|
|
border-radius: 5upx;
|
|
|
@@ -552,12 +593,15 @@ export default {
|
|
|
right: 4upx;
|
|
|
}
|
|
|
.date-filter-icon-line {
|
|
|
+ width: 14upx;
|
|
|
height: 2upx;
|
|
|
- margin-top: 7upx;
|
|
|
+ margin-top: 4upx;
|
|
|
background: #08b955;
|
|
|
}
|
|
|
.date-filter-text {
|
|
|
- font-size: 24upx;
|
|
|
+ flex-shrink: 0;
|
|
|
+ line-height: 26upx;
|
|
|
+ font-size: 26upx;
|
|
|
color: #08b955;
|
|
|
font-weight: 500;
|
|
|
}
|
|
|
@@ -567,18 +611,25 @@ export default {
|
|
|
color: #6abf8e;
|
|
|
}
|
|
|
.date-filter-arrow {
|
|
|
+ flex-shrink: 0;
|
|
|
+ align-self: center;
|
|
|
width: 12upx;
|
|
|
height: 12upx;
|
|
|
- margin-left: 8upx;
|
|
|
+ margin-left: 6upx;
|
|
|
border-top: 2upx solid #08b955;
|
|
|
border-right: 2upx solid #08b955;
|
|
|
- transform: rotate(45deg);
|
|
|
+ transform: rotate(45deg) translateY(-1upx);
|
|
|
}
|
|
|
.pill {
|
|
|
- padding: 8upx 20upx;
|
|
|
- margin-right: 12upx;
|
|
|
- font-size: 24upx;
|
|
|
- border-radius: 24upx;
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ min-height: 68upx;
|
|
|
+ padding: 0 8upx;
|
|
|
+ font-size: 26upx;
|
|
|
+ border-radius: 34upx;
|
|
|
background: #e8f8ef;
|
|
|
color: #333;
|
|
|
}
|
|
|
@@ -617,16 +668,19 @@ export default {
|
|
|
color: #999;
|
|
|
}
|
|
|
.status-tabs {
|
|
|
- white-space: nowrap;
|
|
|
+ display: flex;
|
|
|
+ align-items: stretch;
|
|
|
margin-top: 16upx;
|
|
|
padding-bottom: 12upx;
|
|
|
}
|
|
|
.status-tab {
|
|
|
- display: inline-flex;
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
- padding: 12upx 20upx;
|
|
|
- font-size: 24upx;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 14upx 4upx;
|
|
|
+ font-size: 28upx;
|
|
|
color: #666;
|
|
|
}
|
|
|
.status-tab.active {
|
|
|
@@ -634,8 +688,8 @@ export default {
|
|
|
font-weight: 600;
|
|
|
}
|
|
|
.tab-num {
|
|
|
- font-size: 22upx;
|
|
|
- margin-top: 4upx;
|
|
|
+ font-size: 26upx;
|
|
|
+ margin-top: 6upx;
|
|
|
}
|
|
|
.list-wrap {
|
|
|
padding: 16upx 24upx;
|
|
|
@@ -670,24 +724,17 @@ export default {
|
|
|
gap: 8upx;
|
|
|
}
|
|
|
.name {
|
|
|
- font-size: 30upx;
|
|
|
+ font-size: 34upx;
|
|
|
font-weight: 600;
|
|
|
}
|
|
|
.mobile {
|
|
|
- font-size: 24upx;
|
|
|
+ font-size: 28upx;
|
|
|
color: #888;
|
|
|
}
|
|
|
.level-icon {
|
|
|
width: 40upx;
|
|
|
height: 40upx;
|
|
|
}
|
|
|
-.level-name {
|
|
|
- font-size: 22upx;
|
|
|
- color: #08b955;
|
|
|
- background: #e8f8ef;
|
|
|
- padding: 2upx 10upx;
|
|
|
- border-radius: 8upx;
|
|
|
-}
|
|
|
.info-row {
|
|
|
display: flex;
|
|
|
align-items: flex-start;
|
|
|
@@ -697,16 +744,16 @@ export default {
|
|
|
min-width: 0;
|
|
|
}
|
|
|
.line {
|
|
|
- font-size: 24upx;
|
|
|
+ font-size: 26upx;
|
|
|
color: #666;
|
|
|
- margin-top: 8upx;
|
|
|
+ margin-top:10upx;
|
|
|
}
|
|
|
.line.link {
|
|
|
color: #1989fa;
|
|
|
}
|
|
|
.line.sub {
|
|
|
color: #999;
|
|
|
- font-size: 22upx;
|
|
|
+ font-size: 24upx;
|
|
|
}
|
|
|
.gift-line {
|
|
|
color: #333;
|