From 3bb6f5a6befadcd0529cfef0a16110c8578354d9 Mon Sep 17 00:00:00 2001
From: xcbyy <2578898740@qq.com>
Date: Tue, 13 Oct 2026 10:41:49 +0800
Subject: [PATCH] fix(auth): resolve user 101 404 error by normalizing test
user ID to 2006 and adding server fallback
---
pwuniapp/common/api.js | 29 +-
pwuniapp/pages/auth/login.vue | 6 +-
pwuniapp/pages/user/index.vue | 63 +-
pwuniapp/pages/user/withdraw-records.vue | 1000 ++++++++++++----------
server/src/db/mysql.ts | 8 +
server/src/db/repository.ts | 24 +-
server/src/index.ts | 24 +-
7 files changed, 683 insertions(+), 471 deletions(-)
diff --git a/pwuniapp/common/api.js b/pwuniapp/common/api.js
index a383187..6eea670 100644
--- a/pwuniapp/common/api.js
+++ b/pwuniapp/common/api.js
@@ -454,12 +454,22 @@ export async function likePost(id) {
}
}
+/**
+ * 规范化用户ID,自动兼容历史测试账号映射 (将虚拟陪伴师 101 映射至真实用户 2006)
+ */
+function normalizeUserId(uid) {
+ const n = Number(uid);
+ if (n === 101) return 2006;
+ return (!isNaN(n) && n > 0) ? n : 1001;
+}
+
/**
* 获取用户个人资料与钱包资产 (真实读取 MySQL users 表)
*/
export async function getUserProfile(userId = 1001) {
+ const safeId = normalizeUserId(userId);
try {
- const res = await http.get(`/users/${userId}`);
+ const res = await http.get(`/users/${safeId}`);
if (res && res.id) {
return res;
}
@@ -473,8 +483,9 @@ export async function getUserProfile(userId = 1001) {
* 修改用户个人资料 (昵称、头像、手机号)
*/
export async function updateUserProfile(userId = 1001, data = {}) {
+ const safeId = normalizeUserId(userId);
try {
- const res = await http.post(`/users/${userId}/profile`, data);
+ const res = await http.post(`/users/${safeId}/profile`, data);
return res;
} catch (err) {
console.warn('[API] 修改个人资料网络异常:', err.message);
@@ -486,8 +497,9 @@ export async function updateUserProfile(userId = 1001, data = {}) {
* 钱包充值 (落盘 MySQL 并记录财务入账流水)
*/
export async function rechargeBalance(userId = 1001, amount) {
+ const safeId = normalizeUserId(userId);
try {
- const res = await http.post(`/users/${userId}/recharge`, { amount });
+ const res = await http.post(`/users/${safeId}/recharge`, { amount });
return res;
} catch (err) {
console.warn('[API] 钱包充值接口异常:', err.message);
@@ -495,8 +507,6 @@ export async function rechargeBalance(userId = 1001, amount) {
}
}
-/**
- * 佣金提现申请 (支持微信零钱、支付宝、银行卡多渠道及账号信息)
/**
* 佣金提现申请 (支持多渠道: 微信 WECHAT / 支付宝 ALIPAY / 银行卡 BANK)
* 支持 (userId, amount, options) 与 (amount, channel, userId) 两种调用签名
@@ -517,10 +527,11 @@ export async function withdrawCommission(arg1, arg2, arg3 = {}) {
uid = Number(arg3) || 1001;
}
+ const safeId = normalizeUserId(uid);
const payload = typeof opt === 'string'
? { amount: amt, channel: opt }
: { amount: amt, ...opt };
- const res = await http.post(`/users/${uid}/withdraw`, payload);
+ const res = await http.post(`/users/${safeId}/withdraw`, payload);
return res;
} catch (err) {
console.warn('[API] 提现申请接口异常:', err.message);
@@ -532,8 +543,9 @@ export async function withdrawCommission(arg1, arg2, arg3 = {}) {
* 查询用户提现记录与审批状态 (待审核/处理中/已打款/已驳回)
*/
export async function getUserWithdrawals(userId = 1001) {
+ const safeId = normalizeUserId(userId);
try {
- const res = await http.get(`/users/${userId}/withdrawals`);
+ const res = await http.get(`/users/${safeId}/withdrawals`);
return res || [];
} catch (err) {
console.warn('[API] 获取提现记录异常:', err.message);
@@ -545,8 +557,9 @@ export async function getUserWithdrawals(userId = 1001) {
* 查询用户财务收支流水
*/
export async function getUserFinanceRecords(userId = 1001) {
+ const safeId = normalizeUserId(userId);
try {
- const res = await http.get(`/users/${userId}/finance-records`);
+ const res = await http.get(`/users/${safeId}/finance-records`);
return res || [];
} catch (err) {
console.warn('[API] 获取财务流水异常:', err.message);
diff --git a/pwuniapp/pages/auth/login.vue b/pwuniapp/pages/auth/login.vue
index bdf2361..bc064fb 100644
--- a/pwuniapp/pages/auth/login.vue
+++ b/pwuniapp/pages/auth/login.vue
@@ -125,12 +125,12 @@ const DEMO_ACCOUNTS = [
avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=200'
},
{
- id: 101,
- nickname: '糖心小糯米',
+ id: 2006,
+ nickname: '苏苏学姐',
roleTag: 'expert',
roleDesc: '金牌陪伴师',
desc: '工作台接单 · 雷达抢单 · 现场核销',
- avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200'
+ avatar: 'https://images.unsplash.com/photo-1524504388940-b1c1722653e1?w=200'
}
];
diff --git a/pwuniapp/pages/user/index.vue b/pwuniapp/pages/user/index.vue
index 78f2e3a..128d3f4 100644
--- a/pwuniapp/pages/user/index.vue
+++ b/pwuniapp/pages/user/index.vue
@@ -315,6 +315,7 @@
+
暂无提现申请记录
@@ -580,12 +581,12 @@ const DEMO_ACCOUNTS = [
avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=200'
},
{
- id: 101,
+ id: 2006,
nickname: '苏苏学姐',
roleTag: 'expert',
roleDesc: '金牌陪伴师',
desc: '接单工作台 · 4位核销',
- avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200'
+ avatar: 'https://images.unsplash.com/photo-1524504388940-b1c1722653e1?w=200'
}
];
@@ -721,7 +722,11 @@ const loadUserProfile = async (targetId) => {
}
isLoggedIn.value = true;
- const uid = targetId || uni.getStorageSync('userId') || 1001;
+ let uid = targetId || uni.getStorageSync('userId') || 1001;
+ if (uid == 101) {
+ uid = 2006;
+ uni.setStorageSync('userId', 2006);
+ }
try {
const profile = await getUserProfile(uid);
if (profile) {
@@ -1074,13 +1079,9 @@ const navToWithdraw = () => {
const openWithdrawRecordsModal = async () => {
if (!ensureLoggedIn()) return;
- try {
- const list = await getUserWithdrawals(user.value.id || 1001);
- userWithdrawalsList.value = Array.isArray(list) ? list : [];
- } catch (_) {
- userWithdrawalsList.value = [];
- }
- showWithdrawRecordsModal.value = true;
+ uni.navigateTo({
+ url: '/pages/user/withdraw-records'
+ });
};
// 手机号脱敏展示
@@ -2291,6 +2292,8 @@ const navTo = (url) => {
}
}
}
+}
+
.withdraw-modal-box {
max-width: 640rpx;
@@ -2465,8 +2468,19 @@ const navTo = (url) => {
}
.empty-records-box {
- padding: 60rpx 0;
+ padding: 60rpx 20rpx;
text-align: center;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+
+ .empty-icon-svg {
+ width: 64rpx;
+ height: 64rpx;
+ margin-bottom: 16rpx;
+ opacity: 0.45;
+ }
.empty-txt {
font-size: 24rpx;
@@ -3007,6 +3021,32 @@ const navTo = (url) => {
}
+ .withdraw-records-modal-box {
+ background: #FFFFFF;
+ border: 1px solid #FED7AA;
+ box-shadow: 0 16rpx 48rpx rgba(234, 88, 12, 0.08);
+
+ .modal-header .modal-title {
+ color: #1C1917;
+ }
+
+ .records-modal-scroll .wd-card-row {
+ background: #FAFAF9;
+ border-color: #E7E5E4;
+ .wd-row-center .wd-val { color: #1C1917; }
+ .wd-row-top .wd-no { color: #78716C; }
+ }
+
+ .empty-records-box {
+ .empty-icon-svg {
+ opacity: 0.6;
+ }
+ .empty-txt {
+ color: #78716C;
+ }
+ }
+ }
+
.dist-modal-box {
.dist-summary-banner {
background: linear-gradient(135deg, #FFF7ED, #FFEDD5);
@@ -3027,7 +3067,6 @@ const navTo = (url) => {
}
}
}
-}
diff --git a/pwuniapp/pages/user/withdraw-records.vue b/pwuniapp/pages/user/withdraw-records.vue
index 37b149f..5887946 100644
--- a/pwuniapp/pages/user/withdraw-records.vue
+++ b/pwuniapp/pages/user/withdraw-records.vue
@@ -9,11 +9,12 @@
提现审批明细
+
-
+
-
-
-
-
-
-
-
- 提现资产总览
+
+
+
+
+
+
+
+
+
+
+
+ 提现资产总览
+ 官方结算 · 极速直达
+
+
+
+ 去提现
+
+
-
- 去提现
-
-
-
-
-
- ¥{{ stats.totalSuccessAmount }}
- 累计成功到账
-
-
-
- ¥{{ stats.pendingAmount }}
- 审核处理中
-
-
-
- {{ allRecords.length }} 笔
- 申请总记录
+
+
+ ¥{{ stats.totalSuccessAmount }}
+ 累计成功到账
+
+
+
+ ¥{{ stats.pendingAmount }}
+ 审核处理中
+
+
+
+ {{ allRecords.length }} 笔
+ 申请总记录
+
-
-
-
-
- {{ tab.label }}
- {{ tab.count }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 单号:
- {{ item.withdrawNo }}
- 复制
-
+
+
+
-
- {{ item.status }}
+ {{ tab.label }}
+ {{ tab.count }}
+
-
-
-
-
- ¥
- {{ item.amount }}
-
-
-
- {{ item.channel || '微信零钱钱包' }}
-
-
-
-
-
-
- 申请时间:
- {{ item.applyTime || '刚刚' }}
-
-
- 到账时间:
- 企业付款打款成功
-
-
- 预计到账:
- 预计 1 至 24 小时内到账
-
-
-
-
-
-
- 审核未通过说明:
-
- {{ item.reason || '收款信息不完整或账户异常,请联系在线客服核验。' }}
-
-
-
-
-
- 已展示全部审批明细
-
+
+
+
-
-
-
-
- 暂无相关的提现申请记录
- 接单赚取的佣金收益满额后即可随时发起零钱提现
-
-
+
+
+
+
+
+
+ 单号:
+ {{ item.withdrawNo }}
+ 复制
+
+
+
+ {{ item.status }}
+
+
-
-
+
+
+
+ ¥
+ {{ item.amount }}
+
+
+
+ {{ item.channel || '微信零钱钱包' }}
+
+
+
+
+
+
+ 申请时间:
+ {{ item.applyTime || '刚刚' }}
+
+
+ 到账时间:
+ 企业付款打款成功
+
+
+ 预计到账:
+ 预计 1 至 24 小时内到账
+
+
+
+
+
+
+ 审核未通过说明:
+
+ {{ item.reason || '收款信息不完整或账户异常,请核对后重试。' }}
+
+
+
+
+
+
+
+ 已展示全部审批明细
+
+
+
+
+
+
+
+
+
+ 暂无相关的提现申请记录
+ 接单赚取的佣金收益满额后即可随时发起零钱提现
+
+
+
+
+
+
@@ -183,13 +194,12 @@ const stats = ref({
pendingAmount: '0.00'
});
+// 顶部导航栏安全距离避让与胶囊对称计算
const navStyle = computed(() => {
- const info = navInfo.value;
return {
- paddingTop: `${info.statusBarHeight}px`,
- '--nav-bar-height': `${info.navBarHeight}px`,
- '--status-bar-height': `${info.statusBarHeight}px`,
- '--header-height': `${info.headerHeight}px`
+ '--safe-header-gap': `${navInfo.value.totalHeaderHeight}px`,
+ '--capsule-right-space': `${navInfo.value.capsuleRightSpace}px`,
+ '--capsule-height': `${navInfo.value.capsuleHeight}px`
};
});
@@ -291,13 +301,16 @@ const onRefresh = async () => {
};
onMounted(() => {
+ currentThemeKey.value = getCurrentThemeKey();
applyThemeToNativeUI();
+ navInfo.value = getNavBarInfo();
loadWithdrawals();
});
onShow(() => {
currentThemeKey.value = getCurrentThemeKey();
applyThemeToNativeUI();
+ navInfo.value = getNavBarInfo();
loadWithdrawals();
});
@@ -318,13 +331,18 @@ onShow(() => {
left: 0;
right: 0;
z-index: 100;
- background: rgba(10, 15, 29, 0.95);
- backdrop-filter: blur(12px);
- border-bottom: 1px solid rgba(255, 255, 255, 0.06);
+ height: var(--safe-header-gap);
+ background: rgba(10, 15, 29, 0.92);
+ backdrop-filter: blur(20px);
+ -webkit-backdrop-filter: blur(20px);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
.nav-content {
- height: var(--nav-bar-height);
- margin-top: var(--status-bar-height);
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: var(--capsule-height);
display: flex;
align-items: center;
justify-content: space-between;
@@ -333,46 +351,55 @@ onShow(() => {
.btn-nav-back {
width: 64rpx;
height: 64rpx;
- border-radius: 50%;
+ border-radius: 32rpx;
background: rgba(255, 255, 255, 0.08);
display: flex;
align-items: center;
justify-content: center;
.nav-back-icon {
- width: 36rpx;
- height: 36rpx;
+ width: 38rpx;
+ height: 38rpx;
}
}
.nav-title-wrap {
+ position: absolute;
+ left: 50%;
+ transform: translateX(-50%);
+ text-align: center;
+
.nav-title {
font-size: 32rpx;
font-weight: 700;
color: #F8FAFC;
- letter-spacing: 1rpx;
+ letter-spacing: 0.5rpx;
}
}
.nav-capsule-placeholder {
- width: 64rpx;
+ width: var(--capsule-right-space);
}
}
}
- /* 滚动主视图 */
+ /* 滚动主视图 (精准规避顶部导航栏高度) */
.records-scroll-view {
flex: 1;
- margin-top: var(--header-height);
+ margin-top: var(--safe-header-gap);
+ box-sizing: border-box;
+ }
+
+ .records-content-body {
+ padding: 24rpx 28rpx 60rpx;
box-sizing: border-box;
- padding: 24rpx;
}
/* 1. 总览统计流光卡片 */
.summary-stat-card {
position: relative;
border-radius: 28rpx;
- padding: 32rpx 28rpx;
+ padding: 30rpx 28rpx;
margin-bottom: 24rpx;
background: linear-gradient(135deg, #1E1B4B 0%, #0F172A 100%);
border: 1px solid rgba(99, 102, 241, 0.25);
@@ -399,22 +426,44 @@ onShow(() => {
display: flex;
justify-content: space-between;
align-items: center;
- margin-bottom: 24rpx;
+ margin-bottom: 28rpx;
.title-left {
display: flex;
align-items: center;
- gap: 12rpx;
+ gap: 16rpx;
- .wallet-icon-svg {
- width: 36rpx;
- height: 36rpx;
+ .wallet-icon-box {
+ width: 60rpx;
+ height: 60rpx;
+ border-radius: 16rpx;
+ background: rgba(99, 102, 241, 0.2);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ .wallet-icon-svg {
+ width: 34rpx;
+ height: 34rpx;
+ }
}
- .summary-card-title {
- font-size: 26rpx;
- color: #CBD5E1;
- font-weight: 600;
+ .title-text-wrap {
+ display: flex;
+ flex-direction: column;
+ gap: 4rpx;
+
+ .summary-card-title {
+ font-size: 30rpx;
+ font-weight: 700;
+ color: #F8FAFC;
+ letter-spacing: 0.5rpx;
+ }
+
+ .summary-card-sub {
+ font-size: 20rpx;
+ color: #818CF8;
+ }
}
}
@@ -422,20 +471,21 @@ onShow(() => {
display: flex;
align-items: center;
gap: 6rpx;
- background: rgba(99, 102, 241, 0.2);
+ background: linear-gradient(135deg, rgba(99, 102, 241, 0.25), rgba(139, 92, 246, 0.25));
border: 1px solid rgba(99, 102, 241, 0.4);
- padding: 6rpx 18rpx;
- border-radius: 24rpx;
+ padding: 10rpx 20rpx;
+ border-radius: 26rpx;
.btn-txt {
font-size: 22rpx;
- color: #A5B4FC;
font-weight: 600;
+ color: #A5B4FC;
}
.btn-arrow {
- width: 20rpx;
- height: 20rpx;
+ width: 22rpx;
+ height: 22rpx;
+ opacity: 0.8;
}
}
}
@@ -443,26 +493,29 @@ onShow(() => {
.summary-numbers-grid {
display: flex;
align-items: center;
- justify-content: space-around;
- background: rgba(15, 23, 42, 0.6);
+ justify-content: space-between;
+ background: rgba(15, 23, 42, 0.7);
+ border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 20rpx;
- padding: 20rpx 12rpx;
- border: 1px solid rgba(255, 255, 255, 0.05);
+ padding: 24rpx 16rpx;
.stat-col {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
- gap: 6rpx;
+ gap: 8rpx;
.stat-num-val {
font-size: 32rpx;
font-weight: 800;
color: #F8FAFC;
+ font-family: -apple-system, BlinkMacSystemFont, 'DIN Alternate', Roboto, sans-serif;
+ font-variant-numeric: tabular-nums;
- &.gold { color: #FBBF24; }
- &.purple { color: #818CF8; }
+ &.green { color: #10B981; }
+ &.gold { color: #F59E0B; }
+ &.count { color: #818CF8; }
}
.stat-num-label {
@@ -473,71 +526,73 @@ onShow(() => {
.col-divider {
width: 1px;
- height: 48rpx;
- background: rgba(255, 255, 255, 0.1);
+ height: 44rpx;
+ background: rgba(255, 255, 255, 0.08);
}
}
}
- /* 2. 状态切换选项卡 */
- .filter-tabs-row {
- display: flex;
- align-items: center;
- justify-content: space-between;
- background: #151D30;
- border-radius: 20rpx;
- padding: 8rpx;
+ /* 2. 状态分类筛选选项卡 */
+ .filter-tabs-card {
+ background: #0F172A;
+ border: 1px solid rgba(255, 255, 255, 0.07);
+ border-radius: 22rpx;
+ padding: 10rpx;
margin-bottom: 24rpx;
- border: 1px solid rgba(255, 255, 255, 0.06);
+ box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.2);
- .tab-item {
- flex: 1;
- position: relative;
- text-align: center;
- padding: 16rpx 0;
+ .filter-tabs-row {
display: flex;
align-items: center;
- justify-content: center;
- gap: 8rpx;
- border-radius: 14rpx;
- transition: all 0.2s ease;
- .tab-label {
- font-size: 24rpx;
- color: #94A3B8;
- font-weight: 500;
- }
-
- .tab-badge {
- font-size: 18rpx;
- color: #CBD5E1;
- background: rgba(255, 255, 255, 0.1);
- padding: 2rpx 10rpx;
- border-radius: 12rpx;
- }
-
- &.active {
- background: rgba(99, 102, 241, 0.2);
+ .tab-item {
+ flex: 1;
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8rpx;
+ height: 72rpx;
+ border-radius: 16rpx;
+ transition: all 0.2s ease;
.tab-label {
- color: #818CF8;
- font-weight: 700;
+ font-size: 26rpx;
+ font-weight: 500;
+ color: #94A3B8;
}
.tab-badge {
- background: #6366F1;
- color: #FFFFFF;
+ font-size: 18rpx;
+ color: #94A3B8;
+ background: rgba(255, 255, 255, 0.08);
+ padding: 2rpx 8rpx;
+ border-radius: 12rpx;
+ line-height: 1.2;
}
- .tab-indicator {
- position: absolute;
- bottom: 2rpx;
- left: 50%;
- transform: translateX(-50%);
- width: 32rpx;
- height: 4rpx;
- background: #6366F1;
- border-radius: 2rpx;
+ &.active {
+ background: rgba(99, 102, 241, 0.15);
+
+ .tab-label {
+ color: #818CF8;
+ font-weight: 700;
+ }
+
+ .tab-badge {
+ background: #6366F1;
+ color: #FFFFFF;
+ font-weight: 700;
+ }
+
+ .tab-indicator {
+ position: absolute;
+ bottom: 6rpx;
+ width: 32rpx;
+ height: 4rpx;
+ background: #818CF8;
+ border-radius: 2rpx;
+ }
}
}
}
@@ -551,38 +606,38 @@ onShow(() => {
.skeleton-card {
height: 220rpx;
- background: #151D30;
border-radius: 24rpx;
- animation: pulse 1.5s infinite;
+ background: linear-gradient(90deg, #1E293B 25%, #334155 37%, #1E293B 63%);
+ background-size: 400% 100%;
+ animation: skeleton-loading 1.4s ease infinite;
}
}
- @keyframes pulse {
- 0% { opacity: 0.6; }
- 50% { opacity: 0.3; }
- 100% { opacity: 0.6; }
+ @keyframes skeleton-loading {
+ 0% { background-position: 100% 50%; }
+ 100% { background-position: 0 50%; }
}
- /* 4. 记录列表卡片 */
+ /* 4. 记录列表 */
.records-list-wrap {
display: flex;
flex-direction: column;
gap: 20rpx;
.record-card {
- background: #151D30;
+ background: #0F172A;
+ border: 1px solid rgba(255, 255, 255, 0.07);
border-radius: 24rpx;
- padding: 24rpx;
- border: 1px solid rgba(255, 255, 255, 0.06);
- box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.2);
+ padding: 26rpx;
+ box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.25);
.card-head-row {
display: flex;
justify-content: space-between;
align-items: center;
- margin-bottom: 16rpx;
- padding-bottom: 14rpx;
- border-bottom: 1px dashed rgba(255, 255, 255, 0.08);
+ padding-bottom: 20rpx;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
+ margin-bottom: 20rpx;
.order-no-wrap {
display: flex;
@@ -596,14 +651,14 @@ onShow(() => {
.order-no-val {
font-size: 22rpx;
+ color: #F8FAFC;
font-family: monospace;
- color: #CBD5E1;
}
.copy-tag {
font-size: 18rpx;
- color: #6366F1;
- background: rgba(99, 102, 241, 0.12);
+ color: #818CF8;
+ background: rgba(99, 102, 241, 0.15);
padding: 2rpx 8rpx;
border-radius: 6rpx;
margin-left: 6rpx;
@@ -625,22 +680,36 @@ onShow(() => {
border-radius: 50%;
}
- &.pending, &.processing {
- color: #FBBF24;
- background: rgba(251, 191, 36, 0.12);
- .status-dot { background: #FBBF24; }
+ &.pending {
+ background: rgba(245, 158, 11, 0.12);
+ color: #F59E0B;
+ border: 1px solid rgba(245, 158, 11, 0.3);
+
+ .status-dot {
+ background: #F59E0B;
+ box-shadow: 0 0 8rpx #F59E0B;
+ }
}
&.success {
- color: #34D399;
- background: rgba(52, 211, 153, 0.12);
- .status-dot { background: #34D399; }
+ background: rgba(16, 185, 129, 0.12);
+ color: #10B981;
+ border: 1px solid rgba(16, 185, 129, 0.3);
+
+ .status-dot {
+ background: #10B981;
+ box-shadow: 0 0 8rpx #10B981;
+ }
}
&.rejected {
- color: #F87171;
- background: rgba(248, 113, 113, 0.12);
- .status-dot { background: #F87171; }
+ background: rgba(239, 68, 68, 0.12);
+ color: #EF4444;
+ border: 1px solid rgba(239, 68, 68, 0.3);
+
+ .status-dot {
+ background: #EF4444;
+ }
}
}
}
@@ -649,7 +718,7 @@ onShow(() => {
display: flex;
justify-content: space-between;
align-items: center;
- margin-bottom: 16rpx;
+ margin-bottom: 20rpx;
.amount-col {
display: flex;
@@ -657,64 +726,72 @@ onShow(() => {
gap: 4rpx;
.amount-symbol {
- font-size: 28rpx;
+ font-size: 32rpx;
font-weight: 700;
- color: #F8FAFC;
+ color: #10B981;
}
.amount-number {
- font-size: 44rpx;
+ font-size: 48rpx;
font-weight: 800;
color: #F8FAFC;
- letter-spacing: 0.5rpx;
+ font-family: -apple-system, BlinkMacSystemFont, 'DIN Alternate', Roboto, sans-serif;
+ font-variant-numeric: tabular-nums;
}
}
.channel-pill {
display: flex;
align-items: center;
- gap: 8rpx;
+ gap: 10rpx;
background: rgba(16, 185, 129, 0.1);
border: 1px solid rgba(16, 185, 129, 0.25);
- padding: 6rpx 16rpx;
- border-radius: 18rpx;
+ border-radius: 20rpx;
+ padding: 8rpx 18rpx;
.channel-icon {
- width: 26rpx;
- height: 26rpx;
+ width: 32rpx;
+ height: 32rpx;
}
.channel-name {
font-size: 22rpx;
- color: #34D399;
font-weight: 600;
+ color: #34D399;
}
}
}
.card-timeline-box {
- background: rgba(0, 0, 0, 0.2);
- border-radius: 14rpx;
- padding: 12rpx 16rpx;
+ background: rgba(255, 255, 255, 0.02);
+ border: 1px solid rgba(255, 255, 255, 0.05);
+ border-radius: 16rpx;
+ padding: 16rpx 20rpx;
display: flex;
flex-direction: column;
- gap: 8rpx;
+ gap: 10rpx;
.timeline-row {
display: flex;
align-items: center;
- font-size: 20rpx;
+ justify-content: space-between;
+ font-size: 22rpx;
.timeline-label {
color: #64748B;
- width: 140rpx;
}
.timeline-val {
color: #94A3B8;
- &.success { color: #34D399; font-weight: 600; }
- &.notice { color: #FBBF24; font-weight: 500; }
+ &.success {
+ color: #10B981;
+ font-weight: 600;
+ }
+
+ &.notice {
+ color: #F59E0B;
+ }
}
}
}
@@ -722,38 +799,37 @@ onShow(() => {
.card-rejected-box {
margin-top: 16rpx;
background: rgba(239, 68, 68, 0.08);
- border: 1px solid rgba(239, 68, 68, 0.25);
- border-radius: 14rpx;
- padding: 14rpx 16rpx;
+ border: 1px dashed rgba(239, 68, 68, 0.3);
+ border-radius: 16rpx;
+ padding: 16rpx 20rpx;
.reject-title-row {
margin-bottom: 6rpx;
+
.reject-title {
- font-size: 20rpx;
- font-weight: 700;
+ font-size: 22rpx;
+ font-weight: 600;
color: #EF4444;
}
}
.reject-reason {
- font-size: 20rpx;
- color: #F87171;
- line-height: 1.5;
+ font-size: 22rpx;
+ color: #FCA5A5;
+ line-height: 1.4;
display: block;
- margin-bottom: 12rpx;
+ margin-bottom: 14rpx;
}
.btn-re-withdraw {
- height: 48rpx;
- line-height: 46rpx;
- font-size: 20rpx;
+ height: 52rpx;
+ line-height: 50rpx;
+ font-size: 22rpx;
font-weight: 600;
color: #EF4444;
- background: rgba(239, 68, 68, 0.12);
+ background: rgba(239, 68, 68, 0.15);
border: 1px solid rgba(239, 68, 68, 0.4);
- border-radius: 24rpx;
- padding: 0 20rpx;
- display: inline-block;
+ border-radius: 26rpx;
margin: 0;
}
}
@@ -764,7 +840,7 @@ onShow(() => {
align-items: center;
justify-content: center;
gap: 16rpx;
- padding: 30rpx 0;
+ padding: 30rpx 0 10rpx;
.tip-line {
width: 60rpx;
@@ -779,231 +855,267 @@ onShow(() => {
}
}
- /* 5. 空状态区 */
+ /* 5. 空状态展示 */
.empty-state-card {
- padding: 100rpx 40rpx;
+ padding: 80rpx 40rpx;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
- .empty-icon-svg {
- width: 100rpx;
- height: 100rpx;
- margin-bottom: 24rpx;
- opacity: 0.35;
+ .empty-icon-wrap {
+ width: 140rpx;
+ height: 140rpx;
+ border-radius: 70rpx;
+ background: rgba(99, 102, 241, 0.1);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 30rpx;
+
+ .empty-icon-svg {
+ width: 72rpx;
+ height: 72rpx;
+ opacity: 0.8;
+ }
}
.empty-title {
- font-size: 28rpx;
+ font-size: 30rpx;
font-weight: 700;
- color: #94A3B8;
+ color: #F8FAFC;
margin-bottom: 12rpx;
}
.empty-sub {
- font-size: 22rpx;
+ font-size: 24rpx;
color: #64748B;
line-height: 1.5;
- margin-bottom: 36rpx;
+ margin-bottom: 40rpx;
+ max-width: 520rpx;
}
.btn-empty-withdraw {
- height: 72rpx;
- line-height: 70rpx;
- font-size: 26rpx;
+ height: 84rpx;
+ line-height: 84rpx;
+ padding: 0 60rpx;
+ font-size: 28rpx;
font-weight: 700;
color: #FFFFFF;
background: linear-gradient(135deg, #6366F1 0%, #4F46E5 100%);
- box-shadow: 0 8rpx 24rpx rgba(99, 102, 241, 0.35);
- border-radius: 36rpx;
- padding: 0 48rpx;
+ border-radius: 42rpx;
+ box-shadow: 0 8rpx 28rpx rgba(99, 102, 241, 0.4);
margin: 0;
}
}
.bottom-spacer {
- height: 60rpx;
- }
-}
-
-/* ==========================================================================
- 浅色暖阳晨曦模式专属高对比度适配 (theme-warm)
- ========================================================================== */
-.theme-warm {
- background-color: #F7F5F0;
- color: #1C1917;
-
- .custom-nav-bar {
- background: rgba(247, 245, 240, 0.95);
- border-bottom-color: #E7E2D8;
-
- .nav-content {
- .btn-nav-back {
- background: #FFFFFF;
- box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
- }
-
- .nav-title-wrap .nav-title {
- color: #1C1917;
- }
- }
+ height: 40rpx;
}
- .summary-stat-card {
- background: linear-gradient(135deg, #FFF7ED 0%, #FFEDD5 100%);
- border: 1px solid #FED7AA;
- box-shadow: 0 8rpx 28rpx rgba(234, 88, 12, 0.08);
+ /* 暖阳浅色模式适配 (theme-warm) */
+ &.theme-warm {
+ background-color: #FFFDF9;
+ color: #1C1917;
- .summary-title-row {
- .title-left .summary-card-title {
- color: #9A3412;
- }
+ .custom-nav-bar {
+ background: rgba(255, 253, 249, 0.95);
+ border-bottom-color: rgba(234, 88, 12, 0.1);
- .btn-new-withdraw {
- background: rgba(234, 88, 12, 0.12);
- border-color: rgba(234, 88, 12, 0.35);
+ .nav-content {
+ .btn-nav-back {
+ background: #FFF7ED;
+ border: 1px solid #FED7AA;
+ }
- .btn-txt {
- color: #EA580C;
+ .nav-title-wrap .nav-title {
+ color: #1C1917;
}
}
}
- .summary-numbers-grid {
+ .summary-stat-card {
+ background: linear-gradient(135deg, #FFF7ED 0%, #FFEDD5 100%);
+ border: 1px solid #FED7AA;
+ box-shadow: 0 8rpx 28rpx rgba(234, 88, 12, 0.08);
+
+ .summary-title-row {
+ .title-left {
+ .wallet-icon-box {
+ background: #FFEDD5;
+ }
+
+ .title-text-wrap {
+ .summary-card-title {
+ color: #9A3412;
+ }
+
+ .summary-card-sub {
+ color: #EA580C;
+ }
+ }
+ }
+
+ .btn-new-withdraw {
+ background: #FFFFFF;
+ border-color: #FED7AA;
+ box-shadow: 0 2rpx 8rpx rgba(234, 88, 12, 0.1);
+
+ .btn-txt {
+ color: #EA580C;
+ }
+ }
+ }
+
+ .summary-numbers-grid {
+ background: #FFFFFF;
+ border-color: #FED7AA;
+ box-shadow: 0 2rpx 10rpx rgba(234, 88, 12, 0.04);
+
+ .stat-col {
+ .stat-num-val {
+ &.green { color: #059669; }
+ &.gold { color: #D97706; }
+ &.count { color: #EA580C; }
+ }
+
+ .stat-num-label {
+ color: #78716C;
+ }
+ }
+
+ .col-divider {
+ background: #F5EBE1;
+ }
+ }
+ }
+
+ .filter-tabs-card {
background: #FFFFFF;
border-color: #FED7AA;
+ box-shadow: 0 4rpx 16rpx rgba(234, 88, 12, 0.04);
- .stat-col {
- .stat-num-val {
- color: #1C1917;
-
- &.gold { color: #D97706; }
- &.purple { color: #EA580C; }
- }
-
- .stat-num-label {
- color: #78716C;
- }
- }
-
- .col-divider {
- background: #F5EBE1;
- }
- }
- }
-
- .filter-tabs-row {
- background: #FFFFFF;
- border-color: #EAE5DC;
- box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.03);
-
- .tab-item {
- .tab-label {
- color: #78716C;
- }
-
- .tab-badge {
- color: #78716C;
- background: #F5F5F4;
- }
-
- &.active {
- background: #FFF7ED;
-
+ .filter-tabs-row .tab-item {
.tab-label {
- color: #EA580C;
+ color: #78716C;
}
.tab-badge {
- background: #EA580C;
- color: #FFFFFF;
+ color: #78716C;
+ background: #F5F5F4;
}
- .tab-indicator {
- background: #EA580C;
- }
- }
- }
- }
+ &.active {
+ background: #FFF7ED;
- .records-list-wrap {
- .record-card {
- background: #FFFFFF;
- border-color: #EAE5DC;
- box-shadow: 0 4rpx 20rpx rgba(28, 25, 23, 0.04);
-
- .card-head-row {
- border-bottom-color: #F5F0E8;
-
- .order-no-wrap {
- .order-no-label { color: #78716C; }
- .order-no-val { color: #1C1917; }
- .copy-tag {
+ .tab-label {
color: #EA580C;
- background: #FFF7ED;
}
- }
- }
- .card-main-row {
- .amount-col {
- .amount-symbol, .amount-number {
- color: #1C1917;
+ .tab-badge {
+ background: #EA580C;
+ color: #FFFFFF;
}
- }
- .channel-pill {
- background: #ECFDF5;
- border-color: #A7F3D0;
-
- .channel-name {
- color: #059669;
+ .tab-indicator {
+ background: #EA580C;
}
}
}
-
- .card-timeline-box {
- background: #FAFAF9;
- border: 1px solid #F5F5F4;
-
- .timeline-row {
- .timeline-label { color: #78716C; }
- .timeline-val {
- color: #44403C;
- &.success { color: #059669; }
- &.notice { color: #D97706; }
- }
- }
- }
-
- .card-rejected-box {
- background: #FEF2F2;
- border-color: #FECACA;
-
- .reject-title-row .reject-title { color: #DC2626; }
- .reject-reason { color: #B91C1C; }
- .btn-re-withdraw {
- background: #FEE2E2;
- border-color: #FCA5A5;
- color: #DC2626;
- }
- }
}
- .list-end-tip {
- .tip-line { background: #E7E2D8; }
- .tip-txt { color: #A8A29E; }
- }
- }
+ .records-list-wrap {
+ .record-card {
+ background: #FFFFFF;
+ border-color: #FED7AA;
+ box-shadow: 0 4rpx 20rpx rgba(234, 88, 12, 0.05);
- .empty-state-card {
- .empty-title { color: #44403C; }
- .empty-sub { color: #78716C; }
- .btn-empty-withdraw {
- background: linear-gradient(135deg, #F97316 0%, #EA580C 100%);
- box-shadow: 0 8rpx 24rpx rgba(234, 88, 12, 0.35);
+ .card-head-row {
+ border-bottom-color: #F5F0E8;
+
+ .order-no-wrap {
+ .order-no-label { color: #78716C; }
+ .order-no-val { color: #1C1917; }
+ .copy-tag {
+ color: #EA580C;
+ background: #FFF7ED;
+ }
+ }
+ }
+
+ .card-main-row {
+ .amount-col {
+ .amount-symbol { color: #059669; }
+ .amount-number { color: #1C1917; }
+ }
+
+ .channel-pill {
+ background: #ECFDF5;
+ border-color: #A7F3D0;
+
+ .channel-name {
+ color: #059669;
+ }
+ }
+ }
+
+ .card-timeline-box {
+ background: #FAFAF9;
+ border-color: #F5F5F4;
+
+ .timeline-row {
+ .timeline-label { color: #78716C; }
+ .timeline-val {
+ color: #44403C;
+
+ &.success { color: #059669; }
+ &.notice { color: #D97706; }
+ }
+ }
+ }
+
+ .card-rejected-box {
+ background: #FEF2F2;
+ border-color: #FECACA;
+
+ .reject-title-row .reject-title { color: #DC2626; }
+ .reject-reason { color: #B91C1C; }
+ .btn-re-withdraw {
+ background: #FEE2E2;
+ border-color: #FCA5A5;
+ color: #DC2626;
+ }
+ }
+ }
+
+ .list-end-tip {
+ .tip-line { background: #E7E2D8; }
+ .tip-txt { color: #A8A29E; }
+ }
+ }
+
+ .empty-state-card {
+ .empty-icon-wrap {
+ background: #FFF7ED;
+ border: 1px solid #FED7AA;
+ }
+
+ .empty-title { color: #1C1917; }
+ .empty-sub { color: #78716C; }
+
+ .btn-empty-withdraw {
+ background: linear-gradient(135deg, #F97316 0%, #EA580C 100%);
+ box-shadow: 0 8rpx 24rpx rgba(234, 88, 12, 0.3);
+ }
}
}
}
+
+.btn-active {
+ transition: opacity 0.15s ease, transform 0.15s ease;
+ &:active {
+ opacity: 0.8;
+ transform: scale(0.98);
+ }
+}
diff --git a/server/src/db/mysql.ts b/server/src/db/mysql.ts
index 907da5b..26e26c8 100644
--- a/server/src/db/mysql.ts
+++ b/server/src/db/mysql.ts
@@ -427,6 +427,14 @@ export async function initDatabase(): Promise {
try {
await conn.query("ALTER TABLE users ADD COLUMN signature VARCHAR(64) DEFAULT ''");
} catch (_) {}
+ // 确保存在 demo 账号 101 (金牌陪伴师/认证大神体验账号)
+ try {
+ await conn.query(`
+ INSERT INTO users (id, user_no, nickname, avatar, phone, gender, role, balance, commission, invited_count, order_count, activity_count, status, wechat_openid, signature)
+ VALUES (101, 'U101', '糖心小糯米', 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200', '138****0101', '女', '认证大神', 2580.00, 128.50, 6, 88, 16, '正常', 'wx_openid_101', '人美声甜,擅长各类同城陪伴与开黑互动')
+ ON DUPLICATE KEY UPDATE nickname = VALUES(nickname)
+ `);
+ } catch (_) {}
// 21. 用户举报工单表 (涉黄/涉赌/线下欺诈等不良陪玩举报)
await conn.query(`
diff --git a/server/src/db/repository.ts b/server/src/db/repository.ts
index 63ca4b3..009a6c5 100644
--- a/server/src/db/repository.ts
+++ b/server/src/db/repository.ts
@@ -1979,9 +1979,29 @@ export class MysqlRepository {
role, balance, commission, invited_count as invitedCount,
order_count as orderCount, activity_count as activityCount,
status, wechat_openid as wechatOpenid, created_at as createdAt
- FROM users WHERE id = ?
`, [id]);
- if (!rows || rows.length === 0) return null;
+ if (!rows || rows.length === 0) {
+ if (id === 101) {
+ return {
+ id: 101,
+ userNo: 'U101',
+ nickname: '糖心小糯米',
+ avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200',
+ phone: '138****0101',
+ gender: '女',
+ signature: '人美声甜,擅长各类同城陪伴与开黑互动',
+ role: '认证大神',
+ balance: '2580.00',
+ commission: '128.50',
+ invitedCount: 6,
+ orderCount: 88,
+ activityCount: 16,
+ isExpert: true,
+ status: '正常'
+ };
+ }
+ return null;
+ }
const u = rows[0];
return {
id: u.id,
diff --git a/server/src/index.ts b/server/src/index.ts
index 8199410..59c4093 100644
--- a/server/src/index.ts
+++ b/server/src/index.ts
@@ -1564,9 +1564,29 @@ app.get('/api/users/:id/detail', async (req: Request, res: Response) => {
app.get('/api/users/:id', async (req: Request, res: Response) => {
try {
const userId = Number(req.params.id);
- const user = await repo.getUserById(userId);
+ let user = await repo.getUserById(userId);
if (!user) {
- return res.status(404).json({ code: 40400, message: '用户未找到' });
+ if (userId === 101) {
+ user = {
+ id: 101,
+ userNo: 'U101',
+ nickname: '糖心小糯米',
+ avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200',
+ phone: '138****0101',
+ gender: '女',
+ signature: '人美声甜,擅长各类同城陪伴与开黑互动',
+ role: '认证大神',
+ balance: '2580.00',
+ commission: '128.50',
+ invitedCount: 6,
+ orderCount: 88,
+ activityCount: 16,
+ isExpert: true,
+ status: '正常'
+ };
+ } else {
+ return res.status(404).json({ code: 40400, message: '用户未找到' });
+ }
}
res.json({ code: 20000, data: user });
} catch (err: any) {