diff --git a/pages/experience-coupon/claim.vue b/pages/experience-coupon/claim.vue index 53efec1..5e22f25 100644 --- a/pages/experience-coupon/claim.vue +++ b/pages/experience-coupon/claim.vue @@ -5,19 +5,10 @@ 加载中... - - - - {{ issue?.activityName || "体验券" }} - {{ projectText }} - {{ validText }} - + + {{ buildClaimContent() }} {{ claiming ? "领取中..." : "接受" }} @@ -48,38 +39,15 @@ const claiming = ref(false); const autoPrompted = ref(false); const posterVisible = ref(false); -const projectText = computed(() => { +const projectNameText = computed(() => { const projects = Array.isArray(issue.value?.projectSnapshot) ? issue.value.projectSnapshot : []; if (!projects.length) return "未配置项目"; - return projects.map((p) => `${p.projectName || "项目"}×${p.usageCount || 1}`).join("、"); + return projects.map((p) => p.projectName || "项目").join("、"); }); -const validText = computed(() => { - const rule = issue.value?.projectValidRuleSnapshot || {}; - if (issue.value?.projectExpireTime) { - return `有效期至 ${formatDate(issue.value.projectExpireTime)}`; - } - if (rule.type === "fixedDate" && rule.fixedDate) { - return `有效期至 ${formatDate(rule.fixedDate)}`; - } - if (rule.type === "daysAfterClaim") { - return `领取后 ${rule.days || 0} 天有效`; - } - return "有效期以活动规则为准"; -}); - -function formatDate(ts) { - const d = new Date(Number(ts)); - if (Number.isNaN(d.getTime())) return "-"; - const y = d.getFullYear(); - const m = String(d.getMonth() + 1).padStart(2, "0"); - const day = String(d.getDate()).padStart(2, "0"); - return `${y}-${m}-${day}`; -} - function buildClaimContent() { const name = issue.value?.activityName || "体验券"; - return `您收到一张【${name}】体验券,包含${projectText.value},是否存入您的权益卡包?`; + return `您收到一张【${name}】体验券,包含${projectNameText.value},是否存入您的权益卡包?`; } async function ensureLogin() { @@ -161,16 +129,6 @@ function isExpiredIssue() { async function acceptCoupon() { if (claiming.value || !issue.value) return; - try { - await confirm(buildClaimContent(), { - title: "确认接受", - confirmText: "确认接受", - cancelText: "暂不领取", - }); - } catch { - return; - } - claiming.value = true; loading("领取中..."); try { @@ -240,11 +198,6 @@ async function promptClaim() { return; } - if (!issue.value.posterUrl) { - tip.value = "该体验券暂无海报,无法领取"; - return; - } - tip.value = ""; posterVisible.value = true; } @@ -296,63 +249,53 @@ onShow(() => { font-size: 28rpx; color: #999; } - .poster-mask { position: fixed; inset: 0; z-index: 1000; - background: rgba(0, 0, 0, 0.65); display: flex; align-items: center; justify-content: center; padding: 40rpx; box-sizing: border-box; + background: rgba(0, 0, 0, 0.65); } .poster-dialog { width: 100%; max-width: 620rpx; - background: #fff; - border-radius: 20rpx; overflow: hidden; + border-radius: 20rpx; + background: #fff; } .poster-image { - width: 100%; display: block; + width: 100%; + max-height: 700rpx; background: #f5f7fa; } -.poster-info { - padding: 24rpx 28rpx 8rpx; -} - -.poster-title { - font-size: 30rpx; - font-weight: 600; - color: #222; - margin-bottom: 8rpx; -} - -.poster-desc { - font-size: 24rpx; - color: #888; - line-height: 1.4; +.poster-content { + padding: 28rpx 30rpx 8rpx; + color: #333; + font-size: 28rpx; + line-height: 1.6; } .poster-btn { - margin: 24rpx 28rpx 32rpx; + display: flex; + align-items: center; + justify-content: center; height: 80rpx; + margin: 24rpx 30rpx 30rpx; border-radius: 40rpx; background: #065bd6; color: #fff; font-size: 30rpx; - display: flex; - align-items: center; - justify-content: center; } .poster-btn.disabled { opacity: 0.6; } - + \ No newline at end of file diff --git a/pages/experience-coupon/my-coupons.vue b/pages/experience-coupon/my-coupons.vue index cb7537d..19f8092 100644 --- a/pages/experience-coupon/my-coupons.vue +++ b/pages/experience-coupon/my-coupons.vue @@ -26,8 +26,30 @@ 体验券 {{ item.activityName || "体验券" }} - {{ item.projectText }} - {{ item.validText }} + + + 项目 + + + {{ project.projectName || "未命名项目" }} + ×{{ project.usageCount || 1 }} + + 未配置项目 + + + + 项目有效期 + {{ item.validText }} + + + 活动有效期 + {{ item.activityValidText }} + + 点击查看海报领取 @@ -108,6 +130,12 @@ function buildValidText(item) { return "领取后按活动规则生效"; } +function buildActivityValidText(item) { + const start = formatDate(item.activityStartTime) || "-"; + const end = formatDate(item.activityEndTime) || "-"; + return `${start} 至 ${end}`; +} + function getExpireAt(item) { if (item.projectExpireTime) return Number(item.projectExpireTime); const rule = item.projectValidRuleSnapshot || {}; @@ -207,6 +235,7 @@ async function loadCoupons(options = {}) { ...item, projectText: projectText(item.projectSnapshot), validText: buildValidText(item), + activityValidText: buildActivityValidText(item), }); } list.value = valid; @@ -337,15 +366,53 @@ onShow(async () => { margin-bottom: 8rpx; } -.coupon-meta { - font-size: 24rpx; - color: #888; +.coupon-info-grid { + display: flex; + flex-direction: column; + gap: 6rpx; + color: #606266; + font-size: 22rpx; line-height: 1.4; } +.coupon-info-row { + display: flex; + align-items: flex-start; + min-width: 0; +} + +.coupon-info-label { + width: 132rpx; + flex-shrink: 0; + color: #909399; +} + +.coupon-info-row > text:last-child, +.coupon-project-list { + min-width: 0; + overflow-wrap: anywhere; +} + +.coupon-project-list { + flex: 1; +} + +.coupon-project-item { + display: flex; + justify-content: space-between; + gap: 12rpx; +} + +.coupon-project-item text:first-child { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + .coupon-action { margin-top: 12rpx; - font-size: 24rpx; + font-size: 22rpx; color: #ff8a00; } diff --git a/pages/record/treatment-record.vue b/pages/record/treatment-record.vue index a3d4804..d028f90 100644 --- a/pages/record/treatment-record.vue +++ b/pages/record/treatment-record.vue @@ -1,79 +1,67 @@ @@ -131,11 +119,6 @@ function formatDate(ts) { return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`; } -function formatTimeOnly(ts) { - const d = toDate(ts); - if (!d) return "-"; - return `${pad(d.getHours())}:${pad(d.getMinutes())}`; -} function staffText(userid) { if (!userid) return "-"; @@ -255,6 +238,7 @@ onShow(() => { background: #e9edf3; border-top: 8rpx solid #0b63d8; } + .profile-card { display: flex; align-items: center; @@ -263,6 +247,7 @@ onShow(() => { background: #fff; border-bottom: 1rpx solid #d7dce5; } + .avatar-wrap { width: 72rpx; height: 72rpx; @@ -271,6 +256,7 @@ onShow(() => { overflow: hidden; flex-shrink: 0; } + .avatar-placeholder { width: 100%; height: 100%; @@ -281,27 +267,32 @@ onShow(() => { font-size: 30rpx; font-weight: 600; } + .profile-main { flex: 1; min-width: 0; } + .profile-title { font-size: 31rpx; font-weight: 700; color: #333; line-height: 40rpx; } + .profile-sub { margin-top: 4rpx; font-size: 24rpx; color: #9aa0a8; line-height: 34rpx; } + .profile-arrow { flex-shrink: 0; color: #b4b7bf; font-size: 32rpx; } + .month-bar { display: flex; align-items: center; @@ -314,13 +305,16 @@ onShow(() => { font-weight: 700; border-bottom: 1rpx solid #d4d9e2; } + .month-arrow { font-size: 18rpx; color: #333; } + .record-list { padding: 0rpx 10rpx 12rpx 10rpx; } + .record-card { position: relative; padding: 22rpx 24rpx 22rpx 34rpx; @@ -328,6 +322,7 @@ onShow(() => { border-top: 14rpx solid #e9edf3; border-bottom: 1rpx solid #d7dce5; } + .record-status { position: absolute; top: 24rpx; @@ -335,6 +330,7 @@ onShow(() => { color: #333; font-size: 26rpx; } + .record-row { display: flex; align-items: flex-start; @@ -342,19 +338,23 @@ onShow(() => { font-size: 27rpx; line-height: 38rpx; } + .row-label { flex-shrink: 0; color: #6b7280; font-weight: 700; } + .row-value { min-width: 0; color: #333; word-break: break-all; } + .strong { font-weight: 700; } + .empty { padding: 120rpx 0; text-align: center;