Commit 4598017b3471fc96687126c2f792654ab2fdd488
Committed by
王天杨
1 parent
3a3dc915
feat(profile): 添加用户资料完善功能
- 新增 profile-setup 页面用于完善用户头像、昵称和手机号 - 实现 nicknameCheck 工具函数检查用户是否需要完善资料 - 在登录流程中集成资料完善检查和跳转逻辑 - 更新上传和用户页面以支持资料完善前置验证 - 配置新页面路由和导航栏样式设置
Showing
7 changed files
with
416 additions
and
4 deletions
稻城亚丁小程序/uniapp/src/pages.json
| @@ -54,6 +54,14 @@ | @@ -54,6 +54,14 @@ | ||
| 54 | } | 54 | } |
| 55 | }, | 55 | }, |
| 56 | { | 56 | { |
| 57 | + "path": "pages/profile-setup/profile-setup", | ||
| 58 | + "style": { | ||
| 59 | + "navigationBarTitleText": "完善资料", | ||
| 60 | + "navigationBarBackgroundColor": "#ffffff", | ||
| 61 | + "navigationBarTextStyle": "black" | ||
| 62 | + } | ||
| 63 | + }, | ||
| 64 | + { | ||
| 57 | "path": "pages/photo-detail/photo-detail", | 65 | "path": "pages/photo-detail/photo-detail", |
| 58 | "style": { | 66 | "style": { |
| 59 | "navigationBarTitleText": "作品详情", | 67 | "navigationBarTitleText": "作品详情", |
稻城亚丁小程序/uniapp/src/pages/login/login.vue
| @@ -83,6 +83,7 @@ import { | @@ -83,6 +83,7 @@ import { | ||
| 83 | } from "@/config/api"; | 83 | } from "@/config/api"; |
| 84 | import { getMpToken } from "@/utils/api/http"; | 84 | import { getMpToken } from "@/utils/api/http"; |
| 85 | import { getMpLoginChannel, loginAsGuest, loginWithPhone, loginWithWeixin } from "@/utils/api/mpSession"; | 85 | import { getMpLoginChannel, loginAsGuest, loginWithPhone, loginWithWeixin } from "@/utils/api/mpSession"; |
| 86 | +import { needsProfileSetup } from "@/utils/nicknameCheck"; | ||
| 86 | import { staticAsset } from "@/utils/staticAsset"; | 87 | import { staticAsset } from "@/utils/staticAsset"; |
| 87 | const statusBarHeight = ref(20); | 88 | const statusBarHeight = ref(20); |
| 88 | const headerBg = staticAsset("login-header.png"); | 89 | const headerBg = staticAsset("login-header.png"); |
| @@ -190,17 +191,26 @@ function normalizeAuditSafeMessage(msg: string): string { | @@ -190,17 +191,26 @@ function normalizeAuditSafeMessage(msg: string): string { | ||
| 190 | return m; | 191 | return m; |
| 191 | } | 192 | } |
| 192 | 193 | ||
| 193 | -async function onWeixinLogin() { | 194 | +async function onWeixinLogin(_e?: any) { |
| 194 | errMsg.value = ""; | 195 | errMsg.value = ""; |
| 195 | loading.value = true; | 196 | loading.value = true; |
| 196 | try { | 197 | try { |
| 197 | // #ifdef MP-WEIXIN | 198 | // #ifdef MP-WEIXIN |
| 198 | - await loginWithWeixin(); | 199 | + const user = await loginWithWeixin(); |
| 199 | // #endif | 200 | // #endif |
| 200 | // #ifndef MP-WEIXIN | 201 | // #ifndef MP-WEIXIN |
| 201 | await loginAsGuest(); | 202 | await loginAsGuest(); |
| 203 | + const user = null; | ||
| 202 | // #endif | 204 | // #endif |
| 203 | uni.showToast({ title: "登录成功", icon: "success" }); | 205 | uni.showToast({ title: "登录成功", icon: "success" }); |
| 206 | + // #ifdef MP-WEIXIN | ||
| 207 | + if (needsProfileSetup()) { | ||
| 208 | + setTimeout(() => { | ||
| 209 | + uni.navigateTo({ url: "/pages/profile-setup/profile-setup" }); | ||
| 210 | + }, 500); | ||
| 211 | + return; | ||
| 212 | + } | ||
| 213 | + // #endif | ||
| 204 | afterLoginNavigate(); | 214 | afterLoginNavigate(); |
| 205 | } catch (e: unknown) { | 215 | } catch (e: unknown) { |
| 206 | const raw = appendLoopbackConnectHint(pickErr(e, "登录失败")); | 216 | const raw = appendLoopbackConnectHint(pickErr(e, "登录失败")); |
稻城亚丁小程序/uniapp/src/pages/profile-setup/profile-setup.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <view class="page"> | ||
| 3 | + <view class="header"> | ||
| 4 | + <text class="title">完善个人资料</text> | ||
| 5 | + <text class="sub">设置头像、昵称和手机号,让作品更有辨识度</text> | ||
| 6 | + </view> | ||
| 7 | + | ||
| 8 | + <!-- 头像 --> | ||
| 9 | + <view class="avatar-section"> | ||
| 10 | + <button class="avatar-btn" open-type="chooseAvatar" @chooseavatar="onChooseAvatar"> | ||
| 11 | + <image | ||
| 12 | + v-if="avatarTemp" | ||
| 13 | + class="avatar-img" | ||
| 14 | + :src="avatarTemp" | ||
| 15 | + mode="aspectFill" | ||
| 16 | + /> | ||
| 17 | + <view v-else class="avatar-placeholder"> | ||
| 18 | + <text class="avatar-placeholder-icon">+</text> | ||
| 19 | + <text class="avatar-placeholder-text">点击设置头像</text> | ||
| 20 | + </view> | ||
| 21 | + </button> | ||
| 22 | + </view> | ||
| 23 | + | ||
| 24 | + <!-- 昵称 --> | ||
| 25 | + <view class="name-section"> | ||
| 26 | + <text class="label">昵称</text> | ||
| 27 | + <input | ||
| 28 | + class="name-input" | ||
| 29 | + type="nickname" | ||
| 30 | + v-model="nickname" | ||
| 31 | + maxlength="16" | ||
| 32 | + placeholder="填写昵称" | ||
| 33 | + placeholder-class="name-ph" | ||
| 34 | + /> | ||
| 35 | + <view class="line" /> | ||
| 36 | + </view> | ||
| 37 | + | ||
| 38 | + <!-- 手机号 --> | ||
| 39 | + <!-- #ifdef MP-WEIXIN --> | ||
| 40 | + <view class="phone-section"> | ||
| 41 | + <text class="label">手机号</text> | ||
| 42 | + <button | ||
| 43 | + class="phone-btn" | ||
| 44 | + open-type="getPhoneNumber" | ||
| 45 | + @getphonenumber="onGetPhoneNumber" | ||
| 46 | + > | ||
| 47 | + <text v-if="phoneNumber" class="phone-val">{{ phoneNumber }}</text> | ||
| 48 | + <text v-else class="phone-ph">点击获取微信绑定手机号</text> | ||
| 49 | + </button> | ||
| 50 | + <view class="line" /> | ||
| 51 | + </view> | ||
| 52 | + <!-- #endif --> | ||
| 53 | + | ||
| 54 | + <view class="actions"> | ||
| 55 | + <button class="btn-save" :disabled="saving" @click="onSubmit"> | ||
| 56 | + <text v-if="saving">保存中…</text> | ||
| 57 | + <text v-else>完成</text> | ||
| 58 | + </button> | ||
| 59 | + <text class="skip-link" @click="goHome">跳过,以后再设</text> | ||
| 60 | + </view> | ||
| 61 | + </view> | ||
| 62 | +</template> | ||
| 63 | + | ||
| 64 | +<script setup lang="ts"> | ||
| 65 | +import { ref } from "vue"; | ||
| 66 | +import { onLoad } from "@dcloudio/uni-app"; | ||
| 67 | +import { loadUserProfile, saveUserProfile } from "@/utils/userProfileStorage"; | ||
| 68 | +import { uploadImage, post } from "@/utils/api/http"; | ||
| 69 | +import { isAlreadyPersistedAvatarUrl } from "@/utils/avatarUpload"; | ||
| 70 | +import { bindWechatPhone } from "@/utils/api/mpSession"; | ||
| 71 | + | ||
| 72 | +const nickname = ref(""); | ||
| 73 | +const avatarTemp = ref(""); | ||
| 74 | +const phoneNumber = ref(""); | ||
| 75 | +const saving = ref(false); | ||
| 76 | + | ||
| 77 | +onLoad(() => { | ||
| 78 | + const profile = loadUserProfile(); | ||
| 79 | + nickname.value = profile.nickname || ""; | ||
| 80 | + avatarTemp.value = profile.avatarUrl || ""; | ||
| 81 | + phoneNumber.value = profile.phone || ""; | ||
| 82 | +}); | ||
| 83 | + | ||
| 84 | +function onChooseAvatar(e: any) { | ||
| 85 | + const url = e?.detail?.avatarUrl; | ||
| 86 | + if (url) { | ||
| 87 | + avatarTemp.value = url; | ||
| 88 | + } | ||
| 89 | +} | ||
| 90 | + | ||
| 91 | +async function onGetPhoneNumber(e: any) { | ||
| 92 | + const code = e?.detail?.code; | ||
| 93 | + if (!code) { | ||
| 94 | + uni.showToast({ title: "未获取到手机号授权", icon: "none" }); | ||
| 95 | + return; | ||
| 96 | + } | ||
| 97 | + try { | ||
| 98 | + const phone = await bindWechatPhone(code); | ||
| 99 | + phoneNumber.value = phone; | ||
| 100 | + uni.showToast({ title: "手机号已获取", icon: "success" }); | ||
| 101 | + } catch (err: unknown) { | ||
| 102 | + const msg = | ||
| 103 | + err && typeof err === "object" && "msg" in err | ||
| 104 | + ? (err as { msg: string }).msg | ||
| 105 | + : "手机号绑定失败"; | ||
| 106 | + uni.showToast({ title: msg as string, icon: "none" }); | ||
| 107 | + } | ||
| 108 | +} | ||
| 109 | + | ||
| 110 | +function goHome() { | ||
| 111 | + uni.switchTab({ url: "/pages/home/home" }); | ||
| 112 | +} | ||
| 113 | + | ||
| 114 | +async function onSubmit() { | ||
| 115 | + const nick = nickname.value.trim(); | ||
| 116 | + // #ifdef MP-WEIXIN | ||
| 117 | + const phone = phoneNumber.value.trim(); | ||
| 118 | + if (!phone) { | ||
| 119 | + uni.showToast({ title: "请先绑定手机号", icon: "none" }); | ||
| 120 | + return; | ||
| 121 | + } | ||
| 122 | + // #endif | ||
| 123 | + | ||
| 124 | + saving.value = true; | ||
| 125 | + try { | ||
| 126 | + let avatarUrl = avatarTemp.value.trim(); | ||
| 127 | + if (avatarUrl && !isAlreadyPersistedAvatarUrl(avatarUrl)) { | ||
| 128 | + try { | ||
| 129 | + avatarUrl = await uploadImage(avatarUrl); | ||
| 130 | + } catch { | ||
| 131 | + uni.showToast({ title: "头像上传失败,请重试", icon: "none" }); | ||
| 132 | + saving.value = false; | ||
| 133 | + return; | ||
| 134 | + } | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + // #ifdef MP-WEIXIN | ||
| 138 | + if (phone) { | ||
| 139 | + saveUserProfile({ | ||
| 140 | + nickname: nick, | ||
| 141 | + avatarUrl, | ||
| 142 | + bio: loadUserProfile().bio, | ||
| 143 | + gender: loadUserProfile().gender, | ||
| 144 | + phone, | ||
| 145 | + }); | ||
| 146 | + } | ||
| 147 | + // #endif | ||
| 148 | + | ||
| 149 | + await post("/api/v1/me/profile", { | ||
| 150 | + nickname: nick || undefined, | ||
| 151 | + avatarUrl: avatarUrl || undefined, | ||
| 152 | + }); | ||
| 153 | + | ||
| 154 | + // #ifndef MP-WEIXIN | ||
| 155 | + saveUserProfile({ | ||
| 156 | + nickname: nick, | ||
| 157 | + avatarUrl, | ||
| 158 | + bio: loadUserProfile().bio, | ||
| 159 | + gender: loadUserProfile().gender, | ||
| 160 | + phone: loadUserProfile().phone, | ||
| 161 | + }); | ||
| 162 | + // #endif | ||
| 163 | + | ||
| 164 | + uni.showToast({ title: "已保存", icon: "success" }); | ||
| 165 | + setTimeout(() => goHome(), 500); | ||
| 166 | + } catch { | ||
| 167 | + uni.showToast({ title: "保存失败,请重试", icon: "none" }); | ||
| 168 | + } finally { | ||
| 169 | + saving.value = false; | ||
| 170 | + } | ||
| 171 | +} | ||
| 172 | +</script> | ||
| 173 | + | ||
| 174 | +<style scoped> | ||
| 175 | +.page { | ||
| 176 | + min-height: 100vh; | ||
| 177 | + display: flex; | ||
| 178 | + flex-direction: column; | ||
| 179 | + align-items: center; | ||
| 180 | + padding: 100rpx 48rpx 0; | ||
| 181 | + box-sizing: border-box; | ||
| 182 | + background: #fff; | ||
| 183 | +} | ||
| 184 | + | ||
| 185 | +.header { | ||
| 186 | + display: flex; | ||
| 187 | + flex-direction: column; | ||
| 188 | + align-items: center; | ||
| 189 | + margin-bottom: 60rpx; | ||
| 190 | +} | ||
| 191 | + | ||
| 192 | +.title { | ||
| 193 | + font-size: 40rpx; | ||
| 194 | + font-weight: 700; | ||
| 195 | + color: #111827; | ||
| 196 | + margin-bottom: 16rpx; | ||
| 197 | +} | ||
| 198 | + | ||
| 199 | +.sub { | ||
| 200 | + font-size: 26rpx; | ||
| 201 | + color: #9ca3af; | ||
| 202 | +} | ||
| 203 | + | ||
| 204 | +.avatar-section { | ||
| 205 | + margin-bottom: 48rpx; | ||
| 206 | +} | ||
| 207 | + | ||
| 208 | +.avatar-btn { | ||
| 209 | + width: 160rpx; | ||
| 210 | + height: 160rpx; | ||
| 211 | + padding: 0; | ||
| 212 | + margin: 0; | ||
| 213 | + border: none; | ||
| 214 | + border-radius: 50%; | ||
| 215 | + background: transparent; | ||
| 216 | + overflow: visible; | ||
| 217 | + line-height: 1; | ||
| 218 | +} | ||
| 219 | + | ||
| 220 | +.avatar-btn::after { | ||
| 221 | + display: none; | ||
| 222 | +} | ||
| 223 | + | ||
| 224 | +.avatar-img { | ||
| 225 | + width: 160rpx; | ||
| 226 | + height: 160rpx; | ||
| 227 | + border-radius: 50%; | ||
| 228 | +} | ||
| 229 | + | ||
| 230 | +.avatar-placeholder { | ||
| 231 | + width: 160rpx; | ||
| 232 | + height: 160rpx; | ||
| 233 | + border-radius: 50%; | ||
| 234 | + border: 4rpx dashed #d1d5db; | ||
| 235 | + display: flex; | ||
| 236 | + flex-direction: column; | ||
| 237 | + align-items: center; | ||
| 238 | + justify-content: center; | ||
| 239 | + background: #f9fafb; | ||
| 240 | +} | ||
| 241 | + | ||
| 242 | +.avatar-placeholder-icon { | ||
| 243 | + font-size: 48rpx; | ||
| 244 | + color: #9ca3af; | ||
| 245 | + line-height: 1; | ||
| 246 | + margin-bottom: 4rpx; | ||
| 247 | +} | ||
| 248 | + | ||
| 249 | +.avatar-placeholder-text { | ||
| 250 | + font-size: 20rpx; | ||
| 251 | + color: #9ca3af; | ||
| 252 | +} | ||
| 253 | + | ||
| 254 | +.name-section, | ||
| 255 | +.phone-section { | ||
| 256 | + width: 100%; | ||
| 257 | + margin-bottom: 40rpx; | ||
| 258 | +} | ||
| 259 | + | ||
| 260 | +.label { | ||
| 261 | + display: block; | ||
| 262 | + font-size: 28rpx; | ||
| 263 | + font-weight: 600; | ||
| 264 | + color: #374151; | ||
| 265 | + margin-bottom: 16rpx; | ||
| 266 | +} | ||
| 267 | + | ||
| 268 | +.name-input { | ||
| 269 | + display: block; | ||
| 270 | + width: 100%; | ||
| 271 | + height: 80rpx; | ||
| 272 | + padding: 0 4rpx; | ||
| 273 | + font-size: 32rpx; | ||
| 274 | + color: #111827; | ||
| 275 | + background: transparent; | ||
| 276 | +} | ||
| 277 | + | ||
| 278 | +.name-ph { | ||
| 279 | + color: #c4c4c4; | ||
| 280 | + font-size: 28rpx; | ||
| 281 | +} | ||
| 282 | + | ||
| 283 | +.phone-btn { | ||
| 284 | + display: flex; | ||
| 285 | + align-items: center; | ||
| 286 | + width: 100%; | ||
| 287 | + height: 80rpx; | ||
| 288 | + padding: 0 4rpx; | ||
| 289 | + margin: 0; | ||
| 290 | + border: none; | ||
| 291 | + background: transparent; | ||
| 292 | + text-align: left; | ||
| 293 | + font-size: 32rpx; | ||
| 294 | + line-height: 1; | ||
| 295 | +} | ||
| 296 | + | ||
| 297 | +.phone-btn::after { | ||
| 298 | + display: none; | ||
| 299 | +} | ||
| 300 | + | ||
| 301 | +.phone-val { | ||
| 302 | + color: #111827; | ||
| 303 | +} | ||
| 304 | + | ||
| 305 | +.phone-ph { | ||
| 306 | + color: #c4c4c4; | ||
| 307 | + font-size: 28rpx; | ||
| 308 | +} | ||
| 309 | + | ||
| 310 | +.line { | ||
| 311 | + height: 1rpx; | ||
| 312 | + margin-top: 8rpx; | ||
| 313 | + background: #e5e7eb; | ||
| 314 | +} | ||
| 315 | + | ||
| 316 | +.actions { | ||
| 317 | + width: 100%; | ||
| 318 | + display: flex; | ||
| 319 | + flex-direction: column; | ||
| 320 | + align-items: center; | ||
| 321 | + margin-top: 20rpx; | ||
| 322 | +} | ||
| 323 | + | ||
| 324 | +.btn-save { | ||
| 325 | + width: 100%; | ||
| 326 | + height: 88rpx; | ||
| 327 | + display: flex; | ||
| 328 | + align-items: center; | ||
| 329 | + justify-content: center; | ||
| 330 | + margin-bottom: 24rpx; | ||
| 331 | + padding: 0; | ||
| 332 | + font-size: 32rpx; | ||
| 333 | + font-weight: 500; | ||
| 334 | + color: #fff; | ||
| 335 | + background: #2185ff; | ||
| 336 | + border: none; | ||
| 337 | + border-radius: 999rpx; | ||
| 338 | +} | ||
| 339 | + | ||
| 340 | +.btn-save::after { | ||
| 341 | + display: none; | ||
| 342 | +} | ||
| 343 | + | ||
| 344 | +.btn-save[disabled] { | ||
| 345 | + opacity: 0.6; | ||
| 346 | +} | ||
| 347 | + | ||
| 348 | +.skip-link { | ||
| 349 | + font-size: 26rpx; | ||
| 350 | + color: #9ca3af; | ||
| 351 | + padding: 16rpx; | ||
| 352 | +} | ||
| 353 | +</style> |
稻城亚丁小程序/uniapp/src/pages/upload/upload.vue
| @@ -167,7 +167,7 @@ import { | @@ -167,7 +167,7 @@ import { | ||
| 167 | uploadImage, | 167 | uploadImage, |
| 168 | } from "@/utils/api/http"; | 168 | } from "@/utils/api/http"; |
| 169 | import { ensureMpSession, getMpLoginChannel } from "@/utils/api/mpSession"; | 169 | import { ensureMpSession, getMpLoginChannel } from "@/utils/api/mpSession"; |
| 170 | -import { reLaunchLoginIfNoBoundPhone } from "@/utils/guestTabGuard"; | 170 | +import { reLaunchLoginIfNoBoundPhone, redirectToProfileSetupIfNeeded } from "@/utils/guestTabGuard"; |
| 171 | import { consumeUploadFormClearFlag } from "@/utils/uploadTabClear"; | 171 | import { consumeUploadFormClearFlag } from "@/utils/uploadTabClear"; |
| 172 | import { resolveMediaUrl } from "@/utils/mediaUrl"; | 172 | import { resolveMediaUrl } from "@/utils/mediaUrl"; |
| 173 | import { consumeUploadResubmitWorkId } from "@/utils/uploadResubmit"; | 173 | import { consumeUploadResubmitWorkId } from "@/utils/uploadResubmit"; |
| @@ -277,6 +277,9 @@ onShow(() => { | @@ -277,6 +277,9 @@ onShow(() => { | ||
| 277 | if (reLaunchLoginIfNoBoundPhone()) { | 277 | if (reLaunchLoginIfNoBoundPhone()) { |
| 278 | return; | 278 | return; |
| 279 | } | 279 | } |
| 280 | + if (redirectToProfileSetupIfNeeded()) { | ||
| 281 | + return; | ||
| 282 | + } | ||
| 280 | const rid = consumeUploadResubmitWorkId(); | 283 | const rid = consumeUploadResubmitWorkId(); |
| 281 | if (apiOn.value && rid > 0) { | 284 | if (apiOn.value && rid > 0) { |
| 282 | void loadWorkForEdit(rid); | 285 | void loadWorkForEdit(rid); |
稻城亚丁小程序/uniapp/src/pages/user/user.vue
| @@ -287,7 +287,7 @@ import { | @@ -287,7 +287,7 @@ import { | ||
| 287 | isMpSessionExpiredError, | 287 | isMpSessionExpiredError, |
| 288 | } from "@/utils/api/http"; | 288 | } from "@/utils/api/http"; |
| 289 | import { ensureMpSession, getMpLoginChannel } from "@/utils/api/mpSession"; | 289 | import { ensureMpSession, getMpLoginChannel } from "@/utils/api/mpSession"; |
| 290 | -import { reLaunchLoginIfNoBoundPhone } from "@/utils/guestTabGuard"; | 290 | +import { reLaunchLoginIfNoBoundPhone, redirectToProfileSetupIfNeeded } from "@/utils/guestTabGuard"; |
| 291 | import { resolveMediaUrl } from "@/utils/mediaUrl"; | 291 | import { resolveMediaUrl } from "@/utils/mediaUrl"; |
| 292 | 292 | ||
| 293 | const statusBarHeight = ref(20); | 293 | const statusBarHeight = ref(20); |
| @@ -511,6 +511,9 @@ onShow(() => { | @@ -511,6 +511,9 @@ onShow(() => { | ||
| 511 | if (reLaunchLoginIfNoBoundPhone()) { | 511 | if (reLaunchLoginIfNoBoundPhone()) { |
| 512 | return; | 512 | return; |
| 513 | } | 513 | } |
| 514 | + if (redirectToProfileSetupIfNeeded()) { | ||
| 515 | + return; | ||
| 516 | + } | ||
| 514 | profile.value = loadUserProfile(); | 517 | profile.value = loadUserProfile(); |
| 515 | void loadUserFromApi(); | 518 | void loadUserFromApi(); |
| 516 | }); | 519 | }); |
稻城亚丁小程序/uniapp/src/utils/guestTabGuard.ts
| 1 | +import { needsProfileSetup } from "./nicknameCheck"; | ||
| 2 | + | ||
| 1 | /** | 3 | /** |
| 2 | * 先浏览后登录;不再强制绑定手机号后才可使用上传/我的。 | 4 | * 先浏览后登录;不再强制绑定手机号后才可使用上传/我的。 |
| 3 | * 保留函数签名,避免各处 import 大面积改动;始终视为「未处于仅差手机号」状态。 | 5 | * 保留函数签名,避免各处 import 大面积改动;始终视为「未处于仅差手机号」状态。 |
| @@ -10,3 +12,15 @@ export function isLoggedInWithoutBoundPhone(): boolean { | @@ -10,3 +12,15 @@ export function isLoggedInWithoutBoundPhone(): boolean { | ||
| 10 | export function reLaunchLoginIfNoBoundPhone(): boolean { | 12 | export function reLaunchLoginIfNoBoundPhone(): boolean { |
| 11 | return false; | 13 | return false; |
| 12 | } | 14 | } |
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * 检查当前用户是否缺少必要资料(昵称为占位名 或 未绑定手机号), | ||
| 18 | + * 若是则跳转到资料完善页。返回 true 表示已触发跳转。 | ||
| 19 | + */ | ||
| 20 | +export function redirectToProfileSetupIfNeeded(): boolean { | ||
| 21 | + if (needsProfileSetup()) { | ||
| 22 | + uni.navigateTo({ url: "/pages/profile-setup/profile-setup" }); | ||
| 23 | + return true; | ||
| 24 | + } | ||
| 25 | + return false; | ||
| 26 | +} |
稻城亚丁小程序/uniapp/src/utils/nicknameCheck.ts
0 → 100644
| 1 | +import { loadUserProfile } from "./userProfileStorage"; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * 检查当前用户昵称是否为通用占位名 | ||
| 5 | + * (微信用户 / 游客 / 空 表示用户尚未完善个人资料) | ||
| 6 | + */ | ||
| 7 | +export function isGenericNickname(): boolean { | ||
| 8 | + const profile = loadUserProfile(); | ||
| 9 | + const name = String(profile.nickname || "").trim(); | ||
| 10 | + return name === "" || name === "微信用户" || name === "游客"; | ||
| 11 | +} | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 检查用户是否缺少必要资料(昵称为占位名 或 手机号为空) | ||
| 15 | + */ | ||
| 16 | +export function needsProfileSetup(): boolean { | ||
| 17 | + const profile = loadUserProfile(); | ||
| 18 | + const name = String(profile.nickname || "").trim(); | ||
| 19 | + const phone = String(profile.phone || "").trim(); | ||
| 20 | + return name === "" || name === "微信用户" || name === "游客" || phone === ""; | ||
| 21 | +} |