This commit is contained in:
zhanchao 2026-08-03 10:03:56 +08:00
parent 6314ceb65a
commit 923edea8bf
4 changed files with 155 additions and 37 deletions

View File

@ -1,31 +1,39 @@
<template>
<full-page pageClass="coupons-page" :customScroll="true">
<view class="page-body">
<view v-if="loading" class="empty">加载中...</view>
<view v-else-if="!list.length" class="empty">暂无待领取体验券</view>
<view v-else class="coupon-list">
<view
v-for="item in list"
:key="item._id"
class="coupon-card"
@click="openPoster(item)"
>
<image
v-if="item.posterUrl"
class="coupon-poster"
:src="item.posterUrl"
mode="aspectFill"
/>
<view v-else class="coupon-poster coupon-poster--empty">体验券</view>
<view class="coupon-body">
<view class="coupon-title">{{ item.activityName || "体验券" }}</view>
<view class="coupon-meta">{{ item.projectText }}</view>
<view class="coupon-meta">{{ item.validText }}</view>
<view class="coupon-action">点击查看海报领取</view>
<scroll-view
class="coupon-scroll"
scroll-y="true"
refresher-enabled="true"
:refresher-triggered="refreshing"
@refresherrefresh="refreshCoupons"
>
<view class="page-body">
<view v-if="loading" class="empty">加载中...</view>
<view v-else-if="!list.length" class="empty">暂无待领取体验券</view>
<view v-else class="coupon-list">
<view
v-for="item in list"
:key="item._id"
class="coupon-card"
@click="openPoster(item)"
>
<image
v-if="item.posterUrl"
class="coupon-poster"
:src="item.posterUrl"
mode="aspectFill"
/>
<view v-else class="coupon-poster coupon-poster--empty">体验券</view>
<view class="coupon-body">
<view class="coupon-title">{{ item.activityName || "体验券" }}</view>
<view class="coupon-meta">{{ item.projectText }}</view>
<view class="coupon-meta">{{ item.validText }}</view>
<view class="coupon-action">点击查看海报领取</view>
</view>
</view>
</view>
</view>
</view>
</scroll-view>
<!-- 海报领取弹窗 -->
<view v-if="posterVisible" class="poster-mask" @click="closePoster">
@ -67,6 +75,7 @@ const teamId = ref("");
const customerId = ref("");
const list = ref([]);
const loading = ref(false);
const refreshing = ref(false);
const posterVisible = ref(false);
const current = ref(null);
const claiming = ref(false);
@ -163,12 +172,13 @@ async function voidExpired(item) {
}
}
async function loadCoupons() {
async function loadCoupons(options = {}) {
const { silent = false } = options;
if (!corpId.value || !customerId.value) {
list.value = [];
return;
}
loading.value = true;
if (!silent) loading.value = true;
try {
const res = await api(
"getCustomerExperienceCoupons",
@ -205,6 +215,16 @@ async function loadCoupons() {
}
}
async function refreshCoupons() {
if (refreshing.value) return;
refreshing.value = true;
try {
await loadCoupons({ silent: true });
} finally {
refreshing.value = false;
}
}
function openPoster(item) {
if (!item?.posterUrl) {
toast("该体验券暂无海报");
@ -263,6 +283,15 @@ onShow(async () => {
</script>
<style scoped>
.coupons-page :deep(.page-scroll) {
overflow: hidden;
}
.coupon-scroll {
height: 100%;
background: #f5f5f5;
}
.page-body {
min-height: 100%;
padding: 24rpx 30rpx 40rpx;

View File

@ -1,6 +1,13 @@
<template>
<full-page pageClass="rights-page" :customScroll="true">
<view class="page-body">
<scroll-view
class="rights-scroll"
scroll-y="true"
refresher-enabled="true"
:refresher-triggered="refreshing"
@refresherrefresh="refreshRights"
>
<view class="page-body">
<view class="user-card" @click="toSelectPage">
<view class="avatar">
<uni-icons type="person-filled" size="36" color="#c0c4cc" />
@ -38,7 +45,8 @@
</view>
</view>
</view>
</view>
</view>
</scroll-view>
</full-page>
</template>
@ -66,6 +74,7 @@ const corpName = ref("");
const teams = ref([]);
const records = ref([]);
const loading = ref(false);
const refreshing = ref(false);
function formatDate(ts) {
if (!ts) return "无限期";
@ -187,12 +196,13 @@ async function resolveContext(options = {}) {
return !!customerId.value;
}
async function loadRights() {
async function loadRights(options = {}) {
const { silent = false } = options;
if (!corpId.value || !customerId.value) {
records.value = [];
return;
}
loading.value = true;
if (!silent) loading.value = true;
try {
const res = await api(
"getTreatmentRecord",
@ -215,6 +225,16 @@ async function loadRights() {
}
}
async function refreshRights() {
if (refreshing.value) return;
refreshing.value = true;
try {
await loadRights({ silent: true });
} finally {
refreshing.value = false;
}
}
async function syncSelectedProfile() {
const selected = get(RIGHTS_SELECTION_CACHE_KEY);
if (!selected) return false;
@ -256,6 +276,15 @@ onShow(async () => {
</script>
<style scoped>
.rights-page :deep(.page-scroll) {
overflow: hidden;
}
.rights-scroll {
height: 100%;
background: #f5f5f5;
}
.page-body {
min-height: 100%;
padding: 0 0 40rpx;

View File

@ -1,6 +1,13 @@
<template>
<full-page pageClass="record-page" :customScroll="true">
<view class="page-body">
<scroll-view
class="record-scroll"
scroll-y="true"
refresher-enabled="true"
:refresher-triggered="refreshing"
@refresherrefresh="refreshRecords"
>
<view class="page-body">
<view class="profile-card" @click="switchArchive">
<view class="avatar-wrap">
<view class="avatar-placeholder">{{ avatarText }}</view>
@ -46,7 +53,8 @@
</view>
</view>
</view>
</view>
</view>
</scroll-view>
</full-page>
</template>
@ -67,6 +75,7 @@ const selectedMonth = ref(formatMonth(Date.now()));
const records = ref([]);
const staffNameMap = ref({});
const loading = ref(false);
const refreshing = ref(false);
const statusMap = {
pending: { label: "未到院" },
@ -173,12 +182,13 @@ async function loadStaffNameMap() {
}, {});
}
async function loadRecords() {
async function loadRecords(options = {}) {
const { silent = false } = options;
if (!corpId.value || !customerId.value) {
records.value = [];
return;
}
loading.value = true;
if (!silent) loading.value = true;
try {
const range = monthRange(selectedMonth.value);
const res = await api(
@ -210,6 +220,17 @@ async function loadRecords() {
}
}
async function refreshRecords() {
if (refreshing.value) return;
refreshing.value = true;
try {
await loadStaffNameMap();
await loadRecords({ silent: true });
} finally {
refreshing.value = false;
}
}
async function handleMonthChange(event) {
selectedMonth.value = event?.detail?.value || selectedMonth.value;
await loadRecords();
@ -233,6 +254,15 @@ onShow(() => {
</script>
<style scoped>
.record-page :deep(.page-scroll) {
overflow: hidden;
}
.record-scroll {
height: 100%;
background: #e9edf3;
}
.page-body {
min-height: 100%;
box-sizing: border-box;

View File

@ -1,6 +1,13 @@
<template>
<full-page pageClass="record-page" :customScroll="true">
<view class="page-body">
<scroll-view
class="record-scroll"
scroll-y="true"
refresher-enabled="true"
:refresher-triggered="refreshing"
@refresherrefresh="refreshRecords"
>
<view class="page-body">
<view class="profile-card" @click="switchArchive">
<view class="avatar-wrap">
<view class="avatar-placeholder">{{ avatarText }}</view>
@ -66,7 +73,8 @@
</view>
</view>
</view>
</view>
</view>
</scroll-view>
</full-page>
</template>
@ -87,6 +95,7 @@ const selectedMonth = ref(formatMonth(Date.now()));
const records = ref([]);
const staffNameMap = ref({});
const loading = ref(false);
const refreshing = ref(false);
const avatarText = computed(() => (customerName.value || "档案").slice(0, 1));
const monthText = computed(() => selectedMonth.value.replace("-", "年") + "月");
@ -163,12 +172,13 @@ function switchArchive() {
});
}
async function loadRecords() {
async function loadRecords(options = {}) {
const { silent = false } = options;
if (!corpId.value || !customerId.value) {
records.value = [];
return;
}
loading.value = true;
if (!silent) loading.value = true;
try {
const res = await api(
"getDeductRecord",
@ -196,6 +206,17 @@ async function loadRecords() {
}
}
async function refreshRecords() {
if (refreshing.value) return;
refreshing.value = true;
try {
await loadStaffNameMap();
await loadRecords({ silent: true });
} finally {
refreshing.value = false;
}
}
async function handleMonthChange(event) {
selectedMonth.value = event?.detail?.value || selectedMonth.value;
await loadRecords();
@ -219,6 +240,15 @@ onShow(() => {
</script>
<style scoped>
.record-page :deep(.page-scroll) {
overflow: hidden;
}
.record-scroll {
height: 100%;
background: #e9edf3;
}
.page-body {
min-height: 100%;
box-sizing: border-box;