# 完善基本信息页面(`base-info.vue`)头像处理与交互逻辑 ## 概述 ✅ 本文件记录 `src/pages/patient/profile/infos/base-info.vue` 中关于头像(avatar)下载、选择与上传的实现细节,并**特别强调**你要求的行为: - 在页面加载时默认从服务端下载用户头像(不再判断 avatar 地址是否包含特定域名)。 - 在页面从服务器获取并填充资料期间,禁止用户交互(整体锁定)。 - 只有当用户主动点击头像控件尝试更改时,才将“需要上传头像”标记设为 true —— 即“只要用户尝试更改就上传”,不要做任何域名判断。 这些变更已在 `base-info.vue` 中实现,并在此文档中逐条解释。⚠️ 强调:文档中所有代码符号均以 `code` 标记引用。 --- ## 关键响应式变量(状态)🔧 - `form`:包含 `avatar`, `nickname`, `phone`, `age`, `sex`, `address`。 - `region`:`picker` 的地区数组。 - `loading`:当从服务器拉取资料/下载头像时为 true。用于禁用交互并配合 `uni.showLoading({ mask: true })` 阻止触摸。见 `fetchUserInfo()`。 - `isChoosing`:头像选择防抖/状态。 - `avatarUploading`:头像上传中标志。 - `avatarNeedsUpload`:当为 `true` 时,`onSubmit()` 提交前会触发上传。默认在 `fetchUserInfo()` 结束时设为 `false`。 - `avatarEditedByUser`:表示用户是否主动点击了头像控件(用来控制上传语义)。 --- ## 页面加载与填充逻辑(`fetchUserInfo()`)📥 1. 页面显示时触发 `onShow` → `fetchUserInfo()`。 2. `fetchUserInfo()` 做以下事: - 读取 token(`uni.getStorageSync('token')`),若无直接返回。 - set `loading = true` 并 `uni.showLoading({ title: '加载中...', mask: true })`,阻止与页面交互。 - 发起 `POST https://wx.baiyun.work/user_info`,解析并填入 `form` 字段。 - 不管 `d.avatar` 是何种 URL,若 `userId` 存在都会调用: ```ts uni.downloadFile({ url: `https://wx.baiyun.work/user/avatar/${userId}` }) ``` 若下载成功,`d.avatar = downloadRes.tempFilePath`。 - 填充:`form.value.avatar = d.avatar || form.value.avatar`。 - 默认: ```ts avatarNeedsUpload.value = false avatarEditedByUser.value = false ``` 即:完成从服务器获取资料后默认不上传,等用户主动更改。 - finally 中 `uni.hideLoading()` 和 `loading = false`,恢复交互。 > 重要:这里的实现逻辑**不会**对 `d.avatar` 的 URL 做域名判断或条件分支;总是尝试下载(只要有 userId)。 --- ## 用户交互:点击与选择头像(`startChooseAvatar` / `onChooseAvatar`)🖱️ - 用户点击头像: - `startChooseAvatar()` 会先检查 `loading`,若正在下载则忽略点击;否则: - 将 `avatarEditedByUser.value = true` 与 `avatarNeedsUpload.value = true`(即只要用户点击尝试更改就上传)。 - 进入选择流程(防重入控制 `isChoosing`)。 - 用户选择成功:`onChooseAvatar(e)` 会设置 `form.value.avatar = url`,并再次将 `avatarEditedByUser` 与 `avatarNeedsUpload` 设为 `true`。 - 如果用户取消选择:依然保留 `avatarEditedByUser=true` 与 `avatarNeedsUpload=true`(这是你明确要求的:「只要点击就上传」)。 > 注:如果你希望“点击但取消后不上传”,可以把 `avatarNeedsUpload` 的设置移到 `onChooseAvatar` 成功时再设,而不是 `startChooseAvatar`。但目前实现为“只要点击就上传”。 --- ## 上传流程(`ensureAvatarUploaded()` 与 `uploadAvatar()`)⬆️ - `onSubmit()` 检查 `avatarNeedsUpload`;如果 `true` 且 `avatarUploading` 为 false,会调用 `await ensureAvatarUploaded()`。 - 旧逻辑会绕过本站域名,但现在已移除域名判断(按你的要求):无论 `form.avatar` 是哪种 URL,只要 `avatarNeedsUpload === true`,执行下载再上传流程: 1. 如果 `form.avatar` 是远程 URL(`isHttpUrl` 为 true),先 `uni.downloadFile({ url: form.value.avatar })`,得到 tempFilePath 后 `uploadAvatar(tempFilePath)`。 2. 如果 `form.avatar` 已经是本地临时路径(如拍照/本地选择),直接调用 `uploadAvatar(form.value.avatar)`。 - `uploadAvatar()` 使用 `uni.uploadFile`,解析后端返回的 `data.url` / `data.path` / `data.fileUrl`,如果返回会把 `form.value.avatar` 更新为服务器的新 URL;若上传成功会将 `avatarNeedsUpload.value = false`。 --- ## 禁止页面交互(实现)🚫 - 页面加载并下载服务器资料期间,`loading = true`。 - 在模板中把不同输入/按钮的 `:disabled` 与 `loading` 关联:例如: ```html