Răsfoiți Sursa

feat: 添加五行能量沙盘(溪艾福)组件和溪福俱乐部占位页面(发现/商城/入驻/中心)

User 3 luni în urmă
părinte
comite
0e9cc68345

+ 49 - 0
zxyj-frontend/pages/discover/index.vue

@@ -0,0 +1,49 @@
+<template>
+  <view class="container">
+    <view class="placeholder">
+      <text class="icon">🔍</text>
+      <text class="title">发现</text>
+      <text class="desc">活动与课程即将上线,敬请期待</text>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {}
+  },
+  onLoad() {}
+}
+</script>
+
+<style>
+.container {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  min-height: 100vh;
+  background: #f8f8f8;
+}
+.placeholder {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 100rpx 40rpx;
+}
+.icon {
+  font-size: 120rpx;
+  margin-bottom: 30rpx;
+}
+.title {
+  font-size: 40rpx;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 20rpx;
+}
+.desc {
+  font-size: 28rpx;
+  color: #999;
+  text-align: center;
+}
+</style>

+ 129 - 0
zxyj-frontend/pages/index/child-index.vue

@@ -51,6 +51,40 @@
         </view>
       </view>
 
+      <!-- 五行能量沙盘(溪艾福) -->
+      <view class="wuxing-sandbox">
+        <view class="sandbox-header">
+          <text class="sandbox-title">我的五行能量</text>
+          <text class="sandbox-badge">综合 0%</text>
+        </view>
+        <view class="sandbox-star">
+          <view class="star-point star-point-top" @click="goToDomain('mind')">
+            <text class="point-icon">🔥</text>
+            <text class="point-label">心·火</text>
+          </view>
+          <view class="star-point star-point-left" @click="goToDomain('action')">
+            <text class="point-icon">🌿</text>
+            <text class="point-label">行·木</text>
+          </view>
+          <view class="star-point star-point-right" @click="goToDomain('wealth')">
+            <text class="point-icon">💧</text>
+            <text class="point-label">富·水</text>
+          </view>
+          <view class="star-point star-point-bl" @click="goToDomain('wisdom')">
+            <text class="point-icon">⚔️</text>
+            <text class="point-label">智·金</text>
+          </view>
+          <view class="star-point star-point-br" @click="goToDomain('body')">
+            <text class="point-icon">🌏</text>
+            <text class="point-label">身·土</text>
+          </view>
+          <view class="star-center">
+            <text class="center-text">我的能量</text>
+            <text class="center-sub">加油成长</text>
+          </view>
+        </view>
+      </view>
+
       <!-- 任务进度卡片 -->
       <view class="task-card">
         <view class="task-header">
@@ -286,6 +320,9 @@ export default {
     },
     goToAddChild() {
       uni.navigateTo({ url: '/pages/profile/create-child' })
+    },
+    goToDomain(domain) {
+      uni.showToast({ title: '即将上线', icon: 'none' })
     }
   }
 }
@@ -840,4 +877,96 @@ export default {
 .section-more:active {
   opacity: 0.6;
 }
+
+/* ===== 五行能量沙盘(溪艾福) ===== */
+.wuxing-sandbox {
+  margin: 20rpx 30rpx;
+  padding: 30rpx;
+  background: linear-gradient(135deg, #1a1a2e, #16213e);
+  border-radius: 24rpx;
+  position: relative;
+  overflow: hidden;
+}
+.sandbox-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 30rpx;
+}
+.sandbox-title {
+  font-size: 28rpx;
+  font-weight: bold;
+  color: #FFD700;
+}
+.sandbox-badge {
+  font-size: 22rpx;
+  color: #aaa;
+  background: rgba(255,255,255,0.1);
+  padding: 6rpx 16rpx;
+  border-radius: 20rpx;
+}
+.sandbox-star {
+  position: relative;
+  height: 400rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.star-point {
+  position: absolute;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  width: 120rpx;
+}
+.star-point-top {
+  top: 0;
+  left: 50%;
+  transform: translateX(-50%);
+}
+.star-point-left {
+  top: 120rpx;
+  left: 20rpx;
+}
+.star-point-right {
+  top: 120rpx;
+  right: 20rpx;
+}
+.star-point-bl {
+  bottom: 40rpx;
+  left: 60rpx;
+}
+.star-point-br {
+  bottom: 40rpx;
+  right: 60rpx;
+}
+.point-icon {
+  font-size: 50rpx;
+  margin-bottom: 6rpx;
+}
+.point-label {
+  font-size: 22rpx;
+  color: #fff;
+  font-weight: bold;
+}
+.star-center {
+  width: 120rpx;
+  height: 120rpx;
+  background: radial-gradient(circle, rgba(255,215,0,0.2), rgba(255,215,0,0.05));
+  border: 2rpx solid rgba(255,215,0,0.3);
+  border-radius: 50%;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+}
+.center-text {
+  font-size: 22rpx;
+  color: #FFD700;
+  font-weight: bold;
+}
+.center-sub {
+  font-size: 18rpx;
+  color: #aaa;
+}
 </style>

+ 246 - 0
zxyj-frontend/pages/index/parent-index.vue

@@ -65,6 +65,75 @@
         </view>
       </view>
 
+      <!-- 五行能量沙盘(溪艾福) -->
+      <view class="wuxing-sandbox">
+        <view class="sandbox-header">
+          <text class="sandbox-title">五行能量沙盘</text>
+          <text class="sandbox-badge">综合成长力 0%</text>
+        </view>
+        <view class="sandbox-star">
+          <!-- 五角星布局 -->
+          <view class="star-point star-point-top" @click="goToDomain('mind')">
+            <text class="point-icon">🔥</text>
+            <text class="point-label">心·火</text>
+            <text class="point-status inactive">待激活</text>
+          </view>
+          <view class="star-point star-point-left" @click="goToDomain('action')">
+            <text class="point-icon">🌿</text>
+            <text class="point-label">行·木</text>
+            <text class="point-status inactive">待激活</text>
+          </view>
+          <view class="star-point star-point-right" @click="goToDomain('wealth')">
+            <text class="point-icon">💧</text>
+            <text class="point-label">富·水</text>
+            <text class="point-status inactive">待激活</text>
+          </view>
+          <view class="star-point star-point-bl" @click="goToDomain('wisdom')">
+            <text class="point-icon">⚔️</text>
+            <text class="point-label">智·金</text>
+            <text class="point-status inactive">待激活</text>
+          </view>
+          <view class="star-point star-point-br" @click="goToDomain('body')">
+            <text class="point-icon">🌏</text>
+            <text class="point-label">身·土</text>
+            <text class="point-status inactive">待激活</text>
+          </view>
+          <!-- 中心徽章 -->
+          <view class="star-center">
+            <text class="center-text">五行平衡</text>
+            <text class="center-sub">共同成长</text>
+          </view>
+        </view>
+        <!-- 相生指引 -->
+        <view class="shenke-hint">
+          <text class="hint-text">🌱 完成测评,点亮「身·土」</text>
+        </view>
+        <!-- 维度状态条 -->
+        <view class="dimension-bar">
+          <view class="dim-item inactive">🌿行</view>
+          <text class="dim-arrow">→</text>
+          <view class="dim-item inactive">🔥心</view>
+          <text class="dim-arrow">→</text>
+          <view class="dim-item inactive">🌏身</view>
+          <text class="dim-arrow">→</text>
+          <view class="dim-item inactive">⚔️智</view>
+          <text class="dim-arrow">→</text>
+          <view class="dim-item inactive">💧富</view>
+        </view>
+      </view>
+
+      <!-- 会员Banner(溪福俱乐部) -->
+      <view class="membership-banner" @click="goToMembership">
+        <view class="banner-content">
+          <text class="banner-icon">👑</text>
+          <view class="banner-text">
+            <text class="banner-title">{{ membershipText }}</text>
+            <text class="banner-subtitle">点击查看会员权益</text>
+          </view>
+          <text class="banner-arrow">›</text>
+        </view>
+      </view>
+
       <!-- 成长数据 -->
       <view class="stats-section">
         <view class="section-title">成长数据</view>
@@ -244,6 +313,7 @@ export default {
       pendingTasks: [],
       taskCompletionRate: 0,
       habitCount: 0,
+      membershipText: '开通家庭会员 畅享全部权益',
       loading: true,
       currentChildId: '',
       _initialLoadDone: false,
@@ -446,6 +516,12 @@ export default {
         uni.navigateTo({ url: '/pages/stats/completion-rate?familyView=1' })
       }
     },
+    goToDomain(domain) {
+      uni.showToast({ title: '即将上线', icon: 'none' })
+    },
+    goToMembership() {
+      uni.showToast({ title: '即将上线', icon: 'none' })
+    },
     goToChildDetail(child) {
       uni.navigateTo({ url: '/pages/parent/child-detail?childId=' + child.id + '&childName=' + encodeURIComponent(child.nickname || '') })
     },
@@ -1133,4 +1209,174 @@ export default {
   color: #636E72;
   font-weight: 500;
 }
+
+/* 溪福俱乐部 - 会员Banner */
+.membership-banner {
+  margin: 20rpx 30rpx;
+  padding: 30rpx;
+  background: linear-gradient(135deg, #FFD700, #FFA500);
+  border-radius: 20rpx;
+  box-shadow: 0 4rpx 20rpx rgba(255, 165, 0, 0.3);
+}
+.banner-content {
+  display: flex;
+  align-items: center;
+}
+.banner-icon {
+  font-size: 60rpx;
+  margin-right: 20rpx;
+}
+.banner-text {
+  flex: 1;
+}
+.banner-title {
+  font-size: 30rpx;
+  font-weight: bold;
+  color: #8B4513;
+  display: block;
+}
+.banner-subtitle {
+  font-size: 24rpx;
+  color: #A0522D;
+  margin-top: 6rpx;
+  display: block;
+}
+.banner-arrow {
+  font-size: 40rpx;
+  color: #8B4513;
+}
+
+/* ===== 五行能量沙盘(溪艾福) ===== */
+.wuxing-sandbox {
+  margin: 20rpx 30rpx;
+  padding: 30rpx;
+  background: linear-gradient(135deg, #1a1a2e, #16213e);
+  border-radius: 24rpx;
+  position: relative;
+  overflow: hidden;
+}
+.sandbox-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 30rpx;
+}
+.sandbox-title {
+  font-size: 28rpx;
+  font-weight: bold;
+  color: #FFD700;
+}
+.sandbox-badge {
+  font-size: 22rpx;
+  color: #aaa;
+  background: rgba(255,255,255,0.1);
+  padding: 6rpx 16rpx;
+  border-radius: 20rpx;
+}
+.sandbox-star {
+  position: relative;
+  height: 400rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.star-point {
+  position: absolute;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  width: 120rpx;
+}
+.star-point-top {
+  top: 0;
+  left: 50%;
+  transform: translateX(-50%);
+}
+.star-point-left {
+  top: 120rpx;
+  left: 20rpx;
+}
+.star-point-right {
+  top: 120rpx;
+  right: 20rpx;
+}
+.star-point-bl {
+  bottom: 40rpx;
+  left: 60rpx;
+}
+.star-point-br {
+  bottom: 40rpx;
+  right: 60rpx;
+}
+.point-icon {
+  font-size: 50rpx;
+  margin-bottom: 6rpx;
+}
+.point-label {
+  font-size: 22rpx;
+  color: #fff;
+  font-weight: bold;
+}
+.point-status {
+  font-size: 18rpx;
+  margin-top: 4rpx;
+}
+.point-status.inactive {
+  color: #666;
+}
+.point-status.active {
+  color: #4CAF50;
+}
+.star-center {
+  width: 120rpx;
+  height: 120rpx;
+  background: radial-gradient(circle, rgba(255,215,0,0.2), rgba(255,215,0,0.05));
+  border: 2rpx solid rgba(255,215,0,0.3);
+  border-radius: 50%;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+}
+.center-text {
+  font-size: 22rpx;
+  color: #FFD700;
+  font-weight: bold;
+}
+.center-sub {
+  font-size: 18rpx;
+  color: #aaa;
+}
+.shenke-hint {
+  text-align: center;
+  margin: 20rpx 0;
+}
+.hint-text {
+  font-size: 24rpx;
+  color: #FFD700;
+  opacity: 0.8;
+}
+.dimension-bar {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  gap: 8rpx;
+}
+.dim-item {
+  padding: 6rpx 16rpx;
+  border-radius: 20rpx;
+  font-size: 22rpx;
+}
+.dim-item.inactive {
+  background: rgba(255,255,255,0.1);
+  color: #666;
+}
+.dim-item.active {
+  background: rgba(76,175,80,0.3);
+  color: #4CAF50;
+}
+.dim-arrow {
+  color: #444;
+  font-size: 20rpx;
+}
 </style>

+ 49 - 0
zxyj-frontend/pages/shop/index.vue

@@ -0,0 +1,49 @@
+<template>
+  <view class="container">
+    <view class="placeholder">
+      <text class="icon">🛒</text>
+      <text class="title">商城</text>
+      <text class="desc">商品与服务即将上线,敬请期待</text>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {}
+  },
+  onLoad() {}
+}
+</script>
+
+<style>
+.container {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  min-height: 100vh;
+  background: #f8f8f8;
+}
+.placeholder {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 100rpx 40rpx;
+}
+.icon {
+  font-size: 120rpx;
+  margin-bottom: 30rpx;
+}
+.title {
+  font-size: 40rpx;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 20rpx;
+}
+.desc {
+  font-size: 28rpx;
+  color: #999;
+  text-align: center;
+}
+</style>

+ 164 - 0
zxyj-frontend/pages/vendor/apply.vue

@@ -0,0 +1,164 @@
+<template>
+  <view class="container">
+    <view class="header">
+      <text class="title">服务商入驻</text>
+      <text class="subtitle">选择服务商类型,提交入驻申请</text>
+    </view>
+
+    <view class="form">
+      <view class="form-item">
+        <text class="label">服务商类型</text>
+        <picker mode="selector" :range="vendorTypes" range-key="label" @change="onTypeChange">
+          <view class="picker">
+            <text v-if="formData.vendorType">{{ getTypeLabel(formData.vendorType) }}</text>
+            <text v-else class="placeholder">请选择服务商类型</text>
+            <text class="arrow">›</text>
+          </view>
+        </picker>
+      </view>
+
+      <view class="form-item">
+        <text class="label">资质说明</text>
+        <textarea
+          class="textarea"
+          v-model="formData.vendorInfo"
+          placeholder="请填写您的资质信息、服务经验等"
+          maxlength="500"
+        />
+        <text class="counter">{{ formData.vendorInfo.length }}/500</text>
+      </view>
+
+      <button class="btn-submit" :disabled="!formData.vendorType || submitting" @click="handleSubmit">
+        {{ submitting ? '提交中...' : '提交申请' }}
+      </button>
+    </view>
+  </view>
+</template>
+
+<script>
+import { vendorApply } from '../../utils/api'
+
+export default {
+  data() {
+    return {
+      vendorTypes: [
+        { value: 'planner', label: '成长规划师' },
+        { value: 'activity_provider', label: '活动提供商' },
+        { value: 'product_supplier', label: '商品供应商' }
+      ],
+      formData: {
+        vendorType: '',
+        vendorInfo: ''
+      },
+      submitting: false
+    }
+  },
+  methods: {
+    onTypeChange(e) {
+      this.formData.vendorType = this.vendorTypes[e.detail.value].value
+    },
+    getTypeLabel(value) {
+      const item = this.vendorTypes.find(t => t.value === value)
+      return item ? item.label : value
+    },
+    async handleSubmit() {
+      this.submitting = true
+      try {
+        const res = await vendorApply({
+          vendorType: this.formData.vendorType,
+          vendorInfo: this.formData.vendorInfo
+        })
+        uni.showToast({ title: '提交成功', icon: 'success' })
+        setTimeout(() => {
+          uni.navigateBack()
+        }, 1500)
+      } catch (e) {
+        // api.js already shows error toast
+      } finally {
+        this.submitting = false
+      }
+    }
+  }
+}
+</script>
+
+<style>
+.container {
+  padding: 30rpx;
+  background: #f8f8f8;
+  min-height: 100vh;
+}
+.header {
+  text-align: center;
+  padding: 40rpx 0;
+}
+.title {
+  font-size: 40rpx;
+  font-weight: bold;
+  color: #333;
+}
+.subtitle {
+  font-size: 26rpx;
+  color: #999;
+  margin-top: 10rpx;
+  display: block;
+}
+.form {
+  background: #fff;
+  border-radius: 20rpx;
+  padding: 30rpx;
+}
+.form-item {
+  margin-bottom: 30rpx;
+}
+.label {
+  font-size: 28rpx;
+  color: #333;
+  font-weight: bold;
+  display: block;
+  margin-bottom: 15rpx;
+}
+.picker {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 20rpx 0;
+  border-bottom: 2rpx solid #eee;
+}
+.placeholder {
+  color: #ccc;
+}
+.arrow {
+  color: #ccc;
+  font-size: 36rpx;
+}
+.textarea {
+  width: 100%;
+  height: 200rpx;
+  padding: 20rpx;
+  border: 2rpx solid #eee;
+  border-radius: 10rpx;
+  font-size: 28rpx;
+  box-sizing: border-box;
+}
+.counter {
+  display: block;
+  text-align: right;
+  font-size: 24rpx;
+  color: #ccc;
+  margin-top: 10rpx;
+}
+.btn-submit {
+  width: 100%;
+  height: 88rpx;
+  line-height: 88rpx;
+  background: linear-gradient(135deg, #FF6B6B, #FF8E53);
+  color: #fff;
+  border-radius: 44rpx;
+  font-size: 32rpx;
+  margin-top: 40rpx;
+}
+.btn-submit[disabled] {
+  opacity: 0.5;
+}
+</style>

+ 150 - 0
zxyj-frontend/pages/vendor/center.vue

@@ -0,0 +1,150 @@
+<template>
+  <view class="container">
+    <view class="header">
+      <text class="icon">🏪</text>
+      <text class="title">服务商中心</text>
+    </view>
+
+    <view class="info-card" v-if="vendorInfoData">
+      <view class="info-row">
+        <text class="info-label">服务商类型</text>
+        <text class="info-value">{{ getTypeLabel(vendorInfoData.vendorType) }}</text>
+      </view>
+      <view class="info-row">
+        <text class="info-label">真实姓名</text>
+        <text class="info-value">{{ vendorInfoData.realName || '未设置' }}</text>
+      </view>
+      <view class="info-row">
+        <text class="info-label">联系电话</text>
+        <text class="info-value">{{ vendorInfoData.phone || '未设置' }}</text>
+      </view>
+    </view>
+
+    <view class="menu-list">
+      <view class="menu-item" @click="goToProductManage">
+        <text>📦 商品管理</text>
+        <text class="arrow">›</text>
+      </view>
+      <view class="menu-item" @click="goToOrderManage">
+        <text>📋 订单管理</text>
+        <text class="arrow">›</text>
+      </view>
+    </view>
+
+    <view class="coming-soon">
+      <text>更多功能即将上线...</text>
+    </view>
+  </view>
+</template>
+
+<script>
+import { vendorInfo } from '../../utils/api'
+
+export default {
+  data() {
+    return {
+      vendorTypes: [
+        { value: 'planner', label: '成长规划师' },
+        { value: 'activity_provider', label: '活动提供商' },
+        { value: 'product_supplier', label: '商品供应商' }
+      ],
+      vendorInfoData: null
+    }
+  },
+  onLoad() {
+    this.loadVendorInfo()
+  },
+  methods: {
+    getTypeLabel(value) {
+      const item = this.vendorTypes.find(t => t.value === value)
+      return item ? item.label : value
+    },
+    async loadVendorInfo() {
+      try {
+        const res = await vendorInfo()
+        this.vendorInfoData = res.data
+      } catch (e) {
+        // handled by api.js
+      }
+    },
+    goToProductManage() {
+      uni.showToast({ title: '即将上线', icon: 'none' })
+    },
+    goToOrderManage() {
+      uni.showToast({ title: '即将上线', icon: 'none' })
+    }
+  }
+}
+</script>
+
+<style>
+.container {
+  padding: 30rpx;
+  background: #f8f8f8;
+  min-height: 100vh;
+}
+.header {
+  text-align: center;
+  padding: 40rpx 0;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+.icon {
+  font-size: 100rpx;
+  margin-bottom: 20rpx;
+}
+.title {
+  font-size: 36rpx;
+  font-weight: bold;
+  color: #333;
+}
+.info-card {
+  background: #fff;
+  border-radius: 20rpx;
+  padding: 30rpx;
+  margin-bottom: 30rpx;
+}
+.info-row {
+  display: flex;
+  justify-content: space-between;
+  padding: 15rpx 0;
+  border-bottom: 2rpx solid #f5f5f5;
+}
+.info-row:last-child {
+  border-bottom: none;
+}
+.info-label {
+  font-size: 28rpx;
+  color: #999;
+}
+.info-value {
+  font-size: 28rpx;
+  color: #333;
+}
+.menu-list {
+  background: #fff;
+  border-radius: 20rpx;
+}
+.menu-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 30rpx;
+  border-bottom: 2rpx solid #f5f5f5;
+  font-size: 30rpx;
+}
+.menu-item:last-child {
+  border-bottom: none;
+}
+.arrow {
+  color: #ccc;
+  font-size: 36rpx;
+}
+.coming-soon {
+  text-align: center;
+  padding: 60rpx;
+  color: #ccc;
+  font-size: 26rpx;
+}
+</style>