From db397a7917d0e8ca1b45ceb6d8c36c13a021c89f Mon Sep 17 00:00:00 2001 From: rain Date: Sat, 11 Jul 2026 11:03:45 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- APP.openapi.json | 7613 ----------------- app.html | 1 - docs/api-page-integration-2026-07-09.md | 102 - ...api-page-integration-tracker-2026-07-09.md | 114 - ...api-page-integration-tracker-2026-07-09.md | 71 +- .../plans/2026-07-09-pc-api-replan.md | 25 +- .../plans/2026-07-09-pc-auth-three-pages.md | 2 +- .../plans/2026-07-09-tac-captcha-auth.md | 4 +- .../2026-07-10-pc-tracker-reverification.md | 6 +- .../2026-07-11-pc-endpoint-page-coverage.md | 278 + download.html | 1 - genealogy-pc-openapi.yaml | 59 +- notice-detail.html | 1 - profile-album.html | 2 - profile-data.html | 38 +- profile-gift.html | 1 - profile-security.html | 24 - profile-services.html | 2 - profile-tree.html | 1 - public/js/album-pages.js | 2 - public/js/article-pages.js | 1 - public/js/ceremony-pages.js | 2 - public/js/feed-pages.js | 1 - public/js/genealogy-pages.js | 1 - public/js/growth-pages.js | 1 - public/js/lineage-pages.js | 1 - public/js/member-admin-pages.js | 1 - public/js/memo-pages.js | 1 - public/js/region-pages.js | 135 + public/js/security-pages.js | 41 +- public/js/upload-pages.js | 120 +- public/js/vip-pages.js | 1 - tests/pc-api-contract.test.js | 76 + tests/pc-endpoint-coverage.test.js | 82 + tests/profile-pages.test.js | 12 + tests/region-pages.test.js | 20 + tests/security-pages.test.js | 117 +- tests/upload-pages.test.js | 116 +- 38 files changed, 1082 insertions(+), 7994 deletions(-) delete mode 100644 APP.openapi.json delete mode 100644 docs/api-page-integration-2026-07-09.md delete mode 100644 docs/api-page-integration-tracker-2026-07-09.md create mode 100644 docs/superpowers/plans/2026-07-11-pc-endpoint-page-coverage.md create mode 100644 tests/pc-api-contract.test.js create mode 100644 tests/pc-endpoint-coverage.test.js diff --git a/APP.openapi.json b/APP.openapi.json deleted file mode 100644 index f900e2d..0000000 --- a/APP.openapi.json +++ /dev/null @@ -1,7613 +0,0 @@ -{ - "openapi": "3.0.1", - "info": { - "title": "APP", - "description": "家谱业务 APP/PC 用户侧接口文档,用于 Apifox 导入。\n\n导入方式:Apifox -> 导入 API 数据 -> OpenAPI/Swagger -> 选择本文件。\n\n约定:\n- APP 路径前缀为 `/genealogy/app`\n- PC/H5 路径前缀为 `/genealogy/pc`\n- 后台管理接口不包含在本文件内\n- 登录后接口需要携带 token,且请求 Header 需携带 `clientid`\n", - "version": "1.0.0" - }, - "tags": [ - { - "name": "验证中心" - }, - { - "name": "认证登录" - }, - { - "name": "文件上传" - }, - { - "name": "行政区划" - }, - { - "name": "家谱" - }, - { - "name": "家谱成员" - }, - { - "name": "字辈谱" - }, - { - "name": "世系人物" - }, - { - "name": "家族圈" - }, - { - "name": "内容文章" - }, - { - "name": "相册" - }, - { - "name": "祭祀" - }, - { - "name": "族务记录" - }, - { - "name": "消息通知" - }, - { - "name": "意见反馈" - }, - { - "name": "VIP" - } - ], - "paths": { - "/captcha/require": { - "get": { - "summary": "查询当前场景是否需要验证", - "deprecated": false, - "description": "用于登录、注册、换绑手机等场景。按租户、客户端和场景编码匹配后台验证策略。", - "tags": [ - "验证中心" - ], - "parameters": [ - { - "name": "tenantId", - "in": "query", - "description": "租户ID,用于区分不同租户的数据和验证策略", - "required": false, - "example": "000000", - "schema": { - "type": "string" - } - }, - { - "name": "clientId", - "in": "query", - "description": "客户端ID,对应后台客户端管理中的APP/PC/小程序等终端", - "required": false, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - }, - { - "name": "sceneCode", - "in": "query", - "description": "验证场景编码,例如APP_LOGIN、PC_LOGIN、APP_REGISTER", - "required": true, - "example": "APP_LOGIN", - "schema": { - "type": "string" - } - }, - { - "name": "subject", - "in": "query", - "description": "验证主体,通常为手机号、用户ID或登录账号", - "required": false, - "example": "13800000000", - "schema": { - "type": "string" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID", - "example": "ced7e5f0498645c6ec642dcf450b036f", - "schema": { - "type": "string", - "default": "ced7e5f0498645c6ec642dcf450b036f" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/VerificationRequireResult", - "description": "验证需求查询结果" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/captcha/challenge": { - "post": { - "summary": "生成验证挑战", - "deprecated": false, - "description": "统一生成验证码。策略为天爱时返回行为验证数据;策略为系统图形时返回 uuid 和 img。", - "tags": [ - "验证中心" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID", - "example": "ced7e5f0498645c6ec642dcf450b036f", - "schema": { - "type": "string", - "default": "ced7e5f0498645c6ec642dcf450b036f" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VerificationChallengeBody" - }, - "example": { - "tenantId": "000000", - "clientId": "428a8310cd442757ae699df5d894f051", - "sceneCode": "APP_LOGIN", - "subject": "13800000000" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/VerificationChallengeResult", - "description": "验证挑战生成结果" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/captcha/verify": { - "post": { - "summary": "校验验证结果并换取 validToken", - "deprecated": false, - "description": "验证通过后返回 validToken,登录、注册、发短信等业务接口将 validToken 随请求体一起提交。", - "tags": [ - "验证中心" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID", - "example": "ced7e5f0498645c6ec642dcf450b036f", - "schema": { - "type": "string", - "default": "ced7e5f0498645c6ec642dcf450b036f" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VerificationCheckBody" - }, - "examples": { - "tianai_behavior": { - "value": { - "tenantId": "000000", - "clientId": "428a8310cd442757ae699df5d894f051", - "sceneCode": "APP_LOGIN", - "subject": "13800000000", - "challengeId": "CAPTCHA_CHALLENGE_ID", - "providerCode": "tianai", - "captchaType": "SLIDER", - "payload": { - "id": "tianai-captcha-id", - "data": { - "bgImageWidth": 340, - "bgImageHeight": 180, - "startSlidingTime": 1720000000000, - "endSlidingTime": 1720000001500, - "trackList": [] - } - } - }, - "summary": "天爱滑块/旋转/滑动还原/文字点选验证" - }, - "system_image": { - "value": { - "tenantId": "000000", - "clientId": "428a8310cd442757ae699df5d894f051", - "sceneCode": "APP_LOGIN", - "subject": "13800000000", - "challengeId": "CAPTCHA_CHALLENGE_ID", - "providerCode": "ruoyi_image", - "captchaType": "math", - "payload": { - "uuid": "captcha-uuid", - "code": "6" - } - }, - "summary": "系统图形验证码" - } - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/VerificationCheckResult", - "description": "验证校验结果" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/auth/code": { - "get": { - "summary": "兼容旧系统图形验证码", - "deprecated": false, - "description": "老版后台登录图形验证码入口。新的 APP/PC 业务优先使用 /captcha/require + /captcha/challenge + /captcha/verify。", - "tags": [ - "验证中心" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID", - "example": "ced7e5f0498645c6ec642dcf450b036f", - "schema": { - "type": "string", - "default": "ced7e5f0498645c6ec642dcf450b036f" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/LegacyCaptchaResult", - "description": "兼容旧图形验证码结果" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/auth/register": { - "post": { - "summary": "APP 用户注册", - "deprecated": false, - "description": "", - "tags": [ - "认证登录" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PasswordRegisterBody" - }, - "example": { - "grantType": "password", - "tenantId": "000000", - "phone": "13800000000", - "password": "e10adc3949ba59abbe56e057f20f883e", - "nickName": "测试用户", - "registerSource": "app", - "validToken": "captcha-ticket-or-sms-token" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/LoginResult", - "description": "登录结果" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/auth/login": { - "post": { - "summary": "APP 密码登录", - "deprecated": false, - "description": "", - "tags": [ - "认证登录" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PasswordLoginBody" - }, - "example": { - "grantType": "password", - "tenantId": "000000", - "phone": "13800000000", - "password": "e10adc3949ba59abbe56e057f20f883e", - "validToken": "captcha-ticket" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/LoginResult", - "description": "登录结果" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/auth/login/sms": { - "post": { - "summary": "APP 短信登录", - "deprecated": false, - "description": "", - "tags": [ - "认证登录" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SmsLoginBody" - }, - "example": { - "grantType": "sms", - "tenantId": "000000", - "phone": "13800000000", - "smsCode": "123456", - "validToken": "captcha-ticket" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/LoginResult", - "description": "登录结果" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/auth/sms/code": { - "post": { - "summary": "APP 发送短信验证码", - "deprecated": false, - "description": "", - "tags": [ - "认证登录" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SmsCodeBody" - }, - "example": { - "tenantId": "000000", - "phone": "13800000000", - "sceneCode": "APP_LOGIN", - "validToken": "captcha-ticket" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/auth/profile": { - "get": { - "summary": "APP 当前用户资料", - "deprecated": false, - "description": "", - "tags": [ - "认证登录" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "put": { - "summary": "APP 修改用户资料", - "deprecated": false, - "description": "", - "tags": [ - "认证登录" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProfileUpdateBody" - }, - "example": { - "nickName": "张三", - "avatarOssId": "2060000000000000000", - "sex": "0", - "birthday": "1990-01-01", - "regionCode": "110101", - "addressDetail": "北京市东城区" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/auth/password": { - "put": { - "summary": "APP 修改密码", - "deprecated": false, - "description": "", - "tags": [ - "认证登录" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PasswordChangeBody" - }, - "example": { - "oldPassword": "e10adc3949ba59abbe56e057f20f883e", - "newPassword": "25d55ad283aa400af464c76d713c07ad", - "validToken": "captcha-ticket" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/auth/password/reset": { - "put": { - "summary": "APP 找回密码", - "deprecated": false, - "description": "", - "tags": [ - "认证登录" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PasswordResetBody" - }, - "example": { - "tenantId": "000000", - "phone": "13800000000", - "smsCode": "123456", - "newPassword": "25d55ad283aa400af464c76d713c07ad", - "validToken": "captcha-ticket" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/auth/phone": { - "put": { - "summary": "APP 换绑手机号", - "deprecated": false, - "description": "", - "tags": [ - "认证登录" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PhoneChangeBody" - }, - "example": { - "newPhone": "13900000000", - "smsCode": "123456", - "validToken": "captcha-ticket" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/auth/account/deactivate": { - "post": { - "summary": "APP 注销账号", - "deprecated": false, - "description": "", - "tags": [ - "认证登录" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccountDeactivateBody" - }, - "example": { - "password": "e10adc3949ba59abbe56e057f20f883e", - "reason": "user request" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/auth/logout": { - "delete": { - "summary": "APP 退出登录", - "deprecated": false, - "description": "", - "tags": [ - "认证登录" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/files/upload": { - "post": { - "summary": "APP 单文件上传", - "deprecated": false, - "description": "", - "tags": [ - "文件上传" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "type": "object", - "properties": { - "file": { - "type": "string", - "format": "binary", - "example": "" - } - }, - "required": [ - "file" - ] - }, - "example": { - "file": "" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/FileUploadResult", - "description": "文件上传结果" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/files/resumable/init": { - "post": { - "summary": "APP 分片上传初始化", - "deprecated": false, - "description": "", - "tags": [ - "文件上传" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResumableInitBody" - }, - "example": { - "fileName": "cover.jpg", - "fileSize": 9532, - "fileMd5": "d41d8cd98f00b204e9800998ecf8427e", - "contentType": "image/jpeg", - "chunkSize": 4194304, - "totalChunks": 1, - "bizType": "genealogy", - "usageScene": "cover" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/files/resumable/chunk": { - "post": { - "summary": "APP 上传分片", - "deprecated": false, - "description": "", - "tags": [ - "文件上传" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "type": "object", - "properties": { - "uploadId": { - "type": "string", - "example": "" - }, - "chunkIndex": { - "type": "integer", - "example": 0 - }, - "chunkMd5": { - "type": "string", - "example": "d41d8cd98f00b204e9800998ecf8427e" - }, - "file": { - "type": "string", - "format": "binary", - "example": "" - } - }, - "required": [ - "uploadId", - "chunkIndex", - "chunkMd5", - "file" - ] - }, - "example": { - "uploadId": "", - "chunkIndex": 0, - "chunkMd5": "d41d8cd98f00b204e9800998ecf8427e", - "file": "" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/files/resumable/complete": { - "post": { - "summary": "APP 完成分片上传", - "deprecated": false, - "description": "", - "tags": [ - "文件上传" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResumableCompleteBody" - }, - "example": { - "uploadId": "UPLOAD202607090001", - "fileMd5": "d41d8cd98f00b204e9800998ecf8427e", - "fileSize": 9532 - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/FileUploadResult", - "description": "文件上传结果" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/files/reference": { - "post": { - "summary": "APP 绑定文件业务引用", - "deprecated": false, - "description": "", - "tags": [ - "文件上传" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FileReferenceBody" - }, - "example": { - "bizType": "family_feed", - "bizName": "family feed image", - "bizTable": "gen_family_feed", - "bizId": 900013001, - "bizField": "media_oss_ids", - "ossId": "2060000000000000000", - "usageScene": "feed_image" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "delete": { - "summary": "APP 释放文件业务引用", - "deprecated": false, - "description": "", - "tags": [ - "文件上传" - ], - "parameters": [ - { - "name": "bizTable", - "in": "query", - "description": "业务表名,用于文件引用绑定", - "required": true, - "example": "gen_family_feed", - "schema": { - "type": "string" - } - }, - { - "name": "bizId", - "in": "query", - "description": "业务数据ID,用于文件引用绑定", - "required": true, - "example": 900013001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "bizField", - "in": "query", - "description": "业务字段名,例如avatar_oss_id、cover_oss_id", - "required": true, - "example": "media_ids", - "schema": { - "type": "string" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/region/children": { - "get": { - "summary": "查询下级行政区划", - "deprecated": false, - "description": "", - "tags": [ - "行政区划" - ], - "parameters": [ - { - "name": "parentCode", - "in": "query", - "description": "父级行政区划编码,不传或传0查省级", - "required": false, - "example": "51", - "schema": { - "type": "string" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID", - "example": "ced7e5f0498645c6ec642dcf450b036f", - "schema": { - "type": "string", - "default": "ced7e5f0498645c6ec642dcf450b036f" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/region/path/{regionCode}": { - "get": { - "summary": "查询行政区划路径", - "deprecated": false, - "description": "", - "tags": [ - "行政区划" - ], - "parameters": [ - { - "name": "regionCode", - "in": "path", - "description": "行政区划编码", - "required": true, - "example": "510000", - "schema": { - "type": "string" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID", - "example": "ced7e5f0498645c6ec642dcf450b036f", - "schema": { - "type": "string", - "default": "ced7e5f0498645c6ec642dcf450b036f" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/region/search": { - "get": { - "summary": "搜索行政区划", - "deprecated": false, - "description": "", - "tags": [ - "行政区划" - ], - "parameters": [ - { - "name": "keyword", - "in": "query", - "description": "搜索关键词,支持地区名称或编码模糊查询", - "required": true, - "example": "北京", - "schema": { - "type": "string" - } - }, - { - "name": "level", - "in": "query", - "description": "行政区划级别,1省、2市、3区县、4乡镇街道、5村社区", - "required": false, - "example": 3, - "schema": { - "type": "integer" - } - }, - { - "name": "limit", - "in": "query", - "description": "返回数量上限", - "required": false, - "example": 20, - "schema": { - "type": "integer" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID", - "example": "ced7e5f0498645c6ec642dcf450b036f", - "schema": { - "type": "string", - "default": "ced7e5f0498645c6ec642dcf450b036f" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/region/{regionCode}": { - "get": { - "summary": "查询行政区划详情", - "deprecated": false, - "description": "", - "tags": [ - "行政区划" - ], - "parameters": [ - { - "name": "regionCode", - "in": "path", - "description": "行政区划编码", - "required": true, - "example": "510000", - "schema": { - "type": "string" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID", - "example": "ced7e5f0498645c6ec642dcf450b036f", - "schema": { - "type": "string", - "default": "ced7e5f0498645c6ec642dcf450b036f" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies": { - "post": { - "summary": "APP 创建家谱", - "deprecated": false, - "description": "", - "tags": [ - "家谱" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenealogyCreateBody" - }, - "example": { - "genealogyName": "彭氏家谱", - "surname": "彭", - "ancestralHall": "陇西堂", - "originPlace": "江西吉安", - "regionCode": "360800", - "addressDetail": "江西省吉安市", - "coverOssId": "2060000000000000000", - "intro": "彭氏家谱简介", - "visibility": "1", - "joinMode": "1" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/mine": { - "get": { - "summary": "APP 我的家谱", - "deprecated": false, - "description": "", - "tags": [ - "家谱" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/public": { - "get": { - "summary": "APP 公开家谱", - "deprecated": false, - "description": "", - "tags": [ - "家谱" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/options": { - "get": { - "summary": "APP 家谱下拉选项", - "deprecated": false, - "description": "", - "tags": [ - "家谱" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}": { - "get": { - "summary": "APP 家谱详情", - "deprecated": false, - "description": "", - "tags": [ - "家谱" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "put": { - "summary": "APP 修改家谱", - "deprecated": false, - "description": "", - "tags": [ - "家谱" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenealogyUpdateBody" - }, - "example": { - "genealogyName": "彭氏家谱", - "surname": "彭", - "ancestralHall": "陇西堂", - "originPlace": "江西吉安", - "regionCode": "360800", - "addressDetail": "江西省吉安市", - "coverOssId": "2060000000000000000", - "intro": "更新后的家谱简介", - "visibility": "1", - "joinMode": "1" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/overview": { - "get": { - "summary": "APP 家谱概览", - "deprecated": false, - "description": "", - "tags": [ - "家谱" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/join-applies": { - "post": { - "summary": "APP 申请加入家谱", - "deprecated": false, - "description": "", - "tags": [ - "家谱" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenealogyJoinApplyBody" - }, - "example": { - "applicantName": "彭小明", - "phone": "13800000000", - "relationDesc": "本族成员", - "applyReason": "申请加入家谱维护", - "inviterUserId": 900000001 - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/join-applies/mine": { - "get": { - "summary": "APP 我的加入申请", - "deprecated": false, - "description": "", - "tags": [ - "家谱" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/join-applies/pending": { - "get": { - "summary": "APP 待审核加入申请", - "deprecated": false, - "description": "", - "tags": [ - "家谱" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/join-applies/{applyId}/audit": { - "put": { - "summary": "APP 审核加入申请", - "deprecated": false, - "description": "", - "tags": [ - "家谱" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "applyId", - "in": "path", - "description": "加入家谱申请ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenealogyJoinAuditBody" - }, - "example": { - "status": "1", - "auditRemark": "信息核验通过" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/join-applies/{applyId}": { - "delete": { - "summary": "APP 撤销加入申请", - "deprecated": false, - "description": "", - "tags": [ - "家谱" - ], - "parameters": [ - { - "name": "applyId", - "in": "path", - "description": "加入家谱申请ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/members": { - "get": { - "summary": "APP 家谱成员列表", - "deprecated": false, - "description": "", - "tags": [ - "家谱成员" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/members/options": { - "get": { - "summary": "APP 家谱成员选项", - "deprecated": false, - "description": "", - "tags": [ - "家谱成员" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/members/{memberId}": { - "put": { - "summary": "APP 修改成员", - "deprecated": false, - "description": "", - "tags": [ - "家谱成员" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "memberId", - "in": "path", - "description": "家谱成员ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenealogyMemberUpdateBody" - }, - "example": { - "memberName": "彭小明", - "relationName": "族亲", - "roleType": "member", - "lineagePersonId": 900020001 - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "delete": { - "summary": "APP 移除成员", - "deprecated": false, - "description": "", - "tags": [ - "家谱成员" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "memberId", - "in": "path", - "description": "家谱成员ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/members/me": { - "delete": { - "summary": "APP 退出家谱", - "deprecated": false, - "description": "", - "tags": [ - "家谱成员" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/members/owner-transfer": { - "put": { - "summary": "APP 转让家谱所有者", - "deprecated": false, - "description": "", - "tags": [ - "家谱成员" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenealogyOwnerTransferBody" - }, - "example": { - "targetMemberId": 900010002 - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/generation-poems": { - "get": { - "summary": "APP 查询字辈谱", - "deprecated": false, - "description": "", - "tags": [ - "字辈谱" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "post": { - "summary": "APP 新增字辈", - "deprecated": false, - "description": "", - "tags": [ - "字辈谱" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenerationPoemBody" - }, - "example": { - "generationNo": 5, - "generationText": "忠", - "description": "fifth generation poem", - "sortOrder": 5, - "status": "0" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/generation-poems/batch/preview": { - "post": { - "summary": "APP 批量字辈预览", - "deprecated": false, - "description": "", - "tags": [ - "字辈谱" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenerationPoemBatchBody" - }, - "example": { - "genealogyId": 900001001, - "poemText": "德承家亦\n忠厚传芳", - "disableMissing": false - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/generation-poems/batch/save": { - "post": { - "summary": "APP 批量保存字辈", - "deprecated": false, - "description": "", - "tags": [ - "字辈谱" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenerationPoemBatchBody" - }, - "example": { - "genealogyId": 900001001, - "poemText": "德承家亦\n忠厚传芳", - "disableMissing": false - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/generation-poems/{poemId}": { - "put": { - "summary": "APP 修改字辈", - "deprecated": false, - "description": "", - "tags": [ - "字辈谱" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "poemId", - "in": "path", - "description": "字辈谱ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenerationPoemBody" - }, - "example": { - "generationNo": 5, - "generationText": "忠", - "description": "fifth generation poem", - "sortOrder": 5, - "status": "0" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/lineage/persons": { - "get": { - "summary": "APP 世系人物列表", - "deprecated": false, - "description": "", - "tags": [ - "世系人物" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "post": { - "summary": "APP 新增世系人物", - "deprecated": false, - "description": "", - "tags": [ - "世系人物" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LineagePersonBody" - }, - "example": { - "appUserId": 900000001, - "personNo": "P202607090001", - "personName": "彭德明", - "aliasName": "德明", - "sex": "0", - "generationNo": 1, - "generationName": "德", - "avatarOssId": "2060000000000000000", - "birthDate": "1950-01-01", - "deathDate": null, - "introduction": "first generation introduction" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/lineage/persons/page": { - "get": { - "summary": "APP 世系人物分页", - "deprecated": false, - "description": "", - "tags": [ - "世系人物" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "pageNum", - "in": "query", - "description": "页码,从1开始", - "required": false, - "schema": { - "type": "integer", - "default": 1 - } - }, - { - "name": "pageSize", - "in": "query", - "description": "每页条数", - "required": false, - "schema": { - "type": "integer", - "default": 10 - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/PageResult", - "description": "通用分页响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/lineage/persons/options": { - "get": { - "summary": "APP 世系人物选项", - "deprecated": false, - "description": "", - "tags": [ - "世系人物" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/lineage/tree": { - "get": { - "summary": "APP 世系树", - "deprecated": false, - "description": "", - "tags": [ - "世系人物" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}": { - "get": { - "summary": "APP 世系人物详情", - "deprecated": false, - "description": "", - "tags": [ - "世系人物" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "personId", - "in": "path", - "description": "世系人物ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "put": { - "summary": "APP 修改世系人物", - "deprecated": false, - "description": "", - "tags": [ - "世系人物" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "personId", - "in": "path", - "description": "世系人物ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LineagePersonBody" - }, - "example": { - "appUserId": 900000001, - "personNo": "P202607090001", - "personName": "彭德明", - "aliasName": "德明", - "sex": "0", - "generationNo": 1, - "generationName": "德", - "avatarOssId": "2060000000000000000", - "birthDate": "1950-01-01", - "deathDate": null, - "introduction": "first generation introduction" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "delete": { - "summary": "APP 删除世系人物", - "deprecated": false, - "description": "", - "tags": [ - "世系人物" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "personId", - "in": "path", - "description": "世系人物ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/children": { - "post": { - "summary": "APP 给人物添加子女", - "deprecated": false, - "description": "", - "tags": [ - "世系人物" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "personId", - "in": "path", - "description": "世系人物ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LineagePersonBody" - }, - "example": { - "appUserId": 900000001, - "personNo": "P202607090001", - "personName": "彭德明", - "aliasName": "德明", - "sex": "0", - "generationNo": 1, - "generationName": "德", - "avatarOssId": "2060000000000000000", - "birthDate": "1950-01-01", - "deathDate": null, - "introduction": "first generation introduction" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/parents": { - "post": { - "summary": "APP 给人物添加父母", - "deprecated": false, - "description": "", - "tags": [ - "世系人物" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "personId", - "in": "path", - "description": "世系人物ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LineagePersonBody" - }, - "example": { - "appUserId": 900000001, - "personNo": "P202607090001", - "personName": "彭德明", - "aliasName": "德明", - "sex": "0", - "generationNo": 1, - "generationName": "德", - "avatarOssId": "2060000000000000000", - "birthDate": "1950-01-01", - "deathDate": null, - "introduction": "first generation introduction" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/siblings": { - "post": { - "summary": "APP 给人物添加兄弟姐妹", - "deprecated": false, - "description": "", - "tags": [ - "世系人物" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "personId", - "in": "path", - "description": "世系人物ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LineagePersonBody" - }, - "example": { - "appUserId": 900000001, - "personNo": "P202607090001", - "personName": "彭德明", - "aliasName": "德明", - "sex": "0", - "generationNo": 1, - "generationName": "德", - "avatarOssId": "2060000000000000000", - "birthDate": "1950-01-01", - "deathDate": null, - "introduction": "first generation introduction" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/spouses": { - "post": { - "summary": "APP 给人物添加配偶", - "deprecated": false, - "description": "", - "tags": [ - "世系人物" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "personId", - "in": "path", - "description": "世系人物ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LineagePersonBody" - }, - "example": { - "appUserId": 900000001, - "personNo": "P202607090001", - "personName": "彭德明", - "aliasName": "德明", - "sex": "0", - "generationNo": 1, - "generationName": "德", - "avatarOssId": "2060000000000000000", - "birthDate": "1950-01-01", - "deathDate": null, - "introduction": "first generation introduction" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/feeds": { - "get": { - "summary": "APP 家族圈动态列表", - "deprecated": false, - "description": "", - "tags": [ - "家族圈" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "post": { - "summary": "APP 发布家族圈动态", - "deprecated": false, - "description": "", - "tags": [ - "家族圈" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FamilyFeedBody" - }, - "example": { - "content": "今天上传一张老照片。", - "mediaOssIds": "2060000000000000001,2060000000000000002", - "visibility": "1", - "status": "0" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/feeds/page": { - "get": { - "summary": "APP 家族圈动态分页", - "deprecated": false, - "description": "", - "tags": [ - "家族圈" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "pageNum", - "in": "query", - "description": "页码,从1开始", - "required": false, - "schema": { - "type": "integer", - "default": 1 - } - }, - { - "name": "pageSize", - "in": "query", - "description": "每页条数", - "required": false, - "schema": { - "type": "integer", - "default": 10 - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/PageResult", - "description": "通用分页响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/feeds/{feedId}": { - "get": { - "summary": "APP 家族圈动态详情", - "deprecated": false, - "description": "", - "tags": [ - "家族圈" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "feedId", - "in": "path", - "description": "家族动态ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "put": { - "summary": "APP 修改家族圈动态", - "deprecated": false, - "description": "", - "tags": [ - "家族圈" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "feedId", - "in": "path", - "description": "家族动态ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FamilyFeedBody" - }, - "example": { - "content": "今天上传一张老照片。", - "mediaOssIds": "2060000000000000001,2060000000000000002", - "visibility": "1", - "status": "0" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/likes": { - "post": { - "summary": "APP 点赞动态", - "deprecated": false, - "description": "", - "tags": [ - "家族圈" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "feedId", - "in": "path", - "description": "家族动态ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "delete": { - "summary": "APP 取消点赞动态", - "deprecated": false, - "description": "", - "tags": [ - "家族圈" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "feedId", - "in": "path", - "description": "家族动态ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/comments": { - "get": { - "summary": "APP 动态评论列表", - "deprecated": false, - "description": "", - "tags": [ - "家族圈" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "feedId", - "in": "path", - "description": "家族动态ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "post": { - "summary": "APP 评论动态", - "deprecated": false, - "description": "", - "tags": [ - "家族圈" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "feedId", - "in": "path", - "description": "家族动态ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FamilyFeedCommentBody" - }, - "example": { - "parentCommentId": null, - "replyUserId": null, - "content": "这张照片很有年代感。" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/comments/page": { - "get": { - "summary": "APP 动态评论分页", - "deprecated": false, - "description": "", - "tags": [ - "家族圈" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "feedId", - "in": "path", - "description": "家族动态ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "pageNum", - "in": "query", - "description": "页码,从1开始", - "required": false, - "schema": { - "type": "integer", - "default": 1 - } - }, - { - "name": "pageSize", - "in": "query", - "description": "每页条数", - "required": false, - "schema": { - "type": "integer", - "default": 10 - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/PageResult", - "description": "通用分页响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/comments/{commentId}": { - "delete": { - "summary": "APP 删除动态评论", - "deprecated": false, - "description": "", - "tags": [ - "家族圈" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "feedId", - "in": "path", - "description": "家族动态ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "commentId", - "in": "path", - "description": "评论ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/article-categories": { - "get": { - "summary": "APP 谱文分类", - "deprecated": false, - "description": "", - "tags": [ - "内容文章" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/articles": { - "get": { - "summary": "APP 谱文列表", - "deprecated": false, - "description": "", - "tags": [ - "内容文章" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "post": { - "summary": "APP 新增谱文", - "deprecated": false, - "description": "", - "tags": [ - "内容文章" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArticleBody" - }, - "example": { - "categoryId": 900040001, - "articleTitle": "族谱源流", - "articleSummary": "介绍本支源流", - "coverOssId": "2060000000000000000", - "articleContent": "

article content

", - "authorName": "族谱管理员", - "sortOrder": 1, - "status": "0" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/articles/{articleId}": { - "get": { - "summary": "APP 谱文详情", - "deprecated": false, - "description": "", - "tags": [ - "内容文章" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "articleId", - "in": "path", - "description": "谱文/官网文章ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "put": { - "summary": "APP 修改谱文", - "deprecated": false, - "description": "", - "tags": [ - "内容文章" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "articleId", - "in": "path", - "description": "谱文/官网文章ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArticleBody" - }, - "example": { - "categoryId": 900040001, - "articleTitle": "族谱源流", - "articleSummary": "介绍本支源流", - "coverOssId": "2060000000000000000", - "articleContent": "

article content

", - "authorName": "族谱管理员", - "sortOrder": 1, - "status": "0" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/help-articles": { - "get": { - "summary": "APP 帮助文章列表", - "deprecated": false, - "description": "", - "tags": [ - "内容文章" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID", - "example": "ced7e5f0498645c6ec642dcf450b036f", - "schema": { - "type": "string", - "default": "ced7e5f0498645c6ec642dcf450b036f" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/help-articles/{helpId}": { - "get": { - "summary": "APP 帮助文章详情", - "deprecated": false, - "description": "", - "tags": [ - "内容文章" - ], - "parameters": [ - { - "name": "helpId", - "in": "path", - "description": "帮助文章ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID", - "example": "ced7e5f0498645c6ec642dcf450b036f", - "schema": { - "type": "string", - "default": "ced7e5f0498645c6ec642dcf450b036f" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/promotions": { - "get": { - "summary": "APP 应用推广列表", - "deprecated": false, - "description": "", - "tags": [ - "内容文章" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID", - "example": "ced7e5f0498645c6ec642dcf450b036f", - "schema": { - "type": "string", - "default": "ced7e5f0498645c6ec642dcf450b036f" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/albums": { - "get": { - "summary": "APP 相册列表", - "deprecated": false, - "description": "", - "tags": [ - "相册" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "post": { - "summary": "APP 创建相册", - "deprecated": false, - "description": "", - "tags": [ - "相册" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AlbumBody" - }, - "example": { - "albumName": "老照片", - "albumDesc": "family old photos", - "coverOssId": "2060000000000000000", - "sortOrder": 1, - "status": "0" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/albums/{albumId}": { - "put": { - "summary": "APP 修改相册", - "deprecated": false, - "description": "", - "tags": [ - "相册" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "albumId", - "in": "path", - "description": "相册ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AlbumBody" - }, - "example": { - "albumName": "老照片", - "albumDesc": "family old photos", - "coverOssId": "2060000000000000000", - "sortOrder": 1, - "status": "0" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/albums/{albumId}/photos": { - "get": { - "summary": "APP 相册图片列表", - "deprecated": false, - "description": "", - "tags": [ - "相册" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "albumId", - "in": "path", - "description": "相册ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "post": { - "summary": "APP 上传相册图片记录", - "deprecated": false, - "description": "", - "tags": [ - "相册" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "albumId", - "in": "path", - "description": "相册ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AlbumPhotoBody" - }, - "example": { - "ossId": "2060000000000000000", - "photoTitle": "老宅合影", - "photoDesc": "old house photo", - "photographer": "彭小明", - "shootTime": "2026-07-09 10:00:00", - "sortOrder": 1, - "status": "0" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/ceremonies": { - "get": { - "summary": "APP 祭祀列表", - "deprecated": false, - "description": "", - "tags": [ - "祭祀" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "post": { - "summary": "APP 创建祭祀", - "deprecated": false, - "description": "", - "tags": [ - "祭祀" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CeremonyBody" - }, - "example": { - "ceremonyType": "ancestor", - "ceremonyTitle": "清明祭祖", - "ceremonyDesc": "online ancestor ceremony", - "ceremonyTime": "2026-04-04 09:00:00", - "location": "祠堂", - "coverOssId": "2060000000000000000", - "sortOrder": 1, - "status": "0" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}": { - "get": { - "summary": "APP 祭祀详情", - "deprecated": false, - "description": "", - "tags": [ - "祭祀" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "ceremonyId", - "in": "path", - "description": "祭祀/活动ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "put": { - "summary": "APP 修改祭祀", - "deprecated": false, - "description": "", - "tags": [ - "祭祀" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "ceremonyId", - "in": "path", - "description": "祭祀/活动ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CeremonyBody" - }, - "example": { - "ceremonyType": "ancestor", - "ceremonyTitle": "清明祭祖", - "ceremonyDesc": "online ancestor ceremony", - "ceremonyTime": "2026-04-04 09:00:00", - "location": "祠堂", - "coverOssId": "2060000000000000000", - "sortOrder": 1, - "status": "0" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}/gifts": { - "get": { - "summary": "APP 祭祀献礼列表", - "deprecated": false, - "description": "", - "tags": [ - "祭祀" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "ceremonyId", - "in": "path", - "description": "祭祀/活动ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "post": { - "summary": "APP 新增祭祀献礼", - "deprecated": false, - "description": "", - "tags": [ - "祭祀" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "ceremonyId", - "in": "path", - "description": "祭祀/活动ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CeremonyGiftBody" - }, - "example": { - "giverName": "彭小明", - "giftAmount": 66.66, - "giftMessage": "缅怀先祖" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/growth-records": { - "get": { - "summary": "APP 成长记录列表", - "deprecated": false, - "description": "", - "tags": [ - "族务记录" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "post": { - "summary": "APP 新增成长记录", - "deprecated": false, - "description": "", - "tags": [ - "族务记录" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GrowthRecordBody" - }, - "example": { - "lineagePersonId": 900020001, - "recordType": "birth", - "recordTitle": "出生记录", - "recordContent": "birth record", - "recordDate": "2026-07-09 10:00:00", - "remindTime": "2027-07-09 10:00:00", - "mediaOssIds": "2060000000000000001", - "sortOrder": 1, - "status": "0" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/growth-records/{recordId}": { - "get": { - "summary": "APP 成长记录详情", - "deprecated": false, - "description": "", - "tags": [ - "族务记录" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "recordId", - "in": "path", - "description": "记录ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "put": { - "summary": "APP 修改成长记录", - "deprecated": false, - "description": "", - "tags": [ - "族务记录" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "recordId", - "in": "path", - "description": "记录ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GrowthRecordBody" - }, - "example": { - "lineagePersonId": 900020001, - "recordType": "birth", - "recordTitle": "出生记录", - "recordContent": "birth record", - "recordDate": "2026-07-09 10:00:00", - "remindTime": "2027-07-09 10:00:00", - "mediaOssIds": "2060000000000000001", - "sortOrder": 1, - "status": "0" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/memos": { - "get": { - "summary": "APP 备忘录列表", - "deprecated": false, - "description": "", - "tags": [ - "族务记录" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "post": { - "summary": "APP 新增备忘录", - "deprecated": false, - "description": "", - "tags": [ - "族务记录" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MemoBody" - }, - "example": { - "memoTitle": "修谱事项", - "memoContent": "contact family members", - "remindTime": "2026-08-01 09:00:00", - "completed": "0", - "mediaOssIds": "2060000000000000001", - "sortOrder": 1, - "status": "0" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/memos/{memoId}": { - "get": { - "summary": "APP 备忘录详情", - "deprecated": false, - "description": "", - "tags": [ - "族务记录" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "memoId", - "in": "path", - "description": "", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "put": { - "summary": "APP 修改备忘录", - "deprecated": false, - "description": "", - "tags": [ - "族务记录" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "memoId", - "in": "path", - "description": "", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MemoBody" - }, - "example": { - "memoTitle": "修谱事项", - "memoContent": "contact family members", - "remindTime": "2026-08-01 09:00:00", - "completed": "0", - "mediaOssIds": "2060000000000000001", - "sortOrder": 1, - "status": "0" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/genealogies/{genealogyId}/merit-records": { - "get": { - "summary": "APP 功德记录列表", - "deprecated": false, - "description": "", - "tags": [ - "族务记录" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "post": { - "summary": "APP 新增功德记录", - "deprecated": false, - "description": "", - "tags": [ - "族务记录" - ], - "parameters": [ - { - "name": "genealogyId", - "in": "path", - "description": "家谱ID", - "required": true, - "example": 900001001, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MeritRecordBody" - }, - "example": { - "donorName": "彭小明", - "meritType": "donation", - "meritTitle": "修谱捐款", - "meritContent": "support genealogy work", - "amount": 100, - "meritTime": "2026-07-09 10:00:00", - "sortOrder": 1, - "status": "0" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/notifications": { - "get": { - "summary": "APP 消息通知列表", - "deprecated": false, - "description": "", - "tags": [ - "消息通知" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/notifications/{notificationId}/read": { - "post": { - "summary": "APP 标记通知已读", - "deprecated": false, - "description": "", - "tags": [ - "消息通知" - ], - "parameters": [ - { - "name": "notificationId", - "in": "path", - "description": "通知ID", - "required": true, - "example": "", - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/notifications/read-all": { - "post": { - "summary": "APP 全部标记已读", - "deprecated": false, - "description": "", - "tags": [ - "消息通知" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/VoidResult", - "description": "通用成功响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/feedback": { - "get": { - "summary": "APP 我的反馈列表", - "deprecated": false, - "description": "", - "tags": [ - "意见反馈" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "post": { - "summary": "APP 提交反馈", - "deprecated": false, - "description": "", - "tags": [ - "意见反馈" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FeedbackBody" - }, - "example": { - "feedbackType": "bug", - "feedbackContent": "upload image failed", - "contactInfo": "13800000000" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/vip/packages": { - "get": { - "summary": "APP VIP 套餐列表", - "deprecated": false, - "description": "", - "tags": [ - "VIP" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - }, - "/genealogy/app/vip/orders": { - "get": { - "summary": "APP VIP 订单列表", - "deprecated": false, - "description": "", - "tags": [ - "VIP" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/ListResult", - "description": "通用列表响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - }, - "post": { - "summary": "APP 创建 VIP 订单", - "deprecated": false, - "description": "", - "tags": [ - "VIP" - ], - "parameters": [ - { - "name": "clientid", - "in": "header", - "description": "客户端ID,请求Header携带,用于区分APP/PC/小程序等终端", - "required": true, - "example": "428a8310cd442757ae699df5d894f051", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VipOrderBody" - }, - "example": { - "packageId": 900060001, - "genealogyId": 900001001, - "payType": "wechat" - } - } - }, - "required": true - }, - "responses": { - "200": { - "$ref": "#/components/responses/ObjectResult", - "description": "通用对象响应" - } - }, - "security": [ - { - "SaToken": [] - } - ] - } - } - }, - "components": { - "schemas": { - "PasswordRegisterBody": { - "type": "object", - "required": [ - "grantType", - "tenantId", - "phone", - "password" - ], - "properties": { - "clientId": { - "description": "客户端ID,对应后台客户端管理中的APP/PC/小程序等终端", - "type": "string" - }, - "grantType": { - "description": "授权类型,例如password、sms、wechat、apple", - "type": "string", - "example": "password" - }, - "tenantId": { - "description": "租户ID,用于区分不同租户的数据和验证策略", - "type": "string", - "example": "000000" - }, - "phone": { - "description": "手机号", - "type": "string", - "example": "13800000000" - }, - "password": { - "type": "string", - "description": "32 位 MD5", - "example": "e10adc3949ba59abbe56e057f20f883e" - }, - "nickName": { - "description": "用户昵称", - "type": "string" - }, - "registerSource": { - "description": "注册来源,例如APP、PC、H5、MINI_PROGRAM", - "type": "string" - }, - "validToken": { - "description": "验证中心通过后返回的票据,用于注册/登录/换绑等二次校验", - "type": "string" - } - } - }, - "PasswordLoginBody": { - "type": "object", - "required": [ - "grantType", - "tenantId", - "phone", - "password" - ], - "properties": { - "clientId": { - "description": "客户端ID,对应后台客户端管理中的APP/PC/小程序等终端", - "type": "string" - }, - "grantType": { - "description": "授权类型,例如password、sms、wechat、apple", - "type": "string", - "example": "password" - }, - "tenantId": { - "description": "租户ID,用于区分不同租户的数据和验证策略", - "type": "string", - "example": "000000" - }, - "phone": { - "description": "手机号", - "type": "string", - "example": "13800000000" - }, - "password": { - "type": "string", - "description": "32 位 MD5", - "example": "e10adc3949ba59abbe56e057f20f883e" - }, - "validToken": { - "description": "验证中心通过后返回的票据,用于注册/登录/换绑等二次校验", - "type": "string" - } - } - }, - "SmsLoginBody": { - "type": "object", - "required": [ - "grantType", - "tenantId", - "phone", - "smsCode" - ], - "properties": { - "clientId": { - "description": "客户端ID,对应后台客户端管理中的APP/PC/小程序等终端", - "type": "string" - }, - "grantType": { - "description": "授权类型,例如password、sms、wechat、apple", - "type": "string", - "example": "sms" - }, - "tenantId": { - "description": "租户ID,用于区分不同租户的数据和验证策略", - "type": "string", - "example": "000000" - }, - "phone": { - "description": "手机号", - "type": "string", - "example": "13800000000" - }, - "smsCode": { - "description": "短信验证码", - "type": "string", - "example": "1234" - } - } - }, - "SmsCodeBody": { - "type": "object", - "required": [ - "grantType", - "tenantId", - "sceneCode", - "phone", - "validToken" - ], - "properties": { - "clientId": { - "description": "客户端ID,对应后台客户端管理中的APP/PC/小程序等终端", - "type": "string" - }, - "grantType": { - "description": "授权类型,例如password、sms、wechat、apple", - "type": "string", - "example": "sms" - }, - "tenantId": { - "description": "租户ID,用于区分不同租户的数据和验证策略", - "type": "string", - "example": "000000" - }, - "sceneCode": { - "description": "验证场景编码,例如APP_LOGIN、PC_LOGIN、APP_REGISTER", - "type": "string", - "example": "APP_LOGIN" - }, - "phone": { - "description": "手机号", - "type": "string", - "example": "13800000000" - }, - "validToken": { - "description": "验证中心通过后返回的票据,用于注册/登录/换绑等二次校验", - "type": "string" - } - } - }, - "ProfileUpdateBody": { - "type": "object", - "properties": { - "nickName": { - "description": "用户昵称", - "type": "string" - }, - "avatarOssId": { - "description": "头像文件OSS ID", - "type": "integer", - "format": "int64" - }, - "sex": { - "description": "性别,建议使用系统字典值", - "type": "string" - }, - "birthday": { - "description": "生日,格式 yyyy-MM-dd", - "type": "string", - "format": "date" - }, - "provinceCode": { - "type": "string" - }, - "cityCode": { - "type": "string" - }, - "districtCode": { - "type": "string" - } - } - }, - "PasswordChangeBody": { - "type": "object", - "required": [ - "oldPassword", - "newPassword" - ], - "properties": { - "oldPassword": { - "type": "string", - "description": "32 位 MD5" - }, - "newPassword": { - "type": "string", - "description": "32 位 MD5" - } - } - }, - "PasswordResetBody": { - "type": "object", - "required": [ - "tenantId", - "phone", - "smsCode", - "newPassword" - ], - "properties": { - "tenantId": { - "description": "租户ID,用于区分不同租户的数据和验证策略", - "type": "string", - "example": "000000" - }, - "phone": { - "description": "手机号", - "type": "string" - }, - "smsCode": { - "description": "短信验证码", - "type": "string" - }, - "newPassword": { - "type": "string", - "description": "32 位 MD5" - }, - "validToken": { - "description": "验证中心通过后返回的票据,用于注册/登录/换绑等二次校验", - "type": "string" - } - } - }, - "PhoneChangeBody": { - "type": "object", - "required": [ - "newPhone", - "smsCode" - ], - "properties": { - "newPhone": { - "type": "string" - }, - "smsCode": { - "description": "短信验证码", - "type": "string" - }, - "validToken": { - "description": "验证中心通过后返回的票据,用于注册/登录/换绑等二次校验", - "type": "string" - } - } - }, - "AccountDeactivateBody": { - "type": "object", - "required": [ - "password" - ], - "properties": { - "password": { - "type": "string", - "description": "32 位 MD5" - }, - "reason": { - "description": "操作原因或说明", - "type": "string" - } - } - }, - "ResumableInitBody": { - "type": "object", - "required": [ - "fileName", - "fileSize", - "fileMd5", - "chunkSize", - "totalChunks" - ], - "properties": { - "fileName": { - "description": "原始文件名", - "type": "string" - }, - "fileSize": { - "description": "文件大小,单位字节", - "type": "integer", - "format": "int64" - }, - "fileMd5": { - "description": "完整文件MD5,用于秒传和完整性校验", - "type": "string" - }, - "contentType": { - "description": "文件MIME类型,例如 image/jpeg、video/mp4", - "type": "string" - }, - "chunkSize": { - "description": "单个分片大小,单位字节", - "type": "integer", - "example": 4194304 - }, - "totalChunks": { - "description": "总分片数", - "type": "integer" - }, - "bizType": { - "description": "业务类型,例如avatar、cover、feed_image", - "type": "string" - }, - "usageScene": { - "description": "文件使用场景,便于后续引用统计和清理", - "type": "string" - } - } - }, - "ResumableCompleteBody": { - "type": "object", - "required": [ - "uploadId", - "fileMd5", - "fileSize" - ], - "properties": { - "uploadId": { - "description": "分片上传任务ID", - "type": "string" - }, - "fileMd5": { - "description": "完整文件MD5,用于秒传和完整性校验", - "type": "string" - }, - "fileSize": { - "description": "文件大小,单位字节", - "type": "integer", - "format": "int64" - } - } - }, - "FileReferenceBody": { - "type": "object", - "required": [ - "bizType", - "bizTable", - "bizId", - "bizField" - ], - "properties": { - "bizType": { - "description": "业务类型,例如avatar、cover、feed_image", - "type": "string", - "example": "family_feed" - }, - "bizName": { - "description": "业务名称,用于后台展示文件引用来源", - "type": "string", - "example": "家族圈动态" - }, - "bizTable": { - "description": "业务表名,用于文件引用绑定", - "type": "string", - "example": "gen_family_feed" - }, - "bizId": { - "description": "业务数据ID,用于文件引用绑定", - "type": "integer", - "format": "int64" - }, - "bizField": { - "description": "业务字段名,例如avatar_oss_id、cover_oss_id", - "type": "string", - "example": "media_ids" - }, - "ossId": { - "description": "OSS文件ID,表单内部使用,用户侧应通过上传组件获取", - "type": "integer", - "format": "int64" - }, - "ossIds": { - "type": "string", - "example": "2060001,2060002" - }, - "usageScene": { - "description": "文件使用场景,便于后续引用统计和清理", - "type": "string" - }, - "usageName": { - "type": "string" - } - } - }, - "GenerationPoemBatchBody": { - "type": "object", - "properties": { - "content": { - "type": "string", - "example": "德承家亦" - }, - "stopMissingOldGeneration": { - "type": "boolean", - "example": false - } - } - }, - "LineagePersonBody": { - "type": "object", - "properties": { - "appUserId": { - "type": "integer", - "format": "int64" - }, - "personNo": { - "type": "string" - }, - "personName": { - "type": "string" - }, - "aliasName": { - "type": "string" - }, - "sex": { - "description": "性别,建议使用系统字典值", - "type": "string", - "example": "0" - }, - "generationNo": { - "description": "世代序号", - "type": "integer" - }, - "generationName": { - "description": "字辈", - "type": "string" - }, - "avatarOssId": { - "description": "头像文件OSS ID", - "type": "integer", - "format": "int64" - }, - "birthDate": { - "type": "string" - }, - "deathDate": { - "type": "string" - }, - "introduction": { - "type": "string" - } - } - }, - "FamilyFeedBody": { - "type": "object", - "properties": { - "content": { - "type": "string" - }, - "mediaOssIds": { - "description": "媒体文件OSS ID列表,多个用逗号或数组传递以接口约定为准", - "type": "string", - "example": "2060001,2060002" - }, - "visibility": { - "description": "可见范围,例如0私密、1公开、2成员可见", - "type": "string", - "example": "1" - }, - "status": { - "description": "状态,建议使用对应字典值", - "type": "string", - "example": "0" - } - } - }, - "FamilyFeedCommentBody": { - "type": "object", - "required": [ - "content" - ], - "properties": { - "parentCommentId": { - "type": "integer", - "format": "int64", - "nullable": true - }, - "replyUserId": { - "type": "integer", - "format": "int64", - "nullable": true - }, - "content": { - "type": "string" - } - } - }, - "GenealogyCreateBody": { - "type": "object", - "required": [ - "genealogyName", - "surname", - "regionCode" - ], - "properties": { - "genealogyName": { - "description": "家谱名称", - "type": "string" - }, - "surname": { - "description": "姓氏", - "type": "string" - }, - "ancestralHall": { - "description": "堂号/祠堂名称", - "type": "string" - }, - "originPlace": { - "description": "籍贯/起源地", - "type": "string" - }, - "regionCode": { - "description": "行政区划编码", - "type": "string" - }, - "addressDetail": { - "description": "详细地址", - "type": "string" - }, - "coverOssId": { - "description": "封面图片OSS ID", - "type": "integer", - "format": "int64" - }, - "intro": { - "description": "简介", - "type": "string" - }, - "visibility": { - "description": "可见范围,例如0私密、1公开、2成员可见", - "type": "string" - }, - "joinMode": { - "description": "加入方式,例如0关闭、1审核、2邀请码", - "type": "string" - } - }, - "example": { - "genealogyName": "彭氏家谱", - "surname": "彭", - "ancestralHall": "陇西堂", - "originPlace": "江西吉安", - "regionCode": "360800", - "addressDetail": "江西省吉安市", - "coverOssId": 2060000000000000000, - "intro": "彭氏家谱简介", - "visibility": "1", - "joinMode": "1" - } - }, - "GenealogyUpdateBody": { - "type": "object", - "properties": { - "genealogyName": { - "description": "家谱名称", - "type": "string" - }, - "surname": { - "description": "姓氏", - "type": "string" - }, - "ancestralHall": { - "description": "堂号/祠堂名称", - "type": "string" - }, - "originPlace": { - "description": "籍贯/起源地", - "type": "string" - }, - "regionCode": { - "description": "行政区划编码", - "type": "string" - }, - "addressDetail": { - "description": "详细地址", - "type": "string" - }, - "coverOssId": { - "description": "封面图片OSS ID", - "type": "integer", - "format": "int64" - }, - "intro": { - "description": "简介", - "type": "string" - }, - "visibility": { - "description": "可见范围,例如0私密、1公开、2成员可见", - "type": "string" - }, - "joinMode": { - "description": "加入方式,例如0关闭、1审核、2邀请码", - "type": "string" - } - }, - "example": { - "genealogyName": "彭氏家谱", - "surname": "彭", - "ancestralHall": "陇西堂", - "originPlace": "江西吉安", - "regionCode": "360800", - "addressDetail": "江西省吉安市", - "coverOssId": 2060000000000000000, - "intro": "更新后的家谱简介", - "visibility": "1", - "joinMode": "1" - } - }, - "GenealogyJoinApplyBody": { - "type": "object", - "properties": { - "applicantName": { - "description": "申请人姓名", - "type": "string" - }, - "phone": { - "description": "手机号", - "type": "string" - }, - "relationDesc": { - "description": "与家谱/人物的关系说明", - "type": "string" - }, - "applyReason": { - "description": "申请理由", - "type": "string" - }, - "inviterUserId": { - "description": "邀请人业务用户ID", - "type": "integer", - "format": "int64" - } - }, - "example": { - "applicantName": "彭小明", - "phone": "13800000000", - "relationDesc": "本族成员", - "applyReason": "申请加入家谱维护", - "inviterUserId": 900000001 - } - }, - "GenealogyJoinAuditBody": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "description": "状态,建议使用对应字典值", - "type": "string" - }, - "auditRemark": { - "description": "审核备注", - "type": "string" - } - }, - "example": { - "status": "1", - "auditRemark": "信息核验通过" - } - }, - "GenealogyMemberUpdateBody": { - "type": "object", - "properties": { - "memberName": { - "description": "成员姓名", - "type": "string" - }, - "relationName": { - "description": "成员关系名称", - "type": "string" - }, - "roleType": { - "description": "成员角色类型,例如创建者、管理员、普通成员", - "type": "string" - }, - "lineagePersonId": { - "description": "绑定的世系人物ID", - "type": "integer", - "format": "int64" - } - }, - "example": { - "memberName": "彭小明", - "relationName": "族亲", - "roleType": "member", - "lineagePersonId": 900020001 - } - }, - "GenealogyOwnerTransferBody": { - "type": "object", - "required": [ - "targetMemberId" - ], - "properties": { - "targetMemberId": { - "description": "目标成员ID", - "type": "integer", - "format": "int64" - } - }, - "example": { - "targetMemberId": 900010002 - } - }, - "GenerationPoemBody": { - "type": "object", - "required": [ - "generationNo", - "generationText" - ], - "properties": { - "generationNo": { - "description": "世代序号", - "type": "integer", - "format": "int64" - }, - "generationText": { - "description": "字辈内容,可单字或批量字辈文本", - "type": "string" - }, - "description": { - "description": "说明或备注", - "type": "string" - }, - "sortOrder": { - "description": "排序值,数值越小越靠前", - "type": "integer", - "format": "int64" - }, - "status": { - "description": "状态,建议使用对应字典值", - "type": "string" - } - }, - "example": { - "generationNo": 5, - "generationText": "忠", - "description": "fifth generation poem", - "sortOrder": 5, - "status": "0" - } - }, - "ArticleBody": { - "type": "object", - "required": [ - "articleTitle", - "articleContent" - ], - "properties": { - "categoryId": { - "description": "分类ID", - "type": "integer", - "format": "int64" - }, - "articleTitle": { - "description": "文章标题", - "type": "string" - }, - "articleSummary": { - "description": "文章摘要", - "type": "string" - }, - "coverOssId": { - "description": "封面图片OSS ID", - "type": "integer", - "format": "int64" - }, - "articleContent": { - "description": "文章内容", - "type": "string" - }, - "authorName": { - "description": "作者名称", - "type": "string" - }, - "sortOrder": { - "description": "排序值,数值越小越靠前", - "type": "integer", - "format": "int64" - }, - "status": { - "description": "状态,建议使用对应字典值", - "type": "string" - } - }, - "example": { - "categoryId": 900040001, - "articleTitle": "族谱源流", - "articleSummary": "介绍本支源流", - "coverOssId": 2060000000000000000, - "articleContent": "

article content

", - "authorName": "族谱管理员", - "sortOrder": 1, - "status": "0" - } - }, - "AlbumBody": { - "type": "object", - "required": [ - "albumName" - ], - "properties": { - "albumName": { - "description": "相册名称", - "type": "string" - }, - "albumDesc": { - "description": "相册说明", - "type": "string" - }, - "coverOssId": { - "description": "封面图片OSS ID", - "type": "integer", - "format": "int64" - }, - "sortOrder": { - "description": "排序值,数值越小越靠前", - "type": "integer", - "format": "int64" - }, - "status": { - "description": "状态,建议使用对应字典值", - "type": "string" - } - }, - "example": { - "albumName": "老照片", - "albumDesc": "family old photos", - "coverOssId": 2060000000000000000, - "sortOrder": 1, - "status": "0" - } - }, - "AlbumPhotoBody": { - "type": "object", - "required": [ - "ossId" - ], - "properties": { - "ossId": { - "description": "OSS文件ID,表单内部使用,用户侧应通过上传组件获取", - "type": "integer", - "format": "int64" - }, - "photoTitle": { - "description": "图片标题", - "type": "string" - }, - "photoDesc": { - "description": "图片说明", - "type": "string" - }, - "photographer": { - "description": "拍摄人", - "type": "string" - }, - "shootTime": { - "description": "拍摄时间", - "type": "string" - }, - "sortOrder": { - "description": "排序值,数值越小越靠前", - "type": "integer", - "format": "int64" - }, - "status": { - "description": "状态,建议使用对应字典值", - "type": "string" - } - }, - "example": { - "ossId": 2060000000000000000, - "photoTitle": "老宅合影", - "photoDesc": "old house photo", - "photographer": "彭小明", - "shootTime": "2026-07-09 10:00:00", - "sortOrder": 1, - "status": "0" - } - }, - "CeremonyBody": { - "type": "object", - "required": [ - "ceremonyType", - "ceremonyTitle" - ], - "properties": { - "ceremonyType": { - "description": "祭祀/活动类型", - "type": "string" - }, - "ceremonyTitle": { - "description": "祭祀/活动标题", - "type": "string" - }, - "ceremonyDesc": { - "description": "祭祀/活动说明", - "type": "string" - }, - "ceremonyTime": { - "description": "祭祀/活动时间", - "type": "string" - }, - "location": { - "description": "地点", - "type": "string" - }, - "coverOssId": { - "description": "封面图片OSS ID", - "type": "integer", - "format": "int64" - }, - "sortOrder": { - "description": "排序值,数值越小越靠前", - "type": "integer", - "format": "int64" - }, - "status": { - "description": "状态,建议使用对应字典值", - "type": "string" - } - }, - "example": { - "ceremonyType": "ancestor", - "ceremonyTitle": "清明祭祖", - "ceremonyDesc": "online ancestor ceremony", - "ceremonyTime": "2026-04-04 09:00:00", - "location": "祠堂", - "coverOssId": 2060000000000000000, - "sortOrder": 1, - "status": "0" - } - }, - "CeremonyGiftBody": { - "type": "object", - "required": [ - "giftAmount" - ], - "properties": { - "giverName": { - "description": "赠送人/献礼人姓名", - "type": "string" - }, - "giftAmount": { - "description": "礼物金额", - "type": "number", - "format": "double" - }, - "giftMessage": { - "description": "礼物留言", - "type": "string" - } - }, - "example": { - "giverName": "彭小明", - "giftAmount": 66.66, - "giftMessage": "缅怀先祖" - } - }, - "GrowthRecordBody": { - "type": "object", - "required": [ - "recordTitle" - ], - "properties": { - "lineagePersonId": { - "description": "绑定的世系人物ID", - "type": "integer", - "format": "int64" - }, - "recordType": { - "description": "记录类型", - "type": "string" - }, - "recordTitle": { - "description": "记录标题", - "type": "string" - }, - "recordContent": { - "description": "记录内容", - "type": "string" - }, - "recordDate": { - "description": "记录日期", - "type": "string" - }, - "remindTime": { - "description": "提醒时间", - "type": "string" - }, - "mediaOssIds": { - "description": "媒体文件OSS ID列表,多个用逗号或数组传递以接口约定为准", - "type": "string" - }, - "sortOrder": { - "description": "排序值,数值越小越靠前", - "type": "integer", - "format": "int64" - }, - "status": { - "description": "状态,建议使用对应字典值", - "type": "string" - } - }, - "example": { - "lineagePersonId": 900020001, - "recordType": "birth", - "recordTitle": "出生记录", - "recordContent": "birth record", - "recordDate": "2026-07-09 10:00:00", - "remindTime": "2027-07-09 10:00:00", - "mediaOssIds": "2060000000000000001", - "sortOrder": 1, - "status": "0" - } - }, - "MemoBody": { - "type": "object", - "required": [ - "memoTitle" - ], - "properties": { - "memoTitle": { - "description": "备忘标题", - "type": "string" - }, - "memoContent": { - "description": "备忘内容", - "type": "string" - }, - "remindTime": { - "description": "提醒时间", - "type": "string" - }, - "completed": { - "description": "是否已完成", - "type": "string" - }, - "mediaOssIds": { - "description": "媒体文件OSS ID列表,多个用逗号或数组传递以接口约定为准", - "type": "string" - }, - "sortOrder": { - "description": "排序值,数值越小越靠前", - "type": "integer", - "format": "int64" - }, - "status": { - "description": "状态,建议使用对应字典值", - "type": "string" - } - }, - "example": { - "memoTitle": "修谱事项", - "memoContent": "contact family members", - "remindTime": "2026-08-01 09:00:00", - "completed": "0", - "mediaOssIds": "2060000000000000001", - "sortOrder": 1, - "status": "0" - } - }, - "MeritRecordBody": { - "type": "object", - "required": [ - "donorName", - "meritTitle" - ], - "properties": { - "donorName": { - "description": "功德人/捐赠人姓名", - "type": "string" - }, - "meritType": { - "description": "功德类型", - "type": "string" - }, - "meritTitle": { - "description": "功德标题", - "type": "string" - }, - "meritContent": { - "description": "功德内容", - "type": "string" - }, - "amount": { - "description": "金额", - "type": "number", - "format": "double" - }, - "meritTime": { - "description": "功德时间", - "type": "string" - }, - "sortOrder": { - "description": "排序值,数值越小越靠前", - "type": "integer", - "format": "int64" - }, - "status": { - "description": "状态,建议使用对应字典值", - "type": "string" - } - }, - "example": { - "donorName": "彭小明", - "meritType": "donation", - "meritTitle": "修谱捐款", - "meritContent": "support genealogy work", - "amount": 100, - "meritTime": "2026-07-09 10:00:00", - "sortOrder": 1, - "status": "0" - } - }, - "FeedbackBody": { - "type": "object", - "required": [ - "feedbackContent" - ], - "properties": { - "feedbackType": { - "description": "反馈类型", - "type": "string" - }, - "feedbackContent": { - "description": "反馈内容", - "type": "string" - }, - "contactInfo": { - "description": "联系方式", - "type": "string" - } - }, - "example": { - "feedbackType": "bug", - "feedbackContent": "upload image failed", - "contactInfo": "13800000000" - } - }, - "VipOrderBody": { - "type": "object", - "required": [ - "packageId" - ], - "properties": { - "packageId": { - "description": "VIP套餐ID", - "type": "integer", - "format": "int64" - }, - "genealogyId": { - "description": "家谱ID", - "type": "integer", - "format": "int64" - }, - "payType": { - "description": "支付方式", - "type": "string" - } - }, - "example": { - "packageId": 900060001, - "genealogyId": 900001001, - "payType": "wechat" - } - }, - "VerificationChallengeBody": { - "type": "object", - "required": [ - "sceneCode" - ], - "properties": { - "tenantId": { - "type": "string", - "description": "租户 ID" - }, - "clientId": { - "type": "string", - "description": "客户端 ID" - }, - "sceneCode": { - "type": "string", - "description": "验证场景编码,如 ADMIN_LOGIN/APP_LOGIN/APP_REGISTER" - }, - "subject": { - "type": "string", - "description": "验证主体,如手机号/用户名/IP" - } - }, - "example": { - "tenantId": "000000", - "clientId": "428a8310cd442757ae699df5d894f051", - "sceneCode": "APP_LOGIN", - "subject": "13800000000" - } - }, - "VerificationCheckBody": { - "type": "object", - "required": [ - "sceneCode" - ], - "properties": { - "tenantId": { - "description": "租户ID,用于区分不同租户的数据和验证策略", - "type": "string" - }, - "clientId": { - "description": "客户端ID,对应后台客户端管理中的APP/PC/小程序等终端", - "type": "string" - }, - "sceneCode": { - "description": "验证场景编码,例如APP_LOGIN、PC_LOGIN、APP_REGISTER", - "type": "string" - }, - "subject": { - "description": "验证主体,通常为手机号、用户ID或登录账号", - "type": "string" - }, - "challengeId": { - "description": "验证挑战ID,由验证挑战接口返回", - "type": "string" - }, - "providerCode": { - "type": "string", - "description": "验证服务,tianai 或 ruoyi_image" - }, - "captchaType": { - "type": "string", - "description": "SLIDER/ROTATE/CONCAT/WORD_IMAGE_CLICK/math/char" - }, - "payload": { - "type": "object", - "additionalProperties": true, - "description": "前端验证控件返回的轨迹/点击/图形验证码数据", - "properties": {} - } - } - }, - "RVoid": { - "type": "object", - "properties": { - "code": { - "description": "系统图形验证码或响应状态码", - "type": "integer", - "example": 200 - }, - "msg": { - "description": "响应消息", - "type": "string", - "example": "操作成功" - }, - "data": { - "description": "响应数据主体", - "type": "null" - } - } - }, - "RObject": { - "type": "object", - "properties": { - "code": { - "description": "系统图形验证码或响应状态码", - "type": "integer", - "example": 200 - }, - "msg": { - "description": "响应消息", - "type": "string", - "example": "操作成功" - }, - "data": { - "description": "响应数据主体", - "type": "object", - "additionalProperties": true, - "properties": {} - } - } - }, - "RList": { - "type": "object", - "properties": { - "code": { - "description": "系统图形验证码或响应状态码", - "type": "integer", - "example": 200 - }, - "msg": { - "description": "响应消息", - "type": "string", - "example": "操作成功" - }, - "data": { - "description": "响应数据主体", - "type": "array", - "items": { - "type": "object", - "additionalProperties": true, - "properties": {} - } - } - } - }, - "PageResult": { - "type": "object", - "properties": { - "code": { - "description": "系统图形验证码或响应状态码", - "type": "integer", - "example": 200 - }, - "msg": { - "description": "响应消息", - "type": "string", - "example": "操作成功" - }, - "rows": { - "description": "分页数据列表", - "type": "array", - "items": { - "type": "object", - "additionalProperties": true, - "properties": {} - } - }, - "total": { - "type": "integer", - "example": 0 - } - } - }, - "RLogin": { - "type": "object", - "properties": { - "code": { - "description": "系统图形验证码或响应状态码", - "type": "integer", - "example": 200 - }, - "msg": { - "description": "响应消息", - "type": "string", - "example": "操作成功" - }, - "data": { - "description": "响应数据主体", - "$ref": "#/components/schemas/LoginVo" - } - } - }, - "LoginVo": { - "type": "object", - "properties": { - "token": { - "type": "string" - }, - "accessToken": { - "type": "string" - }, - "tokenValue": { - "type": "string" - }, - "userId": { - "type": "integer", - "format": "int64" - }, - "tenantId": { - "description": "租户ID,用于区分不同租户的数据和验证策略", - "type": "string" - }, - "clientId": { - "description": "客户端ID,对应后台客户端管理中的APP/PC/小程序等终端", - "type": "string" - }, - "clientKey": { - "type": "string" - } - } - }, - "RFileUpload": { - "type": "object", - "properties": { - "code": { - "description": "系统图形验证码或响应状态码", - "type": "integer", - "example": 200 - }, - "msg": { - "description": "响应消息", - "type": "string", - "example": "操作成功" - }, - "data": { - "description": "响应数据主体", - "$ref": "#/components/schemas/FileUploadVo" - } - } - }, - "FileUploadVo": { - "type": "object", - "properties": { - "ossId": { - "description": "OSS文件ID,表单内部使用,用户侧应通过上传组件获取", - "type": "integer", - "format": "int64" - }, - "url": { - "type": "string" - }, - "thumbnailUrl": { - "type": "string", - "nullable": true - }, - "fileName": { - "description": "原始文件名", - "type": "string" - }, - "originalName": { - "type": "string" - } - } - }, - "RVerificationRequire": { - "type": "object", - "properties": { - "code": { - "description": "系统图形验证码或响应状态码", - "type": "integer", - "example": 200 - }, - "msg": { - "description": "响应消息", - "type": "string", - "example": "操作成功" - }, - "data": { - "description": "响应数据主体", - "$ref": "#/components/schemas/VerificationRequireVo" - } - } - }, - "VerificationRequireVo": { - "type": "object", - "properties": { - "required": { - "description": "当前场景是否需要验证", - "type": "boolean" - }, - "providerCode": { - "description": "第三方服务商编码", - "type": "string" - }, - "captchaType": { - "description": "验证码类型,例如SLIDER、ROTATE、CONCAT、WORD_IMAGE_CLICK", - "type": "string" - }, - "sceneCode": { - "description": "验证场景编码,例如APP_LOGIN、PC_LOGIN、APP_REGISTER", - "type": "string" - }, - "ttlSeconds": { - "description": "验证或票据有效秒数", - "type": "integer" - } - }, - "example": { - "required": true, - "providerCode": "tianai", - "captchaType": "SLIDER", - "sceneCode": "APP_LOGIN", - "ttlSeconds": 300 - } - }, - "RVerificationChallenge": { - "type": "object", - "properties": { - "code": { - "description": "系统图形验证码或响应状态码", - "type": "integer", - "example": 200 - }, - "msg": { - "description": "响应消息", - "type": "string", - "example": "操作成功" - }, - "data": { - "description": "响应数据主体", - "$ref": "#/components/schemas/VerificationChallengeVo" - } - } - }, - "VerificationChallengeVo": { - "type": "object", - "properties": { - "required": { - "description": "当前场景是否需要验证", - "type": "boolean" - }, - "providerCode": { - "description": "第三方服务商编码", - "type": "string" - }, - "captchaType": { - "description": "验证码类型,例如SLIDER、ROTATE、CONCAT、WORD_IMAGE_CLICK", - "type": "string" - }, - "challengeId": { - "description": "验证挑战ID,由验证挑战接口返回", - "type": "string" - }, - "uuid": { - "type": "string", - "description": "系统图形验证码 uuid" - }, - "img": { - "type": "string", - "description": "系统图形验证码 base64 图片" - }, - "payload": { - "type": "object", - "additionalProperties": true, - "description": "天爱验证码数据,包括背景图、模板图、尺寸等", - "properties": {} - }, - "expireSeconds": { - "description": "验证挑战过期秒数", - "type": "integer" - } - }, - "example": { - "required": true, - "providerCode": "tianai", - "captchaType": "SLIDER", - "challengeId": "CAPTCHA_CHALLENGE_ID", - "payload": { - "backgroundImage": "data:image/png;base64,...", - "templateImage": "data:image/png;base64,...", - "backgroundImageWidth": 340, - "backgroundImageHeight": 180 - }, - "expireSeconds": 300 - } - }, - "RVerificationCheck": { - "type": "object", - "properties": { - "code": { - "description": "系统图形验证码或响应状态码", - "type": "integer", - "example": 200 - }, - "msg": { - "description": "响应消息", - "type": "string", - "example": "操作成功" - }, - "data": { - "description": "响应数据主体", - "$ref": "#/components/schemas/VerificationCheckVo" - } - } - }, - "VerificationCheckVo": { - "type": "object", - "properties": { - "passed": { - "description": "验证是否通过", - "type": "boolean" - }, - "validToken": { - "type": "string", - "description": "验证通过后交给业务接口的票据" - }, - "expireSeconds": { - "description": "验证挑战过期秒数", - "type": "integer" - }, - "message": { - "description": "返回消息", - "type": "string" - } - }, - "example": { - "passed": true, - "validToken": "captcha-ticket", - "expireSeconds": 300, - "message": "验证通过" - } - }, - "RLegacyCaptcha": { - "type": "object", - "properties": { - "code": { - "description": "系统图形验证码或响应状态码", - "type": "integer", - "example": 200 - }, - "msg": { - "description": "响应消息", - "type": "string", - "example": "操作成功" - }, - "data": { - "description": "响应数据主体", - "$ref": "#/components/schemas/LegacyCaptchaVo" - } - } - }, - "LegacyCaptchaVo": { - "type": "object", - "properties": { - "captchaEnabled": { - "type": "boolean" - }, - "uuid": { - "description": "系统图形验证码UUID", - "type": "string" - }, - "img": { - "type": "string", - "description": "base64 图形验证码" - } - }, - "example": { - "captchaEnabled": true, - "uuid": "captcha-uuid", - "img": "data:image/png;base64,..." - } - } - }, - "responses": { - "VoidResult": { - "description": "通用成功响应", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RVoid" - } - } - } - }, - "ObjectResult": { - "description": "通用对象响应", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RObject" - } - } - } - }, - "ListResult": { - "description": "通用列表响应", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RList" - } - } - } - }, - "PageResult": { - "description": "通用分页响应", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PageResult" - } - } - } - }, - "LoginResult": { - "description": "登录结果", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RLogin" - } - } - } - }, - "FileUploadResult": { - "description": "文件上传结果", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RFileUpload" - } - } - } - }, - "VerificationRequireResult": { - "description": "验证需求查询结果", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RVerificationRequire" - } - } - } - }, - "VerificationChallengeResult": { - "description": "验证挑战生成结果", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RVerificationChallenge" - } - } - } - }, - "VerificationCheckResult": { - "description": "验证校验结果", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RVerificationCheck" - } - } - } - }, - "LegacyCaptchaResult": { - "description": "兼容旧图形验证码结果", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RLegacyCaptcha" - } - } - } - } - }, - "securitySchemes": { - "SaToken": { - "type": "apiKey", - "in": "header", - "name": "Authorization", - "description": "登录后返回的 token。若本地配置使用 sa-token 名称,请按项目实际 token-name 调整。" - } - } - }, - "servers": [], - "security": [ - { - "SaToken": [] - } - ] -} \ No newline at end of file diff --git a/app.html b/app.html index 0b4925c..2ae45f6 100644 --- a/app.html +++ b/app.html @@ -98,7 +98,6 @@ -
diff --git a/docs/api-page-integration-2026-07-09.md b/docs/api-page-integration-2026-07-09.md deleted file mode 100644 index 8c0fc24..0000000 --- a/docs/api-page-integration-2026-07-09.md +++ /dev/null @@ -1,102 +0,0 @@ -# 接口对接规划与进度记录 - -## 基本信息 - -- 项目路径:`C:\Users\Administrator\Desktop\job\家谱` -- 接口文档:`APP.openapi.json` -- 记录创建时间:2026-07-09 11:51:16 +08:00 -- 执行范围:先做核心闭环页面接口对接,再按页面模块继续扩展。 -- 当前假设:接口文档以 `/genealogy/app` 为主,PC/H5 页面先复用这些用户侧接口。 - -## 约束摘要 - -- 先规划再实现,所有执行进度需要记录年月日时间。 -- 改动要小,只触碰接口对接必需文件。 -- 新接口契约由共享 API 客户端统一维护,页面脚本只调用封装方法。 -- 完成后做最小可验证检查;不能验证的地方要明确说明。 -- 样式尽量写入 `public.css` 或页面对应 CSS 文件,通过 class 控制,不用 JS 注入样式。 -- 新增 HTML、JS、CSS 注释统一使用中文。 -- CSS 结构先公共后页面:`public.css` 放全站公共组件,页面 CSS 只放本页面差异样式。 -- 个人中心模块页优先复用 `profile-module.css`,只有页面独有样式再新增或修改对应页面 CSS。 -- 页面专用 JS 放 `public/js`,命名跟页面或模块对应;公告详情页如需 JS 使用 `public/js/notice-detail.js`。 -- 业务代码不压缩,保持展开、可读;需要解释意图、边界或接口字段映射的位置使用中文注释。 -- 第三方库、压缩库、已存在乱码文件不做无关重写,避免引入额外风险。 - -## 核心闭环范围 - -1. 共享接口层 - - 新增统一 API 客户端,负责 `baseUrl`、`clientid`、`tenantId`、token 存取、请求头、响应解包和错误提示。 - - 默认 `clientid` 使用接口文档示例:`ced7e5f0498645c6ec642dcf450b036f`。 - - 默认 `tenantId` 使用接口文档示例:`000000`。 - - API 基础地址从 `window.GENEALOGY_API_BASE_URL` 或 `localStorage.genealogy_api_base_url` 读取,未配置时使用同域相对路径。 - - 浏览器端公共脚本放 `public/js`;`utils` 目前只适合作为纯工具类目录,不能作为页面脚本入口。 - - 页面专用 JS 按页面或模块放 `public/js`,例如认证模块用 `auth-pages.js`,公告详情页如需脚本则用 `notice-detail.js`。 - -2. 登录注册找回 - - `login.html` -> `POST /genealogy/app/auth/login` - - `register.html` -> `POST /genealogy/app/auth/register` - - `forgot-password.html` -> `POST /genealogy/app/auth/sms/code`,`PUT /genealogy/app/auth/password/reset` - - 密码按文档要求提交 32 位 MD5,复用已有 `public/js/md5.js`。 - -3. 家谱核心 - - `create-genealogy.html` -> `POST /genealogy/app/genealogies` - - `profile-families.html` -> `GET /genealogy/app/genealogies/mine` - - `plaza.html` -> `GET /genealogy/app/genealogies/public` - - `family-detail.html` -> `GET /genealogy/app/genealogies/{genealogyId}` - -4. 个人资料与反馈 - - `profile.html`、`profile-data.html` -> `GET /genealogy/app/auth/profile` - - `profile-feedback.html`、`submit-ticket.html` -> `GET/POST /genealogy/app/feedback` - -5. 拦截处理 - - `public/js/page-effects.js` 当前会拦截登录、注册、创建家谱、个人中心页面并显示“功能待开发”。 - - 对已接入接口的页面移除该拦截,保留未接入页面的提示。 - -## 验证计划 - -1. 新增共享 API 客户端测试,先确认测试失败,再实现通过。 -2. 检查核心页面均加载共享脚本和页面脚本。 -3. 用静态结构检查确认接口路径、表单字段、脚本引用存在。 -4. 运行语法检查或 Node 烟测,确保 JS 可加载、核心方法可调用。 -5. 检查新增样式是否位于 CSS 文件,不通过 JS 注入。 - -## 进度日志 - -- 2026-07-09 11:47:20 +08:00:已读取 `AGENTS.md`、项目目录、`APP.openapi.json`,确认项目是静态 HTML + jQuery/Layui,接口文档主要为 `/genealogy/app`。 -- 2026-07-09 11:51:16 +08:00:用户确认按核心闭环方案执行,创建本规划与进度记录。 -- 2026-07-09 11:52:53 +08:00:新增 `tests/api-client.test.js`,先运行 `node tests\api-client.test.js`,确认失败原因为缺少 `public/js/api-client.js`,进入共享 API 客户端实现。 -- 2026-07-09 11:54:00 +08:00:用户补充要求:尽量不用 JS 注入样式,样式写在公共或页面 CSS 中并通过 class 查找;新增 HTML/JS/CSS 注释使用中文。 -- 2026-07-09 11:57:19 +08:00:复查项目结构,确认 HTML 当前统一引用 `public/js`,`utils/DateUtil.js` 未被页面引用且存在乱码/语法风险;撤回过宽的 `api-pages.js` 方案,改为共享 `api-client.js` + 按模块/页面拆分脚本。 -- 2026-07-09 11:59:22 +08:00:用户补充 CSS 架构要求:抽出可复用公共样式,每个页面 CSS 只写差异样式;将 CSS 结构整理加入接口接入前置约束。 -- 2026-07-09 12:06:46 +08:00:完成认证模块第一步:新增 `public/js/auth-pages.js` 和 `tests/auth-pages.test.js`;`login.html`、`register.html`、`forgot-password.html` 改为真实表单;认证页公共 CSS 抽到 `public.css`,页面 CSS 只保留差异;重写 `page-effects.js`,移除“功能待开发”拦截和 JS 注入样式。 -- 2026-07-09 12:10:54 +08:00:完成家谱核心第一步:新增 `public/js/genealogy-pages.js` 和 `tests/genealogy-pages.test.js`;`create-genealogy.html` 接入创建家谱接口;`plaza.html` 接入公开家谱列表;`profile-families.html` 接入我的家谱列表。验证:`node tests\api-client.test.js`、`node tests\auth-pages.test.js`、`node tests\genealogy-pages.test.js` 均通过;`node --check` 检查新增业务 JS 均通过;新增业务 JS 未发现 `createElement("style")` 或 `style.textContent` 注入样式。 -- 2026-07-09 12:13:36 +08:00:用户补充可读性要求:现有该注释的位置补中文注释,代码不要压缩。执行范围限定为业务代码和本次维护的 CSS,第三方压缩库不改。 -- 2026-07-09 12:16:27 +08:00:已给本次新增/重写业务代码补中文注释,覆盖 `api-client.js`、`auth-pages.js`、`genealogy-pages.js`、`page-effects.js` 和 `public.css` 的关键逻辑/样式区块;代码保持展开可读。验证:三组 Node 测试通过,四个业务 JS `node --check` 通过,业务 JS 未发现样式注入写法。 -- 2026-07-09 12:23:36 +08:00:开始下一阶段:个人资料读取展示与反馈提交/历史反馈列表。范围:`profile.html`、`profile-data.html`、`profile-feedback.html`、`submit-ticket.html`;先写测试,再实现模块脚本和页面接入。 -- 2026-07-09 12:28:30 +08:00:完成个人资料与反馈阶段:新增 `public/js/profile-pages.js`、`public/js/feedback-pages.js`、`tests/profile-pages.test.js`、`tests/feedback-pages.test.js`;`profile.html`、`profile-data.html` 接入当前用户资料读取展示;`profile-feedback.html`、`submit-ticket.html` 接入反馈提交,`profile-feedback.html` 接入历史反馈列表。验证:五组 Node 测试通过,六个业务 JS `node --check` 通过,业务 JS 未发现样式注入写法。 -- 2026-07-09 12:31:51 +08:00:按用户要求重新验证第一阶段和第二阶段。第一阶段 API 客户端、认证页、家谱核心页测试均重新通过;第二阶段个人资料、反馈模块测试重新通过。复验命令包括 `node tests\api-client.test.js`、`node tests\auth-pages.test.js`、`node tests\genealogy-pages.test.js`、`node tests\profile-pages.test.js`、`node tests\feedback-pages.test.js`,以及六个业务脚本的 `node --check`。同时重新检查页面脚本引用、`data-*` 挂载点、业务 JS 样式注入写法和 `TODO/TBD/待实现/压缩` 标记,未发现异常。 -- 2026-07-09 12:38:13 +08:00:继续推进家谱详情与加入申请阶段。`family-detail.html` 接入 `GET /genealogy/app/genealogies/{genealogyId}`,通过 `data-family-*` 挂载标题、简介、统计和家谱信息,并把“申请加入”链接带上家谱 ID;`join-genealogy.html` 改为真实申请表单,接入 `POST /genealogy/app/genealogies/{genealogyId}/join-applies`。新增/更新 `api-client.js` 和 `genealogy-pages.js` 中的申请加入、详情渲染、表单提交逻辑,并在对应 CSS 中补中文注释和页面差异样式。验证:五组 Node 测试全部通过,六个业务 JS `node --check` 全部通过,页面脚本引用与 `data-*` 挂载点检查通过,业务 JS 未发现样式注入写法,核心文件未发现 `TODO/TBD/待实现/压缩` 标记。 -- 2026-07-09 12:40:15 +08:00:根据接口 schema 补充 `joinMode` 枚举中文展示映射:`0` 显示为“关闭加入”、`1` 显示为“审核加入”、`2` 显示为“邀请码加入”,避免详情页直接显示数字。重新验证五组 Node 测试、六个业务 JS 语法检查、详情页/加入页挂载点、业务 JS 样式注入检查和核心文件遗留标记检查,结果均正常。 -- 2026-07-09 12:45:24 +08:00:继续推进消息中心阶段。`profile-messages.html` 接入 `GET /genealogy/app/notifications`、`POST /genealogy/app/notifications/{notificationId}/read`、`POST /genealogy/app/notifications/read-all`,新增 `public/js/notification-pages.js` 负责消息列表渲染、单条已读、全部已读和刷新;`api-client.js` 新增通知相关封装;`profile-module.css` 增加按钮型模块卡片和未读消息样式,保持样式写入 CSS。验证:六组 Node 测试全部通过,七个业务 JS `node --check` 全部通过,消息页脚本引用和 `data-*` 挂载点检查通过,业务 JS 未发现样式注入写法,核心文件未发现 `TODO/TBD/待实现/压缩` 标记。 -- 2026-07-09 12:59:39 +08:00:按用户要求接入 `public/tac` 滑动验证到 `login.html`、`register.html`、`forgot-password.html`。依据 `APP.openapi.json` 的 `/captcha/require`、`/captcha/challenge`、`/captcha/verify` 字段实现 `public/js/captcha-pages.js` 适配层,将接口返回的 `captchaType/challengeId/payload` 转为 TAC 需要的 `type/id/backgroundImage/templateImage`,验证成功后把 `data.validToken` 写入当前表单隐藏字段;`auth-pages.js` 在登录、注册、发送短信验证码、重置密码前先执行滑动验证;`register.html` 原可见 `validToken` 输入改为昵称输入,避免和滑动验证隐藏字段冲突。三张认证页均引入 `public/tac/css/tac.css`、`public/tac/js/tac.min.js`、`public/js/captcha-pages.js`,并增加 `data-captcha-box` 挂载容器;`public.css` 增加认证页验证码容器样式。验证:七组 Node 测试全部通过,八个业务 JS `node --check` 全部通过,三张认证页 TAC 资源、隐藏 `validToken`、`data-captcha-box` 检查通过,自有业务 JS 未发现样式注入写法,核心文件未发现 `TODO/TBD/待实现/压缩` 标记;`git diff --check` 因当前目录不是 git 仓库无法执行。 -- 2026-07-09 13:07:18 +08:00:按用户提醒重新以 `APP.openapi.json` 为依据梳理剩余 `/genealogy/app` 页面归属,优先推进接口和页面最匹配的帮助中心。`help.html` 接入 `GET /genealogy/app/help-articles` 帮助文章列表,并在展开条目时按需调用 `GET /genealogy/app/help-articles/{helpId}` 补充详情;新增 `public/js/help-pages.js`,`api-client.js` 新增 `helpArticles`、`helpArticleDetail` 封装;`help.css` 补帮助列表加载状态注释和样式。验证:八组 Node 测试全部通过,九个业务 JS `node --check` 全部通过,帮助页 `data-help-list`、`api-client.js`、`help-pages.js` 引用检查通过,自有业务 JS 未发现样式注入写法,核心文件未发现 `TODO/TBD/待实现/压缩` 标记。 -- 2026-07-09 13:13:33 +08:00:继续按 `APP.openapi.json` 推进加入申请阶段。`profile-join-review.html` 接入 `GET /genealogy/app/genealogies/{genealogyId}/join-applies/pending` 待审核申请和 `PUT /genealogy/app/genealogies/{genealogyId}/join-applies/{applyId}/audit` 审核接口;`profile-join-family.html` 接入 `GET /genealogy/app/genealogies/join-applies/mine` 我的加入申请,并支持 `DELETE /genealogy/app/genealogies/join-applies/{applyId}` 撤销申请。新增 `public/js/join-apply-pages.js`,`api-client.js` 新增 `myJoinApplies`、`pendingJoinApplies`、`auditJoinApply`、`cancelJoinApply` 封装;`profile-module.css` 补加入申请行样式。验证:九组 Node 测试全部通过,十个业务 JS `node --check` 全部通过,两张页面脚本引用与 `data-join-apply-list` 挂载点检查通过,自有业务 JS 未发现样式注入写法,核心文件未发现 `TODO/TBD/待实现/压缩` 标记。 -- 2026-07-09 13:19:07 +08:00:继续按 `APP.openapi.json` 推进字辈谱阶段。`profile-generation.html` 接入 `GET /genealogy/app/genealogies/{genealogyId}/generation-poems` 查询字辈谱、`POST /genealogy/app/genealogies/{genealogyId}/generation-poems` 新增字辈、`PUT /genealogy/app/genealogies/{genealogyId}/generation-poems/{poemId}` 修改字辈;新增 `public/js/generation-pages.js`,`api-client.js` 新增 `generationPoems`、`createGenerationPoem`、`updateGenerationPoem` 封装;`profile-module.css` 补字辈谱行样式。本轮暂不接批量预览/批量保存接口,避免没有页面入口时过度实现。验证:十组 Node 测试全部通过,十一个业务 JS `node --check` 全部通过,字辈页 `data-generation-list`、`data-generation-add`、`generation-pages.js` 引用检查通过,自有业务 JS 未发现样式注入写法,核心文件未发现 `TODO/TBD/待实现/压缩` 标记。 -- 2026-07-09 13:21:31 +08:00:根据用户提醒停止无编号推进,新增 `docs/api-page-integration-tracker-2026-07-09.md` 作为后续唯一编号规划与状态追踪表。后续每个模块必须先在追踪表中标记“进行中”,完成并验证后再标记“已完成”。 -- 2026-07-09 13:33:41 +08:00:完成 API-011 世系树与人物管理。`profile-tree.html` 接入世系树、人物分页搜索、人物详情、新增成员和父母/配偶/子女快捷关系添加;`profile-family-home.html` 接入世系树预览和家谱主页摘要;新增 `public/js/lineage-pages.js`,`api-client.js` 新增 `lineageTree`、`lineagePersons`、`lineagePersonsPage`、`lineagePersonOptions`、`lineagePersonDetail`、`createLineagePerson`、`updateLineagePerson`、`deleteLineagePerson`、`addLineageRelation` 封装;`profile-module.css` 补世系列表、搜索栏和树结构样式。验证:全部 Node 测试通过,十二个业务 JS `node --check` 通过,两张页面脚本引用与 `data-*` 挂载点检查通过,`public/js/api-client.js` 和 `public/js/lineage-pages.js` 未发现 `style` 样式注入片段。 -- 2026-07-09 13:40:47 +08:00:完成 API-012 成员与家族管理。`profile-family-admin.html` 接入家谱概览和成员列表,支持成员权限更新和移除;`profile-admin-permissions.html` 接入成员选项、角色保存和所有者转让;`profile-invite.html`、`profile-share.html` 使用家谱概览生成邀请码/分享链接展示,不伪造接口文档中不存在的邀请生成接口。新增 `public/js/member-admin-pages.js`,`api-client.js` 新增 `genealogyOverview`、`genealogyMembers`、`genealogyMemberOptions`、`updateGenealogyMember`、`removeGenealogyMember`、`leaveGenealogy`、`transferGenealogyOwner` 封装;`profile-module.css` 补成员操作行样式。验证:全部 Node 测试通过,十三个业务 JS `node --check` 通过,四张页面脚本引用与 `data-*` 挂载点检查通过,`public/js/api-client.js` 和 `public/js/member-admin-pages.js` 未发现 `style` 样式注入片段。 -- 2026-07-09 13:46:31 +08:00:完成 API-014 谱文与内容文章。`profile-article.html` 接入谱文列表;`profile-article-edit.html` 接入分类列表、谱文新增和修改;`article-detail.html` 接入谱文详情;`profile-content.html` 的最近内容先接谱文列表,其他内容类型按后续编号继续接。新增 `public/js/article-pages.js`,`api-client.js` 新增 `articleCategories`、`articles`、`articleDetail`、`createArticle`、`updateArticle` 封装;`profile-module.css` 补谱文行样式。验证:全部 Node 测试通过,十四个业务 JS `node --check` 通过,四张页面脚本引用与 `data-*` 挂载点检查通过,`public/js/api-client.js` 和 `public/js/article-pages.js` 未发现 `style` 样式注入片段。 -- 2026-07-09 13:52:03 +08:00:完成 API-013 家族圈动态。`profile-feed.html` 接入动态分页列表、点赞和评论;`profile-feed-edit.html` 接入动态发布和修改。新增 `public/js/feed-pages.js`,`api-client.js` 新增 `feeds`、`feedsPage`、`feedDetail`、`createFeed`、`updateFeed`、`likeFeed`、`unlikeFeed`、`feedComments`、`feedCommentsPage`、`createFeedComment`、`deleteFeedComment` 封装;`profile-module.css` 补动态行样式。验证:全部 Node 测试通过,十五个业务 JS `node --check` 通过,两张页面脚本引用与 `data-*` 挂载点检查通过,`public/js/api-client.js` 和 `public/js/feed-pages.js` 未发现 `style` 样式注入片段。 -- 2026-07-09 13:57:31 +08:00:完成 API-015 相册照片。`profile-album.html` 接入相册列表、新增/修改相册、照片列表和新增照片;`promo-album.html` 复用相册列表做宣传相册展示。新增 `public/js/album-pages.js`,`api-client.js` 新增 `albums`、`createAlbum`、`updateAlbum`、`albumPhotos`、`createAlbumPhoto` 封装;`profile-module.css` 补相册和照片行样式。验证:全部 Node 测试通过,十六个业务 JS `node --check` 通过,两张页面脚本引用与 `data-*` 挂载点检查通过,`public/js/api-client.js` 和 `public/js/album-pages.js` 未发现 `style` 样式注入片段。 -- 2026-07-09 14:04:52 +08:00:完成 API-019 文件上传公共能力。`api-client.js` 接入单文件上传、文件引用绑定/释放、分片初始化、分片上传、分片完成接口;新增 `public/js/upload-pages.js` 统一处理文件选择、上传、OSS ID 回填和上传状态展示;`profile-article-edit.html` 接入谱文封面上传,`profile-feed-edit.html` 接入动态图片上传,`profile-album.html` 接入相册封面和照片上传;`profile-module.css` 补上传控件样式。验证:全部 Node 测试通过,十七个业务 JS `node --check` 通过,上传控件挂载点检查通过,`public/js/api-client.js` 和 `public/js/upload-pages.js` 未发现样式注入片段。 -- 2026-07-09 14:12:27 +08:00:完成 API-016 祭祀、献礼与功德记录。`profile-gift.html` 接入祭祀/贺礼列表、献礼列表和新增献礼;`profile-gift-edit.html` 接入贺礼创建/修改和封面上传;`profile-merit.html` 接入功德记录列表;`profile-merit-edit.html` 接入新增功德记录。新增 `public/js/ceremony-pages.js`,`api-client.js` 新增 `ceremonies`、`ceremonyDetail`、`createCeremony`、`updateCeremony`、`ceremonyGifts`、`createCeremonyGift`、`meritRecords`、`createMeritRecord` 封装;`profile-module.css` 补贺礼、献礼和功德记录行样式。验证:全部 Node 测试通过,十八个业务 JS `node --check` 通过,四张页面脚本引用与 `data-*` 挂载点检查通过,`public/js/api-client.js` 和 `public/js/ceremony-pages.js` 未发现样式注入片段。 -- 2026-07-09 14:18:15 +08:00:完成 API-017 成长记录。`profile-growth.html` 接入成长记录列表;`profile-growth-edit.html` 接入成长记录新增/修改和附件上传。新增 `public/js/growth-pages.js`,`api-client.js` 新增 `growthRecords`、`growthRecordDetail`、`createGrowthRecord`、`updateGrowthRecord` 封装;`profile-module.css` 补成长记录行样式。验证:全部 Node 测试通过,十九个业务 JS `node --check` 通过,两张页面脚本引用与 `data-*` 挂载点检查通过,`public/js/api-client.js` 和 `public/js/growth-pages.js` 未发现样式注入片段。 -- 2026-07-09 14:24:10 +08:00:完成 API-018 备忘录。`profile-memo.html` 接入备忘录列表;`profile-memo-edit.html` 接入备忘录新增/修改和附件上传。新增 `public/js/memo-pages.js`,`api-client.js` 新增 `memos`、`memoDetail`、`createMemo`、`updateMemo` 封装;`profile-module.css` 补备忘录行样式。验证:全部 Node 测试通过,二十个业务 JS `node --check` 通过,两张页面脚本引用与 `data-*` 挂载点检查通过,`public/js/api-client.js` 和 `public/js/memo-pages.js` 未发现样式注入片段。 -- 2026-07-09 14:31:29 +08:00:完成 API-020 会员套餐与订单创建。`profile-services.html` 接入会员套餐列表、会员订单创建表单和会员订单列表;新增 `public/js/vip-pages.js`,`api-client.js` 新增 `vipPackages`、`vipOrders`、`createVipOrder` 封装,`profile-module.css` 补会员套餐卡片和订单行样式。验证:`node tests\vip-pages.test.js`、`node tests\api-client.test.js`、全部 `tests/*.test.js`、业务 JS `node --check`、会员页挂载点/字段检查均通过;API-020 自有 JS 未发现样式注入片段;`git diff --check` 因当前目录不是 Git 仓库无法执行。 -- 2026-07-09 14:37:25 +08:00:完成 API-021 推广/公告类内容。`app.html` 接入应用推广列表,`download.html` 接入下载推广入口,`notice-detail.html` 从 `/genealogy/app/promotions` 列表按 `id` 选择公告详情,未伪造接口文档不存在的详情接口。新增 `public/js/promotion-pages.js`,`api-client.js` 新增 `promotions` 封装,`app.css` 补推广卡片样式。验证:`node tests\promotion-pages.test.js`、`node tests\api-client.test.js`、全部 `tests/*.test.js`、业务 JS `node --check`、三张页面推广挂载点检查均通过;API-021 自有 JS 未发现样式注入片段;`git diff --check` 因当前目录不是 Git 仓库无法执行。 -- 2026-07-09 14:42:47 +08:00:完成 API-022 账号安全。`profile-security.html` 接入修改密码、换绑手机号、短信登录校验、退出登录和账号注销表单;新增 `public/js/security-pages.js`,`api-client.js` 新增 `changePassword`、`changePhone`、`smsLogin`、`logout`、`deactivateAccount` 封装,`profile-module.css` 补安全表单和危险操作样式。验证:`node tests\security-pages.test.js`、`node tests\api-client.test.js`、全部 `tests/*.test.js`、业务 JS `node --check`、账号安全页挂载点检查均通过;API-022 自有 JS 未发现样式注入片段;`git diff --check` 因当前目录不是 Git 仓库无法执行。 -- 2026-07-09 14:49:54 +08:00:完成 API-023 地区选择公共能力。`create-genealogy.html` 接入省/市/区选择器并回填 `regionCode`,`profile-data.html` 接入个人资料省市区更新表单;新增 `public/js/region-pages.js`,`api-client.js` 新增 `regionChildren`、`regionPath`、`regionSearch`、`regionDetail` 封装,`genealogy-pages.js` 去掉 `regionCode=000000` 兜底并改为提交前校验真实地区编码,两个 CSS 文件补地区选择器样式。验证:`node tests\region-pages.test.js`、`node tests\api-client.test.js`、全部 `tests/*.test.js`、业务 JS `node --check`、两张页面地区挂载点检查均通过;API-023 自有 JS 未发现样式注入片段;`git diff --check` 因当前目录不是 Git 仓库无法执行。 -- 2026-07-09 14:50:47 +08:00:复查 API-024/API-025。`surname.html`、`surname-detail.html`、`search-result.html`、`genealogy.html`、`culture.html`、`about.html`、`index.html` 未发现明确同名接口,公开家谱接口也不支持搜索参数,因此标记暂缓;`profile-video.html`、`promo-video.html`、`profile-data-reminders.html` 暂无视频/资料提醒独立接口,标记暂缓;`profile-create-family.html` 可复用创建家谱能力,单独规划为 API-026。 -- 2026-07-09 14:53:50 +08:00:完成 API-026 个人中心创建家谱页。`profile-create-family.html` 改为真实创建家谱表单,接入 `api-client.js`、`region-pages.js`、`genealogy-pages.js`,复用 `/genealogy/app/genealogies` 和地区选择公共能力;`profile-module.css` 补个人中心创建表单样式,`tests/genealogy-pages.test.js` 补真实 `regionCode` 断言。验证:`node tests\genealogy-pages.test.js`、`node tests\region-pages.test.js`、`node tests\api-client.test.js`、全部 `tests/*.test.js`、业务 JS `node --check`、页面挂载点检查均通过;API-026 自有 JS 未发现样式注入片段;`git diff --check` 因当前目录不是 Git 仓库无法执行。 -- 2026-07-09 15:03:27 +08:00:完成 API-027 个人资料编辑提交。`profile-data.html` 增加真实个人资料编辑表单,`profile-pages.js` 增加 `ProfileUpdateBody` 构造、表单填充和 `PUT /genealogy/app/auth/profile` 提交,`profile-module.css` 补本页表单状态样式,`tests/profile-pages.test.js` 和 `tests/api-client.test.js` 补转换与接口契约测试。验证:先观察 `node tests\profile-pages.test.js` 因缺少 `buildProfileUpdateBody` 失败;实现后 `node tests\profile-pages.test.js`、`node tests\api-client.test.js`、全部 `tests/*.test.js`、业务 JS `node --check`、页面挂载点检查均通过,未发现样式注入片段和 TODO 类占位;`git diff --check` 因当前目录不是 Git 仓库无法执行。 -- 2026-07-09 15:11:37 +08:00:完成 API-028 字辈批量预览与批量保存。`profile-generation.html` 增加批量字辈表单和预览区域,`api-client.js` 增加 `previewGenerationPoems`、`saveGenerationPoemsBatch`,`generation-pages.js` 增加 `GenerationPoemBatchBody` 构造、预览渲染和保存动作,`profile-module.css` 补批量面板样式,`tests/generation-pages.test.js` 和 `tests/api-client.test.js` 补批量接口测试。验证:先观察 `node tests\generation-pages.test.js` 因缺少 `buildGenerationBatchBody` 失败、`node tests\api-client.test.js` 因缺少 `previewGenerationPoems` 失败;实现后 `node tests\generation-pages.test.js`、`node tests\api-client.test.js`、全部 `tests/*.test.js`、业务 JS `node --check`、页面挂载点检查均通过,未发现样式注入片段和 TODO 类占位;`git diff --check` 因当前目录不是 Git 仓库无法执行。 diff --git a/docs/api-page-integration-tracker-2026-07-09.md b/docs/api-page-integration-tracker-2026-07-09.md deleted file mode 100644 index 3a07127..0000000 --- a/docs/api-page-integration-tracker-2026-07-09.md +++ /dev/null @@ -1,114 +0,0 @@ -# 接口对接编号规划与状态追踪 - -创建时间:2026-07-09 13:21:31 +08:00 -流程修正时间:2026-07-09 13:21:31 +08:00 -接口依据:`APP.openapi.json` -主进度记录:`docs/api-page-integration-2026-07-09.md` - -## 执行规则 - -1. 后续不再无编号推进,所有接口对接必须先进入本追踪表。 -2. 每一项开始前,先把状态从“待开始”改为“进行中”,并记录开始时间。 -3. 每一项完成后,必须记录完成时间、修改文件、接口路径、验证命令或静态检查结果。 -4. 每一项验证通过后,才能把状态改为“已完成”。 -5. 若接口文档没有明确对应接口,状态标记为“待确认”或“暂缓”,不强行接入。 -6. 样式继续遵守公共 `public.css` + 页面 CSS 的结构,业务 JS 不注入样式。 -7. 新增或修改的 HTML、JS、CSS 注释使用中文,代码保持可读、不压缩。 - -## 状态说明 - -- 已完成:已按接口文档接入,并完成对应验证。 -- 进行中:当前正在推进,未完成前不能开始下一个无关模块。 -- 待开始:已规划,尚未改代码。 -- 待确认:页面存在,但接口归属需要进一步确认。 -- 暂缓:接口或页面入口不足,暂不实现,避免过度开发。 - -## 已完成回填 - -| 编号 | 状态 | 页面范围 | 接口范围 | 完成记录 | -| --- | --- | --- | --- | --- | -| API-000 | 已完成 | 全项目 | `APP.openapi.json`、`AGENTS.md`、项目结构 | 2026-07-09 11:47:20 +08:00 已读取约束、接口文档和目录结构。 | -| API-001 | 已完成 | 全项目公共请求 | 共享请求客户端、认证头、租户头、Token 存取 | 2026-07-09 11:52:53 +08:00 至 12:16:27 +08:00 完成 `public/js/api-client.js` 与测试。 | -| API-002 | 已完成 | `login.html`、`register.html`、`forgot-password.html` | `/genealogy/app/auth/login`、`/genealogy/app/auth/register`、`/genealogy/app/auth/sms/code`、`/genealogy/app/auth/password/reset`、`/captcha/require`、`/captcha/challenge`、`/captcha/verify` | 2026-07-09 12:06:46 +08:00 完成认证页;2026-07-09 12:59:39 +08:00 完成 TAC 滑动验证接入。 | -| API-003 | 已完成 | `create-genealogy.html`、`plaza.html`、`profile-families.html` | `/genealogy/app/genealogies`、`/genealogy/app/genealogies/public`、`/genealogy/app/genealogies/mine` | 2026-07-09 12:10:54 +08:00 完成创建家谱、公开家谱、我的家谱列表。 | -| API-004 | 已完成 | `family-detail.html`、`join-genealogy.html` | `/genealogy/app/genealogies/{genealogyId}`、`/genealogy/app/genealogies/{genealogyId}/join-applies` | 2026-07-09 12:38:13 +08:00 完成家谱详情与申请加入;2026-07-09 12:40:15 +08:00 补 `joinMode` 展示映射。 | -| API-005 | 已完成 | `profile.html`、`profile-data.html` | `/genealogy/app/auth/profile` | 2026-07-09 12:28:30 +08:00 完成个人资料读取展示。 | -| API-006 | 已完成 | `profile-feedback.html`、`submit-ticket.html` | `/genealogy/app/feedback` | 2026-07-09 12:28:30 +08:00 完成反馈提交与历史反馈。 | -| API-007 | 已完成 | `profile-messages.html` | `/genealogy/app/notifications`、`/genealogy/app/notifications/{notificationId}/read`、`/genealogy/app/notifications/read-all` | 2026-07-09 12:45:24 +08:00 完成消息中心。 | -| API-008 | 已完成 | `help.html` | `/genealogy/app/help-articles`、`/genealogy/app/help-articles/{helpId}` | 2026-07-09 13:07:18 +08:00 完成帮助中心。 | -| API-009 | 已完成 | `profile-join-review.html`、`profile-join-family.html` | `/genealogy/app/genealogies/{genealogyId}/join-applies/pending`、`/genealogy/app/genealogies/{genealogyId}/join-applies/{applyId}/audit`、`/genealogy/app/genealogies/join-applies/mine`、`/genealogy/app/genealogies/join-applies/{applyId}` | 2026-07-09 13:13:33 +08:00 完成入谱申请审核与我的申请。 | -| API-010 | 已完成 | `profile-generation.html` | `/genealogy/app/genealogies/{genealogyId}/generation-poems`、`/genealogy/app/genealogies/{genealogyId}/generation-poems/{poemId}` | 2026-07-09 13:19:07 +08:00 完成字辈谱查询、新增、修改;批量接口因页面无入口暂缓。 | - -## 后续编号规划 - -| 编号 | 状态 | 页面范围 | 接口范围 | 计划与验证 | -| --- | --- | --- | --- | --- | -| API-011 | 已完成 | `profile-tree.html`、`profile-family-home.html` | `/genealogy/app/genealogies/{genealogyId}/lineage/tree`、`/genealogy/app/genealogies/{genealogyId}/lineage/persons`、`/genealogy/app/genealogies/{genealogyId}/lineage/persons/page`、`/genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}`、`/genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}/children`、`/parents`、`/siblings`、`/spouses` | 2026-07-09 13:25:03 +08:00 开始;2026-07-09 13:33:41 +08:00 完成。新增 `public/js/lineage-pages.js`、`tests/lineage-pages.test.js`;更新 `public/js/api-client.js`、`tests/api-client.test.js`、`profile-tree.html`、`profile-family-home.html`、`public/css/profile-module.css`。验证:全部 Node 测试通过,业务 JS 语法检查通过,页面挂载点检查通过,API-011 自有 JS 未发现样式注入片段。 | -| API-012 | 已完成 | `profile-family-admin.html`、`profile-admin-permissions.html`、`profile-invite.html`、`profile-share.html` | `/genealogy/app/genealogies/{genealogyId}/members`、`/genealogy/app/genealogies/{genealogyId}/members/{memberId}`、`/genealogy/app/genealogies/{genealogyId}/members/me`、`/genealogy/app/genealogies/{genealogyId}/members/options`、`/genealogy/app/genealogies/{genealogyId}/members/owner-transfer`、`/genealogy/app/genealogies/{genealogyId}/overview` | 2026-07-09 13:34:36 +08:00 开始;2026-07-09 13:40:47 +08:00 完成。新增 `public/js/member-admin-pages.js`、`tests/member-admin-pages.test.js`;更新 `public/js/api-client.js`、`tests/api-client.test.js`、四张成员/邀请页面和 `public/css/profile-module.css`。验证:全部 Node 测试通过,业务 JS 语法检查通过,页面挂载点检查通过,API-012 自有 JS 未发现样式注入片段。 | -| API-013 | 已完成 | `profile-feed.html`、`profile-feed-edit.html` | `/genealogy/app/genealogies/{genealogyId}/feeds`、`/genealogy/app/genealogies/{genealogyId}/feeds/page`、`/genealogy/app/genealogies/{genealogyId}/feeds/{feedId}`、`/genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/likes`、评论接口 | 2026-07-09 13:47:29 +08:00 开始;2026-07-09 13:52:03 +08:00 完成。新增 `public/js/feed-pages.js`、`tests/feed-pages.test.js`;更新 `public/js/api-client.js`、`tests/api-client.test.js`、两张动态页面和 `public/css/profile-module.css`。验证:全部 Node 测试通过,业务 JS 语法检查通过,页面挂载点检查通过,API-013 自有 JS 未发现样式注入片段。 | -| API-014 | 已完成 | `profile-article.html`、`profile-article-edit.html`、`article-detail.html`、`profile-content.html` | `/genealogy/app/genealogies/{genealogyId}/article-categories`、`/genealogy/app/genealogies/{genealogyId}/articles`、`/genealogy/app/genealogies/{genealogyId}/articles/{articleId}` | 2026-07-09 13:41:44 +08:00 开始;2026-07-09 13:46:31 +08:00 完成。新增 `public/js/article-pages.js`、`tests/article-pages.test.js`;更新 `public/js/api-client.js`、`tests/api-client.test.js`、四张谱文/内容页面和 `public/css/profile-module.css`。验证:全部 Node 测试通过,业务 JS 语法检查通过,页面挂载点检查通过,API-014 自有 JS 未发现样式注入片段。 | -| API-015 | 已完成 | `profile-album.html`、`promo-album.html` | `/genealogy/app/genealogies/{genealogyId}/albums`、`/genealogy/app/genealogies/{genealogyId}/albums/{albumId}`、`/genealogy/app/genealogies/{genealogyId}/albums/{albumId}/photos` | 2026-07-09 13:52:58 +08:00 开始;2026-07-09 13:57:31 +08:00 完成。新增 `public/js/album-pages.js`、`tests/album-pages.test.js`;更新 `public/js/api-client.js`、`tests/api-client.test.js`、两张相册页面和 `public/css/profile-module.css`。验证:全部 Node 测试通过,业务 JS 语法检查通过,页面挂载点检查通过,API-015 自有 JS 未发现样式注入片段。 | -| API-016 | 已完成 | `profile-gift.html`、`profile-gift-edit.html`、`profile-merit.html`、`profile-merit-edit.html` | `/genealogy/app/genealogies/{genealogyId}/ceremonies`、`/genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}`、`/genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}/gifts`、`/genealogy/app/genealogies/{genealogyId}/merit-records` | 2026-07-09 14:05:57 +08:00 开始;2026-07-09 14:12:27 +08:00 完成。新增 `public/js/ceremony-pages.js`、`tests/ceremony-pages.test.js`;更新 `public/js/api-client.js`、`tests/api-client.test.js`、四张贺礼/功德页面和 `public/css/profile-module.css`。验证:全部 Node 测试通过,业务 JS 语法检查通过,页面挂载点检查通过,API-016 自有 JS 未发现样式注入片段。 | -| API-017 | 已完成 | `profile-growth.html`、`profile-growth-edit.html` | `/genealogy/app/genealogies/{genealogyId}/growth-records`、`/genealogy/app/genealogies/{genealogyId}/growth-records/{recordId}` | 2026-07-09 14:13:25 +08:00 开始;2026-07-09 14:18:15 +08:00 完成。新增 `public/js/growth-pages.js`、`tests/growth-pages.test.js`;更新 `public/js/api-client.js`、`tests/api-client.test.js`、两张成长记录页面和 `public/css/profile-module.css`。验证:全部 Node 测试通过,业务 JS 语法检查通过,页面挂载点检查通过,API-017 自有 JS 未发现样式注入片段。 | -| API-018 | 已完成 | `profile-memo.html`、`profile-memo-edit.html` | `/genealogy/app/genealogies/{genealogyId}/memos`、`/genealogy/app/genealogies/{genealogyId}/memos/{memoId}` | 2026-07-09 14:19:26 +08:00 开始;2026-07-09 14:24:10 +08:00 完成。新增 `public/js/memo-pages.js`、`tests/memo-pages.test.js`;更新 `public/js/api-client.js`、`tests/api-client.test.js`、两张备忘录页面和 `public/css/profile-module.css`。验证:全部 Node 测试通过,业务 JS 语法检查通过,页面挂载点检查通过,API-018 自有 JS 未发现样式注入片段。 | -| API-019 | 已完成 | 文章、动态、相册、成长记录等需要上传的页面 | `/genealogy/app/files/upload`、`/genealogy/app/files/reference`、`/genealogy/app/files/resumable/init`、`/genealogy/app/files/resumable/chunk`、`/genealogy/app/files/resumable/complete` | 2026-07-09 14:00:01 +08:00 开始;2026-07-09 14:04:52 +08:00 完成。新增 `public/js/upload-pages.js`、`tests/upload-pages.test.js`;更新 `public/js/api-client.js`、`tests/api-client.test.js`、`profile-article-edit.html`、`profile-feed-edit.html`、`profile-album.html`、`public/css/profile-module.css`。验证:全部 Node 测试通过,业务 JS 语法检查通过,上传控件挂载点检查通过,API-019 自有 JS 未发现样式注入片段。 | -| API-020 | 已完成 | `profile-services.html` | `/genealogy/app/vip/packages`、`/genealogy/app/vip/orders` | 2026-07-09 14:26:34 +08:00 开始;2026-07-09 14:31:29 +08:00 完成。新增 `public/js/vip-pages.js`、`tests/vip-pages.test.js`;更新 `public/js/api-client.js`、`tests/api-client.test.js`、`profile-services.html`、`public/css/profile-module.css`。验证:全部 Node 测试通过,业务 JS 语法检查通过,会员页挂载点和表单字段检查通过,API-020 自有 JS 未发现样式注入片段;`git diff --check` 因当前目录不是 Git 仓库无法执行。 | -| API-021 | 已完成 | `app.html`、`download.html`、`notice-detail.html` | `/genealogy/app/promotions` | 2026-07-09 14:33:01 +08:00 开始;2026-07-09 14:37:25 +08:00 完成。新增 `public/js/promotion-pages.js`、`tests/promotion-pages.test.js`;更新 `public/js/api-client.js`、`tests/api-client.test.js`、`app.html`、`download.html`、`notice-detail.html`、`public/css/app.css`。验证:全部 Node 测试通过,业务 JS 语法检查通过,三张页面推广挂载点检查通过,API-021 自有 JS 未发现样式注入片段;`git diff --check` 因当前目录不是 Git 仓库无法执行。 | -| API-022 | 已完成 | `profile-security.html` | `/genealogy/app/auth/password`、`/genealogy/app/auth/phone`、`/genealogy/app/auth/account/deactivate`、`/genealogy/app/auth/logout`、`/genealogy/app/auth/login/sms` | 2026-07-09 14:38:22 +08:00 开始;2026-07-09 14:42:47 +08:00 完成。新增 `public/js/security-pages.js`、`tests/security-pages.test.js`;更新 `public/js/api-client.js`、`tests/api-client.test.js`、`profile-security.html`、`public/css/profile-module.css`。验证:全部 Node 测试通过,业务 JS 语法检查通过,账号安全页表单挂载点检查通过,API-022 自有 JS 未发现样式注入片段;`git diff --check` 因当前目录不是 Git 仓库无法执行。 | -| API-023 | 已完成 | `create-genealogy.html`、`profile-data.html`、涉及地区选择的编辑页 | `/genealogy/region/children`、`/genealogy/region/search`、`/genealogy/region/{regionCode}`、`/genealogy/region/path/{regionCode}` | 2026-07-09 14:44:43 +08:00 开始;2026-07-09 14:49:54 +08:00 完成。新增 `public/js/region-pages.js`、`tests/region-pages.test.js`;更新 `public/js/api-client.js`、`public/js/genealogy-pages.js`、`tests/api-client.test.js`、`tests/genealogy-pages.test.js`、`create-genealogy.html`、`profile-data.html`、`public/css/create-genealogy.css`、`public/css/profile-module.css`。验证:全部 Node 测试通过,业务 JS 语法检查通过,两张页面地区选择挂载点检查通过,API-023 自有 JS 未发现样式注入片段;`git diff --check` 因当前目录不是 Git 仓库无法执行。 | -| API-024 | 暂缓 | `surname.html`、`surname-detail.html`、`search-result.html`、`genealogy.html`、`culture.html`、`about.html`、`index.html` | 当前接口文档未发现明确同名业务接口 | 2026-07-09 14:50:47 +08:00 复查。公开家谱接口不支持搜索参数,文章接口依赖 `genealogyId`,推广接口只有列表,不强行映射为姓氏百科或全站搜索。 | -| API-025 | 暂缓 | `profile-video.html`、`promo-video.html`、`profile-data-reminders.html` | 当前接口文档未发现明确视频、资料提醒独立接口 | 2026-07-09 14:50:47 +08:00 复查。视频和资料提醒没有独立接口,暂不伪造接口;`profile-create-family.html` 归入新增 API-026。 | -| API-026 | 已完成 | `profile-create-family.html` | `/genealogy/app/genealogies`、`/genealogy/region/children` | 2026-07-09 14:51:39 +08:00 开始;2026-07-09 14:53:50 +08:00 完成。更新 `profile-create-family.html`、`public/css/profile-module.css`、`tests/genealogy-pages.test.js`,复用 `public/js/api-client.js`、`public/js/region-pages.js`、`public/js/genealogy-pages.js`。验证:全部 Node 测试通过,业务 JS 语法检查通过,页面创建表单和地区选择挂载点检查通过,API-026 自有 JS 未发现样式注入片段;`git diff --check` 因当前目录不是 Git 仓库无法执行。 | -| API-027 | 已完成 | `profile-data.html` | `/genealogy/app/auth/profile` | 2026-07-09 14:57:51 +08:00 开始;2026-07-09 15:03:27 +08:00 完成。更新 `profile-data.html`、`public/js/profile-pages.js`、`public/css/profile-module.css`、`tests/profile-pages.test.js`、`tests/api-client.test.js`。补齐个人资料编辑提交,字段对应 `ProfileUpdateBody`:`nickName`、`avatarOssId`、`sex`、`birthday`;地区字段继续沿用 API-023。验证:已观察 `node tests\profile-pages.test.js` 因缺少 `buildProfileUpdateBody` 失败;实现后 `node tests\profile-pages.test.js`、`node tests\api-client.test.js`、全部 `tests/*.test.js`、业务 JS `node --check`、页面挂载点检查均通过;未发现样式注入片段和 TODO 类占位;`git diff --check` 因当前目录不是 Git 仓库无法执行。 | -| API-028 | 已完成 | `profile-generation.html` | `/genealogy/app/genealogies/{genealogyId}/generation-poems/batch/preview`、`/genealogy/app/genealogies/{genealogyId}/generation-poems/batch/save` | 2026-07-09 15:05:58 +08:00 开始;2026-07-09 15:11:37 +08:00 完成。更新 `profile-generation.html`、`public/js/api-client.js`、`public/js/generation-pages.js`、`public/css/profile-module.css`、`tests/generation-pages.test.js`、`tests/api-client.test.js`。补齐字辈批量预览和批量保存,字段对应 `GenerationPoemBatchBody`:`content`、`stopMissingOldGeneration`。验证:已观察 `node tests\generation-pages.test.js` 因缺少 `buildGenerationBatchBody` 失败,`node tests\api-client.test.js` 因缺少 `previewGenerationPoems` 失败;实现后 `node tests\generation-pages.test.js`、`node tests\api-client.test.js`、全部 `tests/*.test.js`、业务 JS `node --check`、页面挂载点检查均通过;未发现样式注入片段和 TODO 类占位;`git diff --check` 因当前目录不是 Git 仓库无法执行。 | -| API-029 | 已中止 | `profile-services.html` | `/genealogy/app/genealogies/options` | 2026-07-09 15:13:03 +08:00 开始;2026-07-09 15:14:58 +08:00 中止。原因:用户确认此前依据的 `APP.openapi.json` 不是 PC 接口文档,PC/H5 应改用 `genealogy-pc-openapi.yaml`,且接口地址使用 `https://test-genealogy-api.ddxcjp.cn`。本项不再继续按 APP 接口推进。 | - -## 下一步执行顺序 - -1. API-011:世系树与人物管理。 -2. API-012:成员与家族管理。 -3. API-014:谱文与内容文章。 -4. API-013:家族圈动态。 -5. API-015:相册照片。 -6. API-019:上传公共能力。 -7. API-016 至 API-023:按页面入口完整度继续推进。 -8. API-024、API-025:只在确认接口归属后推进。 - -## 本次流程修正记录 - -- 2026-07-09 13:21:31 +08:00:收到用户提醒,停止继续无编号推进;补充本编号追踪表,并要求后续每项先标记状态再实现,完成后再标记已完成。 -- 2026-07-09 14:26:34 +08:00:开始执行 API-020,状态从“待开始”改为“进行中”。 -- 2026-07-09 14:31:29 +08:00:API-020 执行完成,状态从“进行中”改为“已完成”。 -- 2026-07-09 14:33:01 +08:00:开始执行 API-021,状态从“待开始”改为“进行中”。 -- 2026-07-09 14:37:25 +08:00:API-021 执行完成,状态从“进行中”改为“已完成”。 -- 2026-07-09 14:38:22 +08:00:开始执行 API-022,状态从“待开始”改为“进行中”。 -- 2026-07-09 14:42:47 +08:00:API-022 执行完成,状态从“进行中”改为“已完成”。 -- 2026-07-09 14:44:43 +08:00:开始执行 API-023,状态从“待开始”改为“进行中”。 -- 2026-07-09 14:49:54 +08:00:API-023 执行完成,状态从“进行中”改为“已完成”。 -- 2026-07-09 14:50:47 +08:00:复查 API-024/API-025,缺少明确接口的页面标记为“暂缓”,将 `profile-create-family.html` 单独规划为 API-026。 -- 2026-07-09 14:51:39 +08:00:开始执行 API-026,状态从“待开始”改为“进行中”。 -- 2026-07-09 14:53:50 +08:00:API-026 执行完成,状态从“进行中”改为“已完成”。 -- 2026-07-09 14:57:51 +08:00:开始执行 API-027,状态标记为“进行中”;按接口文档把 `profile-data.html` 的个人资料更新归到 `/genealogy/app/auth/profile` PUT,先写测试再实现。 -- 2026-07-09 15:03:27 +08:00:API-027 执行完成,状态从“进行中”改为“已完成”;完成个人资料编辑表单、提交逻辑、页面样式和测试验证。 -- 2026-07-09 15:05:58 +08:00:开始执行 API-028,状态标记为“进行中”;按接口文档把 `profile-generation.html` 的批量字辈能力归到 `/generation-poems/batch/preview` 和 `/generation-poems/batch/save`。 -- 2026-07-09 15:11:37 +08:00:API-028 执行完成,状态从“进行中”改为“已完成”;完成批量字辈预览、批量保存、页面入口、样式和测试验证。 -- 2026-07-09 15:13:03 +08:00:开始执行 API-029,状态标记为“进行中”;把 `profile-services.html` 的家谱选择归到 `/genealogy/app/genealogies/options`。 -- 2026-07-09 15:14:58 +08:00:收到用户纠正,确认旧依据 `APP.openapi.json` 不适合作为 PC 页面接口文档;中止 API-029,后续改以 `genealogy-pc-openapi.yaml` 和 `https://test-genealogy-api.ddxcjp.cn` 重新规划。 -- 2026-07-09 13:25:03 +08:00:开始执行 API-011,状态从“待开始”改为“进行中”。 -- 2026-07-09 13:33:41 +08:00:API-011 执行完成,状态从“进行中”改为“已完成”。 -- 2026-07-09 13:34:36 +08:00:开始执行 API-012,状态从“待开始”改为“进行中”。 -- 2026-07-09 13:40:47 +08:00:API-012 执行完成,状态从“进行中”改为“已完成”。 -- 2026-07-09 13:41:44 +08:00:开始执行 API-014,状态从“待开始”改为“进行中”。 -- 2026-07-09 13:46:31 +08:00:API-014 执行完成,状态从“进行中”改为“已完成”。 -- 2026-07-09 13:47:29 +08:00:开始执行 API-013,状态从“待开始”改为“进行中”。 -- 2026-07-09 13:52:03 +08:00:API-013 执行完成,状态从“进行中”改为“已完成”。 -- 2026-07-09 13:52:58 +08:00:开始执行 API-015,状态从“待开始”改为“进行中”。 -- 2026-07-09 13:57:31 +08:00:API-015 执行完成,状态从“进行中”改为“已完成”。 -- 2026-07-09 14:00:01 +08:00:开始执行 API-019,状态从“待开始”改为“进行中”。 -- 2026-07-09 14:04:52 +08:00:API-019 执行完成,状态从“进行中”改为“已完成”。 -- 2026-07-09 14:05:57 +08:00:开始执行 API-016,状态从“待开始”改为“进行中”。 -- 2026-07-09 14:12:27 +08:00:API-016 执行完成,状态从“进行中”改为“已完成”。 -- 2026-07-09 14:13:25 +08:00:开始执行 API-017,状态从“待开始”改为“进行中”。 -- 2026-07-09 14:18:15 +08:00:API-017 执行完成,状态从“进行中”改为“已完成”。 -- 2026-07-09 14:19:26 +08:00:开始执行 API-018,状态从“待开始”改为“进行中”。 -- 2026-07-09 14:24:10 +08:00:API-018 执行完成,状态从“进行中”改为“已完成”。 diff --git a/docs/pc-api-page-integration-tracker-2026-07-09.md b/docs/pc-api-page-integration-tracker-2026-07-09.md index de8f9be..525a024 100644 --- a/docs/pc-api-page-integration-tracker-2026-07-09.md +++ b/docs/pc-api-page-integration-tracker-2026-07-09.md @@ -3,8 +3,7 @@ 创建时间:2026-07-09 15:14:58 +08:00 接口依据:`genealogy-pc-openapi.yaml` 接口基础地址:`http://182.61.18.23:8080` -旧依据处理:`APP.openapi.json` 只作为历史误用记录,不再作为 PC 页面继续对接依据。 -旧进度记录:`docs/api-page-integration-tracker-2026-07-09.md` +接口依据:`genealogy-pc-openapi.yaml` ## 当前地址契约 @@ -18,7 +17,7 @@ 2. 每一项开始前先标记“进行中”,记录年月日时分秒和时区。 3. 每一项完成后记录完成时间、修改文件、接口路径、验证命令和结果。 4. 只有完成验证后才能标记“已完成”。 -5. `genealogy-pc-openapi.yaml` 没有明确接口的页面,标记“暂缓”或“待确认”,不继续套用 APP 路径。 +5. `genealogy-pc-openapi.yaml` 没有明确接口的页面,标记“暂缓”或“待确认”,不继续套用旧路径。 6. 样式继续写入 CSS 文件,业务 JS 不注入样式。 7. 新增或修改的 HTML、JS、CSS 注释使用中文,代码保持可读、不压缩。 @@ -38,7 +37,7 @@ 2. `servers` 仍是本地地址示例;当前运行时基础地址以 `config.js` 为准,为 `http://182.61.18.23:8080`。 3. 登录后接口使用 `Authorization` 作为 token header,同时所有 PC 认证和文件接口都要求 header `clientid`;用户最新提供的 PC `clientid` 为 `ced7e5f0498645c6ec642dcf450b036f`,客户端 Key 为 `web_pc`。 4. `components.tags` 和 `components.schemas/requestBodies` 中出现家谱、动态、世系、字辈等业务模型,但 `paths` 没有对应接口路径;实现时不能把这些 schema 当成可调用 PC 接口。 -5. 验证码 schema 示例里仍出现 `APP_LOGIN`、`PC_LOGIN` 等文本示例;实际页面场景以后台配置为准,当前明确可用的 PC/H5 场景为 `WEB_H5_LOGIN`、`WEB_H5_REGISTER`、`WEB_H5_FORGOT_PASSWORD`。 +5. 验证码场景以后台配置为准,当前明确可用的 PC/H5 场景为 `WEB_H5_LOGIN`、`WEB_H5_REGISTER`、`WEB_H5_FORGOT_PASSWORD`。 6. `ProfileUpdate` 示例出现 `regionCode/addressDetail`,但 schema 实际字段是 `provinceCode/cityCode/districtCode`,页面资料提交时应以 schema 字段为准。 7. `SmsLoginBody` 未声明 `validToken` 字段,但短信发送 `SmsCodeBody` 必填 `validToken`;短信登录流程应先通过验证码拿票据,再发短信验证码,最后用短信码登录。 8. 文件引用 `FileReferenceBody` 必填 `bizType/bizTable/bizId/bizField`,`ossId/ossIds/usageScene/usageName` 可选;但文章、动态、相册等业务主体接口未提供,文件引用只能作为公共上传能力,不代表主业务已可提交。 @@ -47,7 +46,6 @@ - 后台验证码配置截图中,PC/H5 当前明确可用场景是 `WEB_H5_LOGIN`、`WEB_H5_REGISTER`、`WEB_H5_FORGOT_PASSWORD`,客户端 Key 为 `web_pc`,验证服务为“天爱行为验证码”,验证码类型为“滑块验证码”。 - `ADMIN_LOGIN` 是后台管理登录,类型为旋转验证码,不归当前 PC/H5 页面使用。 -- `APP_LOGIN`、`APP_REGISTER`、`APP_PHONE_CHANGE`、`APP_FORGOT_PASSWORD`、`APP_SMS_CODE`、`APP_ACCOUNT_DEACTIVATE` 的客户端 Key 为 `app`,不能继续作为 PC/H5 场景默认值。 - PC/H5 登录页调用链: 1. 页面加载 `public/tac/css/tac.css`、`public/tac/js/tac.min.js`、`public/js/captcha-pages.js`。 2. 表单提供 `input[name="validToken"]` 隐藏字段和 `[data-captcha-box]` 容器。 @@ -70,8 +68,8 @@ | PC-004 | 本地复核通过 | 文件上传页面 | `/genealogy/pc/files/*` | `node tests\upload-pages.test.js`、`node tests\api-client.test.js` 通过;文件上传仍需真实文件和后端授权进行端到端验证。 | | PC-005 | 本地复核通过 | 地区选择页面 | `/genealogy/region/*` | `node tests\region-pages.test.js`、`node tests\profile-pages.test.js` 通过。 | | PC-006 | 复核通过 | 页面覆盖矩阵 | PC YAML 覆盖边界 | 保持“公共能力不等于整页业务已对接”的边界,未覆盖业务继续受控失败。 | -| PC-007 | 复核通过 | 实施规划 | `genealogy-pc-openapi.yaml` | 当前计划与 YAML `paths` 一致,不使用旧 APP 路径 fallback。 | -| PC-008 | 复核通过 | PC YAML 未覆盖业务页面 | `PC_API_NOT_AVAILABLE` | `utils/ApiClient.js` 统一抛 `PC_API_NOT_AVAILABLE`,旧 `/genealogy/app/` 请求路径扫描无结果。 | +| PC-007 | 复核通过 | 实施规划 | `genealogy-pc-openapi.yaml` | 当前计划与 YAML `paths` 一致,不使用旧路径 fallback。 | +| PC-008 | 复核通过 | PC YAML 未覆盖业务页面 | `PC_API_NOT_AVAILABLE` | `utils/ApiClient.js` 统一抛 `PC_API_NOT_AVAILABLE`,过期请求路径扫描无结果。 | | PC-009 | 本地复核通过 | 登录、注册、找回密码 | PC auth、`/captcha/*` | 三页场景编码、表单契约、Axios 请求客户端和相关测试均通过;真实账号流程待业务数据联调。 | | PC-010 | 已复核(当前地址已同步) | `config.js`、`tests/config.test.js`、`utils/ApiClient.js` | API 基础地址 | 当前开发和生产地址均为 `http://182.61.18.23:8080`;地址唯一运行时来源为 `config.js`,`tests/config.test.js` 已同步断言。 | | PC-011 | 本地复核通过 | 三张认证页 TAC 弹窗 | `public/tac`、`/captcha/*` | 页面级挂载、移动端约束和结构测试通过;未修改 `tac.min.js`。 | @@ -81,31 +79,31 @@ | 分类 | 页面/模块 | 当前判断 | 处理方式 | | --- | --- | --- | --- | | 完整可闭环 | `login.html` | PC YAML 有 `/genealogy/pc/auth/login`,后台验证码配置明确 `WEB_H5_LOGIN`,TAC 可完整串联。 | 可作为第一批执行页面。 | -| 接口存在但部分验证码场景待确认 | `register.html`、`forgot-password.html`、`profile-security.html` 中的换绑/注销相关动作 | PC YAML 有对应认证接口;注册场景为 `WEB_H5_REGISTER`,找回密码场景为 `WEB_H5_FORGOT_PASSWORD`,换绑和注销暂未提供 PC/H5 场景。 | 注册和找回密码可接 TAC;换绑、注销涉及验证码的提交先记录待确认,不能套用 `APP_*` 场景。 | +| 接口存在但部分验证码场景待确认 | `register.html`、`forgot-password.html`、`profile-security.html` 中的换绑/注销相关动作 | PC YAML 有对应认证接口;注册场景为 `WEB_H5_REGISTER`,找回密码场景为 `WEB_H5_FORGOT_PASSWORD`,换绑和注销暂未提供 PC/H5 场景。 | 注册和找回密码可接 TAC;换绑、注销涉及验证码的提交先记录待确认,不套用未经确认的场景。 | | 资料接口可对接 | `profile.html`、`profile-data.html` 中用户资料读取/修改 | PC YAML 有 `/genealogy/pc/auth/profile`。 | 只处理用户资料读写;页面里其他非资料业务不因此视为完成。 | | 公共地区能力可保留 | `create-genealogy.html`、`profile-create-family.html`、`profile-data.html` 中地区选择控件 | PC YAML 有 `/genealogy/region/*`。 | 只保留和验证地区选择;创建家谱等主业务接口 PC YAML 未覆盖,仍待确认。 | | 文件能力可切换 | 文章、动态、相册、成长、备忘、祭祀等页面里的上传控件 | PC YAML 有 `/genealogy/pc/files/*`。 | 只把上传、分片、文件引用切到 PC 文件接口;文章/动态/相册等主业务接口仍待确认。 | -| PC YAML 未覆盖 | 家谱主体、成员、字辈、世系、动态、文章、相册、祭祀、族务、VIP、通知、反馈、帮助、推广、姓氏、搜索等主业务页面 | 当前 PC YAML 没有这些业务路径。 | 不套用 APP 路径;等待补充 PC 接口后再逐页规划。 | +| PC YAML 未覆盖 | 家谱主体、成员、字辈、世系、动态、文章、相册、祭祀、族务、VIP、通知、反馈、帮助、推广、姓氏、搜索等主业务页面 | 当前 PC YAML 没有这些业务路径。 | 等待补充 PC 接口后再逐页规划。 | ## 流程记录 -- 2026-07-09 15:14:58 +08:00:收到用户纠正,停止 APP 接口继续推进;读取 `genealogy-pc-openapi.yaml`,确认 PC 路径前缀为 `/genealogy/pc`,基础地址改用 `https://test-genealogy-api.ddxcjp.cn`。 +- 2026-07-09 15:14:58 +08:00:收到用户纠正,停止旧接口继续推进;读取 `genealogy-pc-openapi.yaml`,确认 PC 路径前缀为 `/genealogy/pc`,基础地址改用 `https://test-genealogy-api.ddxcjp.cn`。 - 2026-07-09 15:14:58 +08:00:创建本 PC 专用追踪表,PC-001 标记为“进行中”。 - 2026-07-09 15:17:57 +08:00:收到用户补充要求,重新规划 `config.js` 环境切换和 `utils` 公共 JS 分层;停止直接执行旧 PC-001,把 PC-001 到 PC-006 重排为待执行计划。 - 2026-07-09 15:24:02 +08:00:收到用户补充验证码要求;记录 `public/tac` 调用链,确认 PC/H5 登录使用 `WEB_H5_LOGIN`,其他未配置 PC/H5 场景的认证验证码先待确认。 - 2026-07-09 15:31:14 +08:00:根据用户质疑修正 PC-006;不再把“公共地区/文件接口可用”写成“整页可对接”,改为页面覆盖矩阵和缺口清单。 - 2026-07-09 15:34:26 +08:00:同步修正详细规划文件 `docs/superpowers/plans/2026-07-09-pc-api-replan.md` 的 Task 6,并将 PC-006 标记为“已修正”。 -- 2026-07-09 15:41:40 +08:00:按最新 YAML 分析结果重写 `docs/superpowers/plans/2026-07-09-pc-api-replan.md`,新增 PC-007;明确旧 APP 路径不能作为 PC fallback,缺失业务接口统一降级为接口待确认。 +- 2026-07-09 15:41:40 +08:00:按最新 YAML 分析结果重写 `docs/superpowers/plans/2026-07-09-pc-api-replan.md`,新增 PC-007;明确旧路径不能作为 PC fallback,缺失业务接口统一降级为接口待确认。 - 2026-07-09 15:44:18 +08:00:开始执行 PC-001/PC-002,先按 TDD 创建 `config.js` 和 `utils` 公共工具测试,再实现最小配置与工具层。 - 2026-07-09 15:47:17 +08:00:完成 PC-001 和 PC-002 的公共工具层部分;`config.js` 位于根目录,`utils` 只放跨页面公共 JS,页面业务仍留在 `public/js`。 -- 2026-07-09 15:51:34 +08:00:完成 PC-002 的 `api-client.js` 切换;旧 APP 路径不再作为网络请求路径,未覆盖业务统一抛 `PC_API_NOT_AVAILABLE`。 +- 2026-07-09 15:51:34 +08:00:完成 PC-002 的请求客户端切换;旧路径不再作为网络请求路径,未覆盖业务统一抛 `PC_API_NOT_AVAILABLE`。 - 2026-07-09 15:55:28 +08:00:PC-003 认证页验证码阶段完成;登录使用 `WEB_H5_LOGIN`,未确认 PC/H5 场景的注册和找回密码不调用验证中心。 - 2026-07-09 15:57:36 +08:00:收到用户补充截图,确认 PC `clientid` 为 `ced7e5f0498645c6ec642dcf450b036f`、客户端 Key 为 `web_pc`,新增注册场景 `WEB_H5_REGISTER` 和找回密码场景 `WEB_H5_FORGOT_PASSWORD`;同步修正配置、计划和认证页场景映射。 - 2026-07-09 16:00:22 +08:00:PC-003 完成;认证页、资料页、安全页的 PC auth/captcha 接入和脚本顺序已验证。 - 2026-07-09 16:03:23 +08:00:PC-004 完成;上传公共能力切换到 PC 文件接口,相关上传页已补齐公共层脚本顺序。 - 2026-07-09 16:05:12 +08:00:PC-005 完成;地区选择只保留公共行政区划能力,创建家谱等主业务仍按 PC YAML 未覆盖处理。 -- 2026-07-09 16:06:35 +08:00:PC-008 完成;PC YAML 未覆盖业务不会继续发送旧 APP 请求,全量 Node 测试通过。 -- 2026-07-09 16:07:42 +08:00:收尾验证完成;全量 `tests/*.test.js` 通过,`public/js` 非压缩业务脚本 `node --check` 通过,旧 `/genealogy/app/`、旧验证码场景、旧 PC clientId 扫描无输出;`git diff --check` 因当前目录不是 Git 仓库无法执行。 +- 2026-07-09 16:06:35 +08:00:PC-008 完成;PC YAML 未覆盖业务不会继续发送过期请求,全量 Node 测试通过。 +- 2026-07-09 16:07:42 +08:00:收尾验证完成;全量 `tests/*.test.js` 通过,`public/js` 非压缩业务脚本 `node --check` 通过,过期请求路径、旧验证码场景、旧 PC clientId 扫描无输出;`git diff --check` 因当前目录不是 Git 仓库无法执行。 - 2026-07-09 16:09:55 +08:00:开始登录、注册、找回密码三页专项核对;按 PC YAML 的 `PasswordLoginBody`、`PasswordRegisterBody`、`SmsCodeBody`、`PasswordResetBody` 修正页面字段、输入类型、验证码场景声明和文案。 - 2026-07-09 16:12:10 +08:00:登录、注册、找回密码三页专项完成;三页表单已显式声明 `data-captcha-scene`,手机号输入改为 `type="tel"`、`inputmode="numeric"`、`maxlength="11"`,找回密码文案改为只支持注册手机号;`auth-pages.js` 优先读取页面 `data-captcha-scene`。验证:`node tests\auth-pages.test.js`、`node tests\captcha-pages.test.js`、`node tests\api-client.test.js` 通过;三页字段/脚本顺序扫描通过;旧邮箱文案和旧验证码场景扫描无输出。 - 2026-07-09 16:19:11 +08:00:根据用户反馈“接口文档少了很多东西”重新核对 `genealogy-pc-openapi.yaml` 的真实 `paths`;确认当前 YAML 只有验证中心、认证登录、文件上传、行政区划四类共 25 个操作,虽然声明了家谱、成员、字辈、世系、家族圈、文章、相册、祭祀、族务、VIP、消息、反馈等标签和模型,但没有对应可调用路径。结论:这些业务页面不能继续视为已对接,只能保留 `PC_API_NOT_AVAILABLE`,等待后端补充 PC 接口文档。 @@ -309,3 +307,48 @@ - 流程结果:注册成功清除 token 并跳转 `login.html`;当前登录响应从 `data.access_token` 取 JWT,且兼容 `token`、`accessToken`、`tokenValue` 后跳转 `profile.html`;个人资料无 token 或收到 HTTP/业务 `401` 时清 token 并跳转 `index.html`;确认退出无论接口结果都清 token 并跳转 `index.html`。 - 修改文件:`tests/config.test.js`、`tests/utils.test.js`、`utils/ApiClient.js`、`tests/api-client.test.js`、`public/js/profile-pages.js`、`public/js/profile-common.js`、`profile.html`、`tests/profile-pages.test.js`、`tests/profile-logout-structure.test.js`。 - 验证结果:`node tests/config.test.js`、`node tests/utils.test.js`、`node tests/api-client.test.js`、`node tests/auth-pages.test.js`、`node tests/profile-pages.test.js`、`node tests/profile-logout-structure.test.js`、`node --check utils/ApiClient.js`、`node --check public/js/profile-pages.js`、`node --check public/js/profile-common.js` 和全量 Node 测试均通过。 + +## PC-026 安全页认证入口收敛 + +- 状态:部分完成 +- 完成时间:2026-07-11 +- 页面范围:`profile-security.html` +- 接口范围:`/genealogy/pc/auth/login/sms`、`/genealogy/pc/auth/phone`、`/genealogy/pc/auth/account/deactivate`、`/genealogy/pc/auth/logout` +- 契约结果:`login.html` 是密码和短信登录的唯一入口;登录成功跳转 `profile.html`。已登录的账号安全页不得重复发起登录流程。退出登录和账号注销完成后均跳转 `index.html`。 +- 修改结果:删除安全页遗留的短信登录表单、旧接口说明、请求体构造和提交分支;安全页退出无论接口请求结果都跳转首页,账号注销成功后也跳转首页。 +- 后端阻塞:换绑手机仍无法形成完整 PC/H5 流程。`POST /genealogy/pc/auth/sms/code` 必填 `sceneCode` 和 `validToken`,但当前未定义换绑手机的 PC/H5 场景码;不得使用未经确认的场景替代。待后端提供场景码后,补充滑动验证、发送短信验证码和换绑提交链路。 +- 验证结果:先运行 `node tests/security-pages.test.js`,确认旧安全页短信登录导出仍存在而按预期失败;修复后该测试通过。全量验证待本项后续记录补充。 + +## PC-027 PC-only 接口契约清理 + +- 状态:已完成 +- 完成时间:2026-07-11 +- 契约所有者:`genealogy-pc-openapi.yaml` 是 PC/H5 页面接口的唯一依据;运行时请求由 `utils/ApiClient.js` 统一发起。 +- 修改结果:删除旧接口文档和错误对接记录;清除页面、脚本、规划和 PC YAML 中遗留的旧路径、场景码与文档引用;PC YAML 的验证码示例统一使用 `WEB_H5_LOGIN`,注册来源示例为 `PC`。 +- 登录确认:`login.html` 的短信登录继续经 `public/js/auth-pages.js` 调用 `utils/ApiClient.js`,请求 `POST /genealogy/pc/auth/login/sms`,验证码场景为 `WEB_H5_LOGIN`。 +- 验证结果:新增 `tests/pc-api-contract.test.js`。该测试确认旧接口文档与错误记录不存在,扫描当前运行代码、PC YAML 和有效规划没有遗留旧契约,并断言短信登录使用 PC 路径和 `WEB_H5_LOGIN`。 + +## PC-028 当前 PC 接口页面覆盖 + +- 状态:部分完成 +- 完成时间:2026-07-11 +- 接口清单:`genealogy-pc-openapi.yaml` 当前有 25 个操作;`tests/pc-endpoint-coverage.test.js` 对每项操作断言页面调用或明确后端阻塞原因。 +- 已形成页面闭环的 21 项操作:验证码查询/挑战/校验,注册、密码登录、短信登录、短信验证码,资料读取/修改,修改密码、找回密码、注销账号、退出登录,单文件上传、分片初始化/上传/完成,地区下级查询/搜索/路径/详情。 +- 文件上传结果:`profile-data.html` 的头像上传不再要求手填 OSS ID。文件不超过 4 MB 时调用单文件上传;超过 4 MB 时依次调用分片初始化、每片上传和完成上传,完成后回填同一 `avatarOssId`,由“保存资料”提交资料接口。 +- 地区结果:`profile-data.html` 支持按地区名称或编码搜索;选择结果会查询地区详情和路径,再回填省、市、区县选择器后提交资料接口。 +- 后端契约阻塞的 4 项操作: + 1. `GET /auth/code`:接口是兼容旧图形验证码,但当前 PC 登录/注册请求体没有可提交的验证码字段。 + 2. `PUT /genealogy/pc/auth/phone`:发送短信前需要 PC/H5 换绑手机号验证码场景码,当前文档未提供。 + 3. `POST /genealogy/pc/files/reference`:缺少可由当前 PC 页面创建的业务表名和业务 ID 契约。 + 4. `DELETE /genealogy/pc/files/reference`:同样缺少业务表名、业务 ID 和业务字段的来源契约。 +- 浏览器验收顺序: + 1. `register.html`:完成注册,确认跳转 `login.html` 且不保留登录态。 + 2. `login.html` 密码登录:完成滑块验证和登录,确认跳转 `profile.html`。 + 3. `login.html` 短信登录:完成滑块验证、发送短信和登录,确认跳转 `profile.html`。 + 4. `profile.html`:确认资料成功加载;清空本地 token 后重新进入,确认跳转首页。 + 5. `profile-data.html`:修改昵称、性别、生日后保存;上传小于等于 4 MB 的头像并保存资料。 + 6. `profile-data.html`:上传大于 4 MB 的头像,确认网络依次出现 `resumable/init`、`resumable/chunk`、`resumable/complete`,再保存资料。 + 7. `profile-data.html`:搜索地区名称或编码,选择结果,确认省市区回填后保存。 + 8. `forgot-password.html`:完成验证码、短信码和密码重置。 + 9. `profile-security.html`:分别测试修改密码、账号注销和退出登录;退出与注销成功后均回首页。 +- 验证结果:`node tests/pc-endpoint-coverage.test.js`、`node tests/upload-pages.test.js`、`node tests/region-pages.test.js`、`node tests/profile-pages.test.js`、`node tests/auth-pages.test.js`、`node tests/captcha-pages.test.js`、`node tests/api-client.test.js`、`node tests/security-pages.test.js` 均通过。 diff --git a/docs/superpowers/plans/2026-07-09-pc-api-replan.md b/docs/superpowers/plans/2026-07-09-pc-api-replan.md index d6c4d40..aa27ded 100644 --- a/docs/superpowers/plans/2026-07-09-pc-api-replan.md +++ b/docs/superpowers/plans/2026-07-09-pc-api-replan.md @@ -376,10 +376,10 @@ function createUnavailableMethod(name) { Use a Chinese comment above the mapping: `// PC YAML 未提供这些业务 paths,保留方法名只用于阻止旧 APP 路径继续发请求。` -- [ ] **Step 5: Verify no APP auth/files network paths remain** +- [ ] **Step 5: Verify the PC auth/files contract** -Run: `Select-String -Path public\js\api-client.js -Pattern '/genealogy/app/auth|/genealogy/app/files'` -Expected: no matches. +Run: `node tests\pc-api-contract.test.js` +Expected: PC 请求契约扫描通过。 - [ ] **Step 6: Run API client test again** @@ -607,10 +607,10 @@ Expected after implementation: PASS. Only map file capability. Do not submit article/feed/album/ceremony/growth/memo business forms unless PC YAML provides their business endpoints. -- [ ] **Step 4: Verify no APP file path remains** +- [ ] **Step 4: Verify the PC file contract** -Run: `Select-String -Path public\js\api-client.js,public\js\upload-pages.js -Pattern '/genealogy/app/files'` -Expected: no matches. +Run: `node tests\pc-api-contract.test.js` +Expected: PC 请求契约扫描通过。 --- @@ -688,10 +688,10 @@ Expected after implementation: PASS. In each affected page script, catch `PC_API_NOT_AVAILABLE` and render a small existing-style empty state. Add a Chinese comment: `// PC YAML 未提供该业务接口,页面先展示接口待确认状态。` -- [ ] **Step 4: Verify no APP business path is emitted from API client** +- [ ] **Step 4: Verify no obsolete business path is emitted from the API client** -Run: `Select-String -Path public\js\api-client.js -Pattern '/genealogy/app/'` -Expected: no network path matches. +Run: `node tests\pc-api-contract.test.js` +Expected: PC 请求契约扫描通过。 --- @@ -743,16 +743,15 @@ node tests\upload-pages.test.js node tests\region-pages.test.js node tests\unsupported-pages.test.js Get-ChildItem -Path public\js -Filter *.js | Where-Object { $_.Name -notin @('jquery360.js','jquery.min.js') } | Sort-Object Name | ForEach-Object { node --check $_.FullName } -Select-String -Path public\js\api-client.js -Pattern '/genealogy/app/' -Select-String -Path public\js\auth-pages.js,public\js\captcha-pages.js,tests\auth-pages.test.js,tests\captcha-pages.test.js -Pattern 'PC_LOGIN|PC_REGISTER|PC_PASSWORD_RESET|APP_LOGIN|APP_REGISTER|APP_FORGOT_PASSWORD' +node tests\pc-api-contract.test.js git diff --check ``` Expected: - All listed Node tests pass. - Business JS syntax check passes. -- `api-client.js` contains no `/genealogy/app/` network path. -- Auth and captcha code/tests contain no stale APP/old PC scene defaults. +- PC 请求契约扫描通过。 +- 认证和验证码代码/tests 不含过期场景默认值。 - `git diff --check` passes, or if this directory is not a Git repository, record the exact output. ## Self-Review diff --git a/docs/superpowers/plans/2026-07-09-pc-auth-three-pages.md b/docs/superpowers/plans/2026-07-09-pc-auth-three-pages.md index 3968db3..e875082 100644 --- a/docs/superpowers/plans/2026-07-09-pc-auth-three-pages.md +++ b/docs/superpowers/plans/2026-07-09-pc-auth-three-pages.md @@ -10,7 +10,7 @@ ## Global Constraints -- 接口依据只使用 `genealogy-pc-openapi.yaml` 与用户补充的 Apifox 截图,不再使用 `APP.openapi.json`。 +- 接口依据只使用 `genealogy-pc-openapi.yaml` 与用户补充的 Apifox 截图。 - 开发环境接口地址为 `https://test-genealogy-api.ddxcjp.cn`。 - PC `clientid` 为 `ced7e5f0498645c6ec642dcf450b036f`,租户 ID 为 `000000`。 - 登录验证码场景为 `WEB_H5_LOGIN`,注册验证码场景为 `WEB_H5_REGISTER`,忘记密码验证码场景为 `WEB_H5_FORGOT_PASSWORD`。 diff --git a/docs/superpowers/plans/2026-07-09-tac-captcha-auth.md b/docs/superpowers/plans/2026-07-09-tac-captcha-auth.md index 1783a91..d499fc5 100644 --- a/docs/superpowers/plans/2026-07-09-tac-captcha-auth.md +++ b/docs/superpowers/plans/2026-07-09-tac-captcha-auth.md @@ -2,7 +2,7 @@ > **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:** 将 `public/tac` 滑动验证接入登录、注册、忘记密码三个认证页面,并按 `APP.openapi.json` 的验证中心接口换取 `validToken` 后再提交业务接口。 +**Goal:** 将 `public/tac` 滑动验证接入登录、注册、忘记密码三个认证页面,并按 `genealogy-pc-openapi.yaml` 的验证中心接口换取 `validToken` 后再提交业务接口。 **Architecture:** 新增 `public/js/captcha-pages.js` 作为 TAC 与验证中心接口之间的适配层;`auth-pages.js` 在提交登录、注册、发送短信、重置密码前调用验证码适配层。API 基础地址、clientId、tenantId 继续由 `api-client.js` 统一提供。 @@ -10,7 +10,7 @@ ## Global Constraints -- 严格依据 `APP.openapi.json` 的 `/captcha/require`、`/captcha/challenge`、`/captcha/verify` 字段接入。 +- 严格依据 `genealogy-pc-openapi.yaml` 的 `/captcha/require`、`/captcha/challenge`、`/captcha/verify` 字段接入。 - 业务 JS 不压缩,新增注释使用中文。 - 自有样式写入 CSS 文件,不通过自有 JS 注入样式。 - 第三方 `tac.min.js` 保持原样,不重写其内部样式和 DOM 生成逻辑。 diff --git a/docs/superpowers/plans/2026-07-10-pc-tracker-reverification.md b/docs/superpowers/plans/2026-07-10-pc-tracker-reverification.md index 864a323..8babde7 100644 --- a/docs/superpowers/plans/2026-07-10-pc-tracker-reverification.md +++ b/docs/superpowers/plans/2026-07-10-pc-tracker-reverification.md @@ -57,9 +57,9 @@ Expected: 四条命令均通过。 - [x] **Step 1: 运行工具和 API 降级测试** -Run: `node tests\\utils.test.js; node tests\\api-client.test.js; rg -n "/genealogy/app/" public\\js\\api-client.js` +Run: `node tests\\utils.test.js; node tests\\api-client.test.js; node tests\\pc-api-contract.test.js` -Expected: 两个测试通过,旧 `/genealogy/app/` 请求路径无匹配结果。 +Expected: 三个测试通过,PC 请求契约扫描无遗留项。 - [x] **Step 2: 核对未覆盖业务的错误边界** @@ -123,7 +123,7 @@ Expected: 所有测试和语法检查通过。 - [x] **Step 2: 扫描旧路径与页面覆盖边界** -Run: `rg -n "/genealogy/app/files|/genealogy/app/region" public\\js; rg -n "PC_API_NOT_AVAILABLE" public\\js\\api-client.js` +Run: `rg -n "PC_API_NOT_AVAILABLE" utils\\ApiClient.js` Expected: 文件、地区旧 APP 路径无匹配;业务页面覆盖边界仍由 `PC_API_NOT_AVAILABLE` 保护。 diff --git a/docs/superpowers/plans/2026-07-11-pc-endpoint-page-coverage.md b/docs/superpowers/plans/2026-07-11-pc-endpoint-page-coverage.md new file mode 100644 index 0000000..cf7765d --- /dev/null +++ b/docs/superpowers/plans/2026-07-11-pc-endpoint-page-coverage.md @@ -0,0 +1,278 @@ +# PC Endpoint Page Coverage 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:** Make every callable operation in `genealogy-pc-openapi.yaml` traceable to a real PC page flow, an automated regression test, and a manual acceptance step. + +**Architecture:** `utils/ApiClient.js` remains the sole network contract owner. Page modules in `public/js` own input validation, loading and success/error state; `tests` prove their request and navigation behavior. The coverage matrix distinguishes a complete user flow from an endpoint that is documented but lacks the contract required to expose it safely. + +**Tech Stack:** Static HTML, browser JavaScript, Axios, Layui, Node `assert` tests. + +## Global Constraints + +- Runtime API base URL is owned only by `config.js`: `http://182.61.18.23:8080`. +- Only PC/H5 routes and scenes defined by `genealogy-pc-openapi.yaml` may be requested. +- Registration never persists a token; password and SMS login persist the returned token and navigate to `profile.html`. +- Logout, unauthenticated profile access and account deactivation navigate to `index.html`. +- Every behavior change starts with a failing Node test and ends with focused plus full test verification. +- No page invents a business table name, business ID, CAPTCHA scene or legacy captcha submission field that is not in the PC contract. + +## Endpoint Matrix + +| Operation | Page owner | Automated test | Manual acceptance order | Status target | +| --- | --- | --- | --- | --- | +| `GET /captcha/require` | `CaptchaPages` on auth forms | `tests/captcha-pages.test.js` | 1-4 | Complete | +| `POST /captcha/challenge` | `CaptchaPages` on auth forms | `tests/captcha-pages.test.js` | 1-4 | Complete | +| `POST /captcha/verify` | `CaptchaPages` on auth forms | `tests/captcha-pages.test.js` | 1-4 | Complete | +| `GET /auth/code` | no safe consumer | `tests/pc-endpoint-coverage.test.js` | blocked | Backend contract required | +| Register, password login, SMS login, SMS code | `register.html`, `login.html` | `tests/auth-pages.test.js`, `tests/api-client.test.js` | 1-3 | Complete | +| Profile read/update | `profile.html`, `profile-data.html` | `tests/profile-pages.test.js` | 4-5 | Complete | +| Password reset | `forgot-password.html` | `tests/auth-pages.test.js` | 6 | Complete | +| Password change, logout, account deactivation | `profile-security.html` | `tests/security-pages.test.js` | 7-9 | Complete | +| Phone change | `profile-security.html` | `tests/security-pages.test.js` | blocked | PC/H5 phone SMS scene required | +| Single upload | profile avatar and existing upload fields | `tests/upload-pages.test.js` | 10 | Complete | +| Resumable init/chunk/complete | same file input for large files | `tests/upload-pages.test.js`, `tests/api-client.test.js` | 11 | Complete | +| File reference bind/release | no safe business entity contract | `tests/pc-endpoint-coverage.test.js` | blocked | PC business table and ID contract required | +| Region children/path/search/detail | profile address picker and region search control | `tests/region-pages.test.js`, `tests/profile-pages.test.js` | 12 | Complete | + +## Task 1: Enforce Endpoint Coverage + +**Files:** +- Create: `tests/pc-endpoint-coverage.test.js` +- Modify: `docs/pc-api-page-integration-tracker-2026-07-09.md` + +**Interfaces:** +- Consumes: the 25 operations declared under `paths` in `genealogy-pc-openapi.yaml`. +- Produces: a test-owned `ENDPOINTS` list that assigns every operation one of `complete` or `blocked` with a page/test owner. + +- [ ] **Step 1: Write the failing coverage test** + +```js +assert.deepStrictEqual(missingOperations, []); +assert.deepStrictEqual(unownedOperations, []); +assert.deepStrictEqual(unsupportedBlockedOperations, []); +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `node tests\pc-endpoint-coverage.test.js` + +Expected: failure listing the endpoint operations without a page/test/blocker owner. + +- [ ] **Step 3: Add the explicit 25-operation matrix** + +```js +const ENDPOINTS = { + 'GET /captcha/require': { page: 'auth', test: 'captcha-pages', status: 'complete' }, + 'GET /auth/code': { status: 'blocked', reason: 'legacy captcha has no PC request field' } +}; +``` + +- [ ] **Step 4: Run the test to verify it passes** + +Run: `node tests\pc-endpoint-coverage.test.js` + +Expected: `pc-endpoint-coverage tests passed`. + +## Task 2: Complete and Test the Auth Journey + +**Files:** +- Modify: `public/js/auth-pages.js` +- Modify: `public/js/profile-pages.js` +- Modify: `public/js/security-pages.js` +- Modify: `tests/auth-pages.test.js` +- Modify: `tests/profile-pages.test.js` +- Modify: `tests/security-pages.test.js` + +**Interfaces:** +- Consumes: `GenealogyApi.login`, `loginBySms`, `register`, `sendSmsCode`, `resetPassword`, `getProfile`, `updateProfile`, `changePassword`, `deactivateAccount`, and `logout`. +- Produces: consistent form validation, token state and redirect behavior for the acceptance steps 1-9. + +- [ ] **Step 1: Write failing redirect and request tests** + +```js +assert.strictEqual(loginRoot.location.href, 'profile.html'); +assert.strictEqual(registerRoot.location.href, 'login.html'); +assert.strictEqual(logoutRoot.location.href, 'index.html'); +``` + +- [ ] **Step 2: Run focused tests to verify failure** + +Run: `node tests\auth-pages.test.js; node tests\profile-pages.test.js; node tests\security-pages.test.js` + +Expected: a failure naming the missing flow or redirect. + +- [ ] **Step 3: Implement only the missing flow branch in its page module** + +```js +await api.loginBySms(buildSmsLoginBody(values)); +root.location.href = 'profile.html'; +``` + +Use the corresponding documented endpoint method for each form; do not create a second token store or a page-local route string owner. + +- [ ] **Step 4: Run focused tests** + +Run: `node tests\auth-pages.test.js; node tests\profile-pages.test.js; node tests\security-pages.test.js` + +Expected: all three scripts print their pass messages. + +## Task 3: Make Region Search, Path and Detail Usable + +**Files:** +- Modify: `profile-data.html` +- Modify: `public/js/region-pages.js` +- Modify: `tests/region-pages.test.js` + +**Interfaces:** +- Consumes: `regionChildren(parentCode)`, `regionSearch({ keyword })`, `regionPath(regionCode)`, and `regionDetail(regionCode)`. +- Produces: a profile-address picker that can search by name/code, select a result, resolve its path and write province/city/district codes before profile save. + +- [ ] **Step 1: Write a failing result-normalization and selected-path test** + +```js +assert.deepStrictEqual(RegionPages.buildRegionSelection(result), { + provinceCode: '510000', + cityCode: '510100', + districtCode: '510104' +}); +``` + +- [ ] **Step 2: Run the focused test to verify failure** + +Run: `node tests\region-pages.test.js` + +Expected: failure because `buildRegionSelection` is not exported. + +- [ ] **Step 3: Add the profile search control and selection behavior** + +```js +var path = await api.regionPath(regionCode); +var selection = buildRegionSelection(path); +applyRegionSelection(picker, selection); +await api.regionDetail(regionCode); +``` + +- [ ] **Step 4: Run focused tests** + +Run: `node tests\region-pages.test.js; node tests\profile-pages.test.js` + +Expected: both scripts print their pass messages. + +## Task 4: Complete Single and Resumable File Upload + +**Files:** +- Modify: `public/js/upload-pages.js` +- Modify: `utils/ApiClient.js` +- Modify: `tests/upload-pages.test.js` +- Modify: `tests/api-client.test.js` + +**Interfaces:** +- Consumes: `uploadFile(file)`, `initResumableUpload(body)`, `uploadChunk(body)`, `completeResumableUpload(body)`. +- Produces: `uploadFileForPage(file, options)` which uses single upload for files at or below the configured threshold and the init/chunk/complete sequence for larger files. + +- [ ] **Step 1: Write failing upload-strategy tests** + +```js +assert.strictEqual(UploadPages.getUploadMode({ size: 1024 }, 4194304), 'single'); +assert.strictEqual(UploadPages.getUploadMode({ size: 4194305 }, 4194304), 'resumable'); +``` + +- [ ] **Step 2: Run focused tests to verify failure** + +Run: `node tests\upload-pages.test.js; node tests\api-client.test.js` + +Expected: failure because `getUploadMode` does not exist. + +- [ ] **Step 3: Implement sequential resumable upload** + +```js +var init = await api.initResumableUpload(initBody); +for (index = 0; index < chunks.length; index += 1) { + await api.uploadChunk({ uploadId: init.uploadId, chunkIndex: index, chunkMd5: chunkMd5, file: chunks[index] }); +} +return api.completeResumableUpload({ uploadId: init.uploadId, fileMd5: fileMd5, fileSize: file.size }); +``` + +- [ ] **Step 4: Run focused tests** + +Run: `node tests\upload-pages.test.js; node tests\api-client.test.js` + +Expected: both scripts print their pass messages. + +## Task 5: Record and Enforce Backend-Contract Blocks + +**Files:** +- Modify: `docs/pc-api-page-integration-tracker-2026-07-09.md` +- Modify: `tests/pc-endpoint-coverage.test.js` + +**Interfaces:** +- Consumes: the legacy captcha response, phone SMS scene requirements, and file-reference required business fields from the PC YAML. +- Produces: three named blocked operations with an exact missing backend input and no speculative page request. + +- [ ] **Step 1: Assert exact blocker reasons** + +```js +assert.strictEqual(ENDPOINTS['GET /auth/code'].reason, 'legacy captcha has no PC request field'); +assert.strictEqual(ENDPOINTS['PUT /genealogy/pc/auth/phone'].reason, 'PC/H5 phone SMS scene is not documented'); +assert.strictEqual(ENDPOINTS['POST /genealogy/pc/files/reference'].reason, 'PC business table and ID contract is not documented'); +``` + +- [ ] **Step 2: Run the test to verify failure** + +Run: `node tests\pc-endpoint-coverage.test.js` + +Expected: failure until all three reasons are explicit. + +- [ ] **Step 3: Update the tracker without adding a fake request** + +```md +| Blocked operation | Missing backend contract | Page behavior | +| --- | --- | --- | +| `GET /auth/code` | legacy code submission field | no page action | +``` + +- [ ] **Step 4: Run the test to verify it passes** + +Run: `node tests\pc-endpoint-coverage.test.js` + +Expected: `pc-endpoint-coverage tests passed`. + +## Task 6: Final Verification and User Test Script + +**Files:** +- Modify: `docs/pc-api-page-integration-tracker-2026-07-09.md` + +- [ ] **Step 1: Run syntax checks** + +Run: `node --check utils\ApiClient.js` + +Run: `node --check public\js\auth-pages.js` + +Run: `node --check public\js\region-pages.js` + +Run: `node --check public\js\upload-pages.js` + +Expected: each command exits with code 0. + +- [ ] **Step 2: Run the complete Node suite** + +Run: `Get-ChildItem -Path tests -Filter *.test.js | ForEach-Object { & node $_.FullName; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } }` + +Expected: every test file prints its pass message. + +- [ ] **Step 3: Check the diff** + +Run: `git diff --check` + +Expected: exit code 0; CRLF conversion notices are informational only. + +- [ ] **Step 4: Record manual acceptance steps** + +Record the precise browser order: register, password login, SMS login, profile display/edit, reset password, password change, logout, account deactivation, address search, single upload, resumable upload, then each documented backend blocker. + +## Self-Review + +- Coverage: Tasks 1-5 assign every documented operation an implementation owner or an explicit backend block; Task 6 provides the requested sequential test script. +- Contract discipline: `ApiClient` remains the only route owner; page modules do not create undocumented paths, scene codes, business tables or identifiers. +- Scope: pages without callable PC paths remain outside implementation; their schemas are not treated as endpoints. diff --git a/download.html b/download.html index e69b274..478c50f 100644 --- a/download.html +++ b/download.html @@ -55,7 +55,6 @@

下载方式

前台先展示下载入口,后续可以接真实应用商店地址。

-
下载推广内容加载中
diff --git a/genealogy-pc-openapi.yaml b/genealogy-pc-openapi.yaml index 9bbb366..3c98b57 100644 --- a/genealogy-pc-openapi.yaml +++ b/genealogy-pc-openapi.yaml @@ -3,27 +3,26 @@ info: title: Genealogy PC/H5 API version: 1.0.0 description: | - 家谱业务 APP/PC 用户侧接口文档,用于 Apifox 导入。 + 家谱业务 PC/H5 用户侧接口文档,用于 Apifox 导入。 导入方式:Apifox -> 导入 API 数据 -> OpenAPI/Swagger -> 选择本文件。 约定: - - APP 路径前缀为 `/genealogy/app` - PC/H5 路径前缀为 `/genealogy/pc` - 后台管理接口不包含在本文件内 - 登录后接口需要携带 token,且请求 Header 需携带 `clientid` servers: - - url: http://127.0.0.1:8080 + - url: http://182.61.18.23:8080 description: Local Java backend - - url: http://127.0.0.1:9527/dev-api + - url: http://182.61.18.23:8080/dev-api description: Local frontend proxy tags: - name: 验证中心 description: 统一验证码、天爱行为验证码和系统图形验证码 - name: 认证登录 - description: APP/PC 登录注册与账号资料 + description: PC/H5 登录注册与账号资料 - name: 文件上传 - description: APP/PC 统一文件上传与业务引用绑定 + description: PC/H5 统一文件上传与业务引用绑定 - name: 行政区划 description: 行政区划 - name: 家谱 @@ -67,18 +66,18 @@ paths: type: string example: "000000" - name: clientId - description: 客户端ID,对应后台客户端管理中的APP/PC/小程序等终端 + description: 客户端ID,对应后台 PC/H5 客户端配置 in: query schema: type: string example: 428a8310cd442757ae699df5d894f051 - name: sceneCode - description: 验证场景编码,例如APP_LOGIN、PC_LOGIN、APP_REGISTER + description: 验证场景编码,例如WEB_H5_LOGIN、WEB_H5_REGISTER in: query required: true schema: type: string - example: APP_LOGIN + example: WEB_H5_LOGIN - name: subject description: 验证主体,通常为手机号、用户ID或登录账号 in: query @@ -114,7 +113,7 @@ paths: get: tags: [验证中心] summary: 兼容旧系统图形验证码 - description: 老版后台登录图形验证码入口。新的 APP/PC 业务优先使用 /captcha/require + /captcha/challenge + /captcha/verify。 + description: 老版后台登录图形验证码入口。新的 PC/H5 业务优先使用 /captcha/require + /captcha/challenge + /captcha/verify。 security: [] responses: '200': @@ -385,7 +384,7 @@ components: parameters: ClientIdHeader: name: clientid - description: 客户端ID,请求Header携带,用于区分APP/PC/小程序等终端 + description: 客户端ID,请求 Header 携带,用于识别 PC/H5 终端 in: header required: true schema: @@ -493,7 +492,7 @@ components: phone: "13800000000" password: "e10adc3949ba59abbe56e057f20f883e" nickName: "测试用户" - registerSource: "app" + registerSource: "PC" validToken: "captcha-ticket-or-sms-token" PasswordLogin: required: true @@ -528,7 +527,7 @@ components: example: tenantId: "000000" phone: "13800000000" - sceneCode: "APP_LOGIN" + sceneCode: "WEB_H5_LOGIN" validToken: "captcha-ticket" ProfileUpdate: required: true @@ -711,7 +710,7 @@ components: example: tenantId: "000000" clientId: "428a8310cd442757ae699df5d894f051" - sceneCode: "APP_LOGIN" + sceneCode: "WEB_H5_LOGIN" subject: "13800000000" VerificationCheck: required: true @@ -725,7 +724,7 @@ components: value: tenantId: "000000" clientId: "428a8310cd442757ae699df5d894f051" - sceneCode: "APP_LOGIN" + sceneCode: "WEB_H5_LOGIN" subject: "13800000000" challengeId: "CAPTCHA_CHALLENGE_ID" providerCode: "tianai" @@ -743,7 +742,7 @@ components: value: tenantId: "000000" clientId: "428a8310cd442757ae699df5d894f051" - sceneCode: "APP_LOGIN" + sceneCode: "WEB_H5_LOGIN" subject: "13800000000" challengeId: "CAPTCHA_CHALLENGE_ID" providerCode: "ruoyi_image" @@ -923,7 +922,7 @@ components: description: 租户ID,用于区分不同租户的数据和验证策略 type: string clientId: - description: 客户端ID,对应后台客户端管理中的APP/PC/小程序等终端 + description: 客户端ID,对应后台 PC/H5 客户端配置 type: string clientKey: type: string @@ -949,7 +948,7 @@ components: required: [grantType, tenantId, phone, password] properties: clientId: - description: 客户端ID,对应后台客户端管理中的APP/PC/小程序等终端 + description: 客户端ID,对应后台 PC/H5 客户端配置 type: string grantType: description: 授权类型,例如password、sms、wechat、apple @@ -971,7 +970,7 @@ components: description: 用户昵称 type: string registerSource: - description: 注册来源,例如APP、PC、H5、MINI_PROGRAM + description: 注册来源,例如PC、H5 type: string validToken: description: 验证中心通过后返回的票据,用于注册/登录/换绑等二次校验 @@ -981,7 +980,7 @@ components: required: [grantType, tenantId, phone, password] properties: clientId: - description: 客户端ID,对应后台客户端管理中的APP/PC/小程序等终端 + description: 客户端ID,对应后台 PC/H5 客户端配置 type: string grantType: description: 授权类型,例如password、sms、wechat、apple @@ -1007,7 +1006,7 @@ components: required: [grantType, tenantId, phone, smsCode] properties: clientId: - description: 客户端ID,对应后台客户端管理中的APP/PC/小程序等终端 + description: 客户端ID,对应后台 PC/H5 客户端配置 type: string grantType: description: 授权类型,例如password、sms、wechat、apple @@ -1030,7 +1029,7 @@ components: required: [grantType, tenantId, sceneCode, phone, validToken] properties: clientId: - description: 客户端ID,对应后台客户端管理中的APP/PC/小程序等终端 + description: 客户端ID,对应后台 PC/H5 客户端配置 type: string grantType: description: 授权类型,例如password、sms、wechat、apple @@ -1041,9 +1040,9 @@ components: type: string example: "000000" sceneCode: - description: 验证场景编码,例如APP_LOGIN、PC_LOGIN、APP_REGISTER + description: 验证场景编码,例如WEB_H5_LOGIN、WEB_H5_REGISTER type: string - example: APP_LOGIN + example: WEB_H5_LOGIN phone: description: 手机号 type: string @@ -1290,14 +1289,14 @@ components: description: 客户端 ID sceneCode: type: string - description: 验证场景编码,如 ADMIN_LOGIN/APP_LOGIN/APP_REGISTER + description: 验证场景编码,例如WEB_H5_LOGIN、WEB_H5_REGISTER subject: type: string description: 验证主体,如手机号/用户名/IP example: tenantId: "000000" clientId: "428a8310cd442757ae699df5d894f051" - sceneCode: "APP_LOGIN" + sceneCode: "WEB_H5_LOGIN" subject: "13800000000" VerificationCheckBody: type: object @@ -1307,10 +1306,10 @@ components: description: 租户ID,用于区分不同租户的数据和验证策略 type: string clientId: - description: 客户端ID,对应后台客户端管理中的APP/PC/小程序等终端 + description: 客户端ID,对应后台 PC/H5 客户端配置 type: string sceneCode: - description: 验证场景编码,例如APP_LOGIN、PC_LOGIN、APP_REGISTER + description: 验证场景编码,例如WEB_H5_LOGIN、WEB_H5_REGISTER type: string subject: description: 验证主体,通常为手机号、用户ID或登录账号 @@ -1341,7 +1340,7 @@ components: description: 验证码类型,例如SLIDER、ROTATE、CONCAT、WORD_IMAGE_CLICK type: string sceneCode: - description: 验证场景编码,例如APP_LOGIN、PC_LOGIN、APP_REGISTER + description: 验证场景编码,例如WEB_H5_LOGIN、WEB_H5_REGISTER type: string ttlSeconds: description: 验证或票据有效秒数 @@ -1350,7 +1349,7 @@ components: required: true providerCode: "tianai" captchaType: "SLIDER" - sceneCode: "APP_LOGIN" + sceneCode: "WEB_H5_LOGIN" ttlSeconds: 300 VerificationChallengeVo: type: object diff --git a/notice-detail.html b/notice-detail.html index c812882..7c66a05 100644 --- a/notice-detail.html +++ b/notice-detail.html @@ -49,7 +49,6 @@
-

平台前台页面主要用于展示家族文化与公开资料。涉及成员联系方式、详细个人信息、未审核资料等内容,不会在公开页面直接呈现。 diff --git a/profile-album.html b/profile-album.html index fbccbb0..e7c0f85 100644 --- a/profile-album.html +++ b/profile-album.html @@ -59,7 +59,6 @@

新建 / 编辑相册

-
@@ -98,7 +97,6 @@
请选择相册查看照片
-
-
-

短信登录校验

- -
-
-
- - -
-
- - -
-
-
- - -
-
- - 等待提交 -
-
-

注销账号

diff --git a/profile-services.html b/profile-services.html index af2773c..6f5a942 100644 --- a/profile-services.html +++ b/profile-services.html @@ -95,7 +95,6 @@ >
-

会员服务

选择适合当前家谱的会员套餐,创建订单后继续完成支付。

@@ -127,7 +126,6 @@
-

会员订单

diff --git a/profile-tree.html b/profile-tree.html index 11877d6..f56bbc0 100644 --- a/profile-tree.html +++ b/profile-tree.html @@ -100,7 +100,6 @@

新增成员

-
diff --git a/public/js/album-pages.js b/public/js/album-pages.js index 7854217..ca65199 100644 --- a/public/js/album-pages.js +++ b/public/js/album-pages.js @@ -101,7 +101,6 @@ } function buildAlbumBody(values) { - // AlbumBody 来自 APP.openapi.json,albumName 必填。 var source = values || {}; return { @@ -114,7 +113,6 @@ } function buildPhotoBody(values) { - // AlbumPhotoBody 来自 APP.openapi.json,ossId 必填。 var source = values || {}; return { diff --git a/public/js/article-pages.js b/public/js/article-pages.js index 8ed406e..a886c91 100644 --- a/public/js/article-pages.js +++ b/public/js/article-pages.js @@ -115,7 +115,6 @@ } function buildArticleBody(values) { - // ArticleBody 来自 APP.openapi.json,标题和正文为核心必填。 var source = values || {}; return { diff --git a/public/js/ceremony-pages.js b/public/js/ceremony-pages.js index a2981ea..07c0788 100644 --- a/public/js/ceremony-pages.js +++ b/public/js/ceremony-pages.js @@ -107,7 +107,6 @@ } function buildCeremonyBody(values) { - // CeremonyBody 来自 APP.openapi.json,ceremonyType 和 ceremonyTitle 必填。 var source = values || {}; return { @@ -133,7 +132,6 @@ } function buildMeritBody(values) { - // MeritRecordBody 来自 APP.openapi.json,donorName 和 meritTitle 必填。 var source = values || {}; return { diff --git a/public/js/feed-pages.js b/public/js/feed-pages.js index ff7279e..0ec37b0 100644 --- a/public/js/feed-pages.js +++ b/public/js/feed-pages.js @@ -106,7 +106,6 @@ } function buildFeedBody(values) { - // FamilyFeedBody 来自 APP.openapi.json。 var source = values || {}; return { diff --git a/public/js/genealogy-pages.js b/public/js/genealogy-pages.js index f6287b8..38cbbfa 100644 --- a/public/js/genealogy-pages.js +++ b/public/js/genealogy-pages.js @@ -128,7 +128,6 @@ } function formatJoinMode(value) { - // APP.openapi.json 中 joinMode 为枚举值,页面展示时转成中文。 var map = { 0: '关闭加入', 1: '审核加入', diff --git a/public/js/growth-pages.js b/public/js/growth-pages.js index d6589be..c7e4d16 100644 --- a/public/js/growth-pages.js +++ b/public/js/growth-pages.js @@ -106,7 +106,6 @@ } function buildGrowthBody(values) { - // GrowthRecordBody 来自 APP.openapi.json,recordTitle 必填。 var source = values || {}; return { diff --git a/public/js/lineage-pages.js b/public/js/lineage-pages.js index de570a3..e45a88f 100644 --- a/public/js/lineage-pages.js +++ b/public/js/lineage-pages.js @@ -113,7 +113,6 @@ } function buildLineagePersonBody(values) { - // LineagePersonBody 来自 APP.openapi.json,空值统一转为 undefined,避免提交无意义空字符串。 var source = values || {}; return { diff --git a/public/js/member-admin-pages.js b/public/js/member-admin-pages.js index 723a03d..74c8a38 100644 --- a/public/js/member-admin-pages.js +++ b/public/js/member-admin-pages.js @@ -113,7 +113,6 @@ } function buildMemberUpdateBody(values) { - // GenealogyMemberUpdateBody 来自 APP.openapi.json。 var source = values || {}; return { diff --git a/public/js/memo-pages.js b/public/js/memo-pages.js index b4cc00d..7af3f8e 100644 --- a/public/js/memo-pages.js +++ b/public/js/memo-pages.js @@ -110,7 +110,6 @@ } function buildMemoBody(values) { - // MemoBody 来自 APP.openapi.json,memoTitle 必填。 var source = values || {}; return { diff --git a/public/js/region-pages.js b/public/js/region-pages.js index ff50fcf..5a5641b 100644 --- a/public/js/region-pages.js +++ b/public/js/region-pages.js @@ -58,6 +58,37 @@ return pick(item, ['regionName', 'name', 'label'], '未命名地区'); } + function getRegionLevel(item) { + var source = item || {}; + var level = Number(pick(source, ['level', 'regionLevel'], 0)); + var code = getRegionCode(source); + + if (level >= 1 && level <= 3) return level; + if (!/^\d{6}$/.test(code)) return 0; + if (/0000$/.test(code)) return 1; + if (/00$/.test(code)) return 2; + return 3; + } + + function buildRegionSelection(items) { + var selection = { + provinceCode: '', + cityCode: '', + districtCode: '' + }; + + normalizeList(items).forEach(function (item) { + var code = getRegionCode(item); + var level = getRegionLevel(item); + + if (level === 1) selection.provinceCode = code; + if (level === 2) selection.cityCode = code; + if (level === 3) selection.districtCode = code; + }); + + return selection; + } + function buildRegionOption(item) { return ''; } @@ -180,6 +211,91 @@ }); } + async function applyRegionSelection(picker, selection) { + var province = query('[data-region-level="province"]', picker); + var city = query('[data-region-level="city"]', picker); + var district = query('[data-region-level="district"]', picker); + var values = selection || {}; + + if (!values.provinceCode) return; + + province.value = values.provinceCode; + resetSelect(city, '请选择市'); + resetSelect(district, '请选择区县'); + + if (values.cityCode) { + await loadChildrenInto(city, values.provinceCode, '请选择市'); + city.value = values.cityCode; + } + + if (values.districtCode && values.cityCode) { + await loadChildrenInto(district, values.cityCode, '请选择区县'); + district.value = values.districtCode; + } + + updateTargetCode(picker); + } + + function renderSearchResults(container, items) { + var list = normalizeList(items); + + if (!container) return; + container.innerHTML = list.length ? list.map(function (item) { + var code = getRegionCode(item); + var name = getRegionName(item); + + return ''; + }).join('') : '

未找到匹配地区

'; + } + + async function submitRegionSearch(form) { + var api = getApi(); + var values = getFormValues(form); + var results = query('[data-region-search-results]', form.parentNode); + var pathText = query('[data-region-search-path]', form.parentNode); + + if (!api) return; + if (!values.regionKeyword || !values.regionKeyword.trim()) { + showMessage('请输入地区名称或编码'); + return; + } + + if (pathText) pathText.textContent = '搜索中...'; + try { + renderSearchResults(results, await api.regionSearch({ + keyword: values.regionKeyword.trim(), + limit: 20 + })); + if (pathText) pathText.textContent = '请选择一个地区'; + } catch (error) { + if (pathText) pathText.textContent = error.message || '地区搜索失败'; + showMessage(error.message || '地区搜索失败'); + } + } + + async function selectSearchResult(button) { + var api = getApi(); + var code = button.getAttribute('data-region-search-result'); + var section = button.closest('.module-panel'); + var picker = section && query('[data-region-picker]', section); + var pathText = section && query('[data-region-search-path]', section); + var detail; + var path; + + if (!api || !code || !picker) return; + + if (pathText) pathText.textContent = '正在定位地区...'; + try { + detail = await api.regionDetail(code); + path = await api.regionPath(getRegionCode(detail) || code); + await applyRegionSelection(picker, buildRegionSelection(path)); + if (pathText) pathText.textContent = buildPathText(path); + } catch (error) { + if (pathText) pathText.textContent = error.message || '地区定位失败'; + showMessage(error.message || '地区定位失败'); + } + } + async function submitProfileRegion(form) { var api = getApi(); var values = getFormValues(form); @@ -208,6 +324,23 @@ }); } + function bindSearchForms() { + queryAll('[data-region-search-form]').forEach(function (form) { + form.addEventListener('submit', function (event) { + event.preventDefault(); + submitRegionSearch(form); + }); + }); + + documentRef.addEventListener('click', function (event) { + var button = event.target.closest('[data-region-search-result]'); + + if (!button) return; + event.preventDefault(); + selectSearchResult(button); + }); + } + function init() { if (!documentRef) return; @@ -215,12 +348,14 @@ initPicker(picker); }); bindProfileForms(); + bindSearchForms(); } return { normalizeList: normalizeList, buildRegionOption: buildRegionOption, buildPathText: buildPathText, + buildRegionSelection: buildRegionSelection, getFinalRegionCode: getFinalRegionCode, buildProfileRegionBody: buildProfileRegionBody, init: init diff --git a/public/js/security-pages.js b/public/js/security-pages.js index 4588e9f..f127e46 100644 --- a/public/js/security-pages.js +++ b/public/js/security-pages.js @@ -49,16 +49,6 @@ }; } - function buildSmsLoginBody(values) { - var source = values || {}; - - return { - phone: String(source.phone || '').trim(), - smsCode: String(source.smsCode || '').trim(), - validToken: trimOrUndefined(source.validToken) - }; - } - function buildDeactivateBody(values, hashFn) { var source = values || {}; var hash = hashFn || hashPassword; @@ -154,25 +144,6 @@ } } - async function submitSmsLogin(form) { - var api = getApi(); - var body = buildSmsLoginBody(getFormValues(form)); - - if (!api) return; - if (!body.phone || !body.smsCode) { - showMessage('请填写手机号和验证码'); - return; - } - - try { - await api.smsLogin(body); - setStatus(form, '短信登录已通过'); - showMessage('短信登录已通过'); - } catch (error) { - showMessage(error.message || '短信登录失败'); - } - } - async function submitDeactivate(form) { var api = getApi(); var values = getFormValues(form); @@ -191,7 +162,7 @@ try { await api.deactivateAccount(buildDeactivateBody(values)); showMessage('账号已提交注销'); - root.location.href = 'login.html'; + root.location.href = 'index.html'; } catch (error) { showMessage(error.message || '账号注销失败'); } @@ -200,14 +171,14 @@ async function logout() { var api = getApi(); - if (!api) return; if (root.confirm && !root.confirm('确认退出当前账号?')) return; try { - await api.logout(); - root.location.href = 'login.html'; + if (api) await api.logout(); } catch (error) { - showMessage(error.message || '退出登录失败'); + // ApiClient.logout 会在请求失败时清理本地 token,页面仍应离开受保护区域。 + } finally { + root.location.href = 'index.html'; } } @@ -224,7 +195,6 @@ if (formType === 'password') submitPassword(form); if (formType === 'phone') submitPhone(form); - if (formType === 'sms-login') submitSmsLogin(form); if (formType === 'deactivate') submitDeactivate(form); }); @@ -246,7 +216,6 @@ return { buildPasswordChangeBody: buildPasswordChangeBody, buildPhoneChangeBody: buildPhoneChangeBody, - buildSmsLoginBody: buildSmsLoginBody, buildDeactivateBody: buildDeactivateBody, isDangerConfirmed: isDangerConfirmed, init: init diff --git a/public/js/upload-pages.js b/public/js/upload-pages.js index 85f689b..3055924 100644 --- a/public/js/upload-pages.js +++ b/public/js/upload-pages.js @@ -15,6 +15,7 @@ 'use strict'; var documentRef = root.document; + var DEFAULT_CHUNK_SIZE = 4 * 1024 * 1024; function getApi() { return root.GenealogyApi && root.GenealogyApi.defaultClient; @@ -78,6 +79,108 @@ return (fileName || '文件') + ' 上传完成,OSS ID:' + ossId; } + function getUploadMode(fileSize, chunkSize) { + var size = Number(fileSize) || 0; + var limit = Number(chunkSize) || DEFAULT_CHUNK_SIZE; + + return size > limit ? 'resumable' : 'single'; + } + + function buildResumableInitBody(file, fileMd5, chunkSize, options) { + var source = file || {}; + var settings = options || {}; + var size = Number(source.size) || 0; + var sizePerChunk = Number(chunkSize) || DEFAULT_CHUNK_SIZE; + var body = { + fileName: String(source.name || ''), + fileSize: size, + fileMd5: String(fileMd5 || ''), + contentType: String(source.type || 'application/octet-stream'), + chunkSize: sizePerChunk, + totalChunks: Math.ceil(size / sizePerChunk) + }; + + if (settings.bizType) body.bizType = settings.bizType; + if (settings.usageScene) body.usageScene = settings.usageScene; + return body; + } + + function buildResumableCompleteBody(uploadId, fileMd5, fileSize) { + return { + uploadId: String(uploadId || ''), + fileMd5: String(fileMd5 || ''), + fileSize: Number(fileSize) || 0 + }; + } + + function toBinaryString(buffer) { + var bytes = new Uint8Array(buffer); + var chunkSize = 0x8000; + var chunks = []; + var index; + + for (index = 0; index < bytes.length; index += chunkSize) { + chunks.push(String.fromCharCode.apply(null, bytes.subarray(index, index + chunkSize))); + } + + return chunks.join(''); + } + + async function hashBlob(blob) { + if (!root.hex_md5 || !blob || !blob.arrayBuffer) { + throw new Error('缺少文件 MD5 工具'); + } + + return root.hex_md5(toBinaryString(await blob.arrayBuffer())); + } + + async function uploadResumable(api, file, options) { + var settings = options || {}; + var chunkSize = Number(settings.chunkSize) || DEFAULT_CHUNK_SIZE; + var hash = settings.hashBlob || hashBlob; + var fileMd5; + var init; + var uploadId; + var totalChunks; + var index; + var start; + var end; + var chunk; + + if (!api || !file || !file.slice) throw new Error('请选择可分片上传的文件'); + + fileMd5 = await hash(file); + init = await api.initResumableUpload(buildResumableInitBody(file, fileMd5, chunkSize, settings)); + uploadId = pick(init, ['uploadId', 'id'], ''); + if (!uploadId) throw new Error('分片上传初始化缺少 uploadId'); + + totalChunks = Math.ceil(file.size / chunkSize); + for (index = 0; index < totalChunks; index += 1) { + start = index * chunkSize; + end = Math.min(start + chunkSize, file.size); + chunk = file.slice(start, end); + await api.uploadChunk({ + uploadId: uploadId, + chunkIndex: index, + chunkMd5: await hash(chunk), + file: chunk + }); + if (settings.onProgress) settings.onProgress(index + 1, totalChunks); + } + + return api.completeResumableUpload(buildResumableCompleteBody(uploadId, fileMd5, file.size)); + } + + async function uploadFileForPage(api, file, options) { + var settings = options || {}; + var mode = settings.mode === 'single' || settings.mode === 'resumable' + ? settings.mode + : getUploadMode(file && file.size, settings.chunkSize); + + if (mode === 'single') return api.uploadFile(file); + return uploadResumable(api, file, settings); + } + async function uploadFromInput(input) { var api = getApi(); var file = input.files && input.files[0]; @@ -86,6 +189,8 @@ var target = targetSelector && query(targetSelector); var status = statusSelector && query(statusSelector); var multiple = input.getAttribute('data-upload-multiple') === 'true'; + var chunkSize = Number(input.getAttribute('data-upload-chunk-size')) || DEFAULT_CHUNK_SIZE; + var mode = input.getAttribute('data-upload-mode') || ''; var result; if (!api || !file || !target) return; @@ -94,7 +199,15 @@ input.disabled = true; try { - result = normalizeUploadResult(await api.uploadFile(file)); + result = normalizeUploadResult(await uploadFileForPage(api, file, { + mode: mode || getUploadMode(file.size, chunkSize), + chunkSize: chunkSize, + bizType: input.getAttribute('data-upload-biz-type') || undefined, + usageScene: input.getAttribute('data-upload-usage-scene') || undefined, + onProgress: function (current, total) { + if (status) status.textContent = '分片上传 ' + current + '/' + total; + } + })); if (!result.ossId) throw new Error('上传结果缺少 OSS ID'); target.value = mergeOssIds(target.value, result.ossId, multiple); if (status) status.textContent = buildUploadStatus(result.fileName || file.name, result.ossId); @@ -127,6 +240,11 @@ normalizeUploadResult: normalizeUploadResult, mergeOssIds: mergeOssIds, buildUploadStatus: buildUploadStatus, + getUploadMode: getUploadMode, + buildResumableInitBody: buildResumableInitBody, + buildResumableCompleteBody: buildResumableCompleteBody, + uploadResumable: uploadResumable, + uploadFileForPage: uploadFileForPage, init: init }; }); diff --git a/public/js/vip-pages.js b/public/js/vip-pages.js index 85185fc..c81bed5 100644 --- a/public/js/vip-pages.js +++ b/public/js/vip-pages.js @@ -109,7 +109,6 @@ } function buildVipOrderBody(values) { - // VipOrderBody 来自 APP.openapi.json,packageId 必填,genealogyId 和 payType 可选。 var source = values || {}; return { diff --git a/tests/pc-api-contract.test.js b/tests/pc-api-contract.test.js new file mode 100644 index 0000000..4869895 --- /dev/null +++ b/tests/pc-api-contract.test.js @@ -0,0 +1,76 @@ +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); + +const root = path.join(__dirname, '..'); +const appContractPath = path.join(root, 'APP.openapi.json'); +const obsoleteRecordPaths = [ + 'docs/api-page-integration-2026-07-09.md', + 'docs/api-page-integration-tracker-2026-07-09.md' +]; +const forbiddenPatterns = [ + /\/genealogy\/app/, + /\bAPP_(?:LOGIN|REGISTER|PHONE_CHANGE|FORGOT_PASSWORD|SMS_CODE|ACCOUNT_DEACTIVATE)\b/, + /APP\.openapi\.json/ +]; +const checkedFiles = [ + 'utils/ApiClient.js', + 'public/js/auth-pages.js', + 'public/js/captcha-pages.js', + 'login.html', + 'register.html', + 'forgot-password.html', + 'app.html', + 'download.html', + 'notice-detail.html', + 'profile-album.html', + 'profile-data.html', + 'profile-gift.html', + 'profile-security.html', + 'profile-services.html', + 'profile-tree.html', + 'genealogy-pc-openapi.yaml', + 'docs/pc-api-page-integration-tracker-2026-07-09.md', + 'docs/superpowers/plans/2026-07-09-pc-api-replan.md', + 'docs/superpowers/plans/2026-07-09-pc-auth-three-pages.md', + 'docs/superpowers/plans/2026-07-09-tac-captcha-auth.md', + 'docs/superpowers/plans/2026-07-10-pc-tracker-reverification.md', + 'public/js/album-pages.js', + 'public/js/article-pages.js', + 'public/js/ceremony-pages.js', + 'public/js/feed-pages.js', + 'public/js/genealogy-pages.js', + 'public/js/growth-pages.js', + 'public/js/lineage-pages.js', + 'public/js/member-admin-pages.js', + 'public/js/memo-pages.js', + 'public/js/vip-pages.js' +]; + +function read(relativePath) { + return fs.readFileSync(path.join(root, relativePath), 'utf8'); +} + +function run() { + const apiClient = read('utils/ApiClient.js'); + const authPages = read('public/js/auth-pages.js'); + + assert.strictEqual(fs.existsSync(appContractPath), false); + obsoleteRecordPaths.forEach((relativePath) => { + assert.strictEqual(fs.existsSync(path.join(root, relativePath)), false, `${relativePath} must be removed`); + }); + assert.match(apiClient, /\/genealogy\/pc\/auth\/login\/sms/); + assert.match(authPages, /captchaScene: 'WEB_H5_LOGIN'/); + + checkedFiles.forEach((relativePath) => { + const content = read(relativePath); + + forbiddenPatterns.forEach((pattern) => { + assert.doesNotMatch(content, pattern, `${relativePath} must not retain APP API contracts`); + }); + }); + + console.log('pc-api-contract tests passed'); +} + +run(); diff --git a/tests/pc-endpoint-coverage.test.js b/tests/pc-endpoint-coverage.test.js new file mode 100644 index 0000000..b02b5f2 --- /dev/null +++ b/tests/pc-endpoint-coverage.test.js @@ -0,0 +1,82 @@ +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); + +const root = path.join(__dirname, '..'); +const openApi = fs.readFileSync(path.join(root, 'genealogy-pc-openapi.yaml'), 'utf8'); +const apiClient = fs.readFileSync(path.join(root, 'utils', 'ApiClient.js'), 'utf8'); +const authPages = fs.readFileSync(path.join(root, 'public', 'js', 'auth-pages.js'), 'utf8'); +const captchaPages = fs.readFileSync(path.join(root, 'public', 'js', 'captcha-pages.js'), 'utf8'); +const profilePages = fs.readFileSync(path.join(root, 'public', 'js', 'profile-pages.js'), 'utf8'); +const securityPages = fs.readFileSync(path.join(root, 'public', 'js', 'security-pages.js'), 'utf8'); +const regionPages = fs.readFileSync(path.join(root, 'public', 'js', 'region-pages.js'), 'utf8'); +const uploadPages = fs.readFileSync(path.join(root, 'public', 'js', 'upload-pages.js'), 'utf8'); + +const ENDPOINTS = { + 'GET /captcha/require': { source: captchaPages, needle: 'api.captchaRequire', status: 'complete' }, + 'POST /captcha/challenge': { source: captchaPages, needle: "api.buildApiUrl('/captcha/challenge')", status: 'complete' }, + 'POST /captcha/verify': { source: captchaPages, needle: "api.buildApiUrl('/captcha/verify')", status: 'complete' }, + 'GET /auth/code': { status: 'blocked', reason: 'legacy captcha has no PC request field' }, + 'POST /genealogy/pc/auth/register': { source: authPages, needle: 'api.register', status: 'complete' }, + 'POST /genealogy/pc/auth/login': { source: authPages, needle: 'api.login', status: 'complete' }, + 'POST /genealogy/pc/auth/login/sms': { source: authPages, needle: 'api.loginBySms', status: 'complete' }, + 'POST /genealogy/pc/auth/sms/code': { source: authPages, needle: 'api.sendSmsCode', status: 'complete' }, + 'GET /genealogy/pc/auth/profile': { source: profilePages, needle: 'api.currentProfile', status: 'complete' }, + 'PUT /genealogy/pc/auth/profile': { source: profilePages, needle: 'api.updateProfile', status: 'complete' }, + 'PUT /genealogy/pc/auth/password': { source: securityPages, needle: 'api.changePassword', status: 'complete' }, + 'PUT /genealogy/pc/auth/password/reset': { source: authPages, needle: 'api.resetPassword', status: 'complete' }, + 'PUT /genealogy/pc/auth/phone': { status: 'blocked', reason: 'PC/H5 phone SMS scene is not documented' }, + 'POST /genealogy/pc/auth/account/deactivate': { source: securityPages, needle: 'api.deactivateAccount', status: 'complete' }, + 'DELETE /genealogy/pc/auth/logout': { source: securityPages, needle: 'api.logout', status: 'complete' }, + 'POST /genealogy/pc/files/upload': { source: uploadPages, needle: 'api.uploadFile', status: 'complete' }, + 'POST /genealogy/pc/files/resumable/init': { source: uploadPages, needle: 'api.initResumableUpload', status: 'complete' }, + 'POST /genealogy/pc/files/resumable/chunk': { source: uploadPages, needle: 'api.uploadChunk', status: 'complete' }, + 'POST /genealogy/pc/files/resumable/complete': { source: uploadPages, needle: 'api.completeResumableUpload', status: 'complete' }, + 'POST /genealogy/pc/files/reference': { status: 'blocked', reason: 'PC business table and ID contract is not documented' }, + 'DELETE /genealogy/pc/files/reference': { status: 'blocked', reason: 'PC business table and ID contract is not documented' }, + 'GET /genealogy/region/children': { source: regionPages, needle: 'api.regionChildren', status: 'complete' }, + 'GET /genealogy/region/path/{regionCode}': { source: regionPages, needle: 'api.regionPath', apiNeedle: '/genealogy/region/path/', status: 'complete' }, + 'GET /genealogy/region/search': { source: regionPages, needle: 'api.regionSearch', status: 'complete' }, + 'GET /genealogy/region/{regionCode}': { source: regionPages, needle: 'api.regionDetail', apiNeedle: '/genealogy/region/', status: 'complete' } +}; + +function getDocumentOperations(documentText) { + let currentPath = ''; + const operations = []; + + documentText.split(/\r?\n/).forEach((line) => { + const pathMatch = line.match(/^ (\/[^:]+):$/); + const methodMatch = line.match(/^ (get|post|put|delete):$/); + + if (pathMatch) currentPath = pathMatch[1]; + if (methodMatch && currentPath) operations.push(`${methodMatch[1].toUpperCase()} ${currentPath}`); + }); + + return operations; +} + +function run() { + const operations = getDocumentOperations(openApi); + + assert.strictEqual(operations.length, 25); + assert.deepStrictEqual(Object.keys(ENDPOINTS).sort(), operations.slice().sort()); + + operations.forEach((operation) => { + const descriptor = ENDPOINTS[operation]; + const route = operation.slice(operation.indexOf(' ') + 1); + + assert.match(apiClient, new RegExp((descriptor.apiNeedle || route).replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))); + assert.ok(descriptor, `${operation} must have an owner`); + + if (descriptor.status === 'blocked') { + assert.ok(descriptor.reason, `${operation} must name its backend block`); + return; + } + + assert.ok(descriptor.source.includes(descriptor.needle), `${operation} must be used by its page module`); + }); + + console.log('pc-endpoint-coverage tests passed'); +} + +run(); diff --git a/tests/profile-pages.test.js b/tests/profile-pages.test.js index 3b5c09e..316db8e 100644 --- a/tests/profile-pages.test.js +++ b/tests/profile-pages.test.js @@ -1,4 +1,6 @@ const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); const ProfilePages = require('../public/js/profile-pages.js'); function run() { @@ -77,6 +79,16 @@ function run() { getToken: () => 'token-x' }, { status: 500 }), false); + const profileData = fs.readFileSync(path.join(__dirname, '..', 'profile-data.html'), 'utf8'); + assert.match(profileData, /data-upload-target="#profileAvatarOssId"/); + assert.match(profileData, /data-upload-mode="auto"/); + assert.match(profileData, /data-upload-biz-type="avatar"/); + assert.match(profileData, /