Files
gym-manage/gym-manage-uniapp/pages/memberInfo/memberCard.vue
T
2026-06-04 14:18:53 +08:00

211 lines
8.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>