Ver código fonte

refactor: 统一活动详情和商品详情页

活动详情: 保留 activity/activity-detail(880行,最完整),删除 discover/activity-detail(死代码)和 discover-detail/activity-detail(重复注册)
商品详情: 保留 discover-detail/product-detail(已含 mp-html),删除 discover/product-detail(死代码,641行)
更新 15+ 个文件的引用路径
清理 pages.json 移除 discover-detail 子包中的 activity-detail 注册
Sisyphus 1 mês atrás
pai
commit
a7b5f49146

+ 1 - 1
cfc-frontend/components/DimensionProductList.vue

@@ -76,7 +76,7 @@ export default {
       }
 
       uni.navigateTo({
-        url: '/pages/discover/product-detail/product-detail?id=' + product.productId + '&from=dimension'
+        url: '/pages/discover-detail/product-detail/product-detail?id=' + product.productId + '&from=dimension'
       })
     }
   }

+ 1 - 1
cfc-frontend/pages/action-detail/member-action-detail.vue

@@ -199,7 +199,7 @@ export default {
       uni.navigateTo({ url: '/pages/tasks/tasks' })
     },
     goActivityDetail: function(act) {
-      if (act && act.id) uni.navigateTo({ url: '/pages/discover-detail/activity-detail/activity-detail?id=' + act.id })
+      if (act && act.id) uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + act.id })
     },
     goMoreActivities: function() {
       uni.navigateTo({ url: '/pages/activity/index' })

+ 1 - 1
cfc-frontend/pages/action/index.vue

@@ -472,7 +472,7 @@ export default {
     },
     goActivityDetail: function(act) {
       if (!act || !act.id) return
-      uni.navigateTo({ url: '/pages/discover-detail/activity-detail/activity-detail?id=' + act.id })
+      uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + act.id })
     },
     goMoreActivities: function() {
       uni.navigateTo({ url: '/pages/activity/index' })

+ 2 - 2
cfc-frontend/pages/action/member-action-detail.vue

@@ -199,13 +199,13 @@ export default {
       uni.navigateTo({ url: '/pages/tasks/tasks' })
     },
     goActivityDetail: function(act) {
-      if (act && act.id) uni.navigateTo({ url: '/pages/discover/activity-detail/activity-detail?id=' + act.id })
+      if (act && act.id) uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + act.id })
     },
     goMoreActivities: function() {
       uni.navigateTo({ url: '/pages/activity/index' })
     },
     goProductDetail: function(prod) {
-      if (prod && prod.id) uni.navigateTo({ url: '/pages/discover/product-detail/product-detail?id=' + prod.id })
+      if (prod && prod.id) uni.navigateTo({ url: '/pages/discover-detail/product-detail/product-detail?id=' + prod.id })
     },
     goMoreProducts: function() {
       uni.navigateTo({ url: '/pages/shop/index' })

+ 1 - 1
cfc-frontend/pages/body-detail/member-body-detail.vue

@@ -199,7 +199,7 @@ export default {
       uni.navigateTo({ url: '/pages/tasks/tasks' })
     },
     goActivityDetail: function(act) {
-      if (act && act.id) uni.navigateTo({ url: '/pages/discover-detail/activity-detail/activity-detail?id=' + act.id })
+      if (act && act.id) uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + act.id })
     },
     goMoreActivities: function() {
       uni.navigateTo({ url: '/pages/activity/index' })

+ 1 - 1
cfc-frontend/pages/body/index.vue

@@ -433,7 +433,7 @@ export default {
     },
     goActivityDetail: function(act) {
       if (!act || !act.id) return
-      uni.navigateTo({ url: '/pages/discover-detail/activity-detail/activity-detail?id=' + act.id })
+      uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + act.id })
     },
     goMoreActivities: function() {
       uni.navigateTo({ url: '/pages/activity/index' })

+ 2 - 2
cfc-frontend/pages/body/member-body-detail.vue

@@ -199,13 +199,13 @@ export default {
       uni.navigateTo({ url: '/pages/tasks/tasks' })
     },
     goActivityDetail: function(act) {
-      if (act && act.id) uni.navigateTo({ url: '/pages/discover/activity-detail/activity-detail?id=' + act.id })
+      if (act && act.id) uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + act.id })
     },
     goMoreActivities: function() {
       uni.navigateTo({ url: '/pages/activity/index' })
     },
     goProductDetail: function(prod) {
-      if (prod && prod.id) uni.navigateTo({ url: '/pages/discover/product-detail/product-detail?id=' + prod.id })
+      if (prod && prod.id) uni.navigateTo({ url: '/pages/discover-detail/product-detail/product-detail?id=' + prod.id })
     },
     goMoreProducts: function() {
       uni.navigateTo({ url: '/pages/shop/index' })

+ 1 - 1
cfc-frontend/pages/dan-assessment/report-upload.vue

@@ -274,7 +274,7 @@ export default {
       })
     },
     goToProduct: function(productId) {
-      uni.navigateTo({ url: '/pages/discover/product-detail/product-detail?id=' + productId })
+      uni.navigateTo({ url: '/pages/discover-detail/product-detail/product-detail?id=' + productId })
     },
     formatPriceWithSymbol: function(cents) {
       if (cents === null || cents === undefined) return '¥0'

+ 0 - 720
cfc-frontend/pages/discover/activity-detail/activity-detail.vue

@@ -1,720 +0,0 @@
-<template>
-  <view class="container">
-    <!-- 加载状态 -->
-    <view v-if="loading" class="loading-wrap">
-      <view class="loading-spinner"></view>
-      <text class="loading-text">加载中...</text>
-    </view>
-
-    <!-- 错误状态 -->
-    <view v-else-if="error" class="error-wrap">
-      <text class="error-icon">📋</text>
-      <text class="error-text">{{ errorMsg }}</text>
-      <button class="retry-btn" @click="loadDetail(activityId)">重新加载</button>
-    </view>
-
-    <!-- 活动内容 -->
-    <scroll-view v-else-if="activity.id" scroll-y class="content">
-      <!-- 封面图 -->
-      <image
-        v-if="activity.coverImage"
-        class="cover"
-        :src="activity.coverImage"
-        mode="widthFix"
-      />
-      <image v-else class="cover placeholder-cover" src="/static/default-activity.png" mode="aspectFill" />
-
-      <view class="info-section">
-        <text class="activity-title">{{ activity.title }}</text>
-
-        <!-- 活动状态标签 -->
-        <view class="status-row">
-          <text class="status-tag" :class="'status-' + (activity.status || 'upcoming')">{{ statusText(activity.status) }}</text>
-        </view>
-
-        <!-- 活动元信息 -->
-        <view class="meta-list">
-          <view class="meta-item" v-if="activity.startTime">
-            <text class="meta-icon">🕐</text>
-            <text class="meta-text">{{ formatDate(activity.startTime) }}{{ activity.endTime ? ' ~ ' + formatDate(activity.endTime) : '' }}</text>
-          </view>
-          <view class="meta-item" v-if="activity.endTime && activity.requireRegistration === 1">
-            <text class="meta-icon">⏰</text>
-            <text class="meta-text">报名截止: {{ formatDate(activity.endTime) }}</text>
-          </view>
-          <view class="meta-item" v-if="activity.location">
-            <text class="meta-icon">📍</text>
-            <text class="meta-text">{{ activity.location }}</text>
-          </view>
-          <view class="meta-item" v-if="activity.maxParticipants">
-            <text class="meta-icon">👥</text>
-            <text class="meta-text">{{ activity.currentParticipants || 0 }} / {{ activity.maxParticipants }} 人</text>
-          </view>
-          <view class="meta-item">
-            <text class="meta-icon">💰</text>
-            <view class="meta-text" v-if="activity.memberPrice && activity.memberPrice > 0 && activity.memberPrice < activity.price">
-              <text>会员价 ¥{{ activity.memberPrice }} 普通价 ¥{{ activity.price }}</text>
-            </view>
-            <text class="meta-text" v-else>{{ activity.priceLabel || (activity.price > 0 ? '¥' + activity.price : '免费') }}</text>
-          </view>
-        </view>
-
-        <!-- 活动简介 -->
-        <view class="desc-section" v-if="activity.description">
-          <text class="section-title">活动介绍</text>
-          <mp-html :content="activity.description" />
-        </view>
-
-        <!-- 付费不退费说明 -->
-        <view class="refund-notice" v-if="hasPrice">
-          <text class="refund-notice-icon">⚠️</text>
-          <text class="refund-notice-text">本活动为付费活动,报名成功后不支持退费</text>
-        </view>
-      </view>
-
-      <!-- 底部操作栏 -->
-      <view class="bottom-bar">
-        <view class="price-info">
-          <text class="bottom-type">活动</text>
-          <text class="bottom-vendor" v-if="activity.vendorName">{{ activity.vendorName }}</text>
-        </view>
-        <view class="action-btns">
-          <view class="poster-btn" @click="generatePoster">
-            <text class="poster-btn-icon">🖼</text>
-            <text class="poster-btn-text">海报</text>
-          </view>
-          <!-- 未报名 → 显示报名按钮 -->
-          <button
-            v-if="!registrationStatus && activity.requireRegistration !== 0"
-            class="btn-register"
-            :class="{ 'btn-register-loading': registrationLoading || paying }"
-            :disabled="registrationLoading || paying"
-            @click="onRegister"
-          >
-            <text v-if="registrationLoading">报名中...</text>
-            <text v-else-if="paying">支付中...</text>
-            <text v-else-if="hasPrice">¥{{ activity.price }} 立即报名</text>
-            <text v-else>立即报名</text>
-          </button>
-
-          <!-- 已报名(pending 待审核) -->
-          <button
-            v-if="registrationStatus === 'pending'"
-            class="btn-register-done"
-            disabled
-          >
-            <text>审核中</text>
-          </button>
-
-          <!-- 已报名(approved)→ 显示"已报名" + "签到" -->
-          <template v-if="registrationStatus === 'approved'">
-            <button
-              class="btn-registered"
-              :disabled="registrationLoading"
-              @click="onCancelRegistration"
-            >
-              <text>已报名</text>
-            </button>
-            <button
-              class="btn-checkin"
-              :class="{ 'btn-checkin-done': checkinDone, 'btn-checkin-loading': checkinLoading }"
-              :disabled="checkinLoading || checkinDone"
-              @click="onCheckin"
-            >
-              <text v-if="checkinLoading">签到中...</text>
-              <text v-else-if="checkinDone && activity.requireCheckinReview === 1">已签到待审核</text>
-              <text v-else-if="checkinDone">已签到 ✓</text>
-              <text v-else>签到</text>
-            </button>
-            <text v-if="activity.requireCheckinReview === 1 && !checkinDone" class="checkin-review-hint">签到需要管理员审核</text>
-          </template>
-
-          <!-- 已签到(无报名流程的活动) -->
-          <button
-            v-if="registrationStatus === 'approved' && checkinDone"
-            class="btn-checkin btn-checkin-done"
-            disabled
-          >
-            <text>已签到 ✓</text>
-          </button>
-        </view>
-      </view>
-    </scroll-view>
-
-    <!-- 空状态 -->
-    <view v-else class="empty-wrap">
-      <text class="empty-text">活动不存在或已下架</text>
-    </view>
-
-    <ContentSharePoster
-      :show="showPoster"
-      :title="activity.title"
-      :coverImage="activity.coverImage"
-      :qrCodeBase64="posterQrCode"
-      typeLabel="活动推荐"
-      @close="showPoster = false"
-    />
-  </view>
-</template>
-
-<script>
-import { getActivityDetail, activityCheckin, registerActivity, getMyActivityRegistrations, cancelActivityRegistration, getShareQrCode } from '@/utils/api.js'
-import ContentSharePoster from '@/components/ContentSharePoster.vue'
-import MpHtml from '@/components/mp-html/mp-html.vue'
-
-var WEEKDAYS = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
-
-export default {
-  components: { ContentSharePoster, MpHtml },
-  data() {
-    return {
-      activityId: null,
-      activity: {},
-      loading: false,
-      error: false,
-      errorMsg: '',
-      checkinLoading: false,
-      checkinDone: false,
-      checkinPoints: 0,
-      showPoster: false,
-      posterQrCode: '',
-      // 报名相关
-      registrationStatus: '',     // '' | 'pending' | 'approved'
-      registrationLoading: false,
-      registrationId: null,
-      paying: false
-    }
-  },
-  computed: {
-    hasPrice: function() {
-      return this.activity && this.activity.price > 0
-    }
-  },
-  onLoad: function(options) {
-    if (options && options.id) {
-      this.activityId = options.id
-      this.loadDetail(options.id)
-    } else {
-      this.error = true
-      this.errorMsg = '缺少活动ID'
-    }
-
-    // 检查是否已经签到(从路由参数获取)
-    if (options && options.checkinDone === '1') {
-      this.checkinDone = true
-    }
-  },
-  methods: {
-    async generatePoster() {
-      if (!this.activity.id) return
-      uni.showLoading({ title: '生成海报中...' })
-      try {
-        var page = 'pages/discover/activity-detail/activity-detail'
-        var scene = 'id=' + this.activity.id
-        var res = await getShareQrCode(page, scene)
-        if (res && res.data) {
-          this.posterQrCode = res.data.qrCodeBase64 || ''
-          this.showPoster = true
-        }
-      } catch (e) {
-        uni.showToast({ title: '生成失败', icon: 'none' })
-      } finally {
-        uni.hideLoading()
-      }
-    },
-    // ===== 工具方法 =====
-    formatDate: function(dateStr) {
-      if (!dateStr) return ''
-      var d = new Date(dateStr.replace(/-/g, '/'))
-      if (isNaN(d.getTime())) return dateStr
-      var year = d.getFullYear()
-      var month = d.getMonth() + 1
-      var day = d.getDate()
-      var hour = d.getHours()
-      var minute = d.getMinutes()
-      var ampm = hour < 12 ? '上午' : '下午'
-      var h12 = hour % 12
-      if (h12 === 0) h12 = 12
-      var minStr = minute < 10 ? '0' + minute : minute
-      return year + '年' + month + '月' + day + '日 ' + ampm + h12 + ':' + minStr
-    },
-
-    // ===== 数据加载 =====
-    loadDetail: function(id) {
-      var self = this
-      self.loading = true
-      self.error = false
-      getActivityDetail(id).then(function(res) {
-        self.loading = false
-        if (res && res.code === 200 && res.data) {
-          self.activity = res.data
-          // 加载详情后检查报名状态
-          self.loadRegistrationStatus(id)
-        } else {
-          self.error = true
-          self.errorMsg = (res && res.message) || '加载失败'
-        }
-      }).catch(function(err) {
-        self.loading = false
-        self.error = true
-        self.errorMsg = '网络异常,请稍后重试'
-      })
-    },
-    statusText: function(status) {
-      var map = { draft: '草稿', published: '进行中', ended: '已结束' }
-      return map[status] || '未知'
-    },
-
-    // ===== 报名相关 =====
-    loadRegistrationStatus: function(activityId) {
-      var self = this
-      var childId = uni.getStorageSync('currentChildId')
-      if (!childId) return
-
-      getMyActivityRegistrations({ id: activityId, childId: childId, page: 1, size: 10 }).then(function(res) {
-        var records, i, reg
-        if (res && res.code === 200 && res.data) {
-          records = res.data.records || []
-          for (i = 0; i < records.length; i++) {
-            reg = records[i]
-            if (String(reg.activityId) === String(activityId)) {
-              self.registrationStatus = reg.status || 'pending'
-              self.registrationId = reg.id
-              if (reg.checkinTime) {
-                self.checkinDone = true
-              }
-              return
-            }
-          }
-        }
-      }).catch(function(err) {
-        // 静默失败,不阻塞页面
-      })
-    },
-    onRegister: function() {
-      var self = this
-      if (self.registrationLoading || self.paying) return
-
-      var childId = uni.getStorageSync('currentChildId')
-      if (!childId) {
-        uni.showToast({ title: '请选择孩子身份', icon: 'none' })
-        return
-      }
-
-      // 付费活动 → 先确认支付
-      if (self.hasPrice) {
-        uni.showModal({
-          title: '确认报名',
-          content: '该活动需支付 ¥' + self.activity.price + ',报名成功后不支持退费。是否继续?',
-          confirmText: '确认支付',
-          cancelText: '再想想',
-          success: function(confirmRes) {
-            if (confirmRes.confirm) {
-              self.doRegister(childId)
-            }
-          }
-        })
-      } else {
-        // 免费活动 → 直接报名
-        uni.showModal({
-          title: '确认报名',
-          content: '确认报名该活动?',
-          confirmText: '立即报名',
-          cancelText: '再想想',
-          success: function(confirmRes) {
-            if (confirmRes.confirm) {
-              self.doRegister(childId)
-            }
-          }
-        })
-      }
-    },
-    doRegister: function(childId) {
-      var self = this
-      self.registrationLoading = true
-
-      // 付费活动模拟支付等待
-      if (self.hasPrice) {
-        self.paying = true
-      }
-
-      registerActivity({ id: self.activity.id, childId: childId }).then(function(res) {
-        var msg
-        self.registrationLoading = false
-        self.paying = false
-        if (res && res.code === 200) {
-          self.registrationStatus = 'pending'
-          self.registrationId = res.data && res.data.id
-          uni.showToast({ title: '报名成功', icon: 'success' })
-          // 重新加载详情获取最新人数
-          self.loadDetail(self.activityId)
-        } else {
-          msg = (res && res.message) || '报名失败'
-          uni.showToast({ title: msg, icon: 'none' })
-        }
-      }).catch(function(err) {
-        self.registrationLoading = false
-        self.paying = false
-        uni.showToast({ title: '网络异常', icon: 'none' })
-      })
-    },
-    onCancelRegistration: function() {
-      var self = this
-      if (self.registrationLoading) return
-
-      uni.showModal({
-        title: '取消报名',
-        content: '确定取消报名?',
-        confirmText: '确认取消',
-        confirmColor: '#EF4444',
-        success: function(confirmRes) {
-          if (confirmRes.confirm) {
-            self.doCancelRegistration()
-          }
-        }
-      })
-    },
-    doCancelRegistration: function() {
-      var self = this
-      self.registrationLoading = true
-      cancelActivityRegistration({ id: self.activity.id, childId: uni.getStorageSync('currentChildId') }).then(function(res) {
-        var msg
-        self.registrationLoading = false
-        if (res && res.code === 200) {
-          self.registrationStatus = ''
-          self.registrationId = null
-          uni.showToast({ title: '已取消报名', icon: 'success' })
-          // 重新加载详情
-          self.loadDetail(self.activityId)
-        } else {
-          msg = (res && res.message) || '取消失败'
-          uni.showToast({ title: msg, icon: 'none' })
-        }
-      }).catch(function(err) {
-        self.registrationLoading = false
-        uni.showToast({ title: '网络异常', icon: 'none' })
-      })
-    },
-
-    // ===== 签到相关 =====
-    onCheckin: function() {
-      var self = this
-      if (self.checkinLoading || self.checkinDone) return
-
-      // 检查活动是否已开始(只有进行中状态才能签到)
-      if (self.activity.status !== 'published') {
-        uni.showToast({ title: '活动尚未开始,无法签到', icon: 'none' })
-        return
-      }
-
-      var childId = uni.getStorageSync('currentChildId')
-      if (!childId) {
-        uni.showToast({ title: '请选择孩子身份', icon: 'none' })
-        return
-      }
-
-      self.checkinLoading = true
-      activityCheckin({ id: self.activity.id, childId: childId }).then(function(res) {
-        var msg
-        self.checkinLoading = false
-        if (res && res.code === 200 && res.data) {
-          if (res.data.alreadyCompleted) {
-            self.checkinDone = true
-            uni.showToast({ title: '已签到', icon: 'success' })
-          } else if (res.data.pointsEarned && res.data.pointsEarned > 0) {
-            self.checkinDone = true
-            self.checkinPoints = res.data.pointsEarned
-            uni.showToast({ title: '签到成功 +' + res.data.pointsEarned + '积分', icon: 'success' })
-          } else {
-            self.checkinDone = true
-            uni.showToast({ title: '签到成功', icon: 'success' })
-          }
-        } else {
-          msg = (res && res.message) || '签到失败'
-          uni.showToast({ title: msg, icon: 'none' })
-        }
-      }).catch(function(err) {
-        self.checkinLoading = false
-        uni.showToast({ title: '网络异常', icon: 'none' })
-      })
-    }
-  }
-}
-</script>
-
-<style scoped>
-.container {
-  min-height: 100vh;
-  background: #FFF7ED;
-}
-
-/* 加载 / 错误 / 空状态 */
-.loading-wrap,
-.error-wrap,
-.empty-wrap {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  justify-content: center;
-  padding: 120rpx 40rpx;
-}
-.loading-spinner {
-  width: 60rpx;
-  height: 60rpx;
-  border: 4rpx solid #FDE68A;
-  border-top-color: #F97316;
-  border-radius: 50%;
-  animation: spin 0.8s linear infinite;
-  margin-bottom: 20rpx;
-}
-@keyframes spin {
-  to { transform: rotate(360deg); }
-}
-.loading-text,
-.error-text,
-.empty-text {
-  font-size: 28rpx;
-  color: #999;
-  margin-bottom: 20rpx;
-}
-.error-icon {
-  font-size: 60rpx;
-  margin-bottom: 16rpx;
-}
-.retry-btn {
-  background: #F97316;
-  color: #fff;
-  border: none;
-  border-radius: 40rpx;
-  padding: 12rpx 40rpx;
-  font-size: 26rpx;
-  line-height: 1.5;
-}
-
-/* 内容区 */
-.content {
-  height: 100vh;
-  padding-bottom: 120rpx;
-}
-.cover {
-  width: 100%;
-  display: block;
-}
-.placeholder-cover {
-  height: 400rpx;
-  background: #f0f0f0;
-}
-
-/* 信息区 */
-.info-section {
-  padding: 30rpx;
-}
-.activity-title {
-  font-size: 36rpx;
-  font-weight: bold;
-  color: #1f2937;
-  line-height: 1.4;
-}
-.status-row {
-  margin-top: 16rpx;
-}
-.status-tag {
-  display: inline-block;
-  font-size: 22rpx;
-  padding: 4rpx 16rpx;
-  border-radius: 8rpx;
-}
-.status-draft { background: #F5F5F5; color: #999; }
-.status-published { background: #F0FDF4; color: #22C55E; }
-.status-ended { background: #F5F5F5; color: #999; }
-.status-upcoming { background: #FFF7ED; color: #F97316; }
-
-/* 元信息列表 */
-.meta-list {
-  margin-top: 24rpx;
-  background: #fff;
-  border-radius: 16rpx;
-  padding: 24rpx;
-}
-.meta-item {
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-  margin-bottom: 16rpx;
-}
-.meta-item:last-child {
-  margin-bottom: 0;
-}
-.meta-icon {
-  font-size: 28rpx;
-  margin-right: 12rpx;
-  width: 32rpx;
-  text-align: center;
-}
-.meta-text {
-  font-size: 26rpx;
-  color: #4b5563;
-  flex: 1;
-  line-height: 1.4;
-}
-
-/* 活动介绍 */
-.desc-section {
-  margin-top: 30rpx;
-  background: #fff;
-  border-radius: 16rpx;
-  padding: 24rpx;
-}
-.section-title {
-  font-size: 28rpx;
-  font-weight: 600;
-  color: #1f2937;
-  display: block;
-  margin-bottom: 12rpx;
-}
-.desc-text {
-  font-size: 26rpx;
-  color: #4b5563;
-  line-height: 1.6;
-}
-
-/* 付费不退费说明 */
-.refund-notice {
-  margin-top: 20rpx;
-  background: #FEF2F2;
-  border: 2rpx solid #FECACA;
-  border-radius: 12rpx;
-  padding: 16rpx 20rpx;
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-}
-.refund-notice-icon {
-  font-size: 24rpx;
-  margin-right: 10rpx;
-  flex-shrink: 0;
-}
-.refund-notice-text {
-  font-size: 24rpx;
-  color: #DC2626;
-  line-height: 1.4;
-}
-
-/* 底部操作栏 */
-.bottom-bar {
-  position: fixed;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background: #fff;
-  padding: 20rpx 30rpx;
-  padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-  justify-content: space-between;
-  box-shadow: 0 -2rpx 12rpx rgba(0,0,0,0.06);
-}
-.price-info {
-  display: flex;
-  flex-direction: column;
-}
-.bottom-type {
-  font-size: 22rpx;
-  color: #999;
-}
-.bottom-vendor {
-  font-size: 22rpx;
-  color: #999;
-  margin-top: 4rpx;
-}
-.action-btns {
-  display: flex;
-  flex-direction: row;
-  gap: 16rpx;
-  align-items: center;
-}
-.poster-btn {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  justify-content: center;
-  padding: 8rpx 16rpx;
-}
-.poster-btn-icon { font-size: 36rpx; }
-.poster-btn-text { font-size: 20rpx; color: #64748B; }
-
-/* 报名按钮 */
-.btn-register {
-  background: linear-gradient(135deg, #F97316, #FB923C);
-  color: #fff;
-  border: none;
-  border-radius: 40rpx;
-  padding: 16rpx 48rpx;
-  font-size: 28rpx;
-  font-weight: 600;
-  line-height: 1.5;
-  min-width: 160rpx;
-  text-align: center;
-}
-.btn-register:active {
-  opacity: 0.85;
-}
-.btn-register-loading {
-  opacity: 0.7;
-}
-
-/* 已报名(待审核) */
-.btn-register-done {
-  background: #9CA3AF;
-  color: #fff;
-  border: none;
-  border-radius: 40rpx;
-  padding: 16rpx 48rpx;
-  font-size: 28rpx;
-  font-weight: 600;
-  line-height: 1.5;
-  min-width: 160rpx;
-  text-align: center;
-}
-
-/* 已报名(可取消) */
-.btn-registered {
-  background: #F3F4F6;
-  color: #4B5563;
-  border: 2rpx solid #D1D5DB;
-  border-radius: 40rpx;
-  padding: 14rpx 36rpx;
-  font-size: 26rpx;
-  font-weight: 500;
-  line-height: 1.5;
-  min-width: 120rpx;
-  text-align: center;
-}
-.btn-registered:active {
-  opacity: 0.7;
-}
-
-/* 签到按钮 */
-.btn-checkin {
-  background: linear-gradient(135deg, #F97316, #FB923C);
-  color: #fff;
-  border: none;
-  border-radius: 40rpx;
-  padding: 16rpx 48rpx;
-  font-size: 28rpx;
-  font-weight: 600;
-  line-height: 1.5;
-  min-width: 160rpx;
-  text-align: center;
-}
-.btn-checkin:active {
-  opacity: 0.85;
-}
-.btn-checkin-done {
-  background: #22C55E;
-}
-.btn-checkin-loading {
-  opacity: 0.7;
-}
-</style>

+ 0 - 642
cfc-frontend/pages/discover/product-detail/product-detail.vue

@@ -1,642 +0,0 @@
-<template>
-  <view class="container">
-    <view v-if="loading" class="loading-wrap">
-      <text class="loading-text">加载中...</text>
-    </view>
-    <scroll-view v-else-if="product.id" scroll-y class="content">
-      <image
-        class="cover"
-        :src="product.coverImage || '/static/default-product.png'"
-        mode="widthFix"
-      />
-      <view class="info-section">
-        <view class="name-row">
-          <text class="product-name">{{ product.name }}</text>
-        </view>
-        <view class="price-row">
-          <text class="price">{{ formatPriceWithSymbol(displayPrice) }}</text>
-          <text v-if="product.memberPrice" class="member-price">会员价 {{ formatPriceWithSymbol(product.memberPrice) }}</text>
-        </view>
-        <!-- Member upgrade banner -->
-        <view v-if="showMemberBanner" class="member-banner" @click="goUpgrade">
-          <text class="member-banner-text">开通会员立省 <text class="member-banner-saving">{{ formatPriceWithSymbol(product.price - product.memberPrice) }}</text>,享会员专享价</text>
-          <text class="member-banner-arrow">›</text>
-        </view>
-        <view v-if="effectivePpointText" class="ppoint-row">
-          <text class="ppoint-label">可分配利润:</text>
-          <text class="ppoint-value">{{ effectivePpointText }}</text>
-        </view>
-        <view class="meta-row">
-          <text class="meta-item" v-if="product.productType">{{ typeLabel }}</text>
-          <text class="meta-item" v-if="product.domain">{{ domainLabel }}</text>
-          <text class="meta-item">库存 {{ product.stock || 0 }}</text>
-        </view>
-
-        <!-- Spec Selector -->
-        <view v-if="specGroups.length > 0" class="spec-section">
-          <view v-for="group in specGroups" :key="group.id" class="spec-group">
-            <text class="spec-group-name">{{ group.name }}</text>
-            <view class="spec-options">
-              <text
-                v-for="opt in specMap[group.id] || []"
-                :key="opt.id"
-                :class="['spec-chip', selectedSpecs[group.id] === opt.id ? 'spec-chip-active' : '']"
-                @click="selectSpec(group.id, opt.id)"
-              >{{ opt.name }}</text>
-            </view>
-          </view>
-        </view>
-
-        <!-- Supplier Info -->
-        <view class="vendor-row">
-          <text class="vendor-label">供应商:</text>
-          <text class="vendor-name">{{ product.vendorName || '平台官方' }}</text>
-        </view>
-        <view v-if="suppliers.length > 0" class="supplier-row">
-          <view v-for="s in suppliers" :key="s.supplierId" class="supplier-tag">
-            <text class="supplier-name">{{ s.supplierName }}</text>
-          </view>
-        </view>
-      </view>
-
-      <view class="desc-section" v-if="product.description">
-        <text class="section-title">商品介绍</text>
-        <mp-html :content="product.description" />
-      </view>
-
-      <view v-if="product.intro" class="intro-section">
-        <text class="section-title">详细介绍</text>
-        <mp-html :content="product.intro" />
-      </view>
-
-      <view class="bottom-bar">
-        <view class="price-info">
-          <text class="bottom-price">{{ formatPriceWithSymbol(product.price) }}</text>
-          <text v-if="product.memberPrice" class="bottom-member">会员{{ formatPriceWithSymbol(product.memberPrice) }}</text>
-        </view>
-        <view class="action-btns">
-          <button class="share-btn" open-type="share" @click="onShareTap">
-            <text class="share-btn-icon">📤</text>
-            <text class="share-btn-text">分享</text>
-          </button>
-          <view class="share-btn" @click="generatePoster">
-            <text class="share-btn-icon">🖼</text>
-            <text class="share-btn-text">海报</text>
-          </view>
-          <view class="cart-icon-wrap" @click="onAddToCart">
-            <text class="cart-icon">🛒</text>
-            <text v-if="cartCount > 0" class="cart-badge">{{ cartCount > 99 ? '99+' : cartCount }}</text>
-          </view>
-          <button class="btn-cart" @click="onAddToCart">加入购物车</button>
-          <button class="btn-buy" @click="onBuy">立即购买</button>
-        </view>
-      </view>
-    </scroll-view>
-    <view v-else class="empty-wrap">
-      <text class="empty-text">商品不存在或已下架</text>
-    </view>
-
-    <ContentSharePoster
-      :show="showPoster"
-      :title="product.name"
-      :coverImage="product.coverImage"
-      :qrCodeBase64="posterQrCode"
-      typeLabel="好物推荐"
-      @close="showPoster = false"
-    />
-  </view>
-</template>
-
-<script>
-import config from '@/config.js'
-import { productDetail, getMyMembership, getShareQrCode } from '@/utils/api.js'
-import shareMixin from '../../components/share-mixin.js'
-import ContentSharePoster from '@/components/ContentSharePoster.vue'
-import MpHtml from '@/components/mp-html/mp-html.vue'
-
-export default {
-  mixins: [shareMixin],
-  components: { ContentSharePoster, MpHtml },
-  data() {
-    return {
-      product: {},
-      loading: false,
-      cartCount: 0,
-      specGroups: [],
-      specMap: {},
-      selectedSpecs: {},
-      suppliers: [],
-      isMember: false,
-      showPoster: false,
-      posterQrCode: ''
-    }
-  },
-  computed: {
-    showMemberBanner() {
-      return !this.isMember && this.product.memberPrice && this.product.memberPrice < this.product.price
-    },
-    typeLabel() {
-      var map = {
-        activity: '活动',
-        course: '课程',
-        physical: '实物',
-        digital: '数字',
-        service: '服务'
-      }
-      return map[this.product.productType] || this.product.productType
-    },
-    domainLabel() {
-      var map = {
-        action: '行动',
-        mind: '心智',
-        body: '身体',
-        wisdom: '智慧',
-        wealth: '财富'
-      }
-      return map[this.product.domain] || this.product.domain
-    },
-    displayPrice() {
-      return this.product.price || 0
-    },
-    selectedSpecDesc() {
-      var parts = []
-      for (var gid in this.selectedSpecs) {
-        var oid = this.selectedSpecs[gid]
-        var group = this.specGroups.find(function(g) { return g.id === Number(gid) })
-        if (!group) continue
-        var opts = this.specMap[gid] || []
-        var opt = opts.find(function(o) { return o.id === oid })
-        if (opt) {
-          parts.push(group.name + ':' + opt.name)
-        }
-      }
-      return parts.join(', ')
-    },
-    effectivePpointText() {
-      if (!this.product.effectivePpoint && this.product.effectivePpoint !== 0) return ''
-      return (this.product.effectivePpoint / 100).toFixed(2) + '%'
-    }
-  },
-  onLoad(options) {
-    this.checkMemberStatus()
-    if (options.id) {
-      this.loadDetail(options.id)
-    }
-  },
-  onShow() {
-    this.loadCartCount()
-  },
-  methods: {
-    async generatePoster() {
-      if (!this.product.id) return
-      uni.showLoading({ title: '生成海报中...' })
-      try {
-        var page = 'pages/discover/product-detail/product-detail'
-        var scene = 'id=' + this.product.id
-        var res = await getShareQrCode(page, scene)
-        if (res && res.data) {
-          this.posterQrCode = res.data.qrCodeBase64 || ''
-          this.showPoster = true
-        }
-      } catch (e) {
-        uni.showToast({ title: '生成失败', icon: 'none' })
-      } finally {
-        uni.hideLoading()
-      }
-    },
-    checkMemberStatus() {
-      var that = this
-      getMyMembership().then(function(res) {
-        if (res.data && res.data.memberLevel) {
-          that.isMember = res.data.memberLevel !== 'FREE'
-        }
-      }).catch(function() {})
-    },
-    goUpgrade() {
-      uni.navigateTo({ url: '/pages/membership/upgrade' })
-    },
-    loadDetail(id) {
-      this.loading = true
-      var that = this
-      productDetail({ id: parseInt(id) }).then(function(res) {
-        that.loading = false
-        if (res.code === 200 && res.data) {
-          that.product = res.data
-          that.setShareInfo('推荐商品: ' + (res.data.name || ''), '/pages/discover/product-detail/product-detail?id=' + id)
-          that.loadSpecs(id)
-          that.loadSuppliers(id)
-        }
-      }).catch(function() {
-        that.loading = false
-      })
-    },
-    loadSpecs(productId) {
-      var that = this
-      uni.request({
-        url: config.api('/api/product/spec/map'),
-        method: 'POST',
-        data: { productId: productId },
-        header: {
-          'Content-Type': 'application/json',
-          'Authorization': 'Bearer ' + uni.getStorageSync('token')
-        },
-        success: function(res) {
-          if (res.data && res.data.code === 200 && res.data.data) {
-            that.specMap = res.data.data
-            var allGroups = []
-            for (var gid in res.data.data) {
-              var options = res.data.data[gid]
-              if (options && options.length > 0) {
-                allGroups.push({
-                  id: Number(gid),
-                  productId: productId,
-                  name: options[0].groupId ? '' : ''
-                })
-              }
-            }
-            that.specGroups = allGroups
-          }
-        }
-      })
-    },
-    loadSuppliers(productId) {
-      var that = this
-      uni.request({
-        url: config.api('/api/admin/supplier/product/list'),
-        method: 'POST',
-        data: { productId: productId },
-        header: {
-          'Content-Type': 'application/json',
-          'Authorization': 'Bearer ' + uni.getStorageSync('token')
-        },
-        success: function(res) {
-          if (res.data && res.data.code === 200) {
-            that.suppliers = res.data.data || []
-          }
-        }
-      })
-    },
-    selectSpec(groupId, optionId) {
-      var specs = {}
-      for (var k in this.selectedSpecs) {
-        specs[k] = this.selectedSpecs[k]
-      }
-      if (specs[groupId] === optionId) {
-        delete specs[groupId]
-      } else {
-        specs[groupId] = optionId
-      }
-      this.selectedSpecs = specs
-    },
-    loadCartCount() {
-      var that = this
-      uni.request({
-        url: config.api('/api/cart/count'),
-        method: 'POST',
-        data: {},
-        header: {
-          'Content-Type': 'application/json',
-          'Authorization': 'Bearer ' + uni.getStorageSync('token')
-        },
-        success: function(res) {
-          if (res.data && res.data.code === 200) {
-            that.cartCount = res.data.data || 0
-          }
-        }
-      })
-    },
-    onAddToCart() {
-      var that = this
-      var specOptionIds = []
-      for (var k in this.selectedSpecs) {
-        specOptionIds.push(this.selectedSpecs[k])
-      }
-      uni.request({
-        url: config.api('/api/cart/add'),
-        method: 'POST',
-        data: {
-          productId: this.product.id,
-          quantity: 1,
-          specOptionIds: specOptionIds.length > 0 ? JSON.stringify(specOptionIds) : ''
-        },
-        header: {
-          'Content-Type': 'application/json',
-          'Authorization': 'Bearer ' + uni.getStorageSync('token')
-        },
-        success: function(res) {
-          if (res.data && res.data.code === 200) {
-            uni.showToast({ title: '已加入购物车', icon: 'success' })
-            that.loadCartCount()
-          } else {
-            uni.showToast({ title: res.data.message || '加入失败', icon: 'none' })
-          }
-        },
-        fail: function() {
-          uni.showToast({ title: '网络请求失败', icon: 'none' })
-        }
-      })
-    },
-    onBuy() {
-      if (!this.product.id) return
-      var specOptionIds = []
-      for (var k in this.selectedSpecs) {
-        specOptionIds.push(this.selectedSpecs[k])
-      }
-      var url = '/pages/shop/checkout/checkout?productId=' + this.product.id
-        + '&productName=' + encodeURIComponent(this.product.name || '')
-        + '&price=' + (this.product.price || 0)
-        + '&coverImage=' + encodeURIComponent(this.product.coverImage || '')
-        + '&quantity=1'
-        + '&specOptionIds=' + (specOptionIds.length > 0 ? encodeURIComponent(JSON.stringify(specOptionIds)) : '')
-      uni.navigateTo({ url: url })
-    },
-    formatPriceWithSymbol(price) {
-      if (price === null || price === undefined) return '0.00'
-      return (Number(price) / 100).toFixed(2)
-    }
-  }
-}
-</script>
-
-<style scoped>
-.container {
-  min-height: 100vh;
-  background: #f5f5f5;
-}
-.loading-wrap,
-.empty-wrap {
-  display: flex;
-  justify-content: center;
-  padding-top: 200rpx;
-}
-.loading-text,
-.empty-text {
-  font-size: 28rpx;
-  color: #999;
-}
-.content {
-  height: calc(100vh - 120rpx);
-  padding-bottom: 120rpx;
-}
-.cover {
-  width: 100%;
-  background: #f0f0f0;
-}
-.info-section {
-  background: #fff;
-  padding: 30rpx;
-  margin-bottom: 20rpx;
-}
-.name-row {
-  margin-bottom: 16rpx;
-}
-.product-name {
-  font-size: 34rpx;
-  font-weight: bold;
-  color: #333;
-  line-height: 1.4;
-}
-.price-row {
-  display: flex;
-  align-items: baseline;
-  margin-bottom: 16rpx;
-}
-.member-banner {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  background: linear-gradient(135deg, #FFF7ED, #FFEDD5);
-  border: 2rpx solid #FED7AA;
-  border-radius: 12rpx;
-  padding: 16rpx 20rpx;
-  margin-bottom: 16rpx;
-}
-.member-banner-text {
-  font-size: 24rpx;
-  color: #C2410C;
-}
-.member-banner-saving {
-  font-size: 30rpx;
-  font-weight: bold;
-  color: #F97316;
-}
-.member-banner-arrow {
-  font-size: 32rpx;
-  color: #F97316;
-}
-.price {
-  font-size: 40rpx;
-  color: #F97316;
-  font-weight: bold;
-  margin-right: 20rpx;
-}
-.member-price {
-  font-size: 26rpx;
-  color: #999;
-}
-.ppoint-row {
-  display: flex;
-  align-items: center;
-  margin-bottom: 12rpx;
-}
-.ppoint-label {
-  font-size: 24rpx;
-  color: #666;
-}
-.ppoint-value {
-  font-size: 26rpx;
-  color: #10B981;
-  font-weight: 500;
-}
-.meta-row {
-  display: flex;
-  flex-wrap: wrap;
-  margin-bottom: 12rpx;
-}
-.meta-item {
-  font-size: 22rpx;
-  color: #999;
-  background: #f5f5f5;
-  padding: 4rpx 16rpx;
-  border-radius: 4rpx;
-  margin-right: 12rpx;
-  margin-bottom: 8rpx;
-}
-.vendor-row {
-  display: flex;
-  align-items: center;
-}
-.vendor-label {
-  font-size: 24rpx;
-  color: #999;
-}
-.vendor-name {
-  font-size: 24rpx;
-  color: #666;
-}
-.spec-section {
-  padding: 20rpx 0;
-  border-top: 2rpx solid #f5f5f5;
-  margin-top: 16rpx;
-}
-.spec-group {
-  margin-bottom: 16rpx;
-}
-.spec-group:last-child {
-  margin-bottom: 0;
-}
-.spec-group-name {
-  font-size: 26rpx;
-  color: #666;
-  margin-bottom: 12rpx;
-  display: block;
-}
-.spec-options {
-  display: flex;
-  flex-wrap: wrap;
-  gap: 12rpx;
-}
-.spec-chip {
-  padding: 10rpx 24rpx;
-  border-radius: 8rpx;
-  font-size: 24rpx;
-  color: #666;
-  background: #f5f5f5;
-  border: 2rpx solid #eee;
-}
-.spec-chip-active {
-  color: #F97316;
-  background: #FFF7ED;
-  border-color: #F97316;
-}
-.supplier-row {
-  display: flex;
-  flex-wrap: wrap;
-  gap: 8rpx;
-  margin-top: 8rpx;
-}
-.supplier-tag {
-  background: #f0f9ff;
-  padding: 4rpx 16rpx;
-  border-radius: 4rpx;
-}
-.supplier-name {
-  font-size: 22rpx;
-  color: #0EA5E9;
-}
-.desc-section,
-.intro-section {
-  background: #fff;
-  padding: 30rpx;
-  margin-bottom: 20rpx;
-}
-.section-title {
-  font-size: 28rpx;
-  font-weight: bold;
-  color: #333;
-  margin-bottom: 16rpx;
-  display: block;
-}
-.desc-text,
-.intro-text {
-  font-size: 26rpx;
-  color: #666;
-  line-height: 1.6;
-  display: block;
-}
-.bottom-bar {
-  position: fixed;
-  bottom: 0;
-  left: 0;
-  right: 0;
-  height: 100rpx;
-  background: #fff;
-  border-top: 1rpx solid #eee;
-  display: flex;
-  align-items: center;
-  padding: 0 30rpx;
-  justify-content: space-between;
-  z-index: 100;
-}
-.price-info {
-  display: flex;
-  align-items: baseline;
-}
-.bottom-price {
-  font-size: 36rpx;
-  color: #F97316;
-  font-weight: bold;
-}
-.bottom-member {
-  font-size: 24rpx;
-  color: #999;
-  margin-left: 10rpx;
-}
-.action-btns {
-  display: flex;
-  align-items: center;
-}
-.btn-buy {
-  background: linear-gradient(135deg, #F97316, #FB923C);
-  color: #fff;
-  font-size: 28rpx;
-  font-weight: bold;
-  padding: 0 60rpx;
-  height: 72rpx;
-  line-height: 72rpx;
-  border-radius: 36rpx;
-  border: none;
-}
-.btn-buy::after {
-  border: none;
-}
-.action-extra {
-  display: flex;
-  align-items: center;
-  margin-right: 20rpx;
-}
-.btn-favorite {
-  font-size: 40rpx;
-  margin-right: 16rpx;
-  padding: 0 8rpx;
-}
-.btn-cart {
-  background: #fff;
-  color: #F97316;
-  border: 2rpx solid #F97316;
-  font-size: 26rpx;
-  padding: 0 24rpx;
-  height: 64rpx;
-  line-height: 64rpx;
-  border-radius: 32rpx;
-}
-.btn-cart::after {
-  border: none;
-}
-.cart-icon-wrap {
-  position: relative;
-  margin-right: 16rpx;
-  padding: 8rpx;
-}
-.cart-icon {
-  font-size: 44rpx;
-}
-.cart-badge {
-  position: absolute;
-  top: -4rpx;
-  right: -8rpx;
-  min-width: 32rpx;
-  height: 32rpx;
-  line-height: 32rpx;
-  text-align: center;
-  background: #F97316;
-  color: #fff;
-  font-size: 20rpx;
-  border-radius: 16rpx;
-  padding: 0 6rpx;
-}
-.share-btn { height: 64rpx; line-height: 64rpx; background: #f5f5f5; color: #666; font-size: 24rpx; border-radius: 32rpx; padding: 0 20rpx; margin-right: 12rpx; display: flex; align-items: center; border: none; flex-shrink: 0; }
-.share-btn::after { border: none; }
-.share-btn-icon { font-size: 28rpx; margin-right: 4rpx; }
-.share-btn-text { font-size: 24rpx; }
-</style>

+ 1 - 1
cfc-frontend/pages/health/report-upload.vue

@@ -499,7 +499,7 @@ export default {
       })
     },
     goToProduct: function(productId) {
-      uni.navigateTo({ url: '/pages/discover/product-detail/product-detail?id=' + productId })
+      uni.navigateTo({ url: '/pages/discover-detail/product-detail/product-detail?id=' + productId })
     },
     formatPriceWithSymbol: function(cents) {
       if (cents === null || cents === undefined) return '¥0'

+ 2 - 2
cfc-frontend/pages/home-pages/child-index.vue

@@ -713,9 +713,9 @@ export default {
     // ======================== 推荐信息流 ========================
     onFeedItemClick: function(item) {
       if (item.type === 'product') {
-        uni.navigateTo({ url: '/pages/discover/product-detail/product-detail?id=' + item.id })
+        uni.navigateTo({ url: '/pages/discover-detail/product-detail/product-detail?id=' + item.id })
       } else if (item.type === 'activity') {
-        uni.navigateTo({ url: '/pages/discover/activity-detail/activity-detail?id=' + item.id })
+        uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + item.id })
       }
     },
     goMoreDiscover: function() {

+ 2 - 2
cfc-frontend/pages/home-pages/parent-index.vue

@@ -942,9 +942,9 @@ export default {
     goToRewards() { uni.switchTab({ url: '/pages/rewards/rewards' }) },
     onFeedItemClick(item) {
       if (item.type === 'product') {
-        uni.navigateTo({ url: '/pages/discover/product-detail/product-detail?id=' + item.id })
+        uni.navigateTo({ url: '/pages/discover-detail/product-detail/product-detail?id=' + item.id })
       } else if (item.type === 'activity') {
-        uni.navigateTo({ url: '/pages/discover/activity-detail/activity-detail?id=' + item.id })
+        uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + item.id })
       }
     },
     goMoreDiscover() {

+ 3 - 3
cfc-frontend/pages/index-home/index.vue

@@ -757,7 +757,7 @@ export default {
     },
     goActivityDetail: function(act) {
       if (!act || !act.id) return
-      uni.navigateTo({ url: '/pages/discover-detail/activity-detail/activity-detail?id=' + act.id })
+      uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + act.id })
     },
     goMoreActivities: function() {
       uni.navigateTo({ url: '/pages/activity/index' })
@@ -931,7 +931,7 @@ export default {
       uni.navigateTo({ url: '/pages/discover/index?type=activity' })
     },
     goActivityDetail: function(act) {
-      uni.navigateTo({ url: '/pages/discover-detail/activity-detail/activity-detail?id=' + act.id })
+      uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + act.id })
     },
     goArticles: function() {
       uni.navigateTo({ url: '/pages/mind-detail/articles' })
@@ -948,7 +948,7 @@ export default {
       uni.navigateTo({ url: '/pages/discover/index' })
     },
     goDetail(id) {
-      uni.navigateTo({ url: '/pages/discover/product-detail/product-detail?id=' + id })
+      uni.navigateTo({ url: '/pages/discover-detail/product-detail/product-detail?id=' + id })
     },
     handleLogin() {
       uni.navigateTo({ url: '/pages/login/login?redirect=' + encodeURIComponent('/pages/index-home/index') })

+ 1 - 1
cfc-frontend/pages/member-detail/member-detail.vue

@@ -368,7 +368,7 @@ export default {
       if (item.type === 'product') {
         uni.navigateTo({ url: '/pages/discover-detail/product-detail/product-detail?id=' + item.id })
       } else if (item.type === 'activity') {
-        uni.navigateTo({ url: '/pages/discover-detail/activity-detail/activity-detail?id=' + item.id })
+        uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + item.id })
       }
     },
     goMoreDiscover: function() {

+ 2 - 2
cfc-frontend/pages/mind-detail/member-mind-detail.vue

@@ -199,13 +199,13 @@ export default {
       uni.navigateTo({ url: '/pages/tasks/tasks' })
     },
     goActivityDetail: function(act) {
-      if (act && act.id) uni.navigateTo({ url: '/pages/discover/activity-detail/activity-detail?id=' + act.id })
+      if (act && act.id) uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + act.id })
     },
     goMoreActivities: function() {
       uni.navigateTo({ url: '/pages/activity/index' })
     },
     goProductDetail: function(prod) {
-      if (prod && prod.id) uni.navigateTo({ url: '/pages/discover/product-detail/product-detail?id=' + prod.id })
+      if (prod && prod.id) uni.navigateTo({ url: '/pages/discover-detail/product-detail/product-detail?id=' + prod.id })
     },
     goMoreProducts: function() {
       uni.navigateTo({ url: '/pages/shop/index' })

+ 1 - 1
cfc-frontend/pages/mind/index.vue

@@ -900,7 +900,7 @@ components: { TabTransition, PageBanner, RadarChart, LoginGuideCard, FamilyEnerg
       uni.navigateTo({ url: '/pages/tasks/tasks' })
     },
     goActivityDetail: function(act) {
-      if (act && act.id) uni.navigateTo({ url: '/pages/discover-detail/activity-detail/activity-detail?id=' + act.id })
+      if (act && act.id) uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + act.id })
     },
     goMoreActivities: function() {
       uni.navigateTo({ url: '/pages/activity/index' })

+ 2 - 2
cfc-frontend/pages/mind/member-mind-detail.vue

@@ -199,13 +199,13 @@ export default {
       uni.navigateTo({ url: '/pages/tasks/tasks' })
     },
     goActivityDetail: function(act) {
-      if (act && act.id) uni.navigateTo({ url: '/pages/discover/activity-detail/activity-detail?id=' + act.id })
+      if (act && act.id) uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + act.id })
     },
     goMoreActivities: function() {
       uni.navigateTo({ url: '/pages/activity/index' })
     },
     goProductDetail: function(prod) {
-      if (prod && prod.id) uni.navigateTo({ url: '/pages/discover/product-detail/product-detail?id=' + prod.id })
+      if (prod && prod.id) uni.navigateTo({ url: '/pages/discover-detail/product-detail/product-detail?id=' + prod.id })
     },
     goMoreProducts: function() {
       uni.navigateTo({ url: '/pages/shop/index' })

+ 1 - 1
cfc-frontend/pages/shop/detail/detail.vue

@@ -7,7 +7,7 @@ export default {
   onLoad(options) {
     const id = options.id || ''
     uni.redirectTo({
-      url: '/pages/discover/product-detail/product-detail?id=' + id + '&source=shop'
+      url: '/pages/discover-detail/product-detail/product-detail?id=' + id + '&source=shop'
     })
   }
 }

+ 1 - 1
cfc-frontend/pages/wisdom-detail/member-wisdom-detail.vue

@@ -147,7 +147,7 @@ export default {
     goProductDetail: function(id) {
       var token = uni.getStorageSync('token')
       if (token) {
-        uni.navigateTo({ url: '/pages/discover/product-detail/product-detail?id=' + id })
+        uni.navigateTo({ url: '/pages/discover-detail/product-detail/product-detail?id=' + id })
       } else {
         uni.navigateTo({ url: '/pages/login/login' })
       }

+ 1 - 1
cfc-frontend/pages/wisdom/index.vue

@@ -405,7 +405,7 @@ export default {
     goTasks: function() { uni.switchTab({ url: '/pages/tasks/tasks' }) },
     goActivityDetail: function(act) {
       if (!act || !act.id) return
-      uni.navigateTo({ url: '/pages/discover-detail/activity-detail/activity-detail?id=' + act.id })
+      uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + act.id })
     },
     goProductDetail: function(prod) {
       if (prod && prod.id) {

+ 1 - 1
cfc-frontend/pages/wisdom/member-wisdom-detail.vue

@@ -147,7 +147,7 @@ export default {
     goProductDetail: function(id) {
       var token = uni.getStorageSync('token')
       if (token) {
-        uni.navigateTo({ url: '/pages/discover/product-detail/product-detail?id=' + id })
+        uni.navigateTo({ url: '/pages/discover-detail/product-detail/product-detail?id=' + id })
       } else {
         uni.navigateTo({ url: '/pages/login/login' })
       }