hookehuyr

feat: 统一图片显示模式为aspectFill并添加隐私弹窗

将多处图片显示模式从aspectFit改为aspectFill以更好展示头像
在Welcome页面添加个人信息收集说明和年龄限制提示弹窗
更新components.d.ts以支持新增的NutDialog等组件
...@@ -14,11 +14,14 @@ declare module 'vue' { ...@@ -14,11 +14,14 @@ declare module 'vue' {
14 NavBar: typeof import('./src/components/navBar.vue')['default'] 14 NavBar: typeof import('./src/components/navBar.vue')['default']
15 NutActionSheet: typeof import('@nutui/nutui-taro')['ActionSheet'] 15 NutActionSheet: typeof import('@nutui/nutui-taro')['ActionSheet']
16 NutButton: typeof import('@nutui/nutui-taro')['Button'] 16 NutButton: typeof import('@nutui/nutui-taro')['Button']
17 + NutCol: typeof import('@nutui/nutui-taro')['Col']
17 NutDatePicker: typeof import('@nutui/nutui-taro')['DatePicker'] 18 NutDatePicker: typeof import('@nutui/nutui-taro')['DatePicker']
19 + NutDialog: typeof import('@nutui/nutui-taro')['Dialog']
18 NutImagePreview: typeof import('@nutui/nutui-taro')['ImagePreview'] 20 NutImagePreview: typeof import('@nutui/nutui-taro')['ImagePreview']
19 NutInput: typeof import('@nutui/nutui-taro')['Input'] 21 NutInput: typeof import('@nutui/nutui-taro')['Input']
20 NutPicker: typeof import('@nutui/nutui-taro')['Picker'] 22 NutPicker: typeof import('@nutui/nutui-taro')['Picker']
21 NutPopup: typeof import('@nutui/nutui-taro')['Popup'] 23 NutPopup: typeof import('@nutui/nutui-taro')['Popup']
24 + NutRow: typeof import('@nutui/nutui-taro')['Row']
22 NutSearchbar: typeof import('@nutui/nutui-taro')['Searchbar'] 25 NutSearchbar: typeof import('@nutui/nutui-taro')['Searchbar']
23 NutToast: typeof import('@nutui/nutui-taro')['Toast'] 26 NutToast: typeof import('@nutui/nutui-taro')['Toast']
24 Picker: typeof import('./src/components/time-picker-data/picker.vue')['default'] 27 Picker: typeof import('./src/components/time-picker-data/picker.vue')['default']
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
3 <!-- Avatar --> 3 <!-- Avatar -->
4 <view class="flex flex-col items-center py-8" @click="changeAvatar"> 4 <view class="flex flex-col items-center py-8" @click="changeAvatar">
5 <view class="w-24 h-24 rounded-full bg-gray-100 flex items-center justify-center mb-2 overflow-hidden"> 5 <view class="w-24 h-24 rounded-full bg-gray-100 flex items-center justify-center mb-2 overflow-hidden">
6 - <image :src="formData.avatar_url || defaultAvatar" class="w-full h-full" mode="aspectFit" /> 6 + <image :src="formData.avatar_url || defaultAvatar" class="w-full h-full" mode="aspectFill" />
7 </view> 7 </view>
8 <text class="text-gray-500 text-sm">上传头像</text> 8 <text class="text-gray-500 text-sm">上传头像</text>
9 </view> 9 </view>
......
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
85 </view> 85 </view>
86 <view class="grid grid-cols-4 gap-2"> 86 <view class="grid grid-cols-4 gap-2">
87 <view v-for="member in familyMembers" :key="member.user_id" class="flex flex-col items-center"> 87 <view v-for="member in familyMembers" :key="member.user_id" class="flex flex-col items-center">
88 - <image :src="member.avatar_url || defaultAvatar" mode="aspectFit" :alt="member.role" class="w-16 h-16 rounded-full mb-1" /> 88 + <image :src="member.avatar_url || defaultAvatar" mode="aspectFill" :alt="member.role" class="w-16 h-16 rounded-full mb-1" />
89 <span class="text-sm text-gray-700"> 89 <span class="text-sm text-gray-700">
90 {{ member?.today_step?.toLocaleString() }}步 90 {{ member?.today_step?.toLocaleString() }}步
91 </span> 91 </span>
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
3 <!-- Avatar --> 3 <!-- Avatar -->
4 <view class="flex flex-col items-center py-8" @click="changeAvatar"> 4 <view class="flex flex-col items-center py-8" @click="changeAvatar">
5 <view class="w-24 h-24 rounded-full bg-gray-100 flex items-center justify-center mb-2 overflow-hidden"> 5 <view class="w-24 h-24 rounded-full bg-gray-100 flex items-center justify-center mb-2 overflow-hidden">
6 - <image :src="formData.avatar_url || defaultAvatar" class="w-full h-full" mode="aspectFit" /> 6 + <image :src="formData.avatar_url || defaultAvatar" class="w-full h-full" mode="aspectFill" />
7 </view> 7 </view>
8 <text class="text-gray-500 text-sm">上传头像</text> 8 <text class="text-gray-500 text-sm">上传头像</text>
9 </view> 9 </view>
......
1 <!-- 1 <!--
2 * @Date: 2025-09-01 13:07:52 2 * @Date: 2025-09-01 13:07:52
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-09-02 13:13:17 4 + * @LastEditTime: 2025-09-06 12:51:49
5 * @FilePath: /lls_program/src/pages/FamilyRank/index.vue 5 * @FilePath: /lls_program/src/pages/FamilyRank/index.vue
6 * @Description: 文件描述 6 * @Description: 文件描述
7 --> 7 -->
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
40 <view class="rank-item second"> 40 <view class="rank-item second">
41 <view class="crown crown-silver">👑</view> 41 <view class="crown crown-silver">👑</view>
42 <view class="avatar"> 42 <view class="avatar">
43 - <image :src="topRanks[1]?.avatar" class="avatar-img" /> 43 + <image :src="topRanks[1]?.avatar" class="avatar-img" mode="aspectFill" />
44 </view> 44 </view>
45 <view class="family-name">{{ topRanks[1]?.familyName }}</view> 45 <view class="family-name">{{ topRanks[1]?.familyName }}</view>
46 <view class="leader-name">大家长:{{ topRanks[1]?.leaderName }}</view> 46 <view class="leader-name">大家长:{{ topRanks[1]?.leaderName }}</view>
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
54 <view class="rank-item first"> 54 <view class="rank-item first">
55 <view class="crown crown-gold">👑</view> 55 <view class="crown crown-gold">👑</view>
56 <view class="avatar"> 56 <view class="avatar">
57 - <image :src="topRanks[0]?.avatar" class="avatar-img" /> 57 + <image :src="topRanks[0]?.avatar" class="avatar-img" mode="aspectFill" />
58 </view> 58 </view>
59 <view class="family-name">{{ topRanks[0]?.familyName }}</view> 59 <view class="family-name">{{ topRanks[0]?.familyName }}</view>
60 <view class="leader-name">大家长:{{ topRanks[0]?.leaderName }}</view> 60 <view class="leader-name">大家长:{{ topRanks[0]?.leaderName }}</view>
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
68 <view class="rank-item third"> 68 <view class="rank-item third">
69 <view class="crown crown-bronze">👑</view> 69 <view class="crown crown-bronze">👑</view>
70 <view class="avatar"> 70 <view class="avatar">
71 - <image :src="topRanks[2]?.avatar" class="avatar-img" /> 71 + <image :src="topRanks[2]?.avatar" class="avatar-img" mode="aspectFill" />
72 </view> 72 </view>
73 <view class="family-name">{{ topRanks[2]?.familyName }}</view> 73 <view class="family-name">{{ topRanks[2]?.familyName }}</view>
74 <view class="leader-name">大家长:{{ topRanks[2]?.leaderName }}</view> 74 <view class="leader-name">大家长:{{ topRanks[2]?.leaderName }}</view>
...@@ -109,7 +109,7 @@ ...@@ -109,7 +109,7 @@
109 <view class="my-rank-left"> 109 <view class="my-rank-left">
110 <view class="my-rank-number">{{ myRank.rank }}+</view> 110 <view class="my-rank-number">{{ myRank.rank }}+</view>
111 <view class="my-avatar"> 111 <view class="my-avatar">
112 - <image :src="myRank.avatar" class="my-avatar-img" /> 112 + <image :src="myRank.avatar" class="my-avatar-img" mode="aspectFill" />
113 </view> 113 </view>
114 <view class="my-family-info"> 114 <view class="my-family-info">
115 <view class="my-family-name">{{ myRank.familyName }}</view> 115 <view class="my-family-name">{{ myRank.familyName }}</view>
......
1 <!-- 1 <!--
2 * @Date: 2025-08-27 17:43:45 2 * @Date: 2025-08-27 17:43:45
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-09-06 01:21:51 4 + * @LastEditTime: 2025-09-06 12:49:17
5 * @FilePath: /lls_program/src/pages/Welcome/index.vue 5 * @FilePath: /lls_program/src/pages/Welcome/index.vue
6 * @Description: 文件描述 6 * @Description: 文件描述
7 --> 7 -->
...@@ -67,6 +67,71 @@ ...@@ -67,6 +67,71 @@
67 </view> 67 </view>
68 <!-- Bottom Navigation --> 68 <!-- Bottom Navigation -->
69 <BottomNav /> 69 <BottomNav />
70 +
71 + <!-- Dialog Components -->
72 + <!-- 个人信息收集说明弹窗 -->
73 + <nut-dialog
74 + v-model:visible="showPrivacyDialog"
75 + title="个人信息收集说明"
76 + >
77 + <template #default>
78 + <view class=" text-gray-700 leading-loose text-sm text-left">
79 + {{ privacyContent }}
80 + </view>
81 + </template>
82 + <template #footer>
83 + <nut-row :gutter="10">
84 + <nut-col :span="12">
85 + <nut-button
86 + @click="onPrivacyCancel"
87 + type="default"
88 + size="normal"
89 + block
90 + >
91 + 取消操作
92 + </nut-button>
93 + </nut-col>
94 + <nut-col :span="12">
95 + <nut-button
96 + @click="onPrivacyConfirm"
97 + type="primary"
98 + size="normal"
99 + color="#007AFF"
100 + block
101 + >
102 + 同意搜集
103 + </nut-button>
104 + </nut-col>
105 + </nut-row>
106 + </template>
107 + </nut-dialog>
108 +
109 + <!-- 年龄限制提示弹窗 -->
110 + <nut-dialog
111 + v-model:visible="showAgeDialog"
112 + title="温馨提示"
113 + >
114 + <template #default>
115 + <view class="text-center text-gray-700 text-sm leading-loose">
116 + 您需要年满60岁才能创建家庭
117 + </view>
118 + </template>
119 + <template #footer>
120 + <nut-row>
121 + <nut-col :span="24">
122 + <nut-button
123 + @click="onAgeConfirm"
124 + type="primary"
125 + size="normal"
126 + color="#007AFF"
127 + block
128 + >
129 + 了解
130 + </nut-button>
131 + </nut-col>
132 + </nut-row>
133 + </template>
134 + </nut-dialog>
70 </view> 135 </view>
71 </template> 136 </template>
72 137
...@@ -84,6 +149,14 @@ const userInfo = ref({}); ...@@ -84,6 +149,14 @@ const userInfo = ref({});
84 const canCreateFamily = ref(true); 149 const canCreateFamily = ref(true);
85 const hasProfile = ref(false); 150 const hasProfile = ref(false);
86 151
152 +// Dialog相关响应式数据
153 +const showPrivacyDialog = ref(false);
154 +const showAgeDialog = ref(false);
155 +const pendingNavigateUrl = ref('');
156 +
157 +// 个人信息收集说明内容
158 +const privacyContent = `为了提供更好的服务,我们需要收集您的基本信息:1.头像和昵称:用于家庭成员识别 2.出生年月:验证年龄资格,60岁以上可创建家庭。我们承诺严格保护您的个人隐私,仅用于家庭功能和活动服务。`;
159 +
87 const navigateTo = (url) => { 160 const navigateTo = (url) => {
88 Taro.navigateTo({ url }); 161 Taro.navigateTo({ url });
89 }; 162 };
...@@ -109,32 +182,39 @@ useDidShow(async () => { ...@@ -109,32 +182,39 @@ useDidShow(async () => {
109 }); 182 });
110 183
111 const handleNavigate = (url) => { 184 const handleNavigate = (url) => {
112 - // 检查个人信息是否完善 185 + if (url === '/pages/CreateFamily/index') {
113 if (!hasProfile.value) { 186 if (!hasProfile.value) {
114 - // 先显示隐私提醒 187 + // 显示个人信息收集说明弹窗
115 - Taro.showModal({ 188 + pendingNavigateUrl.value = '/pages/AddProfile/index';
116 - title: '个人信息收集说明', 189 + showPrivacyDialog.value = true;
117 - content: `为了提供更好的服务,我们需要收集您的基本信息:1.头像和昵称:用于家庭成员识别 2.出生年月:验证年龄资格,60岁以上可创建家庭 3.轮椅出行信息:为您提供无障碍活动推荐。我们承诺严格保护您的个人隐私,仅用于家庭功能和活动服务。`, 190 + return;
118 - confirmText: '同意搜集',
119 - cancelText: '取消操作',
120 - success: (res) => {
121 - if (res.confirm) {
122 - Taro.navigateTo({ url: '/pages/AddProfile/index' });
123 } 191 }
124 - }, 192 +
125 - }); 193 + if (!canCreateFamily.value) {
126 - } else { 194 + // 显示年龄限制提示弹窗
127 - // 检查用户是否年满60岁 195 + showAgeDialog.value = true;
128 - if (canCreateFamily.value) { 196 + return;
129 - navigateTo(url);
130 - } else {
131 - Taro.showModal({
132 - title: '提示',
133 - content: '您需要年满60岁才能创建家庭',
134 - cancelText: '关闭',
135 - confirmText: '了解',
136 - });
137 } 197 }
138 } 198 }
199 +
200 + navigateTo(url);
201 +};
202 +
203 +// Dialog事件处理方法
204 +const onPrivacyCancel = () => {
205 + showPrivacyDialog.value = false;
206 + pendingNavigateUrl.value = '';
207 +};
208 +
209 +const onPrivacyConfirm = () => {
210 + showPrivacyDialog.value = false;
211 + if (pendingNavigateUrl.value) {
212 + navigateTo(pendingNavigateUrl.value);
213 + pendingNavigateUrl.value = '';
214 + }
215 +};
216 +
217 +const onAgeConfirm = () => {
218 + showAgeDialog.value = false;
139 }; 219 };
140 </script> 220 </script>
......