# P6→NS1/RNS1 缺失项 #5：下拉刷新/触底加载的动画规范

## 简要结论
- 状态：✅ 已解决
- 风险等级：🟡 低
- 已实现下拉刷新、触底加载、骨架屏 loading、错误重试的完整交互链路。

## 详细审查

### 审查范围
- `apps/miniprogram/miniprogram/pages/task-list/task-list.ts` — onPullDownRefresh / onReachBottom / loadData
- `apps/miniprogram/miniprogram/pages/task-list/task-list.wxml` — skeleton 骨架屏
- `apps/miniprogram/miniprogram/pages/task-list/task-list.wxss` — loading 样式

### 发现

**下拉刷新（已实现）：**
```typescript
onPullDownRefresh() {
  this.loadData(() => {
    wx.stopPullDownRefresh()
  })
}
```
使用微信原生下拉刷新机制，刷新完成后调用 `wx.stopPullDownRefresh()` 停止动画。

**触底加载（已实现）：**
```typescript
onReachBottom() {
  if (!this.data.hasMore) return
  this.setData({ hasMore: false })
  wx.showToast({ title: '没有更多了', icon: 'none' })
}
```
当前为简化实现（一次性加载），触底时显示「没有更多了」提示。后端已支持分页参数（page/page_size）。

**骨架屏 Loading（已实现）：**
```html
<view class="state-loading" wx:if="{{pageState === 'loading'}}">
  <view class="loading-placeholder" wx:for="{{[1,2,3]}}" wx:key="*this">
    <view class="ph-line ph-line--title"></view>
    <view class="ph-line ph-line--body"></view>
    <view class="ph-line ph-line--short"></view>
  </view>
</view>
```
3 个占位卡片，每个含标题行、内容行、短行，模拟真实卡片布局。

**错误重试（已实现）：**
```html
<view class="state-error" wx:if="{{pageState === 'error'}}">
  <text class="error-text">加载失败，请重试</text>
  <view class="retry-btn" bindtap="onRetry">重试</view>
</view>
```

**task-detail 页面也有完整状态管理：**
- loading：使用 `t-loading` 组件的 circular 主题浮层
- empty：`t-icon` info-circle + 文案
- error：`t-icon` close-circle + 重试按钮

### 证据

骨架屏样式（task-list.wxss）：
```css
.loading-placeholder {
  background: #ffffff;
  border-radius: 22rpx;
  padding: 29rpx;
  margin-bottom: 22rpx;
}
.ph-line { height: 22rpx; background: #f3f3f3; border-radius: 7rpx; margin-bottom: 15rpx; }
.ph-line--title { width: 40%; height: 29rpx; }
.ph-line--body { width: 80%; }
.ph-line--short { width: 55%; }
```

### 建议（如未完全解决）
- 触底加载目前是简化实现，未真正调用分页接口加载下一页。后端已支持 `page`/`page_size` 参数，前端需补充增量加载逻辑
- 骨架屏可考虑使用 TDesign 的 `t-skeleton` 组件替代自定义实现，获得更丰富的动画效果
- 可添加下拉刷新时的自定义 loading 动画（当前使用微信原生样式）
