会员个人中心页面初步完成

This commit is contained in:
时舟年
2026-06-04 14:18:53 +08:00
committed by liwentao
parent c19e0e0181
commit f30514c700
170 changed files with 18092 additions and 35 deletions
@@ -0,0 +1,210 @@
<template>
<view class="scroll-container theme-light">
<view class="member-card-page">
<MemberInfoSubNav title="我的会员卡" @back="goBack" />
<view class="member-card-page__body">
<view class="mc-hero">
<view class="mc-hero__top">
<view class="mc-hero__title-row">
<image
class="mc-hero__crown"
src="/static/images/crown.png"
mode="aspectFit"
/>
<text class="mc-hero__name">{{ card.name }}</text>
</view>
<view class="mc-hero__badge">
<text class="mc-hero__badge-text">{{ card.status }}</text>
</view>
</view>
<text class="mc-hero__validity">有效期{{ card.validity }}</text>
<view class="mc-hero__bottom">
<view class="mc-hero__days">
<text class="mc-hero__days-num">{{ remainingDays }}</text>
<text class="mc-hero__days-unit"></text>
</view>
<view
class="mc-hero__renew"
hover-class="mi-tap-btn--hover"
:hover-stay-time="150"
@tap="renewCard"
>
<image
class="mc-hero__renew-icon"
src="/static/images/refreshcw.png"
mode="aspectFit"
/>
<text class="mc-hero__renew-text">立即续费</text>
</view>
</view>
</view>
<view class="mc-records">
<view class="mc-records__header">
<text class="mc-records__title">使用记录</text>
<view class="mc-records__tabs">
<view
v-for="tab in recordTabs"
:key="tab.key"
class="mc-records__tab"
:class="{ 'mc-records__tab--active': activeFilter === tab.key }"
hover-class="mi-tap-tab--hover"
:hover-stay-time="150"
@tap="switchFilter(tab.key)"
>
<text
class="mc-records__tab-text"
:class="{ 'mc-records__tab-text--active': activeFilter === tab.key }"
>
{{ tab.label }}
</text>
</view>
</view>
</view>
<view class="mc-records__divider"></view>
<view
v-for="(item, index) in filteredRecords"
:key="item.id"
class="mc-records__item"
>
<view v-if="index > 0" class="mc-records__divider"></view>
<view
class="mc-records__item-inner"
hover-class="mi-tap-row--hover"
:hover-stay-time="150"
@tap="showRecordDetail(item)"
>
<view
class="mc-records__icon-wrap"
:class="'mc-records__icon-wrap--' + item.iconTheme"
>
<image
class="mc-records__icon"
:src="item.icon"
mode="aspectFit"
/>
</view>
<view class="mc-records__info">
<text class="mc-records__item-title">{{ item.title }}</text>
<text class="mc-records__item-time">{{ item.time }}</text>
</view>
<text
class="mc-records__value"
:class="'mc-records__value--' + item.valueType"
>
{{ item.value }}
</text>
</view>
</view>
<view v-if="!filteredRecords.length" class="mc-records__empty">
<text class="mc-records__empty-text">暂无记录</text>
</view>
</view>
<view class="mc-rules">
<text class="mc-rules__title">使用规则</text>
<view
v-for="(rule, index) in rules"
:key="index"
class="mc-rules__item"
>
<view class="mc-rules__bullet"></view>
<text class="mc-rules__text">{{ rule }}</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import MemberInfoSubNav from '@/components/memberInfo/MemberInfoSubNav.vue'
import { memberCardMock } from '@/common/memberInfo/mockData.js'
import {
loadMemberStore,
computeRemainingDays,
renewMemberCard
} from '@/common/memberInfo/store.js'
import { subPageMixin } from '@/common/memberInfo/mixins.js'
export default {
components: { MemberInfoSubNav },
mixins: [subPageMixin],
data() {
return {
card: {},
recordTabs: memberCardMock.recordTabs,
records: [],
rules: memberCardMock.rules,
activeFilter: 'all'
}
},
computed: {
filteredRecords() {
if (this.activeFilter === 'all') {
return this.records
}
return this.records.filter((item) => item.type === this.activeFilter)
},
remainingDays() {
return computeRemainingDays(this.card.validityEnd)
}
},
onShow() {
this.refreshFromStore()
},
methods: {
refreshFromStore() {
const store = loadMemberStore()
this.card = { ...store.card }
this.records = store.records.map((item) => ({ ...item }))
},
switchFilter(filter) {
this.activeFilter = filter
},
renewCard() {
uni.showModal({
title: '续费会员卡',
content: '确认续费 90 天?',
success: (res) => {
if (!res.confirm) return
const store = loadMemberStore()
renewMemberCard(store, 90)
this.activeFilter = 'all'
this.refreshFromStore()
uni.showToast({ title: '续费成功', icon: 'success' })
}
})
},
showRecordDetail(item) {
uni.showModal({
title: item.title,
content: `${item.time}\n变动:${item.value}`,
showCancel: false
})
}
}
}
</script>
<style>
@import '@/common/style/base.css';
@import '@/common/style/memberInfo/pages/page-reset.css';
@import '@/common/style/memberInfo/pages/sub-page-base.css';
@import '@/common/style/memberInfo/member-info-component-reset.css';
@import '@/common/style/memberInfo/member-info-sub-nav.css';
@import '@/common/style/memberInfo/member-info-tap.css';
@import '@/common/style/memberInfo/pages/member-card-page.css';
.mc-records__empty {
display: flex;
align-items: center;
justify-content: center;
padding: 32px 16px;
}
.mc-records__empty-text {
font-size: 14px;
color: #8A99B4;
}
</style>