diff --git a/doc/WebSocket权限实时推送技术方案设计.md b/doc/WebSocket权限实时推送技术方案设计.md new file mode 100644 index 0000000..f329d7e --- /dev/null +++ b/doc/WebSocket权限实时推送技术方案设计.md @@ -0,0 +1,727 @@ +# WebSocket权限实时推送技术方案设计 + +## 📋 项目背景 + +在当前的权限管理系统中,管理员修改用户权限后,用户需要重新登录才能获得最新权限,这严重影响了用户体验。为了解决这个问题,我们设计了基于WebSocket的权限实时推送方案,让权限变更能够立即生效。 + +## 🎯 整体架构设计 + +### 系统架构图 +``` +┌─────────────────┐ WebSocket ┌─────────────────┐ 数据库操作 ┌─────────────────┐ +│ 前端应用 │ ←──────────→ │ Spring Boot │ ←──────────→ │ MySQL数据库 │ +│ │ │ 后端服务 │ │ │ +│ - 权限缓存 │ │ - WebSocket服务 │ │ - 用户权限表 │ +│ - 实时更新 │ │ - 权限管理 │ │ - 权限变更记录 │ +│ - 用户界面 │ │ - 消息推送 │ │ │ +└─────────────────┘ └─────────────────┘ └─────────────────┘ +``` + +### 核心目标 +- ✅ 权限变更实时生效,无需重新登录 +- ✅ 支持多标签页同步更新 +- ✅ 安全可靠的消息推送机制 +- ✅ 良好的用户体验和性能表现 + +## 🔧 后端技术方案设计 + +### 1. WebSocket服务架构 + +#### 1.1 技术栈选择 +``` +Spring Boot + Spring WebSocket + SaToken + Redis + MySQL +``` + +#### 1.2 核心组件设计 +``` +┌── WebSocket管理层 +│ ├── WebSocketConfig (配置) +│ ├── WebSocketHandler (连接处理) +│ └── WebSocketInterceptor (权限验证) +│ +├── 权限推送服务层 +│ ├── PermissionPushService (权限推送核心服务) +│ ├── UserSessionManager (用户会话管理) +│ └── MessageBroadcaster (消息广播器) +│ +├── 权限监听层 +│ ├── PermissionChangeListener (权限变更监听) +│ ├── RoleChangeListener (角色变更监听) +│ └── MenuChangeListener (菜单变更监听) +│ +└── 数据存储层 + ├── Redis (会话存储 + 消息队列) + └── MySQL (权限数据 + 变更记录) +``` + +### 2. 核心服务设计 + +#### 2.1 WebSocket连接管理 +```java +// 连接管理策略 +- 用户登录后自动建立WebSocket连接 +- 一个用户可以有多个连接(多标签页支持) +- 连接断开后自动重连机制 +- 连接状态持久化到Redis + +// 会话存储结构 +Key: "websocket:user:{userId}" +Value: { + "connections": [ + { + "sessionId": "session-123", + "connectTime": 1640995200000, + "lastHeartbeat": 1640995800000, + "browser": "Chrome", + "ip": "192.168.1.100" + } + ] +} +``` + +#### 2.2 权限变更监听机制 +```java +// 监听触发点 +1. 用户角色分配/取消 +2. 角色权限修改 +3. 菜单权限调整 +4. 用户状态变更 + +// 变更事件设计 +@EventListener +public class PermissionChangeListener { + // 用户角色变更 + @Async + public void handleUserRoleChange(UserRoleChangeEvent event) + + // 角色权限变更 + @Async + public void handleRolePermissionChange(RolePermissionChangeEvent event) + + // 菜单权限变更 + @Async + public void handleMenuPermissionChange(MenuPermissionChangeEvent event) +} +``` + +#### 2.3 消息推送策略 +```java +// 消息类型设计 +enum MessageType { + PERMISSION_UPDATE, // 权限更新 + ROLE_CHANGE, // 角色变更 + FORCE_LOGOUT, // 强制退出 + SYSTEM_NOTICE // 系统通知 +} + +// 推送策略 +1. 精准推送:只推送给受影响的用户 +2. 批量推送:角色权限变更时推送给该角色的所有用户 +3. 广播推送:系统级权限调整时推送给所有在线用户 +``` + +### 3. 数据库设计扩展 + +#### 3.1 权限变更记录表 +```sql +CREATE TABLE sys_permission_change_log ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + change_type VARCHAR(50) NOT NULL, -- USER_ROLE, ROLE_PERMISSION, MENU_PERMISSION + target_user_id BIGINT, -- 目标用户ID(如果是用户级变更) + target_role_id BIGINT, -- 目标角色ID(如果是角色级变更) + operator_id BIGINT NOT NULL, -- 操作者ID + change_detail JSON, -- 变更详情 + create_time DATETIME DEFAULT CURRENT_TIMESTAMP, + INDEX idx_user_time (target_user_id, create_time), + INDEX idx_role_time (target_role_id, create_time) +); +``` + +#### 3.2 WebSocket会话表 +```sql +CREATE TABLE sys_websocket_session ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + user_id BIGINT NOT NULL, + session_id VARCHAR(100) NOT NULL UNIQUE, + connect_time DATETIME NOT NULL, + disconnect_time DATETIME, + client_info JSON, -- 客户端信息 + status TINYINT DEFAULT 1, -- 1:连接中 0:已断开 + INDEX idx_user_status (user_id, status) +); +``` + +### 4. 后端核心接口设计 + +#### 4.1 WebSocket端点配置 +```java +@Configuration +@EnableWebSocket +public class WebSocketConfig implements WebSocketConfigurer { + + @Override + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + registry.addHandler(new PermissionWebSocketHandler(), "/ws/permission") + .setAllowedOrigins("*") + .addInterceptors(new WebSocketAuthInterceptor()); + } +} +``` + +#### 4.2 权限推送服务接口 +```java +@Component +public class PermissionPushService { + + /** + * 推送权限更新消息给指定用户 + */ + public void pushPermissionUpdate(Long userId, List newPermissions); + + /** + * 推送角色变更消息给指定用户 + */ + public void pushRoleChange(Long userId, List newRoles); + + /** + * 批量推送权限更新(角色权限变更时) + */ + public void batchPushPermissionUpdate(Long roleId, List newPermissions); + + /** + * 强制用户下线 + */ + public void forceUserLogout(Long userId, String reason); +} +``` + +#### 4.3 消息格式定义 +```java +@Data +public class WebSocketMessage { + private String type; // 消息类型 + private Long userId; // 目标用户ID + private Long timestamp; // 时间戳 + private Object data; // 消息数据 + private String messageId; // 消息ID + private String operator; // 操作者 +} + +@Data +public class PermissionUpdateData { + private List permissions; // 新权限列表 + private List roles; // 新角色列表 + private String updateType; // 更新类型:ADD, REMOVE, REPLACE + private String reason; // 变更原因 +} +``` + +## 🌐 前端技术方案设计 + +### 1. WebSocket客户端架构 + +#### 1.1 技术栈 +``` +Vue3 + TypeScript + Pinia + WebSocket API +``` + +#### 1.2 组件设计 +``` +┌── WebSocket管理层 +│ ├── WebSocketService (核心WebSocket服务) +│ ├── ConnectionManager (连接管理器) +│ └── MessageHandler (消息处理器) +│ +├── 权限更新层 +│ ├── PermissionUpdateService (权限更新服务) +│ ├── PermissionSyncManager (权限同步管理) +│ └── PermissionNotification (权限通知) +│ +└── 用户界面层 + ├── PermissionUpdateNotify (权限更新提示组件) + ├── ConnectionStatus (连接状态组件) + └── WebSocketDebugPanel (调试面板) +``` + +### 2. WebSocket服务设计 + +#### 2.1 连接管理策略 +```typescript +class WebSocketService { + // 连接策略 + - 用户登录成功后自动连接 + - 连接断开后指数退避重连 + - 页面可见性变化时管理连接 + - 网络状态变化时重连 + + // 连接状态管理 + enum ConnectionState { + DISCONNECTED = 'disconnected', + CONNECTING = 'connecting', + CONNECTED = 'connected', + RECONNECTING = 'reconnecting', + ERROR = 'error' + } +} +``` + +#### 2.2 消息处理机制 +```typescript +// 消息类型定义 +interface WebSocketMessage { + type: 'PERMISSION_UPDATE' | 'ROLE_CHANGE' | 'FORCE_LOGOUT' | 'SYSTEM_NOTICE' + userId: number + timestamp: number + data: any + messageId: string +} + +// 消息处理器 +class MessageHandler { + handlePermissionUpdate() // 处理权限更新 + handleRoleChange() // 处理角色变更 + handleForceLogout() // 处理强制退出 + handleSystemNotice() // 处理系统通知 +} +``` + +### 3. 权限同步机制 + +#### 3.1 同步策略 +```typescript +class PermissionSyncManager { + // 同步时机 + 1. 收到权限更新消息时立即同步 + 2. 连接重建后检查权限版本 + 3. 页面激活时检查权限一致性 + + // 同步方式 + async syncPermissions(updateType: string) { + // 1. 请求最新权限数据 + // 2. 更新本地权限缓存 + // 3. 触发UI重新渲染 + // 4. 显示权限更新通知 + } +} +``` + +#### 3.2 冲突处理 +```typescript +// 权限冲突处理策略 +1. 权限被收回:立即隐藏相关UI,显示权限不足提示 +2. 权限被授予:立即显示新的功能按钮,显示权限获得提示 +3. 强制退出:清理本地数据,跳转到登录页 +4. 操作中断:保存用户操作状态,权限恢复后继续 +``` + +### 4. 前端核心服务设计 + +#### 4.1 WebSocket服务接口 +```typescript +export interface IWebSocketService { + // 连接管理 + connect(): Promise + disconnect(): void + reconnect(): Promise + + // 消息发送 + sendMessage(message: WebSocketMessage): void + + // 事件监听 + onMessage(callback: (message: WebSocketMessage) => void): void + onConnected(callback: () => void): void + onDisconnected(callback: () => void): void + onError(callback: (error: Error) => void): void + + // 状态查询 + isConnected(): boolean + getConnectionState(): ConnectionState +} +``` + +#### 4.2 权限更新服务接口 +```typescript +export interface IPermissionUpdateService { + // 权限同步 + syncPermissions(): Promise + updateLocalPermissions(permissions: string[]): void + + // 通知管理 + showPermissionUpdateNotification(updateInfo: PermissionUpdateInfo): void + showPermissionRevokedWarning(revokedPermissions: string[]): void + + // 权限检查 + checkPermissionChange(): Promise + validateCurrentPermissions(): boolean +} +``` + +## 🔐 安全性设计 + +### 1. 连接安全 +```java +// Token验证 +- WebSocket握手时验证JWT Token +- 定期验证Token有效性 +- Token过期时自动断开连接 + +// 权限验证 +- 连接建立时验证用户权限 +- 消息发送前验证操作权限 +- 防止权限越权操作 + +// 示例:WebSocket拦截器 +@Component +public class WebSocketAuthInterceptor implements HandshakeInterceptor { + + @Override + public boolean beforeHandshake(ServerHttpRequest request, + ServerHttpResponse response, + WebSocketHandler wsHandler, + Map attributes) { + // 1. 提取Token + String token = extractTokenFromRequest(request); + + // 2. 验证Token有效性 + if (!saTokenUtil.isValidToken(token)) { + return false; + } + + // 3. 获取用户信息 + Long userId = saTokenUtil.getUserIdFromToken(token); + attributes.put("userId", userId); + + return true; + } +} +``` + +### 2. 消息安全 +```java +// 消息加密 +- 敏感消息内容加密传输 +- 消息完整性校验 +- 防止消息重放攻击 + +// 频率限制 +- 连接频率限制 +- 消息发送频率限制 +- 异常连接自动断开 + +// 示例:消息安全处理 +@Component +public class MessageSecurityHandler { + + public WebSocketMessage encryptMessage(WebSocketMessage message) { + // 对敏感数据进行加密 + if (message.getType().equals("PERMISSION_UPDATE")) { + String encryptedData = aesUtil.encrypt(message.getData().toString()); + message.setData(encryptedData); + } + return message; + } + + public boolean validateMessageIntegrity(WebSocketMessage message) { + // 验证消息完整性 + String expectedHash = calculateMessageHash(message); + return expectedHash.equals(message.getHash()); + } +} +``` + +### 3. 访问控制 +```java +// 用户隔离 +- 确保用户只能接收自己的权限变更消息 +- 防止跨用户信息泄露 +- 管理员权限特殊处理 + +// 示例:消息权限验证 +@Component +public class MessagePermissionValidator { + + public boolean canReceiveMessage(Long userId, WebSocketMessage message) { + // 1. 检查消息是否发给该用户 + if (!message.getUserId().equals(userId)) { + return false; + } + + // 2. 检查用户是否有权限接收该类型消息 + return hasPermissionToReceiveMessageType(userId, message.getType()); + } +} +``` + +## 🚀 性能优化方案 + +### 1. 连接优化 +```java +// 连接池管理 +- 合理设置连接数上限 +- 空闲连接自动清理 +- 连接状态监控 + +// 内存优化 +- 及时清理断开的连接 +- 消息队列大小限制 +- 定期清理过期数据 + +// 示例:连接池配置 +@Configuration +public class WebSocketPoolConfig { + + @Bean + public WebSocketConnectionPool connectionPool() { + return WebSocketConnectionPool.builder() + .maxConnections(10000) // 最大连接数 + .maxConnectionsPerUser(5) // 每用户最大连接数 + .idleTimeout(Duration.ofMinutes(30)) // 空闲超时 + .cleanupInterval(Duration.ofMinutes(5)) // 清理间隔 + .build(); + } +} +``` + +### 2. 推送优化 +```java +// 批量推送 +- 相同类型消息合并推送 +- 延迟推送策略 +- 推送优先级管理 + +// 缓存优化 +- Redis缓存权限数据 +- 权限变更增量推送 +- 本地权限缓存 + +// 示例:批量推送实现 +@Component +public class BatchMessagePusher { + + private final Map> messageBatches = new ConcurrentHashMap<>(); + + @Scheduled(fixedDelay = 1000) // 每秒批量推送一次 + public void flushMessageBatches() { + messageBatches.forEach((batchKey, messages) -> { + WebSocketMessage batchMessage = mergeMess + ages(messages); + webSocketHandler.broadcast(batchMessage); + }); + messageBatches.clear(); + } +} +``` + +### 3. 数据库优化 +```sql +-- 权限查询优化 +CREATE INDEX idx_user_permission_version ON sys_login_user(user_id, permission_version); +CREATE INDEX idx_role_permission_update ON sys_role_menu(role_id, update_time); + +-- 会话查询优化 +CREATE INDEX idx_websocket_user_status ON sys_websocket_session(user_id, status, connect_time); + +-- 变更日志查询优化 +CREATE INDEX idx_permission_log_target ON sys_permission_change_log(target_user_id, target_role_id, create_time); +``` + +## 📊 监控和日志 + +### 1. 连接监控 +```java +// 监控指标 +- 当前连接数 +- 连接成功率 +- 连接断开原因统计 +- 消息推送成功率 + +// 示例:监控服务 +@Component +public class WebSocketMonitorService { + + private final MeterRegistry meterRegistry; + + public void recordConnection(String result) { + Counter.builder("websocket.connections") + .tag("result", result) + .register(meterRegistry) + .increment(); + } + + public void recordMessagePush(String type, String result) { + Counter.builder("websocket.messages") + .tag("type", type) + .tag("result", result) + .register(meterRegistry) + .increment(); + } +} +``` + +### 2. 错误处理和日志 +```java +// 日志记录 +- 连接建立/断开日志 +- 消息推送日志 +- 错误异常日志 +- 性能统计日志 + +// 示例:日志配置 +@Slf4j +@Component +public class WebSocketLogger { + + public void logConnection(Long userId, String action, String result) { + log.info("WebSocket连接 - 用户:{}, 操作:{}, 结果:{}", userId, action, result); + } + + public void logMessagePush(Long userId, String messageType, String result) { + log.info("消息推送 - 用户:{}, 类型:{}, 结果:{}", userId, messageType, result); + } + + public void logError(String operation, Exception e) { + log.error("WebSocket错误 - 操作:{}, 异常:", operation, e); + } +} +``` + +## 📋 实施步骤 + +### 第一阶段:基础WebSocket服务(1-2周) +1. **后端WebSocket服务搭建** + - 创建WebSocket配置类 + - 实现WebSocket处理器 + - 添加权限验证拦截器 + - 基础连接管理功能 + +2. **前端WebSocket客户端** + - 创建WebSocket服务类 + - 实现连接管理逻辑 + - 添加重连机制 + - 基础消息收发功能 + +3. **基础测试** + - 连接建立测试 + - 消息收发测试 + - 断线重连测试 + +### 第二阶段:权限推送核心功能(2-3周) +1. **权限变更监听** + - 实现用户角色变更监听 + - 实现角色权限变更监听 + - 实现菜单权限变更监听 + - 创建权限变更事件 + +2. **消息推送逻辑** + - 实现权限更新消息推送 + - 实现角色变更消息推送 + - 实现批量推送逻辑 + - 添加消息去重机制 + +3. **前端权限同步** + - 实现权限数据更新 + - 实现UI实时刷新 + - 添加权限变更通知 + - 处理权限冲突场景 + +### 第三阶段:高级功能和优化(2-3周) +1. **安全性增强** + - 添加消息加密 + - 实现访问控制 + - 添加频率限制 + - 防止攻击机制 + +2. **性能优化** + - 实现连接池管理 + - 添加消息批量处理 + - 优化数据库查询 + - 添加缓存机制 + +3. **用户体验优化** + - 完善重连策略 + - 优化通知交互 + - 添加调试面板 + - 处理边界情况 + +### 第四阶段:生产环境适配(1-2周) +1. **集群部署支持** + - Redis消息队列 + - 负载均衡配置 + - 会话共享机制 + +2. **监控和运维** + - 添加监控指标 + - 完善日志记录 + - 配置告警机制 + - 制定运维手册 + +3. **测试和部署** + - 压力测试 + - 兼容性测试 + - 生产环境部署 + - 回滚方案准备 + +## 🔍 风险评估和应对方案 + +### 1. 技术风险 +| 风险项 | 影响度 | 概率 | 应对方案 | +|--------|--------|------|----------| +| WebSocket连接不稳定 | 高 | 中 | 完善重连机制,降级到轮询 | +| 消息推送延迟 | 中 | 低 | 优化推送逻辑,添加超时机制 | +| 内存泄漏 | 高 | 低 | 定期清理,添加监控 | +| 安全漏洞 | 高 | 低 | 安全审计,权限校验 | + +### 2. 业务风险 +| 风险项 | 影响度 | 概率 | 应对方案 | +|--------|--------|------|----------| +| 权限同步失败 | 高 | 中 | 手动刷新机制,错误提示 | +| 用户体验下降 | 中 | 低 | 渐进式升级,用户反馈 | +| 系统复杂度增加 | 中 | 高 | 完善文档,团队培训 | + +### 3. 运维风险 +| 风险项 | 影响度 | 概率 | 应对方案 | +|--------|--------|------|----------| +| 服务器压力增加 | 中 | 中 | 性能监控,扩容预案 | +| 故障排查困难 | 中 | 中 | 详细日志,监控告警 | +| 部署复杂度增加 | 低 | 高 | 自动化部署,回滚机制 | + +## 📈 预期效果 + +### 1. 用户体验提升 +- ✅ 权限变更即时生效,无需重新登录 +- ✅ 多标签页权限状态同步 +- ✅ 清晰的权限变更通知 + +### 2. 系统性能 +- ✅ 减少不必要的接口调用 +- ✅ 提高权限检查效率 +- ✅ 降低服务器负载 + +### 3. 管理效率 +- ✅ 权限管理操作即时生效 +- ✅ 减少用户投诉和支持工作 +- ✅ 提高系统管理效率 + +## 📚 相关技术文档 + +1. [Spring WebSocket官方文档](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#websocket) +2. [Vue3 WebSocket最佳实践](https://vuejs.org/guide/extras/web-components.html) +3. [SaToken权限认证文档](https://sa-token.dev33.cn/) +4. [Redis消息队列使用指南](https://redis.io/docs/manual/pubsub/) + +## 👥 团队分工建议 + +| 角色 | 职责 | 时间投入 | +|------|------|----------| +| 后端开发 | WebSocket服务、权限监听、消息推送 | 60% | +| 前端开发 | WebSocket客户端、权限同步、UI更新 | 40% | +| 测试工程师 | 功能测试、性能测试、安全测试 | 全程参与 | +| 运维工程师 | 部署配置、监控告警、性能调优 | 后期参与 | + +--- + +**文档版本**: v1.0 +**创建时间**: 2025-01-07 +**更新时间**: 2025-01-07 +**负责人**: 系统架构团队 +**审核人**: 技术负责人 \ No newline at end of file diff --git a/fix_end_of_line_comments.py b/fix_end_of_line_comments.py new file mode 100644 index 0000000..62b1e58 --- /dev/null +++ b/fix_end_of_line_comments.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +批量修改Java文件中的行尾注释脚本 +将行尾注释改为单独占行的注释 +""" + +import os +import re +import sys +from pathlib import Path + +def find_java_files(root_path): + """查找所有Java文件""" + java_files = [] + for root, dirs, files in os.walk(root_path): + for file in files: + if file.endswith('.java'): + java_files.append(os.path.join(root, file)) + return java_files + +def process_file(file_path): + """处理单个Java文件""" + try: + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + original_content = content + changes = [] + + # 分行处理 + lines = content.split('\n') + new_lines = [] + + for i, line in enumerate(lines): + # 检查是否包含行尾注释 + # 模式1: 代码行后跟 // 注释 + match1 = re.match(r'^(\s*)(.*?)(;)\s*(//\s*(.*))\s*$', line) + if match1: + indent = match1.group(1) + code_part = match1.group(2) + semicolon = match1.group(3) + comment_part = match1.group(4) + comment_text = match1.group(5) + + # 添加单独的注释行 + new_lines.append(f'{indent}{comment_part}') + # 添加代码行 + new_lines.append(f'{indent}{code_part}{semicolon}') + changes.append(f'第{i+1}行: {line.strip()} -> 拆分为注释行和代码行') + continue + + # 模式2: 代码行后跟 /* 注释 */ + match2 = re.match(r'^(\s*)(.*?)(;)\s*(/\*\s*(.*?)\s*\*/)\s*$', line) + if match2: + indent = match2.group(1) + code_part = match2.group(2) + semicolon = match2.group(3) + comment_text = match2.group(5) + + # 添加单独的注释行(转换为//格式) + new_lines.append(f'{indent}// {comment_text}') + # 添加代码行 + new_lines.append(f'{indent}{code_part}{semicolon}') + changes.append(f'第{i+1}行: {line.strip()} -> 拆分为注释行和代码行') + continue + + # 模式3: 其他行尾注释情况(不以分号结尾) + match3 = re.match(r'^(\s*)(.*?)\s*(//\s*(.*))\s*$', line) + if match3 and not line.strip().startswith('//'): + indent = match3.group(1) + code_part = match3.group(2).strip() + comment_part = match3.group(3) + comment_text = match3.group(4) + + # 确保不是整行注释 + if code_part and not code_part.startswith('//'): + # 添加单独的注释行 + new_lines.append(f'{indent}{comment_part}') + # 添加代码行 + new_lines.append(f'{indent}{code_part}') + changes.append(f'第{i+1}行: {line.strip()} -> 拆分为注释行和代码行') + continue + + # 模式4: 其他行尾注释情况(/* */格式,不以分号结尾) + match4 = re.match(r'^(\s*)(.*?)\s*(/\*\s*(.*?)\s*\*/)\s*$', line) + if match4 and not line.strip().startswith('/*'): + indent = match4.group(1) + code_part = match4.group(2).strip() + comment_text = match4.group(4) + + # 确保不是整行注释 + if code_part and not code_part.startswith('/*'): + # 添加单独的注释行(转换为//格式) + new_lines.append(f'{indent}// {comment_text}') + # 添加代码行 + new_lines.append(f'{indent}{code_part}') + changes.append(f'第{i+1}行: {line.strip()} -> 拆分为注释行和代码行') + continue + + # 没有匹配的模式,保持原样 + new_lines.append(line) + + # 如果有变化,写入文件 + if changes: + new_content = '\n'.join(new_lines) + with open(file_path, 'w', encoding='utf-8') as f: + f.write(new_content) + return len(changes), changes + else: + return 0, [] + + except Exception as e: + print(f"处理文件 {file_path} 时出错: {e}") + return 0, [] + +def main(): + """主函数""" + # 项目根目录 + root_path = '/Users/leocoder/leocoder/develop/templates/coder-common-thin/coder-common-thin-backend' + + # 查找所有Java文件 + java_files = find_java_files(root_path) + + print(f"找到 {len(java_files)} 个Java文件") + print("开始处理...") + + total_changes = 0 + modified_files = [] + + for file_path in java_files: + change_count, changes = process_file(file_path) + if change_count > 0: + total_changes += change_count + modified_files.append({ + 'file': file_path, + 'changes': change_count, + 'details': changes + }) + print(f"✓ 修改了 {file_path} - {change_count} 处更改") + + print("\n" + "="*80) + print("修改报告") + print("="*80) + print(f"总共修改了 {len(modified_files)} 个文件") + print(f"总共修改了 {total_changes} 处行尾注释") + + if modified_files: + print("\n详细修改列表:") + for file_info in modified_files: + print(f"\n文件: {file_info['file']}") + print(f"修改数量: {file_info['changes']}") + for detail in file_info['details'][:5]: # 只显示前5个变化 + print(f" - {detail}") + if len(file_info['details']) > 5: + print(f" ... 还有 {len(file_info['details']) - 5} 个变化") + + print("\n处理完成!") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/picture/pictures/bugs/2025/07/06/20250706224303-6c9668.jpg b/picture/pictures/bugs/2025/07/06/20250706224303-6c9668.jpg new file mode 100644 index 0000000..960914e Binary files /dev/null and b/picture/pictures/bugs/2025/07/06/20250706224303-6c9668.jpg differ diff --git a/picture/pictures/yuadmin/2025/07/06/20250706211833-cd4530.jpg b/picture/pictures/yuadmin/2025/07/06/20250706211833-cd4530.jpg new file mode 100644 index 0000000..035e677 Binary files /dev/null and b/picture/pictures/yuadmin/2025/07/06/20250706211833-cd4530.jpg differ diff --git a/picture/pictures/yuadmin/2025/07/06/20250706211840-3766ed.jpg b/picture/pictures/yuadmin/2025/07/06/20250706211840-3766ed.jpg new file mode 100644 index 0000000..035e677 Binary files /dev/null and b/picture/pictures/yuadmin/2025/07/06/20250706211840-3766ed.jpg differ diff --git a/picture/pictures/yuadmin/2025/07/06/20250706212030-40ac11.jpg b/picture/pictures/yuadmin/2025/07/06/20250706212030-40ac11.jpg new file mode 100644 index 0000000..035e677 Binary files /dev/null and b/picture/pictures/yuadmin/2025/07/06/20250706212030-40ac11.jpg differ diff --git a/picture/pictures/yuadmin/2025/07/06/20250706212100-1a6776.jpg b/picture/pictures/yuadmin/2025/07/06/20250706212100-1a6776.jpg new file mode 100644 index 0000000..035e677 Binary files /dev/null and b/picture/pictures/yuadmin/2025/07/06/20250706212100-1a6776.jpg differ diff --git a/picture/pictures/yuadmin/2025/07/06/20250706213204-420924.png b/picture/pictures/yuadmin/2025/07/06/20250706213204-420924.png new file mode 100644 index 0000000..6b210bc Binary files /dev/null and b/picture/pictures/yuadmin/2025/07/06/20250706213204-420924.png differ diff --git a/picture/pictures/yuadmin/2025/07/06/20250706213936-2ea1ff.jpg b/picture/pictures/yuadmin/2025/07/06/20250706213936-2ea1ff.jpg new file mode 100644 index 0000000..960914e Binary files /dev/null and b/picture/pictures/yuadmin/2025/07/06/20250706213936-2ea1ff.jpg differ diff --git a/picture/pictures/yuadmin/2025/07/06/20250706214126-c32667.jpg b/picture/pictures/yuadmin/2025/07/06/20250706214126-c32667.jpg new file mode 100644 index 0000000..035e677 Binary files /dev/null and b/picture/pictures/yuadmin/2025/07/06/20250706214126-c32667.jpg differ diff --git a/picture/pictures/yuadmin/2025/07/06/20250706214853-29a2e0.jpg b/picture/pictures/yuadmin/2025/07/06/20250706214853-29a2e0.jpg new file mode 100644 index 0000000..227d1c5 Binary files /dev/null and b/picture/pictures/yuadmin/2025/07/06/20250706214853-29a2e0.jpg differ diff --git a/picture/pictures/yuadmin/2025/07/06/20250706215438-91fde9.jpg b/picture/pictures/yuadmin/2025/07/06/20250706215438-91fde9.jpg new file mode 100644 index 0000000..035e677 Binary files /dev/null and b/picture/pictures/yuadmin/2025/07/06/20250706215438-91fde9.jpg differ