|
|
@@ -0,0 +1,247 @@
|
|
|
+# OA 五列表 · 折角序号 + 滚动分页加固 Implementation Plan
|
|
|
+
|
|
|
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
|
+
|
|
|
+**Goal:** 五个 OA 列表统一左上折角序号(方案 A),并加固触底滚动分页可触发性。
|
|
|
+
|
|
|
+**Architecture:** `formatCornerIndex` 纯函数 + 全局 `.dd-card__corner` 样式;五页模板在 `.dd-card` 内插入折角并用累计 `list` 下标;`pages.json` 为五页补 `onReachBottomDistance`。分页数据逻辑已存在,不重写。
|
|
|
+
|
|
|
+**Tech Stack:** uni-app(mobile-h5)、SCSS、Node assert
|
|
|
+
|
|
|
+**Spec:** `docs/superpowers/specs/2026-08-13-oa-list-corner-index-pagination-design.md`
|
|
|
+**Demo:** `mobile-ui/zkxw-mobile-oa-mine-card-index-badge-demo.html`(A)
|
|
|
+**取代计划:** `docs/superpowers/plans/2026-08-13-oa-mine-card-corner-index.md`(仅 mine)
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## File map
|
|
|
+
|
|
|
+| 文件 | 职责 |
|
|
|
+|------|------|
|
|
|
+| Create: `mobile-h5/utils/oa-corner-index.js` | 序号文案 |
|
|
|
+| Create: `mobile-h5/utils/oa-corner-index.test.js` | 单测 |
|
|
|
+| Modify: `mobile-h5/styles/components/oa-task-list.scss` | 全局折角样式 |
|
|
|
+| Modify: `mobile-h5/pages.json` | 五页 `onReachBottomDistance: 80` |
|
|
|
+| Modify: `mobile-h5/pages/oa/{drafts,pending,done,mine,cc}/index.vue` | 折角 DOM + `cornerIndex` |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 1: `formatCornerIndex`(TDD)
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Create: `mobile-h5/utils/oa-corner-index.js`
|
|
|
+- Create: `mobile-h5/utils/oa-corner-index.test.js`
|
|
|
+
|
|
|
+- [ ] **Step 1: 写失败单测**
|
|
|
+
|
|
|
+```js
|
|
|
+// mobile-h5/utils/oa-corner-index.test.js
|
|
|
+import assert from 'node:assert/strict'
|
|
|
+import { formatCornerIndex } from './oa-corner-index.js'
|
|
|
+
|
|
|
+assert.equal(formatCornerIndex(1), '01')
|
|
|
+assert.equal(formatCornerIndex(9), '09')
|
|
|
+assert.equal(formatCornerIndex(10), '10')
|
|
|
+assert.equal(formatCornerIndex(11), '11')
|
|
|
+assert.equal(formatCornerIndex(99), '99')
|
|
|
+assert.equal(formatCornerIndex(100), '100')
|
|
|
+
|
|
|
+console.log('oa-corner-index: ok')
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 2: 跑测确认失败**
|
|
|
+
|
|
|
+```bash
|
|
|
+cd mobile-h5 && node utils/oa-corner-index.test.js
|
|
|
+```
|
|
|
+
|
|
|
+Expected: module not found / 失败。
|
|
|
+
|
|
|
+- [ ] **Step 3: 实现**
|
|
|
+
|
|
|
+```js
|
|
|
+// mobile-h5/utils/oa-corner-index.js
|
|
|
+/**
|
|
|
+ * @param {number} n 从 1 起的序号
|
|
|
+ * @returns {string}
|
|
|
+ */
|
|
|
+export function formatCornerIndex(n) {
|
|
|
+ const num = Number(n)
|
|
|
+ if (!Number.isFinite(num) || num < 1) return '01'
|
|
|
+ const i = Math.floor(num)
|
|
|
+ if (i < 10) return '0' + i
|
|
|
+ return String(i)
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 4: 跑测通过**
|
|
|
+
|
|
|
+```bash
|
|
|
+cd mobile-h5 && node utils/oa-corner-index.test.js
|
|
|
+```
|
|
|
+
|
|
|
+Expected: `oa-corner-index: ok`
|
|
|
+
|
|
|
+- [ ] **Step 5: Commit**
|
|
|
+
|
|
|
+```bash
|
|
|
+git add mobile-h5/utils/oa-corner-index.js mobile-h5/utils/oa-corner-index.test.js
|
|
|
+git commit -m "$(cat <<'EOF'
|
|
|
+feat(mobile-h5): add formatCornerIndex for OA list corner badges.
|
|
|
+
|
|
|
+EOF
|
|
|
+)"
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 2: 全局折角样式 + 触底距离
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Modify: `mobile-h5/styles/components/oa-task-list.scss`
|
|
|
+- Modify: `mobile-h5/pages.json`
|
|
|
+
|
|
|
+- [ ] **Step 1: 在 `oa-task-list.scss` 末尾追加**
|
|
|
+
|
|
|
+```scss
|
|
|
+/* 钉钉风列表卡 · 左上折角序号(五中心共用) */
|
|
|
+.dd-card {
|
|
|
+ position: relative;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.dd-card__corner {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 0;
|
|
|
+ height: 0;
|
|
|
+ border-style: solid;
|
|
|
+ border-width: 68rpx 68rpx 0 0;
|
|
|
+ border-color: #0a9f6d transparent transparent transparent;
|
|
|
+ pointer-events: none;
|
|
|
+ z-index: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.dd-card__corner-num {
|
|
|
+ position: absolute;
|
|
|
+ top: -60rpx;
|
|
|
+ left: 8rpx;
|
|
|
+ font-size: 20rpx;
|
|
|
+ font-weight: 800;
|
|
|
+ line-height: 1;
|
|
|
+ color: #fff;
|
|
|
+ letter-spacing: -0.02em;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+说明:`App.vue` 已 `@import` 本文件,无需改各页 scoped 重复写折角色。
|
|
|
+
|
|
|
+- [ ] **Step 2: `pages.json` — 五页 style 增加触底距离**
|
|
|
+
|
|
|
+对以下 path 的 `style` 对象各加一行 `"onReachBottomDistance": 80`(与现有 `enablePullDownRefresh` 并列):
|
|
|
+
|
|
|
+- `pages/oa/drafts/index`
|
|
|
+- `pages/oa/pending/index`
|
|
|
+- `pages/oa/done/index`
|
|
|
+- `pages/oa/mine/index`
|
|
|
+- `pages/oa/cc/index`
|
|
|
+
|
|
|
+- [ ] **Step 3: Commit**
|
|
|
+
|
|
|
+```bash
|
|
|
+git add mobile-h5/styles/components/oa-task-list.scss mobile-h5/pages.json
|
|
|
+git commit -m "$(cat <<'EOF'
|
|
|
+feat(mobile-h5): add shared OA card corner styles and reach-bottom distance.
|
|
|
+
|
|
|
+EOF
|
|
|
+)"
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 3: 五页模板接入折角
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Modify: `mobile-h5/pages/oa/drafts/index.vue`
|
|
|
+- Modify: `mobile-h5/pages/oa/pending/index.vue`
|
|
|
+- Modify: `mobile-h5/pages/oa/done/index.vue`
|
|
|
+- Modify: `mobile-h5/pages/oa/mine/index.vue`
|
|
|
+- Modify: `mobile-h5/pages/oa/cc/index.vue`
|
|
|
+
|
|
|
+每页做相同三件事(草稿/待办/抄送的 `v-for` 在 row 上,折角仍放在内层 `.dd-card`)。
|
|
|
+
|
|
|
+- [ ] **Step 1: `mine/index.vue`**
|
|
|
+
|
|
|
+1. `v-for="(row, idx) in list"`
|
|
|
+2. 在 `.dd-card` 内最前插入:
|
|
|
+
|
|
|
+```vue
|
|
|
+ <view class="dd-card__corner" aria-hidden="true">
|
|
|
+ <text class="dd-card__corner-num">{{ cornerIndex(idx) }}</text>
|
|
|
+ </view>
|
|
|
+```
|
|
|
+
|
|
|
+3. script:
|
|
|
+
|
|
|
+```js
|
|
|
+ import { formatCornerIndex } from '../../../utils/oa-corner-index.js'
|
|
|
+```
|
|
|
+
|
|
|
+```js
|
|
|
+ cornerIndex(idx) {
|
|
|
+ return formatCornerIndex(Number(idx) + 1)
|
|
|
+ },
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 2: `done/index.vue`** — 同 Step 1(结构与 mine 最接近)
|
|
|
+
|
|
|
+- [ ] **Step 3: `drafts/index.vue`**
|
|
|
+
|
|
|
+`v-for="(row, idx) in list"` 在 `.draft-row` 上;折角放进内层 `.dd-card` 开头;同样 import + `cornerIndex`。
|
|
|
+
|
|
|
+- [ ] **Step 4: `pending/index.vue`** — 同 drafts(`.pending-row` + 内层 `.dd-card`)
|
|
|
+
|
|
|
+- [ ] **Step 5: `cc/index.vue`** — 同 pending(管理多选行 + 内层 `.dd-card`)
|
|
|
+
|
|
|
+- [ ] **Step 6: 手工验收**
|
|
|
+
|
|
|
+| 页 | 路径 | 检查 |
|
|
|
+|----|------|------|
|
|
|
+| 草稿箱 | `/#/pages/oa/drafts/index` | 折角 + 触底 + 搜索重置 `01` |
|
|
|
+| 待办 | `/#/pages/oa/pending/index` | 同上;管理勾选不受折角影响 |
|
|
|
+| 已办 | `/#/pages/oa/done/index` | 同上 |
|
|
|
+| 我发起的 | `/#/pages/oa/mine/index` | 同上;长按仍可用 |
|
|
|
+| 抄送 | `/#/pages/oa/cc/index` | 同上;未读点仍可见 |
|
|
|
+
|
|
|
+- [ ] **Step 7: Commit**
|
|
|
+
|
|
|
+```bash
|
|
|
+git add \
|
|
|
+ mobile-h5/pages/oa/drafts/index.vue \
|
|
|
+ mobile-h5/pages/oa/pending/index.vue \
|
|
|
+ mobile-h5/pages/oa/done/index.vue \
|
|
|
+ mobile-h5/pages/oa/mine/index.vue \
|
|
|
+ mobile-h5/pages/oa/cc/index.vue
|
|
|
+git commit -m "$(cat <<'EOF'
|
|
|
+feat(mobile-h5): show corner index on all five OA task list cards.
|
|
|
+
|
|
|
+EOF
|
|
|
+)"
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Spec coverage
|
|
|
+
|
|
|
+| Spec | Task |
|
|
|
+|------|------|
|
|
|
+| 折角样式 / `#0a9f6d` / 补零规则 | Task 1–2 |
|
|
|
+| 五页序号 | Task 3 |
|
|
|
+| 滚动分页保持 + 触底距离 | Task 2 Step 2 + 既有 `loadList` |
|
|
|
+| 搜索重置从 01 | 既有 reset + `idx` |
|
|
|
+| 管理多选不挡 | 折角在 card 内、`pointer-events: none` |
|
|
|
+
|
|
|
+## Out of scope
|
|
|
+
|
|
|
+- 金额角标、状态变色折角、后端改动、Web 端
|