docs: plan A01 login guide
This commit is contained in:
@@ -0,0 +1,319 @@
|
||||
# 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 的测试和实现使用同一命名。
|
||||
Reference in New Issue
Block a user