From 3b0268ab10721c417ac3556bff9be3b1d17fe2f7 Mon Sep 17 00:00:00 2001
From: xcbyy <2578898740@qq.com>
Date: Tue, 13 Oct 2026 14:10:00 +0800
Subject: [PATCH] feat(bill): convert bill records modal into dedicated
independent page
---
pwuniapp/pages.json | 10 +
pwuniapp/pages/user/bill-records.vue | 1299 +++++++++++++++++++++++++
pwuniapp/pages/user/index.vue | 29 +-
server/src/db/repository.ts | 8 +-
server/tests/content-security.spec.ts | 53 +-
5 files changed, 1369 insertions(+), 30 deletions(-)
create mode 100644 pwuniapp/pages/user/bill-records.vue
diff --git a/pwuniapp/pages.json b/pwuniapp/pages.json
index 8630f65..82c0842 100644
--- a/pwuniapp/pages.json
+++ b/pwuniapp/pages.json
@@ -142,6 +142,16 @@
"backgroundColor": "#0A0F1D"
}
},
+ {
+ "path": "pages/user/bill-records",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "账单明细",
+ "navigationBarBackgroundColor": "#0A0F1D",
+ "navigationBarTextStyle": "white",
+ "backgroundColor": "#0A0F1D"
+ }
+ },
{
"path": "pages/user/settings",
"style": {
diff --git a/pwuniapp/pages/user/bill-records.vue b/pwuniapp/pages/user/bill-records.vue
new file mode 100644
index 0000000..cddd760
--- /dev/null
+++ b/pwuniapp/pages/user/bill-records.vue
@@ -0,0 +1,1299 @@
+
+
+
+
+
+
+
+
+
+ 账单明细
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 账户收支总览
+ 资金安全保障 · 实时明细核算
+
+
+
+
+
+
+
+ 钱包当前可用余额
+
+ ¥
+ {{ userBalance }}
+
+
+
+
+
+ +¥{{ stats.totalIn }}
+ 累计入账 (充值/退款)
+
+
+
+ -¥{{ stats.totalOut }}
+ 累计支出 (订单/提现)
+
+
+
+ {{ allRecords.length }} 笔
+ 流水总记录
+
+
+
+
+
+
+
+
+
+
+ {{ tab.label }}
+ {{ tab.count }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 流水号:
+ {{ item.recordNo || item.id }}
+ 复制
+
+
+ {{ item.direction === 'IN' ? '资金入账' : '资金出账' }}
+
+
+
+
+
+
+
+
+
+
+ {{ item.type || '账户资金变动' }}
+ {{ item.counterparty || '系统结算' }}
+
+
+
+
+ {{ item.direction === 'IN' ? '+' : '-' }}¥{{ formatAmount(item.amount) }}
+
+
+
+
+
+
+
+
+
+
+
+ 已展示全部收支明细
+
+
+
+
+
+
+
+
+
+ 暂无相关收支账单记录
+ 预约生活陪伴大神、参与同城组局或充值钱包后将在此自动生成明细
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pwuniapp/pages/user/index.vue b/pwuniapp/pages/user/index.vue
index 128d3f4..8ab6f8e 100644
--- a/pwuniapp/pages/user/index.vue
+++ b/pwuniapp/pages/user/index.vue
@@ -972,32 +972,11 @@ const ensureLoggedIn = () => {
return true;
};
-const viewWalletLog = async () => {
+const viewWalletLog = () => {
if (!ensureLoggedIn()) return;
- try {
- const list = await getUserFinanceRecords(user.value.id || 1001);
- if (!list || list.length === 0) {
- uni.showModal({
- title: '账单明细',
- content: '暂无近期财务收支流水记录',
- showCancel: false,
- confirmText: '我知道了'
- });
- return;
- }
- const lines = list.slice(0, 5).map(item => {
- const sign = item.direction === 'IN' ? '+' : '-';
- return `${item.type}: ${sign}¥${Number(item.amount).toFixed(2)} (${item.counterparty || '系统'})`;
- });
- uni.showModal({
- title: '最近收支明细',
- content: lines.join('\r\n'),
- showCancel: false,
- confirmText: '确定'
- });
- } catch (err) {
- uni.showToast({ title: '账单获取异常', icon: 'none' });
- }
+ uni.navigateTo({
+ url: '/pages/user/bill-records'
+ });
};
const handleRecharge = async () => {
diff --git a/server/src/db/repository.ts b/server/src/db/repository.ts
index c9ef239..ad75c5c 100644
--- a/server/src/db/repository.ts
+++ b/server/src/db/repository.ts
@@ -2183,12 +2183,12 @@ export class MysqlRepository {
const [uRows]: any = await pool.query('SELECT nickname FROM users WHERE id = ?', [userId]);
const nickname = uRows[0]?.nickname || '';
const [rows]: any = await pool.query(`
- SELECT id, record_no as recordNo, type, amount, direction, counterparty, related_id as relatedId, created_at as createdAt
+ SELECT id, record_no as recordNo, user_id as userId, type, amount, direction, counterparty, related_id as relatedId, created_at as createdAt
FROM finance_records
- WHERE counterparty LIKE ? OR counterparty LIKE ? OR related_id = ?
+ WHERE user_id = ? OR counterparty LIKE ? OR counterparty LIKE ? OR related_id = ?
ORDER BY created_at DESC
- LIMIT 50
- `, [`%${nickname}%`, `%${userId}%`, String(userId)]);
+ LIMIT 100
+ `, [userId, `%${nickname}%`, `%${userId}%`, String(userId)]);
return rows;
}
diff --git a/server/tests/content-security.spec.ts b/server/tests/content-security.spec.ts
index 2fcfed4..b9c87c9 100644
--- a/server/tests/content-security.spec.ts
+++ b/server/tests/content-security.spec.ts
@@ -130,7 +130,7 @@ describe('ContentSecurityService & Compliance Architecture (TDD 微信内容安
const raw = fs.readFileSync(pagesJsonPath, 'utf-8');
const config = JSON.parse(raw);
expect(Array.isArray(config.pages)).toBe(true);
- expect(config.pages.length).toBe(20);
+ expect(config.pages.length).toBe(21);
for (const pageItem of config.pages) {
const vueFilePath = path.join(rootDir, 'pwuniapp', `${pageItem.path}.vue`);
@@ -758,7 +758,58 @@ describe('ContentSecurityService & Compliance Architecture (TDD 微信内容安
}
});
});
+
+ describe('17. 独立专属收支账单明细页面验证 (pages/user/bill-records.vue)', () => {
+ it('pages.json 必须成功注册 pages/user/bill-records 且物理文件必须存在', () => {
+ const billPath = path.join(rootDir, 'pwuniapp', 'pages', 'user', 'bill-records.vue');
+ expect(fs.existsSync(billPath)).toBe(true);
+ const pagesJsonPath = path.join(rootDir, 'pwuniapp', 'pages.json');
+ const pagesJson = fs.readFileSync(pagesJsonPath, 'utf-8');
+ expect(pagesJson).toContain('pages/user/bill-records');
+ expect(pagesJson).toContain('账单明细');
+ });
+
+ it('个人中心页面 (pages/user/index.vue) 账单明细入口必须原生跳转至 /pages/user/bill-records 且杜绝弹窗', () => {
+ const userVuePath = path.join(rootDir, 'pwuniapp', 'pages', 'user', 'index.vue');
+ const content = fs.readFileSync(userVuePath, 'utf-8');
+ expect(content).toContain('/pages/user/bill-records');
+ expect(content).not.toContain("title: '最近收支明细'");
+ });
+
+ it('独立账单明细页面必须支持分类选项卡筛选、总览统计、一键复制流水号与双主题适配', () => {
+ const billPath = path.join(rootDir, 'pwuniapp', 'pages', 'user', 'bill-records.vue');
+ const content = fs.readFileSync(billPath, 'utf-8');
+ expect(content).toContain('tabList');
+ expect(content).toContain('filteredRecords');
+ expect(content).toContain('getUserFinanceRecords');
+ expect(content).toContain('handleCopyOrderNo');
+ expect(content).toContain('theme-warm');
+ expect(content).toContain('theme-cool');
+ expect(content).toContain('userBalance');
+ });
+
+ it('仓储层 getUserFinanceRecords 必须包含 user_id 字段选择与查询', () => {
+ const repoPath = path.join(rootDir, 'server', 'src', 'db', 'repository.ts');
+ const content = fs.readFileSync(repoPath, 'utf-8');
+ expect(content).toContain('user_id as userId');
+ expect(content).toContain('user_id = ?');
+ });
+
+ it('账单明细页面代码严禁包含任何系统 Emoji 与 showModal 4 字门禁违规', () => {
+ const billPath = path.join(rootDir, 'pwuniapp', 'pages', 'user', 'bill-records.vue');
+ const content = fs.readFileSync(billPath, 'utf-8');
+ const emojiRegex = /(?:\p{Extended_Pictographic}|\p{Emoji_Presentation}|[\u2600-\u27BF])/u;
+ expect(emojiRegex.test(content)).toBe(false);
+
+ const modalMatches = content.matchAll(/(?:confirmText|cancelText):\s*['"]([^'"]+)['"]/g);
+ for (const match of modalMatches) {
+ const btnText = match[1];
+ expect(btnText.length).toBeLessThanOrEqual(4);
+ }
+ });
+ });
});
+