diff --git a/.gitignore b/.gitignore index d30063c..0e41af8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,8 @@ /docs/design/screens/runtime/ /tmp-g01-icon-audit.png /node_modules/ +**/node_modules/ +/design-pipeline/generated/ +/docs/design/assets/a01-vnext/candidates/ +/docs/design/assets/a01-vnext/review/ /.superpowers/ diff --git a/components/tree/TreeMemberForm.vue b/components/tree/TreeMemberForm.vue index 6cebac6..7ce6d8d 100644 --- a/components/tree/TreeMemberForm.vue +++ b/components/tree/TreeMemberForm.vue @@ -43,6 +43,20 @@ + + + + + + 关系校验规则 + 关系冲突说明 + 同一成员不能同时存在两个生父,也不能形成上下代循环。请返回世系树核对原关系后再调整。 + + 我知道了 + + + + @@ -91,6 +105,7 @@ const query = (() => { return pages[pages.length - 1]?.options || {} })() const formState = ref(query.state === 'success' ? 'success' : query.state === 'conflict' ? 'conflict' : query.state === 'error' ? 'error' : 'form') +const conflictHelpVisible = ref(false) const resultCopy = computed(() => ({ success: { eyebrow: '本地预览已更新', title: `${config.value.pageTitle}内容已保存`, copy: '返回世系树后可查看新的展示位置;正式数据将在接口阶段接入。' }, conflict: { eyebrow: '发现关系冲突', title: '这段关系会造成代际矛盾', copy: '目标成员已经存在父级关系,请先核对原关系,再决定是否调整。' }, @@ -104,7 +119,7 @@ const saveForm = () => { } formState.value = 'success' } -const showConflictHelp = () => uni.showModal({ title: '关系冲突说明', content: '同一成员不能同时存在两个生父或形成上下代循环。请返回世系树核对原关系。', showCancel: false }) +const showConflictHelp = () => { conflictHelpVisible.value = true } diff --git a/design-pipeline/manifests/a01.json b/design-pipeline/manifests/a01.json new file mode 100644 index 0000000..da11926 --- /dev/null +++ b/design-pipeline/manifests/a01.json @@ -0,0 +1,119 @@ +{ + "schemaVersion": 1, + "canvas": { + "width": 412, + "height": 915 + }, + "shared": { + "brandSeal": "static/assets/foundation/transparent/brand-seal.png", + "lock": "static/assets/modules/auth/transparent/a01-icon-lock-v1.png", + "wechat": "static/assets/foundation/transparent/auth-wechat.png", + "agreementUnchecked": "static/assets/modules/auth/transparent/a02-agreement-unchecked.png" + }, + "states": [ + { "name": "password-hidden", "mode": "password", "passwordVisible": false }, + { "name": "password-visible", "mode": "password", "passwordVisible": true }, + { "name": "sms-default", "mode": "sms", "countdown": 0 }, + { "name": "sms-countdown", "mode": "sms", "countdown": 56 } + ], + "assets": [ + { + "id": "header", + "source": "static/assets/modules/auth/opaque/a01-vnext-header-v1.png", + "output": "static/assets/modules/auth/opaque/a01-vnext-header-v1.png", + "width": 824, + "height": 340, + "alpha": false, + "maxBytes": 1200000 + }, + { + "id": "scroll", + "source": "static/assets/modules/auth/transparent/a01-vnext-scroll-v1.png", + "output": "static/assets/modules/auth/transparent/a01-vnext-scroll-v1.png", + "width": 784, + "height": 1544, + "alpha": true, + "maxBytes": 4500000 + }, + { + "id": "titleOrnament", + "source": "static/assets/modules/auth/transparent/a01-vnext-title-ornament-v1.png", + "output": "static/assets/modules/auth/transparent/a01-vnext-title-ornament-v1.png", + "width": 376, + "height": 130, + "alpha": true, + "maxBytes": 350000 + }, + { + "id": "divider", + "source": "static/assets/modules/auth/transparent/a01-vnext-divider-v1.png", + "output": "static/assets/modules/auth/transparent/a01-vnext-divider-v1.png", + "width": 540, + "height": 90, + "alpha": true, + "maxBytes": 350000 + }, + { + "id": "primaryButton", + "source": "static/assets/modules/auth/transparent/a01-vnext-primary-button-v1.png", + "output": "static/assets/modules/auth/transparent/a01-vnext-primary-button-v1.png", + "width": 584, + "height": 130, + "alpha": true, + "maxBytes": 350000 + }, + { + "id": "secondaryButton", + "source": "static/assets/modules/auth/transparent/a01-vnext-secondary-button-v1.png", + "output": "static/assets/modules/auth/transparent/a01-vnext-secondary-button-v1.png", + "width": 584, + "height": 120, + "alpha": true, + "maxBytes": 350000 + }, + { + "id": "phone", + "source": "static/assets/modules/auth/transparent/a01-vnext-phone-v1.png", + "output": "static/assets/modules/auth/transparent/a01-vnext-phone-v1.png", + "width": 120, + "height": 120, + "alpha": true, + "maxBytes": 120000 + }, + { + "id": "eyeOpen", + "source": "static/assets/modules/auth/transparent/a01-vnext-eye-open-v1.png", + "output": "static/assets/modules/auth/transparent/a01-vnext-eye-open-v1.png", + "width": 168, + "height": 128, + "alpha": true, + "maxBytes": 150000 + }, + { + "id": "eyeClosedPupil", + "source": "static/assets/modules/auth/transparent/a01-vnext-eye-closed-pupil-v1.png", + "output": "static/assets/modules/auth/transparent/a01-vnext-eye-closed-pupil-v1.png", + "width": 168, + "height": 140, + "alpha": true, + "maxBytes": 160000 + }, + { + "id": "smsThreeDots", + "source": "static/assets/modules/auth/transparent/a01-vnext-sms-three-dots-v1.png", + "output": "static/assets/modules/auth/transparent/a01-vnext-sms-three-dots-v1.png", + "width": 120, + "height": 120, + "alpha": true, + "maxBytes": 120000 + } + ], + "previews": [ + { "state": "password-hidden", "output": "design-pipeline/generated/a01/A01-password-412x915.png", "width": 412, "height": 915 }, + { "state": "sms-default", "output": "design-pipeline/generated/a01/A01-sms-412x915.png", "width": 412, "height": 915 }, + { "state": "contact", "output": "design-pipeline/generated/a01/A01-password-sms-contact-824x915.png", "width": 824, "height": 915 }, + { "state": "password-hidden", "output": "design-pipeline/generated/a01/A01-password-320x568.png", "width": 320, "height": 568 }, + { "state": "password-hidden", "output": "design-pipeline/generated/a01/A01-password-360x640.png", "width": 360, "height": 640 }, + { "state": "password-hidden", "output": "design-pipeline/generated/a01/A01-password-360x800.png", "width": 360, "height": 800 } + ] +} diff --git a/design-pipeline/package-lock.json b/design-pipeline/package-lock.json new file mode 100644 index 0000000..f675a61 --- /dev/null +++ b/design-pipeline/package-lock.json @@ -0,0 +1,608 @@ +{ + "name": "jiapu-design-pipeline", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "jiapu-design-pipeline", + "dependencies": { + "sharp": "0.34.5" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.2.tgz", + "integrity": "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + } + } +} diff --git a/design-pipeline/package.json b/design-pipeline/package.json new file mode 100644 index 0000000..9eb86a4 --- /dev/null +++ b/design-pipeline/package.json @@ -0,0 +1,11 @@ +{ + "name": "jiapu-design-pipeline", + "private": true, + "type": "module", + "scripts": { + "build:a01": "node scripts/build-a01.mjs" + }, + "dependencies": { + "sharp": "0.34.5" + } +} diff --git a/design-pipeline/scripts/build-a01.mjs b/design-pipeline/scripts/build-a01.mjs new file mode 100644 index 0000000..512fd31 --- /dev/null +++ b/design-pipeline/scripts/build-a01.mjs @@ -0,0 +1,159 @@ +import { createHash } from 'node:crypto' +import { mkdir, readFile, stat, writeFile } from 'node:fs/promises' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import sharp from 'sharp' + +const scriptDirectory = path.dirname(fileURLToPath(import.meta.url)) +const workspace = path.resolve(scriptDirectory, '..', '..') +const manifestPath = path.join(workspace, 'design-pipeline', 'manifests', 'a01.json') +const manifest = JSON.parse(await readFile(manifestPath, 'utf8')) +const generatedDirectory = path.join(workspace, 'design-pipeline', 'generated', 'a01') + +const resolveWorkspacePath = (relativePath) => { + const absolutePath = path.resolve(workspace, relativePath) + const relative = path.relative(workspace, absolutePath) + if (relative.startsWith('..') || path.isAbsolute(relative)) { + throw new Error(`路径越出工作区:${relativePath}`) + } + return absolutePath +} + +const sha256 = (buffer) => createHash('sha256').update(buffer).digest('hex') + +const writeVersionedFile = async (outputPath, buffer) => { + await mkdir(path.dirname(outputPath), { recursive: true }) + try { + const current = await readFile(outputPath) + if (sha256(current) !== sha256(buffer)) { + throw new Error(`拒绝覆盖内容不同的版本化输出:${path.relative(workspace, outputPath)}`) + } + return + } catch (error) { + if (error.code !== 'ENOENT') throw error + } + await writeFile(outputPath, buffer) +} + +const runtimeAssets = new Map() +const reportAssets = [] + +for (const asset of manifest.assets) { + const sourcePath = resolveWorkspacePath(asset.source) + const outputPath = resolveWorkspacePath(asset.output) + await stat(sourcePath) + const pipeline = sharp(sourcePath).resize(asset.width, asset.height, { fit: 'fill' }) + if (!asset.alpha) pipeline.flatten({ background: '#f4eadc' }) + const buffer = await pipeline.png({ compressionLevel: 9, adaptiveFiltering: true, palette: false }).toBuffer() + await writeVersionedFile(outputPath, buffer) + runtimeAssets.set(asset.id, buffer) + const metadata = await sharp(buffer).metadata() + reportAssets.push({ + id: asset.id, + output: asset.output, + width: metadata.width, + height: metadata.height, + bytes: buffer.length, + sha256: sha256(buffer) + }) +} + +const loadShared = async (key) => readFile(resolveWorkspacePath(manifest.shared[key])) +const shared = { + brandSeal: await loadShared('brandSeal'), + lock: await loadShared('lock'), + wechat: await loadShared('wechat'), + agreementUnchecked: await loadShared('agreementUnchecked') +} + +const svgLayer = (mode) => Buffer.from(` + + + 登录家谱 + 密码登录 + 验证码登录 + + + 手机号 + + ${mode === 'password' ? '密码' : '验证码'} + ${mode === 'password' + ? '忘记密码' + : '获取验证码'} + + 登录 + + + 其他登录方式 + 微信登录 + 还没有账号? 注册账号 + 我已阅读并同意《用户协议》与《隐私政策》 +`) + +const sized = async (input, width, height) => sharp(input).resize(width, height, { fit: 'fill' }).png().toBuffer() + +const buildBasePreview = async (mode) => { + const stateIcon = mode === 'password' ? shared.lock : runtimeAssets.get('smsThreeDots') + const rightIcon = mode === 'password' ? runtimeAssets.get('eyeClosedPupil') : null + const layers = [ + { input: await sized(runtimeAssets.get('header'), 412, 170), left: 0, top: 0 }, + { input: await sized(runtimeAssets.get('scroll'), 392, 772), left: 10, top: 143 }, + { input: await sized(shared.brandSeal, 72, 86), left: 170, top: 35 }, + { input: await sized(runtimeAssets.get('titleOrnament'), 126, 44), left: 143, top: 235 }, + { input: await sized(runtimeAssets.get('divider'), 180, 30), left: 116, top: 330 }, + { input: await sized(runtimeAssets.get('phone'), 40, 40), left: 68, top: 420 }, + { input: await sized(stateIcon, 40, 40), left: 68, top: 522 }, + { input: await sized(runtimeAssets.get('primaryButton'), 292, 65), left: 60, top: 608 }, + { input: await sized(runtimeAssets.get('secondaryButton'), 292, 60), left: 60, top: 718 }, + { input: await sized(shared.wechat, 36, 36), left: 126, top: 730 }, + { input: await sized(shared.agreementUnchecked, 24, 24), left: 62, top: 831 }, + { input: svgLayer(mode), left: 0, top: 0 } + ] + if (rightIcon) layers.splice(7, 0, { input: await sized(rightIcon, 42, 35), left: 312, top: 525 }) + return sharp({ create: { width: 412, height: 915, channels: 4, background: '#f4eadc' } }) + .composite(layers) + .png({ compressionLevel: 9, adaptiveFiltering: true }) + .toBuffer() +} + +await mkdir(generatedDirectory, { recursive: true }) +const passwordPreview = await buildBasePreview('password') +const smsPreview = await buildBasePreview('sms') + +const writeGenerated = async (relativePath, buffer) => { + const outputPath = resolveWorkspacePath(relativePath) + await mkdir(path.dirname(outputPath), { recursive: true }) + await writeFile(outputPath, buffer) +} + +await writeGenerated('design-pipeline/generated/a01/A01-password-412x915.png', passwordPreview) +await writeGenerated('design-pipeline/generated/a01/A01-sms-412x915.png', smsPreview) +const contact = await sharp({ create: { width: 824, height: 915, channels: 4, background: '#ffffff' } }) + .composite([{ input: passwordPreview, left: 0, top: 0 }, { input: smsPreview, left: 412, top: 0 }]) + .png({ compressionLevel: 9, adaptiveFiltering: true }) + .toBuffer() +await writeGenerated('design-pipeline/generated/a01/A01-password-sms-contact-824x915.png', contact) + +for (const preview of manifest.previews.filter((item) => item.width !== 412 && item.width !== 824)) { + const compact = await sharp(passwordPreview) + .resize(preview.width, preview.height, { fit: 'fill' }) + .png({ compressionLevel: 9, adaptiveFiltering: true }) + .toBuffer() + await writeGenerated(preview.output, compact) +} + +const buildReport = { + schemaVersion: 1, + manifest: path.relative(workspace, manifestPath).replaceAll('\\', '/'), + assets: reportAssets, + generatedAt: new Date().toISOString() +} +await writeGenerated('design-pipeline/generated/a01/build-report.json', Buffer.from(`${JSON.stringify(buildReport, null, 2)}\n`)) + +console.log('A01-CODE-PIPELINE BUILD PASS') diff --git a/design-qa.md b/design-qa.md index 6cb4350..07770a4 100644 --- a/design-qa.md +++ b/design-qa.md @@ -1,3 +1,467 @@ +# Design QA — T04 新增亲属 + +- representative contact sheet: `docs/design/screens/handoff/2026-07-16/T04-current-form-success-contact-720x800.png` +- viewport: 360×800;成员链路 smoke 覆盖 T04–T08 关键路由与状态 + +## Findings + +没有遗留的 H5 P0/P1/P2 问题。新增亲属表单的关系、姓名、出生日期和性别层级清楚,成功结果与表单使用同一纸面体系。共用成员表单中残留的原生 `uni.showModal` 已替换为项目自定义冲突说明层。 + +## Evidence limits + +当前是 H5 内部候选;关系选择器、真实保存、键盘与 Android 返回手势仍待功能阶段和设备复核,用户视觉验收尚未进行。 + +# Design QA — T01 世系树 + +- representative contact sheet: `docs/design/screens/handoff/2026-07-16/T01-current-tree-empty-contact-720x800.png` +- viewport: 360×800;运行 smoke 覆盖横向提示、空、失败、树态、节点选择和成员档案跳转 + +## Findings + +没有遗留的 H5 P0/P1/P2 问题。 + +- 树态使用横向可拖动画布表达同代支系,页面本身无横向溢出;首屏保留阅读提示、代际标识、节点层级与选中成员操作条。 +- 空态说明内容产生方式,只突出“录入首代成员”;加载失败与横向提示继续由 T01 同页状态承接。 +- 移除了未注册路由但仍残留的 T02 旧占位文件,T01 成为世系阅读状态的唯一所有者。 + +## Evidence limits + +当前是 H5 内部候选,不证明真实世系接口、超大族谱性能或 Android 手势已通过;用户验收和 Android/HBuilderX 复核仍待进行。 + +## Implementation checklist + +- [x] T01 聚焦静态合同 +- [x] T01 H5 运行 smoke +- [x] 树态/空态真实运行联系表及人工审视 +- [ ] Android/HBuilderX 真机或模拟器复核 +- [ ] 用户视觉验收 + +# Design QA — G11 家谱设置/G12 字辈诗 + +- G11 representative contact sheet: `docs/design/screens/handoff/2026-07-16/G11-current-form-permission-contact-720x800.png` +- G12 representative contact sheet: `docs/design/screens/handoff/2026-07-16/G12-current-list-edit-contact-720x800.png` +- viewport: 360×800;运行 smoke 覆盖列表、空、编辑、成功、失败与无权限 + +## Findings + +没有遗留的 H5 P0/P1/P2 问题。 + +- G11:名称、公开范围、访问说明保持接口可解释边界;名称错误就近显示,保存反馈为项目自定义,无权限独立表达。 +- G12:列表、空、编辑、校验、保存失败、无权限均有位置;连续文本预览与缺失旧世代策略保持清晰。 +- 两页均移除原生 Toast,保留现有完整纸面板、按钮和输入资产。 + +## Evidence limits + +当前保存只更新本地候选,不证明设置/字辈接口、权限或并发编辑已经接通;Android 仍待设备复核。 + +## Implementation checklist + +- [x] G11 表单/成功/错误/无权限与自定义反馈 +- [x] G12 列表/空/编辑/校验/失败/无权限与自定义反馈 +- [x] H5 真实运行烟测和联系表 +- [ ] Android/HBuilderX 真机或模拟器复核 +- [ ] 用户验收 + +final result: passed (internal H5 candidate QA only; user review pending) + +--- + +# Design QA — G10 入谱审核 + +- source visual truth path: 现有审核记录卡视觉与 `docs/验收规划.md` G10 状态合同 +- implementation screenshot path: `docs/design/screens/runtime/2026-07-16/G10-current-list-360x800.png`、`G10-current-no-permission-360x800.png` +- representative contact sheet: `docs/design/screens/handoff/2026-07-16/G10-current-list-permission-contact-720x800.png` +- viewport: 360×800;运行 smoke 覆盖说明、确认和结果反馈 +- state: 列表、空、失败、无权限、通过确认、拒绝确认、说明 + +## Findings + +没有遗留的 H5 P0/P1/P2 问题。 + +- 审核操作:每条待审记录保留拒绝/通过,二者都必须进入自定义二次确认后才更新结果。 +- 自定义反馈:顶栏审核说明、确认弹层和处理结果全部使用项目组件,已移除原生 Modal/Toast。 +- 权限状态:无权限与网络失败分开表达,避免把角色限制误报成加载错误。 +- 卡片信息:姓名、脱敏手机号、关系说明和提交时间保持同屏可核对。 + +## Evidence limits + +当前审核结果只更新本地候选卡片,不证明服务端权限、并发审核、消息通知或成员身份写入已经完成。 + +## Implementation checklist + +- [x] 列表/空/失败/无权限 +- [x] 自定义通过/拒绝确认 +- [x] 自定义审核说明与结果反馈 +- [x] H5 真实运行烟测 +- [ ] Android/HBuilderX 真机或模拟器复核 +- [ ] 用户验收 + +final result: passed (internal H5 candidate QA only; user review pending) + +--- + +# Design QA — G05 成员总览/公开预览 + +- source visual truth path: 已选 G05 总览位图与 `docs/验收规划.md` 公开/成员权限合同 +- implementation screenshot path: `docs/design/screens/runtime/2026-07-16/G05-current-member-owner-360x800.png`、`G05-current-public-360x800.png` +- representative contact sheet: `docs/design/screens/handoff/2026-07-16/G05-current-member-public-contact-720x800.png` +- viewport: 360×800;运行 smoke 另查 320×568、412×915 +- state: 公开预览、成员/所有者、加载、空、失败、无权限 + +## Findings + +没有遗留的 H5 P0/P1/P2 问题。 + +- 公开边界:只展示身份、来源、地区、堂号、支系、上级谱和公开说明;不渲染成员统计、世系或管理入口。 +- 申请入口:公开态底部唯一主操作进入 G08 搜索来源。 +- 角色差异:所有者显示四个业务入口与顶栏管理;普通成员只显示世系和字辈,不显示录入、审核或设置。 +- 视觉层级:世系入口不再单独用朱砂强调,保持“总览优先、世系次级”的产品层级。 +- 实现边界:移除远程 API,加载/错误/无权限均为同页本地样式状态。 + +## Evidence limits + +当前公开字段和角色由本地候选决定,不证明真实接口字段级权限、成员身份、管理权限或全局家谱上下文已接通。 + +## Implementation checklist + +- [x] 公开预览最小字段与申请入口 +- [x] 成员/所有者入口差异 +- [x] loading/empty/error/no-permission 同页状态 +- [x] 三档 H5 响应式与真实运行烟测 +- [ ] Android/HBuilderX 真机或模拟器复核 +- [ ] 用户验收 + +final result: passed (internal H5 candidate QA only; user review pending) + +--- + +# Design QA — G03 创建家谱/首代人物 + +- source visual truth path: 现有 G03 两步题签设计与 `docs/验收规划.md` 最新创建合同 +- implementation screenshot path: `docs/design/screens/runtime/2026-07-16/G03-current-create-360x800.png`、`G03-current-ancestor-360x800.png` +- representative contact sheet: `docs/design/screens/handoff/2026-07-16/G03-current-create-ancestor-contact-720x800.png` +- viewport: 360×800;运行 smoke 另查 320×568、412×915 +- state: 创建表单/校验/重复建谱提醒/提交中/失败,首代恢复/校验/保存中/失败/成功 + +## Findings + +没有遗留的 H5 P0/P1/P2 问题。 + +- 创建字段:姓氏、谱名、堂号、所在地和访问规则齐全,访问规则提供仅成员可见/可搜索申请两个明确候选。 +- 防重复建谱:本地校验通过后先打开自定义提醒层,可先去 G06 搜索或确认继续创建。 +- 中断恢复:已创建未录始祖继续使用同一路由 `step=ancestor&genealogyId=`,不重复建谱。 +- 完成路径:首代保存成功显示自定义结果并进入 G05 总览,不再错误直跳 T01。 +- 实现边界:移除本页远程 API 和原生 UniApp 提示,当前只审核页面样式状态。 + +## Evidence limits + +当前创建 ID、保存结果和失败状态均为本地候选,不证明服务端创建、重复谱检索、始祖持久化或断点恢复已经接通。 + +## Implementation checklist + +- [x] 创建字段与页内校验 +- [x] 自定义已有谱提醒和访问规则候选 +- [x] 两步提交中/失败/成功与中断恢复外观 +- [x] 完成后进入 G05 +- [x] 三档 H5 响应式与真实运行烟测 +- [ ] Android/HBuilderX 真机或模拟器复核 +- [ ] 用户验收 + +final result: passed (internal H5 candidate QA only; user review pending) + +--- + +# Design QA — G09 我的申请 + +- source visual truth path: 现有申请状态题签视觉与 `docs/验收规划.md` G09 状态合同 +- implementation screenshot path: `docs/design/screens/runtime/2026-07-16/G09-current-list-360x800.png`、`G09-current-empty-360x800.png` +- representative contact sheet: `docs/design/screens/handoff/2026-07-16/G09-current-list-empty-contact-720x800.png` +- viewport: 360×800;运行 smoke 同时验证交互路径 +- state: 待审、通过、拒绝、撤回、修改后重提、空、失败、加载 + +## Findings + +没有遗留的 H5 P0/P1/P2 问题。 + +- 状态动作:待审只显示撤回,通过只显示进入家谱,拒绝只显示修改后重新提交;状态与动作分行显示,不再重叠。 +- 撤回流程:使用自定义确认层,确认后本地状态变为已撤回且不再显示审核动作。 +- 来源边界:空态明确只有搜索申请进入本页,邀请码直接加入不生成审核记录。 +- 路由语义:通过进入 G05;拒绝携带 `source=search&previous=rejected` 返回 G08。 + +## Evidence limits + +当前记录和撤回结果为本地样式状态,不证明服务端撤回、审核同步、消息通知或列表现场恢复已经完成。 + +## Implementation checklist + +- [x] 待审/通过/拒绝/撤回状态 +- [x] 状态唯一动作与自定义撤回确认 +- [x] 修改后重提和通过后进入家谱路径 +- [x] loading/empty/error 样式与运行烟测 +- [ ] 320/412 Android 真机专项复核 +- [ ] 用户验收 + +final result: passed (internal H5 candidate QA only; user review pending) + +--- + +# Design QA — G08 搜索申请/邀请码直加入谱 + +- source visual truth path: 现有入谱表单题签视觉与 `docs/验收规划.md` 双来源合同 +- implementation screenshot path: `docs/design/screens/runtime/2026-07-16/G08-current-search-360x800.png`、`G08-current-invite-360x800.png` +- representative contact sheet: `docs/design/screens/handoff/2026-07-16/G08-current-search-invite-contact-720x800.png` +- viewport: 360×800;运行 smoke 另查 320×568、412×915 +- state: 搜索申请/邀请直加表单、页内错误、提交中、成功、失败、来源对应下一步 + +## Findings + +没有遗留的 H5 P0/P1/P2 问题。 + +- 单一来源合同:页面通过 `sourceContract` 集中管理两种来源的标题、说明、第三字段、按钮、结果和下一步,避免“申请/直接加入”文案混用。 +- 字段边界:真实姓名、以已知长辈为参照的文字关系必填;没有虚构接口尚不支持的成员选择器或结构化关系。 +- 搜索来源:第三字段为申请说明,成功后去 G09 查看审核进度。 +- 邀请来源:第三字段为可选补充信息,明确无需审核;成功后返回 G01 并携带选中家谱。 +- 错误反馈:必填错误就近显示,重复点击提交被拦截,没有原生 UniApp 提示。 + +## Evidence limits + +当前提交结果为本地样式状态,不证明真实申请、邀请码直加、重复提交防护服务端逻辑或 G01 全局上下文刷新已经接通。 + +## Implementation checklist + +- [x] 搜索/邀请双来源单一合同 +- [x] 真实姓名与参照长辈文字关系校验 +- [x] 来源对应第三字段、结果和下一步 +- [x] 本地提交中/成功/失败与三档响应式 +- [ ] Android/HBuilderX 真机或模拟器复核 +- [ ] 用户验收 + +final result: passed (internal H5 candidate QA only; user review pending) + +--- + +# Design QA — G06 搜索/邀请码加入 + +- source visual truth path: 已选 G06 题签检索视觉与 `docs/验收规划.md` 最新双模式/关系状态合同 +- implementation screenshot path: `docs/design/screens/runtime/2026-07-16/G06-current-initial-360x800.png`、`G06-current-results-360x800.png`、`G06-current-invite-360x800.png` +- representative contact sheet: `docs/design/screens/handoff/2026-07-16/G06-current-initial-results-invite-contact-1080x800.png` +- viewport: 360×800;运行 smoke 另查 320×568、412×915 +- state: 搜索初始/加载/结果/空/失败/清空,邀请码初始/无效/有效目标,六种用户关系动作 + +## Findings + +没有遗留的 H5 P0/P1/P2 问题。 + +- 双模式:同一路由明确区分“搜索家谱”和“邀请码加入”,从 G01 邀请入口可直接进入邀请码状态。 +- 识别信息:结果卡同时展示谱名、姓氏、地区、堂号、上级谱、支系、管理/认证、成员数和更新时间,降低同名谱误选。 +- 关系动作:未加入、已加入、审核中、被拒绝、已退出/移除、我创建的六种状态各只有一个明确动作,不再统一显示“可申请”。 +- 公开预览:未加入用户点结果卡进入 G05 `mode=public`;申请按钮单独进入 G08 搜索来源。 +- 邀请流程:无效邀请码就近显示;有效目标明确提示确认关系后直接加入、无需等待审核。 +- 实现边界:移除远程 `appApi`,当前只用本地展示数据审核样式;没有原生 UniApp 提示。 + +## Evidence limits + +当前邀请码 `JP2026` 和六种结果均为样式数据,不证明真实搜索、邀请码有效性、成员继承规则、认证信息或接口权限已经接通。 + +## Implementation checklist + +- [x] 搜索/邀请码双模式 +- [x] 详细结果字段和六种关系动作 +- [x] 搜索五类状态、清空与地区筛选位置 +- [x] 邀请码无效/有效目标与 G08 来源合同 +- [x] 三档 H5 响应式、真实点击与联系表 +- [ ] Android/HBuilderX 真机或模拟器复核 +- [ ] 用户验收 + +final result: passed (internal H5 candidate QA only; user review pending) + +--- + +# Design QA — G01 我的家谱重新审核 + +- source visual truth path: 历史 G01 成熟视觉基准与 `docs/验收规划.md` 最新 G01 状态合同 +- implementation screenshot path: `docs/design/screens/runtime/2026-07-16/G01-current-default-360x800.png`、`docs/design/screens/runtime/2026-07-16/G01-current-empty-360x800.png` +- representative contact sheet: `docs/design/screens/handoff/2026-07-16/G01-current-default-empty-contact-720x800.png` +- viewport: 360×800;运行 smoke 另查 320×568、412×915 +- state: 默认三分组、空态三入口、loading、error、添加家谱弹层、当前谱切换层 + +## Findings + +没有遗留的 H5 P0/P1/P2 问题。 + +- 视觉策略:保留现有成熟的朱砂顶栏、宣纸、题签、金线图标和水墨页脚,不为重审无必要地更换风格。 +- 空态分流:搜索家谱为朱砂主入口,邀请码为快捷入口,创建为三级入口并明确提示先确认无现有家谱;三者始终同屏可见。 +- 默认状态:我创建的、我加入的、加入申请三组均存在,加入申请示例覆盖审核中、被拒绝和已退出的位置与语义。 +- 页面操作:添加家谱不再直接跳创建页,而是打开自定义三入口弹层;当前大卡支持自定义切换层。 +- 兼容性:三档无横向溢出,底部 Tabbar 保留内容安全距离;短屏正常滚动。 + +## Evidence limits + +当前使用本地展示数据验证页面样式,不代表全局家谱上下文已经持久化,也不代表真实申请状态、接口加载、Android 返回现场恢复或用户验收完成。 + +## Implementation checklist + +- [x] 空态搜索/邀请码/创建三入口及优先级 +- [x] 默认三分组与关键申请状态 +- [x] loading/error 与自定义重新加载 +- [x] 添加家谱弹层和当前谱切换层 +- [x] 三档 H5 响应式、真实点击与截图 QA +- [ ] 全局家谱上下文真实持久化 +- [ ] Android/HBuilderX 真机或模拟器复核 +- [ ] 用户验收 + +final result: passed (internal H5 candidate QA only; user review pending) + +--- + +# Design QA — A06 阻断登录状态 + +- source visual truth path: A01/A04/A05 红色宗祠水墨认证系列与 `docs/验收规划.md` A06 最新产品合同 +- implementation screenshot path: `docs/design/screens/runtime/2026-07-16/A06-current-risk-412x915.png` +- viewport: 412×915;运行 smoke 另查 320×568、360×800 +- state: 账号冻结、账号停用、风险限制、未知旧状态回落、自定义恢复说明层 + +## Findings + +没有遗留的 H5 P0/P1/P2 问题。 + +- 产品边界:旧 normal/failed/register/wechat 状态已移除;A06 仅保留冻结、停用、风险限制,普通登录错误继续由 A01 就近承接。 +- 信息完整性:每种状态明确展示限制原因、影响范围和恢复方式,不只给出模糊失败提示。 +- 视觉与反馈:保持认证系列底板和品牌印;恢复入口使用自定义说明层,不调用原生 Toast/Modal。 +- 尺寸适配:三档无横向溢出,320×568 按正常比例自然滚动。 + +## Evidence limits + +当前结论仅为 HBuilderX H5 + Chrome 内部 QA,不等于用户验收;真实状态来源、账号申诉服务、Android 返回手势和字体放大仍待功能/真机阶段。 + +## Implementation checklist + +- [x] 只保留冻结、停用、风险限制 +- [x] 原因、影响范围、恢复入口完整 +- [x] 未知旧状态安全回落到风险限制 +- [x] 自定义恢复说明层与返回 A01 +- [x] 三档 H5 响应式和运行烟测 +- [ ] Android/HBuilderX 真机或模拟器复核 +- [ ] 用户验收 + +final result: passed (internal H5 candidate QA only; user review pending) + +--- + +# Design QA — A05 重设密码 + +- source visual truth path: A01/A04 红色宗祠水墨认证系列 +- implementation screenshot path: `docs/design/screens/runtime/2026-07-16/A05-current-reset-412x915.png` +- viewport: 412×915;运行 smoke 另查 320×568、360×800 +- state: 默认表单、手机号错误、发送验证码前验证、验证关闭保值、发送反馈、密码不一致、自定义成功结果 + +## Findings + +没有遗留的 H5 P0/P1/P2 问题。 + +- 视觉连续性:使用同一宗祠水墨底板、独立品牌印、朱砂主按钮和宣纸表单,旧大面板已移除。 +- 流程顺序:获取验证码先校验手机号,再打开自定义行为验证;重设提交不重复验证。 +- 错误与结果:四字段错误就近显示,验证码发送反馈和重设成功结果均为项目内自定义组件,不使用原生 UniApp 提示。 +- 尺寸适配:三档无横向溢出,320×568 保持正常比例并自然滚动。 + +## Evidence limits + +当前结论仅为 HBuilderX H5 + Chrome 内部 QA,不等于用户验收;真实短信、行为验证令牌、重设接口、Android 软键盘与成功后手机号回填属于后续功能/真机复核。 + +## Implementation checklist + +- [x] A01/A04 同系列视觉与真实资产 +- [x] 发送验证码前自定义行为验证 +- [x] 关闭验证保留表单与自定义发送反馈 +- [x] 四字段页内校验与自定义成功结果 +- [x] 三档 H5 响应式和运行烟测 +- [ ] Android/HBuilderX 真机或模拟器复核 +- [ ] 用户验收 + +final result: passed (internal H5 candidate QA only; user review pending) + +--- + +# Design QA — A04 注册账号 + +- source visual truth path: A01 已选红色宗祠水墨视觉体系与 `docs/design/screens/handoff/2026-07-16/A01-current-password-sms-contact-824x915.png` +- implementation screenshot path: `docs/design/screens/runtime/2026-07-16/A04-current-register-412x915.png` +- viewport: 412×915;运行 smoke 另查 320×568、360×800 +- state: 默认注册、空表单错误、协议错误、自定义行为验证、自定义反馈 + +## Findings + +没有遗留的 H5 P0/P1/P2 问题。 + +- 视觉连续性:沿用 A01 的红色宗祠、水墨宣纸、独立 `brand-seal.png`、朱砂按钮与古金分隔,不再使用旧大厅与大面板。 +- 表单层级:手机号、设置密码、确认密码三行保持清晰标签和输入提示;错误信息就近显示,不调用原生 UniApp 提示。 +- 尺寸适配:三档宽高无横向溢出;320×568 按最新决定保持正常比例并自然纵向滚动。 +- 流程验证:A01 注册入口、三字段校验、协议校验、自定义验证层、自定义反馈以及返回登录均通过浏览器运行烟测。 + +## Evidence limits + +当前结论仅为 HBuilderX H5 + Chrome 内部 QA,通过不等于用户验收;Android 状态栏、安全区、软键盘、字体放大和返回手势仍需真机或模拟器复核。 + +## Implementation checklist + +- [x] A01 同系列视觉与真实资产 +- [x] 三字段就近校验与协议页内错误 +- [x] 自定义验证层与反馈提示 +- [x] 320×568 自然滚动、360×800 与 412×915 无横向溢出 +- [x] H5 静态契约与真实运行烟测 +- [ ] Android/HBuilderX 真机或模拟器复核 +- [ ] 用户验收 + +final result: passed (internal H5 candidate QA only; user review pending) + +--- + +# Design QA — A01 红色宗祠水墨登录页 + +- source visual truth path: `docs/design/screens/handoff/2026-07-16/A01-selected-password-red-hall-ink-412x915.png`、`docs/design/screens/handoff/2026-07-16/A01-selected-sms-red-hall-ink-412x915.png` +- implementation screenshot path: `docs/design/screens/runtime/2026-07-16/A01-password-final-412x915.png`、`docs/design/screens/runtime/2026-07-16/A01-sms-final-412x915.png` +- viewport: 412×915;另查 320×568、360×640、360×800 +- state: 密码登录、短信验证码登录;运行 smoke 另查协议页内错误与自定义行为验证层 +- full-view comparison evidence: `docs/design/screens/runtime/2026-07-16/A01-password-compare-final.png`、`docs/design/screens/runtime/2026-07-16/A01-sms-compare-final.png` +- focused region comparison evidence: 全页比较以原始 412px 宽度并排显示,顶部宗祠、Logo、输入图标和协议文字均可辨认;没有需要额外放大的高密度区域。 + +## Findings + +没有遗留的 P0/P1/P2 问题。 + +- 字体与层级:标题、Tab、输入文案、主按钮和辅助文案已形成与选定稿一致的层级;中文字体受 H5 系统宋体渲染影响存在轻微字形差异,归为 P3。 +- 间距与布局:第二轮已扩大标题和表单节奏,协议区不再过早结束;四档宽度无横向溢出,320×568 按用户最新决定自然纵向滚动。 +- 颜色与令牌:朱砂红、暗红宗祠、象牙宣纸、淡墨山水和旧金线条与选定稿一致。 +- 图片质量:宗祠水墨底板为 824×1830 PNG;`brand-seal.png` 独立叠放,未让生成模型重绘“谱”字;锁、闭眼瞳孔、短信气泡三点和微信均使用真实资产。 +- 文案与内容:密码/短信标签、短信验证码、获取验证码、忘记密码、微信登录、注册和协议文案齐全。 +- 交互与可达性:密码/短信状态切换、密码显隐、协议页内错误、自定义行为验证层均通过浏览器 smoke;截图不能证明读屏顺序和 Android 真机触摸体验。 + +## Comparison history + +1. v1 P1:标题、Tab、输入和按钮文字明显偏小,表单整体比设计稿提前约 90px 结束;已扩大字号并重排垂直节奏。 +2. v2 P2:宗祠区比设计稿高约 17px;已对新底板分段缩放,保持总尺寸不变。 +3. v3 P2:短信气泡、微信图标偏小且输入图标槽位偏右;已在固定槽位内调整显示比例和视觉位移。 +4. final:密码/短信同尺寸比较未发现新的 P0/P1/P2。 + +## Evidence limits + +本轮是 HBuilderX H5 + Chrome 调试截图,不能替代 Android/HBuilderX 真机或模拟器对状态栏、安全区、软键盘、系统字体放大、读屏和返回手势的最终复核,也不代表用户已经验收。 + +## Implementation checklist + +- [x] 密码/短信共用红色宗祠水墨底板 +- [x] 独立使用现有 `brand-seal.png` +- [x] 密码锁、闭眼瞳孔和横线下方忘记密码 +- [x] 短信气泡三点和获取验证码 +- [x] 320×568 自然滚动与四档无横向溢出 +- [x] 协议页内错误和自定义行为验证层 smoke +- [ ] Android/HBuilderX 真机或模拟器复核 +- [ ] 用户验收 + +final result: passed + +--- + # Design QA — G05 家谱总览 - source visual truth path: `docs/design/screens/runtime/2026-07-14/g-module-audit/before/01-g05-before-360x800.png`、`static/assets/modules/genealogy/opaque/g05-overview-surface.png`、外部思维导图与 `家谱主页.png` 的信息层级参考 diff --git a/docs/design/assets/a01-vnext/source/A01-layered-source-v1.psd b/docs/design/assets/a01-vnext/source/A01-layered-source-v1.psd new file mode 100644 index 0000000..4784907 Binary files /dev/null and b/docs/design/assets/a01-vnext/source/A01-layered-source-v1.psd differ diff --git a/docs/design/assets/a01-vnext/source/a01-psd-manifest.json b/docs/design/assets/a01-vnext/source/a01-psd-manifest.json new file mode 100644 index 0000000..0a16d8b --- /dev/null +++ b/docs/design/assets/a01-vnext/source/a01-psd-manifest.json @@ -0,0 +1,45 @@ +{ + "schemaVersion": 1, + "canvas": { + "width": 1236, + "height": 2745, + "logicalWidth": 412, + "logicalHeight": 915, + "scale": 3, + "resolution": 72 + }, + "groups": [ + { "name": "00-参考", "visible": false }, + { "name": "10-背景", "visible": true }, + { "name": "20-卷轴", "visible": true }, + { "name": "30-品牌与标题装饰", "visible": true }, + { "name": "40-公共控件皮肤", "visible": true }, + { "name": "50-密码登录", "visible": true }, + { "name": "60-验证码登录", "visible": false }, + { "name": "70-内容与标注", "visible": true } + ], + "layers": [], + "states": [ + { + "name": "password-hidden", + "show": ["50-密码登录"], + "hide": ["60-验证码登录"] + }, + { + "name": "password-visible", + "show": ["50-密码登录"], + "hide": ["60-验证码登录"] + }, + { + "name": "sms-default", + "show": ["60-验证码登录"], + "hide": ["50-密码登录"] + }, + { + "name": "sms-countdown", + "show": ["60-验证码登录"], + "hide": ["50-密码登录"] + } + ], + "exports": [] +} diff --git a/docs/design/screens/handoff/2026-07-15/A01-selected-password-brand-seal-841x1870.png b/docs/design/screens/handoff/2026-07-15/A01-selected-password-brand-seal-841x1870.png new file mode 100644 index 0000000..8a204cc Binary files /dev/null and b/docs/design/screens/handoff/2026-07-15/A01-selected-password-brand-seal-841x1870.png differ diff --git a/docs/design/screens/handoff/2026-07-15/A01-selected-sms-brand-seal-841x1870.png b/docs/design/screens/handoff/2026-07-15/A01-selected-sms-brand-seal-841x1870.png new file mode 100644 index 0000000..e820828 Binary files /dev/null and b/docs/design/screens/handoff/2026-07-15/A01-selected-sms-brand-seal-841x1870.png differ diff --git a/docs/design/screens/handoff/2026-07-15/A01-visual-source-password-selected-v2-841x1870.png b/docs/design/screens/handoff/2026-07-15/A01-visual-source-password-selected-v2-841x1870.png new file mode 100644 index 0000000..0497fb2 Binary files /dev/null and b/docs/design/screens/handoff/2026-07-15/A01-visual-source-password-selected-v2-841x1870.png differ diff --git a/docs/design/screens/handoff/2026-07-15/A01-visual-source-sms-selected-v1-841x1870.png b/docs/design/screens/handoff/2026-07-15/A01-visual-source-sms-selected-v1-841x1870.png new file mode 100644 index 0000000..e820828 Binary files /dev/null and b/docs/design/screens/handoff/2026-07-15/A01-visual-source-sms-selected-v1-841x1870.png differ diff --git a/docs/design/screens/handoff/2026-07-16/A01-current-password-sms-contact-824x915.png b/docs/design/screens/handoff/2026-07-16/A01-current-password-sms-contact-824x915.png new file mode 100644 index 0000000..1ba9a64 Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/A01-current-password-sms-contact-824x915.png differ diff --git a/docs/design/screens/handoff/2026-07-16/A01-selected-password-red-hall-ink-412x915.png b/docs/design/screens/handoff/2026-07-16/A01-selected-password-red-hall-ink-412x915.png new file mode 100644 index 0000000..d45b046 Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/A01-selected-password-red-hall-ink-412x915.png differ diff --git a/docs/design/screens/handoff/2026-07-16/A01-selected-sms-red-hall-ink-412x915.png b/docs/design/screens/handoff/2026-07-16/A01-selected-sms-red-hall-ink-412x915.png new file mode 100644 index 0000000..b51c70c Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/A01-selected-sms-red-hall-ink-412x915.png differ diff --git a/docs/design/screens/handoff/2026-07-16/A04-current-register-412x915.png b/docs/design/screens/handoff/2026-07-16/A04-current-register-412x915.png new file mode 100644 index 0000000..bdbb0b6 Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/A04-current-register-412x915.png differ diff --git a/docs/design/screens/handoff/2026-07-16/A05-current-reset-412x915.png b/docs/design/screens/handoff/2026-07-16/A05-current-reset-412x915.png new file mode 100644 index 0000000..56cef30 Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/A05-current-reset-412x915.png differ diff --git a/docs/design/screens/handoff/2026-07-16/A06-current-risk-412x915.png b/docs/design/screens/handoff/2026-07-16/A06-current-risk-412x915.png new file mode 100644 index 0000000..2c6ee72 Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/A06-current-risk-412x915.png differ diff --git a/docs/design/screens/handoff/2026-07-16/G01-current-default-empty-contact-720x800.png b/docs/design/screens/handoff/2026-07-16/G01-current-default-empty-contact-720x800.png new file mode 100644 index 0000000..a5f344f Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/G01-current-default-empty-contact-720x800.png differ diff --git a/docs/design/screens/handoff/2026-07-16/G03-current-create-ancestor-contact-720x800.png b/docs/design/screens/handoff/2026-07-16/G03-current-create-ancestor-contact-720x800.png new file mode 100644 index 0000000..f2cff3f Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/G03-current-create-ancestor-contact-720x800.png differ diff --git a/docs/design/screens/handoff/2026-07-16/G05-current-member-public-contact-720x800.png b/docs/design/screens/handoff/2026-07-16/G05-current-member-public-contact-720x800.png new file mode 100644 index 0000000..85334cd Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/G05-current-member-public-contact-720x800.png differ diff --git a/docs/design/screens/handoff/2026-07-16/G06-current-initial-results-invite-contact-1080x800.png b/docs/design/screens/handoff/2026-07-16/G06-current-initial-results-invite-contact-1080x800.png new file mode 100644 index 0000000..81f24a2 Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/G06-current-initial-results-invite-contact-1080x800.png differ diff --git a/docs/design/screens/handoff/2026-07-16/G08-current-search-invite-contact-720x800.png b/docs/design/screens/handoff/2026-07-16/G08-current-search-invite-contact-720x800.png new file mode 100644 index 0000000..96f9da4 Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/G08-current-search-invite-contact-720x800.png differ diff --git a/docs/design/screens/handoff/2026-07-16/G09-current-list-empty-contact-720x800.png b/docs/design/screens/handoff/2026-07-16/G09-current-list-empty-contact-720x800.png new file mode 100644 index 0000000..d242a61 Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/G09-current-list-empty-contact-720x800.png differ diff --git a/docs/design/screens/handoff/2026-07-16/G10-current-list-permission-contact-720x800.png b/docs/design/screens/handoff/2026-07-16/G10-current-list-permission-contact-720x800.png new file mode 100644 index 0000000..0d8ad7d Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/G10-current-list-permission-contact-720x800.png differ diff --git a/docs/design/screens/handoff/2026-07-16/G11-current-form-permission-contact-720x800.png b/docs/design/screens/handoff/2026-07-16/G11-current-form-permission-contact-720x800.png new file mode 100644 index 0000000..abe7d17 Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/G11-current-form-permission-contact-720x800.png differ diff --git a/docs/design/screens/handoff/2026-07-16/G12-current-list-edit-contact-720x800.png b/docs/design/screens/handoff/2026-07-16/G12-current-list-edit-contact-720x800.png new file mode 100644 index 0000000..688d72c Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/G12-current-list-edit-contact-720x800.png differ diff --git a/docs/design/screens/handoff/2026-07-16/T01-current-tree-empty-contact-720x800.png b/docs/design/screens/handoff/2026-07-16/T01-current-tree-empty-contact-720x800.png new file mode 100644 index 0000000..e78a480 Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/T01-current-tree-empty-contact-720x800.png differ diff --git a/docs/design/screens/handoff/2026-07-16/T04-current-form-success-contact-720x800.png b/docs/design/screens/handoff/2026-07-16/T04-current-form-success-contact-720x800.png new file mode 100644 index 0000000..e7c6ad1 Binary files /dev/null and b/docs/design/screens/handoff/2026-07-16/T04-current-form-success-contact-720x800.png differ diff --git a/docs/design/视觉证据索引.md b/docs/design/视觉证据索引.md index a29e102..000f4a9 100644 --- a/docs/design/视觉证据索引.md +++ b/docs/design/视觉证据索引.md @@ -2,7 +2,21 @@ ## 当前换机检查点 -- A01 当前短信登录态(待审核,不代表通过):[412×915 真实运行代表图](screens/handoff/2026-07-15/A01-current-sms-generated-412x915.png) +- A01 当前密码/短信登录联系表(待审核,不代表通过):[824×915 真实运行代表图](screens/handoff/2026-07-16/A01-current-password-sms-contact-824x915.png) +- A04 当前注册页(待审核,不代表通过):[412×915 真实运行代表图](screens/handoff/2026-07-16/A04-current-register-412x915.png) +- A05 当前重设密码页(待审核,不代表通过):[412×915 真实运行代表图](screens/handoff/2026-07-16/A05-current-reset-412x915.png) +- A06 当前风险限制页(待审核,不代表通过):[412×915 真实运行代表图](screens/handoff/2026-07-16/A06-current-risk-412x915.png) +- G01 当前默认/空态联系表(待审核,不代表通过):[720×800 真实运行联系表](screens/handoff/2026-07-16/G01-current-default-empty-contact-720x800.png) +- G06 当前搜索初始/结果/邀请码联系表(待审核,不代表通过):[1080×800 真实运行联系表](screens/handoff/2026-07-16/G06-current-initial-results-invite-contact-1080x800.png) +- G08 当前搜索申请/邀请码直加联系表(待审核,不代表通过):[720×800 真实运行联系表](screens/handoff/2026-07-16/G08-current-search-invite-contact-720x800.png) +- G09 当前申请列表/空态联系表(待审核,不代表通过):[720×800 真实运行联系表](screens/handoff/2026-07-16/G09-current-list-empty-contact-720x800.png) +- G03 当前创建/首代人物联系表(待审核,不代表通过):[720×800 真实运行联系表](screens/handoff/2026-07-16/G03-current-create-ancestor-contact-720x800.png) +- G05 当前成员总览/公开预览联系表(待审核,不代表通过):[720×800 真实运行联系表](screens/handoff/2026-07-16/G05-current-member-public-contact-720x800.png) +- G10 当前审核列表/无权限联系表(待审核,不代表通过):[720×800 真实运行联系表](screens/handoff/2026-07-16/G10-current-list-permission-contact-720x800.png) +- G11 当前设置/无权限联系表(待审核,不代表通过):[720×800 真实运行联系表](screens/handoff/2026-07-16/G11-current-form-permission-contact-720x800.png) +- G12 当前字辈列表/编辑联系表(待审核,不代表通过):[720×800 真实运行联系表](screens/handoff/2026-07-16/G12-current-list-edit-contact-720x800.png) +- T01 当前世系树/空态联系表(待审核,不代表通过):[720×800 真实运行联系表](screens/handoff/2026-07-16/T01-current-tree-empty-contact-720x800.png) +- T04 当前新增亲属表单/成功态联系表(待审核,不代表通过):[720×800 真实运行联系表](screens/handoff/2026-07-16/T04-current-form-success-contact-720x800.png) - 当前实际为 53 页全部重新待审核;下方旧“已验收”图片只作为历史视觉基础,不计入本轮完成状态。 > 本仓库只保留低负担交接证据:每页一张代表图,复杂模块使用联系表。完整 before/after、多尺寸、历史废稿和全部运行截图保存在项目外本地归档,不进入 Git。 diff --git a/docs/superpowers/plans/2026-07-15-a01-asset-first-design.md b/docs/superpowers/plans/2026-07-15-a01-asset-first-design.md new file mode 100644 index 0000000..255d005 --- /dev/null +++ b/docs/superpowers/plans/2026-07-15-a01-asset-first-design.md @@ -0,0 +1,102 @@ +# A01 资产优先设计落地计划 + +> 本计划由 `superpowers:writing-plans` 生成并在当前会话内直接执行。遵守用户最新约束:不使用子代理、不使用 worktree、不执行 `git add/commit/push/reset/checkout`,资产与设计验收通过前不修改 A01 页面代码。 + +**目标:** 以冻结的密码/验证码视觉真源为依据,制作一套可投入 uni-app Android 的 A01 最终资产,并使用同一批资产组装可编辑 Figma 设计。 + +**架构:** 密码与验证码状态共用唯一的背景、宗祠、卷轴、纹理、按钮和排版组件,仅切换标签、第二输入行和辅助操作。复杂装饰使用最终 PNG,文字、输入框布局、点击区域和状态切换保持可编辑;Figma 和应用后续必须引用相同资产文件与尺寸规则。 + +**技术栈:** Figma Design、Figma Plugin API、ImageGen 位图资产、uni-app/Vue、Android WebView/HBuilderX。 + +## 全局约束 + +- 唯一 Logo:`static/assets/foundation/transparent/brand-seal.png`;后续 Android 桌面图标也以它为源。 +- 密码状态:左侧使用 `static/assets/modules/auth/transparent/a01-icon-lock-v1.png`,右侧是眼睛按钮,“忘记密码”在输入横线下方右对齐。 +- 验证码状态:使用“消息气泡+三点”图标和“获取验证码”,不显示眼睛或忘记密码。 +- 除 `brand-seal` 与 `a01-icon-lock-v1` 外,A01 可见装饰资产全部制作新版本;旧文件保留但最终不引用。 +- 不使用原生 UniApp 提示组件作为最终视觉;本阶段不做接口对接。 +- 基础版本只覆盖当前浅色国风主题,以及 320×568、360×640、360×800、412×915;深色与跟随系统延期到下一版本。 +- 设计审核必须基于真实截图;H5 仅为候选证据,最终需要 Android/HBuilderX 复核。 + +--- + +### 任务 1:冻结视觉真源 + +**文件:** + +- 密码:`docs/design/screens/handoff/2026-07-15/A01-visual-source-password-selected-v2-841x1870.png` +- 验证码:`docs/design/screens/handoff/2026-07-15/A01-visual-source-sms-selected-v1-841x1870.png` + +**验收:** + +- 密码稿 SHA256:`A93F201349C1BB1F2DFAB50BA0B5372A6FC1C4762661326ADE17AA29F31960EF` +- 验证码稿 SHA256:`31D023A523DA8CA25DF00736793FAF40086B5B46F32664B724E570F432BF9D9E` +- 两张均为 `841×1870`,后续按 `412×915` 等比参考,不从聊天缩略图反推。 + +### 任务 2:建立 Figma 视觉真源与资产板 + +**目标文件:** [A01 登录页重设计(可编辑)](https://www.figma.com/design/fWhC0maHCxh5STQsjlOoWw) + +**页面结构:** + +- `00 视觉真源`:密码与验证码全尺寸参考图并排放置,标注文件名和 SHA256。 +- `01 资产板`:Logo、宗祠、卷轴分片、纹理、标题纹样、按钮分片、输入图标、Android 图标安全区。 +- `02 页面状态`:密码隐藏、密码显示、验证码默认、验证码倒计时。 +- `03 响应式验收`:当前浅色国风主题的四档尺寸状态。 + +**验收:** 每个 Figma 写入步骤返回节点 ID,并对新增 Frame 生成截图检查裁切、比例、文字和图标。 + +### 任务 3:制作新资产 + +**候选目录:** `docs/design/assets/a01-vnext/candidates/` + +**最终目录:** + +- `static/assets/modules/auth/opaque/` +- `static/assets/modules/auth/transparent/` +- `static/assets/foundation/opaque/` + +**资产边界:** + +- 宗祠头图:独立不透明宽图,包含 `brand-seal` 安全槽,但 Logo 本体仍单独引用。 +- 卷轴:顶部卷轴、中央纸纹理、左右边框、底部卷轴分离,禁止整张卷轴跨尺寸压缩。 +- 按钮:左端、中部可延展纹理、右端分离,避免边角被拉伸。 +- 图标:手机、开眼、闭眼保留瞳孔、消息气泡三点制作新版本;锁继续使用 `a01-icon-lock-v1.png`。 +- Android 图标:以 `brand-seal.png` 生成自适应图标前景、安全区预览与纯色背景方案,不改变 Logo 本体。 + +**验收:** 检查像素尺寸、ARGB/Alpha、透明边角、主体覆盖率、边缘杂色和小尺寸可读性;不合格资产不进入 `static`。 + +### 任务 4:用最终资产组装可编辑状态 + +**Figma Frame:** + +- `A01 / Password / Hidden / 412×915` +- `A01 / Password / Visible / 412×915` +- `A01 / SMS / Default / 412×915` +- `A01 / SMS / Countdown / 412×915` + +**状态差异:** + +- 密码隐藏:掩码文本、闭眼保留瞳孔。 +- 密码显示:明文文本、开眼图标。 +- 验证码默认:气泡三点图标、“获取验证码”。 +- 验证码倒计时:气泡三点图标、不可点击倒计时文案。 + +**验收:** 背景和共用资产必须为同一组件实例;切换状态时公共区域位置不得漂移。 + +### 任务 5:设计验收后进入代码实现 + +**后续才允许修改:** + +- `pages/auth/a01-entry.vue` +- A01 最终资产引用 +- `manifest.json` 或 HBuilderX Android 图标配置 +- `tests/a01-a02-ui-contract.ps1` + +**验证命令:** + +```powershell +powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/a01-a02-ui-contract.ps1 +``` + +**完成标准:** 合同测试通过,四档 H5 截图通过视觉比较,并取得 Android/HBuilderX 真机或模拟器截图;在此之前不得声明 A01 完成或验收通过。 diff --git a/docs/superpowers/plans/2026-07-15-a01-code-first-implementation.md b/docs/superpowers/plans/2026-07-15-a01-code-first-implementation.md new file mode 100644 index 0000000..06e4797 --- /dev/null +++ b/docs/superpowers/plans/2026-07-15-a01-code-first-implementation.md @@ -0,0 +1,199 @@ +# A01 纯代码资产流水线与页面落地实施计划 + +> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:executing-plans` to implement this plan task-by-task. 本项目明确禁止 worktree、子代理和任何 Git 提交操作,执行时以项目规则为准。 + +**Goal:** 不依赖 Photoshop,用同一份清单和源资产生成 A01 正式 PNG、设计预览与状态联系表,并将选定视觉一比一落到 `pages/auth/a01-entry.vue`。 + +**Architecture:** `design-pipeline/manifests/a01.json` 是 A01 源资产、正式输出、状态和尺寸的唯一机器可读所有者。Node.js 调用 Sharp 完成缩放、PNG 优化、同源预览与联系表生成;A01 页面只引用确认后的正式资产,真实运行截图仍是最终视觉证据。 + +**Tech Stack:** Node.js 24、Sharp、PowerShell 契约测试、Vue 3 ` diff --git a/pages/auth/a05-reset-password.vue b/pages/auth/a05-reset-password.vue index f5d8f0e..d3c3553 100644 --- a/pages/auth/a05-reset-password.vue +++ b/pages/auth/a05-reset-password.vue @@ -1,328 +1,329 @@ diff --git a/pages/auth/a06-auth-status.vue b/pages/auth/a06-auth-status.vue index 469f177..1a76dfe 100644 --- a/pages/auth/a06-auth-status.vue +++ b/pages/auth/a06-auth-status.vue @@ -1,46 +1,60 @@ - +