Просмотр исходного кода

chore(frontend): 合并远程cfclub改动 - ProfileMenu/intent-picker/journey-card/index-home

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
liaoxg 1 месяц назад
Родитель
Сommit
4127b47c9f

+ 91 - 2
cfc-frontend/components/ProfileMenu.vue

@@ -85,6 +85,13 @@
       </view>
     </view>
 
+    <!-- 重新选择意图提示 -->
+    <view class="intent-reselect-hint" v-if="hasIntent">
+      <text class="intent-reselect-label">当前意图:</text>
+      <text class="intent-reselect-value">{{ intentLabel }}</text>
+      <text class="intent-reselect-link" @click="onReSelect">重新选择 ›</text>
+    </view>
+
     <!-- 设置/重置密码弹窗 -->
     <view class="modal-mask" v-if="showPasswordModal" @click="showPasswordModal = false">
       <view class="modal" @click.stop>
@@ -104,14 +111,24 @@
         </view>
       </view>
     </view>
+
+    <!-- 重新选择意图弹层 -->
+    <IntentPicker
+      :show="showIntentPicker"
+      @select="handleReSelect"
+      @close="showIntentPicker = false" />
   </view>
 </template>
 
 <script>
-import { setPassword, verifyPassword, updateMemberVisibility, getVisibleFamilyMembers, vendorStatus, ensureFamily } from '../utils/api.js'
+import { setPassword, verifyPassword, updateMemberVisibility, getVisibleFamilyMembers, vendorStatus, ensureFamily, getUserIntent, chooseUserIntent } from '../utils/api.js'
+import IntentPicker from '../components/intent-picker.vue'
 
 export default {
   name: 'ProfileMenu',
+  components: {
+    IntentPicker
+  },
   props: {
     role: {
       type: String,
@@ -130,7 +147,10 @@ export default {
       newPassword: '',
       confirmPassword: '',
       showToFamily: 1,
-      isVendor: false
+      isVendor: false,
+      hasIntent: false,
+      intentLabel: '',
+      showIntentPicker: false
     }
   },
   onShow() {
@@ -138,6 +158,7 @@ export default {
     this.hasPassword = !!uni.getStorageSync('passwordSet')
     this.loadShowToFamily()
     this.checkVendorStatus()
+    this.loadUserIntent()
   },
   methods: {
     async loadShowToFamily() {
@@ -294,6 +315,51 @@ export default {
       } catch (e) {
         this.isVendor = false
       }
+    },
+    loadUserIntent() {
+      var self = this
+      getUserIntent().then(function(res) {
+        var intent = res && res.data
+        if (intent && intent.intentType) {
+          self.hasIntent = true
+          self.intentLabel = self.intentText(intent.intentType)
+        } else {
+          self.hasIntent = false
+          self.intentLabel = ''
+        }
+      }).catch(function() {
+        self.hasIntent = false
+      })
+    },
+    intentText(type) {
+      if (type === 'A') return '随便看看'
+      if (type === 'B') return '智能问卷'
+      if (type === 'C') return '解决问题'
+      return ''
+    },
+    onReSelect() {
+      this.showIntentPicker = true
+    },
+    handleReSelect(payload) {
+      var self = this
+      this.showIntentPicker = false
+      uni.showLoading({ title: '保存中...', mask: true })
+      var data = { intentType: payload.intentType }
+      if (payload.intentType === 'C' && payload.problemDomainCode) {
+        data.problemDomainCode = payload.problemDomainCode
+      }
+      chooseUserIntent(data).then(function(res) {
+        uni.hideLoading()
+        if (res && (res.code === 0 || res.code === 200)) {
+          self.loadUserIntent()
+          uni.showToast({ title: '已更新你的选择', icon: 'none' })
+        } else {
+          uni.showToast({ title: res.message || '保存失败', icon: 'none' })
+        }
+      }).catch(function() {
+        uni.hideLoading()
+        uni.showToast({ title: '保存失败,请重试', icon: 'none' })
+      })
     }
   }
 }
@@ -386,4 +452,27 @@ export default {
   background: #667eea;
   color: #fff;
 }
+
+.intent-reselect-hint {
+  margin: 0 30rpx 30rpx;
+  padding: 24rpx 30rpx;
+  background: #fff;
+  border-radius: 20rpx;
+  display: flex;
+  align-items: center;
+  font-size: 26rpx;
+}
+.intent-reselect-label {
+  color: #999;
+  margin-right: 8rpx;
+}
+.intent-reselect-value {
+  flex: 1;
+  color: #F97316;
+  font-weight: bold;
+}
+.intent-reselect-link {
+  color: #5B9BD5;
+  text-decoration: underline;
+}
 </style>

+ 3 - 3
cfc-frontend/components/intent-picker.vue

@@ -6,12 +6,12 @@
         <text class="ip-sub">浠艾福为你定制专属家庭成长方案</text>
       </view>
 
-      <!-- A 直达 -->
+      <!-- A 随便看看 -->
       <view class="ip-card" @click="emitSelect('A')">
         <view class="ip-card-icon" style="background: rgba(249,115,22,0.12);"><text class="ip-card-emoji">🎯</text></view>
         <view class="ip-card-body">
-          <text class="ip-card-title">直达目标</text>
-          <text class="ip-card-desc">我有明确需求,直接选购测评或检测服务</text>
+          <text class="ip-card-title">随便看看</text>
+          <text class="ip-card-desc">先到处逛逛,了解浠艾福和各式服务</text>
         </view>
         <text class="ip-card-arrow">›</text>
       </view>

+ 1 - 1
cfc-frontend/components/journey-card.vue

@@ -117,7 +117,7 @@ export default {
       if (code && this.domainMap[code]) {
         return this.domainMap[code]
       }
-      if (this.intentType === 'A') return 'A类 · 直达目标'
+      if (this.intentType === 'A') return 'A类 · 随便看看'
       if (this.intentType === 'B') return 'B类 · 智能问卷'
       if (this.intentType === 'C') return 'C类 · 解决问题'
       return ''

+ 9 - 104
cfc-frontend/pages/index-home/index.vue

@@ -57,29 +57,12 @@
       tagline="知行合一 · 快乐成长"
       quote="千里之行,始于足下" />
 
-    <!-- 旅程状态卡 — 改版v1 需求驱动 -->
+    <!-- 旅程状态卡 — 改版v1 需求驱动(A类·随便看看 不展示旅程卡) -->
     <JourneyCard
-      v-if="userIntent"
+      v-if="userIntent && userIntent.intentType !== 'A'"
       :intent="userIntent"
       @action="handleJourneyAction" />
 
-    <!-- 今日任务卡片 — 每日任务统一入口 -->
-    <DailyTaskCard />
-
-    <!-- 定向科普内容 — F17 B类问卷结果定向展示 -->
-    <view v-if="targetedArticles.length > 0" class="section">
-      <view class="section-header">
-        <text class="section-title">📚 为你推荐</text>
-      </view>
-      <view class="targeted-list">
-        <view class="targeted-card" v-for="article in targetedArticles" :key="article.id" @click="goArticleDetail(article.id)">
-          <text class="targeted-category">{{ article.categoryName || article.category || '推荐' }}</text>
-          <text class="targeted-title">{{ article.title }}</text>
-          <text class="targeted-summary">{{ article.summary || '' }}</text>
-        </view>
-      </view>
-    </view>
-
     <!-- 能量沙盘 — Canvas 五行星图 -->
     <WuxingSandbox
       v-if="sandboxData"
@@ -362,8 +345,7 @@ import ArticleBookshelf from '../../components/ArticleBookshelf.vue'
 import FamilyChallengeCard from '../../components/FamilyChallengeCard.vue'
 import IntentPicker from '../../components/intent-picker.vue'
 import JourneyCard from '../../components/journey-card.vue'
-import DailyTaskCard from '../../components/daily-task-card.vue'
-import { acceptParentInvite, productList, getActivityList, getFeaturedArticles, getFamilyEnergySandbox, getVisibleFamilyMembers, getChildren, getChallengeList, switchToFamilyMember, getMyMembership, updateChallengeProgress, respondChallenge, getTodayTasks, completeTask as completeTaskApi, getTodayParentTasks, completeParentTask as completeParentTaskApi, getTaskHistory, getNotices, getUserIntent, chooseUserIntent, getContentByTags } from '../../utils/api.js'
+import { acceptParentInvite, productList, getActivityList, getFeaturedArticles, getFamilyEnergySandbox, getVisibleFamilyMembers, getChildren, getChallengeList, switchToFamilyMember, getMyMembership, updateChallengeProgress, respondChallenge, getTodayTasks, completeTask as completeTaskApi, getTodayParentTasks, completeParentTask as completeParentTaskApi, getTaskHistory, getNotices, getUserIntent, chooseUserIntent } from '../../utils/api.js'
 import nav from '../../utils/nav.js'
 import config from '@/config.js'
 
@@ -376,8 +358,7 @@ export default {
     ArticleBookshelf,
     FamilyChallengeCard,
     IntentPicker,
-    JourneyCard,
-    DailyTaskCard
+    JourneyCard
   },
   data() {
     // 从 storage 预取登录态/角色,确保首次渲染即正确(WeChat 渲染层/逻辑层分离架构下 onLoad 执行前已渲染)
@@ -443,8 +424,7 @@ export default {
       // 改版v1 用户意图/旅程
       userIntent: null,
       showIntentPicker: false,
-      intentPickerDismissed: false,
-      targetedArticles: []
+      intentPickerDismissed: false
     }
   },
   computed: {
@@ -1051,8 +1031,6 @@ export default {
         var intent = res && res.data
         if (intent) {
           self.userIntent = intent
-          // F17: 已有调研结果的用户加载定向科普内容
-          self.loadTargetedContent(intent)
         } else {
           // 无意图且未跳过,弹选择层
           if (!self.intentPickerDismissed) {
@@ -1064,32 +1042,6 @@ export default {
         // 静默:接口异常时不弹
       })
     },
-    // F17: 按调研 resultTags 定向加载科普内容
-    loadTargetedContent: function(intent) {
-      var self = this
-      var tags = []
-      var resultJson = intent && intent.survey_result_json
-      if (resultJson) {
-        try {
-          var parsed = typeof resultJson === 'string' ? JSON.parse(resultJson) : resultJson
-          if (parsed && parsed.resultTags && Array.isArray(parsed.resultTags)) {
-            tags = parsed.resultTags
-          }
-        } catch (e) {
-          tags = []
-        }
-      }
-      // B类无 tags 时用问题域 contentTags 或空数组
-      if (tags.length === 0 && intent && intent.intentType === 'C' && intent.problemDomainCode) {
-        tags = [intent.problemDomainCode]
-      }
-      getContentByTags({ tags: tags }).then(function(res) {
-        var list = res && res.data
-        self.targetedArticles = Array.isArray(list) ? list : []
-      }).catch(function() {
-        self.targetedArticles = []
-      })
-    },
     handleIntentSelect: function(payload) {
       var self = this
       self.showIntentPicker = false
@@ -1105,11 +1057,9 @@ export default {
           getUserIntent().then(function(r) {
             self.userIntent = r && r.data
           }).catch(function() {})
-          // 按类型跳转
-          if (payload.intentType === 'A') {
-            uni.navigateTo({ url: '/pages/assessment/purchase' })
-          } else if (payload.intentType === 'B') {
-            uni.navigateTo({ url: '/pages/problem/quick-survey' })
+          // 按类型跳转(A类·随便看看 不跳转,留在首页浏览)
+          if (payload.intentType === 'B') {
+            uni.navigateTo({ url: '/pages/problem/domain-list' })
           } else if (payload.intentType === 'C') {
             uni.navigateTo({
               url: '/pages/problem/flow-intro?code=' + (payload.problemDomainCode || '')
@@ -1133,12 +1083,7 @@ export default {
       if (action === 'flow-intro') {
         uni.navigateTo({ url: '/pages/problem/flow-intro?code=' + (code || '') })
       } else if (action === 'survey') {
-        // B类轻问卷 / C类专项调研
-        if (code) {
-          uni.navigateTo({ url: '/pages/problem/survey?code=' + code })
-        } else {
-          uni.navigateTo({ url: '/pages/problem/quick-survey' })
-        }
+        uni.navigateTo({ url: '/pages/problem/survey?code=' + (code || '') })
       } else if (action === 'package') {
         uni.navigateTo({ url: '/pages/problem/package-match?code=' + (code || '') })
       } else if (action === 'logistics') {
@@ -1388,46 +1333,6 @@ export default {
   font-size: 24rpx;
   color: #5B9BD5;
 }
-.targeted-list {
-  display: flex;
-  flex-direction: column;
-  gap: 16rpx;
-}
-.targeted-card {
-  background: #fff;
-  border-radius: 16rpx;
-  padding: 24rpx 28rpx;
-  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
-}
-.targeted-card:active {
-  opacity: 0.9;
-}
-.targeted-category {
-  display: inline-block;
-  font-size: 20rpx;
-  color: #F97316;
-  background: rgba(249, 115, 22, 0.1);
-  padding: 2rpx 14rpx;
-  border-radius: 16rpx;
-  margin-bottom: 10rpx;
-}
-.targeted-title {
-  display: block;
-  font-size: 28rpx;
-  font-weight: 600;
-  color: #333;
-  margin-bottom: 6rpx;
-}
-.targeted-summary {
-  display: block;
-  font-size: 24rpx;
-  color: #999;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  display: -webkit-box;
-  -webkit-box-orient: vertical;
-  -webkit-line-clamp: 2;
-}
 .empty-state {
   display: flex;
   justify-content: center;