fix(miniapp): 幂等键改为按操作稳定;删除指向 404 的互选死代码

1) 幂等键(配合后端机制)

原写法把 Date.now() 拼进幂等键,每次调用都生成新键,即使后端实现了幂等
也永远不会命中 —— 声明端与实现端各自都坏。

api.idempotencyKey(scope, subject):键缓存在 _pendingIdempotency(TTL 10min),
同一逻辑操作在成功之前复用同一把键,收到 200+success 才释放;失败(含网络错误)
不释放,下次重试沿用同一把键。25 处调用点(8 个 service + 2 个 TS 页面)全部替换,
Date.now 幂等键写法残留经 grep 为 0。

2) 删除死代码 submitInterests

它请求 POST /activities/{id}/interests —— 后端从未实现该端点
(Phase 16 已把表达意向合并进 /activities/{id}/feedback 的
interestTargetUserIds)。全仓确认无任何页面/组件调用方。
两个文件各留注释说明删除原因与恢复条件:若产品确认需要独立的
「提交互选」端点,应先定义语义并补后端实现,再恢复前端方法。

store 头部关于 AGENTS 第 6 条(单向意向保密)的注释同步改为引用
submitFeedback 返回的 newMutuals。
This commit is contained in:
WorkBuddy
2026-09-18 16:37:33 +08:00
parent 69cf6a2cc7
commit 8dee67040c
12 changed files with 116 additions and 49 deletions
+8 -8
View File
@@ -22,7 +22,7 @@ function getProfile() {
*/
function updateProfile(payload) {
// PUT 默认幂等:用 userId + 字段指纹作为幂等键,避免重复提交时脏写
const idempotencyKey = 'profile-put:' + (payload && payload.userId || 'me') + ':' + Date.now();
const idempotencyKey = api.idempotencyKey('profile-put', (payload && payload.userId) || 'me');
return api.put('/me/profile', payload, undefined, idempotencyKey);
}
@@ -40,7 +40,7 @@ function getPreferences() {
* @returns {Promise<import('../types').PartnerPreference>}
*/
function updatePreferences(payload) {
const idempotencyKey = 'preferences-put:' + Date.now();
const idempotencyKey = api.idempotencyKey('preferences-put');
return api.put('/me/preferences', payload, undefined, idempotencyKey);
}
@@ -67,7 +67,7 @@ function deletePhoto(photoId) {
* @returns {Promise<{ avatarUrl: string }>}
*/
function setMainPhoto(photoId) {
const idempotencyKey = 'photo-main:' + photoId + ':' + Date.now();
const idempotencyKey = api.idempotencyKey('photo-main', photoId);
return api.put(`/me/photos/${photoId}/main`, {}, undefined, idempotencyKey);
}
@@ -94,7 +94,7 @@ function getPrivacySettings() {
* @returns {Promise<import('../types').PrivacySettings>}
*/
function updatePrivacySettings(payload) {
const idempotencyKey = 'privacy-put:' + Date.now();
const idempotencyKey = api.idempotencyKey('privacy-put');
return api.put('/me/privacy-settings', payload, undefined, idempotencyKey);
}
@@ -129,7 +129,7 @@ function getReviewStatus() {
* @returns {Promise<{ reviewStatus: 'pending', submittedAt: number }>}
*/
function submitReview() {
const idempotencyKey = 'review-submit:' + Date.now();
const idempotencyKey = api.idempotencyKey('review-submit');
return api.post('/me/profile/submit-review', {}, undefined, idempotencyKey);
}
@@ -147,7 +147,7 @@ function getRelationshipStatus() {
* @returns {Promise<{ status: 'paused', recommendationEnabled: boolean }>}
*/
function pauseSearching() {
const idempotencyKey = 'rel-pause:' + Date.now();
const idempotencyKey = api.idempotencyKey('rel-pause');
return api.patch('/me/relationship-status', { status: 'paused' }, undefined, idempotencyKey);
}
@@ -156,7 +156,7 @@ function pauseSearching() {
* @returns {Promise<{ status: 'searching', recommendationEnabled: boolean }>}
*/
function resumeSearching() {
const idempotencyKey = 'rel-resume:' + Date.now();
const idempotencyKey = api.idempotencyKey('rel-resume');
return api.patch('/me/relationship-status', { status: 'searching' }, undefined, idempotencyKey);
}
@@ -165,7 +165,7 @@ function resumeSearching() {
* @returns {Promise<{ status: 'getting_to_know', recommendationEnabled: boolean }>}
*/
function markGettingToKnow() {
const idempotencyKey = 'rel-gtk:' + Date.now();
const idempotencyKey = api.idempotencyKey('rel-gtk');
return api.patch('/me/relationship-status', { status: 'getting_to_know' }, undefined, idempotencyKey);
}