1551 lines
30 KiB
TypeScript
1551 lines
30 KiB
TypeScript
export interface UserInfo {
|
||
id: number;
|
||
password: string;
|
||
realName: string;
|
||
roles: string[];
|
||
username: string;
|
||
homePath?: string;
|
||
}
|
||
|
||
export const MOCK_USERS: UserInfo[] = [
|
||
{
|
||
id: 0,
|
||
password: '123456',
|
||
realName: 'Vben',
|
||
roles: ['super'],
|
||
username: 'vben',
|
||
},
|
||
{
|
||
id: 1,
|
||
password: '123456',
|
||
realName: 'Admin',
|
||
roles: ['admin'],
|
||
username: 'admin',
|
||
homePath: '/workspace',
|
||
},
|
||
{
|
||
id: 2,
|
||
password: '123456',
|
||
realName: 'Jack',
|
||
roles: ['user'],
|
||
username: 'jack',
|
||
homePath: '/workspace',
|
||
},
|
||
];
|
||
|
||
export const MOCK_CODES = [
|
||
// super
|
||
{
|
||
codes: ['AC_100100', 'AC_100110', 'AC_100120', 'AC_100010'],
|
||
username: 'vben',
|
||
},
|
||
{
|
||
// admin
|
||
codes: ['AC_100010', 'AC_100020', 'AC_100030'],
|
||
username: 'admin',
|
||
},
|
||
{
|
||
// user
|
||
codes: ['AC_1000001', 'AC_1000002'],
|
||
username: 'jack',
|
||
},
|
||
];
|
||
|
||
const dashboardMenus = [
|
||
{
|
||
meta: {
|
||
order: -1,
|
||
title: 'page.dashboard.title',
|
||
},
|
||
name: 'Dashboard',
|
||
path: '/dashboard',
|
||
redirect: '/workspace',
|
||
children: [
|
||
{
|
||
name: 'Workspace',
|
||
path: '/workspace',
|
||
component: '/dashboard/workspace/index',
|
||
meta: {
|
||
affixTab: true,
|
||
title: 'page.dashboard.workspace',
|
||
},
|
||
},
|
||
],
|
||
},
|
||
];
|
||
|
||
const analyticsMenus = [
|
||
{
|
||
meta: {
|
||
order: 2,
|
||
title: '数据分析',
|
||
icon: 'ant-design:bar-chart-outlined',
|
||
},
|
||
name: 'Analytics',
|
||
path: '/analytics',
|
||
redirect: '/analytics/overview',
|
||
children: [
|
||
{
|
||
name: 'AnalyticsOverview',
|
||
path: '/analytics/overview',
|
||
component: '/analytics/overview/index',
|
||
meta: {
|
||
title: '数据概览',
|
||
icon: 'ant-design:dashboard-outlined',
|
||
},
|
||
},
|
||
{
|
||
name: 'AnalyticsTrends',
|
||
path: '/analytics/trends',
|
||
component: '/analytics/trends/index',
|
||
meta: {
|
||
title: '趋势分析',
|
||
icon: 'ant-design:line-chart-outlined',
|
||
},
|
||
},
|
||
{
|
||
name: 'AnalyticsReports',
|
||
path: '/analytics/reports',
|
||
meta: {
|
||
title: '报表',
|
||
icon: 'ant-design:file-text-outlined',
|
||
},
|
||
children: [
|
||
{
|
||
name: 'DailyReport',
|
||
path: '/analytics/reports/daily',
|
||
component: '/analytics/reports/daily',
|
||
meta: {
|
||
title: '日报表',
|
||
},
|
||
},
|
||
{
|
||
name: 'MonthlyReport',
|
||
path: '/analytics/reports/monthly',
|
||
component: '/analytics/reports/monthly',
|
||
meta: {
|
||
title: '月报表',
|
||
},
|
||
},
|
||
{
|
||
name: 'YearlyReport',
|
||
path: '/analytics/reports/yearly',
|
||
component: '/analytics/reports/yearly',
|
||
meta: {
|
||
title: '年报表',
|
||
},
|
||
},
|
||
{
|
||
name: 'CustomReport',
|
||
path: '/analytics/reports/custom',
|
||
component: '/analytics/reports/custom',
|
||
meta: {
|
||
title: '自定义报表',
|
||
},
|
||
},
|
||
],
|
||
},
|
||
],
|
||
},
|
||
];
|
||
|
||
const financeMenus = [
|
||
{
|
||
name: 'FinanceDashboard',
|
||
path: '/dashboard-finance',
|
||
component: '/finance/dashboard/index',
|
||
meta: {
|
||
order: 1,
|
||
title: '📊 财务仪表板',
|
||
icon: 'mdi:chart-box',
|
||
},
|
||
},
|
||
{
|
||
name: 'FinanceTransactions',
|
||
path: '/transactions',
|
||
component: '/finance/transactions/index',
|
||
meta: {
|
||
order: 2,
|
||
title: '💰 交易管理',
|
||
icon: 'mdi:swap-horizontal',
|
||
},
|
||
},
|
||
{
|
||
name: 'FinanceAccounts',
|
||
path: '/accounts',
|
||
component: '/finance/accounts/index',
|
||
meta: {
|
||
order: 3,
|
||
title: '🏦 账户管理',
|
||
icon: 'mdi:account-multiple',
|
||
},
|
||
},
|
||
{
|
||
name: 'FinanceCategories',
|
||
path: '/categories',
|
||
component: '/finance/categories/index',
|
||
meta: {
|
||
order: 4,
|
||
title: '🏷️ 分类管理',
|
||
icon: 'mdi:tag-multiple',
|
||
},
|
||
},
|
||
{
|
||
name: 'FinanceBudgets',
|
||
path: '/budgets',
|
||
component: '/finance/budgets/index',
|
||
meta: {
|
||
order: 5,
|
||
title: '🎯 预算管理',
|
||
icon: 'mdi:target',
|
||
},
|
||
},
|
||
{
|
||
name: 'ReportsAnalytics',
|
||
path: '/reports',
|
||
component: '/finance/reports/index',
|
||
meta: {
|
||
order: 6,
|
||
title: '📈 报表分析',
|
||
icon: 'mdi:chart-line',
|
||
},
|
||
},
|
||
{
|
||
name: 'FinanceTools',
|
||
path: '/tools',
|
||
component: '/finance/tools/index',
|
||
meta: {
|
||
order: 7,
|
||
title: '🛠️ 财务工具',
|
||
icon: 'mdi:tools',
|
||
},
|
||
},
|
||
{
|
||
name: 'FinanceSettings',
|
||
path: '/fin-settings',
|
||
component: '/finance/settings/index',
|
||
meta: {
|
||
order: 8,
|
||
title: '⚙️ 系统设置',
|
||
icon: 'mdi:cog',
|
||
},
|
||
},
|
||
];
|
||
|
||
const createDemosMenus = (role: 'admin' | 'super' | 'user') => {
|
||
const roleWithMenus = {
|
||
admin: {
|
||
component: '/demos/access/admin-visible',
|
||
meta: {
|
||
icon: 'mdi:button-cursor',
|
||
title: 'demos.access.adminVisible',
|
||
},
|
||
name: 'AccessAdminVisibleDemo',
|
||
path: '/demos/access/admin-visible',
|
||
},
|
||
super: {
|
||
component: '/demos/access/super-visible',
|
||
meta: {
|
||
icon: 'mdi:button-cursor',
|
||
title: 'demos.access.superVisible',
|
||
},
|
||
name: 'AccessSuperVisibleDemo',
|
||
path: '/demos/access/super-visible',
|
||
},
|
||
user: {
|
||
component: '/demos/access/user-visible',
|
||
meta: {
|
||
icon: 'mdi:button-cursor',
|
||
title: 'demos.access.userVisible',
|
||
},
|
||
name: 'AccessUserVisibleDemo',
|
||
path: '/demos/access/user-visible',
|
||
},
|
||
};
|
||
|
||
return [
|
||
{
|
||
meta: {
|
||
icon: 'ic:baseline-view-in-ar',
|
||
keepAlive: true,
|
||
order: 1000,
|
||
title: 'demos.title',
|
||
},
|
||
name: 'Demos',
|
||
path: '/demos',
|
||
redirect: '/demos/access',
|
||
children: [
|
||
{
|
||
name: 'AccessDemos',
|
||
path: '/demosaccess',
|
||
meta: {
|
||
icon: 'mdi:cloud-key-outline',
|
||
title: 'demos.access.backendPermissions',
|
||
},
|
||
redirect: '/demos/access/page-control',
|
||
children: [
|
||
{
|
||
name: 'AccessPageControlDemo',
|
||
path: '/demos/access/page-control',
|
||
component: '/demos/access/index',
|
||
meta: {
|
||
icon: 'mdi:page-previous-outline',
|
||
title: 'demos.access.pageAccess',
|
||
},
|
||
},
|
||
{
|
||
name: 'AccessButtonControlDemo',
|
||
path: '/demos/access/button-control',
|
||
component: '/demos/access/button-control',
|
||
meta: {
|
||
icon: 'mdi:button-cursor',
|
||
title: 'demos.access.buttonControl',
|
||
},
|
||
},
|
||
{
|
||
name: 'AccessMenuVisible403Demo',
|
||
path: '/demos/access/menu-visible-403',
|
||
component: '/demos/access/menu-visible-403',
|
||
meta: {
|
||
authority: ['no-body'],
|
||
icon: 'mdi:button-cursor',
|
||
menuVisibleWithForbidden: true,
|
||
title: 'demos.access.menuVisible403',
|
||
},
|
||
},
|
||
roleWithMenus[role],
|
||
],
|
||
},
|
||
],
|
||
},
|
||
];
|
||
};
|
||
|
||
export const MOCK_MENUS = [
|
||
{
|
||
menus: [
|
||
...dashboardMenus,
|
||
...analyticsMenus,
|
||
...financeMenus,
|
||
...createDemosMenus('super'),
|
||
],
|
||
username: 'vben',
|
||
},
|
||
{
|
||
menus: [
|
||
...dashboardMenus,
|
||
...analyticsMenus,
|
||
...financeMenus,
|
||
...createDemosMenus('admin'),
|
||
],
|
||
username: 'admin',
|
||
},
|
||
{
|
||
menus: [
|
||
...dashboardMenus,
|
||
...analyticsMenus,
|
||
...financeMenus,
|
||
...createDemosMenus('user'),
|
||
],
|
||
username: 'jack',
|
||
},
|
||
];
|
||
|
||
export const MOCK_MENU_LIST = [
|
||
{
|
||
id: 1,
|
||
name: 'Workspace',
|
||
status: 1,
|
||
type: 'menu',
|
||
icon: 'mdi:dashboard',
|
||
path: '/workspace',
|
||
component: '/dashboard/workspace/index',
|
||
meta: {
|
||
icon: 'carbon:workspace',
|
||
title: 'page.dashboard.workspace',
|
||
affixTab: true,
|
||
order: 0,
|
||
},
|
||
},
|
||
{
|
||
id: 2,
|
||
meta: {
|
||
icon: 'carbon:settings',
|
||
order: 9997,
|
||
title: 'system.title',
|
||
badge: 'new',
|
||
badgeType: 'normal',
|
||
badgeVariants: 'primary',
|
||
},
|
||
status: 1,
|
||
type: 'catalog',
|
||
name: 'System',
|
||
path: '/system',
|
||
children: [
|
||
{
|
||
id: 201,
|
||
pid: 2,
|
||
path: '/system/menu',
|
||
name: 'SystemMenu',
|
||
authCode: 'System:Menu:List',
|
||
status: 1,
|
||
type: 'menu',
|
||
meta: {
|
||
icon: 'carbon:menu',
|
||
title: 'system.menu.title',
|
||
},
|
||
component: '/system/menu/list',
|
||
children: [
|
||
{
|
||
id: 20_101,
|
||
pid: 201,
|
||
name: 'SystemMenuCreate',
|
||
status: 1,
|
||
type: 'button',
|
||
authCode: 'System:Menu:Create',
|
||
meta: { title: 'common.create' },
|
||
},
|
||
{
|
||
id: 20_102,
|
||
pid: 201,
|
||
name: 'SystemMenuEdit',
|
||
status: 1,
|
||
type: 'button',
|
||
authCode: 'System:Menu:Edit',
|
||
meta: { title: 'common.edit' },
|
||
},
|
||
{
|
||
id: 20_103,
|
||
pid: 201,
|
||
name: 'SystemMenuDelete',
|
||
status: 1,
|
||
type: 'button',
|
||
authCode: 'System:Menu:Delete',
|
||
meta: { title: 'common.delete' },
|
||
},
|
||
],
|
||
},
|
||
{
|
||
id: 202,
|
||
pid: 2,
|
||
path: '/system/dept',
|
||
name: 'SystemDept',
|
||
status: 1,
|
||
type: 'menu',
|
||
authCode: 'System:Dept:List',
|
||
meta: {
|
||
icon: 'carbon:container-services',
|
||
title: 'system.dept.title',
|
||
},
|
||
component: '/system/dept/list',
|
||
children: [
|
||
{
|
||
id: 20_401,
|
||
pid: 201,
|
||
name: 'SystemDeptCreate',
|
||
status: 1,
|
||
type: 'button',
|
||
authCode: 'System:Dept:Create',
|
||
meta: { title: 'common.create' },
|
||
},
|
||
{
|
||
id: 20_402,
|
||
pid: 201,
|
||
name: 'SystemDeptEdit',
|
||
status: 1,
|
||
type: 'button',
|
||
authCode: 'System:Dept:Edit',
|
||
meta: { title: 'common.edit' },
|
||
},
|
||
{
|
||
id: 20_403,
|
||
pid: 201,
|
||
name: 'SystemDeptDelete',
|
||
status: 1,
|
||
type: 'button',
|
||
authCode: 'System:Dept:Delete',
|
||
meta: { title: 'common.delete' },
|
||
},
|
||
],
|
||
},
|
||
],
|
||
},
|
||
{
|
||
id: 9,
|
||
meta: {
|
||
badgeType: 'dot',
|
||
order: 9998,
|
||
title: 'demos.vben.title',
|
||
icon: 'carbon:data-center',
|
||
},
|
||
name: 'Project',
|
||
path: '/vben-admin',
|
||
type: 'catalog',
|
||
status: 1,
|
||
children: [
|
||
{
|
||
id: 901,
|
||
pid: 9,
|
||
name: 'VbenDocument',
|
||
path: '/vben-admin/document',
|
||
component: 'IFrameView',
|
||
type: 'embedded',
|
||
status: 1,
|
||
meta: {
|
||
icon: 'carbon:book',
|
||
iframeSrc: 'https://doc.vben.pro',
|
||
title: 'demos.vben.document',
|
||
},
|
||
},
|
||
{
|
||
id: 902,
|
||
pid: 9,
|
||
name: 'VbenGithub',
|
||
path: '/vben-admin/github',
|
||
component: 'IFrameView',
|
||
type: 'link',
|
||
status: 1,
|
||
meta: {
|
||
icon: 'carbon:logo-github',
|
||
link: 'https://github.com/vbenjs/vue-vben-admin',
|
||
title: 'Github',
|
||
},
|
||
},
|
||
{
|
||
id: 903,
|
||
pid: 9,
|
||
name: 'VbenAntdv',
|
||
path: '/vben-admin/antdv',
|
||
component: 'IFrameView',
|
||
type: 'link',
|
||
status: 0,
|
||
meta: {
|
||
icon: 'carbon:hexagon-vertical-solid',
|
||
badgeType: 'dot',
|
||
link: 'https://ant.vben.pro',
|
||
title: 'demos.vben.antdv',
|
||
},
|
||
},
|
||
],
|
||
},
|
||
{
|
||
id: 10,
|
||
component: '_core/about/index',
|
||
type: 'menu',
|
||
status: 1,
|
||
meta: {
|
||
icon: 'lucide:copyright',
|
||
order: 9999,
|
||
title: 'demos.vben.about',
|
||
},
|
||
name: 'About',
|
||
path: '/about',
|
||
},
|
||
];
|
||
|
||
export function getMenuIds(menus: any[]) {
|
||
const ids: number[] = [];
|
||
menus.forEach((item) => {
|
||
ids.push(item.id);
|
||
if (item.children && item.children.length > 0) {
|
||
ids.push(...getMenuIds(item.children));
|
||
}
|
||
});
|
||
return ids;
|
||
}
|
||
|
||
// ==================== 财务管理数据 ====================
|
||
|
||
// 货币类型
|
||
export interface Currency {
|
||
code: string;
|
||
name: string;
|
||
symbol: string;
|
||
isBase: boolean;
|
||
isActive: boolean;
|
||
}
|
||
|
||
export const MOCK_CURRENCIES: Currency[] = [
|
||
{
|
||
code: 'CNY',
|
||
name: '人民币',
|
||
symbol: '¥',
|
||
isBase: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
code: 'THB',
|
||
name: '泰铢',
|
||
symbol: '฿',
|
||
isBase: false,
|
||
isActive: true,
|
||
},
|
||
{
|
||
code: 'USD',
|
||
name: '美元',
|
||
symbol: '$',
|
||
isBase: false,
|
||
isActive: true,
|
||
},
|
||
];
|
||
|
||
// 汇率历史记录
|
||
export interface ExchangeRate {
|
||
id: number;
|
||
fromCurrency: string;
|
||
toCurrency: string;
|
||
rate: number;
|
||
date: string;
|
||
source: 'api' | 'manual' | 'system';
|
||
}
|
||
|
||
export const MOCK_EXCHANGE_RATES: ExchangeRate[] = [
|
||
// CNY 作为基准货币
|
||
{
|
||
id: 1,
|
||
fromCurrency: 'CNY',
|
||
toCurrency: 'CNY',
|
||
rate: 1,
|
||
date: '2025-10-03',
|
||
source: 'system',
|
||
},
|
||
{
|
||
id: 2,
|
||
fromCurrency: 'CNY',
|
||
toCurrency: 'THB',
|
||
rate: 5,
|
||
date: '2025-10-03',
|
||
source: 'api',
|
||
},
|
||
{
|
||
id: 3,
|
||
fromCurrency: 'CNY',
|
||
toCurrency: 'USD',
|
||
rate: 0.14,
|
||
date: '2025-10-03',
|
||
source: 'api',
|
||
},
|
||
|
||
// THB 换算
|
||
{
|
||
id: 4,
|
||
fromCurrency: 'THB',
|
||
toCurrency: 'CNY',
|
||
rate: 0.2,
|
||
date: '2025-10-03',
|
||
source: 'api',
|
||
},
|
||
{
|
||
id: 5,
|
||
fromCurrency: 'THB',
|
||
toCurrency: 'THB',
|
||
rate: 1,
|
||
date: '2025-10-03',
|
||
source: 'system',
|
||
},
|
||
{
|
||
id: 6,
|
||
fromCurrency: 'THB',
|
||
toCurrency: 'USD',
|
||
rate: 0.028,
|
||
date: '2025-10-03',
|
||
source: 'api',
|
||
},
|
||
|
||
// USD 换算
|
||
{
|
||
id: 7,
|
||
fromCurrency: 'USD',
|
||
toCurrency: 'CNY',
|
||
rate: 7.14,
|
||
date: '2025-10-03',
|
||
source: 'api',
|
||
},
|
||
{
|
||
id: 8,
|
||
fromCurrency: 'USD',
|
||
toCurrency: 'THB',
|
||
rate: 35.7,
|
||
date: '2025-10-03',
|
||
source: 'api',
|
||
},
|
||
{
|
||
id: 9,
|
||
fromCurrency: 'USD',
|
||
toCurrency: 'USD',
|
||
rate: 1,
|
||
date: '2025-10-03',
|
||
source: 'system',
|
||
},
|
||
];
|
||
|
||
// 分类
|
||
export interface Category {
|
||
id: number;
|
||
userId: null | number; // null 表示系统预设
|
||
name: string;
|
||
type: 'expense' | 'income';
|
||
icon: string;
|
||
color: string;
|
||
sortOrder: number;
|
||
isSystem: boolean;
|
||
isActive: boolean;
|
||
}
|
||
|
||
export const MOCK_CATEGORIES: Category[] = [
|
||
// 支出分类 (ID 1-17)
|
||
{
|
||
id: 1,
|
||
userId: null,
|
||
name: '餐饮美食',
|
||
type: 'expense',
|
||
icon: '🍜',
|
||
color: '#ff6b6b',
|
||
sortOrder: 1,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 2,
|
||
userId: null,
|
||
name: '佣金/返佣',
|
||
type: 'expense',
|
||
icon: '💸',
|
||
color: '#4ecdc4',
|
||
sortOrder: 2,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 3,
|
||
userId: null,
|
||
name: '分红',
|
||
type: 'expense',
|
||
icon: '💰',
|
||
color: '#95e1d3',
|
||
sortOrder: 3,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 4,
|
||
userId: null,
|
||
name: '技术/软件',
|
||
type: 'expense',
|
||
icon: '💻',
|
||
color: '#f38181',
|
||
sortOrder: 4,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 5,
|
||
userId: null,
|
||
name: '固定资产',
|
||
type: 'expense',
|
||
icon: '🏠',
|
||
color: '#aa96da',
|
||
sortOrder: 5,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 6,
|
||
userId: null,
|
||
name: '退款',
|
||
type: 'expense',
|
||
icon: '↩️',
|
||
color: '#fcbad3',
|
||
sortOrder: 6,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 7,
|
||
userId: null,
|
||
name: '服务器/技术',
|
||
type: 'expense',
|
||
icon: '🖥️',
|
||
color: '#a8d8ea',
|
||
sortOrder: 7,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 8,
|
||
userId: null,
|
||
name: '工资',
|
||
type: 'expense',
|
||
icon: '💼',
|
||
color: '#ffcccc',
|
||
sortOrder: 8,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 9,
|
||
userId: null,
|
||
name: '借款/转账',
|
||
type: 'expense',
|
||
icon: '🔄',
|
||
color: '#ffd3b6',
|
||
sortOrder: 9,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 10,
|
||
userId: null,
|
||
name: '广告推广',
|
||
type: 'expense',
|
||
icon: '📢',
|
||
color: '#dfe4ea',
|
||
sortOrder: 10,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 11,
|
||
userId: null,
|
||
name: '交通出行',
|
||
type: 'expense',
|
||
icon: '🚗',
|
||
color: '#74b9ff',
|
||
sortOrder: 11,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 12,
|
||
userId: null,
|
||
name: '购物消费',
|
||
type: 'expense',
|
||
icon: '🛍️',
|
||
color: '#fd79a8',
|
||
sortOrder: 12,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 13,
|
||
userId: null,
|
||
name: '娱乐休闲',
|
||
type: 'expense',
|
||
icon: '🎮',
|
||
color: '#fdcb6e',
|
||
sortOrder: 13,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 14,
|
||
userId: null,
|
||
name: '医疗健康',
|
||
type: 'expense',
|
||
icon: '🏥',
|
||
color: '#55efc4',
|
||
sortOrder: 14,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 15,
|
||
userId: null,
|
||
name: '教育学习',
|
||
type: 'expense',
|
||
icon: '📚',
|
||
color: '#a29bfe',
|
||
sortOrder: 15,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 16,
|
||
userId: null,
|
||
name: '房租房贷',
|
||
type: 'expense',
|
||
icon: '🏘️',
|
||
color: '#ff7675',
|
||
sortOrder: 16,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 17,
|
||
userId: null,
|
||
name: '其他支出',
|
||
type: 'expense',
|
||
icon: '📝',
|
||
color: '#b2bec3',
|
||
sortOrder: 99,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
|
||
// 收入分类 (ID 18-23)
|
||
{
|
||
id: 18,
|
||
userId: null,
|
||
name: '工资收入',
|
||
type: 'income',
|
||
icon: '💵',
|
||
color: '#38ada9',
|
||
sortOrder: 1,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 19,
|
||
userId: null,
|
||
name: '奖金',
|
||
type: 'income',
|
||
icon: '🎁',
|
||
color: '#78e08f',
|
||
sortOrder: 2,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 20,
|
||
userId: null,
|
||
name: '投资收益',
|
||
type: 'income',
|
||
icon: '📈',
|
||
color: '#079992',
|
||
sortOrder: 3,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 21,
|
||
userId: null,
|
||
name: '副业收入',
|
||
type: 'income',
|
||
icon: '💡',
|
||
color: '#60a3bc',
|
||
sortOrder: 4,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 22,
|
||
userId: null,
|
||
name: '退款收入',
|
||
type: 'income',
|
||
icon: '↩️',
|
||
color: '#82ccdd',
|
||
sortOrder: 5,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 23,
|
||
userId: null,
|
||
name: '其他收入',
|
||
type: 'income',
|
||
icon: '💰',
|
||
color: '#10ac84',
|
||
sortOrder: 99,
|
||
isSystem: true,
|
||
isActive: true,
|
||
},
|
||
];
|
||
|
||
// 账户
|
||
export interface Account {
|
||
id: number;
|
||
userId: number;
|
||
name: string;
|
||
type:
|
||
| 'alipay'
|
||
| 'bank'
|
||
| 'cash'
|
||
| 'credit_card'
|
||
| 'investment'
|
||
| 'virtual_wallet'
|
||
| 'wechat';
|
||
currency: string;
|
||
balance: number;
|
||
icon: string;
|
||
color: string;
|
||
isActive: boolean;
|
||
}
|
||
|
||
export const MOCK_ACCOUNTS: Account[] = [
|
||
// CNY 账户
|
||
{
|
||
id: 1,
|
||
userId: 1,
|
||
name: '支付宝',
|
||
type: 'alipay',
|
||
currency: 'CNY',
|
||
balance: 5280.5,
|
||
icon: '💙',
|
||
color: '#1677ff',
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 2,
|
||
userId: 1,
|
||
name: '微信钱包',
|
||
type: 'wechat',
|
||
currency: 'CNY',
|
||
balance: 1520.3,
|
||
icon: '💚',
|
||
color: '#07c160',
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 3,
|
||
userId: 1,
|
||
name: '中国银行',
|
||
type: 'bank',
|
||
currency: 'CNY',
|
||
balance: 12_500,
|
||
icon: '🏦',
|
||
color: '#c41e3a',
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 4,
|
||
userId: 1,
|
||
name: '人民币现金',
|
||
type: 'cash',
|
||
currency: 'CNY',
|
||
balance: 800,
|
||
icon: '💵',
|
||
color: '#52c41a',
|
||
isActive: true,
|
||
},
|
||
|
||
// THB 账户
|
||
{
|
||
id: 5,
|
||
userId: 1,
|
||
name: '泰铢现金',
|
||
type: 'cash',
|
||
currency: 'THB',
|
||
balance: 15_000,
|
||
icon: '💵',
|
||
color: '#faad14',
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 6,
|
||
userId: 1,
|
||
name: '泰国银行',
|
||
type: 'bank',
|
||
currency: 'THB',
|
||
balance: 48_000,
|
||
icon: '🏦',
|
||
color: '#722ed1',
|
||
isActive: true,
|
||
},
|
||
|
||
// USD 账户
|
||
{
|
||
id: 7,
|
||
userId: 1,
|
||
name: '美金现金',
|
||
type: 'cash',
|
||
currency: 'USD',
|
||
balance: 500,
|
||
icon: '💵',
|
||
color: '#13c2c2',
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 8,
|
||
userId: 1,
|
||
name: 'PayPal',
|
||
type: 'bank',
|
||
currency: 'USD',
|
||
balance: 1250,
|
||
icon: '💳',
|
||
color: '#0070ba',
|
||
isActive: true,
|
||
},
|
||
|
||
// 虚拟钱包
|
||
{
|
||
id: 9,
|
||
userId: 1,
|
||
name: 'USDT钱包',
|
||
type: 'virtual_wallet',
|
||
currency: 'USD',
|
||
balance: 3000,
|
||
icon: '💎',
|
||
color: '#26a17b',
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 10,
|
||
userId: 1,
|
||
name: 'BTC钱包',
|
||
type: 'virtual_wallet',
|
||
currency: 'USD',
|
||
balance: 0.05,
|
||
icon: '₿',
|
||
color: '#f7931a',
|
||
isActive: true,
|
||
},
|
||
|
||
// 投资账户
|
||
{
|
||
id: 11,
|
||
userId: 1,
|
||
name: '证券账户',
|
||
type: 'investment',
|
||
currency: 'CNY',
|
||
balance: 25_000,
|
||
icon: '📊',
|
||
color: '#eb2f96',
|
||
isActive: true,
|
||
},
|
||
|
||
// 信用卡
|
||
{
|
||
id: 12,
|
||
userId: 1,
|
||
name: '招商银行信用卡',
|
||
type: 'credit_card',
|
||
currency: 'CNY',
|
||
balance: -3500,
|
||
icon: '💳',
|
||
color: '#f5222d',
|
||
isActive: true,
|
||
},
|
||
];
|
||
|
||
// 交易记录
|
||
export interface Transaction {
|
||
id: number;
|
||
userId: number;
|
||
type: 'expense' | 'income' | 'transfer';
|
||
amount: number;
|
||
currency: string;
|
||
exchangeRateToBase: number;
|
||
amountInBase: number;
|
||
categoryId: null | number;
|
||
accountId: number;
|
||
transactionDate: string;
|
||
description: string;
|
||
createdAt: string;
|
||
isDeleted?: boolean;
|
||
deletedAt?: string;
|
||
}
|
||
|
||
interface TransactionSeed {
|
||
type: Transaction['type'];
|
||
amount: number;
|
||
currency: string;
|
||
categoryId: null | number;
|
||
accountId: number;
|
||
transactionDate: string;
|
||
description: string;
|
||
}
|
||
|
||
function getExchangeRateToBase(currency: string) {
|
||
const rate = MOCK_EXCHANGE_RATES.find(
|
||
(item) => item.fromCurrency === currency && item.toCurrency === 'CNY',
|
||
);
|
||
return rate?.rate ?? 1;
|
||
}
|
||
|
||
function normalizeAmount(value: number) {
|
||
return Number(value.toFixed(2));
|
||
}
|
||
|
||
const TRANSACTION_SEEDS: TransactionSeed[] = [
|
||
{
|
||
type: 'income',
|
||
amount: 12_800,
|
||
currency: 'CNY',
|
||
categoryId: 11,
|
||
accountId: 3,
|
||
transactionDate: '2025-10-08',
|
||
description: '十月工资入账',
|
||
},
|
||
{
|
||
type: 'income',
|
||
amount: 2800,
|
||
currency: 'CNY',
|
||
categoryId: 12,
|
||
accountId: 3,
|
||
transactionDate: '2025-10-18',
|
||
description: '季度绩效奖金',
|
||
},
|
||
{
|
||
type: 'income',
|
||
amount: 460,
|
||
currency: 'USD',
|
||
categoryId: 13,
|
||
accountId: 9,
|
||
transactionDate: '2025-10-21',
|
||
description: '股票分红(USD)',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 3850,
|
||
currency: 'CNY',
|
||
categoryId: 8,
|
||
accountId: 3,
|
||
transactionDate: '2025-10-05',
|
||
description: '十月房租支出',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 248.4,
|
||
currency: 'CNY',
|
||
categoryId: 1,
|
||
accountId: 1,
|
||
transactionDate: '2025-10-07',
|
||
description: '家庭聚餐消费',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 612.5,
|
||
currency: 'CNY',
|
||
categoryId: 3,
|
||
accountId: 2,
|
||
transactionDate: '2025-10-11',
|
||
description: '大型超市购物',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 420,
|
||
currency: 'CNY',
|
||
categoryId: 4,
|
||
accountId: 2,
|
||
transactionDate: '2025-10-14',
|
||
description: '娱乐活动(电影+KTV)',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 1350,
|
||
currency: 'CNY',
|
||
categoryId: 7,
|
||
accountId: 3,
|
||
transactionDate: '2025-10-19',
|
||
description: '体检及医疗支出',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 92.6,
|
||
currency: 'CNY',
|
||
categoryId: 2,
|
||
accountId: 1,
|
||
transactionDate: '2025-10-22',
|
||
description: '共享单车与地铁',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 168,
|
||
currency: 'CNY',
|
||
categoryId: 5,
|
||
accountId: 4,
|
||
transactionDate: '2025-10-25',
|
||
description: '云服务与软件订阅',
|
||
},
|
||
{
|
||
type: 'income',
|
||
amount: 4500,
|
||
currency: 'USD',
|
||
categoryId: 14,
|
||
accountId: 9,
|
||
transactionDate: '2025-09-10',
|
||
description: '驻外项目服务费',
|
||
},
|
||
{
|
||
type: 'income',
|
||
amount: 12_650,
|
||
currency: 'CNY',
|
||
categoryId: 11,
|
||
accountId: 3,
|
||
transactionDate: '2025-09-08',
|
||
description: '九月工资入账',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 3720,
|
||
currency: 'CNY',
|
||
categoryId: 8,
|
||
accountId: 3,
|
||
transactionDate: '2025-09-05',
|
||
description: '九月房租支出',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 520.8,
|
||
currency: 'CNY',
|
||
categoryId: 1,
|
||
accountId: 1,
|
||
transactionDate: '2025-09-09',
|
||
description: '中秋家庭聚餐',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 980,
|
||
currency: 'CNY',
|
||
categoryId: 6,
|
||
accountId: 11,
|
||
transactionDate: '2025-09-15',
|
||
description: '指数基金定投',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 312,
|
||
currency: 'CNY',
|
||
categoryId: 3,
|
||
accountId: 2,
|
||
transactionDate: '2025-09-18',
|
||
description: '电商平台日常用品',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 1500,
|
||
currency: 'CNY',
|
||
categoryId: 9,
|
||
accountId: 3,
|
||
transactionDate: '2025-09-20',
|
||
description: '孩子辅导课程',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 108.6,
|
||
currency: 'CNY',
|
||
categoryId: 2,
|
||
accountId: 2,
|
||
transactionDate: '2025-09-22',
|
||
description: '地铁月度充值',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 65,
|
||
currency: 'THB',
|
||
categoryId: 1,
|
||
accountId: 5,
|
||
transactionDate: '2025-09-26',
|
||
description: '曼谷街头小吃',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 210,
|
||
currency: 'USD',
|
||
categoryId: 5,
|
||
accountId: 8,
|
||
transactionDate: '2025-09-28',
|
||
description: '年度生产力工具订阅',
|
||
},
|
||
{
|
||
type: 'income',
|
||
amount: 12_580,
|
||
currency: 'CNY',
|
||
categoryId: 11,
|
||
accountId: 3,
|
||
transactionDate: '2025-08-08',
|
||
description: '八月工资入账',
|
||
},
|
||
{
|
||
type: 'income',
|
||
amount: 2150,
|
||
currency: 'CNY',
|
||
categoryId: 13,
|
||
accountId: 11,
|
||
transactionDate: '2025-08-16',
|
||
description: '理财产品收益',
|
||
},
|
||
{
|
||
type: 'income',
|
||
amount: 320,
|
||
currency: 'USD',
|
||
categoryId: 15,
|
||
accountId: 9,
|
||
transactionDate: '2025-08-24',
|
||
description: '海外二手交易收入',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 3680,
|
||
currency: 'CNY',
|
||
categoryId: 8,
|
||
accountId: 3,
|
||
transactionDate: '2025-08-05',
|
||
description: '八月房租支出',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 452.3,
|
||
currency: 'CNY',
|
||
categoryId: 1,
|
||
accountId: 1,
|
||
transactionDate: '2025-08-07',
|
||
description: '工作日餐饮',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 275.4,
|
||
currency: 'CNY',
|
||
categoryId: 4,
|
||
accountId: 2,
|
||
transactionDate: '2025-08-12',
|
||
description: '家庭周末娱乐',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 860,
|
||
currency: 'CNY',
|
||
categoryId: 6,
|
||
accountId: 11,
|
||
transactionDate: '2025-08-15',
|
||
description: '基金定投计划',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 1999,
|
||
currency: 'CNY',
|
||
categoryId: 3,
|
||
accountId: 3,
|
||
transactionDate: '2025-08-18',
|
||
description: '家用电器采购',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 145,
|
||
currency: 'CNY',
|
||
categoryId: 2,
|
||
accountId: 2,
|
||
transactionDate: '2025-08-20',
|
||
description: '外出交通打车',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 72,
|
||
currency: 'USD',
|
||
categoryId: 5,
|
||
accountId: 8,
|
||
transactionDate: '2025-08-23',
|
||
description: '云服务增值包',
|
||
},
|
||
{
|
||
type: 'income',
|
||
amount: 12_480,
|
||
currency: 'CNY',
|
||
categoryId: 11,
|
||
accountId: 3,
|
||
transactionDate: '2025-07-08',
|
||
description: '七月工资入账',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 3680,
|
||
currency: 'CNY',
|
||
categoryId: 8,
|
||
accountId: 3,
|
||
transactionDate: '2025-07-05',
|
||
description: '七月房租支出',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 1299,
|
||
currency: 'CNY',
|
||
categoryId: 3,
|
||
accountId: 1,
|
||
transactionDate: '2025-07-12',
|
||
description: '暑期家庭购物',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 420,
|
||
currency: 'CNY',
|
||
categoryId: 4,
|
||
accountId: 2,
|
||
transactionDate: '2025-07-18',
|
||
description: '亲子乐园娱乐',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 960,
|
||
currency: 'CNY',
|
||
categoryId: 9,
|
||
accountId: 3,
|
||
transactionDate: '2025-07-22',
|
||
description: '暑期培训课程',
|
||
},
|
||
{
|
||
type: 'income',
|
||
amount: 1800,
|
||
currency: 'CNY',
|
||
categoryId: 14,
|
||
accountId: 2,
|
||
transactionDate: '2025-07-25',
|
||
description: '副业项目结算',
|
||
},
|
||
{
|
||
type: 'expense',
|
||
amount: 288,
|
||
currency: 'THB',
|
||
categoryId: 1,
|
||
accountId: 5,
|
||
transactionDate: '2025-07-27',
|
||
description: '泰国商务餐饮',
|
||
},
|
||
{
|
||
type: 'income',
|
||
amount: 520,
|
||
currency: 'USD',
|
||
categoryId: 13,
|
||
accountId: 9,
|
||
transactionDate: '2025-07-30',
|
||
description: '海外理财收益',
|
||
},
|
||
];
|
||
|
||
export const MOCK_TRANSACTIONS: Transaction[] = TRANSACTION_SEEDS.map(
|
||
(seed, index) => {
|
||
const exchangeRate = getExchangeRateToBase(seed.currency);
|
||
const amountInBase = normalizeAmount(seed.amount * exchangeRate);
|
||
|
||
return {
|
||
id: index + 1,
|
||
userId: 1,
|
||
type: seed.type,
|
||
amount: normalizeAmount(seed.amount),
|
||
currency: seed.currency,
|
||
exchangeRateToBase: normalizeAmount(exchangeRate),
|
||
amountInBase,
|
||
categoryId: seed.categoryId,
|
||
accountId: seed.accountId,
|
||
transactionDate: seed.transactionDate,
|
||
description: seed.description,
|
||
createdAt: `${seed.transactionDate}T09:00:00.000Z`,
|
||
};
|
||
},
|
||
);
|
||
|
||
// 预算管理
|
||
export interface Budget {
|
||
id: number;
|
||
userId: number;
|
||
category: string;
|
||
categoryId?: number;
|
||
emoji: string;
|
||
limit: number;
|
||
spent: number;
|
||
remaining: number;
|
||
percentage: number;
|
||
currency: string;
|
||
period: 'monthly' | 'quarterly' | 'weekly' | 'yearly';
|
||
alertThreshold: number;
|
||
description?: string;
|
||
autoRenew: boolean;
|
||
overspendAlert: boolean;
|
||
dailyReminder: boolean;
|
||
monthlyTrend?: number;
|
||
createdAt: string;
|
||
isDeleted?: boolean;
|
||
deletedAt?: string;
|
||
}
|
||
|
||
export const MOCK_BUDGETS: Budget[] = [];
|