# 站内消息 — 前端技术方案（C 端 · shop-app）

> **依据：** 《站内消息功能需求.md》v1.0、《站内消息技术方案.md》v1.0  
> **关联：** 《我的服务前端技术方案》（入驻申请详情跳转）  
> **范围：** 消费者 APP **`shop-app`** 未读红点、消息列表、消息详情、已读标记与入驻类跳转；**不** 改后端、**不** 修改同目录下既有技术/需求文档。  
> **实现状态：** 页面与 API 已落地（v1.0）；待与 `/api/member/message/**` 联调。

---

## 1. 技术栈与约定

| 项 | 说明 |
|----|------|
| 框架 | uni-app **Vue 3** + **uview-plus** |
| 请求 | `@/utils/request`；列表为 **`TableDataInfo`**（`rows` + `total`） |
| 鉴权 | **须登录**；`ensureApiToken` / `navigateMinePage` |
| 已读 | **打开详情接口** 即标记已读（MM2）；列表滑动 **不** 批量已读 |
| 本期类型 | 仅 **入驻审核**（`ENTRY_AUDIT` / `MERCHANT_ENTRY` 跳转） |

---

## 2. 页面与路由

| 页面 | 路径 | 入口 |
|------|------|------|
| 消息列表 | `subpackage/account/message-list` | 我的 Tab →「站内消息」 |
| 消息详情 | `subpackage/account/message-detail` | 列表点击行 |

**Query：**

| 页面 | 参数 |
|------|------|
| 消息详情 | `messageId=123` |

**路径常量：**

```javascript
// utils/pageRoute.js
export const PAGE_MESSAGE_LIST = '/subpackage/account/message-list'
export const PAGE_MESSAGE_DETAIL = '/subpackage/account/message-detail'
```

**分包：** `pages.json` → `pkg-account` 注册 `message-list`、`message-detail`。

---

## 3. 文件清单

| 类型 | 路径 | 说明 |
|------|------|------|
| 列表页 | `shop-app/subpackage/account/message-list.vue` | 分页、下拉刷新、空态 |
| 详情页 | `shop-app/subpackage/account/message-detail.vue` | 正文、入驻跳转 |
| 列表行 | `shop-app/components/message/MessageListItem.vue` | 未读圆点、摘要、驳回醒目 |
| API | `shop-app/api/message.js` | unread-count / list / detail |
| 常量 | `shop-app/constants/message.js` | 分页、业务类型 |
| 映射 | `shop-app/utils/messageDisplay.js` | 列表/详情 VO → 页面模型 |
| 导航 | `shop-app/utils/messageNav.js` | 列表/详情/入驻跳转 |
| 我的 Tab | `shop-app/pages/mine/index.vue` | 「消息中心」菜单 + 未读角标 |

---

## 4. 接口封装

### 4.1 `api/message.js`

| 方法 | HTTP | 路径 | 说明 |
|------|------|------|------|
| `getMessageUnreadCount()` | GET | `/api/member/message/unread-count` | 红点/角标 |
| `listMessages(params)` | GET | `/api/member/message/list` | 分页列表 |
| `getMessageDetail(messageId)` | GET | `/api/member/message/{messageId}` | 详情 + **标记已读** |

**list params：**

```javascript
{ pageNum: 1, pageSize: 10 }
```

**unread-count data：**

```javascript
{ unreadCount: 2 }
```

**列表 rows[] 主要字段：**

| 字段 | 前端用途 |
|------|----------|
| messageId | 详情 query |
| title | 标题；未读加粗 |
| summary | 摘要（服务端截断） |
| readFlag | `0` 未读 / `1` 已读 |
| createTime | 接收时间 |
| bizType / bizId | 跳转上下文 |

**详情 data 扩展：**

| 字段 | 说明 |
|------|------|
| content | 完整正文 |
| linkType | `MERCHANT_ENTRY` → 入驻详情 |
| linkAvailable | `false` 时仅展示正文 |

---

## 5. 页面逻辑

### 5.1 个人中心 · 未读角标

```text
mine onShow（已登录）
    → getMessageUnreadCount()
    → messageUnreadCount → 「站内消息」菜单右侧数字角标（0 隐藏，99+ 封顶）
```

### 5.2 消息列表

```text
message-list onShow
    → ensureApiToken
    → listMessages({ pageNum, pageSize })
    → mapMessageList → MessageListItem 渲染
    → 下拉刷新 / 上拉加载更多
    → 点击行 → message-detail?messageId=
```

| 展示规则 | 说明 |
|----------|------|
| 未读 | 左侧红点 + 标题加粗 + 浅绿底 |
| 驳回类 | 标题含「未通过」→ 摘要橙色 |
| 空态 | 「暂无消息」+「入驻审核结果将在此通知您」 |

### 5.3 消息详情

```text
onLoad(messageId) → onShow → getMessageDetail(messageId)
    → 后端标记已读（MM2）
    → 展示 title / createTime / content（长文可滚动）
    → linkType=MERCHANT_ENTRY 且 linkAvailable
         → 底栏「查看入驻申请」→ entry-detail?applyId=bizId
    → linkAvailable=false → 提示「关联申请已不存在」
```

### 5.4 返回列表后红点更新

```text
从详情返回 → message-list onShow 重新拉列表
我的 Tab onShow → 重新 getMessageUnreadCount
```

---

## 6. 展示映射 `messageDisplay.js`

```javascript
export function mapMessageListRow(row) {
  return {
    messageId: row.messageId,
    title: row.title,
    summary: row.summary,
    unread: row.readFlag === '0',
    createTime: row.createTime,
    isReject: (row.title || '').includes('未通过')
  }
}

export function mapMessageDetail(data) {
  return {
    ...data,
    showEntryLink: data.linkType === 'MERCHANT_ENTRY' && data.linkAvailable !== false
  }
}
```

---

## 7. 与「我的入驻」衔接

| 消息场景 | 跳转 |
|----------|------|
| 公示中 / 入驻完成 / 审核未通过 | `PAGE_ENTRY_DETAIL?applyId={bizId}` |

入驻详情页已有 `applyId` 入参，与消息 `bizId` 对齐。

---

## 8. 联调检查清单

| # | 场景 |
|---|------|
| F1 | 未登录点「站内消息」→ 引导登录 |
| F2 | 有未读时我的页显示角标；已读后角标消失 |
| F3 | 列表按时间倒序；未读/已读样式区分 |
| F4 | 打开详情后该条变已读；未读数减 1 |
| F5 | 驳回消息摘要/正文醒目 |
| F6 | 「查看入驻申请」跳转正确 applyId |
| F7 | linkAvailable=false 时不跳转、有提示 |
| F8 | 空列表友好文案 |

---

## 9. 非本期

| 项 | 说明 |
|----|------|
| 订单/物流/售后消息 | 后端扩展 `biz_type` 后另册 |
| Tab 分类、搜索、删除、全部已读 | 需求非本期 |
| App Push / 短信 | 非本期 |
| 首页/TabBar 全局消息图标 | 产品可选；当前仅 **我的** 入口 |

---

## 10. 修订记录

| 版本 | 说明 |
|------|------|
| **v1.0** | 首版：列表/详情、API、我的入口角标、入驻跳转、前端技术方案 |

---

*文档版本：v1.0 · 工程目录 `shop-app` · 不修改《站内消息技术方案.md》（后端方案）*
