feat: 支持课后评价与成长档案

完成后即可评价并订阅提醒,馆主可记录体测、笔记与成长照片,首页展示匿名星级均分。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
richarjiang
2026-09-09 15:55:48 +08:00
parent c3e46f7ffa
commit 139882d7a1
50 changed files with 1307 additions and 15 deletions

View File

@@ -40,6 +40,9 @@
</view>
</view>
<view class="member-tabs"><button :class="{ selected: activeTab === 'overview' }" @tap="activeTab = 'overview'">会员概览</button><button :class="{ selected: activeTab === 'progress' }" @tap="activeTab = 'progress'">成长档案</button><button @tap="goReviews">课后评价 </button></view>
<MemberProgress v-if="activeTab === 'progress'" admin :user-id="userId" :refresh-key="progressRefreshKey" />
<template v-if="activeTab === 'overview'">
<view class="section section--practice">
<view class="section-heading">
<text class="section-label">上课情况</text>
@@ -137,9 +140,10 @@
<text class="upcoming-empty-text">近期没有待上的课</text>
</view>
</view>
</template>
</template>
<view class="dock">
<view v-if="activeTab === 'overview'" class="dock">
<view class="dock-btn dock-btn--ghost" @tap="goEdit">
<text class="dock-btn-text">编辑资料</text>
</view>
@@ -159,6 +163,7 @@ import { ref, computed, onMounted } from 'vue'
import { onLoad, onShow } from '@dcloudio/uni-app'
import type { AdminMemberDetail, MembershipWithCardType } from '@mp-pilates/shared'
import { MembershipStatus, BookingStatus } from '@mp-pilates/shared'
import MemberProgress from '../../components/MemberProgress.vue'
import CustomNavBar from '../../components/CustomNavBar.vue'
import { getSystemLayout } from '../../utils/system'
import {
@@ -176,6 +181,7 @@ const adminStore = useAdminStore()
const navBarHeight = ref('64px')
const userId = ref('')
const loading = ref(false)
const activeTab = ref('overview'), progressRefreshKey = ref(0)
const detail = ref<AdminMemberDetail | null>(null)
const canArrange = computed(() => (detail.value?.memberships ?? []).some(isArrangableMembership))
@@ -224,6 +230,7 @@ async function loadDetail() {
}
}
function goReviews() { uni.navigateTo({ url: `/pages/admin/reviews?userId=${userId.value}` }) }
function goSupplement() {
if (userId.value) uni.navigateTo({ url: `/pages/admin/member-supplement?userId=${userId.value}` })
}
@@ -250,6 +257,7 @@ onMounted(() => {
})
onShow(() => {
progressRefreshKey.value++
if (userId.value) {
loadDetail()
}
@@ -257,6 +265,9 @@ onShow(() => {
</script>
<style lang="scss" scoped>
.member-tabs {display:flex;margin:28rpx 32rpx 0;border-bottom:1rpx solid #e5dfd6;gap:8rpx;}
.member-tabs button{flex:1;margin:0;padding:0;background:transparent;border-radius:0;line-height:88rpx;font-size:25rpx;color:#8b817b;border-bottom:4rpx solid transparent;&::after{border:0;}&.selected{border-color:#617d73;color:#617d73;}}
.page {
--ink: #514943;
--muted: #8b817b;