hookehuyr

feat(家庭): 实现家庭设置和切换功能

- 在Dashboard页面添加家庭设置按钮显示控制
- 实现编辑家庭信息的API调用和表单处理
- 添加获取家庭信息和切换当前家庭的API
- 更新MyFamily页面使用真实API数据
- 修复家庭成员管理和显示逻辑
1 /* 1 /*
2 * @Date: 2024-01-01 00:00:00 2 * @Date: 2024-01-01 00:00:00
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-09-02 20:09:52 4 + * @LastEditTime: 2025-09-03 11:25:11
5 * @FilePath: /lls_program/src/api/family.js 5 * @FilePath: /lls_program/src/api/family.js
6 * @Description: 家庭相关接口 6 * @Description: 家庭相关接口
7 */ 7 */
...@@ -12,7 +12,10 @@ const Api = { ...@@ -12,7 +12,10 @@ const Api = {
12 LIST_MY_FAMILIES: '/srv/?a=family&t=list_my_families', 12 LIST_MY_FAMILIES: '/srv/?a=family&t=list_my_families',
13 GET_DASHBOARD: '/srv/?a=family&t=get_dashboard', 13 GET_DASHBOARD: '/srv/?a=family&t=get_dashboard',
14 ADD_FAMILY: '/srv/?a=family&t=add', 14 ADD_FAMILY: '/srv/?a=family&t=add',
15 + EDIT_FAMILY: '/srv/?a=family&t=edit',
15 JOIN_FAMILY: '/srv/?a=family&t=join', 16 JOIN_FAMILY: '/srv/?a=family&t=join',
17 + GET_FAMILY_INFO: '/srv/?a=family&t=get_my_family',
18 + SWITCH_CURRENT_FAMILY: '/srv/?a=family&t=switch_current',
16 DEL_MEMBER: '/srv/?a=family&t=del_member', 19 DEL_MEMBER: '/srv/?a=family&t=del_member',
17 } 20 }
18 21
...@@ -44,6 +47,13 @@ export const searchFamilyByPassphraseAPI = (params) => fn(fetch.get(Api.SEARCH_B ...@@ -44,6 +47,13 @@ export const searchFamilyByPassphraseAPI = (params) => fn(fetch.get(Api.SEARCH_B
44 * @returns {string} response.data[].name - 家庭名称 47 * @returns {string} response.data[].name - 家庭名称
45 * @returns {string} response.data[].avatar_url - 家庭头像 48 * @returns {string} response.data[].avatar_url - 家庭头像
46 * @returns {boolean} response.data[].is_my - 是否是我创建的家庭 49 * @returns {boolean} response.data[].is_my - 是否是我创建的家庭
50 + * @returns {string} response.data[].created_by_nickname - 创建者昵称
51 + * @returns {string} response.data[].is_current_family - 是否是当前家庭
52 + * @returns {Array} response.data[].users - 家庭成员列表
53 + * @returns {string} response.data[].users[].user_id - 用户ID
54 + * @returns {string} response.data[].users[].role - 角色
55 + * @returns {string} response.data[].users[].avatar_url - 头像
56 + * @returns {string} response.data[].users[].nickname - 昵称
47 */ 57 */
48 export const getMyFamiliesAPI = () => fn(fetch.get(Api.LIST_MY_FAMILIES)); 58 export const getMyFamiliesAPI = () => fn(fetch.get(Api.LIST_MY_FAMILIES));
49 59
...@@ -96,6 +106,24 @@ export const getFamilyDashboardAPI = (params) => fn(fetch.get(Api.GET_DASHBOARD, ...@@ -96,6 +106,24 @@ export const getFamilyDashboardAPI = (params) => fn(fetch.get(Api.GET_DASHBOARD,
96 export const createFamilyAPI = (params) => fn(fetch.post(Api.ADD_FAMILY, params)); 106 export const createFamilyAPI = (params) => fn(fetch.post(Api.ADD_FAMILY, params));
97 107
98 /** 108 /**
109 + * @description: 编辑家庭
110 + * @param {Object} params - 请求参数
111 + * @param {number} params.id - 家庭ID
112 + * @param {string} params.name - 家庭名称
113 + * @param {string} params.county - 所在区县
114 + * @param {string} params.passphrase - 家训口令
115 + * @param {string} params.avatar_url - 家庭头像
116 + * @param {string} params.note - 家庭介绍
117 + * @returns {Promise} 返回编辑结果
118 + * @returns {Object} response - 响应对象
119 + * @returns {string} response.code - 响应状态码
120 + * @returns {string} response.msg - 响应消息
121 + * @returns {Object} response.data - 响应数据
122 + * @returns {number} response.data.family_id - 家庭ID
123 + */
124 +export const editFamilyAPI = (params) => fn(fetch.post(Api.EDIT_FAMILY, params));
125 +
126 +/**
99 * @description: 加入家庭 127 * @description: 加入家庭
100 * @param {Object} params - 请求参数 128 * @param {Object} params - 请求参数
101 * @param {number} params.family_id - 家庭ID 129 * @param {number} params.family_id - 家庭ID
...@@ -108,6 +136,35 @@ export const createFamilyAPI = (params) => fn(fetch.post(Api.ADD_FAMILY, params) ...@@ -108,6 +136,35 @@ export const createFamilyAPI = (params) => fn(fetch.post(Api.ADD_FAMILY, params)
108 export const joinFamilyAPI = (params) => fn(fetch.post(Api.JOIN_FAMILY, params)); 136 export const joinFamilyAPI = (params) => fn(fetch.post(Api.JOIN_FAMILY, params));
109 137
110 /** 138 /**
139 + * @description: 获取家庭信息
140 + * @returns {Promise} 返回家庭信息
141 + * @returns {Object} response - 响应对象
142 + * @returns {string} response.code - 响应状态码
143 + * @returns {string} response.msg - 响应消息
144 + * @returns {Object} response.data - 响应数据
145 + * @returns {number} response.data.id - 家庭ID
146 + * @returns {string} response.data.name - 家庭名称
147 + * @returns {string} response.data.note - 家庭描述
148 + * @returns {string} response.data.county - 所在区县
149 + * @returns {string} response.data.avatar_url - 家庭头像
150 + * @returns {string} response.data.passphrase - 家庭口令
151 + */
152 +export const getFamilyInfoAPI = (params) => fn(fetch.post(Api.GET_FAMILY_INFO, params));
153 +
154 +/**
155 + * @description: 切换当前家庭
156 + * @param {Object} params - 请求参数
157 + * @param {number} params.family_id - 家庭ID
158 + * @returns {Promise} 返回切换结果
159 + * @returns {Object} response - 响应对象
160 + * @returns {string} response.code - 响应状态码
161 + * @returns {string} response.msg - 响应消息
162 + * @returns {Object} response.data - 响应数据
163 + * @returns {number} response.data.family_id - 家庭ID
164 + */
165 +export const switchCurrentFamilyAPI = (params) => fn(fetch.post(Api.SWITCH_CURRENT_FAMILY, params));
166 +
167 +/**
111 * @description: 退出或移出家庭成员 168 * @description: 退出或移出家庭成员
112 * @param {Object} params - 请求参数 169 * @param {Object} params - 请求参数
113 * @param {number} params.family_id - 家庭ID 170 * @param {number} params.family_id - 家庭ID
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
4 <view class="relative h-48"> 4 <view class="relative h-48">
5 <image :src="familyCover" alt="Family background" class="w-full h-full object-cover" /> 5 <image :src="familyCover" alt="Family background" class="w-full h-full object-cover" />
6 <view class="absolute inset-0 bg-black bg-opacity-30 flex flex-col justify-end p-5"> 6 <view class="absolute inset-0 bg-black bg-opacity-30 flex flex-col justify-end p-5">
7 - <view class="absolute top-4 right-4 text-white flex items-center" @click="goToProfile"> 7 + <view v-if="familyOwner" class="absolute top-4 right-4 text-white flex items-center" @click="goToProfile">
8 <Setting size="24" /> 8 <Setting size="24" />
9 <text class="ml-2">家庭设置</text> 9 <text class="ml-2">家庭设置</text>
10 </view> 10 </view>
...@@ -211,6 +211,7 @@ const pendingPoints = ref([]) // 待收集的积分数据 ...@@ -211,6 +211,7 @@ const pendingPoints = ref([]) // 待收集的积分数据
211 const familyName = ref('') 211 const familyName = ref('')
212 const familySlogn = ref('') 212 const familySlogn = ref('')
213 const familyCover = ref('') 213 const familyCover = ref('')
214 +const familyOwner = ref(false);
214 215
215 // 使用媒体预览 composable 216 // 使用媒体预览 composable
216 const { 217 const {
...@@ -344,6 +345,7 @@ const initPageData = async () => { ...@@ -344,6 +345,7 @@ const initPageData = async () => {
344 familyName.value = data.family.name; 345 familyName.value = data.family.name;
345 familySlogn.value = data.family.note; 346 familySlogn.value = data.family.note;
346 familyCover.value = data.family.avatar_url || defaultFamilyCover; 347 familyCover.value = data.family.avatar_url || defaultFamilyCover;
348 + familyOwner.value = data.family.is_my;
347 // 获取今日我的步数 349 // 获取今日我的步数
348 todaySteps.value = data.my_today_step; 350 todaySteps.value = data.my_today_step;
349 // 获取家庭总步数 351 // 获取家庭总步数
......
1 <!-- 1 <!--
2 * @Date: 2025-08-27 17:44:53 2 * @Date: 2025-08-27 17:44:53
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-09-02 21:41:17 4 + * @LastEditTime: 2025-09-03 11:23:08
5 * @FilePath: /lls_program/src/pages/EditFamily/index.vue 5 * @FilePath: /lls_program/src/pages/EditFamily/index.vue
6 * @Description: 文件描述 6 * @Description: 文件描述
7 --> 7 -->
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
23 class="w-full text-gray-600 focus:outline-none" 23 class="w-full text-gray-600 focus:outline-none"
24 placeholder="请输入家庭名称(最多10个字)" 24 placeholder="请输入家庭名称(最多10个字)"
25 @blur="validateFamilyName" 25 @blur="validateFamilyName"
26 - maxlength="10"
27 /> 26 />
28 <view v-if="familyNameError" class="text-red-500 text-sm mt-2">{{ familyNameError }}</view> 27 <view v-if="familyNameError" class="text-red-500 text-sm mt-2">{{ familyNameError }}</view>
29 </view> 28 </view>
...@@ -38,7 +37,6 @@ ...@@ -38,7 +37,6 @@
38 placeholder="请输入您家庭的特色、成员特点等家庭标签(最多100个字)" 37 placeholder="请输入您家庭的特色、成员特点等家庭标签(最多100个字)"
39 :rows="2" 38 :rows="2"
40 @blur="validateFamilyIntro" 39 @blur="validateFamilyIntro"
41 - maxlength="100"
42 /> 40 />
43 <view v-if="familyIntroError" class="text-red-500 text-sm mt-2">{{ familyIntroError }}</view> 41 <view v-if="familyIntroError" class="text-red-500 text-sm mt-2">{{ familyIntroError }}</view>
44 </view> 42 </view>
...@@ -175,6 +173,8 @@ import { Edit, Tips, Photograph, Right } from '@nutui/icons-vue-taro'; ...@@ -175,6 +173,8 @@ import { Edit, Tips, Photograph, Right } from '@nutui/icons-vue-taro';
175 import BASE_URL from '@/utils/config'; 173 import BASE_URL from '@/utils/config';
176 // 174 //
177 const defaultFamilyCoverSvg = 'https://cdn.ipadbiz.cn/lls_prog/images/default-family-cover.png'; 175 const defaultFamilyCoverSvg = 'https://cdn.ipadbiz.cn/lls_prog/images/default-family-cover.png';
176 +// 获取接口信息
177 +import { editFamilyAPI, getFamilyInfoAPI } from '@/api/family';
178 178
179 const familyName = ref(''); 179 const familyName = ref('');
180 const familyIntro = ref(''); 180 const familyIntro = ref('');
...@@ -217,8 +217,18 @@ const previewVisible = ref(false); ...@@ -217,8 +217,18 @@ const previewVisible = ref(false);
217 const previewImages = ref([]); 217 const previewImages = ref([]);
218 const previewIndex = ref(0); 218 const previewIndex = ref(0);
219 219
220 -onMounted(() => { 220 +onMounted(async () => {
221 Taro.setNavigationBarTitle({ title: '编辑家庭' }); 221 Taro.setNavigationBarTitle({ title: '编辑家庭' });
222 + const { code, data } = await getFamilyInfoAPI();
223 + if (code) {
224 + familyName.value = data.name;
225 + familyIntro.value = data.note;
226 + districtValue.value = [data.county];
227 + selectedDistrict.value = data.county;
228 + selectedDistrictText.value = districtColumns.value.find(item => item.value === selectedDistrict.value).text;
229 + familyMotto.value = data.passphrase.split(',');
230 + familyAvatar.value = data.avatar_url;
231 + }
222 // Mock data for current family information 232 // Mock data for current family information
223 familyName.value = '幸福一家'; 233 familyName.value = '幸福一家';
224 familyIntro.value = '我们是相亲相爱的一家人'; 234 familyIntro.value = '我们是相亲相爱的一家人';
...@@ -443,16 +453,25 @@ const validateForm = () => { ...@@ -443,16 +453,25 @@ const validateForm = () => {
443 /** 453 /**
444 * 保存家庭信息 454 * 保存家庭信息
445 */ 455 */
446 -const handleSaveFamily = () => { 456 +const handleSaveFamily = async () => {
447 if (!validateForm()) { 457 if (!validateForm()) {
448 return; 458 return;
449 } 459 }
450 460
451 - // 在实际应用中,这里会调用API保存家庭信息 461 + // 调用API保存家庭信息
452 - showToast('家庭信息保存成功', 'success'); 462 + const { code } = await editFamilyAPI({
463 + name: familyName.value,
464 + note: familyIntro.value,
465 + county: selectedDistrict.value,
466 + passphrase: familyMotto.value.join(''),
467 + avatar_url: familyAvatar.value,
468 + });
469 + if (code) {
470 + showToast('家庭信息保存成功', 'success');
453 471
454 - setTimeout(() => { 472 + setTimeout(() => {
455 - Taro.navigateBack(); 473 + Taro.navigateBack();
456 - }, 1500); 474 + }, 1500);
475 + }
457 }; 476 };
458 </script> 477 </script>
......
1 <!-- 1 <!--
2 * @Date: 2022-09-19 14:11:06 2 * @Date: 2022-09-19 14:11:06
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-09-03 00:11:18 4 + * @LastEditTime: 2025-09-03 11:34:55
5 * @FilePath: /lls_program/src/pages/MyFamily/index.vue 5 * @FilePath: /lls_program/src/pages/MyFamily/index.vue
6 * @Description: 我的家庭页面 - 展示用户加入的家庭列表 6 * @Description: 我的家庭页面 - 展示用户加入的家庭列表
7 --> 7 -->
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
18 <view class="relative"> 18 <view class="relative">
19 <!-- 当前家庭标记 --> 19 <!-- 当前家庭标记 -->
20 <view 20 <view
21 - v-if="family.is_in" 21 + v-if="family.is_current_family"
22 class="absolute top-2 right-2 bg-blue-500 text-white text-xs px-2 py-1 rounded-sm z-10" 22 class="absolute top-2 right-2 bg-blue-500 text-white text-xs px-2 py-1 rounded-sm z-10"
23 > 23 >
24 当前家庭 24 当前家庭
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
42 <!-- 家庭名称和大家长信息覆盖层 --> 42 <!-- 家庭名称和大家长信息覆盖层 -->
43 <view class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/60 to-transparent p-4"> 43 <view class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/60 to-transparent p-4">
44 <view class="text-white font-bold text-lg mb-1">{{ family.name }}</view> 44 <view class="text-white font-bold text-lg mb-1">{{ family.name }}</view>
45 - <view class="text-white/90 text-sm">大家长:{{ family.ownerName }}</view> 45 + <view class="text-white/90 text-sm">大家长:{{ family.created_by_nickname }}</view>
46 </view> 46 </view>
47 </view> 47 </view>
48 48
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
54 <!-- 成员头像叠加效果 --> 54 <!-- 成员头像叠加效果 -->
55 <view class="avatar-overlap"> 55 <view class="avatar-overlap">
56 <image 56 <image
57 - v-for="(member, index) in family?.members?.slice(0, 4) || []" 57 + v-for="(member, index) in family?.users?.slice(0, 4) || []"
58 :key="member.id" 58 :key="member.id"
59 :src="member.avatar" 59 :src="member.avatar"
60 class="avatar-item w-8 h-8 rounded-full border-2 border-white object-cover" 60 class="avatar-item w-8 h-8 rounded-full border-2 border-white object-cover"
...@@ -62,16 +62,16 @@ ...@@ -62,16 +62,16 @@
62 /> 62 />
63 <!-- 更多成员数量显示 --> 63 <!-- 更多成员数量显示 -->
64 <view 64 <view
65 - v-if="family?.members?.length > 4" 65 + v-if="family?.users?.length > 4"
66 class="w-8 h-8 rounded-full bg-gray-300 border-2 border-white flex items-center justify-center text-xs text-gray-600" 66 class="w-8 h-8 rounded-full bg-gray-300 border-2 border-white flex items-center justify-center text-xs text-gray-600"
67 :style="{ zIndex: 6 }" 67 :style="{ zIndex: 6 }"
68 > 68 >
69 - +{{ family?.members?.length - 4 }} 69 + +{{ family?.users?.length - 4 }}
70 </view> 70 </view>
71 </view> 71 </view>
72 <!-- 总成员数 --> 72 <!-- 总成员数 -->
73 <view class="ml-3 text-sm text-gray-600"> 73 <view class="ml-3 text-sm text-gray-600">
74 - {{ family?.members?.length || 0 }} 位家庭成员 74 + {{ family?.users?.length || 0 }} 位家庭成员
75 </view> 75 </view>
76 </view> 76 </view>
77 </view> 77 </view>
...@@ -86,7 +86,7 @@ ...@@ -86,7 +86,7 @@
86 查看成员 86 查看成员
87 </view> 87 </view>
88 <view 88 <view
89 - v-if="!family.is_in" 89 + v-if="!family.is_current_family"
90 @tap="switchToFamily(family.id)" 90 @tap="switchToFamily(family.id)"
91 class="px-4 py-2 bg-blue-500 text-white text-sm rounded-lg" 91 class="px-4 py-2 bg-blue-500 text-white text-sm rounded-lg"
92 > 92 >
...@@ -144,7 +144,7 @@ ...@@ -144,7 +144,7 @@
144 <view class="px-4 py-3"> 144 <view class="px-4 py-3">
145 <view class="space-y-3"> 145 <view class="space-y-3">
146 <view 146 <view
147 - v-for="member in mockMembers" 147 + v-for="member in currentMembers"
148 :key="member.id" 148 :key="member.id"
149 class="bg-gray-50 rounded-lg p-3" 149 class="bg-gray-50 rounded-lg p-3"
150 @tap="toggleMemberSelection(member.id)" 150 @tap="toggleMemberSelection(member.id)"
...@@ -178,7 +178,7 @@ ...@@ -178,7 +178,7 @@
178 178
179 <!-- 右侧:创建者标识 --> 179 <!-- 右侧:创建者标识 -->
180 <view 180 <view
181 - v-if="member.is_owner" 181 + v-if="member.is_my"
182 class="ml-3 px-2 py-1 bg-yellow-100 text-yellow-600 text-xs rounded flex-shrink-0" 182 class="ml-3 px-2 py-1 bg-yellow-100 text-yellow-600 text-xs rounded flex-shrink-0"
183 > 183 >
184 创建者 184 创建者
...@@ -220,7 +220,8 @@ import { ref, onMounted, computed } from 'vue'; ...@@ -220,7 +220,8 @@ import { ref, onMounted, computed } from 'vue';
220 import Taro, { useDidShow } from '@tarojs/taro'; 220 import Taro, { useDidShow } from '@tarojs/taro';
221 import { Home } from '@nutui/icons-vue-taro'; 221 import { Home } from '@nutui/icons-vue-taro';
222 import './index.less'; 222 import './index.less';
223 -import { getMyFamiliesAPI } from '@/api/family'; 223 +// 获取接口信息
224 +import { getMyFamiliesAPI, switchCurrentFamilyAPI } from '@/api/family';
224 // 225 //
225 const defaultFamilyCoverSvg = 'https://cdn.ipadbiz.cn/lls_prog/images/default-family-cover.png'; 226 const defaultFamilyCoverSvg = 'https://cdn.ipadbiz.cn/lls_prog/images/default-family-cover.png';
226 // 获取接口数据 227 // 获取接口数据
...@@ -232,7 +233,7 @@ const familyList = ref([]); ...@@ -232,7 +233,7 @@ const familyList = ref([]);
232 const showMemberPopup = ref(false); 233 const showMemberPopup = ref(false);
233 const currentFamily = ref(null); 234 const currentFamily = ref(null);
234 const selectedMembers = ref([]); 235 const selectedMembers = ref([]);
235 -const mockMembers = ref([]); 236 +const currentMembers = ref([]);
236 237
237 /** 238 /**
238 * 初始化页面数据 239 * 初始化页面数据
...@@ -248,11 +249,11 @@ const initPageData = async () => { ...@@ -248,11 +249,11 @@ const initPageData = async () => {
248 { 249 {
249 id: 1, 250 id: 1,
250 name: '幸福之家', 251 name: '幸福之家',
251 - ownerName: '张明明', 252 + created_by_nickname: '张明明',
252 avatar_url: 'https://images.unsplash.com/photo-1511895426328-dc8714191300?w=400&h=200&fit=crop', 253 avatar_url: 'https://images.unsplash.com/photo-1511895426328-dc8714191300?w=400&h=200&fit=crop',
253 - is_in: true, 254 + is_current_family: true,
254 is_my: true, // 当前用户是家长,可以管理成员 255 is_my: true, // 当前用户是家长,可以管理成员
255 - members: [ 256 + users: [
256 { id: 1, avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face' }, 257 { id: 1, avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face' },
257 { id: 2, avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face' }, 258 { id: 2, avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face' },
258 { id: 3, avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face' } 259 { id: 3, avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face' }
...@@ -261,11 +262,11 @@ const initPageData = async () => { ...@@ -261,11 +262,11 @@ const initPageData = async () => {
261 { 262 {
262 id: 2, 263 id: 2,
263 name: '欢乐之家', 264 name: '欢乐之家',
264 - ownerName: '李志强', 265 + created_by_nickname: '李志强',
265 avatar_url: 'https://images.unsplash.com/photo-1502086223501-7ea6ecd79368?w=400&h=200&fit=crop', 266 avatar_url: 'https://images.unsplash.com/photo-1502086223501-7ea6ecd79368?w=400&h=200&fit=crop',
266 - is_in: false, 267 + is_current_family: false,
267 is_my: false, // 当前用户不是家长 268 is_my: false, // 当前用户不是家长
268 - members: [ 269 + users: [
269 { id: 4, avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop&crop=face' }, 270 { id: 4, avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop&crop=face' },
270 { id: 5, avatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=100&h=100&fit=crop&crop=face' } 271 { id: 5, avatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=100&h=100&fit=crop&crop=face' }
271 ] 272 ]
...@@ -273,11 +274,11 @@ const initPageData = async () => { ...@@ -273,11 +274,11 @@ const initPageData = async () => {
273 { 274 {
274 id: 3, 275 id: 3,
275 name: '快乐之家', 276 name: '快乐之家',
276 - ownerName: '王芳', 277 + created_by_nickname: '王芳',
277 avatar_url: 'https://images.unsplash.com/photo-1502086223501-7ea6ecd79368?w=400&h=200&fit=crop', 278 avatar_url: 'https://images.unsplash.com/photo-1502086223501-7ea6ecd79368?w=400&h=200&fit=crop',
278 - is_in: false, 279 + is_current_family: false,
279 is_my: true, // 当前用户是家长,但不在此家庭 280 is_my: true, // 当前用户是家长,但不在此家庭
280 - members: [ 281 + users: [
281 { id: 6, avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop&crop=face' }, 282 { id: 6, avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop&crop=face' },
282 { id: 7, avatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=100&h=100&fit=crop&crop=face' } 283 { id: 7, avatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=100&h=100&fit=crop&crop=face' }
283 ] 284 ]
...@@ -294,27 +295,29 @@ const isShowBtn = computed(() => { ...@@ -294,27 +295,29 @@ const isShowBtn = computed(() => {
294 * 切换到指定家庭 295 * 切换到指定家庭
295 * @param {number} familyId - 家庭ID 296 * @param {number} familyId - 家庭ID
296 */ 297 */
297 -const switchToFamily = (familyId) => { 298 +const switchToFamily = async (familyId) => {
298 const family = familyList.value.find(f => f.id === familyId); 299 const family = familyList.value.find(f => f.id === familyId);
299 if (!family) return; 300 if (!family) return;
300 301
301 Taro.showModal({ 302 Taro.showModal({
302 title: '切换家庭', 303 title: '切换家庭',
303 content: `确定要切换到「${family.name}」吗?`, 304 content: `确定要切换到「${family.name}」吗?`,
304 - success: (res) => { 305 + success: async (res) => {
305 if (res.confirm) { 306 if (res.confirm) {
306 - // 切换家庭逻辑 - 先清除所有当前标记,再设置新的当前家庭 307 + const { code } = await switchCurrentFamilyAPI(familyId);
307 - familyList.value = familyList.value.map(f => ({ 308 + if (code) {
308 - ...f, 309 + // 切换家庭逻辑 - 先清除所有当前标记,再设置新的当前家庭
309 - is_in: f.id === familyId 310 + familyList.value = familyList.value.map(f => ({
310 - })); 311 + ...f,
311 - 312 + is_current_family: f.id === familyId
312 - console.log('切换家庭后的列表:', familyList.value); 313 + }));
313 - 314 +
314 - Taro.showToast({ 315 + console.log('切换家庭后的列表:', familyList.value);
315 - title: '切换成功', 316 + Taro.showToast({
316 - icon: 'success' 317 + title: '切换成功',
317 - }); 318 + icon: 'success'
319 + });
320 + }
318 } 321 }
319 } 322 }
320 }); 323 });
...@@ -345,7 +348,7 @@ const exitFamily = (familyId) => { ...@@ -345,7 +348,7 @@ const exitFamily = (familyId) => {
345 // 退出家庭逻辑 348 // 退出家庭逻辑
346 const exitingFamily = familyList.value.find(f => f.id === familyId); 349 const exitingFamily = familyList.value.find(f => f.id === familyId);
347 350
348 - if (exitingFamily?.is_in) { 351 + if (exitingFamily?.is_current_family) {
349 // 如果退出的是当前家庭,需要返回我的页面 352 // 如果退出的是当前家庭,需要返回我的页面
350 familyList.value = familyList.value.filter(f => f.id !== familyId); 353 familyList.value = familyList.value.filter(f => f.id !== familyId);
351 354
...@@ -390,41 +393,41 @@ const joinNewFamily = () => { ...@@ -390,41 +393,41 @@ const joinNewFamily = () => {
390 const showMemberManagement = (family) => { 393 const showMemberManagement = (family) => {
391 currentFamily.value = family; 394 currentFamily.value = family;
392 // 生成模拟成员数据 395 // 生成模拟成员数据
393 - mockMembers.value = [ 396 + currentMembers.value = [
394 { 397 {
395 id: 1, 398 id: 1,
396 nickname: '张明明', 399 nickname: '张明明',
397 avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face', 400 avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face',
398 role: '父亲', 401 role: '父亲',
399 - is_owner: true 402 + is_my: true
400 }, 403 },
401 { 404 {
402 id: 2, 405 id: 2,
403 nickname: '李美丽', 406 nickname: '李美丽',
404 avatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=100&h=100&fit=crop&crop=face', 407 avatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=100&h=100&fit=crop&crop=face',
405 role: '母亲', 408 role: '母亲',
406 - is_owner: false 409 + is_my: false
407 }, 410 },
408 { 411 {
409 id: 3, 412 id: 3,
410 nickname: '张小明', 413 nickname: '张小明',
411 avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop&crop=face', 414 avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop&crop=face',
412 role: '儿子', 415 role: '儿子',
413 - is_owner: false 416 + is_my: false
414 }, 417 },
415 { 418 {
416 id: 4, 419 id: 4,
417 nickname: '张小花', 420 nickname: '张小花',
418 avatar: 'https://images.unsplash.com/photo-1494790108755-2616b612b786?w=100&h=100&fit=crop&crop=face', 421 avatar: 'https://images.unsplash.com/photo-1494790108755-2616b612b786?w=100&h=100&fit=crop&crop=face',
419 role: '女儿', 422 role: '女儿',
420 - is_owner: false 423 + is_my: false
421 }, 424 },
422 { 425 {
423 id: 5, 426 id: 5,
424 nickname: '王奶奶', 427 nickname: '王奶奶',
425 avatar: 'https://images.unsplash.com/photo-1551836022-d5d88e9218df?w=100&h=100&fit=crop&crop=face', 428 avatar: 'https://images.unsplash.com/photo-1551836022-d5d88e9218df?w=100&h=100&fit=crop&crop=face',
426 role: '奶奶', 429 role: '奶奶',
427 - is_owner: false 430 + is_my: false
428 } 431 }
429 ]; 432 ];
430 selectedMembers.value = []; 433 selectedMembers.value = [];
...@@ -438,7 +441,7 @@ const closeMemberPopup = () => { ...@@ -438,7 +441,7 @@ const closeMemberPopup = () => {
438 showMemberPopup.value = false; 441 showMemberPopup.value = false;
439 currentFamily.value = null; 442 currentFamily.value = null;
440 selectedMembers.value = []; 443 selectedMembers.value = [];
441 - mockMembers.value = []; 444 + currentMembers.value = [];
442 }; 445 };
443 446
444 /** 447 /**
...@@ -446,10 +449,10 @@ const closeMemberPopup = () => { ...@@ -446,10 +449,10 @@ const closeMemberPopup = () => {
446 * @param {number} memberId - 成员ID 449 * @param {number} memberId - 成员ID
447 */ 450 */
448 const toggleMemberSelection = (memberId) => { 451 const toggleMemberSelection = (memberId) => {
449 - const member = mockMembers.value.find(m => m.id === memberId); 452 + const member = currentMembers.value.find(m => m.id === memberId);
450 453
451 // 创建者不能被选择移除 454 // 创建者不能被选择移除
452 - if (member?.is_owner) { 455 + if (member?.is_my) {
453 Taro.showToast({ 456 Taro.showToast({
454 title: '创建者不能被移除', 457 title: '创建者不能被移除',
455 icon: 'none' 458 icon: 'none'
...@@ -477,7 +480,7 @@ const removeSelectedMembers = () => { ...@@ -477,7 +480,7 @@ const removeSelectedMembers = () => {
477 return; 480 return;
478 } 481 }
479 482
480 - const selectedNames = mockMembers.value 483 + const selectedNames = currentMembers.value
481 .filter(m => selectedMembers.value.includes(m.id)) 484 .filter(m => selectedMembers.value.includes(m.id))
482 .map(m => m.nickname) 485 .map(m => m.nickname)
483 .join('、'); 486 .join('、');
...@@ -488,7 +491,7 @@ const removeSelectedMembers = () => { ...@@ -488,7 +491,7 @@ const removeSelectedMembers = () => {
488 success: (res) => { 491 success: (res) => {
489 if (res.confirm) { 492 if (res.confirm) {
490 // 从模拟数据中移除选中的成员 493 // 从模拟数据中移除选中的成员
491 - mockMembers.value = mockMembers.value.filter(m => !selectedMembers.value.includes(m.id)); 494 + currentMembers.value = currentMembers.value.filter(m => !selectedMembers.value.includes(m.id));
492 selectedMembers.value = []; 495 selectedMembers.value = [];
493 496
494 Taro.showToast({ 497 Taro.showToast({
......