feat: 设置页新增分区目录导航并支持 URL 锚点,统计面板图表点击跳转可关闭

设置页由单一长列表改为「目录 + 分区」结构:桌面左侧吸附目录、小屏/平板顶部横向条目条,点击可平滑定位并同步 URL 锚点(支持 /settings#<slug> 深链与浏览器前进后退);同时为统计面板图表补充用户级「点击跳转明细」开关(默认开启),面板与设置页两处入口实时联动。

变更内容:
- 设置页目录导航:Settings.vue 分区 slug 化,点击 push / 滚动 replace 同步 URL,显式跳转期间暂停滚动联动并用 ResizeObserver 持续对齐、用户主动滚动后解除;修复悬停样式覆盖高亮、并让选中项自动滚入视野;Layout.vue 在 route.hash 非空时跳过滚动位置恢复;router 对同路径纯 hash 变更提前放行;messages.ts 新增目录三语文案。
- 统计面板图表点击开关:后端新增用户级偏好 `chartClickNavigation`(DTO/Controller/Service,未配置默认开启);前端共享 composable `useChartClickNavigation`;Dashboard.vue 增加关闭守卫、提示显隐与光标联动及面板快捷开关;DisplayConfigPanel.vue 新增开关;messages.ts 新增三语文案。
- 说明:复用通用键值表 t_user_preference,不改动建表脚本与实体/Mapper;未配置默认开启,老用户无感知。
This commit is contained in:
2026-10-13 17:42:08 +08:00
parent 4aeeaac94f
commit bfd314a38e
12 changed files with 627 additions and 18 deletions
@@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.RestController;
import cn.rosercode.ledgerly.common.Result;
import cn.rosercode.ledgerly.dto.BillSourceStatsRequest;
import cn.rosercode.ledgerly.dto.ChartClickNavigationRequest;
import cn.rosercode.ledgerly.dto.ExcludedDisplayStyleRequest;
import cn.rosercode.ledgerly.dto.NavMenuPrefsRequest;
import cn.rosercode.ledgerly.dto.PaginationPrefsRequest;
@@ -116,6 +117,32 @@ public class UserSettingController {
return Result.success(userPreferenceService.getShowHiddenData(userId));
}
/**
* 查询当前用户是否启用统计面板图表的点击跳转明细,未配置时默认开启。
*
* @return true-启用点击跳转,false-关闭点击跳转
*/
@GetMapping("/chart-click-navigation")
@Operation(summary = "查询图表点击跳转偏好", description = "读取当前用户是否启用统计面板图表的点击跳转明细,未配置时默认开启")
public Result<Boolean> getChartClickNavigation() {
return Result.success(userPreferenceService.getChartClickNavigation(UserContext.getUserId()));
}
/**
* 更新当前用户是否启用统计面板图表的点击跳转明细。
*
* @param request 图表点击跳转偏好更新请求
* @return 更新后的图表点击跳转偏好
*/
@PutMapping("/chart-click-navigation")
@Operation(summary = "更新图表点击跳转偏好", description = "设置当前用户是否启用统计面板图表的点击跳转明细")
public Result<Boolean> updateChartClickNavigation(@RequestBody ChartClickNavigationRequest request) {
Long userId = UserContext.getUserId();
boolean enabled = !Boolean.FALSE.equals(request.getEnabled());
userPreferenceService.saveChartClickNavigation(userId, enabled);
return Result.success(userPreferenceService.getChartClickNavigation(userId));
}
/**
* 查询当前用户配置的表格分页偏好。
*
@@ -0,0 +1,15 @@
package cn.rosercode.ledgerly.dto;
import lombok.Data;
/**
* 「图表点击跳转明细」偏好更新请求对象,控制统计面板图表元素点击后是否跳转收支记录页。
*
* @date 2026-10-13 12:50:04
*/
@Data
public class ChartClickNavigationRequest {
/** 是否启用图表点击跳转明细(默认开启) */
private Boolean enabled;
}
@@ -60,6 +60,22 @@ public interface UserPreferenceService {
*/
void saveShowHiddenData(Long userId, boolean show);
/**
* 获取当前用户是否启用统计面板图表的点击跳转明细,未配置时回退默认值(开启)。
*
* @param userId 用户ID
* @return true-启用点击跳转,false-关闭点击跳转
*/
boolean getChartClickNavigation(Long userId);
/**
* 保存当前用户是否启用统计面板图表的点击跳转明细。
*
* @param userId 用户ID
* @param enabled 是否启用点击跳转
*/
void saveChartClickNavigation(Long userId, boolean enabled);
/**
* 获取当前用户配置的表格分页偏好(每页条数候选列表与默认每页条数),未配置或非法时回退默认值。
*
@@ -53,6 +53,9 @@ public class UserPreferenceServiceImpl implements UserPreferenceService {
/** 偏好键:侧边导航菜单偏好(顺序与显隐) */
private static final String KEY_NAV_MENU = "navMenu";
/** 偏好键:统计面板图表点击是否跳转明细 */
private static final String KEY_CHART_CLICK_NAVIGATION = "chartClickNavigation";
/** 导航菜单项数量上限,避免异常数据无限增长 */
private static final int MAX_NAV_MENU_ITEMS = 100;
@@ -177,6 +180,31 @@ public class UserPreferenceServiceImpl implements UserPreferenceService {
log.info("保存隐藏备注记录显示偏好: userId={}, show={}", userId, show);
}
/**
* {@inheritDoc}
*
* 结果按用户缓存,未配置时默认开启点击跳转。
*/
@Override
@Cacheable(cacheNames = CacheConfig.USER_PREFERENCE_CACHE, key = "'chartClickNavigation:' + #userId")
public boolean getChartClickNavigation(Long userId) {
String value = findValue(userId, KEY_CHART_CLICK_NAVIGATION);
// 未配置时默认开启,仅显式为 "false" 时才关闭
return value == null || Boolean.parseBoolean(value);
}
/**
* {@inheritDoc}
*
* 保存后失效该用户的图表点击跳转缓存。
*/
@Override
@CacheEvict(cacheNames = CacheConfig.USER_PREFERENCE_CACHE, key = "'chartClickNavigation:' + #userId")
public void saveChartClickNavigation(Long userId, boolean enabled) {
upsert(userId, KEY_CHART_CLICK_NAVIGATION, Boolean.toString(enabled));
log.info("保存图表点击跳转偏好: userId={}, enabled={}", userId, enabled);
}
/**
* {@inheritDoc}
*