38 lines
1.5 KiB
JavaScript
38 lines
1.5 KiB
JavaScript
/**
|
||||
|
|
* 申诉服务(REST §80 章 POST /appeals)
|
|||
|
|
*
|
|||
|
|
* 封装:提交申诉 / 我的申诉列表。
|
|||
|
|
* 关键不变量(AGENTS.md):
|
|||
|
|
* - 第 8 条:敏感数据默认拒绝——本层不接受身份证号、手机号等敏感字段,
|
|||
|
|
* 申诉内容只接收 reason + 证据图片 URL(已上传至 OSS)。
|
|||
|
|
* - 第 4 条:Block 优先级最高——申诉不会自动恢复账号或解除拉黑,
|
|||
|
|
* 是否解封由运营人工处置。
|
|||
|
|
*/
|
|||
|
|
const api = require('../utils/api');
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 提交申诉(REST §81 章)
|
|||
|
|
* @param {{ appealType: 'ban_appeal'|'suspend_appeal', relatedActionId?: string, reason: string, evidenceFileIds?: string[], contactMethod?: string }} payload
|
|||
|
|
* @returns {Promise<{ appealId: string, status: 'pending', submittedAt: number }>}
|
|||
|
|
*/
|
|||
|
|
function submitAppeal(payload) {
|
|||
|
|
// 幂等键:申诉类型 + 关联处置 ID + 当前秒,防止用户多次点击重复提交
|
|||
|
|
const actionKey = payload.relatedActionId || 'no_action';
|
|||
|
|
const idempotencyKey = `appeal:${payload.appealType}:${actionKey}:${Math.floor(Date.now() / 1000)}`;
|
|||
|
|
return api.post('/appeals', payload, undefined, idempotencyKey);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 我的申诉列表
|
|||
|
|
* @param {{ cursor?: string, pageSize?: number, status?: string }} params
|
|||
|
|
* @returns {Promise<{ items: Array<import('../types').Appeal>, nextCursor: string|null }>}
|
|||
|
|
*/
|
|||
|
|
function getMyAppeals(params = {}) {
|
|||
|
|
return api.get('/me/appeals', params);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = {
|
|||
|
|
submitAppeal,
|
|||
|
|
getMyAppeals,
|
|||
|
|
};
|