bugfix:ui
This commit is contained in:
@@ -0,0 +1,91 @@
|
|||||||
|
---
|
||||||
|
name: 完善资料入口直接弹出编辑弹窗
|
||||||
|
overview: 让新用户登录后的生日引导、以及运势页的「去设置生日/去完善资料」入口,在跳转到「我的」页面后自动弹出用户信息编辑弹窗,而不是停留在页面顶部。
|
||||||
|
todos:
|
||||||
|
- id: add-open-edit-key
|
||||||
|
content: config.ts 的 STORAGE_KEYS 新增 OPEN_PROFILE_EDIT 标记
|
||||||
|
status: completed
|
||||||
|
- id: entry-write-marker
|
||||||
|
content: login.ts 生日引导与 horoscope.ts 去设置生日入口写入标记后 switchTab
|
||||||
|
status: completed
|
||||||
|
dependencies:
|
||||||
|
- add-open-edit-key
|
||||||
|
- id: profile-auto-edit
|
||||||
|
content: profile.ts onShow 消费标记,缓存兜底预填后延迟一帧自动弹出编辑弹窗
|
||||||
|
status: completed
|
||||||
|
dependencies:
|
||||||
|
- add-open-edit-key
|
||||||
|
- id: verify-entries
|
||||||
|
content: 用 [skill:lsp-code-analysis] 校验所有引导完善资料入口覆盖完整、引用无遗漏
|
||||||
|
status: completed
|
||||||
|
dependencies:
|
||||||
|
- entry-write-marker
|
||||||
|
- profile-auto-edit
|
||||||
|
---
|
||||||
|
|
||||||
|
## 产品概述
|
||||||
|
|
||||||
|
优化新用户登录后的「完善资料」引导体验:用户点击引导按钮后,跳转到「我的」页面时直接自动弹出资料编辑弹窗,无需再手动点击编辑入口。
|
||||||
|
|
||||||
|
## 核心功能
|
||||||
|
|
||||||
|
- 登录后生日引导弹窗点击「去完善」:跳转「我的」页并自动弹出编辑资料弹窗
|
||||||
|
- 运势页的「去设置生日」「去完善资料」入口:同样跳转「我的」页并自动弹出编辑资料弹窗
|
||||||
|
- 弹窗自动预填当前昵称、性别、生日、头像,用户可直接设置生日并保存
|
||||||
|
- 弹窗仅自动弹出一次,关闭或保存后停留在「我的」页面,不重复弹出
|
||||||
|
- 若用户资料接口尚未返回,使用本地缓存的资料预填表单,保证弹窗内容完整可用
|
||||||
|
- 「稍后再说」分支保持原有行为:直接进入衣橱页
|
||||||
|
|
||||||
|
## 视觉与交互
|
||||||
|
|
||||||
|
- 复用现有「编辑资料」底部弹窗样式,无新增界面元素
|
||||||
|
- 跳转后弹窗平滑出现,表单内容直接可编辑
|
||||||
|
|
||||||
|
## 技术栈
|
||||||
|
|
||||||
|
- 微信小程序原生框架(TypeScript + WXML + WXSS),沿用现有 `utils/config.ts`、`utils/logger.ts` 等工具模块,无新增依赖
|
||||||
|
|
||||||
|
## 实现方案
|
||||||
|
|
||||||
|
- 核心策略:复用项目已有的「storage 标记 + switchTab + 目标页 onShow 消费」成熟模式(先例:`OPEN_COLLECT` 标记实现从「我的」跳「穿搭」自动切收藏 tab)。因 `wx.switchTab` 不支持 query 传参,用 storage 标记传递「打开编辑弹窗」意图
|
||||||
|
- 写入端(`login.ts`、`horoscope.ts`):点击引导按钮时先 `wx.setStorageSync(STORAGE_KEYS.OPEN_PROFILE_EDIT, 1)` 再 switchTab;switchTab 失败回调中清除标记,避免残留标记导致下次进入「我的」意外弹窗
|
||||||
|
- 消费端(`profile.ts`):`onShow` 登录校验通过后读取标记并立即 `wx.removeStorageSync`(保证一次性),再经 `wx.nextTick` 延迟一帧后打开编辑弹窗——项目多处注释表明首帧渲染未结束就 setData 会触发「Expected updated data but get first rendering data」导致渲染失败,必须规避
|
||||||
|
- 数据兜底:`onEdit()` 依赖 `data.userInfo`,首次进入时 `fetchUser()` 异步未返回会导致表单为空;命中标记时若 `userInfo` 为空则用 `STORAGE_KEYS.USER_INFO` 本地缓存兜底(登录成功时已写入),再调用 `onEdit()`。`fetchUser` 返回后只更新 `userInfo`/`zodiac`,不覆盖 `editForm`,不会打断用户编辑
|
||||||
|
- 性能与可靠性:单次 storage 读写 + 一次 setData,无额外网络请求;标记消费幂等;接口失败时弹窗仍可打开(缓存兜底)
|
||||||
|
|
||||||
|
## 实现注意
|
||||||
|
|
||||||
|
- 消费逻辑放在 `auth.isLoggedIn()` 校验之后(未登录时早返回,标记保留待下次登录后消费)
|
||||||
|
- 不改动编辑弹窗 UI(`profile.wxml`)、保存逻辑(`onSaveProfile`)及「稍后再说」跳衣橱的原有分支
|
||||||
|
- 日志沿用 `logger.debug`,模块名保持 `login` / `horoscope` / `profile`
|
||||||
|
- `horoscope.ts` 需补充 `STORAGE_KEYS` 导入;`login.ts`、`profile.ts` 已有该导入
|
||||||
|
|
||||||
|
## 架构与数据流
|
||||||
|
|
||||||
|
简单链路改动,无需架构图。数据流:
|
||||||
|
引导入口(登录页生日引导 / 运势页)→ 写入 storage 标记 → `wx.switchTab` 到「我的」→ `onShow` 命中并清除标记 → 缓存兜底预填 → `wx.nextTick` → `onEdit()` → `editVisible=true` 弹出编辑弹窗
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
本次改动共涉及 4 个文件,均在现有架构内按既有模式修改:
|
||||||
|
|
||||||
|
```
|
||||||
|
miniprogram/
|
||||||
|
├── utils/
|
||||||
|
│ └── config.ts # [MODIFY] STORAGE_KEYS 新增 OPEN_PROFILE_EDIT: 'zt_open_profile_edit',用于跨 tab 页传递「自动打开编辑弹窗」意图
|
||||||
|
├── pages/
|
||||||
|
│ ├── login/
|
||||||
|
│ │ └── login.ts # [MODIFY] showBirthGuide() 确认分支:先写入 OPEN_PROFILE_EDIT 标记再 switchTab;switchTab fail 回调中清除标记并保持原有日志
|
||||||
|
│ ├── horoscope/
|
||||||
|
│ │ └── horoscope.ts # [MODIFY] onGoProfile():先写入 OPEN_PROFILE_EDIT 标记再 switchTab,fail 回调清除标记;补充 STORAGE_KEYS 导入(覆盖导航栏「去设置生日」、空态「去完善资料」、内容区「去设置生日」三处入口)
|
||||||
|
│ └── profile/
|
||||||
|
│ └── profile.ts # [MODIFY] onShow() 登录校验后消费标记(读取→立即 remove→wx.nextTick 打开);新增 openEditFromGuide() 方法:userInfo 为空时用 USER_INFO 缓存兜底预填,再调用 onEdit() 打开弹窗;增加 logger.debug 记录命中
|
||||||
|
```
|
||||||
|
|
||||||
|
## Agent Extensions
|
||||||
|
|
||||||
|
### Skill
|
||||||
|
|
||||||
|
- **lsp-code-analysis**
|
||||||
|
- Purpose: 校验登录页生日引导、运势页跳转入口与「我的」页编辑弹窗之间的调用链完整性,确认所有「引导完善资料」入口均已覆盖、无遗漏引用
|
||||||
|
- Expected outcome: 输出受影响符号(onGoProfile、showBirthGuide、onEdit、STORAGE_KEYS)的引用清单,确认改动覆盖全部入口且无其他遗留的「只跳转不弹窗」入口
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
---
|
||||||
|
name: 我的页面通知栏显示未读数量红点
|
||||||
|
overview: 在「我的」页面「通知」栏右侧显示未读消息数量红点,让用户知道 tabBar 上的红点来自通知,并与 tabBar 红点数量保持一致。
|
||||||
|
todos:
|
||||||
|
- id: tabbar-set-unread
|
||||||
|
content: 在 utils/tabbar.ts 新增 setTabBarUnread,用已知数量直接更新 tabBar 红点
|
||||||
|
status: completed
|
||||||
|
- id: profile-fetch-unread
|
||||||
|
content: profile.ts 新增 unread 与 fetchUnread,onShow 中刷新并同步 tabBar
|
||||||
|
status: completed
|
||||||
|
dependencies:
|
||||||
|
- tabbar-set-unread
|
||||||
|
- id: profile-badge-ui
|
||||||
|
content: profile.wxml 通知行加数量徽标,profile.wxss 新增 menu-badge 样式
|
||||||
|
status: completed
|
||||||
|
dependencies:
|
||||||
|
- profile-fetch-unread
|
||||||
|
- id: verify-badge-flow
|
||||||
|
content: 用 [skill:lsp-code-analysis] 校验未读红点数据流与引用完整性
|
||||||
|
status: completed
|
||||||
|
dependencies:
|
||||||
|
- profile-badge-ui
|
||||||
|
---
|
||||||
|
|
||||||
|
## 产品概述
|
||||||
|
|
||||||
|
「我的」页底部 tabBar 的红色数字徽标当前只出现在 tab 图标上,用户看到红点却不知道来自哪个功能。本次在「我的」页面内对应的功能行(「通知」)上同步展示相同数量红点,让红点来源一目了然。
|
||||||
|
|
||||||
|
## 核心功能
|
||||||
|
|
||||||
|
- 「我的」页面「通知」一行右侧展示与 tabBar 一致的未读数量红点(超过 99 显示「99+」)
|
||||||
|
- 红点数量与 tabBar 完全同源(通知未读数),保证两处数字始终一致
|
||||||
|
- 进入或切回「我的」页时自动刷新未读数:在通知页读完消息返回后,行内红点与 tabBar 红点同步消失
|
||||||
|
- 未读数为 0 时该红点不渲染;接口失败时静默降级,不报错、不阻塞页面其他内容
|
||||||
|
- 其余功能行(我的额度、我的订单、我的收藏、额度明细)无独立未读数据源,保持原样
|
||||||
|
|
||||||
|
## 视觉与交互
|
||||||
|
|
||||||
|
- 「通知」行内、右侧箭头左侧新增红色胶囊数字徽标,样式与 tabBar 徽标统一(红底白字、圆角胶囊)
|
||||||
|
- 页面其余布局与交互不变
|
||||||
|
|
||||||
|
## 技术栈
|
||||||
|
|
||||||
|
- 微信小程序原生框架(TypeScript + WXML + WXSS),沿用现有 `utils/request.ts`、`utils/logger.ts`、`utils/config.ts`、`utils/tabbar.ts` 等工具模块,无新增依赖
|
||||||
|
|
||||||
|
## 实现方案
|
||||||
|
|
||||||
|
- 数据源唯一:未读数来自 `GET /notification/unread` 的 `unread_count`,与 `custom-tab-bar/index.ts` 的 `syncUnread()` 使用同一接口,缓存 key 复用 `STORAGE_KEYS.UNREAD`,避免出现两个红点数量不一致
|
||||||
|
- 页面侧新增 `fetchUnread()`:在 `profile.ts` 的 `onShow` 中调用(tab 页每次切回都会触发,天然满足「从通知页返回后刷新」的诉求),成功后 `setData({ unread })` 并写回 `STORAGE_KEYS.UNREAD` 缓存
|
||||||
|
- 复用既有同步模式:参考 `pages/notification/notification.ts` 的 `fetchUnread()`——拿到最新数量后直接更新 tabBar 实例(不发第二次请求)。当前 `utils/tabbar.ts` 只导出会触发请求的 `syncTabBarUnread()`,因此新增一个「用已知数量直接更新」的导出函数 `setTabBarUnread(count)`,与既有 `getTabBarInstance()` / `setTabBarSelected()` 风格保持一致,不改变 tabBar 组件本身
|
||||||
|
- 首帧安全:项目多处注释指出首帧渲染未结束就 setData 会触发「Expected updated data but get first rendering data」导致渲染失败。请求回调中的 setData 天然异步、安全;若要用缓存值立即渲染以减少红点出现延迟,必须放在 `wx.nextTick` 内(与 `pages/outfit/outfit.ts` 首次 onShow 的处理方式一致)
|
||||||
|
- 性能:单次网络请求(与 tabBar 自身的 30s 节流请求并行、互不干扰),无额外遍历或渲染开销;失败时静默降级,不重试、不阻塞
|
||||||
|
|
||||||
|
## 实现注意
|
||||||
|
|
||||||
|
- 只在已登录分支执行(`profile.onShow` 中 `auth.isLoggedIn()` 校验之后),未登录直接早返回,不会产生必然 401 的请求
|
||||||
|
- 不改动 `custom-tab-bar` 组件逻辑、`STORAGE_KEYS` 既有 key、以及页面其他功能行
|
||||||
|
- 日志沿用 `logger.debug/warn`,模块名保持 `const LOG = 'profile'`
|
||||||
|
- 徽标样式对齐 `custom-tab-bar/index.wxss` 的 `.tab-badge`(`#FF3B30` 底、白字、胶囊圆角),保持全局视觉统一
|
||||||
|
|
||||||
|
## 架构与数据流
|
||||||
|
|
||||||
|
简单链路补充,无需架构图。数据流:
|
||||||
|
`profile.onShow` → `fetchUnread()` → `GET /notification/unread` → `setData({ unread })`(渲染行内红点)+ 写缓存 `STORAGE_KEYS.UNREAD` + `setTabBarUnread(unread)`(tabBar 红点不发新请求即同步)
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
本次改动共涉及 4 个文件,均在现有架构内按既有模式修改:
|
||||||
|
|
||||||
|
```
|
||||||
|
miniprogram/
|
||||||
|
├── utils/
|
||||||
|
│ └── tabbar.ts # [MODIFY] 新增导出 setTabBarUnread(count: number):取 tabBar 实例并调用其 setUnread(已知数量),不发请求;取不到实例时静默跳过,风格对齐现有 syncTabBarUnread / setTabBarSelected
|
||||||
|
└── pages/
|
||||||
|
└── profile/
|
||||||
|
├── profile.ts # [MODIFY] data 新增 unread: 0;新增 fetchUnread()(请求 /notification/unread,成功 setData + 写 STORAGE_KEYS.UNREAD 缓存 + setTabBarUnread 同步,失败 logger.warn 静默降级);onShow 登录校验后调用;首帧用缓存值渲染时须包在 wx.nextTick 内;补充 setTabBarUnread 导入
|
||||||
|
├── profile.wxml # [MODIFY] 「通知」行在 menu-arrow 前插入 wx:if="{{unread > 0}}" 的数量徽标,文案 {{unread > 99 ? '99+' : unread}}
|
||||||
|
└── profile.wxss # [MODIFY] 新增 .menu-badge 样式:红色 #FF3B30 胶囊、白字、font-size 20rpx、line-height/min-width/height 对齐 tabBar 的 .tab-badge,margin-left: 12rpx、flex-shrink: 0,与 .menu-arrow 间距协调
|
||||||
|
```
|
||||||
|
|
||||||
|
## Agent Extensions
|
||||||
|
|
||||||
|
### Skill
|
||||||
|
|
||||||
|
- **lsp-code-analysis**
|
||||||
|
- Purpose: 校验未读红点数据流的调用链完整性——确认 `fetchUnread`、`setTabBarUnread`、`setUnread` 的引用关系正确,且「我的」页「通知」行绑定与 tabBar 红点数据源唯一,无遗漏或重复渲染路径
|
||||||
|
- Expected outcome: 输出 `setTabBarUnread` / `fetchUnread` / `onTapNotification` / `unread` 的引用清单,确认改动覆盖完整、无其他页面存在同类「红点来源不明」的遗留入口
|
||||||
@@ -3,6 +3,7 @@ import * as auth from '../../utils/auth'
|
|||||||
import { HoroscopeData } from '../../types/models'
|
import { HoroscopeData } from '../../types/models'
|
||||||
import { setTabBarSelected } from '../../utils/tabbar'
|
import { setTabBarSelected } from '../../utils/tabbar'
|
||||||
import { logger } from '../../utils/logger'
|
import { logger } from '../../utils/logger'
|
||||||
|
import { STORAGE_KEYS } from '../../utils/config'
|
||||||
|
|
||||||
// 日志模块名
|
// 日志模块名
|
||||||
const LOG = 'horoscope'
|
const LOG = 'horoscope'
|
||||||
@@ -117,9 +118,15 @@ Page({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onGoProfile() {
|
onGoProfile() {
|
||||||
|
// switchTab 不支持 query 传参,用 storage 标记让「我的」页 onShow 自动弹出编辑弹窗
|
||||||
|
wx.setStorageSync(STORAGE_KEYS.OPEN_PROFILE_EDIT, 1)
|
||||||
wx.switchTab({
|
wx.switchTab({
|
||||||
url: '/pages/profile/profile',
|
url: '/pages/profile/profile',
|
||||||
fail: (e) => logger.warn(LOG, 'switchTab 个人资料失败, err=', e && e.errMsg),
|
fail: (e) => {
|
||||||
|
logger.warn(LOG, 'switchTab 个人资料失败, err=', e && e.errMsg)
|
||||||
|
// 跳转失败时清除标记,避免下次进入「我的」页意外弹窗
|
||||||
|
wx.removeStorageSync(STORAGE_KEYS.OPEN_PROFILE_EDIT)
|
||||||
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -187,9 +187,15 @@ Page({
|
|||||||
cancelText: '稍后再说',
|
cancelText: '稍后再说',
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
|
// switchTab 不支持 query 传参,用 storage 标记让「我的」页 onShow 自动弹出编辑弹窗
|
||||||
|
wx.setStorageSync(STORAGE_KEYS.OPEN_PROFILE_EDIT, 1)
|
||||||
wx.switchTab({
|
wx.switchTab({
|
||||||
url: '/pages/profile/profile',
|
url: '/pages/profile/profile',
|
||||||
fail: (e) => logger.warn(LOG, 'switchTab 个人资料失败, err=', e && e.errMsg),
|
fail: (e) => {
|
||||||
|
logger.warn(LOG, 'switchTab 个人资料失败, err=', e && e.errMsg)
|
||||||
|
// 跳转失败时清除标记,避免下次进入「我的」页意外弹窗
|
||||||
|
wx.removeStorageSync(STORAGE_KEYS.OPEN_PROFILE_EDIT)
|
||||||
|
},
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.goAfterLogin()
|
this.goAfterLogin()
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import * as auth from '../../utils/auth'
|
|||||||
import { UserInfo, QuotaItem } from '../../types/models'
|
import { UserInfo, QuotaItem } from '../../types/models'
|
||||||
import { QuotaType, STORAGE_KEYS } from '../../utils/config'
|
import { QuotaType, STORAGE_KEYS } from '../../utils/config'
|
||||||
import { formatDate } from '../../utils/format'
|
import { formatDate } from '../../utils/format'
|
||||||
import { setTabBarSelected } from '../../utils/tabbar'
|
import { setTabBarSelected, setTabBarUnread } from '../../utils/tabbar'
|
||||||
import { logger } from '../../utils/logger'
|
import { logger } from '../../utils/logger'
|
||||||
|
|
||||||
// 日志模块名
|
// 日志模块名
|
||||||
@@ -31,6 +31,7 @@ Page({
|
|||||||
userInfo: {} as UserInfo,
|
userInfo: {} as UserInfo,
|
||||||
uploadRemain: 0,
|
uploadRemain: 0,
|
||||||
zodiac: '',
|
zodiac: '',
|
||||||
|
unread: 0,
|
||||||
editVisible: false,
|
editVisible: false,
|
||||||
avatarUploading: false,
|
avatarUploading: false,
|
||||||
avatarChanged: false,
|
avatarChanged: false,
|
||||||
@@ -64,8 +65,46 @@ Page({
|
|||||||
redirectToLogin()
|
redirectToLogin()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
this.consumeOpenEditMark()
|
||||||
this.fetchUser()
|
this.fetchUser()
|
||||||
this.fetchQuota()
|
this.fetchQuota()
|
||||||
|
this.fetchUnread()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 拉取未读数:与 tabBar 红点同源(/notification/unread),保证两处数量一致
|
||||||
|
fetchUnread() {
|
||||||
|
request<{ unread_count: number }>({ url: '/notification/unread', showError: false, silentAuth: true })
|
||||||
|
.then((res) => {
|
||||||
|
const unread = res.unread_count || 0
|
||||||
|
logger.debug(LOG, '未读数加载成功, unread=', unread)
|
||||||
|
// 写回缓存并同步 tabBar 红点(setUnread 内部只更新,不再发请求)
|
||||||
|
wx.setStorageSync(STORAGE_KEYS.UNREAD, unread)
|
||||||
|
this.setData({ unread })
|
||||||
|
setTabBarUnread(unread)
|
||||||
|
})
|
||||||
|
.catch((e: any) => logger.warn(LOG, '未读数加载失败(静默降级), code=', e && e.code))
|
||||||
|
},
|
||||||
|
|
||||||
|
// 消费「引导完善资料」标记:命中则自动弹出编辑弹窗(标记一次性,先清除再打开)
|
||||||
|
consumeOpenEditMark() {
|
||||||
|
if (!wx.getStorageSync(STORAGE_KEYS.OPEN_PROFILE_EDIT)) return
|
||||||
|
wx.removeStorageSync(STORAGE_KEYS.OPEN_PROFILE_EDIT)
|
||||||
|
logger.debug(LOG, '命中打开编辑弹窗标记,自动弹出资料编辑')
|
||||||
|
// 首帧渲染未结束就 setData 会触发「Expected updated data but get first rendering data」,
|
||||||
|
// 导致 webview 渲染失败(视觉上仍停留在上一页),故延迟到下一帧再打开
|
||||||
|
wx.nextTick(() => this.openEditFromGuide())
|
||||||
|
},
|
||||||
|
|
||||||
|
// 引导入口进入时自动打开编辑弹窗:fetchUser 未返回时用本地缓存兜底,避免表单为空
|
||||||
|
openEditFromGuide() {
|
||||||
|
if (!Object.keys(this.data.userInfo || {}).length) {
|
||||||
|
const cached = wx.getStorageSync(STORAGE_KEYS.USER_INFO)
|
||||||
|
if (cached && Object.keys(cached).length) {
|
||||||
|
logger.debug(LOG, '用户信息未就绪,使用本地缓存预填编辑表单')
|
||||||
|
this.setData({ userInfo: cached, zodiac: getZodiac(cached.birth_day) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.onEdit()
|
||||||
},
|
},
|
||||||
|
|
||||||
syncTabBar() {
|
syncTabBar() {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
<view class="menu-row hairline" bindtap="onTapNotification">
|
<view class="menu-row hairline" bindtap="onTapNotification">
|
||||||
<view class="icon icon-bell menu-icon"></view>
|
<view class="icon icon-bell menu-icon"></view>
|
||||||
<text class="menu-label">通知</text>
|
<text class="menu-label">通知</text>
|
||||||
|
<view wx:if="{{unread > 0}}" class="menu-badge">{{unread > 99 ? '99+' : unread}}</view>
|
||||||
<view class="icon icon-chevron-right menu-arrow"></view>
|
<view class="icon icon-chevron-right menu-arrow"></view>
|
||||||
</view>
|
</view>
|
||||||
<view class="menu-row hairline" bindtap="onTapCollect">
|
<view class="menu-row hairline" bindtap="onTapCollect">
|
||||||
|
|||||||
@@ -120,6 +120,21 @@
|
|||||||
color: #8E8E93;
|
color: #8E8E93;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu-badge {
|
||||||
|
min-width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
padding: 0 10rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
background: #FF3B30;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 20rpx;
|
||||||
|
line-height: 32rpx;
|
||||||
|
text-align: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
.menu-arrow {
|
.menu-arrow {
|
||||||
width: 28rpx;
|
width: 28rpx;
|
||||||
height: 28rpx;
|
height: 28rpx;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ export const STORAGE_KEYS = {
|
|||||||
USER_INFO: 'zt_closet_user_info',
|
USER_INFO: 'zt_closet_user_info',
|
||||||
UNREAD: 'zt_closet_unread',
|
UNREAD: 'zt_closet_unread',
|
||||||
OPEN_COLLECT: 'zt_open_collect',
|
OPEN_COLLECT: 'zt_open_collect',
|
||||||
|
OPEN_PROFILE_EDIT: 'zt_open_profile_edit',
|
||||||
}
|
}
|
||||||
|
|
||||||
// 衣物图片处理状态
|
// 衣物图片处理状态
|
||||||
|
|||||||
@@ -17,6 +17,12 @@ export function syncTabBarUnread(force = true): void {
|
|||||||
if (tabBar && typeof tabBar.syncUnread === 'function') tabBar.syncUnread(force)
|
if (tabBar && typeof tabBar.syncUnread === 'function') tabBar.syncUnread(force)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 用已知数量直接更新红点:不发请求,供页面拉到最新未读数后同步 tabBar
|
||||||
|
export function setTabBarUnread(count: number): void {
|
||||||
|
const tabBar = getTabBarInstance()
|
||||||
|
if (tabBar && typeof tabBar.setUnread === 'function') tabBar.setUnread(count)
|
||||||
|
}
|
||||||
|
|
||||||
// 更新选中态:走 tabBar 的 setSelected(内部保证首帧安全),
|
// 更新选中态:走 tabBar 的 setSelected(内部保证首帧安全),
|
||||||
// 老版本实例没有该方法时降级为 setData
|
// 老版本实例没有该方法时降级为 setData
|
||||||
export function setTabBarSelected(index: number): void {
|
export function setTabBarSelected(index: number): void {
|
||||||
|
|||||||
Reference in New Issue
Block a user