Files
jiapuapp/docs/superpowers/plans/2026-07-13-a01-login-guide.md
T
2026-07-13 12:23:10 +08:00

323 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# A-01 启动/登录引导页 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:executing-plans` to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 新增不接接口的 A-01 登录方式选择页,以账号密码为主入口,并要求用户主动勾选协议后才允许进入已设计完成的下一页。
**Architecture:** A-01 使用独立的 `pages/auth/entry.vue`,不改动现有 `pages/auth/login.vue` 的临时密码登录骨架,避免破坏现有核心流程合同。页面状态只包含 `consented` 和点击守卫;视觉由现有本地纸纹、朱砂红头、祠堂线描与山水资产组合,微信图标以本地透明 PNG 引入。A-02/A-03 的最终跳转仅在两页都完成设计并注册路由后接通。
**Tech Stack:** uni-app、Vue 3 `<script setup>`、SCSS、PowerShell 静态合同测试、本地 PNG/JPG 资产。
## Global Constraints
- 仅 Android 手机端视觉和本地交互;不调用 `appApi`、不接真实微信授权、短信服务或后端接口。
- A-01 只能有账号密码、手机号验证码、微信三个入口;不得出现注册、忘记密码、输入框、底部 Tab 或“登录即表示同意”。
- 协议默认未勾选;未勾选点击任一登录入口必须阻止跳转并提示;协议文字分别可点击。
- 账号密码是唯一朱砂实底主按钮;手机号验证码、微信为同层纸白古金描边按钮;微信标识不可改色。
- 只使用项目本地资产;第三方品牌 PNG 必须写入 D1 的来源、用途、路径与透明角检查记录。
- 页面视觉先于接口;在 A-02、A-03 设计与路由完成前,不得把 A-01 接到临时或错误的登录页。
## Execution Gate
本计划的视觉与协议部分可以在 A-01 实施时执行;**实际 `navigateTo` 跳转必须等 A-02、A-03 的页面设计获批、对应路由存在后再执行**。这是《规划.md》“页面全部设计后再处理接口/跨页联动”的硬约束,而不是兼容分支。
---
### Task 1: 先建立 A-01 静态合同测试
**Files:**
- Create: `tests/a01-login-guide-contract.ps1`
- Modify: none
**Interfaces:**
- Consumes: `pages.json`、未来的 `pages/auth/entry.vue``docs/design/D1_安卓视觉规范与页面壳.md`
- Produces: `tests/a01-login-guide-contract.ps1`,输出 `PASS A-01 login guide contract`
- [ ] **Step 1: 写入先失败的合同测试**
```powershell
$ErrorActionPreference = 'Stop'
$root = Split-Path -Parent $PSScriptRoot
$pages = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'pages.json') | ConvertFrom-Json
$paths = @($pages.pages | ForEach-Object { $_.path })
if ($paths[0] -ne 'pages/auth/entry') { throw 'A-01 is not the application entry route.' }
if ('pages/auth/entry' -notin $paths) { throw 'Missing A-01 route.' }
$entry = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'pages/auth/entry.vue')
foreach ($copy in @('账号密码登录', '手机号验证码登录', '微信登录', '我已阅读并同意《用户协议》与《隐私政策》')) {
if (-not $entry.Contains($copy)) { throw "Missing A-01 copy: $copy" }
}
foreach ($forbidden in @('登录即表示同意', '注册账号', '忘记密码', 'appApi', 'calcMD5', '<input')) {
if ($entry.Contains($forbidden)) { throw "Forbidden A-01 content: $forbidden" }
}
if ($entry -notmatch 'const consented = ref\(false\)') { throw 'A-01 consent must default to false.' }
if ($entry -notmatch 'if \(!consented\.value\)') { throw 'A-01 does not block unchecked login.' }
if ($entry -notmatch '请先阅读并同意相关协议') { throw 'A-01 has no unchecked-consent prompt.' }
foreach ($asset in @('header-cinnabar-texture-v2.jpg', 'header-hall-lineart.png', 'paper-rice-texture-v2.jpg', 'footer-mountain-bamboo.png', 'wechat-login.png')) {
if (-not $entry.Contains($asset)) { throw "A-01 does not consume required asset: $asset" }
}
$d1 = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'docs/design/D1_安卓视觉规范与页面壳.md')
foreach ($token in @('wechat-login.png', 'A-01')) {
if (-not $d1.Contains($token)) { throw "D1 brand-asset record is missing: $token" }
}
Write-Output 'PASS A-01 login guide contract'
```
- [ ] **Step 2: 运行测试,确认当前因路由与页面缺失而失败**
Run: `powershell -ExecutionPolicy Bypass -File tests\a01-login-guide-contract.ps1`
Expected: FAIL with `A-01 is not the application entry route.` or missing `pages/auth/entry.vue`.
- [ ] **Step 3: 提交测试合同**
```powershell
git add tests/a01-login-guide-contract.ps1
git commit -m "test: define A01 login guide contract"
```
### Task 2: 准备并登记 A-01 本地资产
**Files:**
- Create: `static/assets/icons/brand/wechat-login.png`
- Modify: `docs/design/D1_安卓视觉规范与页面壳.md`
- Test: `tests/a01-login-guide-contract.ps1`
**Interfaces:**
- Consumes: D1 的第三方品牌资产规则与现有 `static/assets/backgrounds/header-cinnabar-texture-v2.jpg``header-hall-lineart.png``paper-rice-texture-v2.jpg``footer-mountain-bamboo.png`
- Produces: `wechat-login.png`RGBA 透明 PNG)及 D1 中唯一的品牌资产记录
- [ ] **Step 1: 取得微信官方或许可渠道的透明 PNG,并保存为 `static/assets/icons/brand/wechat-login.png`**
资产要求:图形为官方绿色微信标识;无文字、无白底、无阴影;四角透明;实际显示 `44rpx` 时清晰。不得从用户截图、整页效果图或生成图裁切。
- [ ] **Step 2: 在 D1 的第三方品牌资产记录中追加唯一一行**
使用 Step 1 实际下载的页面 URL 写入来源栏,并在同一行写明“RGBA,四角透明”。下载页没有可验证的授权或使用说明时,停止本任务,不得改用截图、生成图或未知来源图标。
- [ ] **Step 3: 运行透明角检查**
```powershell
Add-Type -AssemblyName System.Drawing
$image = [System.Drawing.Bitmap]::new('static/assets/icons/brand/wechat-login.png')
try {
if (-not [System.Drawing.Image]::IsAlphaPixelFormat($image.PixelFormat)) { throw 'WeChat icon has no alpha channel.' }
if ($image.GetPixel(0, 0).A -ne 0) { throw 'WeChat icon top-left corner is not transparent.' }
if ($image.Width -lt 48 -or $image.Height -lt 48) { throw 'WeChat icon is too small for mobile display.' }
Write-Output 'PASS WeChat login asset alpha audit'
} finally {
$image.Dispose()
}
```
Expected: `PASS WeChat login asset alpha audit`.
- [ ] **Step 4: 重跑 A-01 合同,确认它仍仅因页面尚未实现失败**
Run: `powershell -ExecutionPolicy Bypass -File tests\a01-login-guide-contract.ps1`
Expected: FAIL with missing A-01 route or page; it must not report a missing brand-asset record.
- [ ] **Step 5: 提交资产与 D1 记录**
```powershell
git add static/assets/icons/brand/wechat-login.png docs/design/D1_安卓视觉规范与页面壳.md
git commit -m "assets: add local WeChat login mark"
```
### Task 3: 实现 A-01 独立欢迎页与协议显式同意
**Files:**
- Create: `pages/auth/entry.vue`
- Modify: `pages.json`
- Test: `tests/a01-login-guide-contract.ps1`
**Interfaces:**
- Consumes: Task 2 的 `wechat-login.png`,现有朱砂红头、祠堂线描、纸纹、山水资产
- Produces: `pages/auth/entry.vue`,其状态名固定为 `consented`,点击守卫固定为 `enterLogin`
- [ ] **Step 1: 在 `pages.json` 的第一项新增 A-01 路由**
```json
{
"path": "pages/auth/entry",
"style": { "navigationStyle": "custom", "enablePullDownRefresh": false }
}
```
保留现有 `pages/auth/login` 路由与其顺序关系,不删除或重命名现有页面。
- [ ] **Step 2: 创建 `pages/auth/entry.vue` 的状态与协议守卫**
```vue
<script setup>
import { ref } from 'vue'
const consented = ref(false)
const toggleConsent = () => {
consented.value = !consented.value
}
const openAgreement = (name) => {
uni.showToast({ title: `${name}将在协议页开放`, icon: 'none' })
}
const enterLogin = (entry) => {
if (!consented.value) {
uni.showToast({ title: '请先阅读并同意相关协议', icon: 'none' })
return
}
uni.showToast({ title: `${entry}入口已确认`, icon: 'none' })
}
</script>
```
本任务阶段不得引入 `appApi``calcMD5`、真实登录、真实微信授权或不存在的 A-02/A-03 路由;跨页跳转在 Task 5 的执行门槛满足后替换。
- [ ] **Step 3: 写入页面主体,保持三种入口与显式复选框**
```vue
<template>
<view class="auth-entry-page">
<view class="auth-hero"><image class="auth-hall" src="/static/assets/backgrounds/header-hall-lineart.png" mode="aspectFit" /><image class="auth-seal" src="/static/assets/icons/brand/jiapu-seal-logo.png" mode="aspectFit" /></view>
<view class="auth-paper">
<image class="auth-side-ink" src="/static/assets/backgrounds/footer-mountain-bamboo.png" mode="aspectFit" />
<view class="auth-title"><text>家谱</text><text>为家族留存可传承的记忆</text></view>
<view class="auth-actions">
<button class="auth-button auth-button--primary" @click="enterLogin('账号密码登录')">账号密码登录</button>
<button class="auth-button" @click="enterLogin('手机号验证码登录')">手机号验证码登录</button>
<button class="auth-button" @click="enterLogin('微信登录')"><image src="/static/assets/icons/brand/wechat-login.png" mode="aspectFit" />微信登录</button>
</view>
<view class="auth-consent" @click="toggleConsent"><view class="auth-checkbox" :class="{ 'auth-checkbox--checked': consented }" /><text>我已阅读并同意</text><text class="auth-link" @click.stop="openAgreement('用户协议')">用户协议</text><text></text><text class="auth-link" @click.stop="openAgreement('隐私政策')">隐私政策</text></view>
</view>
</view>
</template>
```
- [ ] **Step 4: 完成最小 SCSS 外观**
要求:用 `background-image` 组合 `header-cinnabar-texture-v2.jpg``paper-rice-texture-v2.jpg`;红头可见祠堂线描;纸面底部可见但低对比的 `footer-mountain-bamboo.png`;按钮高度至少 `88rpx`;不使用 CSS Grid、`gap``clip-path`、滤镜或外部 URL。协议区域不得使用“登录即表示同意”文案,未选中复选框只显示古金圆圈,选中后显示朱砂对勾。
- [ ] **Step 5: 运行合同测试,确认通过**
Run: `powershell -ExecutionPolicy Bypass -File tests\a01-login-guide-contract.ps1`
Expected: `PASS A-01 login guide contract`.
- [ ] **Step 6: 做一次静态构建健康检查**
Run: `powershell -ExecutionPolicy Bypass -File tests\compile-audit.ps1`
Expected: `PASS compile audit`.
- [ ] **Step 7: 提交独立 A-01 页面**
```powershell
git add pages/auth/entry.vue pages.json tests/a01-login-guide-contract.ps1
git commit -m "feat: add A01 login guide"
```
### Task 4: 视觉验收与设计状态记录
**Files:**
- Modify: `docs/规划.md`
- Test: `tests/a01-login-guide-contract.ps1`, HBuilderX Android 小屏预览
**Interfaces:**
- Consumes: Task 3 完成的页面与合同
- Produces: D2 阶段下 A-01 的真实设计状态
- [ ] **Step 1: 在 HBuilderX 中预览 `pages/auth/entry` 的 `360 × 800dp` 画面**
检查:红头、标题、三个按钮和未勾选协议同时可见;账号密码为唯一红色主操作;宣纸与山水不压住协议;没有底部 Tab。
- [ ] **Step 2: 手动验证两种协议状态**
1. 初始未勾选,分别点击三个入口,均显示“请先阅读并同意相关协议”,且不跳转。
2. 勾选后复选框显示朱砂对勾;三个入口只显示本地确认提示,不请求网络。
- [ ] **Step 3: 仅在上述视觉和手动检查通过后更新 `docs/规划.md`**
`A-01 启动 / 登录引导页` 改为“视觉完成(已验收)”;D2 保持“进行中”,因为 A-02 至 A-06 尚未完成。
- [ ] **Step 4: 重跑最终验证**
Run:
```powershell
powershell -ExecutionPolicy Bypass -File tests\a01-login-guide-contract.ps1
powershell -ExecutionPolicy Bypass -File tests\compile-audit.ps1
powershell -ExecutionPolicy Bypass -File tests\uni-scss-injection.ps1
```
Expected: 三条命令均输出 `PASS`.
- [ ] **Step 5: 提交验收记录**
```powershell
git add docs/规划.md
git commit -m "docs: mark A01 visual review"
```
### Task 5: D2 跨页设计完成后的路由接通(执行门槛任务)
**Precondition:** A-02 与 A-03 的设计说明、页面文件和 `pages.json` 路由均已通过各自视觉验收;否则此任务不得开始。
**Files:**
- Modify: `pages/auth/entry.vue`
- Test: `tests/a01-login-guide-contract.ps1`(扩展路由断言)
**Interfaces:**
- Consumes: A-02 的已验收密码页路由;A-03 的已验收验证码/微信回跳页路由
- Produces: `entryRoutes`,键固定为 `password``phone``wechat`
- [ ] **Step 1: 扩展合同,要求所有目标路由已在 `pages.json` 注册**
```powershell
foreach ($route in @('pages/auth/password-login', 'pages/auth/phone-login')) {
if ($route -notin $paths) { throw "Missing approved auth target route: $route" }
}
```
- [ ] **Step 2: 将 Task 3 的本地确认提示替换为唯一的目标映射**
```js
const entryRoutes = {
password: '/pages/auth/password-login',
phone: '/pages/auth/phone-login',
wechat: '/pages/auth/phone-login?source=wechat'
}
const enterLogin = (entry) => {
if (!consented.value) {
uni.showToast({ title: '请先阅读并同意相关协议', icon: 'none' })
return
}
uni.navigateTo({ url: entryRoutes[entry] })
}
```
模板调用固定为 `enterLogin('password')``enterLogin('phone')``enterLogin('wechat')`。不得在 A-01 增加任何接口调用或注册入口。
- [ ] **Step 3: 运行合同和 A-02/A-03 各自的视觉合同**
Run: `powershell -ExecutionPolicy Bypass -File tests\a01-login-guide-contract.ps1`
Expected: `PASS A-01 login guide contract`.
- [ ] **Step 4: 提交跨页接通**
```powershell
git add pages/auth/entry.vue tests/a01-login-guide-contract.ps1
git commit -m "feat: connect A01 auth routes"
```
## Self-Review
- **规格覆盖:** Task 1 和 Task 3 覆盖三入口、主次层级、本地资产、无接口和显式协议;Task 4 覆盖小屏视觉与两种协议状态;Task 5 覆盖 A-02/A-03 的跳转契约且被 D2 设计完成门槛锁住。
- **占位检查:** 没有未落实的实现步骤。Task 2 的来源 URL 是执行时取得的审计事实;没有可验证来源即停止该任务,不得提交资产。
- **命名一致性:** 页面状态固定为 `consented`,守卫固定为 `enterLogin`,跨页唯一映射固定为 `entryRoutes`Task 1 与 Task 5 的测试和实现使用同一命名。
# 已失效历史记录(2026-07-13
> 本计划在未完成设计归档与验收前被错误建立,现禁止执行。唯一有效的 A-01 归档为 `docs/design/A01_启动登录引导_设计记录.md`;当前工作仍以 `docs/交接记录.md` 的 G-01 验收为准。