feat: 用户级偏好配置与外观设置,枚举统一抽取与账单类型后端下发

- 新增用户偏好表 t_user_preference 与进程内缓存,账单来源统计默认值由全局改为按用户存储(/api/setting)
- 新增外观设置:不计入统计记录支持删除线与灰色标签两种展示样式
- 抽取 ChannelType / TransactionType / StatisticsScope 枚举,替换各处硬编码的渠道、类型与统计口径
- BillType 内聚各来源扩展名,新增 /transaction/import/types 接口,前端改为按后端下发渲染
- 仪表盘趋势图支持点击柱子跳转收支记录并带入筛选条件
- 布局内容区按路由记忆滚动位置;已登录访问登录/注册页自动跳转
This commit is contained in:
2026-09-21 10:51:15 +08:00
parent 2976b85967
commit 1f520f4376
46 changed files with 1565 additions and 284 deletions
+13 -1
View File
@@ -126,6 +126,19 @@ router.beforeEach(async (to, _from, next) => {
return
}
// 已登录用户访问登录/注册页时,自动跳转到回跳地址或首页
const userStore = useUserStore()
if ((to.path === '/login' || to.path === '/register') && userStore.token) {
// 仅允许站内路径回跳,避免开放重定向
const redirect = Array.isArray(to.query.redirect) ? to.query.redirect[0] : to.query.redirect
const target =
typeof redirect === 'string' && redirect.startsWith('/') && !redirect.startsWith('//')
? redirect
: '/dashboard'
next(target)
return
}
// 注册功能关闭且已有用户时,不允许访问注册页
if (to.path === '/register') {
const registrationStore = useRegistrationStore()
@@ -138,7 +151,6 @@ router.beforeEach(async (to, _from, next) => {
}
}
const userStore = useUserStore()
// 如果目标页面不是登录/注册页,且没有 token,则重定向到登录页并记录来源,登录后可回跳
if (to.path !== '/login' && to.path !== '/register' && !userStore.token) {
next({ path: '/login', query: { redirect: to.fullPath } })