feat: server connect mongo
This commit is contained in:
67
web/src/lib/config/theme.ts
Normal file
67
web/src/lib/config/theme.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import Monitor from '@lucide/svelte/icons/monitor';
|
||||
import Sun from '@lucide/svelte/icons/sun';
|
||||
import Moon from '@lucide/svelte/icons/moon';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
export type ThemeMode = 'system' | 'light' | 'dark';
|
||||
|
||||
export interface ThemeOption {
|
||||
label: string;
|
||||
icon: ComponentType;
|
||||
}
|
||||
|
||||
export const themeConfig: Record<ThemeMode, ThemeOption> = {
|
||||
system: { label: '跟随系统', icon: Monitor },
|
||||
light: { label: '浅色模式', icon: Sun },
|
||||
dark: { label: '深色模式', icon: Moon }
|
||||
};
|
||||
|
||||
export const themeCycle: ThemeMode[] = ['system', 'light', 'dark'];
|
||||
|
||||
export const THEME_STORAGE_KEY = 'theme';
|
||||
|
||||
/**
|
||||
* 获取下一个主题模式
|
||||
*/
|
||||
export function getNextTheme(current: ThemeMode): ThemeMode {
|
||||
const currentIndex = themeCycle.indexOf(current);
|
||||
return themeCycle[(currentIndex + 1) % themeCycle.length];
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前是否应该使用深色模式
|
||||
*/
|
||||
export function shouldUseDarkMode(mode: ThemeMode): boolean {
|
||||
if (mode === 'system') {
|
||||
return typeof window !== 'undefined'
|
||||
? window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
: false;
|
||||
}
|
||||
return mode === 'dark';
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用主题到 document
|
||||
*/
|
||||
export function applyThemeToDocument(mode: ThemeMode): void {
|
||||
if (typeof document === 'undefined') return;
|
||||
document.documentElement.classList.toggle('dark', shouldUseDarkMode(mode));
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 localStorage 读取保存的主题
|
||||
*/
|
||||
export function loadThemeFromStorage(): ThemeMode {
|
||||
if (typeof localStorage === 'undefined') return 'system';
|
||||
const saved = localStorage.getItem(THEME_STORAGE_KEY) as ThemeMode | null;
|
||||
return saved && themeCycle.includes(saved) ? saved : 'system';
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存主题到 localStorage
|
||||
*/
|
||||
export function saveThemeToStorage(mode: ThemeMode): void {
|
||||
if (typeof localStorage === 'undefined') return;
|
||||
localStorage.setItem(THEME_STORAGE_KEY, mode);
|
||||
}
|
||||
|
||||
@@ -1,198 +1,169 @@
|
||||
import type { BillRecord } from '$lib/api';
|
||||
|
||||
// 生成随机金额
|
||||
function randomAmount(min: number, max: number): string {
|
||||
return (Math.random() * (max - min) + min).toFixed(2);
|
||||
}
|
||||
/**
|
||||
* 真实账单数据(来自支付宝和微信导出)
|
||||
* 数据已脱敏处理
|
||||
*/
|
||||
export const demoRecords: BillRecord[] = [
|
||||
// ========== 支付宝数据 ==========
|
||||
{ time: "2026-01-07 12:01:02", category: "餐饮美食", merchant: "金山武汉食堂", description: "烧腊", income_expense: "支出", amount: "23.80", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-06 15:54:53", category: "餐饮美食", merchant: "友宝", description: "智能货柜消费", income_expense: "支出", amount: "7.19", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-06 11:55:10", category: "餐饮美食", merchant: "金山武汉食堂", description: "小碗菜", income_expense: "支出", amount: "12.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-06 09:35:09", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "16.09", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-05 18:59:11", category: "餐饮美食", merchant: "板栗", description: "收钱码收款", income_expense: "支出", amount: "21.00", payment_method: "花呗", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-05 18:22:34", category: "服饰装扮", merchant: "金山便利店", description: "立码收收款", income_expense: "支出", amount: "40.69", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-05 15:16:38", category: "充值缴费", merchant: "武汉供电公司", description: "电费自动缴费", income_expense: "支出", amount: "50.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-05 13:49:13", category: "餐饮美食", merchant: "友宝", description: "维他柠檬茶", income_expense: "支出", amount: "2.40", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-05 11:59:45", category: "餐饮美食", merchant: "金山武汉食堂", description: "小碗菜", income_expense: "支出", amount: "9.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-05 09:36:44", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "13.43", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-04 19:27:50", category: "日用百货", merchant: "朴朴超市", description: "商品订单", income_expense: "支出", amount: "52.77", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-04 17:06:22", category: "餐饮美食", merchant: "友宝", description: "香辣鸭翅根", income_expense: "支出", amount: "2.55", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-04 12:03:39", category: "餐饮美食", merchant: "金山武汉食堂", description: "烧腊", income_expense: "支出", amount: "23.80", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-04 09:29:28", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "22.86", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-04 09:04:05", category: "餐饮美食", merchant: "巴比鲜包", description: "早餐", income_expense: "支出", amount: "8.00", payment_method: "花呗", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-03 22:30:01", category: "餐饮美食", merchant: "美团", description: "长沙臭豆腐", income_expense: "支出", amount: "20.88", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-03 17:04:37", category: "家居家装", merchant: "淘宝", description: "四件套", income_expense: "支出", amount: "156.35", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-03 13:44:03", category: "餐饮美食", merchant: "必胜客", description: "外卖订单", income_expense: "支出", amount: "55.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-03 10:16:31", category: "充值缴费", merchant: "湖北联通", description: "手机充值", income_expense: "支出", amount: "50.00", payment_method: "招商银行信用卡", status: "充值成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-03 00:17:12", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "17.45", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-02 21:29:15", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "20.65", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-02 15:39:08", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "12.61", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-02 13:30:02", category: "充值缴费", merchant: "武汉燃气集团", description: "燃气费", income_expense: "支出", amount: "300.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-02 12:06:04", category: "餐饮美食", merchant: "食寨香木甑饭", description: "外卖订单", income_expense: "支出", amount: "17.38", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-02 12:04:27", category: "运动健身", merchant: "携程", description: "武汉冰雪中心", income_expense: "支出", amount: "390.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-02 11:05:33", category: "充值缴费", merchant: "中国移动", description: "话费充值", income_expense: "支出", amount: "50.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-02 01:46:12", category: "充值缴费", merchant: "中国移动", description: "话费自动充值", income_expense: "支出", amount: "50.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-01 21:42:18", category: "文化休闲", merchant: "雷神", description: "超级会员", income_expense: "支出", amount: "88.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-01 20:44:27", category: "餐饮美食", merchant: "茶百道", description: "饮品", income_expense: "支出", amount: "6.85", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-01 14:29:46", category: "餐饮美食", merchant: "星巴克", description: "咖啡", income_expense: "支出", amount: "43.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-31 21:27:54", category: "餐饮美食", merchant: "星巴克", description: "咖啡", income_expense: "支出", amount: "43.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-31 14:00:33", category: "餐饮美食", merchant: "海底捞", description: "聚餐", income_expense: "支出", amount: "207.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-31 12:06:13", category: "餐饮美食", merchant: "coco", description: "饮品", income_expense: "支出", amount: "10.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-30 18:38:25", category: "餐饮美食", merchant: "金山武汉食堂", description: "便利店", income_expense: "支出", amount: "3.50", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-30 12:05:17", category: "餐饮美食", merchant: "金山武汉食堂", description: "烧腊", income_expense: "支出", amount: "23.80", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-30 09:31:36", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "14.06", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-29 21:27:52", category: "餐饮美食", merchant: "茶百道", description: "饮品", income_expense: "支出", amount: "18.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-29 17:52:16", category: "家居家装", merchant: "淘宝", description: "家居用品", income_expense: "支出", amount: "131.80", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-29 12:05:20", category: "餐饮美食", merchant: "金山武汉食堂", description: "烧腊", income_expense: "支出", amount: "23.80", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-28 17:12:07", category: "日用百货", merchant: "朴朴超市", description: "商品订单", income_expense: "支出", amount: "57.99", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-28 13:29:06", category: "餐饮美食", merchant: "美团", description: "老乡鸡", income_expense: "支出", amount: "38.60", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-28 11:50:34", category: "运动健身", merchant: "携程", description: "武汉冰雪中心", income_expense: "支出", amount: "340.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-27 18:34:40", category: "餐饮美食", merchant: "金山武汉食堂", description: "便利店", income_expense: "支出", amount: "5.50", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-27 12:05:32", category: "餐饮美食", merchant: "金山武汉食堂", description: "烧腊", income_expense: "支出", amount: "23.80", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-27 09:50:53", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "15.62", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-26 18:34:52", category: "餐饮美食", merchant: "金山武汉食堂", description: "便利店", income_expense: "支出", amount: "3.50", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-26 12:04:30", category: "餐饮美食", merchant: "金山武汉食堂", description: "小碗菜", income_expense: "支出", amount: "10.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-26 09:09:26", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "22.53", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-25 21:48:08", category: "餐饮美食", merchant: "瑞幸咖啡", description: "咖啡", income_expense: "支出", amount: "6.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-25 18:44:14", category: "餐饮美食", merchant: "金山武汉食堂", description: "便利店", income_expense: "支出", amount: "5.50", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-25 12:06:00", category: "餐饮美食", merchant: "金山武汉食堂", description: "烧腊", income_expense: "支出", amount: "23.80", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-25 09:54:55", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "19.62", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-24 19:45:03", category: "日用百货", merchant: "朴朴超市", description: "商品订单", income_expense: "支出", amount: "44.47", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-24 18:47:15", category: "餐饮美食", merchant: "金山武汉食堂", description: "便利店", income_expense: "支出", amount: "19.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-24 12:03:03", category: "餐饮美食", merchant: "金山武汉食堂", description: "烧腊", income_expense: "支出", amount: "23.80", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-24 09:32:03", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "23.41", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-23 18:30:33", category: "餐饮美食", merchant: "金山武汉食堂", description: "便利店", income_expense: "支出", amount: "5.50", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-23 12:05:52", category: "餐饮美食", merchant: "金山武汉食堂", description: "烧腊", income_expense: "支出", amount: "23.80", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-23 09:34:15", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "14.04", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-22 23:22:30", category: "餐饮美食", merchant: "可多", description: "便利店", income_expense: "支出", amount: "44.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-22 20:34:29", category: "餐饮美食", merchant: "美团", description: "外卖", income_expense: "支出", amount: "18.55", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-22 18:02:54", category: "运动健身", merchant: "携程", description: "武汉冰雪中心", income_expense: "支出", amount: "340.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-21 21:30:42", category: "餐饮美食", merchant: "美团", description: "外卖", income_expense: "支出", amount: "19.32", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-21 16:00:41", category: "餐饮美食", merchant: "美团", description: "外卖", income_expense: "支出", amount: "54.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-20 21:23:32", category: "餐饮美食", merchant: "星巴克", description: "咖啡", income_expense: "支出", amount: "34.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-20 18:29:55", category: "餐饮美食", merchant: "金山武汉食堂", description: "便利店", income_expense: "支出", amount: "3.50", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-20 12:05:11", category: "餐饮美食", merchant: "金山武汉食堂", description: "小碗菜", income_expense: "支出", amount: "10.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-20 09:20:06", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "16.67", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-19 20:24:43", category: "餐饮美食", merchant: "美团", description: "外卖", income_expense: "支出", amount: "26.40", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-19 18:30:04", category: "餐饮美食", merchant: "金山武汉食堂", description: "便利店", income_expense: "支出", amount: "3.50", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-19 12:03:27", category: "餐饮美食", merchant: "金山武汉食堂", description: "烧腊", income_expense: "支出", amount: "23.80", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-19 09:24:21", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "16.47", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-18 18:31:46", category: "餐饮美食", merchant: "金山武汉食堂", description: "便利店", income_expense: "支出", amount: "3.50", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-18 12:06:47", category: "餐饮美食", merchant: "金山武汉食堂", description: "烧腊", income_expense: "支出", amount: "23.80", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-18 09:20:38", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "20.15", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-17 18:33:54", category: "餐饮美食", merchant: "金山武汉食堂", description: "便利店", income_expense: "支出", amount: "8.50", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-17 12:04:46", category: "餐饮美食", merchant: "金山武汉食堂", description: "小碗菜", income_expense: "支出", amount: "10.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-17 09:43:18", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "18.72", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-16 18:29:23", category: "餐饮美食", merchant: "金山武汉食堂", description: "便利店", income_expense: "支出", amount: "8.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-16 12:05:02", category: "餐饮美食", merchant: "金山武汉食堂", description: "烧腊", income_expense: "支出", amount: "23.80", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-16 09:48:27", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "16.30", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-15 20:47:21", category: "日用百货", merchant: "朴朴超市", description: "商品订单", income_expense: "支出", amount: "48.47", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-15 16:35:52", category: "运动健身", merchant: "携程", description: "武汉冰雪中心", income_expense: "支出", amount: "340.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-15 13:29:58", category: "餐饮美食", merchant: "美团", description: "外卖", income_expense: "支出", amount: "52.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-14 21:28:13", category: "餐饮美食", merchant: "美团", description: "外卖", income_expense: "支出", amount: "17.60", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-14 16:14:05", category: "餐饮美食", merchant: "美团", description: "外卖", income_expense: "支出", amount: "48.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-13 18:23:06", category: "餐饮美食", merchant: "金山武汉食堂", description: "便利店", income_expense: "支出", amount: "3.50", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-13 12:04:46", category: "餐饮美食", merchant: "金山武汉食堂", description: "小碗菜", income_expense: "支出", amount: "10.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-13 09:24:17", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "18.27", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-12 18:22:26", category: "餐饮美食", merchant: "金山武汉食堂", description: "便利店", income_expense: "支出", amount: "3.50", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-12 12:04:12", category: "餐饮美食", merchant: "金山武汉食堂", description: "烧腊", income_expense: "支出", amount: "23.80", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-12 09:18:36", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "13.59", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-11 18:26:14", category: "餐饮美食", merchant: "金山武汉食堂", description: "便利店", income_expense: "支出", amount: "6.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-11 12:03:48", category: "餐饮美食", merchant: "金山武汉食堂", description: "烧腊", income_expense: "支出", amount: "23.80", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-11 09:17:00", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "14.27", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-10 21:10:09", category: "餐饮美食", merchant: "瑞幸咖啡", description: "咖啡", income_expense: "支出", amount: "9.90", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-10 18:29:53", category: "餐饮美食", merchant: "金山武汉食堂", description: "便利店", income_expense: "支出", amount: "5.50", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-10 12:09:23", category: "餐饮美食", merchant: "金山武汉食堂", description: "烧腊", income_expense: "支出", amount: "23.80", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-10 09:23:16", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "13.70", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-09 18:26:48", category: "餐饮美食", merchant: "金山武汉食堂", description: "便利店", income_expense: "支出", amount: "3.50", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-09 12:08:06", category: "餐饮美食", merchant: "金山武汉食堂", description: "小碗菜", income_expense: "支出", amount: "10.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-09 09:32:16", category: "交通出行", merchant: "高德打车", description: "打车订单", income_expense: "支出", amount: "14.33", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-08 21:00:28", category: "日用百货", merchant: "朴朴超市", description: "商品订单", income_expense: "支出", amount: "57.50", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-08 16:19:40", category: "运动健身", merchant: "携程", description: "武汉冰雪中心", income_expense: "支出", amount: "340.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-08 14:15:07", category: "餐饮美食", merchant: "肯德基", description: "套餐", income_expense: "支出", amount: "44.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-07 21:05:23", category: "餐饮美食", merchant: "美团", description: "外卖", income_expense: "支出", amount: "25.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-07 15:06:26", category: "餐饮美食", merchant: "星巴克", description: "咖啡", income_expense: "支出", amount: "34.00", payment_method: "招商银行信用卡", status: "交易成功", remark: "", needs_review: "" },
|
||||
|
||||
// 生成指定日期的时间字符串
|
||||
function formatDateTime(date: Date, hour: number, minute: number): string {
|
||||
const y = date.getFullYear();
|
||||
const m = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const d = String(date.getDate()).padStart(2, '0');
|
||||
const h = String(hour).padStart(2, '0');
|
||||
const min = String(minute).padStart(2, '0');
|
||||
return `${y}-${m}-${d} ${h}:${min}:00`;
|
||||
}
|
||||
|
||||
// 商家和消费场景配置
|
||||
const merchants = {
|
||||
餐饮美食: [
|
||||
{ merchant: '金山武汉食堂', descriptions: ['午餐', '烧腊', '小碗菜'], amountRange: [12, 28] },
|
||||
{ merchant: '瑞幸咖啡', descriptions: ['生椰拿铁', '美式', '拿铁'], amountRange: [9.9, 18] },
|
||||
{ merchant: '星巴克', descriptions: ['美式咖啡', '拿铁', '星冰乐'], amountRange: [28, 45] },
|
||||
{ merchant: '麦当劳', descriptions: ['早餐套餐', '午餐套餐', '汉堡'], amountRange: [20, 45] },
|
||||
{ merchant: '肯德基', descriptions: ['套餐', '炸鸡', '汉堡'], amountRange: [25, 50] },
|
||||
{ merchant: '海底捞', descriptions: ['火锅', '聚餐'], amountRange: [150, 300] },
|
||||
{ merchant: '美团外卖', descriptions: ['外卖订单', '午餐外卖', '晚餐外卖'], amountRange: [20, 50] },
|
||||
{ merchant: '饿了么', descriptions: ['外卖订单', '午餐', '晚餐'], amountRange: [18, 45] },
|
||||
{ merchant: '便利店', descriptions: ['零食', '饮料', '早餐'], amountRange: [8, 30] },
|
||||
{ merchant: '喜茶', descriptions: ['多肉葡萄', '芝芝莓莓'], amountRange: [18, 32] },
|
||||
],
|
||||
交通出行: [
|
||||
{ merchant: '高德打车', descriptions: ['打车订单', '快车'], amountRange: [12, 35] },
|
||||
{ merchant: '滴滴出行', descriptions: ['快车', '打车'], amountRange: [15, 40] },
|
||||
{ merchant: '武汉地铁', descriptions: ['地铁充值', '乘车'], amountRange: [50, 100] },
|
||||
{ merchant: '哈啰单车', descriptions: ['骑行', '单车'], amountRange: [1.5, 5] },
|
||||
{ merchant: '中国石化', descriptions: ['加油', '油费'], amountRange: [200, 400] },
|
||||
],
|
||||
日用百货: [
|
||||
{ merchant: '朴朴超市', descriptions: ['日用品', '商品订单'], amountRange: [30, 80] },
|
||||
{ merchant: '盒马鲜生', descriptions: ['生鲜蔬果', '日用品'], amountRange: [50, 150] },
|
||||
{ merchant: '沃尔玛', descriptions: ['日用品采购', '超市购物'], amountRange: [80, 200] },
|
||||
{ merchant: '名创优品', descriptions: ['日用品', '小商品'], amountRange: [20, 60] },
|
||||
{ merchant: '屈臣氏', descriptions: ['洗护用品', '化妆品'], amountRange: [50, 150] },
|
||||
],
|
||||
充值缴费: [
|
||||
{ merchant: '武汉供电公司', descriptions: ['电费', '电费缴费'], amountRange: [50, 200] },
|
||||
{ merchant: '武汉燃气集团', descriptions: ['燃气费', '天然气'], amountRange: [100, 300] },
|
||||
{ merchant: '中国移动', descriptions: ['话费充值', '手机充值'], amountRange: [50, 100] },
|
||||
{ merchant: '中国联通', descriptions: ['话费充值', '手机充值'], amountRange: [50, 100] },
|
||||
{ merchant: '中国电信', descriptions: ['宽带续费', '话费'], amountRange: [100, 200] },
|
||||
],
|
||||
服饰鞋包: [
|
||||
{ merchant: '优衣库', descriptions: ['衣服', '裤子', '外套'], amountRange: [100, 500] },
|
||||
{ merchant: 'ZARA', descriptions: ['衣服', '外套'], amountRange: [200, 600] },
|
||||
{ merchant: 'Nike', descriptions: ['运动鞋', '运动服'], amountRange: [300, 800] },
|
||||
{ merchant: '淘宝', descriptions: ['服装', '鞋子'], amountRange: [80, 300] },
|
||||
],
|
||||
数码电器: [
|
||||
{ merchant: '京东', descriptions: ['数码配件', '电子产品'], amountRange: [50, 500] },
|
||||
{ merchant: '天猫', descriptions: ['手机配件', '电子产品'], amountRange: [30, 200] },
|
||||
{ merchant: '苹果官网', descriptions: ['配件', '保护壳'], amountRange: [100, 300] },
|
||||
],
|
||||
文化休闲: [
|
||||
{ merchant: '腾讯视频', descriptions: ['VIP会员', '会员续费'], amountRange: [25, 30] },
|
||||
{ merchant: '爱奇艺', descriptions: ['VIP会员', '会员'], amountRange: [25, 30] },
|
||||
{ merchant: 'B站', descriptions: ['大会员', '会员'], amountRange: [25, 25] },
|
||||
{ merchant: '万达影城', descriptions: ['电影票', '观影'], amountRange: [40, 100] },
|
||||
{ merchant: '书店', descriptions: ['书籍', '购书'], amountRange: [30, 100] },
|
||||
],
|
||||
运动健身: [
|
||||
{ merchant: '迪卡侬', descriptions: ['运动装备', '健身用品'], amountRange: [100, 300] },
|
||||
{ merchant: '健身房', descriptions: ['月卡', '私教课'], amountRange: [200, 500] },
|
||||
{ merchant: '携程', descriptions: ['滑雪', '运动场馆'], amountRange: [150, 400] },
|
||||
],
|
||||
医疗健康: [
|
||||
{ merchant: '药店', descriptions: ['药品', '保健品'], amountRange: [30, 100] },
|
||||
{ merchant: '医院', descriptions: ['挂号费', '门诊'], amountRange: [20, 100] },
|
||||
],
|
||||
家居家装: [
|
||||
{ merchant: '淘宝', descriptions: ['家居用品', '四件套', '收纳'], amountRange: [50, 200] },
|
||||
{ merchant: '宜家', descriptions: ['家具', '家居'], amountRange: [100, 500] },
|
||||
],
|
||||
};
|
||||
|
||||
const paymentMethods = ['微信支付', '支付宝', '招商银行信用卡', '花呗', '工商银行储蓄卡'];
|
||||
|
||||
// 生成单条支出记录
|
||||
function generateExpenseRecord(date: Date, category: string): BillRecord {
|
||||
const categoryMerchants = merchants[category as keyof typeof merchants] || merchants['餐饮美食'];
|
||||
const merchantInfo = categoryMerchants[Math.floor(Math.random() * categoryMerchants.length)];
|
||||
const description = merchantInfo.descriptions[Math.floor(Math.random() * merchantInfo.descriptions.length)];
|
||||
const amount = randomAmount(merchantInfo.amountRange[0], merchantInfo.amountRange[1]);
|
||||
const paymentMethod = paymentMethods[Math.floor(Math.random() * paymentMethods.length)];
|
||||
const hour = Math.floor(Math.random() * 14) + 8; // 8:00 - 22:00
|
||||
const minute = Math.floor(Math.random() * 60);
|
||||
|
||||
return {
|
||||
time: formatDateTime(date, hour, minute),
|
||||
category,
|
||||
merchant: merchantInfo.merchant,
|
||||
description,
|
||||
income_expense: '支出',
|
||||
amount,
|
||||
payment_method: paymentMethod,
|
||||
status: '交易成功',
|
||||
remark: '',
|
||||
needs_review: '',
|
||||
};
|
||||
}
|
||||
|
||||
// 生成收入记录
|
||||
function generateIncomeRecord(date: Date): BillRecord {
|
||||
const incomeTypes = [
|
||||
{ category: '退款', merchant: '淘宝', description: '商品退款', amountRange: [30, 200] },
|
||||
{ category: '退款', merchant: '京东', description: '退货退款', amountRange: [50, 300] },
|
||||
{ category: '其他收入', merchant: '微信红包', description: '红包', amountRange: [5, 100] },
|
||||
{ category: '其他收入', merchant: '支付宝', description: '余额宝收益', amountRange: [1, 20] },
|
||||
{ category: '其他收入', merchant: '微信转账', description: '朋友转账', amountRange: [100, 500] },
|
||||
];
|
||||
|
||||
const incomeInfo = incomeTypes[Math.floor(Math.random() * incomeTypes.length)];
|
||||
const amount = randomAmount(incomeInfo.amountRange[0], incomeInfo.amountRange[1]);
|
||||
const hour = Math.floor(Math.random() * 14) + 8;
|
||||
const minute = Math.floor(Math.random() * 60);
|
||||
|
||||
return {
|
||||
time: formatDateTime(date, hour, minute),
|
||||
category: incomeInfo.category,
|
||||
merchant: incomeInfo.merchant,
|
||||
description: incomeInfo.description,
|
||||
income_expense: '收入',
|
||||
amount,
|
||||
payment_method: incomeInfo.category === '退款' ? '原路退回' : '微信零钱',
|
||||
status: incomeInfo.category === '退款' ? '退款成功' : '已到账',
|
||||
remark: '',
|
||||
needs_review: '',
|
||||
};
|
||||
}
|
||||
|
||||
// 生成一天的记录
|
||||
function generateDayRecords(date: Date): BillRecord[] {
|
||||
const records: BillRecord[] = [];
|
||||
const dayOfWeek = date.getDay();
|
||||
const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
|
||||
|
||||
// 每天固定的支出
|
||||
const categories = Object.keys(merchants);
|
||||
|
||||
// 工作日:早餐、午餐、晚餐、交通
|
||||
// 周末:可能有更多消费
|
||||
const baseExpenses = isWeekend ?
|
||||
Math.floor(Math.random() * 4) + 4 : // 周末 4-7 笔
|
||||
Math.floor(Math.random() * 3) + 3; // 工作日 3-5 笔
|
||||
|
||||
// 必有餐饮
|
||||
records.push(generateExpenseRecord(date, '餐饮美食'));
|
||||
records.push(generateExpenseRecord(date, '餐饮美食'));
|
||||
|
||||
// 可能有交通
|
||||
if (Math.random() > 0.3) {
|
||||
records.push(generateExpenseRecord(date, '交通出行'));
|
||||
}
|
||||
|
||||
// 随机其他消费
|
||||
for (let i = 0; i < baseExpenses - 2; i++) {
|
||||
const randomCategory = categories[Math.floor(Math.random() * categories.length)];
|
||||
records.push(generateExpenseRecord(date, randomCategory));
|
||||
}
|
||||
|
||||
// 10% 概率有收入
|
||||
if (Math.random() < 0.1) {
|
||||
records.push(generateIncomeRecord(date));
|
||||
}
|
||||
|
||||
return records;
|
||||
}
|
||||
|
||||
// 生成指定日期范围的所有记录
|
||||
function generateRecords(startDate: Date, endDate: Date): BillRecord[] {
|
||||
const records: BillRecord[] = [];
|
||||
const currentDate = new Date(startDate);
|
||||
|
||||
while (currentDate <= endDate) {
|
||||
records.push(...generateDayRecords(new Date(currentDate)));
|
||||
currentDate.setDate(currentDate.getDate() + 1);
|
||||
}
|
||||
|
||||
// 按时间排序(最新的在前)
|
||||
return records.sort((a, b) => new Date(b.time).getTime() - new Date(a.time).getTime());
|
||||
}
|
||||
|
||||
// 生成从2025年10月1日到2026年1月8日的数据
|
||||
const startDate = new Date(2025, 9, 1); // 2025-10-01
|
||||
const endDate = new Date(2026, 0, 8); // 2026-01-08
|
||||
|
||||
/** 演示数据(支付宝 + 微信支付混合数据,覆盖约100天) */
|
||||
export const demoRecords: BillRecord[] = generateRecords(startDate, endDate);
|
||||
// ========== 微信数据 ==========
|
||||
{ time: "2026-01-07 12:14:45", category: "餐饮美食", merchant: "瑞幸咖啡", description: "订单付款", income_expense: "支出", amount: "10.60", payment_method: "微信零钱", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-07 09:11:03", category: "交通出行", merchant: "广州骑安", description: "先乘车后付款", income_expense: "支出", amount: "1.50", payment_method: "微信零钱", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-07 09:06:40", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "微信零钱", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-07 09:01:42", category: "交通出行", merchant: "滴滴出行", description: "单车", income_expense: "支出", amount: "0.75", payment_method: "微信零钱", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-06 18:28:04", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "微信零钱", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-06 14:17:03", category: "医疗健康", merchant: "皮肤病诊所", description: "扫码付款", income_expense: "支出", amount: "40.00", payment_method: "微信零钱", status: "已转账", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-06 10:50:23", category: "其他收入", merchant: "微信转账", description: "转账", income_expense: "收入", amount: "80.00", payment_method: "微信零钱", status: "已到账", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-05 18:28:38", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "微信零钱", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-04 20:40:57", category: "交通出行", merchant: "京庐出行", description: "共享单车", income_expense: "支出", amount: "3.00", payment_method: "微信零钱", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-04 19:24:34", category: "日用百货", merchant: "盒马鲜生", description: "购物", income_expense: "支出", amount: "54.60", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-04 18:38:16", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "微信零钱", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-03 20:24:05", category: "餐饮美食", merchant: "金山武汉食堂", description: "食堂订餐", income_expense: "支出", amount: "9.00", payment_method: "微信零钱", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-03 20:23:30", category: "餐饮美食", merchant: "金山武汉食堂", description: "食堂订餐", income_expense: "支出", amount: "8.00", payment_method: "微信零钱", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-03 20:22:42", category: "餐饮美食", merchant: "金山武汉食堂", description: "食堂订餐", income_expense: "支出", amount: "9.00", payment_method: "微信零钱", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-03 20:21:58", category: "餐饮美食", merchant: "金山武汉食堂", description: "食堂订餐", income_expense: "支出", amount: "11.00", payment_method: "微信零钱", status: "支付成功", remark: "原金额12.00,退款1.00", needs_review: "" },
|
||||
{ time: "2026-01-03 20:21:26", category: "餐饮美食", merchant: "金山武汉食堂", description: "食堂订餐", income_expense: "支出", amount: "7.00", payment_method: "微信零钱", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-02 22:32:23", category: "餐饮美食", merchant: "茶悦德", description: "饮品", income_expense: "支出", amount: "14.00", payment_method: "微信零钱", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-02 21:08:52", category: "其他收入", merchant: "微信转账", description: "转账", income_expense: "收入", amount: "100.00", payment_method: "微信零钱", status: "已到账", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-02 15:43:56", category: "其他", merchant: "众雪Popsnowboard", description: "微信转账", income_expense: "支出", amount: "190.00", payment_method: "招商银行储蓄卡", status: "对方已收钱", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-02 14:00:55", category: "日用百货", merchant: "京东", description: "购物", income_expense: "支出", amount: "47.52", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2026-01-02 12:18:07", category: "日用百货", merchant: "沃尔玛", description: "购物", income_expense: "支出", amount: "12.29", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-31 20:21:14", category: "日用百货", merchant: "沃尔玛", description: "购物", income_expense: "支出", amount: "56.16", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-31 18:26:43", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-30 19:04:35", category: "餐饮美食", merchant: "可多", description: "便利店", income_expense: "支出", amount: "14.50", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-30 18:16:47", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-29 18:51:56", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-28 18:08:51", category: "餐饮美食", merchant: "星巴克", description: "咖啡", income_expense: "支出", amount: "33.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-28 16:02:06", category: "文化休闲", merchant: "CGV影城", description: "电影票", income_expense: "支出", amount: "85.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-27 18:30:10", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-26 18:33:55", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-25 18:30:56", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-25 12:37:44", category: "餐饮美食", merchant: "喜茶", description: "饮品", income_expense: "支出", amount: "23.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-24 18:27:06", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-23 18:26:11", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-22 20:08:27", category: "餐饮美食", merchant: "瑞幸咖啡", description: "咖啡", income_expense: "支出", amount: "9.90", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-21 19:25:12", category: "餐饮美食", merchant: "盒马鲜生", description: "购物", income_expense: "支出", amount: "41.30", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-20 18:26:51", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-19 18:31:02", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-18 18:28:15", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-17 18:29:33", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-16 18:30:27", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-15 20:32:01", category: "餐饮美食", merchant: "必胜客", description: "套餐", income_expense: "支出", amount: "65.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-14 19:45:22", category: "餐饮美食", merchant: "星巴克", description: "咖啡", income_expense: "支出", amount: "37.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-13 18:27:08", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-12 18:28:41", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-11 18:27:55", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-10 21:30:18", category: "餐饮美食", merchant: "麦当劳", description: "套餐", income_expense: "支出", amount: "35.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-10 18:29:02", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-09 18:26:33", category: "交通出行", merchant: "金山软件", description: "通勤班车", income_expense: "支出", amount: "1.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-08 19:15:45", category: "餐饮美食", merchant: "瑞幸咖啡", description: "咖啡", income_expense: "支出", amount: "12.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
{ time: "2025-12-07 18:42:19", category: "餐饮美食", merchant: "奶茶店", description: "饮品", income_expense: "支出", amount: "15.00", payment_method: "招商银行信用卡", status: "支付成功", remark: "", needs_review: "" },
|
||||
].sort((a, b) => new Date(b.time).getTime() - new Date(a.time).getTime());
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<script lang="ts">
|
||||
import '../app.css';
|
||||
import { page } from '$app/stores';
|
||||
import { onMount } from 'svelte';
|
||||
import * as Sidebar from '$lib/components/ui/sidebar';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import * as DropdownMenu from '$lib/components/ui/dropdown-menu';
|
||||
import * as Avatar from '$lib/components/ui/avatar';
|
||||
import { Separator } from '$lib/components/ui/separator';
|
||||
|
||||
// Icons
|
||||
import Upload from '@lucide/svelte/icons/upload';
|
||||
import ClipboardCheck from '@lucide/svelte/icons/clipboard-check';
|
||||
import FileText from '@lucide/svelte/icons/file-text';
|
||||
@@ -13,30 +15,65 @@
|
||||
import Settings from '@lucide/svelte/icons/settings';
|
||||
import HelpCircle from '@lucide/svelte/icons/help-circle';
|
||||
import Search from '@lucide/svelte/icons/search';
|
||||
import Moon from '@lucide/svelte/icons/moon';
|
||||
import Sun from '@lucide/svelte/icons/sun';
|
||||
import ChevronsUpDown from '@lucide/svelte/icons/chevrons-up-down';
|
||||
import Wallet from '@lucide/svelte/icons/wallet';
|
||||
import LogOut from '@lucide/svelte/icons/log-out';
|
||||
import User from '@lucide/svelte/icons/user';
|
||||
import Bell from '@lucide/svelte/icons/bell';
|
||||
import Sparkles from '@lucide/svelte/icons/sparkles';
|
||||
|
||||
// Theme
|
||||
import {
|
||||
type ThemeMode,
|
||||
themeConfig,
|
||||
getNextTheme,
|
||||
applyThemeToDocument,
|
||||
loadThemeFromStorage,
|
||||
saveThemeToStorage
|
||||
} from '$lib/config/theme';
|
||||
|
||||
let { children } = $props();
|
||||
let { children } = $props();
|
||||
|
||||
let darkMode = $state(false);
|
||||
let themeMode = $state<ThemeMode>('system');
|
||||
|
||||
function toggleDarkMode() {
|
||||
darkMode = !darkMode;
|
||||
if (darkMode) {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
onMount(() => {
|
||||
themeMode = loadThemeFromStorage();
|
||||
applyThemeToDocument(themeMode);
|
||||
|
||||
// 监听系统主题变化
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const handleChange = () => applyThemeToDocument(themeMode);
|
||||
mediaQuery.addEventListener('change', handleChange);
|
||||
return () => mediaQuery.removeEventListener('change', handleChange);
|
||||
});
|
||||
|
||||
function cycleTheme() {
|
||||
themeMode = getNextTheme(themeMode);
|
||||
saveThemeToStorage(themeMode);
|
||||
applyThemeToDocument(themeMode);
|
||||
}
|
||||
|
||||
const mainNavItems = [
|
||||
{ href: '/', label: '上传', icon: Upload },
|
||||
{ href: '/review', label: '复核', icon: ClipboardCheck },
|
||||
{ href: '/bills', label: '账单', icon: FileText },
|
||||
{ href: '/analysis', label: '分析', icon: BarChart3 },
|
||||
// 主导航
|
||||
const navMain = [
|
||||
{ href: '/', label: '上传账单', icon: Upload },
|
||||
{ href: '/review', label: '智能复核', icon: ClipboardCheck },
|
||||
{ href: '/bills', label: '账单管理', icon: FileText },
|
||||
{ href: '/analysis', label: '数据分析', icon: BarChart3 },
|
||||
];
|
||||
|
||||
// 次级导航(底部)
|
||||
const navSecondary = [
|
||||
{ href: '/settings', label: '设置', icon: Settings },
|
||||
{ href: '/help', label: '帮助', icon: HelpCircle },
|
||||
];
|
||||
|
||||
// 用户数据
|
||||
const user = {
|
||||
name: '用户',
|
||||
email: 'user@example.com',
|
||||
avatar: ''
|
||||
};
|
||||
|
||||
function isActive(href: string, pathname: string): boolean {
|
||||
if (href === '/') return pathname === '/';
|
||||
return pathname.startsWith(href);
|
||||
@@ -44,57 +81,33 @@
|
||||
</script>
|
||||
|
||||
<Sidebar.Provider>
|
||||
<Sidebar.Root>
|
||||
<Sidebar.Root collapsible="offcanvas">
|
||||
<!-- Header: Logo + App Name -->
|
||||
<Sidebar.Header>
|
||||
<Sidebar.Menu>
|
||||
<Sidebar.MenuItem>
|
||||
<DropdownMenu.Root>
|
||||
<DropdownMenu.Trigger>
|
||||
{#snippet child({ props })}
|
||||
<Sidebar.MenuButton
|
||||
{...props}
|
||||
class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
|
||||
>
|
||||
<div class="flex aspect-square size-8 items-center justify-center rounded-lg bg-primary text-primary-foreground">
|
||||
<span class="text-lg">💰</span>
|
||||
</div>
|
||||
<div class="grid flex-1 text-left text-sm leading-tight">
|
||||
<span class="truncate font-semibold">BillAI</span>
|
||||
<span class="truncate text-xs text-muted-foreground">智能账单分析</span>
|
||||
</div>
|
||||
<ChevronsUpDown class="ml-auto" />
|
||||
</Sidebar.MenuButton>
|
||||
{/snippet}
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Content
|
||||
class="w-[--bits-dropdown-menu-anchor-width] min-w-56 rounded-lg"
|
||||
side="bottom"
|
||||
align="end"
|
||||
sideOffset={4}
|
||||
>
|
||||
<DropdownMenu.Label class="text-xs text-muted-foreground">
|
||||
版本信息
|
||||
</DropdownMenu.Label>
|
||||
<DropdownMenu.Item>
|
||||
<span class="mr-2">📦</span>
|
||||
v0.1.0 Beta
|
||||
</DropdownMenu.Item>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Root>
|
||||
<Sidebar.MenuButton class="!p-1.5">
|
||||
{#snippet child({ props })}
|
||||
<a href="/" {...props} class="flex items-center gap-2">
|
||||
<div class="flex size-8 items-center justify-center rounded-lg bg-gradient-to-br from-orange-500 to-amber-500 text-white">
|
||||
<Wallet class="size-5" />
|
||||
</div>
|
||||
<span class="text-base font-semibold">BillAI</span>
|
||||
</a>
|
||||
{/snippet}
|
||||
</Sidebar.MenuButton>
|
||||
</Sidebar.MenuItem>
|
||||
</Sidebar.Menu>
|
||||
</Sidebar.Header>
|
||||
|
||||
<Sidebar.Content>
|
||||
<!-- 主导航 -->
|
||||
<Sidebar.Group>
|
||||
<Sidebar.GroupLabel>主要功能</Sidebar.GroupLabel>
|
||||
<Sidebar.GroupContent>
|
||||
<Sidebar.Menu>
|
||||
{#each mainNavItems as item}
|
||||
{#each navMain as item}
|
||||
<Sidebar.MenuItem>
|
||||
<Sidebar.MenuButton
|
||||
isActive={isActive(item.href, $page.url.pathname)}
|
||||
>
|
||||
<Sidebar.MenuButton isActive={isActive(item.href, $page.url.pathname)}>
|
||||
{#snippet child({ props })}
|
||||
<a href={item.href} {...props}>
|
||||
<item.icon class="size-4" />
|
||||
@@ -108,50 +121,41 @@
|
||||
</Sidebar.GroupContent>
|
||||
</Sidebar.Group>
|
||||
|
||||
<Sidebar.Group>
|
||||
<Sidebar.GroupLabel>系统</Sidebar.GroupLabel>
|
||||
<!-- 次级导航 (底部) -->
|
||||
<Sidebar.Group class="mt-auto">
|
||||
<Sidebar.GroupContent>
|
||||
<Sidebar.Menu>
|
||||
<!-- 主题切换 -->
|
||||
<Sidebar.MenuItem>
|
||||
<Sidebar.MenuButton>
|
||||
{#snippet child({ props })}
|
||||
<button {...props} onclick={toggleDarkMode}>
|
||||
{#if darkMode}
|
||||
<Sun class="size-4" />
|
||||
<span>浅色模式</span>
|
||||
{:else}
|
||||
<Moon class="size-4" />
|
||||
<span>深色模式</span>
|
||||
{/if}
|
||||
{@const theme = themeConfig[themeMode]}
|
||||
<button {...props} onclick={cycleTheme}>
|
||||
<theme.icon class="size-4" />
|
||||
<span>{theme.label}</span>
|
||||
</button>
|
||||
{/snippet}
|
||||
</Sidebar.MenuButton>
|
||||
</Sidebar.MenuItem>
|
||||
<Sidebar.MenuItem>
|
||||
<Sidebar.MenuButton>
|
||||
{#snippet child({ props })}
|
||||
<a href="/settings" {...props}>
|
||||
<Settings class="size-4" />
|
||||
<span>设置</span>
|
||||
</a>
|
||||
{/snippet}
|
||||
</Sidebar.MenuButton>
|
||||
</Sidebar.MenuItem>
|
||||
<Sidebar.MenuItem>
|
||||
<Sidebar.MenuButton>
|
||||
{#snippet child({ props })}
|
||||
<a href="/help" {...props}>
|
||||
<HelpCircle class="size-4" />
|
||||
<span>帮助</span>
|
||||
</a>
|
||||
{/snippet}
|
||||
</Sidebar.MenuButton>
|
||||
</Sidebar.MenuItem>
|
||||
|
||||
{#each navSecondary as item}
|
||||
<Sidebar.MenuItem>
|
||||
<Sidebar.MenuButton>
|
||||
{#snippet child({ props })}
|
||||
<a href={item.href} {...props}>
|
||||
<item.icon class="size-4" />
|
||||
<span>{item.label}</span>
|
||||
</a>
|
||||
{/snippet}
|
||||
</Sidebar.MenuButton>
|
||||
</Sidebar.MenuItem>
|
||||
{/each}
|
||||
</Sidebar.Menu>
|
||||
</Sidebar.GroupContent>
|
||||
</Sidebar.Group>
|
||||
</Sidebar.Content>
|
||||
|
||||
<!-- Footer: 用户信息 -->
|
||||
<Sidebar.Footer>
|
||||
<Sidebar.Menu>
|
||||
<Sidebar.MenuItem>
|
||||
@@ -163,13 +167,13 @@
|
||||
class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
|
||||
>
|
||||
<Avatar.Root class="h-8 w-8 rounded-lg">
|
||||
<Avatar.Fallback class="rounded-lg bg-gradient-to-br from-primary to-chart-1 text-primary-foreground">
|
||||
U
|
||||
<Avatar.Fallback class="rounded-lg bg-gradient-to-br from-violet-500 to-purple-600 text-white font-medium">
|
||||
{user.name.charAt(0).toUpperCase()}
|
||||
</Avatar.Fallback>
|
||||
</Avatar.Root>
|
||||
<div class="grid flex-1 text-left text-sm leading-tight">
|
||||
<span class="truncate font-semibold">用户</span>
|
||||
<span class="truncate text-xs text-muted-foreground">user@example.com</span>
|
||||
<span class="truncate font-semibold">{user.name}</span>
|
||||
<span class="truncate text-xs text-muted-foreground">{user.email}</span>
|
||||
</div>
|
||||
<ChevronsUpDown class="ml-auto size-4" />
|
||||
</Sidebar.MenuButton>
|
||||
@@ -184,23 +188,43 @@
|
||||
<DropdownMenu.Label class="p-0 font-normal">
|
||||
<div class="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
|
||||
<Avatar.Root class="h-8 w-8 rounded-lg">
|
||||
<Avatar.Fallback class="rounded-lg bg-gradient-to-br from-primary to-chart-1 text-primary-foreground">
|
||||
U
|
||||
<Avatar.Fallback class="rounded-lg bg-gradient-to-br from-violet-500 to-purple-600 text-white font-medium">
|
||||
{user.name.charAt(0).toUpperCase()}
|
||||
</Avatar.Fallback>
|
||||
</Avatar.Root>
|
||||
<div class="grid flex-1 text-left text-sm leading-tight">
|
||||
<span class="truncate font-semibold">用户</span>
|
||||
<span class="truncate text-xs text-muted-foreground">user@example.com</span>
|
||||
<span class="truncate font-semibold">{user.name}</span>
|
||||
<span class="truncate text-xs text-muted-foreground">{user.email}</span>
|
||||
</div>
|
||||
</div>
|
||||
</DropdownMenu.Label>
|
||||
<DropdownMenu.Separator />
|
||||
<DropdownMenu.Group>
|
||||
<DropdownMenu.Item>
|
||||
<Settings class="mr-2 size-4" />
|
||||
账户设置
|
||||
<Sparkles class="mr-2 size-4" />
|
||||
升级到 Pro
|
||||
</DropdownMenu.Item>
|
||||
</DropdownMenu.Group>
|
||||
<DropdownMenu.Separator />
|
||||
<DropdownMenu.Group>
|
||||
<DropdownMenu.Item>
|
||||
<User class="mr-2 size-4" />
|
||||
账户
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item>
|
||||
<Settings class="mr-2 size-4" />
|
||||
设置
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item>
|
||||
<Bell class="mr-2 size-4" />
|
||||
通知
|
||||
</DropdownMenu.Item>
|
||||
</DropdownMenu.Group>
|
||||
<DropdownMenu.Separator />
|
||||
<DropdownMenu.Item>
|
||||
<LogOut class="mr-2 size-4" />
|
||||
退出登录
|
||||
</DropdownMenu.Item>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Root>
|
||||
</Sidebar.MenuItem>
|
||||
@@ -210,7 +234,7 @@
|
||||
</Sidebar.Root>
|
||||
|
||||
<Sidebar.Inset>
|
||||
<header class="flex h-16 shrink-0 items-center gap-2 border-b px-4">
|
||||
<header class="flex h-14 shrink-0 items-center gap-2 border-b px-4">
|
||||
<Sidebar.Trigger class="-ml-1" />
|
||||
<Separator orientation="vertical" class="mr-2 h-4" />
|
||||
<div class="flex items-center gap-2">
|
||||
@@ -229,7 +253,7 @@
|
||||
</header>
|
||||
|
||||
<main class="flex-1 p-6">
|
||||
{@render children()}
|
||||
{@render children()}
|
||||
</main>
|
||||
</Sidebar.Inset>
|
||||
</Sidebar.Provider>
|
||||
|
||||
Reference in New Issue
Block a user