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

View File

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

View File

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

View File

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