fix(miniapp): 提现/财务接口不再用 1001 演示身份,修复 403

- getUserProfile/getUserWithdrawals/getUserFinanceRecords 去掉 userId=1001 默认值,改由 normalizeUserId 解析登录身份

- withdraw.vue / withdraw-records.vue / workspace.vue 调用改为 normalizeUserId(),不再硬编码 1001

- normalizeUserId 将 1001 视为演示占位符:登录态下传 0 由 token 识别,未登录才兜底 1001

- request.js 遇 403 身份校验失败时清理错配登录态并提示重新登录(其它 403 权限拒绝不受影响)

- 登录态闸门补齐用例(108 套件/714 用例全绿)
这个提交包含在:
xcbyy
2026-10-21 11:38:26 +08:00
父节点 9217dfcf11
当前提交 87cb6a6374
共有 6 个文件被更改,包括 45 次插入 和 12 次删除

查看文件

@@ -558,13 +558,16 @@ export async function viewPost(id) {
*/
export function normalizeUserId(uid) {
let target = uid;
if (!target && target !== 0) {
// 1001 是历史演示账号默认值,不代表真实登录用户:一律回到本地存储解析
const isPlaceholder = target === undefined || target === null || target === '' || Number(target) === 1001;
if (isPlaceholder) {
try {
target = uni.getStorageSync('userId');
} catch (_) {}
}
const n = Number(target);
const valid = !isNaN(n) && n > 0;
// 1001 仅作为"未登录演示"的兜底,登录态下不作为真实身份
const valid = !isNaN(n) && n > 0 && n !== 1001;
// 已登录(存在会话 token)时身份以服务端 token 为准:若本地 userId 缺失则传 0,
// 避免"旧 token 属主 + 声明的 userId"不一致被服务端判定为以他人身份操作(403)。
try {
@@ -577,7 +580,7 @@ export function normalizeUserId(uid) {
/**
* 获取用户个人资料与钱包资产 (真实读取 MySQL users 表)
*/
export async function getUserProfile(userId = 1001) {
export async function getUserProfile(userId) {
const safeId = normalizeUserId(userId);
try {
const res = await http.get(`/users/${safeId}`);
@@ -653,7 +656,7 @@ export async function withdrawCommission(arg1, arg2, arg3 = {}) {
/**
* 查询用户提现记录与审批状态 (待审核/处理中/已打款/已驳回)
*/
export async function getUserWithdrawals(userId = 1001) {
export async function getUserWithdrawals(userId) {
const safeId = normalizeUserId(userId);
try {
const res = await http.get(`/users/${safeId}/withdrawals`);
@@ -667,7 +670,7 @@ export async function getUserWithdrawals(userId = 1001) {
/**
* 查询用户财务收支流水
*/
export async function getUserFinanceRecords(userId = 1001) {
export async function getUserFinanceRecords(userId) {
const safeId = normalizeUserId(userId);
try {
const res = await http.get(`/users/${safeId}/finance-records`);

查看文件

@@ -75,6 +75,7 @@ export function request(options = {}) {
bizErr.code = res.data.code;
bizErr.statusCode = res.statusCode;
if (res.data.code === 40100) handleAuthExpired();
else if (res.data.code === 40300 && /身份校验失败|无权以他人身份/.test(res.data.message || '')) handleAuthExpired();
reject(bizErr);
}
} else {
@@ -86,6 +87,7 @@ export function request(options = {}) {
httpErr.statusCode = res.statusCode;
httpErr.code = (res.data && res.data.code) || res.statusCode;
if (res.statusCode === 401) handleAuthExpired();
else if (res.statusCode === 403 && /身份校验失败|无权以他人身份/.test(errMsg)) handleAuthExpired();
reject(httpErr);
}
},

查看文件

@@ -490,7 +490,8 @@ import {
updateExpertService,
deleteExpertService,
uploadVoiceIntro,
getUserWithdrawals
getUserWithdrawals,
normalizeUserId
} from '@/common/api.js';
const currentThemeKey = ref(getCurrentThemeKey());
@@ -801,7 +802,7 @@ const goToWithdrawPage = () => {
const openWithdrawRecords = async () => {
try {
const list = await getUserWithdrawals(1001);
const list = await getUserWithdrawals(normalizeUserId());
withdrawRecords.value = list || [];
} catch (_) {}
showWithdrawRecordsModal.value = true;

查看文件

@@ -180,7 +180,7 @@ import { onShow } from '@dcloudio/uni-app';
import { ICONS } from '@/common/icons.js';
import { getCurrentThemeKey, applyThemeToNativeUI } from '@/common/theme.js';
import { getNavBarInfo } from '@/common/nav.js';
import { getUserWithdrawals } from '@/common/api.js';
import { getUserWithdrawals, normalizeUserId } from '@/common/api.js';
const currentThemeKey = ref(getCurrentThemeKey());
const navInfo = ref(getNavBarInfo());
@@ -272,7 +272,7 @@ const handleCopyOrderNo = (orderNo) => {
const loadWithdrawals = async () => {
try {
const list = await getUserWithdrawals(1001);
const list = await getUserWithdrawals(normalizeUserId());
if (Array.isArray(list)) {
allRecords.value = list;
let successSum = 0;

查看文件

@@ -189,7 +189,8 @@ import {
getUserProfile,
withdrawCommission,
getUserWithdrawals,
getPlatformConfigs
getPlatformConfigs,
normalizeUserId
} from '@/common/api.js';
const currentThemeKey = ref(getCurrentThemeKey());
@@ -281,7 +282,7 @@ const handleFillAllCommission = () => {
const loadPageData = async () => {
try {
const profile = await getUserProfile(1001);
const profile = await getUserProfile(normalizeUserId());
if (profile && profile.commission !== undefined) {
userCommission.value = String(profile.commission);
if (profile.nickname) {
@@ -298,7 +299,7 @@ const loadPageData = async () => {
} catch (_) {}
try {
const records = await getUserWithdrawals(1001);
const records = await getUserWithdrawals(normalizeUserId());
if (Array.isArray(records)) {
withdrawalsList.value = records;
let successSum = 0;

查看文件

@@ -26,4 +26,30 @@ describe('第九十批登录态一致性闸门', () => {
expect(api).not.toContain('if (n === 101) return 2006;');
expect(api).toContain('if (token) return valid ? n : 0;');
});
it('1001 演示默认值不作为真实身份(登录态下回退 token 识别)', () => {
expect(api).toContain('Number(target) === 1001');
expect(api).toContain('n !== 1001');
expect(api).not.toContain('getUserWithdrawals(userId = 1001)');
expect(api).not.toContain('getUserFinanceRecords(userId = 1001)');
expect(api).not.toContain('getUserProfile(userId = 1001)');
});
it('提现/财务页面不再硬编码 1001 查询本人数据', () => {
for (const rel of [
'pwuniapp/pages/user/withdraw.vue',
'pwuniapp/pages/user/withdraw-records.vue',
'pwuniapp/pages/expert/workspace.vue',
]) {
const src = fs.readFileSync(path.join(root, rel), 'utf-8');
expect(src).not.toContain('getUserWithdrawals(1001)');
expect(src).not.toContain('getUserProfile(1001)');
}
});
it('请求层遇身份校验失败 403 时清理错配登录态并提示重新登录', () => {
const request = fs.readFileSync(path.join(root, 'pwuniapp/common/request.js'), 'utf-8');
expect(request).toContain('40300 && /身份校验失败|无权以他人身份/');
expect(request).toContain('res.statusCode === 403 && /身份校验失败|无权以他人身份/');
});
});