Эх сурвалжийг харах

feat: 屏蔽在线开通会员功能,改为管理员后台设置

- plans.vue: 替换为'会员由管理员设置'提示页

- upgrade.vue: 替换为'暂不支持在线开通'提示页

- ProfileMenu: 导航从index改为benefits

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
liaoxg 3 сар өмнө
parent
commit
7f3725c70e

+ 18 - 370
cfc-frontend/pages/membership/plans.vue

@@ -1,383 +1,31 @@
 <template>
-  <scroll-view class="container" scroll-y>
-    <view class="plans-header">
-      <text class="header-title">会员方案</text>
-      <text class="header-subtitle">全家人的健康守护</text>
+  <view class="container">
+    <view class="notice-card">
+      <text class="notice-icon">👑</text>
+      <text class="notice-title">会员功能</text>
+      <text class="notice-desc">会员级别由管理员在后台统一设置,暂不支持在线开通。</text>
+      <text class="notice-desc">如有疑问请联系客服。</text>
+      <button class="back-btn" @click="goBack">返回</button>
     </view>
-
-    <view class="plans-list">
-      <!-- 免费卡片(静态) -->
-      <view class="plan-card plan-l0">
-        <view class="plan-header">
-          <text class="plan-name">注册会员</text>
-          <text class="plan-tag">免费</text>
-        </view>
-        <view class="plan-price">
-          <text class="price-amount">¥0</text>
-          <text class="price-unit">/永久</text>
-        </view>
-        <view class="plan-features">
-          <view class="feature-row" v-for="(feat, idx) in l0Features" :key="idx">
-            <text class="feature-icon">✓</text>
-            <text class="feature-text">{{ feat }}</text>
-          </view>
-        </view>
-        <button class="btn-action" disabled>当前等级</button>
-      </view>
-
-      <!-- 付费等级卡片(从后端动态加载) -->
-      <view class="plan-card" v-for="level in levels" :key="level.levelCode"
-        :class="{'active': level.recommended}">
-        <view class="plan-badge" v-if="level.recommended">推荐</view>
-        <view class="plan-badge premium" v-else-if="level.levelCode === 'PREMIUM'">至尊</view>
-        <view class="plan-header">
-          <text class="plan-name">{{ level.levelName }}</text>
-          <text class="plan-tag">{{ level.levelCode === 'FAMILY' ? '年付会员' : '年付/月付' }}</text>
-        </view>
-        <view class="plan-price">
-          <text class="price-amount">{{ formatPrice(level.yearly) }}</text>
-          <text class="price-unit">/年</text>
-        </view>
-        <view class="plan-features" v-if="level.levelDesc">
-          <view class="feature-row" v-for="(feat, idx) in parseFeatures(level.levelDesc)" :key="idx">
-            <text class="feature-icon">✓</text>
-            <text class="feature-text">{{ feat }}</text>
-          </view>
-        </view>
-        <button class="btn-action" :class="level.recommended ? 'btn-primary' : 'btn-premium'"
-          @click="purchasePlan(level.levelCode)">
-          {{ level.levelCode === 'FAMILY' ? '立即开通' : '立即订阅' }}
-        </button>
-      </view>
-    </view>
-
-    <view class="benefits-section">
-      <text class="section-title">会员权益详解</text>
-      <view class="benefits-grid">
-        <view class="benefit-item" v-for="(item, idx) in benefits" :key="idx">
-          <view class="benefit-icon" :style="'background:' + item.bg">
-            <text class="benefit-emoji">{{ item.icon }}</text>
-          </view>
-          <text class="benefit-name">{{ item.name }}</text>
-          <text class="benefit-desc">{{ item.desc }}</text>
-        </view>
-      </view>
-    </view>
-
-    <view class="faq-section">
-      <text class="section-title">常见问题</text>
-      <view class="faq-item" v-for="(faq, idx) in faqs" :key="idx">
-        <text class="faq-question">{{ faq.q }}</text>
-        <text class="faq-answer">{{ faq.a }}</text>
-      </view>
-    </view>
-  </scroll-view>
+  </view>
 </template>
 
 <script>
-import { getMembershipPlans } from '../../utils/api.js'
-
 export default {
-  data() {
-    return {
-      levels: [],
-      l0Features: [
-        '每日 3 次 AI 问答',
-        '基础健康百科',
-        '社区内容浏览'
-      ],
-      benefits: [
-        { icon: '🤖', name: 'AI 健康顾问', desc: '7×24 小时智能问答', bg: '#DBEAFE' },
-        { icon: '👨‍👩‍👧‍👦', name: '家庭覆盖', desc: '一次付费全家守护', bg: '#D1FAE5' },
-        { icon: '👨‍🏫', name: '专属管家', desc: '认证专业人员服务', bg: '#FEF3C7' },
-        { icon: '🛒', name: '商品折扣', desc: '会员专享优惠价', bg: '#FCE7F3' },
-        { icon: '💰', name: '消费返利', desc: 'P 点制终身返利', bg: '#FFEDD5' },
-        { icon: '📈', name: '推广佣金', desc: 'R0-R4 阶梯奖励', bg: '#E0E7FF' }
-      ],
-      faqs: [
-        { q: '家庭会员适合谁?', a: '适合有 1-2 个孩子的家庭,追求性价比,希望获得 AI 健康顾问 + 认证管家服务' },
-        { q: '高级家庭会员与家庭会员的区别?', a: '高级会员享资深管家 (1:30 配比)、深度 AI 分析、专家会诊、更高折扣和返利加成' },
-        { q: '可以取消吗?', a: '可以,取消后当前月结束后降级为免费用户,健康档案保留 30 天' },
-        { q: '消费返利如何计算?', a: '被推荐人消费 P 点总和 × 推广人等级返利率,高级会员额外 +5% 加成' }
-      ]
-    }
-  },
-  onLoad() {
-    this.loadPlans()
-  },
   methods: {
-    loadPlans() {
-      var self = this
-      getMembershipPlans().then(function(res) {
-        if (res.code === 200 && Array.isArray(res.data)) {
-          self.levels = res.data
-        }
-      }).catch(function(e) {
-        console.error('获取方案失败', e)
-      })
-    },
-    formatPrice(cents) {
-      if (!cents && cents !== 0) return '¥0'
-      return '¥' + (cents / 100).toLocaleString()
-    },
-    parseFeatures(features) {
-      if (!features) return []
-      if (Array.isArray(features)) return features
-      try { return JSON.parse(features) } catch (e) { return [] }
-    },
-    purchasePlan(levelCode) {
-      uni.navigateTo({ url: '/pages/membership/upgrade?level=' + levelCode })
+    goBack() {
+      uni.navigateBack()
     }
   }
 }
 </script>
 
-<style scoped>
-.container {
-  padding: 30rpx;
-  min-height: 100vh;
-  background: linear-gradient(180deg, #FFF7ED 0%, #FEF3C7 100%);
-}
-
-.plans-header {
-  text-align: center;
-  padding: 60rpx 0 40rpx;
-}
-.header-title {
-  font-size: 44rpx;
-  font-weight: bold;
-  color: #1E293B;
-  display: block;
-}
-.header-subtitle {
-  font-size: 28rpx;
-  color: #64748B;
-  margin-top: 12rpx;
-  display: block;
-}
-
-.plans-list {
-  display: flex;
-  flex-direction: column;
-  gap: 30rpx;
-  margin-bottom: 40rpx;
-}
-
-.plan-card {
-  background: #fff;
-  border-radius: 24rpx;
-  padding: 40rpx;
-  position: relative;
-  border: 2rpx solid #FED7AA;
-  box-shadow: 0 4rpx 20rpx rgba(249,115,22,0.08);
-}
-
-.plan-card.active {
-  border-color: #F97316;
-  background: linear-gradient(135deg, #FFF7ED 0%, #FEF3C7 100%);
-  transform: scale(1.02);
-}
-
-.plan-badge {
-  position: absolute;
-  top: -16rpx;
-  right: 40rpx;
-  background: #F97316;
-  color: #fff;
-  padding: 8rpx 24rpx;
-  border-radius: 9999rpx;
-  font-size: 22rpx;
-  font-weight: 600;
-}
-
-.plan-badge.premium {
-  background: linear-gradient(135deg, #8B5CF6 0%, #EC4899 100%);
-}
-
-.plan-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 20rpx;
-}
-
-.plan-name {
-  font-size: 32rpx;
-  font-weight: bold;
-  color: #1E293B;
-}
-
-.plan-tag {
-  font-size: 22rpx;
-  color: #64748B;
-  background: #F1F5F9;
-  padding: 6rpx 16rpx;
-  border-radius: 8rpx;
-}
-
-.plan-price {
-  text-align: center;
-  margin: 24rpx 0;
-}
-
-.price-amount {
-  font-size: 56rpx;
-  font-weight: bold;
-  color: #F97316;
-}
-
-.price-unit {
-  font-size: 24rpx;
-  color: #94A3B8;
-  margin-left: 8rpx;
-}
-
-.plan-features {
-  margin: 24rpx 0;
-}
-
-.feature-row {
-  display: flex;
-  align-items: center;
-  padding: 12rpx 0;
-}
-
-.feature-icon {
-  width: 40rpx;
-  height: 40rpx;
-  line-height: 40rpx;
-  text-align: center;
-  background: #10B981;
-  color: #fff;
-  border-radius: 50%;
-  font-size: 20rpx;
-  margin-right: 12rpx;
-  flex-shrink: 0;
-}
-
-.feature-text {
-  font-size: 26rpx;
-  color: #334155;
-  flex: 1;
-}
-
-.btn-action {
-  width: 100%;
-  height: 80rpx;
-  line-height: 80rpx;
-  background: #E5E7EB;
-  color: #9CA3AF;
-  font-size: 28rpx;
-  border-radius: 40rpx;
-  border: none;
-  margin-top: 20rpx;
-}
-
-.btn-action:disabled {
-  opacity: 0.6;
-}
-
-.btn-primary {
-  background: linear-gradient(135deg, #F97316 0%, #EA580C 100%);
-  color: #fff;
-  font-weight: 600;
-}
-
-.btn-premium {
-  background: linear-gradient(135deg, #8B5CF6 0%, #EC4899 100%);
-  color: #fff;
-  font-weight: 600;
-}
-
-.btn-action::after {
-  border: none;
-}
-
-.benefits-section {
-  background: #fff;
-  border-radius: 24rpx;
-  padding: 30rpx;
-  margin-bottom: 30rpx;
-  box-shadow: 0 4rpx 20rpx rgba(249,115,22,0.08);
-}
-
-.section-title {
-  font-size: 32rpx;
-  font-weight: bold;
-  color: #1E293B;
-  display: block;
-  margin-bottom: 24rpx;
-}
-
-.benefits-grid {
-  display: flex;
-  flex-wrap: wrap;
-}
-
-.benefit-item {
-  width: 50%;
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  padding: 24rpx 16rpx;
-  box-sizing: border-box;
-}
-
-.benefit-icon {
-  width: 80rpx;
-  height: 80rpx;
-  border-radius: 50%;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  margin-bottom: 16rpx;
-}
-
-.benefit-emoji {
-  font-size: 40rpx;
-}
-
-.benefit-name {
-  font-size: 26rpx;
-  font-weight: 600;
-  color: #1E293B;
-  margin-bottom: 8rpx;
-}
-
-.benefit-desc {
-  font-size: 22rpx;
-  color: #94A3B8;
-  text-align: center;
-}
-
-.faq-section {
-  background: #fff;
-  border-radius: 24rpx;
-  padding: 30rpx;
-  box-shadow: 0 4rpx 20rpx rgba(249,115,22,0.08);
-}
-
-.faq-item {
-  padding: 20rpx 0;
-  border-bottom: 1rpx solid #F1F5F9;
-}
-
-.faq-item:last-child {
-  border-bottom: none;
-}
-
-.faq-question {
-  font-size: 26rpx;
-  font-weight: 600;
-  color: #1E293B;
-  display: block;
-  margin-bottom: 8rpx;
-}
-
-.faq-answer {
-  font-size: 24rpx;
-  color: #64748B;
-  line-height: 1.6;
-  display: block;
-}
+<style>
+.container { min-height: 100vh; background: #f5f7fa; display: flex; align-items: center; justify-content: center; padding: 60rpx; }
+.notice-card { background: #fff; border-radius: 24rpx; padding: 60rpx 40rpx; text-align: center; width: 100%; }
+.notice-icon { font-size: 80rpx; }
+.notice-title { font-size: 36rpx; font-weight: 700; color: #333; margin-top: 24rpx; }
+.notice-desc { font-size: 28rpx; color: #999; margin-top: 16rpx; line-height: 1.6; }
+.back-btn { margin-top: 48rpx; width: 60%; height: 80rpx; line-height: 80rpx; background: linear-gradient(135deg, #5B9BD5, #3A7CC4); color: #fff; font-size: 30rpx; border-radius: 40rpx; border: none; }
+.back-btn::after { border: none; }
 </style>

+ 30 - 4
cfc-frontend/pages/membership/upgrade.vue

@@ -1,8 +1,34 @@
 <template>
-  <view class="upgrade-page-wrapper">
-    <scroll-view class="page" scroll-y>
-      <!-- 当前会员状态卡片 -->
-      <view class="status-card">
+  <view class="container">
+    <view class="notice-card">
+      <text class="notice-icon">🔒</text>
+      <text class="notice-title">开通会员</text>
+      <text class="notice-desc">会员级别由管理员在后台统一设置,暂不支持在线开通。</text>
+      <text class="notice-desc">如有疑问请联系客服。</text>
+      <button class="back-btn" @click="goBack">返回</button>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  methods: {
+    goBack() {
+      uni.navigateBack()
+    }
+  }
+}
+</script>
+
+<style>
+.container { min-height: 100vh; background: #f5f7fa; display: flex; align-items: center; justify-content: center; padding: 60rpx; }
+.notice-card { background: #fff; border-radius: 24rpx; padding: 60rpx 40rpx; text-align: center; width: 100%; }
+.notice-icon { font-size: 80rpx; }
+.notice-title { font-size: 36rpx; font-weight: 700; color: #333; margin-top: 24rpx; }
+.notice-desc { font-size: 28rpx; color: #999; margin-top: 16rpx; line-height: 1.6; }
+.back-btn { margin-top: 48rpx; width: 60%; height: 80rpx; line-height: 80rpx; background: linear-gradient(135deg, #5B9BD5, #3A7CC4); color: #fff; font-size: 30rpx; border-radius: 40rpx; border: none; }
+.back-btn::after { border: none; }
+</style>
         <view class="status-badge" :class="isFree ? 'badge-free' : 'badge-family'">
           <text class="badge-icon">{{ isFree ? '○' : '●' }}</text>
           <text class="badge-text">{{ currentLevelName }}</text>

+ 1 - 1
cfc-frontend/pages/profile/components/ProfileMenu.vue

@@ -173,7 +173,7 @@ export default {
       }
     },
     goToMembership() {
-      uni.navigateTo({ url: '/pages/membership/index' })
+      uni.navigateTo({ url: '/pages/membership/benefits' })
     },
     goToVendorCenter() {
       uni.navigateTo({ url: '/pages/vendor/center' })