Explorar o código

Merge branch 'cfclub' of http://git.iwintrue.com/liaoxg/cfc into cfclub

asus hai 1 mes
pai
achega
703cdefba0

+ 0 - 135
cfc-frontend/components/family-guard.vue

@@ -1,135 +0,0 @@
-<template>
-	<view v-if="visible" class="family-guard-mask" @click="close">
-		<view class="family-guard-panel" @click.stop>
-			<text class="family-guard-title">创建家庭后即可使用</text>
-			<text class="family-guard-desc">家庭是任务、测评、成长档案等功能的基础,创建后邀请家人加入</text>
-			<view class="family-guard-input-wrap">
-				<input class="family-guard-input" v-model="familyName" placeholder="请输入家庭名称(默认:我的家庭)" maxlength="20" />
-			</view>
-			<view class="family-guard-actions">
-				<button class="family-guard-btn family-guard-btn-primary" @click="doCreate" :loading="loading">去创建家庭</button>
-				<button class="family-guard-btn family-guard-btn-plain" @click="close">暂不创建</button>
-			</view>
-		</view>
-	</view>
-</template>
-
-<script>
-import { createFamily } from '../utils/api.js'
-
-export default {
-	name: 'FamilyGuard',
-	data() {
-		return {
-			visible: false,
-			loading: false,
-			familyName: ''
-		}
-	},
-	methods: {
-		show() {
-			this.familyName = ''
-			this.visible = true
-		},
-		close() {
-			this.visible = false
-		},
-		doCreate() {
-			var self = this
-			var name = (this.familyName || '').trim() || '我的家庭'
-			this.loading = true
-			createFamily(name).then(function(res) {
-				self.loading = false
-				if (res && res.code === 200 && res.data) {
-					// 同步 userInfo 缓存(familyId 由后端 JWT 属性注入,无需单独存储)
-					var userInfo = uni.getStorageSync('userInfo') || {}
-					userInfo.familyId = res.data
-					uni.setStorageSync('userInfo', userInfo)
-					// 同步 familyId 到 store(hasFamily getter 依赖,8ddc5b55 移除存储后此数据流断裂)
-					if (self.$store) {
-						self.$store.commit('setFamilyId', res.data)
-					}
-					self.visible = false
-					uni.showToast({ title: '家庭创建成功', icon: 'success' })
-					if (self.$listeners && self.$listeners.created) {
-						self.$emit('created', res.data)
-					}
-				} else {
-					uni.showToast({ title: (res && res.message) || '创建失败', icon: 'none' })
-				}
-			}).catch(function() {
-				self.loading = false
-				uni.showToast({ title: '网络异常', icon: 'none' })
-			})
-		}
-	}
-}
-</script>
-
-<style scoped>
-.family-guard-mask {
-	position: fixed;
-	top: 0;
-	left: 0;
-	right: 0;
-	bottom: 0;
-	background: rgba(0, 0, 0, 0.5);
-	z-index: 999;
-	display: flex;
-	align-items: center;
-	justify-content: center;
-}
-.family-guard-panel {
-	width: 600rpx;
-	background: #fff;
-	border-radius: 20rpx;
-	padding: 40rpx 36rpx;
-	display: flex;
-	flex-direction: column;
-}
-.family-guard-title {
-	font-size: 34rpx;
-	font-weight: bold;
-	color: #333;
-	text-align: center;
-}
-.family-guard-desc {
-	font-size: 26rpx;
-	color: #999;
-	margin-top: 16rpx;
-	line-height: 1.6;
-	text-align: center;
-}
-.family-guard-input-wrap {
-	margin-top: 30rpx;
-}
-.family-guard-input {
-	height: 80rpx;
-	background: #f5f7fa;
-	border-radius: 12rpx;
-	padding: 0 24rpx;
-	font-size: 28rpx;
-}
-.family-guard-actions {
-	margin-top: 36rpx;
-	display: flex;
-	flex-direction: column;
-}
-.family-guard-btn {
-	height: 84rpx;
-	border-radius: 42rpx;
-	font-size: 30rpx;
-	display: flex;
-	align-items: center;
-	justify-content: center;
-	margin-top: 16rpx;
-}
-.family-guard-btn-primary {
-	background: #F97316;
-	color: #fff;
-}
-.family-guard-btn-plain {
-	background: #f5f7fa;
-	color: #666;
-}
-</style>

+ 2 - 3
cfc-frontend/pages/diet/food-query.vue

@@ -68,7 +68,7 @@
 </template>
 
 <script>
-import { request } from '@/config/index.js'
+import config from '@/config.js'
 
 export default {
   data() {
@@ -146,8 +146,7 @@ export default {
       this.filterType = type
     },
     getApiUrl: function(path) {
-      var config = require('@/config/index.js')
-      return config.baseUrl + path
+      return config.api(path)
     }
   }
 }

+ 2 - 2
cfc-frontend/pages/diet/meal-config.vue

@@ -54,6 +54,7 @@
 </template>
 
 <script>
+import config from '@/config.js'
 import { getMealConfig, saveMealConfig } from '@/utils/api.js'
 
 export default {
@@ -166,8 +167,7 @@ export default {
       })
     },
     getApiUrl: function(path) {
-      var config = require('@/config/index.js')
-      return config.baseUrl + path
+      return config.api(path)
     }
   }
 }

+ 13 - 31
cfc-frontend/pages/profile-extra/family-members.vue

@@ -33,10 +33,7 @@
 
     <!-- ===== 分享邀请卡海报 ===== -->
     <SharePoster v-if="hasFamily" :show="showPoster" :referralCode="inviteCode" :qrCodeBase64="inviteQrCode" :nickname="userNickname" :userAvatar="userAvatar" @close="showPoster = false" />
-    <view v-else class="empty-tip">暂无家庭成员,请先创建或加入家庭</view>
-
-    <!-- ===== 无家庭引导弹窗 ===== -->
-    <family-guard ref="familyGuard" @created="onFamilyCreated" />
+    <view v-else class="empty-tip">暂无家庭成员,正在为您创建家庭...</view>
 
     <!-- ===== 成员详情弹窗 ===== -->
     <view class="modal-mask" v-if="showMemberDetailModal" @click="closeMemberDetail">
@@ -118,15 +115,14 @@ import {
 } from '../../utils/api.js'
 import store from '../../store/index.js'
 import SharePoster from '@/components/SharePoster.vue'
-import FamilyGuard from '../../components/family-guard.vue'
+import { ensureFamily } from '../../utils/api.js'
 
 export default {
-  components: { SharePoster, FamilyGuard },
+  components: { SharePoster },
   data() {
     return {
       userId: 0,
       familyId: 0,
-      pendingCreate: false,
       familyName: '',
       inviteCode: '',
       inviteQrCode: '',
@@ -156,9 +152,12 @@ export default {
     }
   },
   onLoad(options) {
-    // 支持 ?action=create 直达:无家庭用户引导创建
-    if (options && options.action === 'create') {
-      this.pendingCreate = true
+    // 无家庭时自动创建
+    if (!this.hasFamily) {
+      var self = this
+      ensureFamily().then(function() {
+        self.loadMembers()
+      })
     }
   },
   onShow() {
@@ -208,33 +207,16 @@ export default {
           this.inviteCode = data.inviteCode || ''
           this.creatorId = data.creatorId
           this.isAdmin = this.creatorId === this.userId
-          this.checkPendingCreate()
         } else if (res.code === 5001 || (res.message && res.message.indexOf('未加入家庭') >= 0)) {
-          // 无家庭:弹出创建家庭引导
-          this.showFamilyGuard()
+          // 无家庭:自动创建
+          ensureFamily().then(function() {
+            self.loadMembers()
+          })
         }
       } catch (e) {
         // 静默处理
       }
     },
-    showFamilyGuard() {
-      var self = this
-      setTimeout(function() {
-        if (self.$refs.familyGuard) {
-          self.$refs.familyGuard.show()
-        }
-      }, 300)
-    },
-    checkPendingCreate() {
-      if (this.pendingCreate) {
-        this.pendingCreate = false
-        this.showFamilyGuard()
-      }
-    },
-    onFamilyCreated() {
-      // 家庭创建成功后刷新成员列表
-      this.loadMembers()
-    },
     showMemberDetail(member) {
       this.detailMember = member
       this.showMemberDetailModal = true

+ 8 - 9
cfc-frontend/pages/profile/components/ProfileMenu.vue

@@ -96,20 +96,14 @@
         </view>
       </view>
     </view>
-
-    <family-guard ref="familyGuard" />
   </view>
 </template>
 
 <script>
-import { setPassword, verifyPassword, updateMemberVisibility, getVisibleFamilyMembers, vendorStatus } from '../../../utils/api.js'
-import FamilyGuard from '../../../components/family-guard.vue'
+import { setPassword, verifyPassword, updateMemberVisibility, getVisibleFamilyMembers, vendorStatus, ensureFamily } from '../../../utils/api.js'
 
 export default {
   name: 'ProfileMenu',
-  components: {
-    FamilyGuard
-  },
   props: {
     role: {
       type: String,
@@ -195,9 +189,14 @@ export default {
     },
     
     showInviteActionSheet() {
+      var self = this
       var ui = uni.getStorageSync('userInfo') || {}
       if (!ui.familyId) {
-        this.$refs.familyGuard.show()
+        ensureFamily().then(function(result) {
+          if (result && result.created) {
+            self.showInviteActionSheet()
+          }
+        })
         return
       }
       const userInfo = ui
@@ -206,7 +205,7 @@ export default {
       uni.showActionSheet({
         itemList: items,
         success: (res) => {
-          this.inviteGenerate(types[res.tapIndex], userInfo)
+          self.inviteGenerate(types[res.tapIndex], userInfo)
         }
       })
     },

+ 7 - 9
cfc-frontend/pages/wealth-sub/insurance-planning.vue

@@ -184,19 +184,13 @@
       <text class="empty-title">暂无保险规划数据</text>
       <text class="empty-desc">请先加入家庭后再使用此功能</text>
     </view>
-
-    <family-guard ref="familyGuard" @created="loadPlanning" />
   </scroll-view>
 </template>
 
 <script>
-import { getInsurancePlanning } from '../../utils/api'
-import FamilyGuard from '../../components/family-guard.vue'
+import { getInsurancePlanning, ensureFamily } from '../../utils/api'
 
 export default {
-  components: {
-    FamilyGuard
-  },
   data() {
     return {
       loading: true,
@@ -226,8 +220,12 @@ export default {
     async loadPlanning() {
       var ui = uni.getStorageSync('userInfo') || {}
       if (!ui.familyId) {
-        this.loading = false
-        this.$refs.familyGuard.show()
+        var result = await ensureFamily()
+        if (result && result.created) {
+          this.loadPlanning()
+        } else {
+          this.loading = false
+        }
         return
       }
       this.loading = true

+ 20 - 0
cfc-frontend/utils/api.js

@@ -283,6 +283,26 @@ export const createFamily = (name) => {
 	return request('/api/family/user/create-family', 'POST', { name })
 }
 
+// 确保家庭已存在:无家庭则自动创建(默认名)
+export const ensureFamily = () => {
+	var ui = uni.getStorageSync('userInfo') || {}
+	if (ui.familyId) return Promise.resolve({ alreadyExists: true, familyId: ui.familyId })
+	var name = (ui.nickname || '用户') + '的家庭'
+	return createFamily(name).then(function(res) {
+		if (res && res.code === 200 && res.data) {
+			ui.familyId = res.data
+			uni.setStorageSync('userInfo', ui)
+			try { getApp().$store.commit('setFamilyId', res.data) } catch (e) {}
+			uni.showToast({ title: '家庭创建成功', icon: 'success' })
+			return { created: true, familyId: res.data }
+		}
+		throw new Error((res && res.message) || '创建失败')
+	}).catch(function(err) {
+		uni.showToast({ title: err.message || '网络异常', icon: 'none' })
+		return { failed: true, error: err }
+	})
+}
+
 // 获取家庭所有成员(家长+孩子)
 export const getFamilyMembers = () => {
 	return request('/api/family/user/family-members', 'POST')

+ 1 - 1
cfc-web/.last_build_commit

@@ -1 +1 @@
-4146cb16d1242584b6ebd45da28da6ff651acefb
+eae95396ab46ef5f62ec03215c773532dd3dca99

+ 2 - 2
cfc-web/package-lock.json

@@ -1,12 +1,12 @@
 {
   "name": "cfc-web",
-  "version": "1.0.833",
+  "version": "1.0.837",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "cfc-web",
-      "version": "1.0.833",
+      "version": "1.0.837",
       "dependencies": {
         "@wangeditor/editor": "^5.1.23",
         "@wangeditor/editor-for-vue": "^1.0.2",

+ 1 - 1
cfc-web/package.json

@@ -1,6 +1,6 @@
 {
   "name": "cfc-web",
-  "version": "1.0.834",
+  "version": "1.0.838",
   "private": true,
   "scripts": {
     "dev": "vue-cli-service serve",

+ 31 - 0
cfc-web/public/CHANGELOG-v1.0.md

@@ -4,6 +4,37 @@
 
 ---
 
+## v1.0.838 (2026-08-07)
+
+### Bug 修复
+- 修复pages.json饮食分包位置错误 + 饮食模块config引用改为config.js
+
+
+## v1.0.837 (2026-08-07)
+
+### 新功能
+- 添加饮食模块 AI 接口
+
+
+## v1.0.836 (2026-08-07)
+
+### 重构
+- 移除family-guard弹窗,无家庭时自动创建;移除创建/加入家庭按钮
+
+
+## v1.0.835 (2026-08-07)
+
+### Bug 修复
+- 修复 FamilyEmptyState 误显示 - 28处 hasFamily 守卫改为数据优先判断
+
+### 其他
+-   store getter 仅兜底(store.familyId 恒空导致空态吞掉正常内容)
+- - App.vue 冷启动从接口恢复 familyId,store setFamilyId 持久化供恢复
+- - login.vue 登录/自动登录同步 familyId 到 store
+- - 修复 9 处批量修改导致的 computed 对象未闭合语法错误
+- 
+
+
 ## v1.0.834 (2026-08-07)
 
 ### Bug 修复

+ 32 - 1
cfc-web/public/CHANGELOG.md

@@ -1,6 +1,6 @@
 # 更新日志
 
-> 当前版本: v1.0.834
+> 当前版本: v1.0.838
 
 ## 历史版本
 
@@ -8,6 +8,37 @@
 
 ---
 
+## v1.0.838 (2026-08-07)
+
+### Bug 修复
+- 修复pages.json饮食分包位置错误 + 饮食模块config引用改为config.js
+
+
+## v1.0.837 (2026-08-07)
+
+### 新功能
+- 添加饮食模块 AI 接口
+
+
+## v1.0.836 (2026-08-07)
+
+### 重构
+- 移除family-guard弹窗,无家庭时自动创建;移除创建/加入家庭按钮
+
+
+## v1.0.835 (2026-08-07)
+
+### Bug 修复
+- 修复 FamilyEmptyState 误显示 - 28处 hasFamily 守卫改为数据优先判断
+
+### 其他
+-   store getter 仅兜底(store.familyId 恒空导致空态吞掉正常内容)
+- - App.vue 冷启动从接口恢复 familyId,store setFamilyId 持久化供恢复
+- - login.vue 登录/自动登录同步 familyId 到 store
+- - 修复 9 处批量修改导致的 computed 对象未闭合语法错误
+- 
+
+
 ## v1.0.834 (2026-08-07)
 
 ### Bug 修复