+
+
+
WORTHPATH / {today()}
+
{p ? p.name : labels[page]}
+
+ {page === 'overview'
+ ? '你的财富全貌,从这里开始。'
+ : page === 'settings'
+ ? '让数据始终可控,让换算清晰可靠。'
+ : '保留原币金额,追踪长期变化。'}
+
+
+ {['overview', 'account', 'asset', 'debt'].includes(page) && !p && newAction}
+
+ {error && (
+
+ {error}
+
+
+ )}
+ {success && (
+
+ {success}
+
+
+ )}
+ {loading && (
+
+ 正在刷新数据…
+
+ )}
+ {page === 'overview' && overview && (
+ <>
+ {!overview.complete && (
+
+ 缺少 {overview.missing.join('、')} 到 {user.baseCurrency}{' '}
+ 的汇率。以下仅展示已能换算的部分,不能作为完整总额。
+
+
+ )}
+
+ {[
+ ['总资产', overview.assets, 'asset'],
+ ['总负债', overview.liabilities, 'debt'],
+ ['净资产', overview.net, 'net'],
+ ].map(([title, value, cls]) => (
+
+
+
+ {title}
+ {!overview.complete ? '(部分)' : ''}
+
+
+
+ {money(value, user.baseCurrency)}
+
+ {title === '净资产'
+ ? '总资产 − 总负债'
+ : title === '总资产'
+ ? '账户资产 + 独立资产'
+ : '负债账户 + 独立债务'}
+
+
+ ))}
+
+
+
+
+
净资产轨迹
+ 按业务日期
+
+
+ 按当时可用汇率重放;更正历史后重新计算。归档项目仍计入。
+
+
+ 资产与负债组成
+ {positions.length ? (
+ ['account', 'asset', 'debt'].map((k) => (
+
+ ))
+ ) : (
+
+ )}
+
+
+ 关联关系不会重复计入总额
+
+
+
+
+
+
最近变化
+
+
+ {
+ setSelected(id);
+ setPage(positions.find((p) => p.id === id)?.kind || 'account');
+ }}
+ />
+
+
+ 本位币 {user.baseCurrency} · 汇率日期:
+ {[
+ ...new Set(
+ overview.items
+ .filter((i) => i.currency !== user.baseCurrency && i.rateDate)
+ .map((i) => i.rateDate),
+ ),
+ ].join(' / ') || '尚无外币汇率'}{' '}
+ · 每日尝试更新,失败保留已有数据;旧日期汇率可能产生换算偏差。
+
+ {overview.trend.length > 1 && (
+
+ 变化归因
+
+
+
+
+ | 日期 |
+ 余额 / 估值变化 |
+ 汇率变化 |
+ 净资产 |
+
+
+
+ {overview.trend.slice(-10).map((r) => (
+
+ | {r.date} |
+
+ {r.balanceChange === null || r.balanceChange === undefined
+ ? '—'
+ : money(r.balanceChange, user.baseCurrency)}
+ |
+
+ {r.fxChange === null || r.fxChange === undefined
+ ? '—'
+ : money(r.fxChange, user.baseCurrency)}
+ |
+ {r.complete ? money(r.net, user.baseCurrency) : '汇率不完整'} |
+
+ ))}
+
+
+
+
+ )}
+ >
+ )}
+ {['account', 'asset', 'debt'].includes(page) &&
+ (p ? (
+ <>
+
+
+
+
+ {categoryLabel(p)} · {p.side === 'asset' ? '资产' : '负债'}
+ {p.archived ? ' · 已归档' : ''}
+
+
{money(p.amount, p.currency)}
+
+ 本位币:
+ {overview?.items.find((i) => i.id === p.id)?.converted !== null
+ ? money(
+ overview?.items.find((i) => i.id === p.id)?.converted || '0',
+ user.baseCurrency,
+ )
+ : '缺少汇率'}
+
+
{p.notes || '暂无备注'}
+
币种和资产负债属性创建后固定。归档项目仍计入总览。
+
+
+
+
+
+
+
+ {p.kind === 'debt' && (
+
+
+
关联资产与账户
+
+
+ 只展示关系,不改变资产或债务的统计。
+ {p.outgoing.length ? (
+ p.outgoing.map((l) => (
+
+ ))
+ ) : (
+ 尚未关联
+ )}
+
+ )}
+
+ 余额与估值历史
+
+ 每次更新保留独立历史,同日按记录顺序展示。错误记录可单独更正,后续变化自动重算。
+
+ setModal({ kind: 'correction', p, h })}
+ />
+
+ >
+ ) : (
+
+ {positions.some((p) => p.kind === page) ? (
+
+ {positions
+ .filter((p) => p.kind === page)
+ .map((p) => (
+
+ ))}
+
+ ) : (
+
+ )}
+
+ ))}
+ {page === 'history' && (
+
+ 全部金额变化
+ 原币绝对余额记录;负债减少即还款。选择项目可查看详情并更正。
+ p.history)
+ .sort((a, b) => b.date.localeCompare(a.date) || b.sequence - a.sequence)}
+ open={(id) => {
+ setSelected(id);
+ setPage(positions.find((p) => p.id === id)?.kind || 'account');
+ }}
+ />
+
+ )}
+ {page === 'settings' && (
+ <>
+
+
+
+
本位币与个人设置
+
+
+
+ 账号:{user.username}。切换本位币会重新换算整个历史,原币数据保留。
+
+
+
+
+ 每日汇率
+ {fxStatus && (
+
+ {fxStatus.message}
+ {fxStatus.attemptedAt
+ ? ' · ' +
+ new Date(fxStatus.attemptedAt).toLocaleString('zh-CN', {
+ timeZone: 'Asia/Hong_Kong',
+ })
+ : ''}
+
+ )}
+
+ 服务器每小时检查当日是否已尝试更新。外部请求固定下载公共汇率表,不发送个人数据。失败保留已有汇率,可手动录入。
+
+
+
+ 公共参考汇率可能与银行成交价不同;休市日日期可能滞后。
+
+
+
+ 已保存汇率
+ {rates.length ? (
+
+
+
+
+ | 原币 → 本位币 |
+ 汇率 |
+ 日期 |
+ 来源 |
+
+
+
+ {rates.slice(0, 100).map((r) => (
+
+ |
+ {r.currency} → {r.baseCurrency}
+ |
+ {r.rate} |
+ {r.date.slice(0, 10)} |
+ {r.source === 'manual' ? '手动' : 'Frankfurter'} |
+
+ ))}
+
+
+
+ ) : (
+
+ )}
+
+
+ 数据备份与恢复
+
+ 可读的版本化
+ JSON,包括项目、历史、关联、币种和汇率;不包含任何认证凭据。备份含个人财务信息,请妥善保管。
+
+
+
setSuccess('备份下载请求已发起,请检查浏览器下载列表')}
+ >
+
+ 下载我的数据备份
+
+
+
+ {preview && (
+
+
导入预览
+
+ {preview.positions} 个项目 · {preview.revisions} 条历史 · {preview.rates}{' '}
+ 条汇率
+
+
+ 备份本位币 {preview.baseCurrency} / 当前本位币 {preview.currentBaseCurrency}
+
+
{preview.message}
+
+
+
+ )}
+
+ >
+ )}
+
+
+